Comparison

util/startup.lua @ 11200:bf8f2da84007

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Thu, 05 Nov 2020 22:31:25 +0100
parent 11152:89162d27e1b1
child 11304:c022b582d312
comparison
equal deleted inserted replaced
11199:6c7c50a4de32 11200:bf8f2da84007
3 local startup = {}; 3 local startup = {};
4 4
5 local prosody = { events = require "util.events".new() }; 5 local prosody = { events = require "util.events".new() };
6 local logger = require "util.logger"; 6 local logger = require "util.logger";
7 local log = logger.init("startup"); 7 local log = logger.init("startup");
8 local parse_args = require "util.argparse".parse;
8 9
9 local config = require "core.configmanager"; 10 local config = require "core.configmanager";
11 local config_warnings;
10 12
11 local dependencies = require "util.dependencies"; 13 local dependencies = require "util.dependencies";
12 14
13 local original_logging_config; 15 local original_logging_config;
14 16
16 18
17 local short_params = { D = "daemonize", F = "no-daemonize" }; 19 local short_params = { D = "daemonize", F = "no-daemonize" };
18 local value_params = { config = true }; 20 local value_params = { config = true };
19 21
20 function startup.parse_args() 22 function startup.parse_args()
21 local parsed_opts = {}; 23 local opts, err, where = parse_args(arg, {
22 prosody.opts = parsed_opts; 24 short_params = short_params,
23 25 value_params = value_params,
24 if #arg == 0 then 26 });
25 return; 27 if not opts then
26 end 28 if err == "param-not-found" then
27 while true do 29 print("Unknown command-line option: "..tostring(where));
28 local raw_param = arg[1];
29 if not raw_param then
30 break;
31 end
32
33 local prefix = raw_param:match("^%-%-?");
34 if not prefix then
35 break;
36 elseif prefix == "--" and raw_param == "--" then
37 table.remove(arg, 1);
38 break;
39 end
40 local param = table.remove(arg, 1):sub(#prefix+1);
41 if #param == 1 then
42 param = short_params[param];
43 end
44
45 if not param then
46 print("Unknown command-line option: "..tostring(param));
47 print("Perhaps you meant to use prosodyctl instead?"); 30 print("Perhaps you meant to use prosodyctl instead?");
48 os.exit(1); 31 elseif err == "missing-value" then
49 end 32 print("Expected a value to follow command-line option: "..where);
50 33 end
51 local param_k, param_v; 34 os.exit(1);
52 if value_params[param] then 35 end
53 param_k, param_v = param, table.remove(arg, 1); 36 prosody.opts = opts;
54 if not param_v then
55 print("Expected a value to follow command-line option: "..raw_param);
56 os.exit(1);
57 end
58 else
59 param_k, param_v = param:match("^([^=]+)=(.+)$");
60 if not param_k then
61 if param:match("^no%-") then
62 param_k, param_v = param:sub(4), false;
63 else
64 param_k, param_v = param, true;
65 end
66 end
67 end
68 parsed_opts[param_k] = param_v;
69 end
70 end 37 end
71 38
72 function startup.read_config() 39 function startup.read_config()
73 local filenames = {}; 40 local filenames = {};
74 41
119 print("More help on configuring Prosody can be found at https://prosody.im/doc/configure"); 86 print("More help on configuring Prosody can be found at https://prosody.im/doc/configure");
120 print("Good luck!"); 87 print("Good luck!");
121 print("**************************"); 88 print("**************************");
122 print(""); 89 print("");
123 os.exit(1); 90 os.exit(1);
91 elseif err and #err > 0 then
92 config_warnings = err;
124 end 93 end
125 prosody.config_loaded = true; 94 prosody.config_loaded = true;
126 end 95 end
127 96
128 function startup.check_dependencies() 97 function startup.check_dependencies()
151 loggingmanager.reload_logging(); 120 loggingmanager.reload_logging();
152 prosody.events.fire_event("logging-reloaded"); 121 prosody.events.fire_event("logging-reloaded");
153 end); 122 end);
154 end 123 end
155 124
156 function startup.log_dependency_warnings() 125 function startup.log_startup_warnings()
157 dependencies.log_warnings(); 126 dependencies.log_warnings();
127 if config_warnings then
128 for _, warning in ipairs(config_warnings) do
129 log("warn", "Configuration warning: %s", warning);
130 end
131 end
158 end 132 end
159 133
160 function startup.sanity_check() 134 function startup.sanity_check()
161 for host, host_config in pairs(config.getconfig()) do 135 for host, host_config in pairs(config.getconfig()) do
162 if host ~= "*" 136 if host ~= "*"
221 if name then 195 if name then
222 debug.setupvalue(f, i, value); 196 debug.setupvalue(f, i, value);
223 end 197 end
224 end 198 end
225 function mt.__tostring(f) 199 function mt.__tostring(f)
226 local info = debug.getinfo(f); 200 local info = debug.getinfo(f, "Su");
227 return ("function(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.linedefined); 201 local n_params = info.nparams or 0;
202 for i = 1, n_params do
203 info[i] = debug.getlocal(f, i);
204 end
205 if info.isvararg then
206 info[n_params+1] = "...";
207 end
208 return ("function<%s:%d>(%s)"):format(info.short_src:match("[^\\/]*$"), info.linedefined, table.concat(info, ", "));
228 end 209 end
229 debug.setmetatable(function() end, mt); 210 debug.setmetatable(function() end, mt);
230 end 211 end
231 212
232 function startup.detect_platform() 213 function startup.detect_platform()
274 prosody.paths.data = config.get("*", "data_path") or CFG_DATADIR or "data"; 255 prosody.paths.data = config.get("*", "data_path") or CFG_DATADIR or "data";
275 end 256 end
276 257
277 function startup.setup_plugindir() 258 function startup.setup_plugindir()
278 local custom_plugin_paths = config.get("*", "plugin_paths"); 259 local custom_plugin_paths = config.get("*", "plugin_paths");
260 local path_sep = package.config:sub(3,3);
279 if custom_plugin_paths then 261 if custom_plugin_paths then
280 local path_sep = package.config:sub(3,3);
281 -- path1;path2;path3;defaultpath... 262 -- path1;path2;path3;defaultpath...
282 -- luacheck: ignore 111 263 -- luacheck: ignore 111
283 CFG_PLUGINDIR = table.concat(custom_plugin_paths, path_sep)..path_sep..(CFG_PLUGINDIR or "plugins"); 264 CFG_PLUGINDIR = table.concat(custom_plugin_paths, path_sep)..path_sep..(CFG_PLUGINDIR or "plugins");
284 prosody.paths.plugins = CFG_PLUGINDIR; 265 prosody.paths.plugins = CFG_PLUGINDIR;
285 end 266 end
267 end
268
269 function startup.setup_plugin_install_path()
270 local installer_plugin_path = config.get("*", "installer_plugin_path") or (CFG_DATADIR or "data").."/custom_plugins";
271 local path_sep = package.config:sub(3,3);
272 -- TODO Figure out what this should be relative to, because CWD could be anywhere
273 installer_plugin_path = config.resolve_relative_path(require "lfs".currentdir(), installer_plugin_path);
274 -- TODO Can probably move directory creation to the install command
275 require "lfs".mkdir(installer_plugin_path);
276 require"util.paths".complement_lua_path(installer_plugin_path);
277 -- luacheck: ignore 111
278 CFG_PLUGINDIR = installer_plugin_path..path_sep..(CFG_PLUGINDIR or "plugins");
279 prosody.paths.installer = installer_plugin_path;
280 prosody.paths.plugins = CFG_PLUGINDIR;
286 end 281 end
287 282
288 function startup.chdir() 283 function startup.chdir()
289 if prosody.installed then 284 if prosody.installed then
290 local lfs = require "lfs"; 285 local lfs = require "lfs";
304 log("info", "Reloading configuration file"); 299 log("info", "Reloading configuration file");
305 prosody.events.fire_event("reloading-config"); 300 prosody.events.fire_event("reloading-config");
306 local ok, level, err = config.load(prosody.config_file); 301 local ok, level, err = config.load(prosody.config_file);
307 if not ok then 302 if not ok then
308 if level == "parser" then 303 if level == "parser" then
309 log("error", "There was an error parsing the configuration file: %s", tostring(err)); 304 log("error", "There was an error parsing the configuration file: %s", err);
310 elseif level == "file" then 305 elseif level == "file" then
311 log("error", "Couldn't read the config file when trying to reload: %s", tostring(err)); 306 log("error", "Couldn't read the config file when trying to reload: %s", err);
312 end 307 end
313 else 308 else
314 prosody.events.fire_event("config-reloaded", { 309 prosody.events.fire_event("config-reloaded", {
315 filename = prosody.config_file, 310 filename = prosody.config_file,
316 config = config.getconfig(), 311 config = config.getconfig(),
480 if not prosody.switched_user then 475 if not prosody.switched_user then
481 -- Boo! 476 -- Boo!
482 print("Warning: Couldn't switch to Prosody user/group '"..tostring(desired_user).."'/'"..tostring(desired_group).."': "..tostring(err)); 477 print("Warning: Couldn't switch to Prosody user/group '"..tostring(desired_user).."'/'"..tostring(desired_group).."': "..tostring(err));
483 else 478 else
484 -- Make sure the Prosody user can read the config 479 -- Make sure the Prosody user can read the config
485 local conf, err, errno = io.open(prosody.config_file); 480 local conf, err, errno = io.open(prosody.config_file); --luacheck: ignore 211/errno
486 if conf then 481 if conf then
487 conf:close(); 482 conf:close();
488 else 483 else
489 print("The config file is not readable by the '"..desired_user.."' user."); 484 print("The config file is not readable by the '"..desired_user.."' user.");
490 print("Prosody will not be able to read it."); 485 print("Prosody will not be able to read it.");
557 return nil, err; 552 return nil, err;
558 end 553 end
559 return true; 554 return true;
560 end 555 end
561 556
557 function startup.init_errors()
558 require "util.error".configure(config.get("*", "error_library") or {});
559 end
560
562 function startup.make_host(hostname) 561 function startup.make_host(hostname)
563 return { 562 return {
564 type = "local", 563 type = "local",
565 events = prosody.events, 564 events = prosody.events,
566 modules = {}, 565 modules = {},
581 end 580 end
582 end 581 end
583 582
584 -- prosodyctl only 583 -- prosodyctl only
585 function startup.prosodyctl() 584 function startup.prosodyctl()
585 prosody.process_type = "prosodyctl";
586 startup.parse_args(); 586 startup.parse_args();
587 startup.init_global_state(); 587 startup.init_global_state();
588 startup.read_config(); 588 startup.read_config();
589 startup.force_console_logging(); 589 startup.force_console_logging();
590 startup.init_logging(); 590 startup.init_logging();
591 startup.init_gc(); 591 startup.init_gc();
592 startup.init_errors();
592 startup.setup_plugindir(); 593 startup.setup_plugindir();
594 startup.setup_plugin_install_path();
593 startup.setup_datadir(); 595 startup.setup_datadir();
594 startup.chdir(); 596 startup.chdir();
595 startup.read_version(); 597 startup.read_version();
596 startup.switch_user(); 598 startup.switch_user();
597 startup.check_dependencies(); 599 startup.check_dependencies();
598 startup.log_dependency_warnings(); 600 startup.log_startup_warnings();
599 startup.check_unwriteable(); 601 startup.check_unwriteable();
600 startup.load_libraries(); 602 startup.load_libraries();
601 startup.init_http_client(); 603 startup.init_http_client();
602 startup.make_dummy_hosts(); 604 startup.make_dummy_hosts();
603 end 605 end
604 606
605 function startup.prosody() 607 function startup.prosody()
606 -- These actions are in a strict order, as many depend on 608 -- These actions are in a strict order, as many depend on
607 -- previous steps to have already been performed 609 -- previous steps to have already been performed
610 prosody.process_type = "prosody";
608 startup.parse_args(); 611 startup.parse_args();
609 startup.init_global_state(); 612 startup.init_global_state();
610 startup.read_config(); 613 startup.read_config();
611 startup.init_logging(); 614 startup.init_logging();
612 startup.init_gc(); 615 startup.init_gc();
616 startup.init_errors();
613 startup.sanity_check(); 617 startup.sanity_check();
614 startup.sandbox_require(); 618 startup.sandbox_require();
615 startup.set_function_metatable(); 619 startup.set_function_metatable();
616 startup.check_dependencies(); 620 startup.check_dependencies();
617 startup.load_libraries(); 621 startup.load_libraries();
618 startup.setup_plugindir(); 622 startup.setup_plugindir();
623 startup.setup_plugin_install_path();
619 startup.setup_datadir(); 624 startup.setup_datadir();
620 startup.chdir(); 625 startup.chdir();
621 startup.add_global_prosody_functions(); 626 startup.add_global_prosody_functions();
622 startup.read_version(); 627 startup.read_version();
623 startup.log_greeting(); 628 startup.log_greeting();
624 startup.log_dependency_warnings(); 629 startup.log_startup_warnings();
625 startup.load_secondary_libraries(); 630 startup.load_secondary_libraries();
626 startup.init_http_client(); 631 startup.init_http_client();
627 startup.init_data_store(); 632 startup.init_data_store();
628 startup.init_global_protection(); 633 startup.init_global_protection();
629 startup.prepare_to_start(); 634 startup.prepare_to_start();