summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemctl.xml25
-rw-r--r--shell-completion/bash/systemctl7
-rw-r--r--shell-completion/systemd-zsh-completion.zsh2
-rw-r--r--src/systemctl/systemctl.c104
4 files changed, 80 insertions, 58 deletions
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 5656564f54..97bc47ce24 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -92,21 +92,22 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--type=</option></term>
<listitem>
- <para>The argument should be a unit type name such as
- <option>service</option> and <option>socket</option>, or a
- unit load state such as <option>loaded</option> and
- <option>masked</option>.
- </para>
-
- <para>If the argument is a unit type, when listing units,
- limit display to certain unit types. If not specified units
+ <para>The argument should be a comma separated list of unit
+ types such as <option>service</option> and
+ <option>socket</option>, or unit load states such as
+ <option>loaded</option> and <option>masked</option>
+ (types and states can be mixed).</para>
+
+ <para>If one of the arguments is a unit type, when listing
+ units, limit display to certain unit types. Otherwise units
of all types will be shown.</para>
- <para>If the argument is a unit load state, when listing
- units, limit display to certain unit types. If not specified
- units of in all load states will be shown.</para>
+ <para>If one of the arguments is a unit load state, when
+ listing units, limit display to certain unit
+ types. Otherwise units of in all load states will be
+ shown.</para>
- <para>As a special case, if the argument is
+ <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>
</listitem>
diff --git a/shell-completion/bash/systemctl b/shell-completion/bash/systemctl
index aba76f6543..f24a145424 100644
--- a/shell-completion/bash/systemctl
+++ b/shell-completion/bash/systemctl
@@ -45,7 +45,7 @@ __get_all_units () { __systemctl $1 list-units --all \
| { while read -r a b; do echo " $a"; done; }; }
__get_active_units () { __systemctl $1 list-units \
| { while read -r a b; do echo " $a"; done; }; }
-__get_inactive_units () { __systemctl $1 list-units --all \
+__get_startable_units () { __systemctl $1 list-units --all -t service,timer,socket,mount,automount,path,snapshot,swap \
| { while read -r a b c d; do [[ $c == "inactive" || $c == "failed " ]] && echo " $a"; done; }; }
__get_failed_units () { __systemctl $1 list-units \
| { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; }
@@ -156,10 +156,7 @@ _systemctl () {
elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStart yes \
- $( __get_inactive_units $mode \
- | while read -r line; do \
- [[ "$line" =~ \.(device|snapshot)$ ]] || echo " $line"; \
- done ))
+ $( __get_startable_units $mode))
elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStart yes \
diff --git a/shell-completion/systemd-zsh-completion.zsh b/shell-completion/systemd-zsh-completion.zsh
index a54e9d727a..8b60859c23 100644
--- a/shell-completion/systemd-zsh-completion.zsh
+++ b/shell-completion/systemd-zsh-completion.zsh
@@ -536,7 +536,7 @@ for fun in restart reload-or-restart ; do
_systemctl_all_units
compadd "$@" - $( _filter_units_by_property CanStart yes \
${_sys_all_units[*]} | while read line; do \
- [[ "$line" =~ \.(device|snapshot|socket|timer)$ ]] || echo " $line"; \
+ [[ "$line" =~ \.device$ ]] || echo " $line"; \
done )
}
done
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index af7ecd7af1..0e6087c62a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -68,9 +68,9 @@
#include "socket-util.h"
#include "fileio.h"
-static const char *arg_type = NULL;
-static const char *arg_load_state = NULL;
-static char **arg_property = NULL;
+static char **arg_types = NULL;
+static char **arg_load_states = NULL;
+static char **arg_properties = NULL;
static bool arg_all = false;
static const char *arg_job_mode = "replace";
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
@@ -295,9 +295,9 @@ static bool output_show_unit(const struct unit_info *u) {
if (arg_failed)
return streq(u->active_state, "failed");
- return (!arg_type || ((dot = strrchr(u->id, '.')) &&
- streq(dot+1, arg_type))) &&
- (!arg_load_state || streq(u->load_state, arg_load_state)) &&
+ return (!arg_types || ((dot = strrchr(u->id, '.')) &&
+ strv_find(arg_types, dot+1))) &&
+ (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
(arg_all || !(streq(u->active_state, "inactive")
|| u->following[0]) || u->job_id > 0);
}
@@ -524,7 +524,7 @@ static int compare_unit_file_list(const void *a, const void *b) {
static bool output_show_unit_file(const UnitFileList *u) {
const char *dot;
- return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
+ return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
}
static void output_unit_file_list(const UnitFileList *units, unsigned c) {
@@ -2946,7 +2946,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
/* This is a low-level property printer, see
* print_status_info() for the nicer output */
- if (arg_property && !strv_find(arg_property, name))
+ if (arg_properties && !strv_find(arg_properties, name))
return 0;
switch (dbus_message_iter_get_arg_type(iter)) {
@@ -4504,45 +4504,67 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
puts(SYSTEMD_FEATURES);
return 0;
- case 't':
- if (streq(optarg, "help")) {
- help_types();
- return 0;
- }
+ case 't': {
+ char *word, *state;
+ size_t size;
- if (unit_type_from_string(optarg) >= 0) {
- arg_type = optarg;
- break;
- }
- if (unit_load_state_from_string(optarg) >= 0) {
- arg_load_state = optarg;
- break;
+ FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ char _cleanup_free_ *type;
+
+ type = strndup(word, size);
+ if (!type)
+ return -ENOMEM;
+
+ if (streq(type, "help")) {
+ help_types();
+ return 0;
+ }
+
+ if (unit_type_from_string(type) >= 0) {
+ if (strv_push(&arg_types, type))
+ return log_oom();
+ type = NULL;
+ continue;
+ }
+
+ if (unit_load_state_from_string(optarg) >= 0) {
+ if (strv_push(&arg_load_states, type))
+ return log_oom();
+ type = NULL;
+ continue;
+ }
+
+ log_error("Unkown unit type or load state '%s'.", type);
+ log_info("Use -t help to see a list of allowed values.");
+ return -EINVAL;
}
- log_error("Unkown unit type or load state '%s'.",
- optarg);
- log_info("Use -t help to see a list of allowed values.");
- return -EINVAL;
+
+ break;
+ }
+
case 'p': {
- char *word, *state;
- size_t size;
/* Make sure that if the empty property list
was specified, we won't show any properties. */
- const char *source = isempty(optarg) ? " " : optarg;
+ if (isempty(optarg) && !arg_properties) {
+ arg_properties = strv_new(NULL, NULL);
+ if (!arg_properties)
+ return log_oom();
+ } else {
+ char *word, *state;
+ size_t size;
- FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
- char _cleanup_free_ *prop;
- char **tmp;
+ FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ char *prop;
- prop = strndup(word, size);
- if (!prop)
- return -ENOMEM;
+ prop = strndup(word, size);
+ if (!prop)
+ return log_oom();
- tmp = strv_append(arg_property, prop);
- if (!tmp)
- return -ENOMEM;
-
- strv_free(arg_property);
- arg_property = tmp;
+ if (strv_push(&arg_properties, prop)) {
+ free(prop);
+ return log_oom();
+ }
+ }
}
/* If the user asked for a particular
@@ -5725,7 +5747,9 @@ finish:
dbus_shutdown();
- strv_free(arg_property);
+ strv_free(arg_types);
+ strv_free(arg_load_states);
+ strv_free(arg_properties);
pager_close();
ask_password_agent_close();