#include <limits>
#include <csignal>
#include <cstring>
+#include <utility>
#include <sys/types.h>
#include <sys/time.h>
#include <grp.h>
#include <pwd.h>
+#include "dinit-utmp.h"
+#include "dinit-util.h"
+
struct service_flags_t
{
// on-start flags:
}
}
+// A wrapper type for service parameters. It is parameterised by dependency type.
+template <class dep_type>
+class service_settings_wrapper
+{
+ template <typename A, typename B> using pair = std::pair<A,B>;
+ template <typename A> using list = std::list<A>;
+
+ public:
+
+ string command;
+ list<pair<unsigned,unsigned>> command_offsets;
+ string stop_command;
+ list<pair<unsigned,unsigned>> 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<dep_type> 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<service_rlimits> 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 <typename settings_wrapper,
+ typename load_service_t,
+ typename process_dep_dir_t>
+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<std::pair<unsigned,unsigned>> 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<std::pair<unsigned,unsigned>> 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<int>::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<int>::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;
throw service_not_found(string(name));
}
- string command;
- list<pair<unsigned,unsigned>> command_offsets;
- string stop_command;
- list<pair<unsigned,unsigned>> 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<prelim_dep> 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<service_rlimits> 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<prelim_dep> settings;
string line;
// getline can set failbit if it reaches end-of-file, we don't want an exception in that case. There's
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<std::pair<unsigned,unsigned>> 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<std::pair<unsigned,unsigned>> 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<int>::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<int>::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<prelim_dep> &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");
}
}
// 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;
}