From 896da2ce06ab40e0eaf08c655b9e0f4c17ffb3d3 Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 2 Oct 2024 14:50:07 +0200 Subject: [PATCH 1/2] Fix depends-ms.d reading --- src/includes/load-service.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/includes/load-service.h b/src/includes/load-service.h index 19348f8b..ff31c93a 100644 --- a/src/includes/load-service.h +++ b/src/includes/load-service.h @@ -1556,9 +1556,8 @@ void process_service_line(settings_wrapper &settings, const char *name, string & } case setting_id_t::DEPENDS_MS_D: { - string dependency_name = read_setting_value(input_pos, i, end); - settings.depends.emplace_back(load_service(dependency_name.c_str()), - dependency_type::MILESTONE); + string depends_ms_d = read_setting_value(input_pos, i, end); + process_dep_dir(settings.depends, depends_ms_d, dependency_type::MILESTONE); break; } case setting_id_t::AFTER: From 151478232ea35d06135bd6753b8749ce8b81c173 Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 2 Oct 2024 01:53:18 +0200 Subject: [PATCH 2/2] Add support for services with an argument Fixes https://github.com/davmac314/dinit/issues/385 --- doc/manpages/dinit-service.5.m4 | 32 +++++++++++++++-- doc/manpages/dinit.8.m4 | 2 +- doc/manpages/dinitctl.8.m4 | 3 +- src/dinitcheck.cc | 4 +-- src/igr-tests/igr-runner.cc | 24 ++++++++++++- src/igr-tests/svc-arg/checkarg.sh | 3 ++ src/igr-tests/svc-arg/sd/checkarg | 4 +++ src/igr-tests/svc-arg/sd/checkarg2 | 3 ++ src/igr-tests/svc-arg/sd/checkarg3 | 3 ++ src/igr-tests/svc-arg/sd/checkarg4 | 3 ++ src/igr-tests/svc-arg/sd/checkarg5 | 2 ++ src/includes/load-service.h | 57 ++++++++++++++++++++++-------- src/load-service.cc | 49 ++++++++++++++----------- src/tests/loadtests.cc | 22 ++++++------ 14 files changed, 156 insertions(+), 55 deletions(-) create mode 100755 src/igr-tests/svc-arg/checkarg.sh create mode 100644 src/igr-tests/svc-arg/sd/checkarg create mode 100644 src/igr-tests/svc-arg/sd/checkarg2 create mode 100644 src/igr-tests/svc-arg/sd/checkarg3 create mode 100644 src/igr-tests/svc-arg/sd/checkarg4 create mode 100644 src/igr-tests/svc-arg/sd/checkarg5 diff --git a/doc/manpages/dinit-service.5.m4 b/doc/manpages/dinit-service.5.m4 index 1586c5ab..32b51b1a 100644 --- a/doc/manpages/dinit-service.5.m4 +++ b/doc/manpages/dinit-service.5.m4 @@ -12,15 +12,22 @@ Dinit service description files .SH DESCRIPTION .\" The service description files for \fBDinit\fR each describe a service. The name -of the file corresponds to the name of the service it describes. +of the file corresponds to the name of the service it describes, minus its argument. .LP Service description files specify the various attributes of a service. A -service description file is named after the service it represents, and is -a plain-text file with simple key-value format. +service description file is named after the service it represents (without +its argument), and is a plain-text file with simple key-value format. The description files are located in a service description directory; See \fBdinit\fR(8) for more details of the default service description directories, and how and when service descriptions are loaded. .LP +The full name of the service includes its argument, such as \fIservice@argument\fR. +The argument is optional, so you can also invoke just \fIservice\fR. Each instance +of a service, i.e. with different arguments, is separate, including loading. This +means every time you invoke the service with a different argument, it is loaded +separately. Empty argument is not the same as missing argument, as this affects +variable substitution (see \fBVARIABLE SUBSTITUTION\fR). +.LP All services have a \fItype\fR and a set of \fIdependencies\fR. These are discussed in the following subsections. The type, dependencies, and other attributes are specified via property settings, the format of which are documented in the @@ -269,6 +276,8 @@ This service depends on the named service. Starting this service will start the named service; the command to start this service will not be executed until the named service has started. If the named service stops then this service will also be stopped. +The \fIservice-name\fR is subject to minimal variable substitution +(see \fBVARIABLE SUBSTITUTION\fR). .TP \fBdepends\-ms\fR: \fIservice-name\fR This service has a "milestone" dependency on the named service. Starting this @@ -277,6 +286,7 @@ named service has started, and will fail to start if the named service does not start. Once the named (dependent) service reaches the started state, however, the dependency may stop without affecting the dependent service. +The name is likewise subject to minimal variable substitution. .TP \fBwaits\-for\fR: \fIservice-name\fR When this service is started, wait for the named service to finish starting @@ -284,6 +294,7 @@ When this service is started, wait for the named service to finish starting Starting this service will automatically start the named service. If the named service fails to start, this service will start as usual (subject to other dependencies being met). +The name is likewise subject to minimal variable substitution. .TP \fBdepends\-on.d\fR: \fIdirectory-path\fR For each file name in \fIdirectory-path\fR which does not begin with a dot, @@ -296,6 +307,7 @@ is not considered fatal. .IP The directory path, if not absolute, is relative to the directory containing the service description file. +No variable substitution is done for path dependencies. .TP \fBdepends\-ms.d\fR: \fIdirectory-path\fR As for \fBdepends-on.d\fR, but with dependency type \fBdepends\-ms\fR. @@ -311,6 +323,8 @@ starting this service will not cause it to start (nor wait for it in that case). It does not by itself cause the named service to be loaded (if loaded later, the "after" relationship will be enforced from that point). .TP +The name is subject to minimal variable substitution. +.TP \fBbefore\fR: \fIservice-name\fR When starting the named service, if this service is also starting, wait for this service to finish starting before bringing the named service up. This is largely equivalent to specifying @@ -318,6 +332,8 @@ an \fBafter\fR relationship to this service from the named service. However, it does not by itself cause the named service to be loaded (if loaded later, the "before" relationship will be enforced from that point). .TP +The name is subject to minimal variable substitution. +.TP \fBchain\-to\fR = \fIservice-name\fR When this service terminates (i.e. starts successfully, and then stops of its own accord), the named service should be started. @@ -338,6 +354,8 @@ stopped due to a dependency stopping (for any reason), if it will restart abnormally or with an exit status indicating an error. However, if the \fBalways-chain\fR option is set the chain is started regardless of the reason and the status of this service termination. +.IP +The name is subject to minimal variable substitution. .TP \fBsocket\-listen\fR = \fIsocket-path\fR Pre-open a socket for the service and pass it to the service using the @@ -711,6 +729,10 @@ set and non\-empty), and `\fB${NAME+word}\fR' (substitute `\fBword\fR' if variab Unlike in shell expansion, the substituted \fBword\fR does not itself undergo expansion and cannot contain closing brace characters or whitespace, even if quoted. .LP +To substitute the service argument, the `\fB$1\fR' syntax may be used. The complete syntax +of the substitution is supported here. Services without an argument are treated as if the +variable was unset, which affects some of the curly brace syntax variants. +.LP Note that by default, command-line variable substitution occurs after splitting the line into separate arguments and so a single environment variable cannot be used to add multiple arguments to a command line. @@ -741,6 +763,10 @@ used for substitution, if they have been changed in the meantime. Using environment variable values in service commands and parameters can be used as means to provide easily-adjustable service configuration, but is not ideal for this purpose and alternatives should be considered. +.LP +In dependency fields, including \fIbefore\fR and similar, minimal version of variable +substitution may happen. Only the service argument may be substituted. No curly brace +syntax is supported. Escaping to avoid substitution is still supported. .\" .SS META-COMMANDS .\" diff --git a/doc/manpages/dinit.8.m4 b/doc/manpages/dinit.8.m4 index 69054aae..daf5543a 100644 --- a/doc/manpages/dinit.8.m4 +++ b/doc/manpages/dinit.8.m4 @@ -119,7 +119,7 @@ Specifies the name of a service that should be started (along with its dependencies). If none are specified, defaults to \fIboot\fR (which requires that a suitable service description for the \fIboot\fR service exists). Multiple services can be specified in which case they will each -be started. +be started. An argument to the service may be included here. .sp \fBNote:\fR on Linux, if \fBdinit\fR is running as PID 1 and with UID 0, it may ignore "naked" service names (without preceding \fB\-\-service\fR/\fB\-t\fR) provided on the command line. diff --git a/doc/manpages/dinitctl.8.m4 b/doc/manpages/dinitctl.8.m4 index e148de87..b8597173 100644 --- a/doc/manpages/dinitctl.8.m4 +++ b/doc/manpages/dinitctl.8.m4 @@ -162,7 +162,8 @@ success. Clear the log buffer for the service after displaying it. .TP \fIservice-name\fR -Specifies the name of the service to which the command applies. +Specifies the name of the service to which the command applies. It may have an argument that is passed +to the service. .\" .SH COMMAND DESCRIPTIONS .\" diff --git a/src/dinitcheck.cc b/src/dinitcheck.cc index 824d6c5e..0e59a016 100644 --- a/src/dinitcheck.cc +++ b/src/dinitcheck.cc @@ -671,7 +671,7 @@ service_record *load_service(service_set_t &services, const std::string &name, }; try { - process_service_line(settings, name.c_str(), line, input_pos, setting, op, i, end, + process_service_line(settings, name.c_str(), nullptr, line, input_pos, setting, op, i, end, load_service_n, process_dep_dir_n); } catch (service_description_exc &exc) { @@ -745,7 +745,7 @@ service_record *load_service(service_set_t &services, const std::string &name, return resolve_env_var(name, envmap); }; - settings.finalise(report_err, renvmap, report_err, resolve_var); + settings.finalise(report_err, renvmap, nullptr, report_err, resolve_var); if (!settings.working_dir.empty()) { service_wdir = settings.working_dir; diff --git a/src/igr-tests/igr-runner.cc b/src/igr-tests/igr-runner.cc index c87731b0..662a7757 100644 --- a/src/igr-tests/igr-runner.cc +++ b/src/igr-tests/igr-runner.cc @@ -40,6 +40,7 @@ void catlog_test(); void offline_enable_test(); void xdg_config_test(); void cycles_test(); +void svc_arg_test(); int main(int argc, char **argv) { @@ -55,7 +56,8 @@ int main(int argc, char **argv) { "pseudo-cycle", pseudo_cycle_test }, { "before-after", before_after_test}, { "before-after2", before_after2_test }, { "log-via-pipe", log_via_pipe_test }, { "catlog", catlog_test }, { "offline-enable", offline_enable_test }, - { "xdg-config", xdg_config_test }, { "cycles", cycles_test } }; + { "xdg-config", xdg_config_test }, { "cycles", cycles_test }, + { "svc-arg", svc_arg_test } }; constexpr int num_tests = sizeof(tests) / sizeof(tests[0]); dinit_bindir = "../.."; @@ -974,3 +976,23 @@ void cycles_test() igr_assert_eq(read_file_contents(igr_input_basedir + "/cycles/expected-after_self"), dinitctl_p.get_stderr()); } + +void svc_arg_test() +{ + igr_test_setup setup("svc-arg"); + std::string output_file = setup.prep_output_file("svc-arg-record"); + std::string socket_path = setup.prep_socket_path(); + + igr_env_var_setup env_output("OUTPUT", output_file.c_str()); + + dinit_proc dinit_p; + dinit_p.start("svc-arg", {"-u", "-d", "sd", "-p", socket_path, "-q", "checkarg@foo"}); + dinit_p.wait_for_term({1,0} /* max 1 second */); + + check_file_contents(output_file, std::string() + + "test-$1\n" + + "test-hello\n" + + "hello\n" + + "foo\n" + + "foo\n"); +} diff --git a/src/igr-tests/svc-arg/checkarg.sh b/src/igr-tests/svc-arg/checkarg.sh new file mode 100755 index 00000000..f6bff94b --- /dev/null +++ b/src/igr-tests/svc-arg/checkarg.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "$1" >> "$OUTPUT" diff --git a/src/igr-tests/svc-arg/sd/checkarg b/src/igr-tests/svc-arg/sd/checkarg new file mode 100644 index 00000000..d781ef9c --- /dev/null +++ b/src/igr-tests/svc-arg/sd/checkarg @@ -0,0 +1,4 @@ +type = process +waits-for = checkarg2@$1 +command = ../checkarg.sh $1 +restart = false diff --git a/src/igr-tests/svc-arg/sd/checkarg2 b/src/igr-tests/svc-arg/sd/checkarg2 new file mode 100644 index 00000000..e8b58df5 --- /dev/null +++ b/src/igr-tests/svc-arg/sd/checkarg2 @@ -0,0 +1,3 @@ +type = scripted +waits-for = checkarg3@hello +command = ../checkarg.sh $1 diff --git a/src/igr-tests/svc-arg/sd/checkarg3 b/src/igr-tests/svc-arg/sd/checkarg3 new file mode 100644 index 00000000..0521f6fb --- /dev/null +++ b/src/igr-tests/svc-arg/sd/checkarg3 @@ -0,0 +1,3 @@ +type = scripted +waits-for = checkarg4@test-$1 +command = ../checkarg.sh $1 diff --git a/src/igr-tests/svc-arg/sd/checkarg4 b/src/igr-tests/svc-arg/sd/checkarg4 new file mode 100644 index 00000000..7ef74878 --- /dev/null +++ b/src/igr-tests/svc-arg/sd/checkarg4 @@ -0,0 +1,3 @@ +type = scripted +waits-for = checkarg5@test-$$1 +command = ../checkarg.sh $1 diff --git a/src/igr-tests/svc-arg/sd/checkarg5 b/src/igr-tests/svc-arg/sd/checkarg5 new file mode 100644 index 00000000..26ee0c21 --- /dev/null +++ b/src/igr-tests/svc-arg/sd/checkarg5 @@ -0,0 +1,2 @@ +type = scripted +command = ../checkarg.sh $1 diff --git a/src/includes/load-service.h b/src/includes/load-service.h index ff31c93a..832f61f1 100644 --- a/src/includes/load-service.h +++ b/src/includes/load-service.h @@ -547,6 +547,27 @@ inline string read_setting_value(file_pos_ref input_pos, string_iterator &i, str return rval; } +// Reads a dependency name while performing minimal argument expansion in it. +inline string read_dependency_value(file_pos_ref input_pos, string_iterator &i, string_iterator end, + const char *argval) +{ + string rval; + if (!argval) argval = ""; + read_setting_value(rval, setting_op_t::ASSIGN, input_pos, i, end, nullptr); + for (auto v = rval.find('$'); v != rval.npos && v != (rval.size() - 1); v = rval.find('$', v + 1)) { + switch (rval[v + 1]) { + case '$': + rval.erase(v, 1); + break; + case '1': + rval.replace(v, 2, argval); + v += strlen(argval) - 1; + continue; + } + } + return rval; +} + inline void fill_environment_userinfo(uid_t uid, const std::string &service_name, environment &env) { if (uid == (uid_t)-1) { @@ -1031,7 +1052,7 @@ inline const char *resolve_env_var(const string &name, const environment::env_ma template static void value_var_subst(const char *setting_name, std::string &line, std::list> &offsets, T &var_resolve, - environment::env_map const &envmap) + environment::env_map const &envmap, const char *argval = nullptr) { auto dindx = line.find('$'); if (dindx == string::npos) { @@ -1074,11 +1095,16 @@ static void value_var_subst(const char *setting_name, std::string &line, bool brace = line[spos] == '{'; if (brace) ++spos; auto j = std::next(line.begin(), spos); + // may be a service argument + bool is_arg = j != token_end && *j == '1'; // read environment variable name - string name = read_config_name(j, token_end, true); - if (name.empty()) { - throw service_description_exc(setting_name, "invalid/missing variable name after '$'"); - } + string name; + if (!is_arg) { + name = read_config_name(j, token_end, true); + if (name.empty()) { + throw service_description_exc(setting_name, "invalid/missing variable name after '$'"); + } + } else ++j; char altmode = '\0'; bool colon = false; auto altbeg = j, altend = j; @@ -1106,7 +1132,7 @@ static void value_var_subst(const char *setting_name, std::string &line, } size_t line_len_before = r_line.size(); string_view resolved_vw; - auto *resolved = var_resolve(name, envmap); + auto *resolved = is_arg ? argval : var_resolve(name, envmap); if (resolved) { resolved_vw = resolved; } @@ -1300,7 +1326,7 @@ class service_settings_wrapper // var_subst - functor to resolve environment variable values template ::value> - void finalise(T &report_error, environment::env_map const &envmap, U &report_lint = dummy_lint, V &var_subst = resolve_env_var) + void finalise(T &report_error, environment::env_map const &envmap, const char *argval, U &report_lint = dummy_lint, V &var_subst = resolve_env_var) { if (service_type == service_type_t::PROCESS || service_type == service_type_t::BGPROCESS || service_type == service_type_t::SCRIPTED) { @@ -1384,7 +1410,7 @@ class service_settings_wrapper try { offsets.front().first = 0; offsets.front().second = setting_value.size(); - value_var_subst(setting_name, setting_value, offsets, var_subst, envmap); + value_var_subst(setting_name, setting_value, offsets, var_subst, envmap, argval); } catch (service_description_exc &exc) { if (propagate_sde) throw; @@ -1460,7 +1486,7 @@ class service_settings_wrapper template -void process_service_line(settings_wrapper &settings, const char *name, string &line, +void process_service_line(settings_wrapper &settings, const char *name, const char *arg, string &line, file_pos_ref input_pos, string &setting, setting_op_t setting_op, string::iterator &i, string::iterator &end, load_service_t load_service, process_dep_dir_t process_dep_dir) @@ -1524,20 +1550,21 @@ void process_service_line(settings_wrapper &settings, const char *name, string & break; case setting_id_t::DEPENDS_ON: { - string dependency_name = read_setting_value(input_pos, i, end); - settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::REGULAR); + string dependency_name = read_dependency_value(input_pos, i, end, arg); + settings.depends.emplace_back(load_service(dependency_name.c_str()), + dependency_type::REGULAR); break; } case setting_id_t::DEPENDS_MS: { - string dependency_name = read_setting_value(input_pos, i, end); + string dependency_name = read_dependency_value(input_pos, i, end, arg); settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::MILESTONE); break; } case setting_id_t::WAITS_FOR: { - string dependency_name = read_setting_value(input_pos, i, end); + string dependency_name = read_dependency_value(input_pos, i, end, arg); settings.depends.emplace_back(load_service(dependency_name.c_str()), dependency_type::WAITS_FOR); break; @@ -1562,13 +1589,13 @@ void process_service_line(settings_wrapper &settings, const char *name, string & } case setting_id_t::AFTER: { - string after_name = read_setting_value(input_pos, i, end); + string after_name = read_dependency_value(input_pos, i, end, arg); settings.after_svcs.emplace_back(std::move(after_name)); break; } case setting_id_t::BEFORE: { - string before_name = read_setting_value(input_pos, i, end); + string before_name = read_dependency_value(input_pos, i, end, arg); settings.before_svcs.emplace_back(std::move(before_name)); break; } diff --git a/src/load-service.cc b/src/load-service.cc index b1f48f8d..70eac0f1 100644 --- a/src/load-service.cc +++ b/src/load-service.cc @@ -31,11 +31,11 @@ using string_iterator = std::string::iterator; // throws: std::bad_alloc, std::length_error, service_description_exc static void do_env_subst(const char *setting_name, ha_string &line, std::list> &offsets, - environment::env_map const &envmap) + environment::env_map const &envmap, const char *arg) { using namespace dinit_load; std::string line_s = std::string(line.c_str(), line.length()); - value_var_subst(setting_name, line_s, offsets, resolve_env_var, envmap); + value_var_subst(setting_name, line_s, offsets, resolve_env_var, envmap, arg); line = line_s; } @@ -311,7 +311,7 @@ static bool check_settings_for_reload(service_record *service, return create_new_record; } -service_record * dirload_service_set::load_reload_service(const char *name, service_record *reload_svc, +service_record * dirload_service_set::load_reload_service(const char *fullname, service_record *reload_svc, const service_record *avoid_circular) { // Load a new service, or reload an already-loaded service. @@ -366,9 +366,16 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv using namespace dinit_load; + const auto *argp = strchr(fullname, '@'); + if (!argp) argp = fullname + strlen(fullname); + + auto name = string(fullname, argp); + + auto *argval = *argp ? argp + 1 : nullptr; + if (reload_svc == nullptr) { // First try and find an existing record... - service_record *existing = find_service(string(name), true); + service_record *existing = find_service(string(fullname), true); if (existing != nullptr) { if (existing == avoid_circular || existing->check_is_loading()) { throw service_cyclic_dependency(name); @@ -412,7 +419,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv if (!service_file) { if (fail_load_errno == 0) { - throw service_not_found(string(name)); + throw service_not_found(name); } else { throw service_load_error(name, std::move(fail_load_path), fail_load_errno); @@ -476,7 +483,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv // Add a placeholder record now to prevent infinite recursion in case of cyclic dependency. // We replace this with the real service later (or remove it if we find a configuration error). try { - dummy = new service_record(this, string(name), service_record::LOADING_TAG); + dummy = new service_record(this, string(fullname), service_record::LOADING_TAG); add_service(dummy); } catch (...) { @@ -496,7 +503,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv 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, reload_svc); + process_dep_dir(*this, name.c_str(), service_filename, deplist, waitsford, dep_type, reload_svc); }; auto load_service_n = [&](const string &dep_name) -> service_record * { @@ -514,8 +521,8 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv } }; - process_service_line(settings, name, line, fpr, setting, op, i, end, load_service_n, - process_dep_dir_n); + process_service_line(settings, name.c_str(), argval, line, fpr, setting, + op, i, end, load_service_n, process_dep_dir_n); }); auto report_err = [&](const char *msg){ @@ -558,7 +565,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv srv_envmap = srv_env.build(main_env); - settings.finalise(report_err, srv_envmap); + settings.finalise(report_err, srv_envmap, argval); auto service_type = settings.service_type; if (reload_svc != nullptr) { @@ -702,15 +709,15 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv } if (service_type == service_type_t::PROCESS) { - do_env_subst("command", settings.command, settings.command_offsets, srv_envmap); - do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap); + do_env_subst("command", settings.command, settings.command_offsets, srv_envmap, argval); + do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap, argval); std::vector stop_arg_parts = separate_args(settings.stop_command, settings.stop_command_offsets); process_service *rvalps; if (create_new_record) { if (reload_svc != nullptr) { check_cycle(settings.depends, reload_svc); } - rvalps = new process_service(this, string(name), std::move(settings.command), + rvalps = new process_service(this, string(fullname), std::move(settings.command), settings.command_offsets, settings.depends); settings.depends.clear(); } @@ -745,15 +752,15 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv #endif } else if (service_type == service_type_t::BGPROCESS) { - do_env_subst("command", settings.command, settings.command_offsets, srv_envmap); - do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap); + do_env_subst("command", settings.command, settings.command_offsets, srv_envmap, argval); + do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap, argval); std::vector stop_arg_parts = separate_args(settings.stop_command, settings.stop_command_offsets); bgproc_service *rvalps; if (create_new_record) { if (reload_svc != nullptr) { check_cycle(settings.depends, reload_svc); } - rvalps = new bgproc_service(this, string(name), std::move(settings.command), + rvalps = new bgproc_service(this, string(fullname), std::move(settings.command), settings.command_offsets, settings.depends); settings.depends.clear(); } @@ -784,15 +791,15 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv settings.onstart_flags.runs_on_console = false; } else if (service_type == service_type_t::SCRIPTED) { - do_env_subst("command", settings.command, settings.command_offsets, srv_envmap); - do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap); + do_env_subst("command", settings.command, settings.command_offsets, srv_envmap, argval); + do_env_subst("stop-command", settings.stop_command, settings.stop_command_offsets, srv_envmap, argval); std::vector stop_arg_parts = separate_args(settings.stop_command, settings.stop_command_offsets); scripted_service *rvalps; if (create_new_record) { if (reload_svc != nullptr) { check_cycle(settings.depends, reload_svc); } - rvalps = new scripted_service(this, string(name), std::move(settings.command), + rvalps = new scripted_service(this, string(fullname), std::move(settings.command), settings.command_offsets, settings.depends); settings.depends.clear(); } @@ -824,11 +831,11 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv check_cycle(settings.depends, reload_svc); } if (service_type == service_type_t::INTERNAL) { - rval = new service_record(this, string(name), service_type, settings.depends); + rval = new service_record(this, string(fullname), service_type, settings.depends); } else { /* TRIGGERED */ - rval = new triggered_service(this, string(name), service_type, settings.depends); + rval = new triggered_service(this, string(fullname), service_type, settings.depends); } settings.depends.clear(); } diff --git a/src/tests/loadtests.cc b/src/tests/loadtests.cc index 44e0f073..9cf8a724 100644 --- a/src/tests/loadtests.cc +++ b/src/tests/loadtests.cc @@ -237,8 +237,8 @@ void test_settings() }; try { - process_service_line(settings, "test-service", line, input_pos, setting, op, i, end, - load_service_n, process_dep_dir_n); + process_service_line(settings, "test-service", nullptr, line, input_pos, setting, + op, i, end, load_service_n, process_dep_dir_n); } catch (service_description_exc &exc) { //report_service_description_exc(exc); @@ -287,7 +287,7 @@ void test_path_env_subst() ss << "type = process\n" "command = /something/test\n" - "logfile = /some/$username/dir\n"; + "logfile = /some/$1/$username/${1}/dir\n"; file_input_stack input_stack; input_stack.add_source(ss.str(), "dummy"); @@ -307,8 +307,8 @@ void test_path_env_subst() }; try { - process_service_line(settings, "test-service", line, input_pos, setting, op, i, - end, load_service_n, process_dep_dir_n); + process_service_line(settings, "test-service", nullptr, line, input_pos, setting, + op, i, end, load_service_n, process_dep_dir_n); } catch (service_description_exc &exc) { //report_service_description_exc(exc); @@ -327,11 +327,11 @@ void test_path_env_subst() return nullptr; }; - settings.finalise(report_error, tenvmap, report_error /* lint */, resolve_var); + settings.finalise(report_error, tenvmap, "foo", report_error /* lint */, resolve_var); assert(settings.service_type == service_type_t::PROCESS); assert(settings.command == "/something/test"); - assert(settings.logfile == "/some/testsuccess/dir"); + assert(settings.logfile == "/some/foo/testsuccess/foo/dir"); } void test_newline() @@ -381,8 +381,8 @@ void test_newline_err() return dep_name; }; - process_service_line(settings, "test-service", line, input_pos, setting, op, i, end, - load_service_n, process_dep_dir_n); + process_service_line(settings, "test-service", nullptr, line, input_pos, setting, + op, i, end, load_service_n, process_dep_dir_n); }); }; @@ -448,8 +448,8 @@ void test_newline2() }; try { - process_service_line(settings, "test-service", line, input_pos, setting, op, i, end, - load_service_n, process_dep_dir_n); + process_service_line(settings, "test-service", nullptr, line, input_pos, + setting, op, i, end, load_service_n, process_dep_dir_n); } catch (service_description_exc &exc) { //report_service_description_exc(exc);