diff options
Diffstat (limited to 'util/startup.lua')
-rw-r--r-- | util/startup.lua | 157 |
1 files changed, 96 insertions, 61 deletions
diff --git a/util/startup.lua b/util/startup.lua index 602dfe5e..5db1c51a 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -5,8 +5,10 @@ local startup = {}; local prosody = { events = require "util.events".new() }; local logger = require "util.logger"; local log = logger.init("startup"); +local parse_args = require "util.argparse".parse; local config = require "core.configmanager"; +local config_warnings; local dependencies = require "util.dependencies"; @@ -20,59 +22,38 @@ local default_gc_params = { minor_threshold = 20, major_threshold = 50; }; -local short_params = { D = "daemonize", F = "no-daemonize" }; -local value_params = { config = true }; - -function startup.parse_args() - local parsed_opts = {}; - prosody.opts = parsed_opts; - - if #arg == 0 then - return; - end - while true do - local raw_param = arg[1]; - if not raw_param then - break; - end - - local prefix = raw_param:match("^%-%-?"); - if not prefix then - break; - elseif prefix == "--" and raw_param == "--" then - table.remove(arg, 1); - break; - end - local param = table.remove(arg, 1):sub(#prefix+1); - if #param == 1 then - param = short_params[param]; - end - - if not param then - print("Unknown command-line option: "..tostring(raw_param)); - print("Perhaps you meant to use prosodyctl instead?"); - os.exit(1); - end - - local param_k, param_v; - if value_params[param] then - param_k, param_v = param, table.remove(arg, 1); - if not param_v then - print("Expected a value to follow command-line option: "..raw_param); - os.exit(1); - end - else - param_k, param_v = param:match("^([^=]+)=(.+)$"); - if not param_k then - if param:match("^no%-") then - param_k, param_v = param:sub(4), false; - else - param_k, param_v = param, true; - end +local arg_settigs = { + prosody = { + short_params = { D = "daemonize"; F = "no-daemonize", h = "help", ["?"] = "help" }; + value_params = { config = true }; + }; + prosodyctl = { + short_params = { v = "verbose", h = "help", ["?"] = "help" }; + value_params = { config = true }; + }; +} + +function startup.parse_args(profile) + local opts, err, where = parse_args(arg, arg_settigs[profile or prosody.process_type] or profile); + if not opts then + if err == "param-not-found" then + print("Unknown command-line option: "..tostring(where)); + if prosody.process_type == "prosody" then + print("Perhaps you meant to use prosodyctl instead?"); end + elseif err == "missing-value" then + print("Expected a value to follow command-line option: "..where); end - parsed_opts[param_k] = param_v; + os.exit(1); + end + if opts.help and prosody.process_type == "prosody" then + print("prosody [ -D | -F ] [ --config /path/to/prosody.cfg.lua ]"); + print(" -D, --daemonize Run in the background") + print(" -F, --no-daemonize Run in the foreground") + print(" --config FILE Specify config file") + os.exit(0); end + prosody.opts = opts; end function startup.read_config() @@ -127,6 +108,8 @@ function startup.read_config() print("**************************"); print(""); os.exit(1); + elseif err and #err > 0 then + config_warnings = err; end prosody.config_loaded = true; end @@ -159,8 +142,13 @@ function startup.init_logging() end); end -function startup.log_dependency_warnings() +function startup.log_startup_warnings() dependencies.log_warnings(); + if config_warnings then + for _, warning in ipairs(config_warnings) do + log("warn", "Configuration warning: %s", warning); + end + end end function startup.sanity_check() @@ -229,8 +217,15 @@ function startup.set_function_metatable() end end function mt.__tostring(f) - local info = debug.getinfo(f); - return ("function(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.linedefined); + local info = debug.getinfo(f, "Su"); + local n_params = info.nparams or 0; + for i = 1, n_params do + info[i] = debug.getlocal(f, i); + end + if info.isvararg then + info[n_params+1] = "..."; + end + return ("function<%s:%d>(%s)"):format(info.short_src:match("[^\\/]*$"), info.linedefined, table.concat(info, ", ")); end debug.setmetatable(function() end, mt); end @@ -282,8 +277,8 @@ end function startup.setup_plugindir() local custom_plugin_paths = config.get("*", "plugin_paths"); + local path_sep = package.config:sub(3,3); if custom_plugin_paths then - local path_sep = package.config:sub(3,3); -- path1;path2;path3;defaultpath... -- luacheck: ignore 111 CFG_PLUGINDIR = table.concat(custom_plugin_paths, path_sep)..path_sep..(CFG_PLUGINDIR or "plugins"); @@ -291,6 +286,17 @@ function startup.setup_plugindir() end end +function startup.setup_plugin_install_path() + local installer_plugin_path = config.get("*", "installer_plugin_path") or "custom_plugins"; + local path_sep = package.config:sub(3,3); + installer_plugin_path = config.resolve_relative_path(CFG_DATADIR or "data", installer_plugin_path); + require"util.paths".complement_lua_path(installer_plugin_path); + -- luacheck: ignore 111 + CFG_PLUGINDIR = installer_plugin_path..path_sep..(CFG_PLUGINDIR or "plugins"); + prosody.paths.installer = installer_plugin_path; + prosody.paths.plugins = CFG_PLUGINDIR; +end + function startup.chdir() if prosody.installed then local lfs = require "lfs"; @@ -312,9 +318,9 @@ function startup.add_global_prosody_functions() local ok, level, err = config.load(prosody.config_file); if not ok then if level == "parser" then - log("error", "There was an error parsing the configuration file: %s", tostring(err)); + log("error", "There was an error parsing the configuration file: %s", err); elseif level == "file" then - log("error", "Couldn't read the config file when trying to reload: %s", tostring(err)); + log("error", "Couldn't read the config file when trying to reload: %s", err); end else prosody.events.fire_event("config-reloaded", { @@ -389,6 +395,21 @@ function startup.init_http_client() { capath = config_ssl.capath, cafile = config_ssl.cafile, verify = "peer", }, https_client); end +function startup.init_promise() + local promise = require "util.promise"; + + local timer = require "util.timer"; + promise.set_nexttick(function(f) return timer.add_task(0, f); end); +end + +function startup.init_async() + local async = require "util.async"; + + local timer = require "util.timer"; + async.set_nexttick(function(f) return timer.add_task(0, f); end); + async.set_schedule_function(timer.add_task); +end + function startup.init_data_store() require "core.storagemanager"; end @@ -448,7 +469,9 @@ end -- Override logging config (used by prosodyctl) function startup.force_console_logging() original_logging_config = config.get("*", "log"); - config.set("*", "log", { { levels = { min = os.getenv("PROSODYCTL_LOG_LEVEL") or "info" }, to = "console" } }); + local log_level = os.getenv("PROSODYCTL_LOG_LEVEL"); + if not log_level and prosody.opts.verbose then log_level = "debug"; end + config.set("*", "log", { { levels = { min = log_level or "info" }, to = "console" } }); end function startup.switch_user() @@ -486,9 +509,9 @@ function startup.switch_user() if not prosody.switched_user then -- Boo! print("Warning: Couldn't switch to Prosody user/group '"..tostring(desired_user).."'/'"..tostring(desired_group).."': "..tostring(err)); - else + elseif prosody.config_file then -- Make sure the Prosody user can read the config - local conf, err, errno = io.open(prosody.config_file); + local conf, err, errno = io.open(prosody.config_file); --luacheck: ignore 211/errno if conf then conf:close(); else @@ -565,6 +588,10 @@ function startup.init_gc() return true; end +function startup.init_errors() + require "util.error".configure(config.get("*", "error_library") or {}); +end + function startup.make_host(hostname) return { type = "local", @@ -589,19 +616,22 @@ end -- prosodyctl only function startup.prosodyctl() + prosody.process_type = "prosodyctl"; startup.parse_args(); startup.init_global_state(); startup.read_config(); startup.force_console_logging(); startup.init_logging(); startup.init_gc(); + startup.init_errors(); startup.setup_plugindir(); + startup.setup_plugin_install_path(); startup.setup_datadir(); startup.chdir(); startup.read_version(); startup.switch_user(); startup.check_dependencies(); - startup.log_dependency_warnings(); + startup.log_startup_warnings(); startup.check_unwriteable(); startup.load_libraries(); startup.init_http_client(); @@ -611,24 +641,29 @@ end function startup.prosody() -- These actions are in a strict order, as many depend on -- previous steps to have already been performed + prosody.process_type = "prosody"; startup.parse_args(); startup.init_global_state(); startup.read_config(); startup.init_logging(); startup.init_gc(); + startup.init_errors(); startup.sanity_check(); startup.sandbox_require(); startup.set_function_metatable(); startup.check_dependencies(); startup.load_libraries(); startup.setup_plugindir(); + startup.setup_plugin_install_path(); startup.setup_datadir(); startup.chdir(); startup.add_global_prosody_functions(); startup.read_version(); startup.log_greeting(); - startup.log_dependency_warnings(); + startup.log_startup_warnings(); startup.load_secondary_libraries(); + startup.init_promise(); + startup.init_async(); startup.init_http_client(); startup.init_data_store(); startup.init_global_protection(); |