prosodyctl
changeset 8674 a4899174a894
parent 8671 31c5abd49dfe
child 8704 b7a22baaf55f
--- a/prosodyctl	Thu Mar 22 23:20:06 2018 +0100
+++ b/prosodyctl	Thu Mar 22 22:33:42 2018 +0000
@@ -45,7 +45,8 @@
 
 -----------
 
-require "util.startup".prosodyctl();
+local startup = require "util.startup";
+startup.prosodyctl();
 
 -----------
 
@@ -61,9 +62,9 @@
 		["no-posix"] = "The mod_posix module is not enabled in the Prosody config file, see https://prosody.im/doc/prosodyctl for more info";
 		["no-such-method"] = "This module has no commands";
 		["not-running"] = "Prosody is not running";
-		}, { __index = function (t,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end });
+		}, { __index = function (_,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end });
 
-local config = require "core.configmanager";
+local configmanager = require "core.configmanager";
 local modulemanager = require "core.modulemanager"
 local prosodyctl = require "util.prosodyctl"
 local socket = require "socket"
@@ -79,7 +80,7 @@
 
 local jid_split = require "util.jid".prepped_split;
 
-local prosodyctl_timeout = (config.get("*", "prosodyctl_timeout") or 5) * 2;
+local prosodyctl_timeout = (configmanager.get("*", "prosodyctl_timeout") or 5) * 2;
 -----------------------
 local commands = {};
 local command = arg[1];
@@ -104,7 +105,7 @@
 	if not hosts[host] then
 		show_warning("The host '%s' is not listed in the configuration file (or is not enabled).", host)
 		show_warning("The user will not be able to log in until this is changed.");
-		hosts[host] = make_host(host);
+		hosts[host] = startup.make_host(host); --luacheck: ignore 122/hosts
 	end
 
 	if prosodyctl.user_exists{ user = user, host = host } then
@@ -143,7 +144,7 @@
 	if not hosts[host] then
 		show_warning("The host '%s' is not listed in the configuration file (or is not enabled).", host)
 		show_warning("The user will not be able to log in until this is changed.");
-		hosts[host] = make_host(host);
+		hosts[host] = startup.make_host(host); --luacheck: ignore 122/hosts
 	end
 
 	if not prosodyctl.user_exists { user = user, host = host } then
@@ -181,7 +182,7 @@
 
 	if not hosts[host] then
 		show_warning("The host '%s' is not listed in the configuration file (or is not enabled).", host)
-		hosts[host] = make_host(host);
+		hosts[host] = startup.make_host(host); --luacheck: ignore 122/hosts
 	end
 
 	if not prosodyctl.user_exists { user = user, host = host } then
@@ -209,6 +210,7 @@
 	end
 
 	if ret then
+		--luacheck: ignore 421/ret
 		local ok, ret = prosodyctl.getpid();
 		if not ok then
 			show_message("Couldn't get running Prosody's PID");
@@ -219,9 +221,10 @@
 		return 1;
 	end
 
+	--luacheck: ignore 411/ret
 	local ok, ret = prosodyctl.start(prosody.paths.source);
 	if ok then
-		local daemonize = config.get("*", "daemonize");
+		local daemonize = configmanager.get("*", "daemonize");
 		if daemonize == nil then
 			daemonize = prosody.installed;
 		end
@@ -263,6 +266,7 @@
 	end
 
 	if ret then
+		--luacheck: ignore 421/ret
 		local ok, ret = prosodyctl.getpid();
 		if not ok then
 			show_message("Couldn't get running Prosody's PID");
@@ -273,7 +277,7 @@
 		return 0;
 	else
 		show_message("Prosody is not running");
-		if not switched_user and current_uid ~= 0 then
+		if not prosody.switched_user and prosody.current_uid ~= 0 then
 			print("\nNote:")
 			print(" You will also see this if prosodyctl is not running under");
 			print(" the same user account as Prosody. Try running as root (e.g. ");
@@ -281,7 +285,6 @@
 		end
 		return 2
 	end
-	return 1;
 end
 
 function commands.stop(arg)
@@ -336,11 +339,10 @@
 	end
 
 	local pwd = ".";
-	local lfs = require "lfs";
 	local array = require "util.array";
 	local keys = require "util.iterators".keys;
 	local hg = require"util.mercurial";
-	local relpath = config.resolve_relative_path;
+	local relpath = configmanager.resolve_relative_path;
 
 	print("Prosody "..(prosody.version or "(unknown version)"));
 	print("");
