From caa39bba7dc7aaa75a868b51c863a5d428fa74c3 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Thu, 21 Nov 2019 12:06:15 +0000 Subject: [PATCH] dinitcheck: use previously factored-out parameter processing dinitcheck now shares parameter processing with dinit, providing consistent error messages and parsing. --- src/dinitcheck.cc | 324 ++---------------------------------- src/includes/load-service.h | 2 +- 2 files changed, 15 insertions(+), 311 deletions(-) diff --git a/src/dinitcheck.cc b/src/dinitcheck.cc index 302e9ae..0237fd9 100644 --- a/src/dinitcheck.cc +++ b/src/dinitcheck.cc @@ -31,7 +31,7 @@ class prelim_dep std::string name; dependency_type dep_type; - prelim_dep(std::string &name_p, dependency_type dep_type_p) + prelim_dep(const std::string &name_p, dependency_type dep_type_p) : name(name_p), dep_type(dep_type_p) { } prelim_dep(std::string &&name_p, dependency_type dep_type_p) : name(std::move(name_p)), dep_type(dep_type_p) { } @@ -124,16 +124,6 @@ int main(int argc, char **argv) return 0; } -static void report_unknown_setting_error(const std::string &service_name, const char *setting_name) -{ - std::cerr << "Service '" << service_name << "', unknown setting: '" << setting_name << "'.\n"; -} - -static void report_error(dinit_load::setting_exception &exc, const std::string &service_name, const char *setting_name) -{ - std::cerr << "Service '" << service_name << "', " << setting_name << ": " << exc.get_info() << "\n"; -} - static void report_service_description_exc(service_description_exc &exc) { std::cerr << "Service '" << exc.service_name << "': " << exc.exc_description << "\n"; @@ -216,49 +206,7 @@ service_record *load_service(service_set_t &services, const std::string &name, throw service_not_found(string(name)); } - string command; - list> command_offsets; - string stop_command; - list> stop_command_offsets; - string working_dir; - string pid_file; - string env_file; - - bool do_sub_vars = false; - - service_type_t service_type = service_type_t::PROCESS; - std::list depends; - string logfile; - service_flags_t onstart_flags; - int term_signal = -1; // additional termination signal - bool auto_restart = false; - bool smooth_recovery = false; - string socket_path; - int socket_perms = 0666; - // Note: Posix allows that uid_t and gid_t may be unsigned types, but eg chown uses -1 as an - // invalid value, so it's safe to assume that we can do the same: - uid_t socket_uid = -1; - gid_t socket_gid = -1; - // Restart limit interval / count; default is 10 seconds, 3 restarts: - timespec restart_interval = { .tv_sec = 10, .tv_nsec = 0 }; - int max_restarts = 3; - timespec restart_delay = { .tv_sec = 0, .tv_nsec = 200000000 }; - timespec stop_timeout = { .tv_sec = 10, .tv_nsec = 0 }; - timespec start_timeout = { .tv_sec = 60, .tv_nsec = 0 }; - std::vector rlimits; - - int readiness_fd = -1; // readiness fd in service process - std::string readiness_var; // environment var to hold readiness fd - - uid_t run_as_uid = -1; - gid_t run_as_gid = -1; - - string chain_to_name; - - #if USE_UTMPX - char inittab_id[sizeof(utmpx().ut_id)] = {0}; - char inittab_line[sizeof(utmpx().ut_line)] = {0}; - #endif + service_settings_wrapper settings; string line; service_file.exceptions(ios::badbit); @@ -266,266 +214,22 @@ service_record *load_service(service_set_t &services, const std::string &name, try { process_service_file(name, service_file, [&](string &line, string &setting, string_iterator &i, string_iterator &end) -> void { + + auto process_dep_dir_n = [&](std::list &deplist, const std::string &waitsford, + dependency_type dep_type) -> void { + process_dep_dir(name.c_str(), service_filename, deplist, waitsford, dep_type); + }; + + auto load_service_n = [&](const string &dep_name) -> const string & { + return dep_name; + }; + try { - if (setting == "command") { - command = read_setting_value(i, end, &command_offsets); - } - else if (setting == "working-dir") { - working_dir = read_setting_value(i, end, nullptr); - } - else if (setting == "env-file") { - env_file = read_setting_value(i, end, nullptr); - } - else if (setting == "socket-listen") { - socket_path = read_setting_value(i, end, nullptr); - } - else if (setting == "socket-permissions") { - string sock_perm_str = read_setting_value(i, end, nullptr); - std::size_t ind = 0; - try { - socket_perms = std::stoi(sock_perm_str, &ind, 8); - if (ind != sock_perm_str.length()) { - throw std::logic_error(""); - } - } - catch (std::logic_error &exc) { - throw service_description_exc(name, "socket-permissions: Badly-formed or " - "out-of-range numeric value"); - } - } - else if (setting == "socket-uid") { - string sock_uid_s = read_setting_value(i, end, nullptr); - socket_uid = parse_uid_param(sock_uid_s, name, "socket-uid", &socket_gid); - } - else if (setting == "socket-gid") { - string sock_gid_s = read_setting_value(i, end, nullptr); - socket_gid = parse_gid_param(sock_gid_s, "socket-gid", name); - } - else if (setting == "stop-command") { - stop_command = read_setting_value(i, end, &stop_command_offsets); - } - else if (setting == "pid-file") { - pid_file = read_setting_value(i, end); - } - else if (setting == "depends-on") { - string dependency_name = read_setting_value(i, end); - depends.emplace_back(std::move(dependency_name), dependency_type::REGULAR); - } - else if (setting == "depends-ms") { - string dependency_name = read_setting_value(i, end); - depends.emplace_back(dependency_name, dependency_type::MILESTONE); - } - else if (setting == "waits-for") { - string dependency_name = read_setting_value(i, end); - depends.emplace_back(dependency_name, dependency_type::WAITS_FOR); - } - else if (setting == "waits-for.d") { - string waitsford = read_setting_value(i, end); - process_dep_dir(name.c_str(), service_filename, depends, waitsford, - dependency_type::WAITS_FOR); - } - else if (setting == "logfile") { - logfile = read_setting_value(i, end); - } - else if (setting == "restart") { - string restart = read_setting_value(i, end); - auto_restart = (restart == "yes" || restart == "true"); - } - else if (setting == "smooth-recovery") { - string recovery = read_setting_value(i, end); - smooth_recovery = (recovery == "yes" || recovery == "true"); - } - else if (setting == "type") { - string type_str = read_setting_value(i, end); - if (type_str == "scripted") { - service_type = service_type_t::SCRIPTED; - } - else if (type_str == "process") { - service_type = service_type_t::PROCESS; - } - else if (type_str == "bgprocess") { - service_type = service_type_t::BGPROCESS; - } - else if (type_str == "internal") { - service_type = service_type_t::INTERNAL; - } - else { - throw service_description_exc(name, "Service type must be one of: \"scripted\"," - " \"process\", \"bgprocess\" or \"internal\""); - } - } - else if (setting == "options") { - std::list> indices; - string onstart_cmds = read_setting_value(i, end, &indices); - for (auto indexpair : indices) { - string option_txt = onstart_cmds.substr(indexpair.first, - indexpair.second - indexpair.first); - if (option_txt == "starts-rwfs") { - onstart_flags.rw_ready = true; - } - else if (option_txt == "starts-log") { - onstart_flags.log_ready = true; - } - else if (option_txt == "no-sigterm") { - onstart_flags.no_sigterm = true; - } - else if (option_txt == "runs-on-console") { - onstart_flags.runs_on_console = true; - // A service that runs on the console necessarily starts on console: - onstart_flags.starts_on_console = true; - onstart_flags.shares_console = false; - } - else if (option_txt == "starts-on-console") { - onstart_flags.starts_on_console = true; - onstart_flags.shares_console = false; - } - else if (option_txt == "shares-console") { - onstart_flags.shares_console = true; - onstart_flags.runs_on_console = false; - onstart_flags.starts_on_console = false; - } - else if (option_txt == "pass-cs-fd") { - onstart_flags.pass_cs_fd = true; - } - else if (option_txt == "start-interruptible") { - onstart_flags.start_interruptible = true; - } - else if (option_txt == "skippable") { - onstart_flags.skippable = true; - } - else if (option_txt == "signal-process-only") { - onstart_flags.signal_process_only = true; - } - else { - throw service_description_exc(name, "Unknown option: " + option_txt); - } - } - } - else if (setting == "load-options") { - std::list> indices; - string load_opts = read_setting_value(i, end, &indices); - for (auto indexpair : indices) { - string option_txt = load_opts.substr(indexpair.first, - indexpair.second - indexpair.first); - if (option_txt == "sub-vars") { - // substitute environment variables in command line - do_sub_vars = true; - } - else if (option_txt == "no-sub-vars") { - do_sub_vars = false; - } - else { - throw service_description_exc(name, "Unknown load option: " + option_txt); - } - } - } - else if (setting == "term-signal" || setting == "termsignal") { - // Note: "termsignal" supported for legacy reasons. - string signame = read_setting_value(i, end, nullptr); - int signo = signal_name_to_number(signame); - if (signo == -1) { - throw service_description_exc(name, "Unknown/unsupported termination signal: " - + signame); - } - else { - term_signal = signo; - } - } - else if (setting == "restart-limit-interval") { - string interval_str = read_setting_value(i, end, nullptr); - parse_timespec(interval_str, name, "restart-limit-interval", restart_interval); - } - else if (setting == "restart-delay") { - string rsdelay_str = read_setting_value(i, end, nullptr); - parse_timespec(rsdelay_str, name, "restart-delay", restart_delay); - } - else if (setting == "restart-limit-count") { - string limit_str = read_setting_value(i, end, nullptr); - max_restarts = parse_unum_param(limit_str, name, std::numeric_limits::max()); - } - else if (setting == "stop-timeout") { - string stoptimeout_str = read_setting_value(i, end, nullptr); - parse_timespec(stoptimeout_str, name, "stop-timeout", stop_timeout); - } - else if (setting == "start-timeout") { - string starttimeout_str = read_setting_value(i, end, nullptr); - parse_timespec(starttimeout_str, name, "start-timeout", start_timeout); - } - else if (setting == "run-as") { - string run_as_str = read_setting_value(i, end, nullptr); - run_as_uid = parse_uid_param(run_as_str, name, "run-as", &run_as_gid); - } - else if (setting == "chain-to") { - chain_to_name = read_setting_value(i, end, nullptr); - } - else if (setting == "ready-notification") { - string notify_setting = read_setting_value(i, end, nullptr); - if (starts_with(notify_setting, "pipefd:")) { - readiness_fd = parse_unum_param(notify_setting.substr(7 /* len 'pipefd:' */), - name, std::numeric_limits::max()); - } - else if (starts_with(notify_setting, "pipevar:")) { - readiness_var = notify_setting.substr(8 /* len 'pipevar:' */); - if (readiness_var.empty()) { - throw service_description_exc(name, "Invalid pipevar variable name " - "in ready-notification"); - } - } - else { - throw service_description_exc(name, "Unknown ready-notification setting: " - + notify_setting); - } - } - else if (setting == "inittab-id") { - string inittab_setting = read_setting_value(i, end, nullptr); - #if USE_UTMPX - if (inittab_setting.length() > sizeof(inittab_id)) { - throw service_description_exc(name, "inittab-id setting is too long"); - } - strncpy(inittab_id, inittab_setting.c_str(), sizeof(inittab_id)); - #endif - } - else if (setting == "inittab-line") { - string inittab_setting = read_setting_value(i, end, nullptr); - #if USE_UTMPX - if (inittab_setting.length() > sizeof(inittab_line)) { - throw service_description_exc(name, "inittab-line setting is too long"); - } - strncpy(inittab_line, inittab_setting.c_str(), sizeof(inittab_line)); - #endif - } - else if (setting == "rlimit-nofile") { - string nofile_setting = read_setting_value(i, end, nullptr); - service_rlimits &nofile_limits = find_rlimits(rlimits, RLIMIT_NOFILE); - parse_rlimit(line, name, "rlimit-nofile", nofile_limits); - } - else if (setting == "rlimit-core") { - string nofile_setting = read_setting_value(i, end, nullptr); - service_rlimits &nofile_limits = find_rlimits(rlimits, RLIMIT_CORE); - parse_rlimit(line, name, "rlimit-core", nofile_limits); - } - else if (setting == "rlimit-data") { - string nofile_setting = read_setting_value(i, end, nullptr); - service_rlimits &nofile_limits = find_rlimits(rlimits, RLIMIT_DATA); - parse_rlimit(line, name, "rlimit-data", nofile_limits); - } - else if (setting == "rlimit-addrspace") { - #if defined(RLIMIT_AS) - string nofile_setting = read_setting_value(i, end, nullptr); - service_rlimits &nofile_limits = find_rlimits(rlimits, RLIMIT_AS); - parse_rlimit(line, name, "rlimit-addrspace", nofile_limits); - #endif - } - else { - report_unknown_setting_error(name, setting.c_str()); - } + process_service_line(settings, name.c_str(), line, setting, i, end, load_service_n, process_dep_dir_n); } catch (service_description_exc &exc) { report_service_description_exc(exc); } - catch (setting_exception &exc) { - report_error(exc, name, setting.c_str()); - } }); } catch (std::system_error &sys_err) @@ -534,5 +238,5 @@ service_record *load_service(service_set_t &services, const std::string &name, return nullptr; } - return new service_record(name, depends); + return new service_record(name, settings.depends); } diff --git a/src/includes/load-service.h b/src/includes/load-service.h index a00a081..2f6b278 100644 --- a/src/includes/load-service.h +++ b/src/includes/load-service.h @@ -892,7 +892,7 @@ void process_service_line(settings_wrapper &settings, const char *name, string & #endif } else { - throw service_description_exc(name, "Unknown setting: " + setting); + throw service_description_exc(name, "Unknown setting: '" + setting + "'."); } } -- 2.25.1