Mercurial > prosody-hg
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 |
| parents | 89162d27e1b1 |
| children | 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(); |
