]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: split out helper for --state= and allow resetting
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Wed, 13 May 2026 15:00:00 +0000 (17:00 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 14 May 2026 07:03:11 +0000 (09:03 +0200)
So far we'd reject --state=, but it seems nicer to make it reset the
setting as we generally do. The output variable is modified in place…
Option parsing isn't atomic anyway, so I think it's fine to to that.

man/systemctl.xml
src/systemctl/systemctl.c

index b8ba0f945e97bafb17ad819b6da5b497037f8009..355956c8adbdcc0abbda7bd4bba73c9629613a31 100644 (file)
@@ -2000,9 +2000,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
 
         <listitem>
           <para>The argument is a comma-separated list of unit LOAD, SUB, or ACTIVE states. When listing
-          units with <command>list-units</command>, <command>list-dependencies</command>, <command>show</command>
-          or <command>status</command>, show only those in the specified states. Use <option>--state=failed</option>
-          or <option>--failed</option> to show only failed units.</para>
+          units with <command>list-units</command>, <command>list-dependencies</command>,
+          <command>show</command> or <command>status</command>, show only those in the specified states. Use
+          <option>--state=failed</option> or <option>--failed</option> to show only failed units. Use
+          <option>--state=</option> to reset the filter.</para>
 
           <para>As a special case, if one of the arguments is <option>help</option>, a list of allowed values
           will be printed and the program will exit.</para>
index 775188b5191cb101b353aee984f82a4669fd167f..47f34e1ad3434e084e9775701f86fa0f35cf3204 100644 (file)
@@ -334,7 +334,7 @@ static void help_types(void) {
         DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
 }
 
-static void help_states(void) {
+static int help_states(void) {
         if (arg_legend != 0)
                 puts("Available unit load states:");
         DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
@@ -389,7 +389,38 @@ static void help_states(void) {
 
         if (arg_legend != 0)
                 puts("\nAvailable timer unit substates:");
-        DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
+        return DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
+}
+
+static int parse_states_argument(const char *value, char ***states) {
+        int r;
+
+        assert(value);
+        assert(states);
+
+        if (isempty(value)) {
+                /* reset the setting */
+                *states = strv_free(*states);
+                return 1;
+        }
+
+        for (const char *p = value;;) {
+                _cleanup_free_ char *s = NULL;
+
+                r = extract_first_word(&p, &s, ",", /* flags= */ 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse --state=: %m");
+                if (r == 0)
+                        break;
+
+                if (streq(s, "help"))
+                        return help_states();
+
+                if (strv_consume(states, TAKE_PTR(s)) < 0)
+                        return log_oom();
+        }
+
+        return 1;
 }
 
 static int systemctl_parse_argv(int argc, char *argv[]) {
@@ -869,27 +900,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_STATE:
-                        if (isempty(optarg))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "--state= requires arguments.");
-
-                        for (const char *p = optarg;;) {
-                                _cleanup_free_ char *s = NULL;
-
-                                r = extract_first_word(&p, &s, ",", 0);
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to parse state: %s", optarg);
-                                if (r == 0)
-                                        break;
-
-                                if (streq(s, "help")) {
-                                        help_states();
-                                        return 0;
-                                }
-
-                                if (strv_consume(&arg_states, TAKE_PTR(s)) < 0)
-                                        return log_oom();
-                        }
+                        r = parse_states_argument(optarg, &arg_states);
+                        if (r <= 0)
+                                return r;
                         break;
 
                 case 'r':