From 15c3626e069b67e0168d00b643b2cc36f2247a3e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Mar 2018 14:05:08 +0900 Subject: [PATCH 01/21] networkctl,hwdb: make verbs static --- src/hwdb/hwdb.c | 2 +- src/network/networkctl.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) 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/network/networkctl.c b/src/network/networkctl.c index 14d8ecb03f..50317e948d 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -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 }, {} }; From 9bb31a0c9fe1a4b7a039e826f02cc0355ba919b3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 05:09:16 +0900 Subject: [PATCH 02/21] busctl: use dispatch_verb() --- src/busctl/busctl.c | 328 ++++++++++++++++++++------------------------ 1 file changed, 150 insertions(+), 178 deletions(-) diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index f8c43b5079..f4ef947c21 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,11 +156,13 @@ 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"); @@ -417,14 +495,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; @@ -848,7 +931,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 +944,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) @@ -1071,7 +1146,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 +1156,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 +1266,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 +1280,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 +1292,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 +1597,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) @@ -1602,19 +1682,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; @@ -1660,20 +1736,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 +1759,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 +1830,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 +2054,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 +2083,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; } From cb05d2a5149517ed524f859aa219e27c601d74ad Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Mar 2018 17:45:42 +0900 Subject: [PATCH 03/21] busctl: add missing oom check --- src/busctl/busctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index f4ef947c21..44a050af3d 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -190,6 +190,9 @@ static int list_bus_names(int argc, char **argv, void *userdata) { } merged = new(char*, hashmap_size(names) + 1); + if (!merged) + return log_oom(); + HASHMAP_FOREACH_KEY(v, k, names, iterator) merged[n++] = k; From 548866015467d82c0688730807bd1b704be21c38 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 12 Mar 2018 17:47:16 +0900 Subject: [PATCH 04/21] busctl: drop redundant pager_open() --- src/busctl/busctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 44a050af3d..ae4c8c26c0 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -364,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) { From 5ce97d33d098d225a6480179293d0b02da6dde41 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 17:46:34 +0900 Subject: [PATCH 05/21] coredumpctl: use dispatch_verb() --- src/coredump/coredumpctl.c | 200 ++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 105 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index a4cc9c1db3..2795f5b675 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; + + 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", From a456324fefec12ac929fd844bcec243b657d7b1f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 14:06:50 +0900 Subject: [PATCH 06/21] man: mention that 'status' is the default command for `hostnamectl` --- man/hostnamectl.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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. From f46bc484f7ba9fc32ecac889162143d31d3ef892 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 14:29:55 +0900 Subject: [PATCH 07/21] hostnamectl: use dispatch_verb() --- src/hostname/hostnamectl.c | 137 +++++++++---------------------------- 1 file changed, 32 insertions(+), 105 deletions(-) diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index e06b111b43..c545caa4bf 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; @@ -200,11 +201,10 @@ fail: 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 +247,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 +299,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 +334,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 +374,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 +417,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[]) { From 1d4ecb98be3c908321a2b6148f71ba83eda65c14 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 14:50:40 +0900 Subject: [PATCH 08/21] localectl: use dispatch_verb() --- src/locale/localectl.c | 172 +++++++++++------------------------------ 1 file changed, 47 insertions(+), 125 deletions(-) diff --git a/src/locale/localectl.c b/src/locale/localectl.c index af39e431f5..e67ba4e7e0 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; @@ -142,7 +143,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 +158,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; int r; assert(bus); @@ -176,13 +178,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 +198,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,12 +215,10 @@ 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"); @@ -229,23 +229,18 @@ static int list_locales(sd_bus *bus, char **args, unsigned n) { 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,12 +257,10 @@ 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"); @@ -279,25 +272,18 @@ static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) { 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 +301,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 +314,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 +357,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 +373,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; @@ -416,7 +397,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) { 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 +421,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 +459,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 +498,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[]) { From d4e0773b4da6146f64947360ae6f8c971d459372 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 14:52:45 +0900 Subject: [PATCH 09/21] man: mention 'status' is the default command for localectl --- man/localectl.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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. From be90a886547c76a6caa7ca8b84949fbd9da092cd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 15:09:28 +0900 Subject: [PATCH 10/21] timedatectl: use dispatch_verb() --- src/timedate/timedatectl.c | 164 ++++++++++--------------------------- 1 file changed, 45 insertions(+), 119 deletions(-) diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index d0a510468e..cd1e00a196 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; @@ -143,7 +144,7 @@ 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) { +static int show_status(int argc, char **argv, void *userdata) { _cleanup_(status_info_clear) StatusInfo info = {}; static const struct bus_properties_map map[] = { { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, @@ -157,6 +158,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; int r; assert(bus); @@ -175,22 +177,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 +197,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 +218,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 +245,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,18 +270,15 @@ 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"); @@ -304,7 +289,7 @@ static int list_timezones(sd_bus *bus, char **args, unsigned n) { 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 +307,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 +345,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 +384,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[]) { From 24fcd009c3eb89f590bef96dd5495fd4ef796fd0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 15:10:46 +0900 Subject: [PATCH 11/21] man: mention 'status' is the default command for timedatectl --- man/timedatectl.xml | 5 +++++ 1 file changed, 5 insertions(+) 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. From ee5324aa04bb46a9a8e1ad23307efa85e05879b6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 17:48:29 +0900 Subject: [PATCH 12/21] tree-wide: voidify pager_open() Even if pager_open() fails, in general, we should continue the operations. All erroneous cases in pager_open() show log message in the function. So, it is not necessary to check the returned value. --- src/analyze/analyze.c | 10 +++++----- src/busctl/busctl.c | 14 +++++++------- src/cgls/cgls.c | 8 +++----- src/core/main.c | 2 +- src/coredump/coredumpctl.c | 2 +- src/delta/delta.c | 2 +- src/journal/journalctl.c | 8 ++++---- src/locale/localectl.c | 6 +++--- src/login/loginctl.c | 12 ++++++------ src/machine/machinectl.c | 12 ++++++------ src/mount/mount-tool.c | 2 +- src/network/networkctl.c | 6 +++--- src/resolve/resolve-tool.c | 4 ++-- src/systemctl/systemctl.c | 26 +++++++++++++------------- src/timedate/timedatectl.c | 2 +- 15 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 092ff763ba..1bed16e219 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1027,7 +1027,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 +1060,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 +1283,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 +1445,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 +1607,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 ae4c8c26c0..2f9250e2ae 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -167,7 +167,7 @@ static int list_bus_names(int argc, char **argv, void *userdata) { 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) @@ -482,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) @@ -516,7 +516,7 @@ static int tree(int argc, char **argv, void *userdata) { 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; @@ -546,7 +546,7 @@ static int tree(int argc, char **argv, void *userdata) { 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()); } @@ -1052,7 +1052,7 @@ static int introspect(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); name_width = STRLEN("NAME"); type_width = STRLEN("TYPE"); @@ -1662,7 +1662,7 @@ static int call(int argc, char **argv, void *userdata) { 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) @@ -1713,7 +1713,7 @@ static int get_property(int argc, char **argv, void *userdata) { 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) 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 2795f5b675..2f8b9b7cbf 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -658,7 +658,7 @@ static int dump_list(int argc, char **argv, void *userdata) { if (r < 0) return r; - pager_open(arg_no_pager, false); + (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 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/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 e67ba4e7e0..f50d31a29b 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -223,7 +223,7 @@ static int list_locales(int argc, char **argv, void *userdata) { 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; @@ -265,7 +265,7 @@ static int list_vconsole_keymaps(int argc, char **argv, void *userdata) { 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); @@ -391,7 +391,7 @@ static int list_x11_keymaps(int argc, char **argv, void *userdata) { strv_sort(list); strv_uniq(list); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); strv_print(list); return 0; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index c811ee6c5e..2f53a2740d 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, @@ -903,7 +903,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 +955,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 +1015,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..9180ec4725 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", @@ -860,7 +860,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) { @@ -1213,7 +1213,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 +2543,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 +2758,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 50317e948d..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", diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 04f883654a..d1395b2e2c 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -1241,7 +1241,7 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt goto finish; } - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); if (*empty_line) fputc('\n', stdout); @@ -1450,7 +1450,7 @@ 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()); STRV_FOREACH(i, global_info.dns) { diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 0f383ec9e0..7bd5ecbb40 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -791,7 +791,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 +1003,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 +1310,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 +1599,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); @@ -1854,7 +1854,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); @@ -2086,7 +2086,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 +2258,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 +2373,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; @@ -5325,7 +5325,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; @@ -5427,7 +5427,7 @@ 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) /* Increase max number of open files to 16K if we can, we @@ -5555,7 +5555,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 +5834,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, @@ -7220,7 +7220,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 cd1e00a196..d390e24e62 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -283,7 +283,7 @@ static int list_timezones(int argc, char **argv, void *userdata) { 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; From 32b4727965c3adcf05ae7b8bf272db64da229c70 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 15 Mar 2018 18:44:34 +0900 Subject: [PATCH 13/21] systemctl: use bus_map_all_properties() in list-dependencies command --- src/systemctl/systemctl.c | 111 ++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 65 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7bd5ecbb40..5624d34b50 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1652,91 +1652,72 @@ 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, + &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; From 4f00a11c736b015f40f513b9349afb560791abdc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 16 Mar 2018 02:35:29 +0900 Subject: [PATCH 14/21] bus-util: store boolean message to bool --- src/shared/bus-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 548e817105..8699ed5ce2 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1060,13 +1060,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; } From f37f8a61c0d5192bd9dc038d5996a41a6e940caf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 19 Mar 2018 23:46:29 +0900 Subject: [PATCH 15/21] bus-util: make bus_map_all_properties() not copy string --- src/analyze/analyze.c | 2 + src/hostname/hostnamectl.c | 58 +++++++++-------------- src/locale/localectl.c | 20 ++++---- src/login/loginctl.c | 97 ++++++++++++-------------------------- src/machine/machinectl.c | 54 +++++++-------------- src/resolve/resolve-tool.c | 15 +++--- src/run/run.c | 1 + src/shared/bus-util.c | 26 +++++++--- src/shared/bus-util.h | 6 +-- src/systemctl/systemctl.c | 33 ++++--------- src/timedate/timedatectl.c | 21 ++++----- 11 files changed, 132 insertions(+), 201 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 1bed16e219..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)); diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index c545caa4bf..baa48c7f71 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -44,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) { @@ -163,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, @@ -170,34 +171,21 @@ 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; } diff --git a/src/locale/localectl.c b/src/locale/localectl.c index f50d31a29b..550e97b3ed 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -50,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); } } @@ -158,6 +152,7 @@ static int show_status(int argc, char **argv, void *userdata) { }; _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; @@ -168,6 +163,7 @@ static int show_status(int argc, char **argv, void *userdata) { "/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)); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 2f53a2740d..403ba40c1c 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -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)); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 9180ec4725..d4b8c15272 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -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)); @@ -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)); diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index d1395b2e2c..c757e59ecb 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,6 +1236,7 @@ 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)); @@ -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; } @@ -1428,6 +1427,7 @@ static int status_global(sd_bus *bus, bool *empty_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 **i; int r; @@ -1439,6 +1439,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)); 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 8699ed5ce2..2336338102 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1020,7 +1020,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 +1031,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 +1041,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: { @@ -1111,6 +1115,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 +1158,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 +1184,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 +1194,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 +1225,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 +1248,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..5e1fe893f9 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); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 5624d34b50..6f2074dbde 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -250,21 +250,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 */ @@ -1701,6 +1686,7 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha 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)); @@ -1905,7 +1891,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; @@ -5119,8 +5105,8 @@ static int show_one( 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) }, {} }; @@ -5159,7 +5145,7 @@ static int show_one( 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); + r = bus_message_map_all_properties(reply, property_map, false, &error, &info); if (r < 0) return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); @@ -5341,7 +5327,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)); @@ -6256,10 +6242,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 = {}; @@ -6277,7 +6264,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)); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index d390e24e62..a9bb8aacde 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -44,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; @@ -145,7 +138,7 @@ static void print_status_info(const StatusInfo *i) { } static int show_status(int argc, char **argv, void *userdata) { - _cleanup_(status_info_clear) StatusInfo info = {}; + StatusInfo info = {}; static const struct bus_properties_map map[] = { { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, @@ -158,6 +151,7 @@ static int show_status(int argc, char **argv, void *userdata) { }; _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; @@ -168,6 +162,7 @@ static int show_status(int argc, char **argv, void *userdata) { "/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)); From 8559e61d6438ee0fc95eb6bf0501fd11ad6da8f1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Mar 2018 00:09:04 +0900 Subject: [PATCH 16/21] systemctl: use string table for show() --- src/systemctl/systemctl.c | 69 ++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6f2074dbde..e4222b8573 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" @@ -5095,12 +5096,27 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte 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) { @@ -5150,13 +5166,12 @@ static int show_one( return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) { - log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG, + log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG, "Unit %s could not be found.", unit); - if (streq(verb, "status")) + if (show_mode == SYSTEMCTL_SHOW_STATUS) return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN; - - if (!streq(verb, "show")) + else if (show_mode == SYSTEMCTL_SHOW_HELP) return -ENOENT; } @@ -5189,7 +5204,7 @@ static int show_one( if (r < 0) return bus_log_parse_error(r); - if (show_properties) { + if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) { r = set_ensure_allocated(&found_properties, &string_hash_ops); if (r < 0) return log_oom(); @@ -5220,16 +5235,16 @@ static int show_one( return bus_log_parse_error(r); r = 0; - if (show_properties) { + if (show_mode == SYSTEMCTL_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")) + } else if (show_mode == SYSTEMCTL_SHOW_HELP) show_unit_help(&info); - else if (streq(verb, "status")) { + else { print_status_info(bus, &info, ellipsized); if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading")) @@ -5276,9 +5291,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) { @@ -5305,7 +5318,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) @@ -5374,18 +5387,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; } @@ -5396,23 +5411,23 @@ static int show(int argc, char *argv[], void *userdata) { (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; @@ -5426,7 +5441,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(); @@ -5444,7 +5459,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) @@ -5465,7 +5480,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) From 4679a8c3018d82e4c7ee9718db4cf97464b55dc7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Mar 2018 00:20:39 +0900 Subject: [PATCH 17/21] systemctl: use bus_map_all_properties() in status command --- src/systemctl/systemctl.c | 662 +++++++++++++++----------------------- 1 file changed, 265 insertions(+), 397 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index e4222b8573..c90cf0acd8 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4393,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; } @@ -5121,8 +4932,76 @@ static int show_one( bool *ellipsized) { static const struct bus_properties_map property_map[] = { - { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, - { "ActiveState", "s", NULL, 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 }, {} }; @@ -5141,6 +5020,7 @@ static int show_one( .ip_ingress_bytes = (uint64_t) -1, .ip_egress_bytes = (uint64_t) -1, }; + char **pp; int r; assert(path); @@ -5148,47 +5028,53 @@ 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, false, &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(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG, - "Unit %s could not be found.", unit); - - 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_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; + if (show_mode == SYSTEMCTL_SHOW_STATUS) { + print_status_info(bus, &info, ellipsized); + + if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading")) + 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; + } + + 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 = 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 *name, *contents; @@ -5204,18 +5090,15 @@ static int show_one( if (r < 0) return bus_log_parse_error(r); - if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) { - r = set_ensure_allocated(&found_properties, &string_hash_ops); - if (r < 0) - return log_oom(); + 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 = 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); + r = print_property(name, reply, contents); if (r < 0) return r; @@ -5234,26 +5117,11 @@ static int show_one( if (r < 0) return bus_log_parse_error(r); - r = 0; - if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) { - char **pp; + STRV_FOREACH(pp, arg_properties) + if (!set_contains(found_properties, *pp)) + log_debug("Property %s does not exist.", *pp); - STRV_FOREACH(pp, arg_properties) - if (!set_contains(found_properties, *pp)) - log_debug("Property %s does not exist.", *pp); - - } else if (show_mode == SYSTEMCTL_SHOW_HELP) - show_unit_help(&info); - else { - 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 r; + return 0; } static int get_unit_dbus_path_by_pid( From 07636114b131741fe9e385cb86a721f32169e5ca Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Mar 2018 00:37:00 +0900 Subject: [PATCH 18/21] bus-util: introduce bus_message_print_all_properties() Then, use it where applicable. --- src/login/loginctl.c | 98 ++++----------------- src/machine/machinectl.c | 4 +- src/shared/bus-util.c | 177 +++++++++++++++++++++++--------------- src/shared/bus-util.h | 5 +- src/systemctl/systemctl.c | 141 +++++++++--------------------- 5 files changed, 175 insertions(+), 250 deletions(-) diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 403ba40c1c..7554faeda3 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -688,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); @@ -734,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; @@ -749,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) { @@ -757,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) @@ -767,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; } @@ -798,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); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d4b8c15272..78a7ce2fa3 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -838,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"); @@ -1176,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"); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 2336338102..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) { diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index 5e1fe893f9..e42198ff1c 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -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 c90cf0acd8..cae4ff023a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4564,7 +4564,9 @@ static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_e 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); @@ -4573,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); @@ -4592,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; @@ -4640,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); } @@ -4663,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; @@ -4688,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)"); @@ -4706,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)"); @@ -4724,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) @@ -4748,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; @@ -4771,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)"); @@ -4808,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)"); @@ -4826,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; @@ -4846,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; @@ -4867,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; @@ -4885,25 +4885,12 @@ 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; } @@ -5071,49 +5058,7 @@ static int show_one( if (r < 0) return log_error_errno(r, "Failed to rewind: %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); - - 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 = 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); - 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_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties); if (r < 0) return bus_log_parse_error(r); From 3b85dace6db013f2e91be0f4a2bfde4f5ee75c15 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Mar 2018 00:38:36 +0900 Subject: [PATCH 19/21] doc: update TODO --- TODO | 5 ----- 1 file changed, 5 deletions(-) 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 From bf4e5c4cc63dfbdb171771860858963b95915326 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 19 Mar 2018 14:29:22 +0900 Subject: [PATCH 20/21] resolve: expose global LLMNR, MulticastDNS, and DNSSEC settings as bus property --- src/resolve/resolved-bus.c | 22 ++++++++++++++++++++++ src/resolve/resolved-bus.h | 3 +++ src/resolve/resolved-link-bus.c | 6 ++---- 3 files changed, 27 insertions(+), 4 deletions(-) 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), From 11d6e9e9dcf958fae81fa2f3bbe2caabfe9e039f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 20 Mar 2018 00:40:05 +0900 Subject: [PATCH 21/21] resolve: show more global settings in `systemd-resolve --status` Closes #8455. --- src/resolve/resolve-tool.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index c757e59ecb..462ea7a2d5 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -1417,12 +1417,20 @@ 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) }, {} }; @@ -1454,6 +1462,16 @@ static int status_global(sd_bus *bus, bool *empty_line) { (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:" : " ",