diff --git a/TODO b/TODO
index d5e37e49ac..b21166f90b 100644
--- a/TODO
+++ b/TODO
@@ -334,11 +334,6 @@ Features:
* networkd/udev: implement SR_IOV configuration in .link files:
http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html
-* Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
-
-* Port various tools to make use of verbs.[ch], where applicable: busctl,
- coredumpctl, hostnamectl, localectl, timedatectl
-
* hostnamectl: show root image uuid
* sysfs set api in libudev is not const
diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml
index fa70d5cc6c..9bfead6d21 100644
--- a/man/hostnamectl.xml
+++ b/man/hostnamectl.xml
@@ -121,6 +121,10 @@
+
+
+
+ Commands
The following commands are understood:
@@ -128,9 +132,8 @@
status
- Show current system
- hostname and related
- information.
+ Show current system hostname and related information. If no command is specified,
+ this is the implied default.
diff --git a/man/localectl.xml b/man/localectl.xml
index 89a7ab2855..eff8bc3c9e 100644
--- a/man/localectl.xml
+++ b/man/localectl.xml
@@ -118,6 +118,10 @@
+
+
+
+ Commands
The following commands are understood:
@@ -125,8 +129,8 @@
status
- Show current settings of the system locale and
- keyboard mapping.
+ Show current settings of the system locale and keyboard mapping.
+ If no command is specified, this is the implied default.
diff --git a/man/timedatectl.xml b/man/timedatectl.xml
index dba94d8831..f24ec2d4c8 100644
--- a/man/timedatectl.xml
+++ b/man/timedatectl.xml
@@ -98,6 +98,10 @@
+
+
+
+ Commands
The following commands are understood:
@@ -109,6 +113,7 @@
including whether network time synchronization through
systemd-timesyncd.service is active. Even if it is
inactive, a different service might still synchronize the clock.
+ If no command is specified, this is the implied default.
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 092ff763ba..22f634ac5c 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -474,6 +474,7 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
"/org/freedesktop/hostname1",
hostname_map,
&error,
+ NULL,
host);
if (r < 0)
log_debug_errno(r, "Failed to get host information from systemd-hostnamed: %s", bus_error_message(&error, r));
@@ -483,6 +484,7 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
"/org/freedesktop/systemd1",
manager_map,
&error,
+ NULL,
host);
if (r < 0)
return log_error_errno(r, "Failed to get host information from systemd: %s", bus_error_message(&error, r));
@@ -1027,7 +1029,7 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
}
unit_times_hashmap = h;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
puts("The time after the unit is active or started is printed after the \"@\" character.\n"
"The time the unit takes to start is printed after the \"+\" character.\n");
@@ -1060,7 +1062,7 @@ static int analyze_blame(int argc, char *argv[], void *userdata) {
qsort(times, n, sizeof(struct unit_times), compare_unit_time);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
for (i = 0; i < (unsigned) n; i++) {
char ts[FORMAT_TIMESPAN_MAX];
@@ -1283,7 +1285,7 @@ static int dump(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -1445,7 +1447,7 @@ static void dump_syscall_filter(const SyscallFilterSet *set) {
static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
bool first = true;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (strv_isempty(strv_skip(argv, 1))) {
int i;
@@ -1607,7 +1609,7 @@ static int do_verify(int argc, char *argv[], void *userdata) {
static int help(int argc, char *argv[], void *userdata) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Profile systemd, show unit dependencies, check unit files.\n\n"
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index f8c43b5079..2f9250e2ae 100644
--- a/src/busctl/busctl.c
+++ b/src/busctl/busctl.c
@@ -42,6 +42,7 @@
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
+#include "verbs.h"
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -68,7 +69,82 @@ static usec_t arg_timeout = 0;
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
-static int list_bus_names(sd_bus *bus, char **argv) {
+static int acquire_bus(bool set_monitor, sd_bus **ret) {
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ int r;
+
+ r = sd_bus_new(&bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate bus: %m");
+
+ if (set_monitor) {
+ r = sd_bus_set_monitor(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set monitor mode: %m");
+
+ r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable credentials: %m");
+
+ r = sd_bus_negotiate_timestamp(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable timestamps: %m");
+
+ r = sd_bus_negotiate_fds(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable fds: %m");
+ }
+
+ r = sd_bus_set_bus_client(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set bus client: %m");
+
+ r = sd_bus_set_watch_bind(bus, arg_watch_bind);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
+
+ if (arg_address)
+ r = sd_bus_set_address(bus, arg_address);
+ else {
+ switch (arg_transport) {
+
+ case BUS_TRANSPORT_LOCAL:
+ if (arg_user) {
+ bus->is_user = true;
+ r = bus_set_address_user(bus);
+ } else {
+ bus->is_system = true;
+ r = bus_set_address_system(bus);
+ }
+ break;
+
+ case BUS_TRANSPORT_REMOTE:
+ r = bus_set_address_system_remote(bus, arg_host);
+ break;
+
+ case BUS_TRANSPORT_MACHINE:
+ r = bus_set_address_system_machine(bus, arg_host);
+ break;
+
+ default:
+ assert_not_reached("Hmm, unknown transport type.");
+ }
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to set address: %m");
+
+ r = sd_bus_start(bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to bus: %m");
+
+ *ret = bus;
+ bus = NULL;
+
+ return 0;
+}
+
+static int list_bus_names(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
_cleanup_free_ char **merged = NULL;
_cleanup_hashmap_free_ Hashmap *names = NULL;
@@ -80,16 +156,18 @@ static int list_bus_names(sd_bus *bus, char **argv) {
char *k;
Iterator iterator;
- assert(bus);
-
if (!arg_unique && !arg_acquired && !arg_activatable)
arg_unique = arg_acquired = arg_activatable = true;
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
+
r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
if (r < 0)
return log_error_errno(r, "Failed to list names: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
names = hashmap_new(&string_hash_ops);
if (!names)
@@ -112,6 +190,9 @@ static int list_bus_names(sd_bus *bus, char **argv) {
}
merged = new(char*, hashmap_size(names) + 1);
+ if (!merged)
+ return log_oom();
+
HASHMAP_FOREACH_KEY(v, k, names, iterator)
merged[n++] = k;
@@ -283,8 +364,6 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
static void print_tree(const char *prefix, char **l) {
- pager_open(arg_no_pager, false);
-
prefix = strempty(prefix);
if (arg_list) {
@@ -403,7 +482,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
p = NULL;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
l = set_get_strv(done);
if (!l)
@@ -417,14 +496,19 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
return r;
}
-static int tree(sd_bus *bus, char **argv) {
+static int tree(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
char **i;
int r = 0;
if (!arg_unique && !arg_acquired)
arg_acquired = true;
- if (strv_length(argv) <= 1) {
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
+
+ if (argc <= 1) {
_cleanup_strv_free_ char **names = NULL;
bool not_first = false;
@@ -432,7 +516,7 @@ static int tree(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to get name list: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
STRV_FOREACH(i, names) {
int q;
@@ -462,7 +546,7 @@ static int tree(sd_bus *bus, char **argv) {
printf("\n");
if (argv[2]) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
@@ -848,7 +932,7 @@ static const char *strdash(const char *x) {
return isempty(x) ? "-" : x;
}
-static int introspect(sd_bus *bus, char **argv) {
+static int introspect(int argc, char **argv, void *userdata) {
static const struct hash_ops member_hash_ops = {
.hash = member_hash_func,
.compare = member_compare_func,
@@ -861,27 +945,19 @@ static int introspect(sd_bus *bus, char **argv) {
.on_property = on_property,
};
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_xml = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(member_set_freep) Set *members = NULL;
+ unsigned name_width, type_width, signature_width, result_width, j, k = 0;
+ Member *m, **sorted = NULL;
Iterator i;
- Member *m;
const char *xml;
int r;
- unsigned name_width, type_width, signature_width, result_width;
- Member **sorted = NULL;
- unsigned k = 0, j, n_args;
- n_args = strv_length(argv);
- if (n_args < 3) {
- log_error("Requires service and object path argument.");
- return -EINVAL;
- }
-
- if (n_args > 4) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
members = set_new(&member_hash_ops);
if (!members)
@@ -976,7 +1052,7 @@ static int introspect(sd_bus *bus, char **argv) {
return bus_log_parse_error(r);
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
name_width = STRLEN("NAME");
type_width = STRLEN("TYPE");
@@ -1071,7 +1147,8 @@ static int message_pcap(sd_bus_message *m, FILE *f) {
return bus_message_pcap_frame(m, arg_snaplen, f);
}
-static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
+static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f)) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char **i;
@@ -1080,6 +1157,10 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
bool is_monitor = false;
int r;
+ r = acquire_bus(true, &bus);
+ if (r < 0)
+ return r;
+
/* upgrade connection; it's not used for anything else after this call */
r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
if (r < 0)
@@ -1186,7 +1267,11 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
}
}
-static int capture(sd_bus *bus, char *argv[]) {
+static int verb_monitor(int argc, char **argv, void *userdata) {
+ return monitor(argc, argv, message_dump);
+}
+
+static int verb_capture(int argc, char **argv, void *userdata) {
int r;
if (isatty(fileno(stdout)) > 0) {
@@ -1196,7 +1281,7 @@ static int capture(sd_bus *bus, char *argv[]) {
bus_pcap_header(arg_snaplen, stdout);
- r = monitor(bus, argv, message_pcap);
+ r = monitor(argc, argv, message_pcap);
if (r < 0)
return r;
@@ -1208,19 +1293,17 @@ static int capture(sd_bus *bus, char *argv[]) {
return r;
}
-static int status(sd_bus *bus, char *argv[]) {
+static int status(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
int r;
- assert(bus);
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
- if (strv_length(argv) > 2) {
- log_error("Expects no or one argument.");
- return -EINVAL;
- }
-
- if (argv[1]) {
+ if (!isempty(argv[1])) {
r = parse_pid(argv[1], &pid);
if (r < 0)
r = sd_bus_get_name_creds(
@@ -1515,17 +1598,15 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
return 0;
}
-static int call(sd_bus *bus, char *argv[]) {
+static int call(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
int r;
- assert(bus);
-
- if (strv_length(argv) < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
if (r < 0)
@@ -1581,7 +1662,7 @@ static int call(sd_bus *bus, char *argv[]) {
if (r == 0 && !arg_quiet) {
if (arg_verbose) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, 0);
if (r < 0)
@@ -1602,19 +1683,15 @@ static int call(sd_bus *bus, char *argv[]) {
return 0;
}
-static int get_property(sd_bus *bus, char *argv[]) {
+static int get_property(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
char **i;
int r;
- assert(bus);
-
- n = strv_length(argv);
- if (n < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
STRV_FOREACH(i, argv + 4) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -1636,7 +1713,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
return bus_log_parse_error(r);
if (arg_verbose) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
if (r < 0)
@@ -1660,20 +1737,16 @@ static int get_property(sd_bus *bus, char *argv[]) {
return 0;
}
-static int set_property(sd_bus *bus, char *argv[]) {
+static int set_property(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
char **p;
int r;
- assert(bus);
-
- n = strv_length(argv);
- if (n < 6) {
- log_error("Expects at least five arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
if (r < 0)
@@ -1687,7 +1760,7 @@ static int set_property(sd_bus *bus, char *argv[]) {
if (r < 0)
return bus_log_create_error(r);
- p = argv+6;
+ p = argv + 6;
r = message_append_cmdline(m, argv[5], &p);
if (r < 0)
return r;
@@ -1758,6 +1831,10 @@ static int help(void) {
return 0;
}
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
+}
+
static int parse_argv(int argc, char *argv[]) {
enum {
@@ -1978,46 +2055,26 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
-static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
- assert(bus);
+static int busctl_main(int argc, char *argv[]) {
- if (optind >= argc ||
- streq(argv[optind], "list"))
- return list_bus_names(bus, argv + optind);
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names },
+ { "status", VERB_ANY, 2, 0, status },
+ { "monitor", VERB_ANY, VERB_ANY, 0, verb_monitor },
+ { "capture", VERB_ANY, VERB_ANY, 0, verb_capture },
+ { "tree", VERB_ANY, VERB_ANY, 0, tree },
+ { "introspect", 3, 4, 0, introspect },
+ { "call", 5, VERB_ANY, 0, call },
+ { "get-property", 5, VERB_ANY, 0, get_property },
+ { "set-property", 6, VERB_ANY, 0, set_property },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help },
+ {}
+ };
- if (streq(argv[optind], "monitor"))
- return monitor(bus, argv + optind, message_dump);
-
- if (streq(argv[optind], "capture"))
- return capture(bus, argv + optind);
-
- if (streq(argv[optind], "status"))
- return status(bus, argv + optind);
-
- if (streq(argv[optind], "tree"))
- return tree(bus, argv + optind);
-
- if (streq(argv[optind], "introspect"))
- return introspect(bus, argv + optind);
-
- if (streq(argv[optind], "call"))
- return call(bus, argv + optind);
-
- if (streq(argv[optind], "get-property"))
- return get_property(bus, argv + optind);
-
- if (streq(argv[optind], "set-property"))
- return set_property(bus, argv + optind);
-
- if (streq(argv[optind], "help"))
- return help();
-
- log_error("Unknown command '%s'", argv[optind]);
- return -EINVAL;
+ return dispatch_verb(argc, argv, verbs, NULL);
}
int main(int argc, char *argv[]) {
- sd_bus *bus = NULL;
int r;
log_parse_environment();
@@ -2027,98 +2084,14 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- r = sd_bus_new(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate bus: %m");
- goto finish;
- }
-
- if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
-
- r = sd_bus_set_monitor(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set monitor mode: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
- if (r < 0) {
- log_error_errno(r, "Failed to enable credentials: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_timestamp(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable timestamps: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_fds(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable fds: %m");
- goto finish;
- }
- }
-
- r = sd_bus_set_bus_client(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set bus client: %m");
- goto finish;
- }
-
- r = sd_bus_set_watch_bind(bus, arg_watch_bind);
- if (r < 0) {
- log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
- goto finish;
- }
-
- if (arg_address)
- r = sd_bus_set_address(bus, arg_address);
- else {
- switch (arg_transport) {
-
- case BUS_TRANSPORT_LOCAL:
- if (arg_user) {
- bus->is_user = true;
- r = bus_set_address_user(bus);
- } else {
- bus->is_system = true;
- r = bus_set_address_system(bus);
- }
- break;
-
- case BUS_TRANSPORT_REMOTE:
- r = bus_set_address_system_remote(bus, arg_host);
- break;
-
- case BUS_TRANSPORT_MACHINE:
- r = bus_set_address_system_machine(bus, arg_host);
- break;
-
- default:
- assert_not_reached("Hmm, unknown transport type.");
- }
- }
- if (r < 0) {
- log_error_errno(r, "Failed to set address: %m");
- goto finish;
- }
-
- r = sd_bus_start(bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to bus: %m");
- goto finish;
- }
-
- r = busctl_main(bus, argc, argv);
+ r = busctl_main(argc, argv);
finish:
/* make sure we terminate the bus connection first, and then close the
* pager, see issue #3543 for the details. */
- sd_bus_flush_close_unref(bus);
pager_close();
- strv_free(arg_matches);
+ arg_matches = strv_free(arg_matches);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index bd8c6a0059..1e92dabe0c 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -176,11 +176,9 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- if (!arg_no_pager) {
- r = pager_open(arg_no_pager, false);
- if (r > 0 && arg_full < 0)
- arg_full = true;
- }
+ r = pager_open(arg_no_pager, false);
+ if (r > 0 && arg_full < 0)
+ arg_full = true;
output_flags =
arg_all * OUTPUT_SHOW_ALL |
diff --git a/src/core/main.c b/src/core/main.c
index 4b2d149237..a4d2cdf759 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -2326,7 +2326,7 @@ int main(int argc, char *argv[]) {
goto finish;
if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS))
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (arg_action != ACTION_RUN)
skip_setup = true;
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index a4cc9c1db3..2f8b9b7cbf 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -51,18 +51,11 @@
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
+#include "verbs.h"
#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC)
static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
-
-static enum {
- ACTION_NONE,
- ACTION_INFO,
- ACTION_LIST,
- ACTION_DUMP,
- ACTION_GDB,
-} arg_action = ACTION_LIST;
static const char* arg_field = NULL;
static const char *arg_directory = NULL;
static bool arg_no_pager = false;
@@ -70,7 +63,6 @@ static int arg_no_legend = false;
static int arg_one = false;
static FILE* arg_output = NULL;
static bool arg_reverse = false;
-static char** arg_matches = NULL;
static bool arg_quiet = false;
static int add_match(sd_journal *j, const char *match) {
@@ -102,7 +94,7 @@ static int add_match(sd_journal *j, const char *match) {
return 0;
}
-static int add_matches(sd_journal *j) {
+static int add_matches(sd_journal *j, char **matches) {
char **match;
int r;
@@ -114,7 +106,7 @@ static int add_matches(sd_journal *j) {
if (r < 0)
return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
- STRV_FOREACH(match, arg_matches) {
+ STRV_FOREACH(match, matches) {
r = add_match(j, *match);
if (r < 0)
return r;
@@ -123,7 +115,44 @@ static int add_matches(sd_journal *j) {
return 0;
}
-static void help(void) {
+static int acquire_journal(sd_journal **ret, char **matches) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
+ int r;
+
+ assert(ret);
+
+ if (arg_directory) {
+ r = sd_journal_open_directory(&j, arg_directory, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
+ } else {
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open journal: %m");
+ }
+
+ r = journal_access_check_and_warn(j, arg_quiet, true);
+ if (r < 0)
+ return r;
+
+ r = add_matches(j, matches);
+ if (r < 0)
+ return r;
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *filter;
+
+ filter = journal_make_match_string(j);
+ log_debug("Journal filter: %s", filter);
+ }
+
+ *ret = j;
+ j = NULL;
+
+ return 0;
+}
+
+static int help(void) {
printf("%s [OPTIONS...]\n\n"
"List or retrieve coredumps from the journal.\n\n"
"Flags:\n"
@@ -145,6 +174,8 @@ static void help(void) {
" dump [MATCHES...] Print first matching coredump to stdout\n"
" gdb [MATCHES...] Start gdb for the first matching coredump\n"
, program_invocation_short_name);
+
+ return 0;
}
static int parse_argv(int argc, char *argv[]) {
@@ -177,12 +208,9 @@ static int parse_argv(int argc, char *argv[]) {
while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0)
switch(c) {
case 'h':
- arg_action = ACTION_NONE;
- help();
- return 0;
+ return help();
case ARG_VERSION:
- arg_action = ACTION_NONE;
return version();
case ARG_NO_PAGER:
@@ -254,31 +282,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (optind < argc) {
- const char *cmd = argv[optind++];
- if (streq(cmd, "list"))
- arg_action = ACTION_LIST;
- else if (streq(cmd, "dump"))
- arg_action = ACTION_DUMP;
- else if (streq(cmd, "gdb"))
- arg_action = ACTION_GDB;
- else if (streq(cmd, "info"))
- arg_action = ACTION_INFO;
- else {
- log_error("Unknown action '%s'", cmd);
- return -EINVAL;
- }
- }
-
- if (arg_field && arg_action != ACTION_LIST) {
- log_error("Option --field/-F only makes sense with list");
- return -EINVAL;
- }
-
- if (optind < argc)
- arg_matches = argv + optind;
-
- return 0;
+ return 1;
}
static int retrieve(const void *data,
@@ -631,10 +635,10 @@ static int focus(sd_journal *j) {
return r;
}
-static int print_entry(sd_journal *j, unsigned n_found) {
+static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) {
assert(j);
- if (arg_action == ACTION_INFO)
+ if (verb_is_info)
return print_info(stdout, j, n_found);
else if (arg_field)
return print_field(stdout, j);
@@ -642,11 +646,19 @@ static int print_entry(sd_journal *j, unsigned n_found) {
return print_list(stdout, j, n_found);
}
-static int dump_list(sd_journal *j) {
+static int dump_list(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
unsigned n_found = 0;
+ bool verb_is_info;
int r;
- assert(j);
+ verb_is_info = (argc >= 1 && streq(argv[0], "info"));
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_no_pager, false);
/* The coredumps are likely to compressed, and for just
* listing them we don't need to decompress them, so let's
@@ -658,7 +670,7 @@ static int dump_list(sd_journal *j) {
if (r < 0)
return r;
- return print_entry(j, 0);
+ return print_entry(j, 0, verb_is_info);
} else {
if (arg_since != USEC_INFINITY && !arg_reverse)
r = sd_journal_seek_realtime_usec(j, arg_since);
@@ -703,7 +715,7 @@ static int dump_list(sd_journal *j) {
continue;
}
- r = print_entry(j, n_found++);
+ r = print_entry(j, n_found++, verb_is_info);
if (r < 0)
return r;
}
@@ -856,10 +868,18 @@ error:
return r;
}
-static int dump_core(sd_journal* j) {
+static int dump_core(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
- assert(j);
+ if (arg_field) {
+ log_error("Option --field/-F only makes sense with list");
+ return -EINVAL;
+ }
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
r = focus(j);
if (r < 0)
@@ -878,7 +898,8 @@ static int dump_core(sd_journal* j) {
return 0;
}
-static int run_gdb(sd_journal *j) {
+static int run_gdb(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
_cleanup_free_ char *exe = NULL, *path = NULL;
bool unlink_path = false;
const char *data;
@@ -886,7 +907,14 @@ static int run_gdb(sd_journal *j) {
pid_t pid;
int r;
- assert(j);
+ if (arg_field) {
+ log_error("Option --field/-F only makes sense with list");
+ return -EINVAL;
+ }
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
r = focus(j);
if (r < 0)
@@ -1007,73 +1035,35 @@ static int check_units_active(void) {
return c;
}
+static int coredumpctl_main(int argc, char *argv[]) {
+
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list },
+ { "info", VERB_ANY, VERB_ANY, 0, dump_list },
+ { "dump", VERB_ANY, VERB_ANY, 0, dump_core },
+ { "gdb", VERB_ANY, VERB_ANY, 0, run_gdb },
+ {}
+ };
+
+ return dispatch_verb(argc, argv, verbs, NULL);
+}
+
int main(int argc, char *argv[]) {
- _cleanup_(sd_journal_closep) sd_journal*j = NULL;
- int r = 0, units_active;
+ int r, units_active;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
- if (r < 0)
- goto end;
-
- if (arg_action == ACTION_NONE)
+ if (r <= 0)
goto end;
sigbus_install();
- if (arg_directory) {
- r = sd_journal_open_directory(&j, arg_directory, 0);
- if (r < 0) {
- log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
- goto end;
- }
- } else {
- r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
- if (r < 0) {
- log_error_errno(r, "Failed to open journal: %m");
- goto end;
- }
- }
-
- r = journal_access_check_and_warn(j, arg_quiet, true);
- if (r < 0)
- goto end;
-
- r = add_matches(j);
- if (r < 0)
- goto end;
-
- if (DEBUG_LOGGING) {
- _cleanup_free_ char *filter;
-
- filter = journal_make_match_string(j);
- log_debug("Journal filter: %s", filter);
- }
-
units_active = check_units_active(); /* error is treated the same as 0 */
- switch(arg_action) {
-
- case ACTION_LIST:
- case ACTION_INFO:
- pager_open(arg_no_pager, false);
- r = dump_list(j);
- break;
-
- case ACTION_DUMP:
- r = dump_core(j);
- break;
-
- case ACTION_GDB:
- r = run_gdb(j);
- break;
-
- default:
- assert_not_reached("Shouldn't be here");
- }
+ r = coredumpctl_main(argc, argv);
if (units_active > 0)
printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n",
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 4fe89ff9b0..49d9f0bb03 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -662,7 +662,7 @@ int main(int argc, char *argv[]) {
else if (arg_diff)
arg_flags |= SHOW_OVERRIDDEN;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (optind < argc) {
int i;
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index e06b111b43..baa48c7f71 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -34,6 +34,7 @@
#include "hostname-util.h"
#include "spawn-polkit-agent.h"
#include "util.h"
+#include "verbs.h"
static bool arg_ask_password = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@@ -43,19 +44,19 @@ static bool arg_pretty = false;
static bool arg_static = false;
typedef struct StatusInfo {
- char *hostname;
- char *static_hostname;
- char *pretty_hostname;
- char *icon_name;
- char *chassis;
- char *deployment;
- char *location;
- char *kernel_name;
- char *kernel_release;
- char *os_pretty_name;
- char *os_cpe_name;
- char *virtualization;
- char *architecture;
+ const char *hostname;
+ const char *static_hostname;
+ const char *pretty_hostname;
+ const char *icon_name;
+ const char *chassis;
+ const char *deployment;
+ const char *location;
+ const char *kernel_name;
+ const char *kernel_release;
+ const char *os_pretty_name;
+ const char *os_cpe_name;
+ const char *virtualization;
+ const char *architecture;
} StatusInfo;
static void print_status_info(StatusInfo *i) {
@@ -162,6 +163,7 @@ static int show_all_names(sd_bus *bus, sd_bus_error *error) {
{}
};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *host_message = NULL, *manager_message = NULL;
int r;
r = bus_map_all_properties(bus,
@@ -169,42 +171,28 @@ static int show_all_names(sd_bus *bus, sd_bus_error *error) {
"/org/freedesktop/hostname1",
hostname_map,
error,
+ &host_message,
&info);
if (r < 0)
- goto fail;
+ return r;
- bus_map_all_properties(bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- manager_map,
- error,
- &info);
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ manager_map,
+ error,
+ &manager_message,
+ &info);
print_status_info(&info);
-fail:
- free(info.hostname);
- free(info.static_hostname);
- free(info.pretty_hostname);
- free(info.icon_name);
- free(info.chassis);
- free(info.deployment);
- free(info.location);
- free(info.kernel_name);
- free(info.kernel_release);
- free(info.os_pretty_name);
- free(info.os_cpe_name);
- free(info.virtualization);
- free(info.architecture);
-
return r;
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
+static int show_status(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
int r;
- assert(args);
-
if (arg_pretty || arg_static || arg_transient) {
const char *attr;
@@ -247,14 +235,12 @@ static int set_simple_string(sd_bus *bus, const char *method, const char *value)
return r;
}
-static int set_hostname(sd_bus *bus, char **args, unsigned n) {
+static int set_hostname(int argc, char **argv, void *userdata) {
_cleanup_free_ char *h = NULL;
- const char *hostname = args[1];
+ const char *hostname = argv[1];
+ sd_bus *bus = userdata;
int r;
- assert(args);
- assert(n == 2);
-
if (!arg_pretty && !arg_static && !arg_transient)
arg_pretty = arg_static = arg_transient = true;
@@ -301,35 +287,23 @@ static int set_hostname(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int set_icon_name(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetIconName", args[1]);
+static int set_icon_name(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetIconName", argv[1]);
}
-static int set_chassis(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetChassis", args[1]);
+static int set_chassis(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetChassis", argv[1]);
}
-static int set_deployment(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetDeployment", args[1]);
+static int set_deployment(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetDeployment", argv[1]);
}
-static int set_location(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetLocation", args[1]);
+static int set_location(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetLocation", argv[1]);
}
-static void help(void) {
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system hostname.\n\n"
" -h --help Show this help\n"
@@ -348,6 +322,12 @@ static void help(void) {
" set-deployment NAME Set deployment environment for host\n"
" set-location NAME Set location for host\n"
, program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -382,8 +362,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -426,82 +405,18 @@ static int parse_argv(int argc, char *argv[]) {
static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-hostname", EQUAL, 2, set_hostname },
- { "set-icon-name", EQUAL, 2, set_icon_name },
- { "set-chassis", EQUAL, 2, set_chassis },
- { "set-deployment", EQUAL, 2, set_deployment },
- { "set-location", EQUAL, 2, set_location },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "set-hostname", 2, 2, 0, set_hostname },
+ { "set-icon-name", 2, 2, 0, set_icon_name },
+ { "set-chassis", 2, 2, 0, set_chassis },
+ { "set-deployment", 2, 2, 0, set_deployment },
+ { "set-location", 2, 2, 0, set_location },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char *argv[]) {
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index f27f60e977..f579ef737e 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -753,7 +753,7 @@ static int parse_argv(int argc, char *argv[]) {
}
static int hwdb_main(int argc, char *argv[]) {
- const Verb verbs[] = {
+ static const Verb verbs[] = {
{ "update", 1, 1, 0, hwdb_update },
{ "query", 2, 2, 0, hwdb_query },
{},
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index e0ad0e1d11..3c9c6df07d 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -316,7 +316,7 @@ static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset
static void help(void) {
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
printf("%s [OPTIONS...] [MATCHES...]\n\n"
"Query the journal.\n\n"
@@ -1369,7 +1369,7 @@ static int list_boots(sd_journal *j) {
if (count == 0)
return count;
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
/* numbers are one less, but we need an extra char for the sign */
w = DECIMAL_STR_WIDTH(count - 1) + 1;
@@ -2135,7 +2135,7 @@ int main(int argc, char *argv[]) {
} else {
bool oneline = arg_action == ACTION_LIST_CATALOG;
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
if (optind < argc)
r = catalog_list_items(stdout, database, oneline, argv + optind);
@@ -2492,7 +2492,7 @@ int main(int argc, char *argv[]) {
need_seek = true;
if (!arg_follow)
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
if (!arg_quiet && (arg_lines != 0 || arg_follow)) {
usec_t start, end;
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index af39e431f5..550e97b3ed 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -39,6 +39,7 @@
#include "spawn-polkit-agent.h"
#include "strv.h"
#include "util.h"
+#include "verbs.h"
#include "virt.h"
static bool arg_no_pager = false;
@@ -49,23 +50,17 @@ static bool arg_convert = true;
typedef struct StatusInfo {
char **locale;
- char *vconsole_keymap;
- char *vconsole_keymap_toggle;
- char *x11_layout;
- char *x11_model;
- char *x11_variant;
- char *x11_options;
+ const char *vconsole_keymap;
+ const char *vconsole_keymap_toggle;
+ const char *x11_layout;
+ const char *x11_model;
+ const char *x11_variant;
+ const char *x11_options;
} StatusInfo;
static void status_info_clear(StatusInfo *info) {
if (info) {
strv_free(info->locale);
- free(info->vconsole_keymap);
- free(info->vconsole_keymap_toggle);
- free(info->x11_layout);
- free(info->x11_model);
- free(info->x11_variant);
- free(info->x11_options);
zero(*info);
}
}
@@ -142,7 +137,7 @@ static void print_status_info(StatusInfo *i) {
printf(" X11 Options: %s\n", i->x11_options);
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
+static int show_status(int argc, char **argv, void *userdata) {
_cleanup_(status_info_clear) StatusInfo info = {};
static const struct bus_properties_map map[] = {
{ "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
@@ -157,6 +152,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
@@ -166,6 +163,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
"/org/freedesktop/locale1",
map,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -176,13 +174,13 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int set_locale(sd_bus *bus, char **args, unsigned n) {
+static int set_locale(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
- assert(args);
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
@@ -196,7 +194,7 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_append_strv(m, args + 1);
+ r = sd_bus_message_append_strv(m, argv + 1);
if (r < 0)
return bus_log_create_error(r);
@@ -213,39 +211,32 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int list_locales(sd_bus *bus, char **args, unsigned n) {
+static int list_locales(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
int r;
- assert(args);
-
r = get_locales(&l);
if (r < 0)
return log_error_errno(r, "Failed to read list of locales: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(l);
return 0;
}
-static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
+static int set_vconsole_keymap(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *map, *toggle_map;
+ sd_bus *bus = userdata;
int r;
assert(bus);
- assert(args);
-
- if (n > 3) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- map = args[1];
- toggle_map = n > 2 ? args[2] : "";
+ map = argv[1];
+ toggle_map = argc > 2 ? argv[2] : "";
r = sd_bus_call_method(
bus,
@@ -262,42 +253,33 @@ static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
+static int list_vconsole_keymaps(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
int r;
- assert(args);
-
r = get_keymaps(&l);
if (r < 0)
return log_error_errno(r, "Failed to read list of keymaps: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(l);
return 0;
}
-static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
+static int set_x11_keymap(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *layout, *model, *variant, *options;
+ sd_bus *bus = userdata;
int r;
- assert(bus);
- assert(args);
-
- if (n > 5) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- layout = args[1];
- model = n > 2 ? args[2] : "";
- variant = n > 3 ? args[3] : "";
- options = n > 4 ? args[4] : "";
+ layout = argv[1];
+ model = argc > 2 ? argv[2] : "";
+ variant = argc > 3 ? argv[3] : "";
+ options = argc > 4 ? argv[4] : "";
r = sd_bus_call_method(
bus,
@@ -315,7 +297,7 @@ static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
+static int list_x11_keymaps(int argc, char **argv, void *userdata) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **list = NULL;
char line[LINE_MAX];
@@ -328,22 +310,17 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
} state = NONE, look_for;
int r;
- if (n > 2) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
if (!f)
return log_error_errno(errno, "Failed to open keyboard mapping list. %m");
- if (streq(args[0], "list-x11-keymap-models"))
+ if (streq(argv[0], "list-x11-keymap-models"))
look_for = MODELS;
- else if (streq(args[0], "list-x11-keymap-layouts"))
+ else if (streq(argv[0], "list-x11-keymap-layouts"))
look_for = LAYOUTS;
- else if (streq(args[0], "list-x11-keymap-variants"))
+ else if (streq(argv[0], "list-x11-keymap-variants"))
look_for = VARIANTS;
- else if (streq(args[0], "list-x11-keymap-options"))
+ else if (streq(argv[0], "list-x11-keymap-options"))
look_for = OPTIONS;
else
assert_not_reached("Wrong parameter");
@@ -376,7 +353,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
w = l + strcspn(l, WHITESPACE);
- if (n > 1) {
+ if (argc > 1) {
char *e;
if (*w == 0)
@@ -392,7 +369,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
*e = 0;
- if (!streq(w, args[1]))
+ if (!streq(w, argv[1]))
continue;
} else
*w = 0;
@@ -410,13 +387,13 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
strv_sort(list);
strv_uniq(list);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(list);
return 0;
}
-static void help(void) {
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system locale and keyboard settings.\n\n"
" -h --help Show this help\n"
@@ -440,6 +417,12 @@ static void help(void) {
" Show known X11 keyboard mapping variants\n"
" list-x11-keymap-options Show known X11 keyboard mapping options\n"
, program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -472,8 +455,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -512,86 +494,22 @@ static int parse_argv(int argc, char *argv[]) {
static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-locale", MORE, 2, set_locale },
- { "list-locales", EQUAL, 1, list_locales },
- { "set-keymap", MORE, 2, set_vconsole_keymap },
- { "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
- { "set-x11-keymap", MORE, 2, set_x11_keymap },
- { "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps },
- { "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps },
- { "list-x11-keymap-variants", LESS, 2, list_x11_keymaps },
- { "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "set-locale", 2, VERB_ANY, 0, set_locale },
+ { "list-locales", VERB_ANY, 1, 0, list_locales },
+ { "set-keymap", 2, 3, 0, set_vconsole_keymap },
+ { "list-keymaps", VERB_ANY, 1, 0, list_vconsole_keymaps },
+ { "set-x11-keymap", 2, 5, 0, set_x11_keymap },
+ { "list-x11-keymap-models", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "list-x11-keymap-layouts", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "list-x11-keymap-variants", VERB_ANY, 2, 0, list_x11_keymaps },
+ { "list-x11-keymap-options", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char*argv[]) {
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index c811ee6c5e..7554faeda3 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -111,7 +111,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -186,7 +186,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -231,7 +231,7 @@ static int list_seats(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -307,77 +307,52 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
}
typedef struct SessionStatusInfo {
- char *id;
+ const char *id;
uid_t uid;
- char *name;
+ const char *name;
struct dual_timestamp timestamp;
unsigned int vtnr;
- char *seat;
- char *tty;
- char *display;
- int remote;
- char *remote_host;
- char *remote_user;
- char *service;
+ const char *seat;
+ const char *tty;
+ const char *display;
+ bool remote;
+ const char *remote_host;
+ const char *remote_user;
+ const char *service;
pid_t leader;
- char *type;
- char *class;
- char *state;
- char *scope;
- char *desktop;
+ const char *type;
+ const char *class;
+ const char *state;
+ const char *scope;
+ const char *desktop;
} SessionStatusInfo;
typedef struct UserStatusInfo {
uid_t uid;
- int linger;
- char *name;
+ bool linger;
+ const char *name;
struct dual_timestamp timestamp;
- char *state;
+ const char *state;
char **sessions;
- char *display;
- char *slice;
+ const char *display;
+ const char *slice;
} UserStatusInfo;
typedef struct SeatStatusInfo {
- char *id;
- char *active_session;
+ const char *id;
+ const char *active_session;
char **sessions;
} SeatStatusInfo;
-static void session_status_info_clear(SessionStatusInfo *info) {
- if (info) {
- free(info->id);
- free(info->name);
- free(info->seat);
- free(info->tty);
- free(info->display);
- free(info->remote_host);
- free(info->remote_user);
- free(info->service);
- free(info->type);
- free(info->class);
- free(info->state);
- free(info->scope);
- free(info->desktop);
- zero(*info);
- }
-}
-
static void user_status_info_clear(UserStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->state);
strv_free(info->sessions);
- free(info->display);
- free(info->slice);
zero(*info);
}
}
static void seat_status_info_clear(SeatStatusInfo *info) {
if (info) {
- free(info->id);
- free(info->active_session);
strv_free(info->sessions);
zero(*info);
}
@@ -395,22 +370,9 @@ static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_mess
if (r < 0)
return r;
- if (IN_SET(contents[0], 's', 'o')) {
- const char *s;
- char **p = (char **) userdata;
-
- r = sd_bus_message_read_basic(m, contents[0], &s);
- if (r < 0)
- return r;
-
- r = free_and_strdup(p, s);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_read_basic(m, contents[0], userdata);
- if (r < 0)
- return r;
- }
+ r = sd_bus_message_read_basic(m, contents[0], userdata);
+ if (r < 0)
+ return r;
r = sd_bus_message_skip(m, contents+1);
if (r < 0)
@@ -471,12 +433,13 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
- _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
+ SessionStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -601,12 +564,13 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -676,10 +640,11 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -723,40 +688,41 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
#define property(name, fmt, ...) \
do { \
- if (arg_value) \
+ if (value) \
printf(fmt "\n", __VA_ARGS__); \
else \
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char type;
+ const char *contents;
int r;
assert(name);
assert(m);
- assert(contents);
- if (arg_property && !strv_find(arg_property, name))
- /* skip what we didn't read */
- return sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
- switch (contents[0]) {
+ switch (type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
+ if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
+ if (all || !isempty(s))
property(name, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
+ } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
uint32_t uid;
r = sd_bus_message_read(m, "(uo)", &uid, NULL);
@@ -769,14 +735,13 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
}
property(name, UID_FMT, uid);
- return 0;
+ return 1;
}
-
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
const char *s;
bool space = false;
@@ -784,7 +749,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- if (!arg_value)
+ if (!value)
printf("%s=", name);
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
@@ -792,7 +757,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
space = true;
}
- if (space || !arg_value)
+ if (space || !value)
printf("\n");
if (r < 0)
@@ -802,25 +767,11 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
}
-
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
-
return 0;
}
@@ -833,58 +784,12 @@ static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
assert(path);
assert(new_line);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = print_property(name, reply, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
+ r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -903,7 +808,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self";
@@ -955,7 +860,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -1015,7 +920,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index e695bdbab4..78a7ce2fa3 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -207,7 +207,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
assert(bus);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
@@ -363,7 +363,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
assert(bus);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
@@ -639,12 +639,12 @@ static int print_uid_shift(sd_bus *bus, const char *name) {
}
typedef struct MachineStatusInfo {
- char *name;
+ const char *name;
sd_id128_t id;
- char *class;
- char *service;
- char *unit;
- char *root_directory;
+ const char *class;
+ const char *service;
+ const char *unit;
+ const char *root_directory;
pid_t leader;
struct dual_timestamp timestamp;
int *netif;
@@ -653,11 +653,6 @@ typedef struct MachineStatusInfo {
static void machine_status_info_clear(MachineStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->class);
- free(info->service);
- free(info->unit);
- free(info->root_directory);
free(info->netif);
zero(*info);
}
@@ -803,6 +798,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(machine_status_info_clear) MachineStatusInfo info = {};
int r;
@@ -816,6 +812,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo
path,
map,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -841,7 +838,7 @@ static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -860,7 +857,7 @@ static int show_machine(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (properties && argc <= 1) {
@@ -994,10 +991,10 @@ static int print_image_machine_info(sd_bus *bus, const char *name) {
}
typedef struct ImageStatusInfo {
- char *name;
- char *path;
- char *type;
- int read_only;
+ const char *name;
+ const char *path;
+ const char *type;
+ bool read_only;
usec_t crtime;
usec_t mtime;
uint64_t usage;
@@ -1006,16 +1003,6 @@ typedef struct ImageStatusInfo {
uint64_t limit_exclusive;
} ImageStatusInfo;
-static void image_status_info_clear(ImageStatusInfo *info) {
- if (!info)
- return;
-
- free(info->name);
- free(info->path);
- free(info->type);
- zero(*info);
-}
-
static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
@@ -1093,7 +1080,8 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(image_status_info_clear) ImageStatusInfo info = {};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ ImageStatusInfo info = {};
int r;
assert(bus);
@@ -1105,6 +1093,7 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
path,
map,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -1119,20 +1108,11 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
}
typedef struct PoolStatusInfo {
- char *path;
+ const char *path;
uint64_t usage;
uint64_t limit;
} PoolStatusInfo;
-static void pool_status_info_clear(PoolStatusInfo *info) {
- if (info) {
- free(info->path);
- zero(*info);
- info->usage = -1;
- info->limit = -1;
- }
-}
-
static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) {
char bs[FORMAT_BYTES_MAX], *s;
@@ -1157,12 +1137,13 @@ static int show_pool_info(sd_bus *bus) {
{}
};
- _cleanup_(pool_status_info_clear) PoolStatusInfo info = {
+ PoolStatusInfo info = {
.usage = (uint64_t) -1,
.limit = (uint64_t) -1,
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -1172,6 +1153,7 @@ static int show_pool_info(sd_bus *bus) {
"/org/freedesktop/machine1",
map,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -1194,7 +1176,7 @@ static int show_image_properties(sd_bus *bus, const char *path, bool *new_line)
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -1213,7 +1195,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
@@ -2543,7 +2525,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
double progress;
int r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(bus,
"org.freedesktop.import1",
@@ -2758,7 +2740,7 @@ static int clean_images(int argc, char *argv[], void *userdata) {
}
static int help(int argc, char *argv[], void *userdata) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c
index 0cd9f07094..dd139740c2 100644
--- a/src/mount/mount-tool.c
+++ b/src/mount/mount-tool.c
@@ -1529,7 +1529,7 @@ static int list_devices(void) {
qsort_safe(items, n, sizeof(struct item), compare_item);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
fputs(ansi_underline(), stdout);
for (c = 0; c < _COLUMN_MAX; c++) {
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 14d8ecb03f..362f671417 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -273,7 +273,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (c < 0)
return c;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (arg_legend)
printf("%3s %-16s %-18s %-11s %-10s\n",
@@ -897,7 +897,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
_cleanup_free_ LinkInfo *links = NULL;
int r, c, i;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_netlink_open(&rtnl);
if (r < 0)
@@ -993,7 +993,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
if (c < 0)
return c;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (arg_legend)
printf("%-16s %-17s %-16s %-11s %-17s %-16s\n",
@@ -1156,11 +1156,11 @@ static int parse_argv(int argc, char *argv[]) {
}
static int networkctl_main(int argc, char *argv[]) {
- const Verb verbs[] = {
- { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
- { "status", VERB_ANY, VERB_ANY, 0, link_status },
- { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
- { "label", VERB_ANY, VERB_ANY, 0, list_address_labels},
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
+ { "status", VERB_ANY, VERB_ANY, 0, link_status },
+ { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
+ { "label", VERB_ANY, VERB_ANY, 0, list_address_labels },
{}
};
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 04f883654a..462ea7a2d5 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -1185,13 +1185,13 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
struct link_info {
uint64_t scopes_mask;
- char *llmnr;
- char *mdns;
- char *dnssec;
+ const char *llmnr;
+ const char *mdns;
+ const char *dnssec;
char **dns;
char **domains;
char **ntas;
- int dnssec_supported;
+ bool dnssec_supported;
} link_info = {};
static const struct bus_properties_map property_map[] = {
@@ -1207,6 +1207,7 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *ifi = NULL, *p = NULL;
char ifname[IF_NAMESIZE] = "";
char **i;
@@ -1235,13 +1236,14 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
p,
property_map,
&error,
+ &m,
&link_info);
if (r < 0) {
log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r));
goto finish;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (*empty_line)
fputc('\n', stdout);
@@ -1293,9 +1295,6 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
finish:
strv_free(link_info.dns);
strv_free(link_info.domains);
- free(link_info.llmnr);
- free(link_info.mdns);
- free(link_info.dnssec);
strv_free(link_info.ntas);
return r;
}
@@ -1418,16 +1417,25 @@ static int status_global(sd_bus *bus, bool *empty_line) {
char **dns;
char **domains;
char **ntas;
+ const char *llmnr;
+ const char *mdns;
+ const char *dnssec;
+ bool dnssec_supported;
} global_info = {};
static const struct bus_properties_map property_map[] = {
- { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
- { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
- { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
+ { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
+ { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
+ { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
+ { "LLMNR", "s", NULL, offsetof(struct global_info, llmnr) },
+ { "MulticastDNS", "s", NULL, offsetof(struct global_info, mdns) },
+ { "DNSSEC", "s", NULL, offsetof(struct global_info, dnssec) },
+ { "DNSSECSupported", "b", NULL, offsetof(struct global_info, dnssec_supported) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char **i;
int r;
@@ -1439,6 +1447,7 @@ static int status_global(sd_bus *bus, bool *empty_line) {
"/org/freedesktop/resolve1",
property_map,
&error,
+ &m,
&global_info);
if (r < 0) {
log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
@@ -1450,9 +1459,19 @@ static int status_global(sd_bus *bus, bool *empty_line) {
goto finish;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
+
+ printf(" LLMNR setting: %s\n"
+ "MulticastDNS setting: %s\n"
+ " DNSSEC setting: %s\n"
+ " DNSSEC supported: %s\n",
+ strna(global_info.llmnr),
+ strna(global_info.mdns),
+ strna(global_info.dnssec),
+ yes_no(global_info.dnssec_supported));
+
STRV_FOREACH(i, global_info.dns) {
printf(" %s %s\n",
i == global_info.dns ? "DNS Servers:" : " ",
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index ffd7c4824e..e7026d4320 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -31,6 +31,8 @@
#include "user-util.h"
#include "utf8.h"
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
+
static int reply_query_state(DnsQuery *q) {
switch (q->state) {
@@ -1425,6 +1427,23 @@ static int bus_property_get_dnssec_supported(
return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
}
+static int bus_property_get_dnssec_mode(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+
+ assert(reply);
+ assert(m);
+
+ return sd_bus_message_append(reply, "s", dnssec_mode_to_string(manager_get_dnssec_mode(m)));
+}
+
static int bus_property_get_ntas(
sd_bus *bus,
const char *path,
@@ -1814,10 +1833,13 @@ static int bus_method_unregister_service(sd_bus_message *message, void *userdata
static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
+ SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
+ SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
+ SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h
index 11ddae9d8d..49e4e257b4 100644
--- a/src/resolve/resolved-bus.h
+++ b/src/resolve/resolved-bus.h
@@ -24,3 +24,6 @@
int manager_connect_bus(Manager *m);
int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex);
+int bus_property_get_resolve_support(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/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
index 711dff0954..82a29289d2 100644
--- a/src/resolve/resolved-link-bus.c
+++ b/src/resolve/resolved-link-bus.c
@@ -28,8 +28,6 @@
#include "resolved-resolv-conf.h"
#include "strv.h"
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport);
-
static int property_get_dnssec_mode(
sd_bus *bus,
const char *path,
@@ -533,8 +531,8 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
- SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
- SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
+ SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0),
+ SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0),
SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0),
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0),
diff --git a/src/run/run.c b/src/run/run.c
index a30501169c..cfab3d6f97 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -876,6 +876,7 @@ static int run_context_update(RunContext *c, const char *path) {
path,
map,
&error,
+ NULL,
c);
if (r < 0) {
sd_event_exit(c->event, EXIT_FAILURE);
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 548e817105..8061af1865 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -656,15 +656,15 @@ int bus_connect_user_systemd(sd_bus **_bus) {
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
+int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
char type;
const char *contents;
int r;
assert(name);
- assert(property);
+ assert(m);
- r = sd_bus_message_peek_type(property, &type, &contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return r;
@@ -673,7 +673,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_STRING: {
const char *s;
- r = sd_bus_message_read_basic(property, type, &s);
+ r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
return r;
@@ -692,7 +692,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_BOOLEAN: {
int b;
- r = sd_bus_message_read_basic(property, type, &b);
+ r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
@@ -704,7 +704,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT64: {
uint64_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
@@ -781,7 +781,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT64: {
int64_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -793,7 +793,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT32: {
uint32_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
@@ -818,7 +818,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT32: {
int32_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -829,7 +829,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_DOUBLE: {
double d;
- r = sd_bus_message_read_basic(property, type, &d);
+ r = sd_bus_message_read_basic(m, type, &d);
if (r < 0)
return r;
@@ -842,11 +842,11 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
bool first = true;
const char *str;
- r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
if (r < 0)
return r;
- while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
+ while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
bool good;
if (first && !value)
@@ -868,7 +868,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
if (!first || all)
puts("");
- r = sd_bus_message_exit_container(property);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
@@ -878,7 +878,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
const uint8_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
if (r < 0)
return r;
@@ -900,7 +900,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
uint32_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
if (r < 0)
return r;
@@ -925,7 +925,97 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
return 0;
}
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
+int bus_message_print_all_properties(
+ sd_bus_message *m,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
+
+ int r;
+
+ assert(m);
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *name;
+ const char *contents;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
+ if (r < 0)
+ return r;
+
+ if (found_properties) {
+ r = set_ensure_allocated(found_properties, &string_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_put(*found_properties, name);
+ if (r < 0 && r != EEXIST)
+ return log_oom();
+ }
+
+ if (!filter || strv_find(filter, name)) {
+ r = sd_bus_message_peek_type(m, NULL, &contents);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
+ if (r < 0)
+ return r;
+
+ if (func)
+ r = func(name, m, value, all);
+ if (!func || r == 0)
+ r = bus_print_property(name, m, value, all);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ if (all)
+ printf("%s=[unprintable]\n", name);
+ /* skip what we didn't read */
+ r = sd_bus_message_skip(m, contents);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+ } else {
+ r = sd_bus_message_skip(m, "v");
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int bus_print_all_properties(
+ sd_bus *bus,
+ const char *dest,
+ const char *path,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
+
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -944,60 +1034,7 @@ int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, ch
if (r < 0)
return r;
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name;
- const char *contents;
-
- r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
- if (r < 0)
- return r;
-
- if (!filter || strv_find(filter, name)) {
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return r;
-
- r = bus_print_property(name, reply, value, all);
- if (r < 0)
- return r;
- if (r == 0) {
- if (all)
- printf("%s=[unprintable]\n", name);
- /* skip what we didn't read */
- r = sd_bus_message_skip(reply, contents);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_skip(reply, "v");
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return r;
-
- return 0;
+ return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
}
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
@@ -1020,7 +1057,7 @@ int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_err
return 0;
}
-static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata, bool copy_string) {
char type;
int r;
@@ -1031,7 +1068,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
switch (type) {
case SD_BUS_TYPE_STRING: {
- char **p = userdata;
+ const char **p = userdata;
const char *s;
r = sd_bus_message_read_basic(m, type, &s);
@@ -1041,7 +1078,11 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
if (isempty(s))
s = NULL;
- return free_and_strdup(p, s);
+ if (copy_string)
+ return free_and_strdup((char **) userdata, s);
+
+ *p = s;
+ return 0;
}
case SD_BUS_TYPE_ARRAY: {
@@ -1060,13 +1101,13 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
case SD_BUS_TYPE_BOOLEAN: {
unsigned b;
- int *p = userdata;
+ bool *p = userdata;
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
- *p = b;
+ *p = !!b;
return 0;
}
@@ -1111,6 +1152,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
int bus_message_map_all_properties(
sd_bus_message *m,
const struct bus_properties_map *map,
+ bool copy_string,
sd_bus_error *error,
void *userdata) {
@@ -1153,7 +1195,7 @@ int bus_message_map_all_properties(
if (map[i].set)
r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
else
- r = map_basic(sd_bus_message_get_bus(m), member, m, error, v);
+ r = map_basic(sd_bus_message_get_bus(m), member, m, error, v, copy_string);
if (r < 0)
return r;
@@ -1179,6 +1221,7 @@ int bus_message_map_all_properties(
int bus_message_map_properties_changed(
sd_bus_message *m,
const struct bus_properties_map *map,
+ bool copy_string,
sd_bus_error *error,
void *userdata) {
@@ -1188,7 +1231,7 @@ int bus_message_map_properties_changed(
assert(m);
assert(map);
- r = bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, copy_string, error, userdata);
if (r < 0)
return r;
@@ -1219,6 +1262,7 @@ int bus_map_all_properties(
const char *path,
const struct bus_properties_map *map,
sd_bus_error *error,
+ sd_bus_message **reply,
void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@@ -1241,7 +1285,14 @@ int bus_map_all_properties(
if (r < 0)
return r;
- return bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, !reply, error, userdata);
+ if (r < 0)
+ return r;
+
+ if (reply)
+ *reply = sd_bus_message_ref(m);
+
+ return r;
}
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index 8103f0e9a7..e42198ff1c 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -51,9 +51,9 @@ struct bus_properties_map {
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
-int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
-int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
-int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
+int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, bool copy_string, sd_bus_error *error, void *userdata);
+int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, bool copy_string, sd_bus_error *error, void *userdata);
+int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, sd_bus_message **reply, void *userdata);
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name);
@@ -76,8 +76,11 @@ int bus_connect_user_systemd(sd_bus **_bus);
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
+typedef int (*bus_message_print_t) (const char *name, sd_bus_message *m, bool value, bool all);
+
int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all);
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
+int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 0f383ec9e0..cae4ff023a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -82,6 +82,7 @@
#include "spawn-polkit-agent.h"
#include "special.h"
#include "stat-util.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-def.h"
@@ -250,21 +251,6 @@ static void release_busses(void) {
busses[w] = sd_bus_flush_close_unref(busses[w]);
}
-static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- char *s;
- const char **p = userdata;
- int r;
-
- r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s);
- if (r < 0)
- return r;
-
- if (!isempty(s))
- *p = s;
-
- return 0;
-}
-
static void ask_password_agent_open_if_enabled(void) {
/* Open the password agent as a child process if necessary */
@@ -791,7 +777,7 @@ static int list_units(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (r < 0)
@@ -1003,7 +989,7 @@ static int list_sockets(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
@@ -1310,7 +1296,7 @@ static int list_timers(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
@@ -1599,7 +1585,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
output_unit_file_list(units, c);
@@ -1652,91 +1638,73 @@ static int list_dependencies_print(const char *name, int level, unsigned int bra
static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
- static const char *dependencies[_DEPENDENCY_MAX] = {
- [DEPENDENCY_FORWARD] = "Requires\0"
- "Requisite\0"
- "Wants\0"
- "ConsistsOf\0"
- "BindsTo\0",
- [DEPENDENCY_REVERSE] = "RequiredBy\0"
- "RequisiteOf\0"
- "WantedBy\0"
- "PartOf\0"
- "BoundBy\0",
- [DEPENDENCY_AFTER] = "After\0",
- [DEPENDENCY_BEFORE] = "Before\0",
+ struct DependencyStatusInfo {
+ char **dep[5];
+ } info = {};
+
+ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = {
+ [DEPENDENCY_FORWARD] = {
+ { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
+ { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
+ { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
+ { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
+ {}
+ },
+ [DEPENDENCY_REVERSE] = {
+ { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
+ { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
+ { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
+ { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
+ {}
+ },
+ [DEPENDENCY_AFTER] = {
+ { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ {}
+ },
+ [DEPENDENCY_BEFORE] = {
+ { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ {}
+ },
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **ret = NULL;
_cleanup_free_ char *path = NULL;
- int r;
+ int i, r;
assert(bus);
assert(name);
assert(deps);
- assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
path = unit_dbus_path_from_name(name);
if (!path)
return log_oom();
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "org.freedesktop.systemd1.Unit");
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.systemd1",
+ path,
+ map[arg_dependency],
+ &error,
+ NULL,
+ &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *prop;
-
- r = sd_bus_message_read(reply, "s", &prop);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!nulstr_contains(dependencies[arg_dependency], prop)) {
- r = sd_bus_message_skip(reply, "v");
- if (r < 0)
- return bus_log_parse_error(r);
- } else {
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = bus_message_read_strv_extend(reply, &ret);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
+ if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) {
+ *deps = info.dep[0];
+ return 0;
}
- if (r < 0)
- return bus_log_parse_error(r);
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
+ for (i = 0; i < 5; i++) {
+ r = strv_extend_strv(&ret, info.dep[i], true);
+ if (r < 0)
+ return log_oom();
+ info.dep[i] = strv_free(info.dep[i]);
+ }
- *deps = strv_uniq(ret);
+ *deps = ret;
ret = NULL;
return 0;
@@ -1854,7 +1822,7 @@ static int list_dependencies(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
puts(u);
@@ -1924,7 +1892,7 @@ static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
bus = container;
}
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, NULL, mi);
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, NULL, NULL, mi);
if (r < 0)
return r;
@@ -2086,7 +2054,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
output_machines_list(machine_infos, r);
@@ -2258,7 +2226,7 @@ static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned
return;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
id_len = STRLEN("JOB");
unit_len = STRLEN("UNIT");
@@ -2373,7 +2341,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
output_jobs_list(bus, jobs, c, skipped);
return 0;
@@ -4425,354 +4393,165 @@ static void show_unit_help(UnitStatusInfo *i) {
log_info("Can't show: %s", *p);
}
-static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
+static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ uint32_t u;
int r;
- assert(name);
- assert(m);
- assert(i);
+ r = sd_bus_message_read(m, "u", &u);
+ if (r < 0)
+ return r;
- switch (contents[0]) {
-
- case SD_BUS_TYPE_STRING: {
- const char *s;
-
- r = sd_bus_message_read(m, "s", &s);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(s)) {
- if (streq(name, "Id"))
- i->id = s;
- else if (streq(name, "LoadState"))
- i->load_state = s;
- else if (streq(name, "ActiveState"))
- i->active_state = s;
- else if (streq(name, "SubState"))
- i->sub_state = s;
- else if (streq(name, "Description"))
- i->description = s;
- else if (streq(name, "FragmentPath"))
- i->fragment_path = s;
- else if (streq(name, "SourcePath"))
- i->source_path = s;
-#ifndef NOLEGACY
- else if (streq(name, "DefaultControlGroup")) {
- const char *e;
- e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
- if (e)
- i->control_group = e;
- }
-#endif
- else if (streq(name, "ControlGroup"))
- i->control_group = s;
- else if (streq(name, "StatusText"))
- i->status_text = s;
- else if (streq(name, "PIDFile"))
- i->pid_file = s;
- else if (streq(name, "SysFSPath"))
- i->sysfs_path = s;
- else if (streq(name, "Where"))
- i->where = s;
- else if (streq(name, "What"))
- i->what = s;
- else if (streq(name, "Following"))
- i->following = s;
- else if (streq(name, "UnitFileState"))
- i->unit_file_state = s;
- else if (streq(name, "UnitFilePreset"))
- i->unit_file_preset = s;
- else if (streq(name, "Result"))
- i->result = s;
- }
-
- break;
- }
-
- case SD_BUS_TYPE_BOOLEAN: {
- int b;
-
- r = sd_bus_message_read(m, "b", &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "Accept"))
- i->accept = b;
- else if (streq(name, "NeedDaemonReload"))
- i->need_daemon_reload = b;
- else if (streq(name, "ConditionResult"))
- i->condition_result = b;
- else if (streq(name, "AssertResult"))
- i->assert_result = b;
- else if (streq(name, "Transient"))
- i->transient = b;
-
- break;
- }
-
- case SD_BUS_TYPE_UINT32: {
- uint32_t u;
-
- r = sd_bus_message_read(m, "u", &u);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "MainPID")) {
- if (u > 0) {
- i->main_pid = (pid_t) u;
- i->running = true;
- }
- } else if (streq(name, "ControlPID"))
- i->control_pid = (pid_t) u;
- else if (streq(name, "ExecMainPID")) {
- if (u > 0)
- i->main_pid = (pid_t) u;
- } else if (streq(name, "NAccepted"))
- i->n_accepted = u;
- else if (streq(name, "NConnections"))
- i->n_connections = u;
-
- break;
- }
-
- case SD_BUS_TYPE_INT32: {
- int32_t j;
-
- r = sd_bus_message_read(m, "i", &j);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "ExecMainCode"))
- i->exit_code = (int) j;
- else if (streq(name, "ExecMainStatus"))
- i->exit_status = (int) j;
- else if (streq(name, "StatusErrno"))
- i->status_errno = (int) j;
-
- break;
- }
-
- case SD_BUS_TYPE_UINT64: {
- uint64_t u;
-
- r = sd_bus_message_read(m, "t", &u);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "ExecMainStartTimestamp"))
- i->start_timestamp = (usec_t) u;
- else if (streq(name, "ExecMainExitTimestamp"))
- i->exit_timestamp = (usec_t) u;
- else if (streq(name, "ActiveEnterTimestamp"))
- i->active_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveEnterTimestamp"))
- i->inactive_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestamp"))
- i->inactive_exit_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestampMonotonic"))
- i->inactive_exit_timestamp_monotonic = (usec_t) u;
- else if (streq(name, "ActiveExitTimestamp"))
- i->active_exit_timestamp = (usec_t) u;
- else if (streq(name, "ConditionTimestamp"))
- i->condition_timestamp = (usec_t) u;
- else if (streq(name, "AssertTimestamp"))
- i->assert_timestamp = (usec_t) u;
- else if (streq(name, "MemoryCurrent"))
- i->memory_current = u;
- else if (streq(name, "MemoryLow"))
- i->memory_low = u;
- else if (streq(name, "MemoryHigh"))
- i->memory_high = u;
- else if (streq(name, "MemoryMax"))
- i->memory_max = u;
- else if (streq(name, "MemorySwapMax"))
- i->memory_swap_max = u;
- else if (streq(name, "MemoryLimit"))
- i->memory_limit = u;
- else if (streq(name, "TasksCurrent"))
- i->tasks_current = u;
- else if (streq(name, "TasksMax"))
- i->tasks_max = u;
- else if (streq(name, "CPUUsageNSec"))
- i->cpu_usage_nsec = u;
- else if (streq(name, "NextElapseUSecMonotonic"))
- i->next_elapse_monotonic = u;
- else if (streq(name, "NextElapseUSecRealtime"))
- i->next_elapse_real = u;
- else if (streq(name, "IPIngressBytes"))
- i->ip_ingress_bytes = u;
- else if (streq(name, "IPEgressBytes"))
- i->ip_egress_bytes = u;
-
- break;
- }
-
- case SD_BUS_TYPE_ARRAY:
-
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
- _cleanup_free_ ExecStatusInfo *info = NULL;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return log_oom();
-
- while ((r = exec_status_info_deserialize(m, info)) > 0) {
-
- info->name = strdup(name);
- if (!info->name)
- return log_oom();
-
- LIST_PREPEND(exec, i->exec, info);
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return log_oom();
- }
-
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
- const char *type, *path;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
-
- r = strv_extend(&i->listen, type);
- if (r < 0)
- return r;
-
- r = strv_extend(&i->listen, path);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
-
- r = sd_bus_message_read_strv(m, &i->dropin_paths);
- if (r < 0)
- return bus_log_parse_error(r);
-
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
-
- r = sd_bus_message_read_strv(m, &i->documentation);
- if (r < 0)
- return bus_log_parse_error(r);
-
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
- _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
-
- log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state);
-
- c = new0(UnitCondition, 1);
- if (!c)
- return log_oom();
-
- c->name = strdup(cond);
- c->param = strdup(param);
- if (!c->name || !c->param)
- return log_oom();
-
- c->trigger = trigger;
- c->negate = negate;
- c->tristate = state;
-
- LIST_PREPEND(conditions, i->conditions, c);
- c = NULL;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
- log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
- if (state < 0 && (!trigger || !i->failed_assert)) {
- i->failed_assert = cond;
- i->failed_assert_trigger = trigger;
- i->failed_assert_negate = negate;
- i->failed_assert_parameter = param;
- }
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- } else
- goto skip;
-
- break;
-
- case SD_BUS_TYPE_STRUCT_BEGIN:
-
- if (streq(name, "LoadError")) {
- const char *n, *message;
-
- r = sd_bus_message_read(m, "(ss)", &n, &message);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(message))
- i->load_error = message;
- } else
- goto skip;
-
- break;
-
- default:
- goto skip;
- }
+ i->main_pid = (pid_t) u;
+ i->running = u > 0;
return 0;
+}
-skip:
- r = sd_bus_message_skip(m, contents);
+static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *n, *message;
+ const char **p = userdata;
+ int r;
+
+ r = sd_bus_message_read(m, "(ss)", &n, &message);
if (r < 0)
- return bus_log_parse_error(r);
+ return r;
+
+ if (!isempty(message))
+ *p = message;
+
+ return 0;
+}
+
+static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *type, *path;
+ char ***p = userdata;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
+
+ r = strv_extend(p, type);
+ if (r < 0)
+ return r;
+
+ r = strv_extend(p, path);
+ if (r < 0)
+ return r;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
+ _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
+
+ c = new0(UnitCondition, 1);
+ if (!c)
+ return -ENOMEM;
+
+ c->name = strdup(cond);
+ c->param = strdup(param);
+ if (!c->name || !c->param)
+ return -ENOMEM;
+
+ c->trigger = trigger;
+ c->negate = negate;
+ c->tristate = state;
+
+ LIST_PREPEND(conditions, i->conditions, c);
+ c = NULL;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
+
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
+ if (state < 0 && (!trigger || !i->failed_assert)) {
+ i->failed_assert = cond;
+ i->failed_assert_trigger = trigger;
+ i->failed_assert_negate = negate;
+ i->failed_assert_parameter = param;
+ }
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ _cleanup_free_ ExecStatusInfo *info = NULL;
+ UnitStatusInfo *i = userdata;
+ int r;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
+ if (r < 0)
+ return r;
+
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
+
+ while ((r = exec_status_info_deserialize(m, info)) > 0) {
+
+ info->name = strdup(member);
+ if (!info->name)
+ return -ENOMEM;
+
+ LIST_PREPEND(exec, i->exec, info);
+
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
+ }
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
return 0;
}
@@ -4785,7 +4564,9 @@ skip:
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char bus_type;
+ const char *contents;
int r;
assert(name);
@@ -4794,17 +4575,15 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
/* This is a low-level property printer, see
* print_status_info() for the nicer output */
- if (arg_properties && !strv_find(arg_properties, name)) {
- /* skip what we didn't read */
- r = sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &bus_type, &contents);
+ if (r < 0)
return r;
- }
- switch (contents[0]) {
+ switch (bus_type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
+ if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
uint32_t u;
r = sd_bus_message_read(m, "(uo)", &u, NULL);
@@ -4813,34 +4592,34 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (u > 0)
print_prop(name, "%"PRIu32, u);
- else if (arg_all)
+ else if (all)
print_prop(name, "%s", "");
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
+ if (all || !isempty(s))
print_prop(name, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
const char *a = NULL, *b = NULL;
r = sd_bus_message_read(m, "(ss)", &a, &b);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(a) || !isempty(b))
+ if (all || !isempty(a) || !isempty(b))
print_prop(name, "%s \"%s\"", strempty(a), strempty(b));
- return 0;
+ return 1;
} else if (streq_ptr(name, "SystemCallFilter")) {
_cleanup_strv_free_ char **l = NULL;
int whitelist;
@@ -4861,11 +4640,11 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || whitelist || !strv_isempty(l)) {
+ if (all || whitelist || !strv_isempty(l)) {
bool first = true;
char **i;
- if (!arg_value) {
+ if (!value) {
fputs(name, stdout);
fputc('=', stdout);
}
@@ -4884,14 +4663,14 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
fputc('\n', stdout);
}
- return 0;
+ return 1;
}
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
const char *path;
int ignore;
@@ -4909,9 +4688,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
const char *type, *path;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -4927,9 +4706,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
const char *type, *path;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -4945,21 +4724,21 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
const char *base;
- uint64_t value, next_elapse;
+ uint64_t v, next_elapse;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
+ while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
print_prop(name, "{ %s=%s ; next_elapse=%s }", base,
- format_timespan(timespan1, sizeof(timespan1), value, 0),
+ format_timespan(timespan1, sizeof(timespan1), v, 0),
format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
}
if (r < 0)
@@ -4969,9 +4748,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
const char *base, *spec;
uint64_t next_elapse;
@@ -4992,9 +4771,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
ExecStatusInfo info = {};
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
@@ -5029,9 +4808,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
const char *path, *rwm;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -5047,9 +4826,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
const char *path;
uint64_t weight;
@@ -5067,9 +4846,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
(cgroup_io_limit_type_from_string(name) >= 0 ||
STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
const char *path;
@@ -5088,9 +4867,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
+ } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
_cleanup_free_ char *h = NULL;
const void *p;
size_t sz;
@@ -5106,40 +4885,110 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
print_prop(name, "%s", h);
- return 0;
+ return 1;
}
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
-
return 0;
}
+typedef enum SystemctlShowMode{
+ SYSTEMCTL_SHOW_PROPERTIES,
+ SYSTEMCTL_SHOW_STATUS,
+ SYSTEMCTL_SHOW_HELP,
+ _SYSTEMCTL_SHOW_MODE_MAX,
+ _SYSTEMCTL_SHOW_MODE_INVALID = -1,
+} SystemctlShowMode;
+
+static const char* const systemctl_show_mode_table[] = {
+ [SYSTEMCTL_SHOW_PROPERTIES] = "show",
+ [SYSTEMCTL_SHOW_STATUS] = "status",
+ [SYSTEMCTL_SHOW_HELP] = "help",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
+
static int show_one(
- const char *verb,
sd_bus *bus,
const char *path,
const char *unit,
- bool show_properties,
+ SystemctlShowMode show_mode,
bool *new_line,
bool *ellipsized) {
static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) },
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ {}
+ }, status_map[] = {
+ { "Id", "s", NULL, offsetof(UnitStatusInfo, id) },
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) },
+ { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
+ { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) },
+ { "Description", "s", NULL, offsetof(UnitStatusInfo, description) },
+ { "Following", "s", NULL, offsetof(UnitStatusInfo, following) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) },
+ { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) },
+ { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) },
+ { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) },
+ { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) },
+ { "Result", "s", NULL, offsetof(UnitStatusInfo, result) },
+ { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) },
+ { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
+ { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) },
+ { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) },
+ { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) },
+ { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) },
+ { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) },
+ { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) },
+ { "MainPID", "u", map_main_pid, 0 },
+ { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) },
+ { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) },
+ { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) },
+ { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) },
+ { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) },
+ { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) },
+ { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) },
+ { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) },
+ { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) },
+ { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) },
+ { "Conditions", "a(sbbsi)", map_conditions, 0 },
+ { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) },
+ { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) },
+ { "Asserts", "a(sbbsi)", map_asserts, 0 },
+ { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) },
+ { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) },
+ { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) },
+ { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) },
+ { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) },
+ { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) },
+ { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) },
+ { "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
+ { "What", "s", NULL, offsetof(UnitStatusInfo, what) },
+ { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
+ { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
+ { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },
+ { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) },
+ { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) },
+ { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) },
+ { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) },
+ { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) },
+ { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
+ { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
+ { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
+ { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStart", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecReload", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStop", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 },
{}
};
@@ -5158,6 +5007,7 @@ static int show_one(
.ip_ingress_bytes = (uint64_t) -1,
.ip_egress_bytes = (uint64_t) -1,
};
+ char **pp;
int r;
assert(path);
@@ -5165,113 +5015,58 @@ static int show_one(
log_debug("Showing one %s", path);
- r = sd_bus_call_method(
+ r = bus_map_all_properties(
bus,
"org.freedesktop.systemd1",
path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
+ show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
&error,
&reply,
- "s", "");
+ &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
- if (unit) {
- r = bus_message_map_all_properties(reply, property_map, &error, &info);
- if (r < 0)
- return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
+ if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
+ log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG,
+ "Unit %s could not be found.", unit);
- if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
- log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG,
- "Unit %s could not be found.", unit);
-
- if (streq(verb, "status"))
- return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
-
- if (!streq(verb, "show"))
- return -ENOENT;
- }
-
- r = sd_bus_message_rewind(reply, true);
- if (r < 0)
- return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+ if (show_mode == SYSTEMCTL_SHOW_STATUS)
+ return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+ else if (show_mode == SYSTEMCTL_SHOW_HELP)
+ return -ENOENT;
}
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (show_properties) {
- r = set_ensure_allocated(&found_properties, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- r = set_put(found_properties, name);
- if (r < 0 && r != EEXIST)
- return log_oom();
-
- r = print_property(name, reply, contents);
- } else
- r = status_property(name, reply, &info, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = 0;
- if (show_properties) {
- char **pp;
-
- STRV_FOREACH(pp, arg_properties)
- if (!set_contains(found_properties, *pp))
- log_debug("Property %s does not exist.", *pp);
-
- } else if (streq(verb, "help"))
- show_unit_help(&info);
- else if (streq(verb, "status")) {
+ if (show_mode == SYSTEMCTL_SHOW_STATUS) {
print_status_info(bus, &info, ellipsized);
if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
- r = EXIT_PROGRAM_NOT_RUNNING;
- else
- r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
+ return EXIT_PROGRAM_NOT_RUNNING;
+
+ return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
+
+ } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
+ show_unit_help(&info);
+ return 0;
}
- return r;
+ r = sd_bus_message_rewind(reply, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+
+ r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ STRV_FOREACH(pp, arg_properties)
+ if (!set_contains(found_properties, *pp))
+ log_debug("Property %s does not exist.", *pp);
+
+ return 0;
}
static int get_unit_dbus_path_by_pid(
@@ -5309,9 +5104,7 @@ static int get_unit_dbus_path_by_pid(
}
static int show_all(
- const char* verb,
sd_bus *bus,
- bool show_properties,
bool *new_line,
bool *ellipsized) {
@@ -5325,7 +5118,7 @@ static int show_all(
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
c = (unsigned) r;
@@ -5338,7 +5131,7 @@ static int show_all(
if (!p)
return log_oom();
- r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
+ r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -5360,7 +5153,7 @@ static int show_system_status(sd_bus *bus) {
if (!hn)
return log_oom();
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &error, &mi);
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &error, NULL, &mi);
if (r < 0)
return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
@@ -5407,18 +5200,20 @@ static int show_system_status(sd_bus *bus) {
}
static int show(int argc, char *argv[], void *userdata) {
- bool show_properties, show_status, show_help, new_line = false;
- bool ellipsized = false;
+ bool new_line = false, ellipsized = false;
+ SystemctlShowMode show_mode;
int r, ret = 0;
sd_bus *bus;
assert(argv);
- show_properties = streq(argv[0], "show");
- show_status = streq(argv[0], "status");
- show_help = streq(argv[0], "help");
+ show_mode = systemctl_show_mode_from_string(argv[0]);
+ if (show_mode < 0) {
+ log_error("Invalid argument.");
+ return -EINVAL;
+ }
- if (show_help && argc <= 1) {
+ if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1) {
log_error("This command expects one or more unit names. Did you mean --help?");
return -EINVAL;
}
@@ -5427,25 +5222,25 @@ static int show(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
- if (show_status)
+ if (show_mode == SYSTEMCTL_SHOW_STATUS)
/* Increase max number of open files to 16K if we can, we
* might needs this when browsing journal files, which might
* be split up into many files. */
setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
/* If no argument is specified inspect the manager itself */
- if (show_properties && argc <= 1)
- return show_one(argv[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
+ if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
+ return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
- if (show_status && argc <= 1) {
+ if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
show_system_status(bus);
new_line = true;
if (arg_all)
- ret = show_all(argv[0], bus, false, &new_line, &ellipsized);
+ ret = show_all(bus, &new_line, &ellipsized);
} else {
_cleanup_free_ char **patterns = NULL;
char **name;
@@ -5459,7 +5254,7 @@ static int show(int argc, char *argv[], void *userdata) {
return log_oom();
continue;
- } else if (show_properties) {
+ } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
/* Interpret as job id */
if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
return log_oom();
@@ -5477,7 +5272,7 @@ static int show(int argc, char *argv[], void *userdata) {
return log_oom();
}
- r = show_one(argv[0], bus, path, unit, show_properties, &new_line, &ellipsized);
+ r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -5498,7 +5293,7 @@ static int show(int argc, char *argv[], void *userdata) {
if (!path)
return log_oom();
- r = show_one(argv[0], bus, path, *name, show_properties, &new_line, &ellipsized);
+ r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
if (r < 0)
return r;
if (r > 0 && ret == 0)
@@ -5555,7 +5350,7 @@ static int cat(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to expand names: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
STRV_FOREACH(name, names) {
_cleanup_free_ char *fragment_path = NULL;
@@ -5834,7 +5629,7 @@ static int show_environment(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_get_property(
bus,
@@ -6275,10 +6070,11 @@ static int normalize_names(char **names, bool warn_if_path) {
static int unit_exists(LookupPaths *lp, const char *unit) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *path = NULL;
static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)},
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)},
{},
};
UnitStatusInfo info = {};
@@ -6296,7 +6092,7 @@ static int unit_exists(LookupPaths *lp, const char *unit) {
if (r < 0)
return r;
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, &error, &info);
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, &error, &m, &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
@@ -7220,7 +7016,7 @@ end:
static void systemctl_help(void) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Query or send control commands to the systemd manager.\n\n"
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index d0a510468e..a9bb8aacde 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -34,6 +34,7 @@
#include "strv.h"
#include "terminal-util.h"
#include "util.h"
+#include "verbs.h"
static bool arg_no_pager = false;
static bool arg_ask_password = true;
@@ -43,23 +44,16 @@ static bool arg_adjust_system_clock = false;
typedef struct StatusInfo {
usec_t time;
- char *timezone;
+ const char *timezone;
usec_t rtc_time;
- int rtc_local;
+ bool rtc_local;
- int ntp_enabled;
- int ntp_capable;
- int ntp_synced;
+ bool ntp_enabled;
+ bool ntp_capable;
+ bool ntp_synced;
} StatusInfo;
-static void status_info_clear(StatusInfo *info) {
- if (info) {
- free(info->timezone);
- zero(*info);
- }
-}
-
static void print_status_info(const StatusInfo *i) {
char a[LINE_MAX];
struct tm tm;
@@ -143,8 +137,8 @@ static void print_status_info(const StatusInfo *i) {
" 'timedatectl set-local-rtc 0'.%s\n", ansi_highlight(), ansi_normal());
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
- _cleanup_(status_info_clear) StatusInfo info = {};
+static int show_status(int argc, char **argv, void *userdata) {
+ StatusInfo info = {};
static const struct bus_properties_map map[] = {
{ "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
{ "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
@@ -157,6 +151,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
@@ -166,6 +162,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
"/org/freedesktop/timedate1",
map,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r));
@@ -175,22 +172,18 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int set_time(sd_bus *bus, char **args, unsigned n) {
+static int set_time(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool relative = false, interactive = arg_ask_password;
+ sd_bus *bus = userdata;
usec_t t;
int r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- r = parse_timestamp(args[1], &t);
- if (r < 0) {
- log_error("Failed to parse time specification: %s", args[1]);
- return r;
- }
+ r = parse_timestamp(argv[1], &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse time specification '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -199,20 +192,18 @@ static int set_time(sd_bus *bus, char **args, unsigned n) {
"SetTime",
&error,
NULL,
- "xbb", (int64_t)t, relative, interactive);
+ "xbb", (int64_t) t, relative, interactive);
if (r < 0)
- log_error("Failed to set time: %s", bus_error_message(&error, -r));
+ log_error("Failed to set time: %s", bus_error_message(&error, r));
return r;
}
-static int set_timezone(sd_bus *bus, char **args, unsigned n) {
+static int set_timezone(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
r = sd_bus_call_method(bus,
@@ -222,27 +213,23 @@ static int set_timezone(sd_bus *bus, char **args, unsigned n) {
"SetTimezone",
&error,
NULL,
- "sb", args[1], arg_ask_password);
+ "sb", argv[1], arg_ask_password);
if (r < 0)
- log_error("Failed to set time zone: %s", bus_error_message(&error, -r));
+ log_error("Failed to set time zone: %s", bus_error_message(&error, r));
return r;
}
-static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
+static int set_local_rtc(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r, b;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- b = parse_boolean(args[1]);
- if (b < 0) {
- log_error("Failed to parse local RTC setting: %s", args[1]);
- return b;
- }
+ b = parse_boolean(argv[1]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse local RTC setting '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -253,25 +240,21 @@ static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
NULL,
"bbb", b, arg_adjust_system_clock, arg_ask_password);
if (r < 0)
- log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
+ log_error("Failed to set local RTC: %s", bus_error_message(&error, r));
return r;
}
-static int set_ntp(sd_bus *bus, char **args, unsigned n) {
+static int set_ntp(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int b, r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- b = parse_boolean(args[1]);
- if (b < 0) {
- log_error("Failed to parse NTP setting: %s", args[1]);
- return b;
- }
+ b = parse_boolean(argv[1]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse NTP setting '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -282,29 +265,26 @@ static int set_ntp(sd_bus *bus, char **args, unsigned n) {
NULL,
"bb", b, arg_ask_password);
if (r < 0)
- log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
+ log_error("Failed to set ntp: %s", bus_error_message(&error, r));
return r;
}
-static int list_timezones(sd_bus *bus, char **args, unsigned n) {
+static int list_timezones(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **zones = NULL;
int r;
- assert(args);
- assert(n == 1);
-
r = get_timezones(&zones);
if (r < 0)
return log_error_errno(r, "Failed to read list of time zones: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(zones);
return 0;
}
-static void help(void) {
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system time and date settings.\n\n"
" -h --help Show this help message\n"
@@ -322,6 +302,12 @@ static void help(void) {
" set-local-rtc BOOL Control whether RTC is in local time\n"
" set-ntp BOOL Enable or disable network time synchronization\n",
program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -354,8 +340,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -394,82 +379,18 @@ static int parse_argv(int argc, char *argv[]) {
static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-time", EQUAL, 2, set_time },
- { "set-timezone", EQUAL, 2, set_timezone },
- { "list-timezones", EQUAL, 1, list_timezones },
- { "set-local-rtc", EQUAL, 2, set_local_rtc },
- { "set-ntp", EQUAL, 2, set_ntp, },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "set-time", 2, 2, 0, set_time },
+ { "set-timezone", 2, 2, 0, set_timezone },
+ { "list-timezones", VERB_ANY, 1, 0, list_timezones },
+ { "set-local-rtc", 2, 2, 0, set_local_rtc },
+ { "set-ntp", 2, 2, 0, set_ntp },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char *argv[]) {