Merge pull request #4835 from poettering/unit-name-printf
Various specifier resolution fixes.
This commit is contained in:
commit
1ac7a93574
2
TODO
2
TODO
|
@ -116,8 +116,6 @@ Features:
|
||||||
* journald: sigbus API via a signal-handler safe function that people may call
|
* journald: sigbus API via a signal-handler safe function that people may call
|
||||||
from the SIGBUS handler
|
from the SIGBUS handler
|
||||||
|
|
||||||
* move specifier expansion from service_spawn() into load-fragment.c
|
|
||||||
|
|
||||||
* optionally, also require WATCHDOG=1 notifications during service start-up and shutdown
|
* optionally, also require WATCHDOG=1 notifications during service start-up and shutdown
|
||||||
|
|
||||||
* resolved: when routing queries, make sure only look for the *longest* suffix...
|
* resolved: when routing queries, make sure only look for the *longest* suffix...
|
||||||
|
|
|
@ -1246,21 +1246,6 @@
|
||||||
<entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>.</entry>
|
<entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%c</literal></entry>
|
|
||||||
<entry>Control group path of the unit</entry>
|
|
||||||
<entry>This path does not include the <filename>/sys/fs/cgroup/systemd/</filename> prefix.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><literal>%r</literal></entry>
|
|
||||||
<entry>Control group path of the slice the unit is placed in</entry>
|
|
||||||
<entry>This usually maps to the parent control group path of <literal>%c</literal>.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><literal>%R</literal></entry>
|
|
||||||
<entry>Root control group path below which slices and units are placed</entry>
|
|
||||||
<entry>For system instances, this resolves to <filename>/</filename>, except in containers, where this maps to the container's root control group path.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><literal>%t</literal></entry>
|
<entry><literal>%t</literal></entry>
|
||||||
<entry>Runtime directory</entry>
|
<entry>Runtime directory</entry>
|
||||||
<entry>This is either <filename>/run</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
|
<entry>This is either <filename>/run</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
|
||||||
|
@ -1314,13 +1299,6 @@
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<para>Please note that specifiers <literal>%U</literal>,
|
|
||||||
<literal>%h</literal>, <literal>%s</literal> are mostly useless
|
|
||||||
when systemd is running in system mode. PID 1 cannot query the
|
|
||||||
user account database for information, so the specifiers only work
|
|
||||||
as shortcuts for things which are already specified in a different
|
|
||||||
way in the unit file. They are fully functional when systemd is
|
|
||||||
running in <option>--user</option> mode.</para>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|
|
@ -191,13 +191,13 @@ Unit.IgnoreOnIsolate, config_parse_bool, 0,
|
||||||
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
|
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||||
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
|
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
|
||||||
Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
|
Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
|
||||||
Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
|
Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
|
||||||
Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
||||||
m4_dnl The following is a legacy alias name for compatibility
|
m4_dnl The following is a legacy alias name for compatibility
|
||||||
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
||||||
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
||||||
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
||||||
Unit.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
|
Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
|
||||||
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
|
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
|
||||||
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
|
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
|
||||||
Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
|
Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
|
||||||
|
@ -254,7 +254,7 @@ m4_dnl The following three only exist for compatibility, they moved into Unit, s
|
||||||
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
||||||
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
||||||
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
||||||
Service.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
|
Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
|
||||||
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action)
|
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action)
|
||||||
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
|
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
|
||||||
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
|
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
|
||||||
|
@ -272,8 +272,8 @@ Service.FileDescriptorStoreMax, config_parse_unsigned, 0,
|
||||||
Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
|
Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
|
||||||
Service.Sockets, config_parse_service_sockets, 0, 0
|
Service.Sockets, config_parse_service_sockets, 0, 0
|
||||||
Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
|
Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||||
Service.USBFunctionDescriptors, config_parse_path, 0, offsetof(Service, usb_function_descriptors)
|
Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors)
|
||||||
Service.USBFunctionStrings, config_parse_path, 0, offsetof(Service, usb_function_strings)
|
Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
|
||||||
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
||||||
CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
||||||
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
|
||||||
|
@ -332,9 +332,9 @@ Socket.Service, config_parse_socket_service, 0,
|
||||||
Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
|
Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
|
||||||
Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
|
Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
|
||||||
m4_ifdef(`HAVE_SMACK',
|
m4_ifdef(`HAVE_SMACK',
|
||||||
`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
|
`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack)
|
||||||
Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
|
Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in)
|
||||||
Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)',
|
Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)',
|
||||||
`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||||
Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
|
||||||
Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
|
Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
|
||||||
|
@ -354,9 +354,9 @@ BusName.AllowWorld, config_parse_bus_policy_world, 0,
|
||||||
BusName.SELinuxContext, config_parse_exec_selinux_context, 0, 0
|
BusName.SELinuxContext, config_parse_exec_selinux_context, 0, 0
|
||||||
BusName.AcceptFileDescriptors, config_parse_bool, 0, offsetof(BusName, accept_fd)
|
BusName.AcceptFileDescriptors, config_parse_bool, 0, offsetof(BusName, accept_fd)
|
||||||
m4_dnl
|
m4_dnl
|
||||||
Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what)
|
Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
|
||||||
Mount.Where, config_parse_path, 0, offsetof(Mount, where)
|
Mount.Where, config_parse_path, 0, offsetof(Mount, where)
|
||||||
Mount.Options, config_parse_string, 0, offsetof(Mount, parameters_fragment.options)
|
Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
|
||||||
Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
|
Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
|
||||||
Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec)
|
Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec)
|
||||||
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
|
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
|
||||||
|
@ -373,7 +373,7 @@ Automount.TimeoutIdleSec, config_parse_sec, 0,
|
||||||
m4_dnl
|
m4_dnl
|
||||||
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
|
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
|
||||||
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
|
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
|
||||||
Swap.Options, config_parse_string, 0, offsetof(Swap, parameters_fragment.options)
|
Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
|
||||||
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
|
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
|
||||||
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
|
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
|
||||||
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
|
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
|
||||||
|
|
|
@ -579,6 +579,7 @@ int config_parse_exec(
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
ExecCommand **e = data;
|
ExecCommand **e = data;
|
||||||
|
Unit *u = userdata;
|
||||||
const char *p;
|
const char *p;
|
||||||
bool semicolon;
|
bool semicolon;
|
||||||
int r;
|
int r;
|
||||||
|
@ -604,7 +605,7 @@ int config_parse_exec(
|
||||||
_cleanup_free_ ExecCommand *nce = NULL;
|
_cleanup_free_ ExecCommand *nce = NULL;
|
||||||
_cleanup_strv_free_ char **n = NULL;
|
_cleanup_strv_free_ char **n = NULL;
|
||||||
size_t nlen = 0, nbufsize = 0;
|
size_t nlen = 0, nbufsize = 0;
|
||||||
char *f;
|
const char *f;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
semicolon = false;
|
semicolon = false;
|
||||||
|
@ -631,47 +632,47 @@ int config_parse_exec(
|
||||||
f++;
|
f++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isempty(f)) {
|
r = unit_full_printf(u, f, &path);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isempty(path)) {
|
||||||
/* First word is either "-" or "@" with no command. */
|
/* First word is either "-" or "@" with no command. */
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!string_is_safe(f)) {
|
if (!string_is_safe(path)) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!path_is_absolute(f)) {
|
if (!path_is_absolute(path)) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (endswith(f, "/")) {
|
if (endswith(path, "/")) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f == firstword) {
|
|
||||||
path = firstword;
|
|
||||||
firstword = NULL;
|
|
||||||
} else {
|
|
||||||
path = strdup(f);
|
|
||||||
if (!path)
|
|
||||||
return log_oom();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!separate_argv0) {
|
if (!separate_argv0) {
|
||||||
|
char *w = NULL;
|
||||||
|
|
||||||
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
f = strdup(path);
|
|
||||||
if (!f)
|
w = strdup(path);
|
||||||
|
if (!w)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
n[nlen++] = f;
|
n[nlen++] = w;
|
||||||
n[nlen] = NULL;
|
n[nlen] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_kill_slashes(path);
|
path_kill_slashes(path);
|
||||||
|
|
||||||
while (!isempty(p)) {
|
while (!isempty(p)) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||||
|
|
||||||
/* Check explicitly for an unquoted semicolon as
|
/* Check explicitly for an unquoted semicolon as
|
||||||
* command separator token. */
|
* command separator token. */
|
||||||
|
@ -682,18 +683,21 @@ int config_parse_exec(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for \; explicitly, to not confuse it with \\;
|
/* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc.
|
||||||
* or "\;" or "\\;" etc. extract_first_word would
|
* extract_first_word() would return the same for all of those. */
|
||||||
* return the same for all of those. */
|
|
||||||
if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
|
if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
|
||||||
|
char *w;
|
||||||
|
|
||||||
p += 2;
|
p += 2;
|
||||||
p += strspn(p, WHITESPACE);
|
p += strspn(p, WHITESPACE);
|
||||||
|
|
||||||
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
f = strdup(";");
|
|
||||||
if (!f)
|
w = strdup(";");
|
||||||
|
if (!w)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
n[nlen++] = f;
|
n[nlen++] = w;
|
||||||
n[nlen] = NULL;
|
n[nlen] = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -701,14 +705,20 @@ int config_parse_exec(
|
||||||
r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
|
r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
break;
|
||||||
else if (r < 0)
|
if (r < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
r = unit_full_printf(u, word, &resolved);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to resolve unit specifiers on %s, ignoring: %m", word);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
n[nlen++] = word;
|
n[nlen++] = resolved;
|
||||||
n[nlen] = NULL;
|
n[nlen] = NULL;
|
||||||
word = NULL;
|
resolved = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!n || !n[0]) {
|
if (!n || !n[0]) {
|
||||||
|
@ -1326,7 +1336,7 @@ int config_parse_exec_selinux_context(
|
||||||
} else
|
} else
|
||||||
ignore = false;
|
ignore = false;
|
||||||
|
|
||||||
r = unit_name_printf(u, rvalue, &k);
|
r = unit_full_printf(u, rvalue, &k);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1374,7 +1384,7 @@ int config_parse_exec_apparmor_profile(
|
||||||
} else
|
} else
|
||||||
ignore = false;
|
ignore = false;
|
||||||
|
|
||||||
r = unit_name_printf(u, rvalue, &k);
|
r = unit_full_printf(u, rvalue, &k);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1422,7 +1432,7 @@ int config_parse_exec_smack_process_label(
|
||||||
} else
|
} else
|
||||||
ignore = false;
|
ignore = false;
|
||||||
|
|
||||||
r = unit_name_printf(u, rvalue, &k);
|
r = unit_full_printf(u, rvalue, &k);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1689,7 +1699,7 @@ int config_parse_fdname(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = unit_name_printf(UNIT(s), rvalue, &p);
|
r = unit_full_printf(UNIT(s), rvalue, &p);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2555,7 +2565,7 @@ int config_parse_unit_requires_mounts_for(
|
||||||
assert(data);
|
assert(data);
|
||||||
|
|
||||||
for (p = rvalue;; ) {
|
for (p = rvalue;; ) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||||
|
|
||||||
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
|
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
|
@ -2573,9 +2583,15 @@ int config_parse_unit_requires_mounts_for(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = unit_require_mounts_for(u, word);
|
r = unit_full_printf(u, word, &resolved);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", word);
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit name \"%s\", ignoring: %m", word);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = unit_require_mounts_for(u, resolved);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3710,7 +3726,7 @@ int config_parse_runtime_directory(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = unit_name_printf(u, word, &k);
|
r = unit_full_printf(u, word, &k);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
"Failed to resolve specifiers in \"%s\", ignoring: %m", word);
|
"Failed to resolve specifiers in \"%s\", ignoring: %m", word);
|
||||||
|
@ -3812,8 +3828,8 @@ int config_parse_namespace_path_strv(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
|
Unit *u = userdata;
|
||||||
char*** sv = data;
|
char*** sv = data;
|
||||||
const char *prev;
|
|
||||||
const char *cur;
|
const char *cur;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -3828,10 +3844,10 @@ int config_parse_namespace_path_strv(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = cur = rvalue;
|
cur = rvalue;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
|
||||||
int offset;
|
bool ignore_enoent;
|
||||||
|
|
||||||
r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
|
r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
|
@ -3839,31 +3855,37 @@ int config_parse_namespace_path_strv(
|
||||||
if (r == -ENOMEM)
|
if (r == -ENOMEM)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage, ignoring: %s", prev);
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utf8_is_valid(word)) {
|
if (!utf8_is_valid(word)) {
|
||||||
log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
|
log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
|
||||||
prev = cur;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = word[0] == '-';
|
ignore_enoent = word[0] == '-';
|
||||||
if (!path_is_absolute(word + offset)) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", word);
|
r = unit_full_printf(u, word + ignore_enoent, &resolved);
|
||||||
prev = cur;
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s: %m", word);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
path_kill_slashes(word + offset);
|
if (!path_is_absolute(resolved)) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
r = strv_push(sv, word);
|
path_kill_slashes(resolved);
|
||||||
|
|
||||||
|
joined = strjoin(ignore_enoent ? "-" : "", resolved);
|
||||||
|
|
||||||
|
r = strv_push(sv, joined);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
prev = cur;
|
joined = NULL;
|
||||||
word = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -49,7 +49,6 @@
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "unit-name.h"
|
#include "unit-name.h"
|
||||||
#include "unit-printf.h"
|
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -1205,7 +1204,7 @@ static int service_spawn(
|
||||||
ExecFlags flags,
|
ExecFlags flags,
|
||||||
pid_t *_pid) {
|
pid_t *_pid) {
|
||||||
|
|
||||||
_cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL;
|
_cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL;
|
||||||
_cleanup_free_ int *fds = NULL;
|
_cleanup_free_ int *fds = NULL;
|
||||||
unsigned n_fds = 0, n_env = 0;
|
unsigned n_fds = 0, n_env = 0;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
@ -1263,10 +1262,6 @@ static int service_spawn(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
our_env = new0(char*, 9);
|
our_env = new0(char*, 9);
|
||||||
if (!our_env)
|
if (!our_env)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1349,7 +1344,7 @@ static int service_spawn(
|
||||||
} else
|
} else
|
||||||
path = UNIT(s)->cgroup_path;
|
path = UNIT(s)->cgroup_path;
|
||||||
|
|
||||||
exec_params.argv = argv;
|
exec_params.argv = c->argv;
|
||||||
exec_params.environment = final_env;
|
exec_params.environment = final_env;
|
||||||
exec_params.fds = fds;
|
exec_params.fds = fds;
|
||||||
exec_params.fd_names = fd_names;
|
exec_params.fd_names = fd_names;
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "unit-name.h"
|
#include "unit-name.h"
|
||||||
#include "unit-printf.h"
|
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
|
@ -1740,7 +1739,6 @@ static int socket_coldplug(Unit *u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
|
static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
|
||||||
_cleanup_free_ char **argv = NULL;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
ExecParameters exec_params = {
|
ExecParameters exec_params = {
|
||||||
|
@ -1772,11 +1770,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
|
exec_params.argv = c->argv;
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
exec_params.argv = argv;
|
|
||||||
exec_params.environment = UNIT(s)->manager->environment;
|
exec_params.environment = UNIT(s)->manager->environment;
|
||||||
exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
|
exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
|
||||||
exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
|
exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
|
||||||
|
|
|
@ -78,12 +78,18 @@ static int specifier_filename(char specifier, void *data, void *userdata, char *
|
||||||
return unit_name_to_path(u->id, ret);
|
return unit_name_to_path(u->id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bad_specifier(Unit *u, char specifier) {
|
||||||
|
log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
|
||||||
|
}
|
||||||
|
|
||||||
static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
|
static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
|
||||||
Unit *u = userdata;
|
Unit *u = userdata;
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
if (u->cgroup_path)
|
if (u->cgroup_path)
|
||||||
n = strdup(u->cgroup_path);
|
n = strdup(u->cgroup_path);
|
||||||
else
|
else
|
||||||
|
@ -101,6 +107,8 @@ static int specifier_cgroup_root(char specifier, void *data, void *userdata, cha
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
n = strdup(u->manager->cgroup_root);
|
n = strdup(u->manager->cgroup_root);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -115,6 +123,8 @@ static int specifier_cgroup_slice(char specifier, void *data, void *userdata, ch
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
if (UNIT_ISSET(u->slice)) {
|
if (UNIT_ISSET(u->slice)) {
|
||||||
Unit *slice;
|
Unit *slice;
|
||||||
|
|
||||||
|
@ -194,13 +204,20 @@ static int specifier_user_shell(char specifier, void *data, void *userdata, char
|
||||||
int unit_name_printf(Unit *u, const char* format, char **ret) {
|
int unit_name_printf(Unit *u, const char* format, char **ret) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will use the passed string as format string and
|
* This will use the passed string as format string and replace the following specifiers (which should all be
|
||||||
* replace the following specifiers:
|
* safe for inclusion in unit names):
|
||||||
*
|
*
|
||||||
* %n: the full id of the unit (foo@bar.waldo)
|
* %n: the full id of the unit (foo@bar.waldo)
|
||||||
* %N: the id of the unit without the suffix (foo@bar)
|
* %N: the id of the unit without the suffix (foo@bar)
|
||||||
* %p: the prefix (foo)
|
* %p: the prefix (foo)
|
||||||
* %i: the instance (bar)
|
* %i: the instance (bar)
|
||||||
|
*
|
||||||
|
* %U: the UID of the running user
|
||||||
|
* %u: the username of the running user
|
||||||
|
*
|
||||||
|
* %m: the machine ID of the running system
|
||||||
|
* %H: the host name of the running system
|
||||||
|
* %b: the boot ID of the running system
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Specifier table[] = {
|
const Specifier table[] = {
|
||||||
|
@ -208,7 +225,14 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
|
||||||
{ 'N', specifier_prefix_and_instance, NULL },
|
{ 'N', specifier_prefix_and_instance, NULL },
|
||||||
{ 'p', specifier_prefix, NULL },
|
{ 'p', specifier_prefix, NULL },
|
||||||
{ 'i', specifier_string, u->instance },
|
{ 'i', specifier_string, u->instance },
|
||||||
{ 0, NULL, NULL }
|
|
||||||
|
{ 'U', specifier_user_id, NULL },
|
||||||
|
{ 'u', specifier_user_name, NULL },
|
||||||
|
|
||||||
|
{ 'm', specifier_machine_id, NULL },
|
||||||
|
{ 'H', specifier_host_name, NULL },
|
||||||
|
{ 'b', specifier_boot_id, NULL },
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
@ -220,22 +244,23 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
|
||||||
|
|
||||||
int unit_full_printf(Unit *u, const char *format, char **ret) {
|
int unit_full_printf(Unit *u, const char *format, char **ret) {
|
||||||
|
|
||||||
/* This is similar to unit_name_printf() but also supports
|
/* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
|
||||||
* unescaping. Also, adds a couple of additional codes:
|
* (which are likely not suitable for unescaped inclusion in unit names):
|
||||||
*
|
*
|
||||||
* %f the instance if set, otherwise the id
|
* %f: the unescaped instance if set, otherwise the id unescaped as path
|
||||||
* %c cgroup path of unit
|
* %c: cgroup path of unit (deprecated)
|
||||||
* %r where units in this slice are placed in the cgroup tree
|
* %r: where units in this slice are placed in the cgroup tree (deprecated)
|
||||||
* %R the root of this systemd's instance tree
|
* %R: the root of this systemd's instance tree (deprecated)
|
||||||
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
|
* %t: the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
|
||||||
* %U the UID of the running user
|
*
|
||||||
* %u the username of the running user
|
* %h: the homedir of the running user
|
||||||
* %h the homedir of the running user
|
* %s: the shell of the running user
|
||||||
* %s the shell of the running user
|
*
|
||||||
* %m the machine ID of the running system
|
* %v: `uname -r` of the running system
|
||||||
* %H the host name of the running system
|
*
|
||||||
* %b the boot ID of the running system
|
* NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of the unit
|
||||||
* %v `uname -r` of the running system
|
* file itself are broken by design, as they would resolve differently depending on whether they are used
|
||||||
|
* before or after the relevant configuration setting. Hence: don't add them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Specifier table[] = {
|
const Specifier table[] = {
|
||||||
|
|
|
@ -409,8 +409,8 @@ static void test_exec_spec_interpolation(Manager *m) {
|
||||||
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
|
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_tests(UnitFileScope scope, test_function_t *tests) {
|
static int run_tests(UnitFileScope scope, const test_function_t *tests) {
|
||||||
test_function_t *test = NULL;
|
const test_function_t *test = NULL;
|
||||||
Manager *m = NULL;
|
Manager *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -433,7 +433,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_function_t user_tests[] = {
|
static const test_function_t user_tests[] = {
|
||||||
test_exec_workingdirectory,
|
test_exec_workingdirectory,
|
||||||
test_exec_personality,
|
test_exec_personality,
|
||||||
test_exec_ignoresigpipe,
|
test_exec_ignoresigpipe,
|
||||||
|
@ -464,7 +464,7 @@ int main(int argc, char *argv[]) {
|
||||||
test_exec_spec_interpolation,
|
test_exec_spec_interpolation,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
test_function_t system_tests[] = {
|
static const test_function_t system_tests[] = {
|
||||||
test_exec_systemcall_system_mode_with_user,
|
test_exec_systemcall_system_mode_with_user,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue