From bec46b4d4a30fa64fa021a9a0df2c4767fa0e44d Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Thu, 21 Nov 2019 10:41:34 +0000 Subject: [PATCH] Factor out service parameter processing Factor service parameter processing into a template method, to enable sharing (later) between load_service in dinit and dinitcheck. --- src/includes/dinit-utmp.h | 2 + src/includes/load-service.h | 341 ++++++++++++++++++++++++++++++ src/includes/service.h | 2 +- src/load-service.cc | 408 ++++++------------------------------ src/mconfig-gen.cc | 8 +- 5 files changed, 415 insertions(+), 346 deletions(-) diff --git a/src/includes/dinit-utmp.h b/src/includes/dinit-utmp.h index f02eca2..eb32e4f 100644 --- a/src/includes/dinit-utmp.h +++ b/src/includes/dinit-utmp.h @@ -3,6 +3,8 @@ #ifndef DINIT_UTMP_H_INCLUDED #define DINIT_UTMP_H_INCLUDED +#include "mconfig.h" // pull in any explicit configuration + // Configuration: // USE_UTMPX - whether to update the utmp[x] database. If 0, no-op stubs are defined. // USE_UPDWTMPX - whether to use the updwtmpx function to log boot (contingent on USE_UTMPX). diff --git a/src/includes/load-service.h b/src/includes/load-service.h index d19bac1..a00a081 100644 --- a/src/includes/load-service.h +++ b/src/includes/load-service.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -10,6 +11,9 @@ #include #include +#include "dinit-utmp.h" +#include "dinit-util.h" + struct service_flags_t { // on-start flags: @@ -555,6 +559,343 @@ void process_service_file(string name, std::istream &service_file, T func) } } +// A wrapper type for service parameters. It is parameterised by dependency type. +template +class service_settings_wrapper +{ + template using pair = std::pair; + template using list = std::list; + + public: + + 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 +}; + +// Process a service description line. In general, parse the setting value and record the parsed value +// in a service settings wrapper object. Errors will be reported via service_description_exc exception. +// +// type parameters: +// settings_wrapper : wrapper for service settings +// load_service_t : type of load service function/lambda (see below) +// process_dep_dir_t : type of process_dep_dir funciton/lambda (see below) +// +// parameters: +// settings : wrapper object for service settings +// name : name of the service being processed +// line : the current line of the service description file +// setting : the name of the setting (from the beginning of line) +// i : iterator at beginning of setting value (including whitespace) +// end : iterator at end of line +// load_service : function to load a service +// arguments: const char *service_name +// return: a value that can be used (with a dependency type) to construct a dependency +// in the 'depends' vector within the 'settings' object +// process_dep_dir : function to process a dependency directory +// arguments: decltype(settings.depends) &dependencies +// const string &waitsford - directory as specified in parameter +// dependency_type dep_type - type of dependency to add +template +void process_service_line(settings_wrapper &settings, const char *name, string &line, string &setting, + string::iterator &i, string::iterator &end, load_service_t load_service, + process_dep_dir_t process_dep_dir) +{ + if (setting == "command") { + settings.command = read_setting_value(i, end, &settings.command_offsets); + } + else if (setting == "working-dir") { + settings.working_dir = read_setting_value(i, end, nullptr); + } + else if (setting == "env-file") { + settings.env_file = read_setting_value(i, end, nullptr); + } + else if (setting == "socket-listen") { + settings.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 { + settings.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); + settings.socket_uid = parse_uid_param(sock_uid_s, name, "socket-uid", &settings.socket_gid); + } + else if (setting == "socket-gid") { + string sock_gid_s = read_setting_value(i, end, nullptr); + settings.socket_gid = parse_gid_param(sock_gid_s, "socket-gid", name); + } + else if (setting == "stop-command") { + settings.stop_command = read_setting_value(i, end, &settings.stop_command_offsets); + } + else if (setting == "pid-file") { + settings.pid_file = read_setting_value(i, end); + } + else if (setting == "depends-on") { + string dependency_name = read_setting_value(i, end); + settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::REGULAR); + } + else if (setting == "depends-ms") { + string dependency_name = read_setting_value(i, end); + settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::MILESTONE); + } + else if (setting == "waits-for") { + string dependency_name = read_setting_value(i, end); + settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::WAITS_FOR); + } + else if (setting == "waits-for.d") { + string waitsford = read_setting_value(i, end); + process_dep_dir(settings.depends, waitsford, dependency_type::WAITS_FOR); + } + else if (setting == "logfile") { + settings.logfile = read_setting_value(i, end); + } + else if (setting == "restart") { + string restart = read_setting_value(i, end); + settings.auto_restart = (restart == "yes" || restart == "true"); + } + else if (setting == "smooth-recovery") { + string recovery = read_setting_value(i, end); + settings.smooth_recovery = (recovery == "yes" || recovery == "true"); + } + else if (setting == "type") { + string type_str = read_setting_value(i, end); + if (type_str == "scripted") { + settings.service_type = service_type_t::SCRIPTED; + } + else if (type_str == "process") { + settings.service_type = service_type_t::PROCESS; + } + else if (type_str == "bgprocess") { + settings.service_type = service_type_t::BGPROCESS; + } + else if (type_str == "internal") { + settings.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") { + settings.onstart_flags.rw_ready = true; + } + else if (option_txt == "starts-log") { + settings.onstart_flags.log_ready = true; + } + else if (option_txt == "no-sigterm") { + settings.onstart_flags.no_sigterm = true; + } + else if (option_txt == "runs-on-console") { + settings.onstart_flags.runs_on_console = true; + // A service that runs on the console necessarily starts on console: + settings.onstart_flags.starts_on_console = true; + settings.onstart_flags.shares_console = false; + } + else if (option_txt == "starts-on-console") { + settings.onstart_flags.starts_on_console = true; + settings.onstart_flags.shares_console = false; + } + else if (option_txt == "shares-console") { + settings.onstart_flags.shares_console = true; + settings.onstart_flags.runs_on_console = false; + settings.onstart_flags.starts_on_console = false; + } + else if (option_txt == "pass-cs-fd") { + settings.onstart_flags.pass_cs_fd = true; + } + else if (option_txt == "start-interruptible") { + settings.onstart_flags.start_interruptible = true; + } + else if (option_txt == "skippable") { + settings.onstart_flags.skippable = true; + } + else if (option_txt == "signal-process-only") { + settings.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 + settings.do_sub_vars = true; + } + else if (option_txt == "no-sub-vars") { + settings.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 { + settings.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", settings.restart_interval); + } + else if (setting == "restart-delay") { + string rsdelay_str = read_setting_value(i, end, nullptr); + parse_timespec(rsdelay_str, name, "restart-delay", settings.restart_delay); + } + else if (setting == "restart-limit-count") { + string limit_str = read_setting_value(i, end, nullptr); + settings.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", settings.stop_timeout); + } + else if (setting == "start-timeout") { + string starttimeout_str = read_setting_value(i, end, nullptr); + parse_timespec(starttimeout_str, name, "start-timeout", settings.start_timeout); + } + else if (setting == "run-as") { + string run_as_str = read_setting_value(i, end, nullptr); + settings.run_as_uid = parse_uid_param(run_as_str, name, "run-as", &settings.run_as_gid); + } + else if (setting == "chain-to") { + settings.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:")) { + settings.readiness_fd = parse_unum_param(notify_setting.substr(7 /* len 'pipefd:' */), + name, std::numeric_limits::max()); + } + else if (starts_with(notify_setting, "pipevar:")) { + settings.readiness_var = notify_setting.substr(8 /* len 'pipevar:' */); + if (settings.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(settings.inittab_id)) { + throw service_description_exc(name, "inittab-id setting is too long"); + } + strncpy(settings.inittab_id, inittab_setting.c_str(), sizeof(settings.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(settings.inittab_line)) { + throw service_description_exc(name, "inittab-line setting is too long"); + } + strncpy(settings.inittab_line, inittab_setting.c_str(), sizeof(settings.inittab_line)); + #endif + } + else if (setting == "rlimit-nofile") { + string nofile_setting = read_setting_value(i, end, nullptr); + service_rlimits &nofile_limits = find_rlimits(settings.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(settings.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(settings.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(settings.rlimits, RLIMIT_AS); + parse_rlimit(line, name, "rlimit-addrspace", nofile_limits); + #endif + } + else { + throw service_description_exc(name, "Unknown setting: " + setting); + } +} + } // namespace dinit_load using dinit_load::process_service_file; diff --git a/src/includes/service.h b/src/includes/service.h index 35c58a4..ef1b6a6 100644 --- a/src/includes/service.h +++ b/src/includes/service.h @@ -164,7 +164,7 @@ class prelim_dep prelim_dep(service_record *to_p, dependency_type dep_type_p) : to(to_p), dep_type(dep_type_p) { - // + // (constructor) } }; diff --git a/src/load-service.cc b/src/load-service.cc index 791f05b..35de651 100644 --- a/src/load-service.cc +++ b/src/load-service.cc @@ -160,49 +160,7 @@ service_record * dirload_service_set::load_service(const char * 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; // getline can set failbit if it reaches end-of-file, we don't want an exception in that case. There's @@ -217,265 +175,26 @@ service_record * dirload_service_set::load_service(const char * name) try { process_service_file(name, service_file, [&](string &line, string &setting, string_iterator &i, string_iterator &end) -> void { - 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(load_service(dependency_name.c_str()), dependency_type::REGULAR); - } - else if (setting == "depends-ms") { - string dependency_name = read_setting_value(i, end); - depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::MILESTONE); - } - else if (setting == "waits-for") { - string dependency_name = read_setting_value(i, end); - depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::WAITS_FOR); - } - else if (setting == "waits-for.d") { - string waitsford = read_setting_value(i, end); - process_dep_dir(*this, name, 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 { - throw service_description_exc(name, "Unknown setting: " + setting); - } + + auto process_dep_dir_n = [&](std::list &deplist, const std::string &waitsford, + dependency_type dep_type) -> void { + process_dep_dir(*this, name, service_filename, deplist, waitsford, dep_type); + }; + + auto load_service_n = [&](const string &dep_name) -> service_record * { + return load_service(dep_name.c_str()); + }; + + process_service_line(settings, name, line, setting, i, end, load_service_n, process_dep_dir_n); }); service_file.close(); + auto service_type = settings.service_type; + if (service_type == service_type_t::PROCESS || service_type == service_type_t::BGPROCESS || service_type == service_type_t::SCRIPTED) { - if (command.length() == 0) { + if (settings.command.length() == 0) { throw service_description_exc(name, "Service command not specified"); } } @@ -486,66 +205,67 @@ service_record * dirload_service_set::load_service(const char * name) // We've found the dummy record delete rval; if (service_type == service_type_t::PROCESS) { - do_env_subst(command, command_offsets, do_sub_vars); - auto rvalps = new process_service(this, string(name), std::move(command), - command_offsets, depends); - rvalps->set_working_dir(working_dir); - rvalps->set_env_file(env_file); - rvalps->set_rlimits(std::move(rlimits)); - rvalps->set_restart_interval(restart_interval, max_restarts); - rvalps->set_restart_delay(restart_delay); - rvalps->set_stop_timeout(stop_timeout); - rvalps->set_start_timeout(start_timeout); - rvalps->set_extra_termination_signal(term_signal); - rvalps->set_run_as_uid_gid(run_as_uid, run_as_gid); - rvalps->set_notification_fd(readiness_fd); - rvalps->set_notification_var(std::move(readiness_var)); + do_env_subst(settings.command, settings.command_offsets, settings.do_sub_vars); + auto rvalps = new process_service(this, string(name), std::move(settings.command), + settings.command_offsets, settings.depends); + rvalps->set_working_dir(settings.working_dir); + rvalps->set_env_file(settings.env_file); + rvalps->set_rlimits(std::move(settings.rlimits)); + rvalps->set_restart_interval(settings.restart_interval, settings.max_restarts); + rvalps->set_restart_delay(settings.restart_delay); + rvalps->set_stop_timeout(settings.stop_timeout); + rvalps->set_start_timeout(settings.start_timeout); + rvalps->set_extra_termination_signal(settings.term_signal); + rvalps->set_run_as_uid_gid(settings.run_as_uid, settings.run_as_gid); + rvalps->set_notification_fd(settings.readiness_fd); + rvalps->set_notification_var(std::move(settings.readiness_var)); #if USE_UTMPX - rvalps->set_utmp_id(inittab_id); - rvalps->set_utmp_line(inittab_line); + rvalps->set_utmp_id(settings.inittab_id); + rvalps->set_utmp_line(settings.inittab_line); #endif rval = rvalps; } else if (service_type == service_type_t::BGPROCESS) { - do_env_subst(command, command_offsets, do_sub_vars); - auto rvalps = new bgproc_service(this, string(name), std::move(command), - command_offsets, depends); - rvalps->set_working_dir(working_dir); - rvalps->set_env_file(env_file); - rvalps->set_rlimits(std::move(rlimits)); - rvalps->set_pid_file(std::move(pid_file)); - rvalps->set_restart_interval(restart_interval, max_restarts); - rvalps->set_restart_delay(restart_delay); - rvalps->set_stop_timeout(stop_timeout); - rvalps->set_start_timeout(start_timeout); - rvalps->set_extra_termination_signal(term_signal); - rvalps->set_run_as_uid_gid(run_as_uid, run_as_gid); - onstart_flags.runs_on_console = false; + do_env_subst(settings.command, settings.command_offsets, settings.do_sub_vars); + auto rvalps = new bgproc_service(this, string(name), std::move(settings.command), + settings.command_offsets, settings.depends); + rvalps->set_working_dir(settings.working_dir); + rvalps->set_env_file(settings.env_file); + rvalps->set_rlimits(std::move(settings.rlimits)); + rvalps->set_pid_file(std::move(settings.pid_file)); + rvalps->set_restart_interval(settings.restart_interval, settings.max_restarts); + rvalps->set_restart_delay(settings.restart_delay); + rvalps->set_stop_timeout(settings.stop_timeout); + rvalps->set_start_timeout(settings.start_timeout); + rvalps->set_extra_termination_signal(settings.term_signal); + rvalps->set_run_as_uid_gid(settings.run_as_uid, settings.run_as_gid); + settings.onstart_flags.runs_on_console = false; rval = rvalps; } else if (service_type == service_type_t::SCRIPTED) { - do_env_subst(command, command_offsets, do_sub_vars); - auto rvalps = new scripted_service(this, string(name), std::move(command), - command_offsets, depends); - rvalps->set_stop_command(stop_command, stop_command_offsets); - rvalps->set_working_dir(working_dir); - rvalps->set_env_file(env_file); - rvalps->set_rlimits(std::move(rlimits)); - rvalps->set_stop_timeout(stop_timeout); - rvalps->set_start_timeout(start_timeout); - rvalps->set_extra_termination_signal(term_signal); - rvalps->set_run_as_uid_gid(run_as_uid, run_as_gid); + do_env_subst(settings.command, settings.command_offsets, settings.do_sub_vars); + auto rvalps = new scripted_service(this, string(name), std::move(settings.command), + settings.command_offsets, settings.depends); + rvalps->set_stop_command(settings.stop_command, settings.stop_command_offsets); + rvalps->set_working_dir(settings.working_dir); + rvalps->set_env_file(settings.env_file); + rvalps->set_rlimits(std::move(settings.rlimits)); + rvalps->set_stop_timeout(settings.stop_timeout); + rvalps->set_start_timeout(settings.start_timeout); + rvalps->set_extra_termination_signal(settings.term_signal); + rvalps->set_run_as_uid_gid(settings.run_as_uid, settings.run_as_gid); rval = rvalps; } else { - rval = new service_record(this, string(name), service_type, depends); + rval = new service_record(this, string(name), service_type, settings.depends); } - rval->set_log_file(logfile); - rval->set_auto_restart(auto_restart); - rval->set_smooth_recovery(smooth_recovery); - rval->set_flags(onstart_flags); - rval->set_socket_details(std::move(socket_path), socket_perms, socket_uid, socket_gid); - rval->set_chain_to(std::move(chain_to_name)); + rval->set_log_file(settings.logfile); + rval->set_auto_restart(settings.auto_restart); + rval->set_smooth_recovery(settings.smooth_recovery); + rval->set_flags(settings.onstart_flags); + rval->set_socket_details(std::move(settings.socket_path), settings.socket_perms, + settings.socket_uid, settings.socket_gid); + rval->set_chain_to(std::move(settings.chain_to_name)); *iter = rval; break; } diff --git a/src/mconfig-gen.cc b/src/mconfig-gen.cc index 5864bdd..4ab7075 100644 --- a/src/mconfig-gen.cc +++ b/src/mconfig-gen.cc @@ -59,13 +59,19 @@ int main(int argc, char **argv) } using namespace std; - cout << "// This file is auto-generated by mconfig-gen.cc." << endl; + cout << "// This file is auto-generated by mconfig-gen.cc.\n"; + cout << "#ifndef DINIT_MCONFIG_H\n"; + cout << "#define DINIT_MCONFIG_H 1\n"; + cout << "\n// Defines\n"; if (vars.find("USE_UTMPX") != vars.end()) { cout << "#define USE_UTMPX " << vars["USE_UTMPX"] << "\n"; } + cout << "\n// Constants\n"; cout << "constexpr static char SYSCONTROLSOCKET[] = " << stringify(vars["SYSCONTROLSOCKET"]) << ";\n"; cout << "constexpr static char SBINDIR[] = " << stringify(vars["SBINDIR"]) << ";\n"; + + cout << "\n#endif\n"; return 0; } -- 2.25.1