diff --git a/man/systemctl.xml b/man/systemctl.xml
index 355956c8ad..a6d295927a 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1988,7 +1988,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
The argument is a comma-separated list of unit types such as and
. When units are listed with list-units,
list-dependencies, show, or status,
- only units of the specified types will be shown. By default, units of all types are shown.
+ only units of the specified types will be shown. By default, units of all types are shown.
+ Use to reset the filter.
As a special case, if one of the arguments is , a list of allowed values
will be printed and the program will exit.
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 00da6d39b4..5c90092f2a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -355,13 +355,6 @@ static int parse_property_argument(const char *value, char ***properties) {
return 0;
}
-static void help_types(void) {
- if (arg_legend != 0)
- puts("Available unit types:");
-
- DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
-}
-
static int help_states(void) {
if (arg_legend != 0)
puts("Available unit load states:");
@@ -451,6 +444,60 @@ static int parse_states_argument(const char *value, char ***states) {
return 1;
}
+static int help_types(void) {
+ if (arg_legend != 0)
+ puts("Available unit types:");
+
+ return DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
+}
+
+static int parse_types_argument(const char *value, char ***types, char ***states) {
+ int r;
+
+ assert(value);
+ assert(types);
+ assert(states);
+
+ if (isempty(value)) {
+ /* reset the setting */
+ *types = strv_free(*types);
+ return 1;
+ }
+
+ for (const char *p = value;;) {
+ _cleanup_free_ char *type = NULL;
+
+ r = extract_first_word(&p, &type, ",", /* flags= */ 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse -t/--type=: %m");
+ if (r == 0)
+ break;
+
+ if (streq(type, "help"))
+ return help_types();
+
+ if (unit_type_from_string(type) >= 0) {
+ if (strv_consume(types, TAKE_PTR(type)) < 0)
+ return log_oom();
+ continue;
+ }
+
+ /* It's much nicer to use --state= for load states, but let's support this in
+ * --types= too for compatibility with old versions */
+ if (unit_load_state_from_string(type) >= 0) {
+ if (strv_consume(states, TAKE_PTR(type)) < 0)
+ return log_oom();
+ continue;
+ }
+
+ log_error("Unknown unit type or load state '%s'.", type);
+ return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Use -t help to see a list of allowed values.");
+ }
+
+ return 1;
+}
+
static int systemctl_parse_argv(int argc, char *argv[]) {
enum {
ARG_FAIL = 0x100, /* compatibility only */
@@ -597,43 +644,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return version();
case 't':
- if (isempty(optarg))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--type= requires arguments.");
-
- for (const char *p = optarg;;) {
- _cleanup_free_ char *type = NULL;
-
- r = extract_first_word(&p, &type, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to parse type: %s", optarg);
- if (r == 0)
- break;
-
- if (streq(type, "help")) {
- help_types();
- return 0;
- }
-
- if (unit_type_from_string(type) >= 0) {
- if (strv_consume(&arg_types, TAKE_PTR(type)) < 0)
- return log_oom();
- continue;
- }
-
- /* It's much nicer to use --state= for load states, but let's support this in
- * --types= too for compatibility with old versions */
- if (unit_load_state_from_string(type) >= 0) {
- if (strv_consume(&arg_states, TAKE_PTR(type)) < 0)
- return log_oom();
- continue;
- }
-
- log_error("Unknown unit type or load state '%s'.", type);
- return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
- "Use -t help to see a list of allowed values.");
- }
-
+ r = parse_types_argument(optarg, &arg_types, &arg_states);
+ if (r <= 0)
+ return r;
break;
case 'P':