diff options
-rw-r--r-- | man/systemctl.xml | 13 | ||||
-rw-r--r-- | src/systemctl/systemctl-enable.c | 134 |
2 files changed, 90 insertions, 57 deletions
diff --git a/man/systemctl.xml b/man/systemctl.xml index e589711ea8..55389a910b 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -973,6 +973,11 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err enabled with to the defaults configured in its [Install] section. This command expects a unit name only, it does not accept paths to unit files.</para> + <para>This command implicitly reloads the system manager configuration after completing the operation. + Note that this command does not implicitly restart the units that are being disabled. If this is + desired, either combine this command with the <option>--now</option> switch, or invoke + the <command>try-restart</command> command with appropriate arguments later.</para> + <xi:include href="version-info.xml" xpointer="v238"/> </listitem> </varlistentry> @@ -2583,11 +2588,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err <term><option>--now</option></term> <listitem> - <para>When used with <command>enable</command>, the units - will also be started. When used with <command>disable</command> or - <command>mask</command>, the units will also be stopped. The start - or stop operation is only carried out when the respective enable or - disable operation has been successful.</para> + <para>When used with <command>enable</command>, <command>disable</command>, <command>mask</command>, + or <command>reenable</command>, also start/stop/try-restart the units after the specified + unit file operations succeed.</para> <xi:include href="version-info.xml" xpointer="v220"/> </listitem> diff --git a/src/systemctl/systemctl-enable.c b/src/systemctl/systemctl-enable.c index 496a8173c0..ad90765029 100644 --- a/src/systemctl/systemctl-enable.c +++ b/src/systemctl/systemctl-enable.c @@ -2,7 +2,6 @@ #include "bus-error.h" #include "bus-locator.h" -#include "locale-util.h" #include "path-util.h" #include "systemctl-daemon-reload.h" #include "systemctl-enable.h" @@ -11,46 +10,53 @@ #include "systemctl-util.h" #include "systemctl.h" -static int normalize_filenames(char **names) { +static int normalize_link_paths(char **paths) { int r; - STRV_FOREACH(u, names) - if (!path_is_absolute(*u)) { - char* normalized_path; + STRV_FOREACH(u, paths) { + if (path_is_absolute(*u)) + continue; - if (!isempty(arg_root)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Non-absolute paths are not allowed when --root is used: %s", - *u); + if (!isempty(arg_root)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Non-absolute paths are not allowed when --root= is used: %s", + *u); - if (!strchr(*u, '/')) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Link argument must contain at least one directory separator.\n" - "If you intended to link a file in the current directory, try ./%s instead.", - *u); + if (!is_path(*u)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Link argument must contain at least one directory separator.\n" + "If you intended to link a file in the current directory, try './%s' instead.", + *u); - r = path_make_absolute_cwd(*u, &normalized_path); - if (r < 0) - return r; + char *normalized_path; - free_and_replace(*u, normalized_path); - } + r = path_make_absolute_cwd(*u, &normalized_path); + if (r < 0) + return log_error_errno(r, "Failed to normalize path '%s': %m", *u); + + path_simplify(normalized_path); + + free_and_replace(*u, normalized_path); + } return 0; } static int normalize_names(char **names) { bool was_path = false; + int r; STRV_FOREACH(u, names) { - int r; - if (!is_path(*u)) continue; - r = free_and_strdup(u, basename(*u)); + char *fn; + + r = path_extract_filename(*u, &fn); if (r < 0) - return log_error_errno(r, "Failed to normalize unit file path: %m"); + return log_error_errno(r, "Failed to extract file name from '%s': %m", *u); + + free_and_replace(*u, fn); was_path = true; } @@ -62,18 +68,15 @@ static int normalize_names(char **names) { } int verb_enable(int argc, char *argv[], void *userdata) { + const char *verb = ASSERT_PTR(argv[0]); _cleanup_strv_free_ char **names = NULL; - const char *verb = argv[0]; int carries_install_info = -1; bool ignore_carries_install_info = arg_quiet || arg_no_warn; sd_bus *bus = NULL; int r; - if (!argv[1]) - return 0; - const char *operation = strjoina("to ", verb); - r = mangle_names(operation, strv_skip(argv, 1), &names); + r = mangle_names(operation, ASSERT_PTR(strv_skip(argv, 1)), &names); if (r < 0) return r; @@ -90,17 +93,14 @@ int verb_enable(int argc, char *argv[], void *userdata) { return r > 0 ? 0 : r; } - if (streq(verb, "disable")) { + if (streq(verb, "disable")) r = normalize_names(names); - if (r < 0) - return r; - } - - if (streq(verb, "link")) { - r = normalize_filenames(names); - if (r < 0) - return r; - } + else if (streq(verb, "link")) + r = normalize_link_paths(names); + else + r = 0; + if (r < 0) + return r; if (install_client_side()) { UnitFileFlags flags; @@ -110,6 +110,7 @@ int verb_enable(int argc, char *argv[], void *userdata) { CLEANUP_ARRAY(changes, n_changes, install_changes_free); flags = unit_file_flags_from_args(); + if (streq(verb, "enable")) { r = unit_file_enable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes); carries_install_info = r; @@ -315,10 +316,26 @@ int verb_enable(int argc, char *argv[], void *userdata) { if (arg_now) { _cleanup_strv_free_ char **new_args = NULL; + const char *start_verb; + bool accept_path, prohibit_templates; - if (!STR_IN_SET(verb, "enable", "disable", "mask")) + if (streq(verb, "enable")) { + start_verb = "start"; + accept_path = true; + prohibit_templates = true; + } else if (STR_IN_SET(verb, "disable", "mask")) { + start_verb = "stop"; + accept_path = false; + prohibit_templates = false; + } else if (streq(verb, "reenable")) { + /* Note that we use try-restart here. This matches the semantics of reenable better, + * and allows us to glob template units. */ + start_verb = "try-restart"; + accept_path = true; + prohibit_templates = false; + } else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "--now can only be used with verb enable, disable, or mask."); + "--now can only be used with verb enable, disable, reenable, or mask."); if (install_client_side()) return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), @@ -326,33 +343,46 @@ int verb_enable(int argc, char *argv[], void *userdata) { assert(bus); - if (strv_extend(&new_args, streq(verb, "enable") ? "start" : "stop") < 0) + if (strv_extend(&new_args, start_verb) < 0) return log_oom(); STRV_FOREACH(name, names) { - if (streq(verb, "enable")) { - char *fn; + _cleanup_free_ char *fn = NULL; + const char *unit_name; - /* 'enable' accept path to unit files, so extract it first. Don't try to - * glob them though, as starting globbed unit seldom makes sense and - * actually changes the semantic (we're operating on DefaultInstance= - * when enabling). */ + if (accept_path) { + /* 'enable' and 'reenable' accept path to unit files, so extract it first. */ r = path_extract_filename(*name, &fn); if (r < 0) return log_error_errno(r, "Failed to extract filename of '%s': %m", *name); - r = strv_consume(&new_args, fn); - } else if (unit_name_is_valid(*name, UNIT_NAME_TEMPLATE)) { + unit_name = fn; + } else + unit_name = *name; + + if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { char *globbed; - r = unit_name_replace_instance_full(*name, "*", /* accept_glob = */ true, &globbed); + if (prohibit_templates) { + /* Skip template units when enabling. Globbing doesn't make sense + * since the semantics would be altered (we're operating on + * DefaultInstance= when enabling), and starting template unit + * is not supported anyway. */ + log_warning("Template unit is not supported by %s --now, skipping: %s", + verb, unit_name); + continue; + } + + assert(!STR_IN_SET(start_verb, "start", "restart")); + + r = unit_name_replace_instance_full(unit_name, "*", /* accept_glob = */ true, &globbed); if (r < 0) - return log_error_errno(r, "Failed to glob unit name '%s': %m", *name); + return log_error_errno(r, "Failed to glob unit name '%s': %m", unit_name); r = strv_consume(&new_args, globbed); } else - r = strv_extend(&new_args, *name); + r = strv_extend(&new_args, unit_name); if (r < 0) return log_oom(); } |