@@ -350,7 +352,7 @@
 	print("Source directory:   "..relpath(pwd, prosody.paths.source or "."));
 	print("Plugin directories:")
 	print("  "..(prosody.paths.plugins:gsub("([^;]+);?", function(path)
-			path = config.resolve_relative_path(pwd, path);
+			path = configmanager.resolve_relative_path(pwd, path);
 			local hgid, hgrepo = hg.check_id(path);
 			if not hgid and hgrepo then
 				return path.." - "..hgrepo .."!\n  ";
@@ -382,7 +384,7 @@
 	print("# Lua module versions");
 	local module_versions, longest_name = {}, 8;
 	local luaevent =dependencies.softreq"luaevent";
-	local ssl = dependencies.softreq"ssl";
+	dependencies.softreq"ssl";
 	for name, module in pairs(package.loaded) do
 		if type(module) == "table" and rawget(module, "_VERSION")
 		and name ~= "_G" and not name:match("%.") then
@@ -503,8 +505,8 @@
 local cert_basedir = prosody.paths.data == "." and "./certs" or prosody.paths.data;
 if have_pposix and pposix.getuid() == 0 then
 	-- FIXME should be enough to check if this directory is writable
-	local cert_dir = config.get("*", "certificates") or "certs";
-	cert_basedir = config.resolve_relative_path(prosody.paths.config, cert_dir);
+	local cert_dir = configmanager.get("*", "certificates") or "certs";
+	cert_basedir = configmanager.resolve_relative_path(prosody.paths.config, cert_dir);
 end
 
 function cert_commands.config(arg)
@@ -518,7 +520,7 @@
 			distinguished_name = table.remove(arg);
 		end
 		local conf = openssl.config.new();
-		conf:from_prosody(hosts, config, arg);
+		conf:from_prosody(hosts, configmanager, arg);
 		if distinguished_name then
 			local dn = {};
 			for k, v in distinguished_name:gmatch("/([^=/]+)=([^/]+)") do
@@ -532,7 +534,7 @@
 			for _, k in ipairs(openssl._DN_order) do
 				local v = conf.distinguished_name[k];
 				if v then
-					local nv;
+					local nv = nil;
 					if k == "commonName" then
 						v = arg[1]
 					elseif k == "emailAddress" then
@@ -671,7 +673,7 @@
 			end
 		else
 			for host in pairs(prosody.hosts) do
-				if host ~= "*" and config.get(host, "enabled") ~= false then
+				if host ~= "*" and configmanager.get(host, "enabled") ~= false then
 					table.insert(hostnames, host);
 				end
 			end
@@ -684,8 +686,8 @@
 	end
 	local owner, group;
 	if pposix.getuid() == 0 then -- We need root to change ownership
-		owner = config.get("*", "prosody_user") or "prosody";
-		group = config.get("*", "prosody_group") or owner;
+		owner = configmanager.get("*", "prosody_user") or "prosody";
+		group = configmanager.get("*", "prosody_group") or owner;
 	end
 	local cm = require "core.certmanager";
 	local imported = {};
@@ -766,22 +768,22 @@
 		return 1;
 	end
 	local what = table.remove(arg, 1);
-	local array, set = require "util.array", require "util.set";
+	local set = require "util.set";
 	local it = require "util.iterators";
 	local ok = true;
 	local function disabled_hosts(host, conf) return host ~= "*" and conf.enabled ~= false; end
-	local function enabled_hosts() return it.filter(disabled_hosts, pairs(config.getconfig())); end
+	local function enabled_hosts() return it.filter(disabled_hosts, pairs(configmanager.getconfig())); end
 	if not what or what == "disabled" then
-		local disabled_hosts = set.new();
-		for host, host_options in it.filter("*", pairs(config.getconfig())) do
+		local disabled_hosts_set = set.new();
+		for host, host_options in it.filter("*", pairs(configmanager.getconfig())) do
 			if host_options.enabled == false then
-				disabled_hosts:add(host);
+				disabled_hosts_set:add(host);
 			end
 		end
-		if not disabled_hosts:empty() then
+		if not disabled_hosts_set:empty() then
 			local msg = "Checks will be skipped for these disabled hosts: %s";
 			if what then msg = "These hosts are disabled: %s"; end
-			show_warning(msg, tostring(disabled_hosts));
+			show_warning(msg, tostring(disabled_hosts_set));
 			if what then return 0; end
 			print""
 		end
@@ -797,7 +799,7 @@
 			"umask", "prosodyctl_timeout", "use_ipv6", "use_libevent", "network_settings",
 			"network_backend", "http_default_host",
 		});
-		local config = config.getconfig();
+		local config = configmanager.getconfig();
 		-- Check that we have any global options (caused by putting a host at the top)
 		if it.count(it.filter("log", pairs(config["*"]))) == 0 then
 			ok = false;
@@ -819,7 +821,7 @@
 		if not config["*"].modules_enabled then
 			print("    No global modules_enabled is set?");
 			local suggested_global_modules;
-			for host, options in enabled_hosts() do
+			for host, options in enabled_hosts() do --luacheck: ignore 213/host
 				if not options.component_module and options.modules_enabled then
 					suggested_global_modules = set.intersection(suggested_global_modules or set.new(options.modules_enabled), set.new(options.modules_enabled));
 				end
@@ -862,10 +864,10 @@
 			local subdomain = host:match("^[^.]+");
 			if not(host_options:contains("component_module")) and (subdomain == "jabber" or subdomain == "xmpp"
 			   or subdomain == "chat" or subdomain == "im") then
-			   	print("");
-			   	print("    Suggestion: If "..host.. " is a new host with no real users yet, consider renaming it now to");
-			   	print("     "..host:gsub("^[^.]+%.", "")..". You can use SRV records to redirect XMPP clients and servers to "..host..".");
-			   	print("     For more information see: https://prosody.im/doc/dns");
+				print("");
+				print("    Suggestion: If "..host.. " is a new host with no real users yet, consider renaming it now to");
+				print("     "..host:gsub("^[^.]+%.", "")..". You can use SRV records to redirect XMPP clients and servers to "..host..".");
+				print("     For more information see: https://prosody.im/doc/dns");
 			end
 		end
 		local all_modules = set.new(config["*"].modules_enabled);
@@ -895,14 +897,16 @@
 				print("    For more information see https://prosody.im/doc/storage");
 			end
 		end
-		for host, config in pairs(config) do
-			if type(rawget(config, "storage")) == "string" and rawget(config, "default_storage") then
+		for host, host_config in pairs(config) do --luacheck: ignore 213/host
+			if type(rawget(host_config, "storage")) == "string" and rawget(host_config, "default_storage") then
 				print("");
 				print("    The 'default_storage' option is not needed if 'storage' is set to a string.");
 				break;
 			end
 		end
-		local require_encryption = set.intersection(all_options, set.new({"require_encryption", "c2s_require_encryption", "s2s_require_encryption"})):empty();
+		local require_encryption = set.intersection(all_options, set.new({
+			"require_encryption", "c2s_require_encryption", "s2s_require_encryption"
+		})):empty();
 		local ssl = dependencies.softreq"ssl";
 		if not ssl then
 			if not require_encryption then
@@ -948,8 +952,8 @@
 		local dns = require "net.dns";
 		local idna = require "util.encodings".idna;
 		local ip = require "util.ip";
-		local c2s_ports = set.new(config.get("*", "c2s_ports") or {5222});
-		local s2s_ports = set.new(config.get("*", "s2s_ports") or {5269});
+		local c2s_ports = set.new(configmanager.get("*", "c2s_ports") or {5222});
+		local s2s_ports = set.new(configmanager.get("*", "s2s_ports") or {5269});
 
 		local c2s_srv_required, s2s_srv_required;
 		if not c2s_ports:contains(5222) then
@@ -965,16 +969,20 @@
 
 		local fqdn = socket.dns.tohostname(socket.dns.gethostname());
 		if fqdn then
-			local res = dns.lookup(idna.to_ascii(fqdn), "A");
-			if res then
-				for _, record in ipairs(res) do
-					external_addresses:add(record.a);
+			do
+				local res = dns.lookup(idna.to_ascii(fqdn), "A");
+				if res then
+					for _, record in ipairs(res) do
+						external_addresses:add(record.a);
+					end
 				end
 			end
-			local res = dns.lookup(idna.to_ascii(fqdn), "AAAA");
-			if res then
-				for _, record in ipairs(res) do
-					external_addresses:add(record.aaaa);
+			do
+				local res = dns.lookup(idna.to_ascii(fqdn), "AAAA");
+				if res then
+					for _, record in ipairs(res) do
+						external_addresses:add(record.aaaa);
+					end
 				end
 			end
 		end
@@ -1025,20 +1033,22 @@
 					end
 				end
 			end
-			local res = dns.lookup("_xmpp-server._tcp."..idna.to_ascii(host)..".", "SRV");
-			if res then
-				for _, record in ipairs(res) do
-					target_hosts:add(record.srv.target);
-					if not s2s_ports:contains(record.srv.port) then
-						print("    SRV target "..record.srv.target.." contains unknown server port: "..record.srv.port);
+			do
+				local res = dns.lookup("_xmpp-server._tcp."..idna.to_ascii(host)..".", "SRV");
+				if res then
+					for _, record in ipairs(res) do
+						target_hosts:add(record.srv.target);
+						if not s2s_ports:contains(record.srv.port) then
+							print("    SRV target "..record.srv.target.." contains unknown server port: "..record.srv.port);
+						end
 					end
-				end
-			else
-				if s2s_srv_required then
-					print("    No _xmpp-server SRV record found for "..host..", but it looks like you need one.");
-					all_targets_ok = false;
 				else
-					target_hosts:add(host);
+					if s2s_srv_required then
+						print("    No _xmpp-server SRV record found for "..host..", but it looks like you need one.");
+						all_targets_ok = false;
+					else
+						target_hosts:add(host);
+					end
 				end
 			end
 			if target_hosts:empty() then
@@ -1051,11 +1061,11 @@
 			end
 
 			local modules = set.new(it.to_array(it.values(host_options.modules_enabled or {})))
-			                + set.new(it.to_array(it.values(config.get("*", "modules_enabled") or {})))
-			                + set.new({ config.get(host, "component_module") });
+			                + set.new(it.to_array(it.values(configmanager.get("*", "modules_enabled") or {})))
+			                + set.new({ configmanager.get(host, "component_module") });
 
 			if modules:contains("proxy65") then
-				local proxy65_target = config.get(host, "proxy65_address") or host;
+				local proxy65_target = configmanager.get(host, "proxy65_address") or host;
 				local A, AAAA = dns.lookup(idna.to_ascii(proxy65_target), "A"), dns.lookup(idna.to_ascii(proxy65_target), "AAAA");
 				local prob = {};
 				if not A then
@@ -1065,41 +1075,46 @@
 					table.insert(prob, "AAAA");
 				end
 				if #prob > 0 then
-					print("    File transfer proxy "..proxy65_target.." has no "..table.concat(prob, "/").." record. Create one or set 'proxy65_address' to the correct host/IP.");
+					print("    File transfer proxy "..proxy65_target.." has no "..table.concat(prob, "/")
+					.." record. Create one or set 'proxy65_address' to the correct host/IP.");
 				end
 			end
 
-			for host in target_hosts do
+			for target_host in target_hosts do
 				local host_ok_v4, host_ok_v6;
-				local res = dns.lookup(idna.to_ascii(host), "A");
-				if res then
-					for _, record in ipairs(res) do
-						if external_addresses:contains(record.a) then
-							some_targets_ok = true;
-							host_ok_v4 = true;
-						elseif internal_addresses:contains(record.a) then
-							host_ok_v4 = true;
-							some_targets_ok = true;
-							print("    "..host.." A record points to internal address, external connections might fail");
-						else
-							print("    "..host.." A record points to unknown address "..record.a);
-							all_targets_ok = false;
+				do
+					local res = dns.lookup(idna.to_ascii(target_host), "A");
+					if res then
+						for _, record in ipairs(res) do
+							if external_addresses:contains(record.a) then
+								some_targets_ok = true;
+								host_ok_v4 = true;
+							elseif internal_addresses:contains(record.a) then
+								host_ok_v4 = true;
+								some_targets_ok = true;
+								print("    "..target_host.." A record points to internal address, external connections might fail");
+							else
+								print("    "..target_host.." A record points to unknown address "..record.a);
+								all_targets_ok = false;
+							end
 						end
 					end
 				end
-				local res = dns.lookup(idna.to_ascii(host), "AAAA");
-				if res then
-					for _, record in ipairs(res) do
-						if external_addresses:contains(record.aaaa) then
-							some_targets_ok = true;
-							host_ok_v6 = true;
-						elseif internal_addresses:contains(record.aaaa) then
-							host_ok_v6 = true;
-							some_targets_ok = true;
-							print("    "..host.." AAAA record points to internal address, external connections might fail");
-						else
-							print("    "..host.." AAAA record points to unknown address "..record.aaaa);
-							all_targets_ok = false;
+				do
+					local res = dns.lookup(idna.to_ascii(target_host), "AAAA");
+					if res then
+						for _, record in ipairs(res) do
+							if external_addresses:contains(record.aaaa) then
+								some_targets_ok = true;
+								host_ok_v6 = true;
+							elseif internal_addresses:contains(record.aaaa) then
+								host_ok_v6 = true;
+								some_targets_ok = true;
+								print("    "..target_host.." AAAA record points to internal address, external connections might fail");
+							else
+								print("    "..target_host.." AAAA record points to unknown address "..record.aaaa);
+								all_targets_ok = false;
+							end
 						end
 					end
 				end
@@ -1112,10 +1127,10 @@
 					table.insert(bad_protos, "IPv6");
 				end
 				if #bad_protos > 0 then
-					print("    Host "..host.." does not seem to resolve to this server ("..table.concat(bad_protos, "/")..")");
+					print("    Host "..target_host.." does not seem to resolve to this server ("..table.concat(bad_protos, "/")..")");
 				end
 				if host_ok_v6 and not v6_supported then
-					print("    Host "..host.." has AAAA records, but your version of LuaSocket does not support IPv6.");
+					print("    Host "..target_host.." has AAAA records, but your version of LuaSocket does not support IPv6.");
 					print("      Please see https://prosody.im/doc/ipv6 for more information.");
 				end
 			end
@@ -1161,9 +1176,9 @@
 			for host in it.filter(skip_bare_jid_hosts, enabled_hosts()) do
 				print("Checking certificate for "..host);
 				-- First, let's find out what certificate this host uses.
-				local host_ssl_config = config.rawget(host, "ssl")
-					or config.rawget(host:match("%.(.*)"), "ssl");
-				local global_ssl_config = config.rawget("*", "ssl");
+				local host_ssl_config = configmanager.rawget(host, "ssl")
+					or configmanager.rawget(host:match("%.(.*)"), "ssl");
+				local global_ssl_config = configmanager.rawget("*", "ssl");
 				local ok, err, ssl_config = create_context(host, "server", host_ssl_config, global_ssl_config);
 				if not ok then
 					print("  Error: "..err);
@@ -1188,7 +1203,7 @@
 						cert_ok = false
 					else
 						print("  Certificate: "..ssl_config.certificate)
-						local cert = load_cert(cert_fh:read"*a"); cert_fh = cert_fh:close();
+						local cert = load_cert(cert_fh:read"*a"); cert_fh:close();
 						if not cert:validat(os.time()) then
 							print("    Certificate has expired.")
 							cert_ok = false
@@ -1200,13 +1215,13 @@
 						elseif not cert:validat(os.time() + 86400*31) then
 							print("    Certificate expires within one month.")
 						end
-						if config.get(host, "component_module") == nil
+						if configmanager.get(host, "component_module") == nil
 							and not x509_verify_identity(host, "_xmpp-client", cert) then
 							print("    Not valid for client connections to "..host..".")
 							cert_ok = false
 						end
-						if (not (config.get(host, "anonymous_login")
-							or config.get(host, "authentication") == "anonymous"))
+						if (not (configmanager.get(host, "anonymous_login")
+							or configmanager.get(host, "authentication") == "anonymous"))
 							and not x509_verify_identity(host, "_xmpp-server", cert) then
 							print("    Not valid for server-to-server connections to "..host..".")
 							cert_ok = false
@@ -1214,11 +1229,11 @@
 					end
 				end
 			end
-			if cert_ok == false then
-				print("")
-				print("For more information about certificates please see https://prosody.im/doc/certificates");
-				ok = false
-			end
+		end
+		if cert_ok == false then
+			print("")
+			print("For more information about certificates please see https://prosody.im/doc/certificates");
+			ok = false
 		end
 		print("")
 	end
@@ -1233,6 +1248,7 @@
 ---------------------
 
 local async = require "util.async";
+local server = require "net.server";
 local watchers = {
 	error = function (_, err)
 		error(err);
@@ -1244,10 +1260,12 @@
 local command_runner = async.runner(function ()
 	if command and command:match("^mod_") then -- Is a command in a module
 		local module_name = command:match("^mod_(.+)");
-		local ret, err = modulemanager.load("*", module_name);
-		if not ret then
-			show_message("Failed to load module '"..module_name.."': "..err);
-			os.exit(1);
+		do
+			local ret, err = modulemanager.load("*", module_name);
+			if not ret then
+				show_message("Failed to load module '"..module_name.."': "..err);
+				os.exit(1);
+			end
 		end
 
 		table.remove(arg, 1);
@@ -1295,17 +1313,17 @@
 		local done = {};
 
 		for _, command_name in ipairs(commands_order) do
-			local command = commands[command_name];
-			if command then
-				command{ "--help" };
+			local command_func = commands[command_name];
+			if command_func then
+				command_func{ "--help" };
 				print""
 				done[command_name] = true;
 			end
 		end
 
-		for command_name, command in pairs(commands) do
+		for command_name, command_func in pairs(commands) do
 			if not done[command_name] and not hidden_commands:contains(command_name) then
-				command{ "--help" };
+				command_func{ "--help" };
 				print""
 				done[command_name] = true;
 			end