diff --git a/man/portablectl.xml b/man/portablectl.xml
index 5472397d481..0571c9d7c45 100644
--- a/man/portablectl.xml
+++ b/man/portablectl.xml
@@ -311,7 +311,7 @@
- set-limit [NAME] BYTES
+ set-limit [IMAGE] BYTES
Sets the maximum size in bytes that a specific portable service image, or all images, may grow
up to on disk (disk quota). Takes either one or two parameters. The first, optional parameter refers to a
diff --git a/man/systemd.xml b/man/systemd.xml
index 84aa43723cd..b409ba7c015 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -96,6 +96,13 @@
outputs a terse but complete list of configuration items
understood in unit definition files.
+
+
+
+ Dump exposed bus properties. This outputs
+ a terse but complete list of properties exposed to dbus.
+
+
diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build
index 3705adccf51..34ade44ab16 100644
--- a/shell-completion/bash/meson.build
+++ b/shell-completion/bash/meson.build
@@ -41,8 +41,9 @@ if bashcompletiondir != 'no'
['loginctl', 'ENABLE_LOGIND'],
['machinectl', 'ENABLE_MACHINED'],
['networkctl', 'ENABLE_NETWORKD'],
- ['systemd-resolve', 'ENABLE_RESOLVE'],
+ ['portablectl', 'ENABLE_PORTABLED'],
['resolvectl', 'ENABLE_RESOLVE'],
+ ['systemd-resolve', 'ENABLE_RESOLVE'],
['timedatectl', 'ENABLE_TIMEDATED'],
]
diff --git a/shell-completion/bash/portablectl b/shell-completion/bash/portablectl
new file mode 100644
index 00000000000..faeaeefe3ce
--- /dev/null
+++ b/shell-completion/bash/portablectl
@@ -0,0 +1,113 @@
+# portablectl(1) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# Copyright 2018 Yu Watanabe
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see .
+
+__contains_word () {
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+}
+
+__get_machines() {
+ local a b
+ machinectl list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
+}
+
+_portablectl() {
+ local i n comps verb
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local -A OPTS=(
+ [STANDALONE]='-q --quiet --runtime --no-reload --cat --no-pager --no-legend
+ --no-ask-password -h --help --version'
+ [ARG]='-p --profile --copy -H --host -M --machine'
+ )
+
+ local -A VERBS=(
+ [STANDALONE]='list'
+ [IMAGE]='attach detach inspect is-attached set-limit'
+ [IMAGES]='remove'
+ [IMAGE_WITH_BOOL]='read-only'
+ )
+
+ if __contains_word "$prev" ${OPTS[ARG]}; then
+ case $prev in
+ --profile|-p)
+ comps="default nonetwork strict trusted"
+ ;;
+ --copy)
+ comps="copy symlink auto"
+ ;;
+ --host|-H)
+ comps=$(compgen -A hostname)
+ ;;
+ --machine|-M)
+ comps=$( __get_machines )
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ fi
+
+ if [[ "$cur" = -* ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+ fi
+
+ for ((i=0; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ verb=${COMP_WORDS[i]}
+ break
+ fi
+ done
+
+ n=$(($COMP_CWORD - $i))
+
+ if [[ -z $verb ]]; then
+ comps=${VERBS[*]}
+ elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
+ comps=''
+ elif __contains_word "$verb" ${VERBS[IMAGE]}; then
+ if [[ $n == 1 ]]; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ else
+ comps=''
+ fi
+ elif __contains_word "$verb" ${VERBS[IMAGES]}; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ elif __contains_word "$verb" ${VERBS[IMAGE_WITH_BOOL]}; then
+ if [[ $n == 1 ]]; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ elif [[ $n == 2 ]]; then
+ comps='yes no'
+ else
+ comps=''
+ fi
+ fi
+
+ COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _portablectl portablectl
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 30056e37821..8bf83c8aeae 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -11,12 +11,7 @@ __systemctl() {
}
__systemd_properties() {
- local mode=$1
- { __systemctl $mode show --all;
- @rootlibexecdir@/systemd --dump-configuration-items; } |
- while IFS='=' read -r key value; do
- [[ $value ]] && echo "$key"
- done
+ @rootlibexecdir@/systemd --dump-bus-properties
}
__contains_word () {
@@ -67,6 +62,8 @@ __filter_units_by_properties () {
}
__get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \
+ | { while read -r a b; do echo " $a"; done; }; }
+__get_non_template_units() { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \
| { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; }
__get_template_names () { __systemctl $1 list-unit-files \
| { while read -r a b; do [[ $a =~ @\. ]] && echo " ${a%%@.*}@"; done; }; }
@@ -154,7 +151,7 @@ _systemctl () {
comps=$(compgen -A hostname)
;;
--property|-p)
- comps=$(__systemd_properties $mode)
+ comps=$(__systemd_properties)
;;
--preset-mode)
comps='full enable-only disable-only'
@@ -177,7 +174,8 @@ _systemctl () {
fi
local -A VERBS=(
- [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies edit set-property revert'
+ [ALL_UNITS]='cat mask'
+ [NONTEMPLATE_UNITS]='is-active is-failed is-enabled status show preset help list-dependencies edit set-property revert'
[ENABLED_UNITS]='disable'
[DISABLED_UNITS]='enable'
[REENABLABLE_UNITS]='reenable'
@@ -217,6 +215,10 @@ _systemctl () {
comps=$( __get_all_units $mode )
compopt -o filenames
+ elif __contains_word "$verb" ${VERBS[NONTEMPLATE_UNITS]}; then
+ comps=$( __get_non_template_units $mode )
+ compopt -o filenames
+
elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then
comps=$( __get_enabled_units $mode )
compopt -o filenames
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index 6957a848c31..000b58560b2 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -337,9 +337,7 @@ _unit_properties() {
if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES$_sys_service_mgr ) ||
! _retrieve_cache SYS_ALL_PROPERTIES$_sys_service_mgr;
then
- _sys_all_properties=( ${${(M)${(f)"$(__systemctl show --all;
- @rootlibexecdir@/systemd --dump-configuration-items)"}##[[:alnum:]]##=*}%%=*}
- )
+ _sys_all_properties=( ${${(M)${(f)"$(@rootlibexecdir@/systemd --dump-bus-properties)"}}} )
_store_cache SYS_ALL_PROPERTIES$_sys_service_mgr _sys_all_properties
fi
_values -s , "${_sys_all_properties[@]}"
diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h
index 2d4079a7b47..755bdab1b6a 100644
--- a/src/core/dbus-automount.h
+++ b/src/core/dbus-automount.h
@@ -7,6 +7,11 @@
Copyright 2010 Lennart Poettering
***/
+#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+
+#include "unit.h"
+
extern const sd_bus_vtable bus_automount_vtable[];
int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h
index b0cd63ebc30..72f135d29c7 100644
--- a/src/core/dbus-cgroup.h
+++ b/src/core/dbus-cgroup.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
#include "cgroup.h"
diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h
index c0f8f79adf9..eca3559d6e1 100644
--- a/src/core/dbus-device.h
+++ b/src/core/dbus-device.h
@@ -7,6 +7,6 @@
Copyright 2010 Lennart Poettering
***/
-#include "unit.h"
+#include "sd-bus-vtable.h"
extern const sd_bus_vtable bus_device_vtable[];
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 56b04b57219..fbf8b483b18 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "execute.h"
diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h
index 819e69f3d4b..6e332b3082b 100644
--- a/src/core/dbus-job.h
+++ b/src/core/dbus-job.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "job.h"
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
index e764e4e101c..6d5197a0d3a 100644
--- a/src/core/dbus-kill.h
+++ b/src/core/dbus-kill.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "kill.h"
#include "unit.h"
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
index 86f33931a9c..c0a6ab93cf6 100644
--- a/src/core/dbus-manager.h
+++ b/src/core/dbus-manager.h
@@ -7,6 +7,8 @@
Copyright 2010 Lennart Poettering
***/
+#include "sd-bus-vtable.h"
+
#include "manager.h"
extern const sd_bus_vtable bus_manager_vtable[];
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
index 66a675935ea..d6c480f5776 100644
--- a/src/core/dbus-mount.h
+++ b/src/core/dbus-mount.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h
index 5d729cdefca..ea12de5fb86 100644
--- a/src/core/dbus-path.h
+++ b/src/core/dbus-path.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h
index 115886b134a..31ccbb47f94 100644
--- a/src/core/dbus-scope.h
+++ b/src/core/dbus-scope.h
@@ -8,8 +8,10 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "scope.h"
+#include "unit.h"
extern const sd_bus_vtable bus_scope_vtable[];
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
index f96d426a9ca..bc684ac80cb 100644
--- a/src/core/dbus-service.h
+++ b/src/core/dbus-service.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h
index 3a02fa64d00..5760cd8d61e 100644
--- a/src/core/dbus-slice.h
+++ b/src/core/dbus-slice.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
index 7743031a108..59db02686c4 100644
--- a/src/core/dbus-socket.h
+++ b/src/core/dbus-socket.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
index 88e2b211ad3..da089d2ea4b 100644
--- a/src/core/dbus-swap.h
+++ b/src/core/dbus-swap.h
@@ -9,6 +9,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h
index 8c1a5ec5231..76f0f1a34e4 100644
--- a/src/core/dbus-target.h
+++ b/src/core/dbus-target.h
@@ -7,6 +7,6 @@
Copyright 2010 Lennart Poettering
***/
-#include "sd-bus.h"
+#include "sd-bus-vtable.h"
extern const sd_bus_vtable bus_target_vtable[];
diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h
index ff3ad6cf6d4..1cfc9bf9be5 100644
--- a/src/core/dbus-timer.h
+++ b/src/core/dbus-timer.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index 7fce07d1e96..8c55d7dfdf3 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -8,7 +8,9 @@
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+#include "job.h"
#include "unit.h"
extern const sd_bus_vtable bus_unit_vtable[];
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
index b1f7b69d796..73d1ebd3136 100644
--- a/src/core/dbus-util.h
+++ b/src/core/dbus-util.h
@@ -8,6 +8,7 @@
***/
#include "sd-bus.h"
+
#include "unit.h"
int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 4df898f963b..e535d9eda9e 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -16,11 +16,22 @@
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-util.h"
+#include "dbus-automount.h"
#include "dbus-cgroup.h"
+#include "dbus-device.h"
#include "dbus-execute.h"
#include "dbus-job.h"
#include "dbus-kill.h"
#include "dbus-manager.h"
+#include "dbus-mount.h"
+#include "dbus-path.h"
+#include "dbus-scope.h"
+#include "dbus-service.h"
+#include "dbus-slice.h"
+#include "dbus-socket.h"
+#include "dbus-swap.h"
+#include "dbus-target.h"
+#include "dbus-timer.h"
#include "dbus-unit.h"
#include "dbus.h"
#include "fd-util.h"
@@ -1292,3 +1303,38 @@ uint64_t manager_bus_n_queued_write(Manager *m) {
return c;
}
+
+static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) {
+ const sd_bus_vtable *i;
+
+ for (i = table; i->type != _SD_BUS_VTABLE_END; i++) {
+ if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) ||
+ (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0)
+ continue;
+
+ fprintf(f, "%s\n", i->x.property.member);
+ }
+}
+
+void dump_bus_properties(FILE *f) {
+ assert(f);
+
+ vtable_dump_bus_properties(f, bus_automount_vtable);
+ vtable_dump_bus_properties(f, bus_cgroup_vtable);
+ vtable_dump_bus_properties(f, bus_device_vtable);
+ vtable_dump_bus_properties(f, bus_exec_vtable);
+ vtable_dump_bus_properties(f, bus_job_vtable);
+ vtable_dump_bus_properties(f, bus_kill_vtable);
+ vtable_dump_bus_properties(f, bus_manager_vtable);
+ vtable_dump_bus_properties(f, bus_mount_vtable);
+ vtable_dump_bus_properties(f, bus_path_vtable);
+ vtable_dump_bus_properties(f, bus_scope_vtable);
+ vtable_dump_bus_properties(f, bus_service_vtable);
+ vtable_dump_bus_properties(f, bus_slice_vtable);
+ vtable_dump_bus_properties(f, bus_socket_vtable);
+ vtable_dump_bus_properties(f, bus_swap_vtable);
+ vtable_dump_bus_properties(f, bus_target_vtable);
+ vtable_dump_bus_properties(f, bus_timer_vtable);
+ vtable_dump_bus_properties(f, bus_unit_vtable);
+ vtable_dump_bus_properties(f, bus_unit_cgroup_vtable);
+}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index f13f607111c..a7a0eb3249d 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -7,6 +7,8 @@
Copyright 2010 Lennart Poettering
***/
+#include "sd-bus.h"
+
#include "manager.h"
int bus_send_queued_message(Manager *m);
@@ -37,3 +39,5 @@ int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_er
int bus_forward_agent_released(Manager *m, const char *path);
uint64_t manager_bus_n_queued_write(Manager *m);
+
+void dump_bus_properties(FILE *f);
diff --git a/src/core/main.c b/src/core/main.c
index 7e5a7c22b7a..8c04d41c0c4 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -36,6 +36,7 @@
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
+#include "dbus.h"
#include "dbus-manager.h"
#include "def.h"
#include "emergency-action.h"
@@ -89,7 +90,8 @@ static enum {
ACTION_HELP,
ACTION_VERSION,
ACTION_TEST,
- ACTION_DUMP_CONFIGURATION_ITEMS
+ ACTION_DUMP_CONFIGURATION_ITEMS,
+ ACTION_DUMP_BUS_PROPERTIES,
} arg_action = ACTION_RUN;
static char *arg_default_unit = NULL;
static bool arg_system = false;
@@ -775,6 +777,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_PAGER,
ARG_VERSION,
ARG_DUMP_CONFIGURATION_ITEMS,
+ ARG_DUMP_BUS_PROPERTIES,
ARG_DUMP_CORE,
ARG_CRASH_CHVT,
ARG_CRASH_SHELL,
@@ -802,6 +805,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
+ { "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES },
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
{ "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT },
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
@@ -921,6 +925,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
break;
+ case ARG_DUMP_BUS_PROPERTIES:
+ arg_action = ACTION_DUMP_BUS_PROPERTIES;
+ break;
+
case ARG_DUMP_CORE:
if (!optarg)
arg_dump_core = true;
@@ -1064,6 +1072,7 @@ static int help(void) {
" --test Determine startup sequence, dump it and exit\n"
" --no-pager Do not pipe output into a pager\n"
" --dump-configuration-items Dump understood unit configuration items\n"
+ " --dump-bus-properties Dump exposed bus properties\n"
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
@@ -2302,7 +2311,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS))
+ if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES))
(void) pager_open(arg_no_pager, false);
if (arg_action != ACTION_RUN)
@@ -2318,6 +2327,10 @@ int main(int argc, char *argv[]) {
unit_dump_config_items(stdout);
retval = EXIT_SUCCESS;
goto finish;
+ } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) {
+ dump_bus_properties(stdout);
+ retval = EXIT_SUCCESS;
+ goto finish;
}
assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST));