Software / code / prosody
Annotate
util/prosodyctl/shell.lua @ 13652:a08065207ef0
net.server_epoll: Call :shutdown() on TLS sockets when supported
Comment from Matthew:
This fixes a potential issue where the Prosody process gets blocked on sockets
waiting for them to close. Unlike non-TLS sockets, closing a TLS socket sends
layer 7 data, and this can cause problems for sockets which are in the process
of being cleaned up.
This depends on LuaSec changes which are not yet upstream.
From Martijn's original email:
So first my analysis of luasec. in ssl.c the socket is put into blocking
mode right before calling SSL_shutdown() inside meth_destroy(). My best
guess to why this is is because meth_destroy is linked to the __close
and __gc methods, which can't exactly be called multiple times and
luasec does want to make sure that a tls session is shutdown as clean
as possible.
I can't say I disagree with this reasoning and don't want to change this
behaviour. My solution to this without changing the current behaviour is
to introduce a shutdown() method. I am aware that this overlaps in a
conflicting way with tcp's shutdown method, but it stays close to the
OpenSSL name. This method calls SSL_shutdown() in the current
(non)blocking mode of the underlying socket and returns a boolean
whether or not the shutdown is completed (matching SSL_shutdown()'s 0
or 1 return values), and returns the familiar ssl_ioerror() strings on
error with a false for completion. This error can then be used to
determine if we have wantread/wantwrite to finalize things. Once
meth_shutdown() has been called once a shutdown flag will be set, which
indicates to meth_destroy() that the SSL_shutdown() has been handled
by the application and it shouldn't be needed to set the socket to
blocking mode. I've left the SSL_shutdown() call in the
LSEC_STATE_CONNECTED to prevent TOCTOU if the application reaches a
timeout for the shutdown code, which might allow SSL_shutdown() to
clean up anyway at the last possible moment.
Another thing I've changed to luasec is the call to socket_setblocking()
right before calling close(2) in socket_destroy() in usocket.c.
According to the latest POSIX[0]:
Note that the requirement for close() on a socket to block for up to
the current linger interval is not conditional on the O_NONBLOCK
setting.
Which I read to mean that removing O_NONBLOCK on the socket before close
doesn't impact the behaviour and only causes noise in system call
tracers. I didn't touch the windows bits of this, since I don't do
windows.
For the prosody side of things I've made the TLS shutdown bits resemble
interface:onwritable(), and put it under a combined guard of self._tls
and self.conn.shutdown. The self._tls bit is there to prevent getting
stuck on this condition, and self.conn.shutdown is there to prevent the
code being called by instances where the patched luasec isn't deployed.
The destroy() method can be called from various places and is read by
me as the "we give up" error path. To accommodate for these unexpected
entrypoints I've added a single call to self.conn:shutdown() to prevent
the socket being put into blocking mode. I have no expectations that
there is any other use here. Same as previous, the self.conn.shutdown
check is there to make sure it's not called on unpatched luasec
deployments and self._tls is there to make sure we don't call shutdown()
on tcp sockets.
I wouldn't recommend logging of the conn:shutdown() error inside
close(), since a lot of clients simply close the connection before
SSL_shutdown() is done.
| author | Martijn van Duren <martijn@openbsd.org> |
|---|---|
| date | Thu, 06 Feb 2025 15:04:38 +0000 |
| parent | 13643:e5f62871e6a5 |
| child | 13732:1465b1e305df |
| rev | line source |
|---|---|
|
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
1 local config = require "prosody.core.configmanager"; |
|
13590
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
2 local human_io = require "prosody.util.human.io"; |
|
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
3 local server = require "prosody.net.server"; |
|
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
4 local st = require "prosody.util.stanza"; |
|
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
5 local path = require "prosody.util.paths"; |
|
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
6 local parse_args = require "prosody.util.argparse".parse; |
|
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
7 local tc = require "prosody.util.termcolours"; |
|
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
8 local isatty = require "prosody.util.pposix".isatty; |
|
13046
4c3dc767fb11
util.prosodyctl.shell: Use new term_width() for width
Kim Alvefur <zash@zash.se>
parents:
12975
diff
changeset
|
9 local term_width = require"prosody.util.human.io".term_width; |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 local have_readline, readline = pcall(require, "readline"); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 |
|
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12864
diff
changeset
|
13 local adminstream = require "prosody.util.adminstream"; |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 if have_readline then |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 readline.set_readline_name("prosody"); |
|
10877
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
17 readline.set_options({ |
|
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
18 histfile = path.join(prosody.paths.data, ".shell_history"); |
|
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
19 ignoredups = true; |
|
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
20 }); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
21 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
22 |
|
11890
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
23 local function read_line(prompt_string) |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
24 if have_readline then |
|
11890
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
25 return readline.readline(prompt_string); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 else |
|
11890
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
27 io.write(prompt_string); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 return io.read("*line"); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
31 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
32 local function send_line(client, line) |
|
13050
4ae759490e31
util.prosodyctl.shell: Coerce terminal width to string (for util.stanza)
Kim Alvefur <zash@zash.se>
parents:
13047
diff
changeset
|
33 client.send(st.stanza("repl-input", { width = tostring(term_width()) }):text(line)); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
34 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
35 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 local function repl(client) |
|
11890
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
37 local line = read_line(client.prompt_string or "prosody> "); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
38 if not line or line == "quit" or line == "exit" or line == "bye" then |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
39 if not line then |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
40 print(""); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
41 end |
|
10877
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
42 if have_readline then |
|
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
43 readline.save_history(); |
|
2b015ef8cd06
util.prosodyctl.shell: Save readline history
Kim Alvefur <zash@zash.se>
parents:
10875
diff
changeset
|
44 end |
|
12862
3dfb87814d65
util.prosodyctl.shell: Close state on exit to fix saving shell history
Kim Alvefur <zash@zash.se>
parents:
11902
diff
changeset
|
45 os.exit(0, true); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 send_line(client, line); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 local function printbanner() |
|
11902
98fd531594bd
util.prosodyctl.shell: Bring back banner set from config!
Kim Alvefur <zash@zash.se>
parents:
11890
diff
changeset
|
51 local banner = config.get("*", "console_banner"); |
|
98fd531594bd
util.prosodyctl.shell: Bring back banner set from config!
Kim Alvefur <zash@zash.se>
parents:
11890
diff
changeset
|
52 if banner then return print(banner); end |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
53 print([[ |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
54 ____ \ / _ |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 | _ \ _ __ ___ ___ _-_ __| |_ _ |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 | |_) | '__/ _ \/ __|/ _ \ / _` | | | | |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
57 | __/| | | (_) \__ \ |_| | (_| | |_| | |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 |_| |_| \___/|___/\___/ \__,_|\__, | |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 A study in simplicity |___/ |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 ]]); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 print("Welcome to the Prosody administration console. For a list of commands, type: help"); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 print("You may find more help on using this console in our online documentation at "); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 print("https://prosody.im/doc/console\n"); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 |
|
13643
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
67 local function check() |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
68 local lfs = require "lfs"; |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
69 local socket_path = path.resolve_relative_path(prosody.paths.data, config.get("*", "admin_socket") or "prosody.sock"); |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
70 local state = lfs.attributes(socket_path, "mode"); |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
71 return state == "socket"; |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
72 end |
|
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
73 |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 local function start(arg) --luacheck: ignore 212/arg |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 local client = adminstream.client(); |
|
10938
a5b8ae066688
util.prosodyctl.shell: Collect extra return values
Kim Alvefur <zash@zash.se>
parents:
10937
diff
changeset
|
76 local opts, err, where = parse_args(arg); |
|
12539
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
77 local ttyout = isatty(io.stdout); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 |
|
10937
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
79 if not opts then |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
80 if err == "param-not-found" then |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
81 print("Unknown command-line option: "..tostring(where)); |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
82 elseif err == "missing-value" then |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
83 print("Expected a value to follow command-line option: "..where); |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
84 end |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
85 os.exit(1); |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
86 end |
|
d86f59c31458
util.prosodyctl.shell: Handle argument parsing errors
Kim Alvefur <zash@zash.se>
parents:
10877
diff
changeset
|
87 |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
88 if arg[1] then |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
89 if arg[2] then |
|
13396
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
90 local fmt = { "%s"; ":%s("; ")" }; |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
91 for i = 3, #arg do |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
92 if arg[i]:sub(1, 1) == ":" then |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
93 table.insert(fmt, i, ")%s("); |
|
13483
7b070909bd15
prosodyctl shell: Fix invocation with 3+ command arguments
Matthew Wild <mwild1@gmail.com>
parents:
13398
diff
changeset
|
94 elseif i > 3 and fmt[i - 1]:match("%%q$") then |
|
13396
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
95 table.insert(fmt, i, ", %q"); |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
96 else |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
97 table.insert(fmt, i, "%q"); |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
98 end |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
99 end |
|
16413bc29361
util.prosodyctl.shell: Add :method syntax to make e.g. MUC commands easier
Kim Alvefur <zash@zash.se>
parents:
13052
diff
changeset
|
100 arg[1] = string.format(table.concat(fmt), table.unpack(arg)); |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
101 end |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
102 |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
103 client.events.add_handler("connected", function() |
|
13052
585bd71a1a97
util.prosodyctl.shell: Fix sending terminal width with single argument
Kim Alvefur <zash@zash.se>
parents:
13050
diff
changeset
|
104 send_line(client, arg[1]); |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
105 return true; |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
106 end, 1); |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
107 |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
108 local errors = 0; -- TODO This is weird, but works for now. |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
109 client.events.add_handler("received", function(stanza) |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
110 if stanza.name == "repl-output" or stanza.name == "repl-result" then |
|
12396
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
111 local dest = io.stdout; |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
112 if stanza.attr.type == "error" then |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
113 errors = errors + 1; |
|
12396
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
114 dest = io.stderr; |
|
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
115 end |
|
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
116 if stanza.attr.eol == "0" then |
|
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
117 dest:write(stanza:get_text()); |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
118 else |
|
12396
bdb9577a4830
util.prosodyctl.shell: Support for receiving partial lines (no automatic \n)
Matthew Wild <mwild1@gmail.com>
parents:
11902
diff
changeset
|
119 dest:write(stanza:get_text(), "\n"); |
|
11423
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
120 end |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
121 end |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
122 if stanza.name == "repl-result" then |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
123 os.exit(errors); |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
124 end |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
125 return true; |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
126 end, 1); |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
127 end |
|
0a10bb3b129b
util.prosodyctl.shell: Allow passing a single command as argument
Kim Alvefur <zash@zash.se>
parents:
11422
diff
changeset
|
128 |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
129 client.events.add_handler("connected", function () |
|
11422
fa5a23d7aabc
util.prosodyctl.shell: Fix check for --quiet
Kim Alvefur <zash@zash.se>
parents:
10938
diff
changeset
|
130 if not opts.quiet then |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
131 printbanner(); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
132 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
133 repl(client); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
134 end); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
135 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
136 client.events.add_handler("disconnected", function () |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
137 print("--- session closed ---"); |
|
12862
3dfb87814d65
util.prosodyctl.shell: Close state on exit to fix saving shell history
Kim Alvefur <zash@zash.se>
parents:
11902
diff
changeset
|
138 os.exit(0, true); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
139 end); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
140 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
141 client.events.add_handler("received", function (stanza) |
|
13590
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
142 if stanza.name ~= "repl-request-input" then |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
143 return; |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
144 end |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
145 if stanza.attr.type == "password" then |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
146 local password = human_io.read_password(); |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
147 client.send(st.stanza("repl-requested-input", { type = stanza.attr.type, id = stanza.attr.id }):text(password)); |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
148 else |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
149 io.stderr:write("Internal error - unexpected input request type "..tostring(stanza.attr.type).."\n"); |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
150 os.exit(1); |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
151 end |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
152 return true; |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
153 end, 2); |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
154 |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
155 |
|
d66f30855822
util.prosodyctl.shell: Support for requesting special inputs, e.g. passwords
Matthew Wild <mwild1@gmail.com>
parents:
13483
diff
changeset
|
156 client.events.add_handler("received", function (stanza) |
|
10859
8de0057b4279
mod_admin_shell, mod_admin_telnet, util.prosodyctl.shell: Separate output from final result
Matthew Wild <mwild1@gmail.com>
parents:
10858
diff
changeset
|
157 if stanza.name == "repl-output" or stanza.name == "repl-result" then |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
158 local result_prefix = stanza.attr.type == "error" and "!" or "|"; |
|
12539
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
159 local out = result_prefix.." "..stanza:get_text(); |
|
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
160 if ttyout and stanza.attr.type == "error" then |
|
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
161 out = tc.getstring(tc.getstyle("red"), out); |
|
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
162 end |
|
cfdc8cca64d3
util.prosodyctl.shell: Print errors in red to highlight them
Kim Alvefur <zash@zash.se>
parents:
12529
diff
changeset
|
163 print(out); |
|
10859
8de0057b4279
mod_admin_shell, mod_admin_telnet, util.prosodyctl.shell: Separate output from final result
Matthew Wild <mwild1@gmail.com>
parents:
10858
diff
changeset
|
164 end |
|
8de0057b4279
mod_admin_shell, mod_admin_telnet, util.prosodyctl.shell: Separate output from final result
Matthew Wild <mwild1@gmail.com>
parents:
10858
diff
changeset
|
165 if stanza.name == "repl-result" then |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
166 repl(client); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
167 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
168 end); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
169 |
|
11890
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
170 client.prompt_string = config.get("*", "admin_shell_prompt"); |
|
b9aab1962a2b
util.prosodyctl.shell: Allow setting custom prompt (admin_shell_prompt)
Matthew Wild <mwild1@gmail.com>
parents:
11522
diff
changeset
|
171 |
|
10874
98c535531450
util.prosodyctl.shell: Really fix --socket option
Kim Alvefur <zash@zash.se>
parents:
10873
diff
changeset
|
172 local socket_path = path.resolve_relative_path(prosody.paths.data, opts.socket or config.get("*", "admin_socket") or "prosody.sock"); |
|
10875
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
173 local conn = adminstream.connection(socket_path, client.listeners); |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
174 local ok, err = conn:connect(); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
175 if not ok then |
|
10875
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
176 if err == "no unix socket support" then |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
177 print("** LuaSocket unix socket support not available or incompatible, ensure your"); |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
178 print("** version is up to date."); |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
179 else |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
180 print("** Unable to connect to server - is it running? Is mod_admin_shell enabled?"); |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
181 print("** Connection error: "..err); |
|
09674bbb833f
util.prosodyctl.shell, util.adminstream: Move connection logic into adminstream for easier reuse
Matthew Wild <mwild1@gmail.com>
parents:
10874
diff
changeset
|
182 end |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
183 os.exit(1); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
184 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
185 server.loop(); |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
186 end |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
187 |
|
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
188 return { |
|
10871
e5dee71d0ebb
prosodyctl+util.prosodyctl.*: Start breaking up the ever-growing prosodyctl
Matthew Wild <mwild1@gmail.com>
parents:
10869
diff
changeset
|
189 shell = start; |
|
13643
e5f62871e6a5
util.prosodyctl.shell: Export function to check for availability of admin socket
Matthew Wild <mwild1@gmail.com>
parents:
13607
diff
changeset
|
190 available = check; |
|
10858
efa49d484560
prosodyctl, util.prosodyctl.shell: `prosodyctl shell` - a client to access the prosodyctl admin shell
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
191 }; |