From 65d36d59c936650e141fcbf38b287627fd0ba21a Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Fri, 15 May 2015 09:54:10 +0200 Subject: [PATCH] systemctl: introduce --now for enable, disable and mask https://bugs.freedesktop.org/show_bug.cgi?id=42940 Conflicts: src/libsystemd/sd-bus/bus-util.c src/libsystemd/sd-bus/bus-util.h src/systemctl/systemctl.c Cherry-picked from: 57ab2eabb8f92fad5239c7d4492e9c6e23ee0678 Resolves: #1233081 --- Makefile.am | 1 + man/systemctl.xml | 33 ++++++--- src/libsystemd/sd-bus/bus-util.c | 6 +- src/libsystemd/sd-bus/bus-util.h | 3 +- src/machine/machinectl.c | 2 +- src/shared/install.c | 112 +++++++++++++++---------------- src/shared/install.h | 1 + src/systemctl/systemctl.c | 28 ++++++-- 8 files changed, 114 insertions(+), 72 deletions(-) diff --git a/Makefile.am b/Makefile.am index 604eaf2f1..d3fb398fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5253,6 +5253,7 @@ machinectl_LDADD = \ libsystemd-internal.la \ libsystemd-logs.la \ libsystemd-journal-internal.la \ + libsystemd-units.la \ libsystemd-shared.la rootbin_PROGRAMS += \ diff --git a/man/systemctl.xml b/man/systemctl.xml index 3c4c9cb92..44ec0d7bc 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -455,6 +455,18 @@ + + + + + When used with enable, the units + will also be started. When used with disable or + mask, 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. + + + @@ -909,11 +921,12 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service the changes are taken into account immediately. Note that this does not have the effect of also starting any of the units being enabled. If this - is desired, a separate start command must - be invoked for the unit. Also note that in case of instance - enablement, symlinks named the same as instances are created in - the install location, however they all point to the same - template unit file. + is desired, either should be used + together with this command, or an additional start + command must be invoked for the unit. Also note that in case of + instance enablement, symlinks named the same as instances + are created in the install location, however they all point to the + same template unit file. This command will print the actions executed. This output may be suppressed by passing . @@ -968,9 +981,10 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service enable. This call implicitly reloads the systemd daemon configuration after completing the disabling of the units. Note that this command does not implicitly - stop the units that are being disabled. If this is desired, - an additional stop command should be - executed afterwards. + stop the units that are being disabled. If this is desired, either + should be used together with this command, or + an additional stop command should be executed + afterwards. This command will print the actions executed. This output may be suppressed by passing . @@ -1116,7 +1130,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service activation of the unit, including enablement and manual activation. Use this option with care. This honors the option to only mask temporarily - until the next reboot of the system. + until the next reboot of the system. The + option can be used to ensure that the units are also stopped. diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index 2e6d88962..fff00d9f9 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -1849,7 +1849,7 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { return set_put_strdup(d->jobs, path); } -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { const char *type, *path, *source; int r; @@ -1864,6 +1864,10 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { else log_info("Removed symlink %s.", path); } + + r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source); + if (r < 0) + return r; } if (r < 0) return bus_log_parse_error(r); diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h index e8a97cef9..21db98228 100644 --- a/src/libsystemd/sd-bus/bus-util.h +++ b/src/libsystemd/sd-bus/bus-util.h @@ -24,6 +24,7 @@ #include "sd-event.h" #include "sd-bus.h" #include "hashmap.h" +#include "install.h" #include "time-util.h" #include "util.h" @@ -211,4 +212,4 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet); DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet); +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 9f8c68b18..f1910709d 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1709,7 +1709,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) { return bus_log_parse_error(r); } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; diff --git a/src/shared/install.c b/src/shared/install.c index efd489ec0..b62065be5 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -113,51 +113,6 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d return 0; } -static int add_file_change( - UnitFileChange **changes, - unsigned *n_changes, - UnitFileChangeType type, - const char *path, - const char *source) { - - UnitFileChange *c; - unsigned i; - - assert(path); - assert(!changes == !n_changes); - - if (!changes) - return 0; - - c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); - if (!c) - return -ENOMEM; - - *changes = c; - i = *n_changes; - - c[i].type = type; - c[i].path = strdup(path); - if (!c[i].path) - return -ENOMEM; - - path_kill_slashes(c[i].path); - - if (source) { - c[i].source = strdup(source); - if (!c[i].source) { - free(c[i].path); - return -ENOMEM; - } - - path_kill_slashes(c[i].path); - } else - c[i].source = NULL; - - *n_changes = i+1; - return 0; -} - static int mark_symlink_for_removal( Set **remove_symlinks_to, const char *p) { @@ -310,7 +265,7 @@ static int remove_marked_symlinks_fd( path_kill_slashes(p); rmdir_parents(p, config_path); - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); if (!set_get(remove_symlinks_to, p)) { @@ -597,7 +552,7 @@ int unit_file_mask( } if (symlink("/dev/null", path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); continue; } @@ -608,8 +563,8 @@ int unit_file_mask( if (force) { if (symlink_atomic("/dev/null", path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); continue; } } @@ -665,7 +620,7 @@ int unit_file_unmask( q = -errno; else { q = mark_symlink_for_removal(&remove_symlinks_to, path); - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); } } @@ -747,7 +702,7 @@ int unit_file_link( return -ENOMEM; if (symlink(*i, path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); continue; } @@ -766,8 +721,8 @@ int unit_file_link( if (force) { if (symlink_atomic(*i, path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); continue; } } @@ -794,6 +749,51 @@ void unit_file_list_free(Hashmap *h) { hashmap_free(h); } +int unit_file_changes_add( + UnitFileChange **changes, + unsigned *n_changes, + UnitFileChangeType type, + const char *path, + const char *source) { + + UnitFileChange *c; + unsigned i; + + assert(path); + assert(!changes == !n_changes); + + if (!changes) + return 0; + + c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); + if (!c) + return -ENOMEM; + + *changes = c; + i = *n_changes; + + c[i].type = type; + c[i].path = strdup(path); + if (!c[i].path) + return -ENOMEM; + + path_kill_slashes(c[i].path); + + if (source) { + c[i].source = strdup(source); + if (!c[i].source) { + free(c[i].path); + return -ENOMEM; + } + + path_kill_slashes(c[i].path); + } else + c[i].source = NULL; + + *n_changes = i+1; + return 0; +} + void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { unsigned i; @@ -1199,7 +1199,7 @@ static int create_symlink( mkdir_parents_label(new_path, 0755); if (symlink(old_path, new_path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); return 0; } @@ -1220,8 +1220,8 @@ static int create_symlink( if (r < 0) return r; - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); return 0; } diff --git a/src/shared/install.h b/src/shared/install.h index 3ca39397e..d729e6ed1 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -112,6 +112,7 @@ UnitFileState unit_file_get_state( int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h); void unit_file_list_free(Hashmap *h); +int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source); void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes); int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 089c25f83..9898694d7 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -138,6 +138,7 @@ static char *arg_host = NULL; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_plain = false; +static bool arg_now = false; static bool original_stdout_is_tty; @@ -1979,7 +1980,7 @@ static int set_default(sd_bus *bus, char **args) { return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -5415,7 +5416,7 @@ static int enable_unit(sd_bus *bus, char **args) { return bus_log_parse_error(r); } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); if (r < 0) return r; @@ -5437,6 +5438,18 @@ static int enable_unit(sd_bus *bus, char **args) { "3) A unit may be started when needed via activation (socket, path, timer,\n" " D-Bus, udev, scripted systemctl call, ...).\n"); + if (arg_now && n_changes > 0 && STR_IN_SET(args[0], "enable", "disable", "mask")) { + char *new_args[n_changes + 2]; + unsigned i; + + new_args[0] = streq(args[0], "enable") ? (char *)"start" : (char *)"stop"; + for (i = 0; i < n_changes; i++) + new_args[i + 1] = basename(changes[i].path); + new_args[i + 1] = NULL; + + r = start_unit(bus, new_args); + } + finish: unit_file_changes_free(changes, n_changes); @@ -5516,7 +5529,7 @@ static int add_dependency(sd_bus *bus, char **args) { return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -5582,7 +5595,7 @@ static int preset_all(sd_bus *bus, char **args) { return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -6058,6 +6071,7 @@ static void systemctl_help(void) { " When shutting down or sleeping, ignore inhibitors\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" + " --now Start or stop unit in addition to enabling or disabling it\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" " --no-wall Don't send wall message before halt/power-off/reboot\n" @@ -6255,6 +6269,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_STATE, ARG_JOB_MODE, ARG_PRESET_MODE, + ARG_NOW, }; static const struct option options[] = { @@ -6297,6 +6312,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "state", required_argument, NULL, ARG_STATE }, { "recursive", no_argument, NULL, 'r' }, { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "now", no_argument, NULL, ARG_NOW }, {} }; @@ -6573,6 +6589,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; + case ARG_NOW: + arg_now = true; + break; + case '?': return -EINVAL;