4 -- |
4 -- |
5 -- This project is MIT/X11 licensed. Please see the |
5 -- This project is MIT/X11 licensed. Please see the |
6 -- COPYING file in the source package for more information. |
6 -- COPYING file in the source package for more information. |
7 -- |
7 -- |
8 |
8 |
9 module.host = "*"; |
9 module:set_global(); |
10 |
10 |
11 local _G = _G; |
11 local _G = _G; |
12 |
12 |
13 local prosody = _G.prosody; |
13 local prosody = _G.prosody; |
14 local hosts = prosody.hosts; |
14 local hosts = prosody.hosts; |
15 local connlisteners_register = require "net.connlisteners".register; |
15 |
16 |
16 local console_listener = { default_port = 5582; default_mode = "*l"; interface = "127.0.0.1" }; |
17 local console_listener = { default_port = 5582; default_mode = "*l"; default_interface = "127.0.0.1" }; |
17 |
18 |
18 local iterators = require "util.iterators"; |
19 require "util.iterators"; |
19 local keys, values = iterators.keys, iterators.values; |
20 local jid_bare = require "util.jid".bare; |
20 local jid_bare = require "util.jid".bare; |
21 local set, array = require "util.set", require "util.array"; |
21 local set, array = require "util.set", require "util.array"; |
22 local cert_verify_identity = require "util.x509".verify_identity; |
22 local cert_verify_identity = require "util.x509".verify_identity; |
23 |
23 |
24 local commands = {}; |
24 local commands = module:shared("commands") |
25 local def_env = {}; |
25 local def_env = module:shared("env"); |
26 local default_env_mt = { __index = def_env }; |
26 local default_env_mt = { __index = def_env }; |
27 |
|
28 prosody.console = { commands = commands, env = def_env }; |
|
29 |
27 |
30 local function redirect_output(_G, session) |
28 local function redirect_output(_G, session) |
31 local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end }); |
29 local env = setmetatable({ print = session.print }, { __index = function (t, k) return rawget(_G, k); end }); |
32 env.dofile = function(name) |
30 env.dofile = function(name) |
33 local f, err = loadfile(name); |
31 local f, err = loadfile(name); |
146 if session then |
144 if session then |
147 session.disconnect(); |
145 session.disconnect(); |
148 sessions[conn] = nil; |
146 sessions[conn] = nil; |
149 end |
147 end |
150 end |
148 end |
151 |
|
152 connlisteners_register('console', console_listener); |
|
153 |
149 |
154 -- Console commands -- |
150 -- Console commands -- |
155 -- These are simple commands, not valid standalone in Lua |
151 -- These are simple commands, not valid standalone in Lua |
156 |
152 |
157 function commands.bye(session) |
153 function commands.bye(session) |
279 end |
275 end |
280 elseif type(hosts) == "string" then |
276 elseif type(hosts) == "string" then |
281 return set.new { hosts }; |
277 return set.new { hosts }; |
282 elseif hosts == nil then |
278 elseif hosts == nil then |
283 local mm = require "modulemanager"; |
279 local mm = require "modulemanager"; |
284 return set.new(array.collect(keys(prosody.hosts))) |
280 local hosts_set = set.new(array.collect(keys(prosody.hosts))) |
285 / function (host) return prosody.hosts[host].type == "local" or module and mm.is_loaded(host, module); end; |
281 / function (host) return prosody.hosts[host].type == "local" or module and mm.is_loaded(host, module); end; |
|
282 if module and mm.get_module("*", module) then |
|
283 hosts_set:add("*"); |
|
284 end |
|
285 return hosts_set; |
286 end |
286 end |
287 end |
287 end |
288 |
288 |
289 function def_env.module:load(name, hosts, config) |
289 function def_env.module:load(name, hosts, config) |
290 local mm = require "modulemanager"; |
290 local mm = require "modulemanager"; |
291 |
291 |
292 hosts = get_hosts_set(hosts); |
292 hosts = get_hosts_set(hosts); |
293 |
293 |
294 -- Load the module for each host |
294 -- Load the module for each host |
295 local ok, err, count = true, nil, 0; |
295 local ok, err, count, mod = true, nil, 0, nil; |
296 for host in hosts do |
296 for host in hosts do |
297 if (not mm.is_loaded(host, name)) then |
297 if (not mm.is_loaded(host, name)) then |
298 ok, err = mm.load(host, name, config); |
298 mod, err = mm.load(host, name, config); |
299 if not ok then |
299 if not mod then |
300 ok = false; |
300 ok = false; |
|
301 if err == "global-module-already-loaded" then |
|
302 if count > 0 then |
|
303 ok, err, count = true, nil, 1; |
|
304 end |
|
305 break; |
|
306 end |
301 self.session.print(err or "Unknown error loading module"); |
307 self.session.print(err or "Unknown error loading module"); |
302 else |
308 else |
303 count = count + 1; |
309 count = count + 1; |
304 self.session.print("Loaded for "..host); |
310 self.session.print("Loaded for "..mod.module.host); |
305 end |
311 end |
306 end |
312 end |
307 end |
313 end |
308 |
314 |
309 return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err)); |
315 return ok, (ok and "Module loaded onto "..count.." host"..(count ~= 1 and "s" or "")) or ("Last error: "..tostring(err)); |
332 end |
338 end |
333 |
339 |
334 function def_env.module:reload(name, hosts) |
340 function def_env.module:reload(name, hosts) |
335 local mm = require "modulemanager"; |
341 local mm = require "modulemanager"; |
336 |
342 |
337 hosts = get_hosts_set(hosts, name); |
343 hosts = array.collect(get_hosts_set(hosts, name)):sort(function (a, b) |
338 |
344 if a == "*" then return true |
|
345 elseif b == "*" then return false |
|
346 else return a < b; end |
|
347 end); |
|
348 |
339 -- Reload the module for each host |
349 -- Reload the module for each host |
340 local ok, err, count = true, nil, 0; |
350 local ok, err, count = true, nil, 0; |
341 for host in hosts do |
351 for _, host in ipairs(hosts) do |
342 if mm.is_loaded(host, name) then |
352 if mm.is_loaded(host, name) then |
343 ok, err = mm.reload(host, name); |
353 ok, err = mm.reload(host, name); |
344 if not ok then |
354 if not ok then |
345 ok = false; |
355 ok = false; |
346 self.session.print(err or "Unknown error reloading module"); |
356 self.session.print(err or "Unknown error reloading module"); |
357 end |
367 end |
358 |
368 |
359 function def_env.module:list(hosts) |
369 function def_env.module:list(hosts) |
360 if hosts == nil then |
370 if hosts == nil then |
361 hosts = array.collect(keys(prosody.hosts)); |
371 hosts = array.collect(keys(prosody.hosts)); |
|
372 table.insert(hosts, 1, "*"); |
362 end |
373 end |
363 if type(hosts) == "string" then |
374 if type(hosts) == "string" then |
364 hosts = { hosts }; |
375 hosts = { hosts }; |
365 end |
376 end |
366 if type(hosts) ~= "table" then |
377 if type(hosts) ~= "table" then |
367 return false, "Please supply a host or a list of hosts you would like to see"; |
378 return false, "Please supply a host or a list of hosts you would like to see"; |
368 end |
379 end |
369 |
380 |
370 local print = self.session.print; |
381 local print = self.session.print; |
371 for _, host in ipairs(hosts) do |
382 for _, host in ipairs(hosts) do |
372 print(host..":"); |
383 print((host == "*" and "Global" or host)..":"); |
373 local modules = array.collect(keys(prosody.hosts[host] and prosody.hosts[host].modules or {})):sort(); |
384 local modules = array.collect(keys(modulemanager.get_modules(host) or {})):sort(); |
374 if #modules == 0 then |
385 if #modules == 0 then |
375 if prosody.hosts[host] then |
386 if prosody.hosts[host] then |
376 print(" No modules loaded"); |
387 print(" No modules loaded"); |
377 else |
388 else |
378 print(" Host not found"); |
389 print(" Host not found"); |
764 print(host); |
775 print(host); |
765 end |
776 end |
766 return true, i.." hosts"; |
777 return true, i.." hosts"; |
767 end |
778 end |
768 |
779 |
|
780 def_env.port = {}; |
|
781 |
|
782 function def_env.port:list() |
|
783 local print = self.session.print; |
|
784 local services = portmanager.get_active_services().data; |
|
785 local ordered_services, n_ports = {}, 0; |
|
786 for service, interfaces in pairs(services) do |
|
787 table.insert(ordered_services, service); |
|
788 end |
|
789 table.sort(ordered_services); |
|
790 for _, service in ipairs(ordered_services) do |
|
791 local ports_list = {}; |
|
792 for interface, ports in pairs(services[service]) do |
|
793 for port in pairs(ports) do |
|
794 table.insert(ports_list, "["..interface.."]:"..port); |
|
795 end |
|
796 end |
|
797 n_ports = n_ports + #ports_list; |
|
798 print(service..": "..table.concat(ports_list, ", ")); |
|
799 end |
|
800 return true, #ordered_services.." services listening on "..n_ports.." ports"; |
|
801 end |
|
802 |
|
803 function def_env.port:close(close_port, close_interface) |
|
804 close_port = assert(tonumber(close_port), "Invalid port number"); |
|
805 local n_closed = 0; |
|
806 local services = portmanager.get_active_services().data; |
|
807 for service, interfaces in pairs(services) do |
|
808 for interface, ports in pairs(interfaces) do |
|
809 if not close_interface or close_interface == interface then |
|
810 if ports[close_port] then |
|
811 self.session.print("Closing ["..interface.."]:"..close_port.."..."); |
|
812 local ok, err = portmanager.close(interface, close_port) |
|
813 if not ok then |
|
814 self.session.print("Failed to close "..interface.." "..port..": "..err); |
|
815 else |
|
816 n_closed = n_closed + 1; |
|
817 end |
|
818 end |
|
819 end |
|
820 end |
|
821 end |
|
822 return true, "Closed "..n_closed.." ports"; |
|
823 end |
|
824 |
769 ------------- |
825 ------------- |
770 |
826 |
771 function printbanner(session) |
827 function printbanner(session) |
772 local option = config.get("*", "core", "console_banner"); |
828 local option = config.get("*", "core", "console_banner"); |
773 if option == nil or option == "full" or option == "graphic" then |
829 if option == nil or option == "full" or option == "graphic" then |