diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-03-14 05:09:16 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-03-19 21:03:36 +0900 |
commit | 9bb31a0c9fe1a4b7a039e826f02cc0355ba919b3 (patch) | |
tree | ed6929818fcbdbfa9c444fd936656e9260541ad3 /src/busctl | |
parent | 15c3626e069b67e0168d00b643b2cc36f2247a3e (diff) | |
download | systemd-9bb31a0c9fe1a4b7a039e826f02cc0355ba919b3.tar.gz |
busctl: use dispatch_verb()
Diffstat (limited to 'src/busctl')
-rw-r--r-- | src/busctl/busctl.c | 330 |
1 files changed, 151 insertions, 179 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); - - if (strv_length(argv) > 2) { - log_error("Expects no or one argument."); - return -EINVAL; - } + r = acquire_bus(false, &bus); + if (r < 0) + return r; - 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); - - if (optind >= argc || - streq(argv[optind], "list")) - return list_bus_names(bus, argv + optind); - - 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(); +static int busctl_main(int argc, char *argv[]) { + + 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 }, + {} + }; - 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; } |