[systemd-devel] [PATCH] systemctl: introduce --now for enable, disable and mask

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Thu May 14 05:56:32 PDT 2015


On Thu, May 14, 2015 at 02:26:34PM +0200, jsynacek at redhat.com wrote:
> From: Jan Synacek <jsynacek at redhat.com>
> 
> ---
>  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             |  2 +-
>  src/shared/install.h             |  3 +++
>  src/systemctl/systemctl.c        | 33 +++++++++++++++++++++++++++++----
>  8 files changed, 66 insertions(+), 17 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index e8a329f..861f3b2 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -5351,6 +5351,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 4dbdfe1..951ce4d 100644
> --- a/man/systemctl.xml
> +++ b/man/systemctl.xml
> @@ -456,6 +456,17 @@
>        </varlistentry>
>  
>        <varlistentry>
> +        <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 additionally be
> +          stopped.</para>
> +        </listitem>
> +      </varlistentry>
> +
> +      <varlistentry>
>          <term><option>--root=</option></term>
>  
>          <listitem>
> @@ -921,11 +932,12 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
>              the changes are taken into account immediately. Note that
>              this does <emphasis>not</emphasis> have the effect of also
>              starting any of the units being enabled. If this
> -            is desired, a separate <command>start</command> 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.</para>
> +            is desired, either <option>--now</option> should be used
> +            together with this command, or a separate <command>start</command>
> +            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.</para>
>  
>              <para>This command will print the actions executed. This
>              output may be suppressed by passing <option>--quiet</option>.
> @@ -980,9 +992,10 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
>              <command>enable</command>. 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 <command>stop</command> command should be
> -            executed afterwards.</para>
> +            stop the units that are being disabled. If this is desired, either
> +            <option>--now</option> should be used together with this command, or
> +            an additional <command>stop</command> command should be executed
> +            afterwards.</para>
>  
>              <para>This command will print the actions executed. This
>              output may be suppressed by passing <option>--quiet</option>.
> @@ -1128,7 +1141,9 @@ 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>--runtime</option> option to only mask temporarily
> -            until the next reboot of the system.</para>
> +            until the next reboot of the system. The <option>--now</option>
> +            can be additionally used to ensure that the units are also
> +            stopped.</para>
>            </listitem>
>          </varlistentry>
>  
> diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
> index 7536a96..fe7eb43 100644
> --- a/src/libsystemd/sd-bus/bus-util.c
> +++ b/src/libsystemd/sd-bus/bus-util.c
> @@ -1899,7 +1899,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
>          return bus_wait_for_jobs(d, quiet);
>  }
>  
> -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;
>  
> @@ -1914,6 +1914,10 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
>                          else
>                                  log_info("Removed symlink %s.", path);
>                  }
> +
> +                r = add_file_change(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 093b48b..999a372 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"
>  
>  typedef enum BusTransport {
> @@ -201,7 +202,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, 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);
>  
>  int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path);
>  int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external);
> diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
> index 3764c0a..b21a339 100644
> --- a/src/machine/machinectl.c
> +++ b/src/machine/machinectl.c
> @@ -1479,7 +1479,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 dc4cc62..5c9ea8b 100644
> --- a/src/shared/install.c
> +++ b/src/shared/install.c
> @@ -112,7 +112,7 @@ static int get_config_path(UnitFileScope scope, bool runtime, const char *root_d
>          return 0;
>  }
>  
> -static int add_file_change(
> +int add_file_change(
>                  UnitFileChange **changes,
>                  unsigned *n_changes,
>                  UnitFileChangeType type,
> diff --git a/src/shared/install.h b/src/shared/install.h
> index 45eca42..831823e 100644
> --- a/src/shared/install.h
> +++ b/src/shared/install.h
> @@ -132,3 +132,6 @@ UnitFileChangeType unit_file_change_type_from_string(const char *s) _pure_;
>  
>  const char *unit_file_preset_mode_to_string(UnitFilePresetMode m) _const_;
>  UnitFilePresetMode unit_file_preset_mode_from_string(const char *s) _pure_;
> +
> +
> +int add_file_change(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
> diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
> index 1f18f9c..0f969c5 100644
> --- a/src/systemctl/systemctl.c
> +++ b/src/systemctl/systemctl.c
> @@ -136,6 +136,7 @@ static unsigned arg_lines = 10;
>  static OutputMode arg_output = OUTPUT_SHORT;
>  static bool arg_plain = false;
>  static bool arg_firmware_setup = false;
> +static bool arg_now = false;
>  
>  static bool original_stdout_is_tty;
>  
> @@ -1973,7 +1974,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;
>  
> @@ -5388,7 +5389,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;
>  
> @@ -5410,6 +5411,23 @@ 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")) {
> +                _cleanup_strv_free_ char **new_args = NULL;
> +                unsigned i;
> +
> +                r = strv_push(&new_args, streq(args[0], "enable") ? strdup("start") : strdup("stop"));
This is not oom safe below. But do you really need to allocate the strings?
You can use alloca or malloc for new_args, and put pointers to existing
strings in the array. It only needs to live until the end of the block,
and changes[i].path should not go away in the meantime.


> +                if (r < 0)
> +                        goto finish;
> +
> +                for (i = 0; i < n_changes; i++) {
> +                        r = strv_push(&new_args, strdup(strrchr(changes[i].path, '/') + 1));
> +                        if (r < 0)
> +                                goto finish;
> +                }
> +
> +                r = start_unit(bus, new_args);
> +        }
> +
>  finish:
>          unit_file_changes_free(changes, n_changes);
>  
> @@ -5485,7 +5503,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;
>  
> @@ -5539,7 +5557,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;
>  
> @@ -6015,6 +6033,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"
> @@ -6214,6 +6233,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
>                  ARG_JOB_MODE,
>                  ARG_PRESET_MODE,
>                  ARG_FIRMWARE_SETUP,
> +                ARG_NOW,
>          };
>  
>          static const struct option options[] = {
> @@ -6257,6 +6277,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
>                  { "recursive",           no_argument,       NULL, 'r'                     },
>                  { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
>                  { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
> +                { "now",                 no_argument,       NULL, ARG_NOW                 },
>                  {}
>          };
>  
> @@ -6537,6 +6558,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
>  
>                          break;
>  
> +                case ARG_NOW:
> +                        arg_now = true;
> +                        break;
> +
>                  case '?':
>                          return -EINVAL;
>  

zbyszek


More information about the systemd-devel mailing list