1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 #include "path-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
37 #include "bus-signature.h"
39 static bool arg_no_pager = false;
40 static bool arg_legend = true;
41 static char *arg_address = NULL;
42 static bool arg_unique = false;
43 static bool arg_acquired = false;
44 static bool arg_activatable = false;
45 static bool arg_show_machine = false;
46 static char **arg_matches = NULL;
47 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
48 static char *arg_host = NULL;
49 static bool arg_user = false;
50 static size_t arg_snaplen = 4096;
51 static bool arg_list = false;
52 static bool arg_quiet = false;
54 static void pager_open_if_enabled(void) {
56 /* Cache result before we open the pager */
63 static int list_bus_names(sd_bus *bus, char **argv) {
64 _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
65 _cleanup_free_ char **merged = NULL;
66 _cleanup_hashmap_free_ Hashmap *names = NULL;
77 if (!arg_unique && !arg_acquired && !arg_activatable)
78 arg_unique = arg_acquired = arg_activatable = true;
80 r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
82 log_error("Failed to list names: %s", strerror(-r));
86 pager_open_if_enabled();
88 names = hashmap_new(&string_hash_ops);
92 STRV_FOREACH(i, acquired) {
93 max_i = MAX(max_i, strlen(*i));
95 r = hashmap_put(names, *i, INT_TO_PTR(1));
97 log_error("Failed to add to hashmap: %s", strerror(-r));
102 STRV_FOREACH(i, activatable) {
103 max_i = MAX(max_i, strlen(*i));
105 r = hashmap_put(names, *i, INT_TO_PTR(2));
106 if (r < 0 && r != -EEXIST) {
107 log_error("Failed to add to hashmap: %s", strerror(-r));
112 merged = new(char*, hashmap_size(names) + 1);
113 HASHMAP_FOREACH_KEY(v, k, names, iterator)
120 printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
121 (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
123 if (arg_show_machine)
129 STRV_FOREACH(i, merged) {
130 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
133 if (hashmap_get(names, *i) == INT_TO_PTR(2)) {
136 printf("%-*s", (int) max_i, *i);
137 printf(" - - - (activatable) - - ");
138 if (arg_show_machine)
146 if (!arg_unique && (*i)[0] == ':')
149 if (!arg_acquired && (*i)[0] != ':')
152 printf("%-*s", (int) max_i, *i);
154 r = sd_bus_get_name_creds(bus, *i,
155 SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|
156 SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION|
157 SD_BUS_CREDS_DESCRIPTION, &creds);
159 const char *unique, *session, *unit, *cn;
163 r = sd_bus_creds_get_pid(creds, &pid);
165 const char *comm = NULL;
167 sd_bus_creds_get_comm(creds, &comm);
169 printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
171 fputs(" - - ", stdout);
173 r = sd_bus_creds_get_uid(creds, &uid);
175 _cleanup_free_ char *u = NULL;
177 u = uid_to_name(uid);
186 fputs(" - ", stdout);
188 r = sd_bus_creds_get_unique_name(creds, &unique);
190 printf(" %-13s", unique);
192 fputs(" - ", stdout);
194 r = sd_bus_creds_get_unit(creds, &unit);
196 _cleanup_free_ char *e;
198 e = ellipsize(unit, 25, 100);
204 fputs(" - ", stdout);
206 r = sd_bus_creds_get_session(creds, &session);
208 printf(" %-10s", session);
210 fputs(" - ", stdout);
212 r = sd_bus_creds_get_description(creds, &cn);
214 printf(" %-19s", cn);
216 fputs(" - ", stdout);
219 printf(" - - - - - - - ");
221 if (arg_show_machine) {
222 r = sd_bus_get_name_machine_id(bus, *i, &mid);
224 char m[SD_ID128_STRING_MAX];
225 printf(" %s\n", sd_id128_to_string(mid, m));
235 static void print_subtree(const char *prefix, const char *path, char **l) {
236 const char *vertical, *space;
239 /* We assume the list is sorted. Let's first skip over the
240 * entry we are looking at. */
245 if (!streq(*l, path))
251 vertical = strappenda(prefix, draw_special_char(DRAW_TREE_VERTICAL));
252 space = strappenda(prefix, draw_special_char(DRAW_TREE_SPACE));
255 bool has_more = false;
257 if (!*l || !path_startswith(*l, path))
262 if (!*n || !path_startswith(*n, path))
265 if (!path_startswith(*n, *l)) {
273 printf("%s%s%s\n", prefix, draw_special_char(has_more ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), *l);
275 print_subtree(has_more ? vertical : space, *l, l);
280 static void print_tree(const char *prefix, char **l) {
282 pager_open_if_enabled();
284 prefix = strempty(prefix);
290 printf("%s%s\n", prefix, *i);
294 if (strv_isempty(l)) {
295 printf("No objects discovered.\n");
299 if (streq(l[0], "/") && !l[1]) {
300 printf("Only root object discovered.\n");
304 print_subtree(prefix, "/", l);
307 static int parse_xml_annotation(
316 } state = STATE_ANNOTATION;
319 _cleanup_free_ char *name = NULL;
323 t = xml_tokenize(p, &name, xml_state, NULL);
325 log_error("XML parse error.");
330 log_error("Premature end of XML data.");
336 case STATE_ANNOTATION:
338 if (t == XML_ATTRIBUTE_NAME) {
340 if (streq_ptr(name, "name"))
343 else if (streq_ptr(name, "value"))
347 log_error("Unexpected <annotation> attribute %s.", name);
351 } else if (t == XML_TAG_CLOSE_EMPTY ||
352 (t == XML_TAG_CLOSE && streq_ptr(name, "annotation")))
356 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
357 log_error("Unexpected token in <annotation>. (1)");
365 if (t == XML_ATTRIBUTE_VALUE)
366 state = STATE_ANNOTATION;
368 log_error("Unexpected token in <annotation>. (2)");
376 if (t == XML_ATTRIBUTE_VALUE)
377 state = STATE_ANNOTATION;
379 log_error("Unexpected token in <annotation>. (3)");
386 assert_not_reached("Bad state");
391 static int parse_xml_node(
401 STATE_INTERFACE_NAME,
405 STATE_METHOD_ARG_NAME,
406 STATE_METHOD_ARG_TYPE,
407 STATE_METHOD_ARG_DIRECTION,
411 STATE_SIGNAL_ARG_NAME,
412 STATE_SIGNAL_ARG_TYPE,
416 STATE_PROPERTY_ACCESS,
417 } state = STATE_NODE;
419 _cleanup_free_ char *node_path = NULL;
420 const char *np = prefix;
424 _cleanup_free_ char *name = NULL;
427 t = xml_tokenize(p, &name, xml_state, NULL);
429 log_error("XML parse error.");
434 log_error("Premature end of XML data.");
441 if (t == XML_ATTRIBUTE_NAME) {
443 if (streq_ptr(name, "name"))
444 state = STATE_NODE_NAME;
446 log_error("Unexpected <node> attribute %s.", name);
450 } else if (t == XML_TAG_OPEN) {
452 if (streq_ptr(name, "interface"))
453 state = STATE_INTERFACE;
455 else if (streq_ptr(name, "node")) {
457 r = parse_xml_node(np, paths, p, xml_state);
461 log_error("Unexpected <node> tag %s.", name);
464 } else if (t == XML_TAG_CLOSE_EMPTY ||
465 (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
469 node_path = strdup(np);
474 r = set_put(paths, node_path);
483 } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
484 log_error("Unexpected token in <node>. (1)");
490 case STATE_NODE_NAME:
492 if (t == XML_ATTRIBUTE_VALUE) {
496 if (name[0] == '/') {
501 if (endswith(prefix, "/"))
502 node_path = strappend(prefix, name);
504 node_path = strjoin(prefix, "/", name, NULL);
512 log_error("Unexpected token in <node>. (2)");
518 case STATE_INTERFACE:
520 if (t == XML_ATTRIBUTE_NAME) {
521 if (streq_ptr(name, "name"))
522 state = STATE_INTERFACE_NAME;
524 log_error("Unexpected <interface> attribute %s.", name);
528 } else if (t == XML_TAG_OPEN) {
529 if (streq_ptr(name, "method"))
530 state = STATE_METHOD;
531 else if (streq_ptr(name, "signal"))
532 state = STATE_SIGNAL;
533 else if (streq_ptr(name, "property"))
534 state = STATE_PROPERTY;
535 else if (streq_ptr(name, "annotation")) {
536 r = parse_xml_annotation(p, xml_state);
540 log_error("Unexpected <interface> tag %s.", name);
543 } else if (t == XML_TAG_CLOSE_EMPTY ||
544 (t == XML_TAG_CLOSE && streq_ptr(name, "interface")))
548 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
549 log_error("Unexpected token in <interface>. (1)");
555 case STATE_INTERFACE_NAME:
557 if (t == XML_ATTRIBUTE_VALUE)
558 state = STATE_INTERFACE;
560 log_error("Unexpected token in <interface>. (2)");
568 if (t == XML_ATTRIBUTE_NAME) {
569 if (streq_ptr(name, "name"))
570 state = STATE_METHOD_NAME;
572 log_error("Unexpected <method> attribute %s", name);
575 } else if (t == XML_TAG_OPEN) {
576 if (streq_ptr(name, "arg"))
577 state = STATE_METHOD_ARG;
578 else if (streq_ptr(name, "annotation")) {
579 r = parse_xml_annotation(p, xml_state);
583 log_error("Unexpected <method> tag %s.", name);
586 } else if (t == XML_TAG_CLOSE_EMPTY ||
587 (t == XML_TAG_CLOSE && streq_ptr(name, "method")))
589 state = STATE_INTERFACE;
591 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
592 log_error("Unexpected token in <method> (1).");
598 case STATE_METHOD_NAME:
600 if (t == XML_ATTRIBUTE_VALUE)
601 state = STATE_METHOD;
603 log_error("Unexpected token in <method> (2).");
609 case STATE_METHOD_ARG:
611 if (t == XML_ATTRIBUTE_NAME) {
612 if (streq_ptr(name, "name"))
613 state = STATE_METHOD_ARG_NAME;
614 else if (streq_ptr(name, "type"))
615 state = STATE_METHOD_ARG_TYPE;
616 else if (streq_ptr(name, "direction"))
617 state = STATE_METHOD_ARG_DIRECTION;
619 log_error("Unexpected method <arg> attribute %s.", name);
622 } else if (t == XML_TAG_OPEN) {
623 if (streq_ptr(name, "annotation")) {
624 r = parse_xml_annotation(p, xml_state);
628 log_error("Unexpected method <arg> tag %s.", name);
631 } else if (t == XML_TAG_CLOSE_EMPTY ||
632 (t == XML_TAG_CLOSE && streq_ptr(name, "arg")))
634 state = STATE_METHOD;
636 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
637 log_error("Unexpected token in method <arg>. (1)");
643 case STATE_METHOD_ARG_NAME:
645 if (t == XML_ATTRIBUTE_VALUE)
646 state = STATE_METHOD_ARG;
648 log_error("Unexpected token in method <arg>. (2)");
654 case STATE_METHOD_ARG_TYPE:
656 if (t == XML_ATTRIBUTE_VALUE)
657 state = STATE_METHOD_ARG;
659 log_error("Unexpected token in method <arg>. (3)");
665 case STATE_METHOD_ARG_DIRECTION:
667 if (t == XML_ATTRIBUTE_VALUE)
668 state = STATE_METHOD_ARG;
670 log_error("Unexpected token in method <arg>. (4)");
678 if (t == XML_ATTRIBUTE_NAME) {
679 if (streq_ptr(name, "name"))
680 state = STATE_SIGNAL_NAME;
682 log_error("Unexpected <signal> attribute %s.", name);
685 } else if (t == XML_TAG_OPEN) {
686 if (streq_ptr(name, "arg"))
687 state = STATE_SIGNAL_ARG;
688 else if (streq_ptr(name, "annotation")) {
689 r = parse_xml_annotation(p, xml_state);
693 log_error("Unexpected <signal> tag %s.", name);
696 } else if (t == XML_TAG_CLOSE_EMPTY ||
697 (t == XML_TAG_CLOSE && streq_ptr(name, "signal")))
699 state = STATE_INTERFACE;
701 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
702 log_error("Unexpected token in <signal>. (1)");
708 case STATE_SIGNAL_NAME:
710 if (t == XML_ATTRIBUTE_VALUE)
711 state = STATE_SIGNAL;
713 log_error("Unexpected token in <signal>. (2)");
720 case STATE_SIGNAL_ARG:
722 if (t == XML_ATTRIBUTE_NAME) {
723 if (streq_ptr(name, "name"))
724 state = STATE_SIGNAL_ARG_NAME;
725 else if (streq_ptr(name, "type"))
726 state = STATE_SIGNAL_ARG_TYPE;
728 log_error("Unexpected signal <arg> attribute %s.", name);
731 } else if (t == XML_TAG_OPEN) {
732 if (streq_ptr(name, "annotation")) {
733 r = parse_xml_annotation(p, xml_state);
737 log_error("Unexpected signal <arg> tag %s.", name);
740 } else if (t == XML_TAG_CLOSE_EMPTY ||
741 (t == XML_TAG_CLOSE && streq_ptr(name, "arg")))
743 state = STATE_SIGNAL;
745 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
746 log_error("Unexpected token in signal <arg> (1).");
752 case STATE_SIGNAL_ARG_NAME:
754 if (t == XML_ATTRIBUTE_VALUE)
755 state = STATE_SIGNAL_ARG;
757 log_error("Unexpected token in signal <arg> (2).");
763 case STATE_SIGNAL_ARG_TYPE:
765 if (t == XML_ATTRIBUTE_VALUE)
766 state = STATE_SIGNAL_ARG;
768 log_error("Unexpected token in signal <arg> (3).");
776 if (t == XML_ATTRIBUTE_NAME) {
777 if (streq_ptr(name, "name"))
778 state = STATE_PROPERTY_NAME;
779 else if (streq_ptr(name, "type"))
780 state = STATE_PROPERTY_TYPE;
781 else if (streq_ptr(name, "access"))
782 state = STATE_PROPERTY_ACCESS;
784 log_error("Unexpected <property> attribute %s.", name);
787 } else if (t == XML_TAG_OPEN) {
789 if (streq_ptr(name, "annotation")) {
790 r = parse_xml_annotation(p, xml_state);
794 log_error("Unexpected <property> tag %s.", name);
798 } else if (t == XML_TAG_CLOSE_EMPTY ||
799 (t == XML_TAG_CLOSE && streq_ptr(name, "property")))
801 state = STATE_INTERFACE;
803 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
804 log_error("Unexpected token in <property>. (1)");
810 case STATE_PROPERTY_NAME:
812 if (t == XML_ATTRIBUTE_VALUE)
813 state = STATE_PROPERTY;
815 log_error("Unexpected token in <property>. (2)");
821 case STATE_PROPERTY_TYPE:
823 if (t == XML_ATTRIBUTE_VALUE)
824 state = STATE_PROPERTY;
826 log_error("Unexpected token in <property>. (3)");
832 case STATE_PROPERTY_ACCESS:
834 if (t == XML_ATTRIBUTE_VALUE)
835 state = STATE_PROPERTY;
837 log_error("Unexpected token in <property>. (4)");
846 static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths) {
847 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
848 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
850 void *xml_state = NULL;
853 r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
855 log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
859 r = sd_bus_message_read(reply, "s", &xml);
861 return bus_log_parse_error(r);
863 /* fputs(xml, stdout); */
867 _cleanup_free_ char *name = NULL;
869 r = xml_tokenize(&p, &name, &xml_state, NULL);
871 log_error("XML parse error");
878 if (r == XML_TAG_OPEN) {
880 if (streq(name, "node")) {
881 r = parse_xml_node(path, paths, &p, &xml_state);
885 log_error("Unexpected tag '%s' in introspection data.", name);
888 } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
889 log_error("Unexpected token.");
897 static int tree_one(sd_bus *bus, const char *service, const char *prefix) {
898 _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
899 _cleanup_free_ char **l = NULL;
903 paths = set_new(&string_hash_ops);
907 done = set_new(&string_hash_ops);
911 failed = set_new(&string_hash_ops);
919 r = set_put(paths, m);
926 _cleanup_free_ char *p = NULL;
929 p = set_steal_first(paths);
933 if (set_contains(done, p) ||
934 set_contains(failed, p))
937 q = find_nodes(bus, service, p, paths);
942 q = set_put(failed, p);
944 q = set_put(done, p);
953 l = set_get_strv(done);
958 print_tree(prefix, l);
965 static int tree(sd_bus *bus, char **argv) {
969 if (!arg_unique && !arg_acquired)
972 if (strv_length(argv) <= 1) {
973 _cleanup_strv_free_ char **names = NULL;
974 bool not_first = false;
976 r = sd_bus_list_names(bus, &names, NULL);
978 log_error("Failed to get name list: %s", strerror(-r));
982 pager_open_if_enabled();
984 STRV_FOREACH(i, names) {
987 if (!arg_unique && (*i)[0] == ':')
990 if (!arg_acquired && (*i)[0] == ':')
996 printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
998 q = tree_one(bus, *i, NULL);
1005 pager_open_if_enabled();
1007 STRV_FOREACH(i, argv+1) {
1014 printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
1016 q = tree_one(bus, *i, NULL);
1017 if (q < 0 && r >= 0)
1025 static int message_dump(sd_bus_message *m, FILE *f) {
1026 return bus_message_dump(m, f, true);
1029 static int message_pcap(sd_bus_message *m, FILE *f) {
1030 return bus_message_pcap_frame(m, arg_snaplen, f);
1033 static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
1034 bool added_something = false;
1038 STRV_FOREACH(i, argv+1) {
1039 _cleanup_free_ char *m = NULL;
1041 if (!service_name_is_valid(*i)) {
1042 log_error("Invalid service name '%s'", *i);
1046 m = strjoin("sender='", *i, "'", NULL);
1050 r = sd_bus_add_match(bus, NULL, m, NULL, NULL);
1052 log_error("Failed to add match: %s", strerror(-r));
1056 added_something = true;
1059 STRV_FOREACH(i, arg_matches) {
1060 r = sd_bus_add_match(bus, NULL, *i, NULL, NULL);
1062 log_error("Failed to add match: %s", strerror(-r));
1066 added_something = true;
1069 if (!added_something) {
1070 r = sd_bus_add_match(bus, NULL, "", NULL, NULL);
1072 log_error("Failed to add match: %s", strerror(-r));
1078 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1080 r = sd_bus_process(bus, &m);
1082 log_error("Failed to process bus: %s", strerror(-r));
1094 r = sd_bus_wait(bus, (uint64_t) -1);
1096 log_error("Failed to wait for bus: %s", strerror(-r));
1102 static int capture(sd_bus *bus, char *argv[]) {
1105 if (isatty(fileno(stdout)) > 0) {
1106 log_error("Refusing to write message data to console, please redirect output to a file.");
1110 bus_pcap_header(arg_snaplen, stdout);
1112 r = monitor(bus, argv, message_pcap);
1116 if (ferror(stdout)) {
1117 log_error("Couldn't write capture file.");
1124 static int status(sd_bus *bus, char *argv[]) {
1125 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1131 if (strv_length(argv) != 2) {
1132 log_error("Expects one argument.");
1136 r = parse_pid(argv[1], &pid);
1138 r = sd_bus_get_name_creds(bus, argv[1], _SD_BUS_CREDS_ALL, &creds);
1140 r = sd_bus_creds_new_from_pid(&creds, pid, _SD_BUS_CREDS_ALL);
1143 log_error("Failed to get credentials: %s", strerror(-r));
1147 bus_creds_dump(creds, NULL);
1151 static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
1171 log_error("Too few parameters for signature.");
1180 case SD_BUS_TYPE_BOOLEAN:
1182 r = parse_boolean(v);
1184 log_error("Failed to parse as boolean: %s", v);
1188 r = sd_bus_message_append_basic(m, t, &r);
1191 case SD_BUS_TYPE_BYTE: {
1194 r = safe_atou8(v, &z);
1196 log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
1200 r = sd_bus_message_append_basic(m, t, &z);
1204 case SD_BUS_TYPE_INT16: {
1207 r = safe_atoi16(v, &z);
1209 log_error("Failed to parse as signed 16bit integer: %s", v);
1213 r = sd_bus_message_append_basic(m, t, &z);
1217 case SD_BUS_TYPE_UINT16: {
1220 r = safe_atou16(v, &z);
1222 log_error("Failed to parse as unsigned 16bit integer: %s", v);
1226 r = sd_bus_message_append_basic(m, t, &z);
1230 case SD_BUS_TYPE_INT32: {
1233 r = safe_atoi32(v, &z);
1235 log_error("Failed to parse as signed 32bit integer: %s", v);
1239 r = sd_bus_message_append_basic(m, t, &z);
1243 case SD_BUS_TYPE_UINT32: {
1246 r = safe_atou32(v, &z);
1248 log_error("Failed to parse as unsigned 32bit integer: %s", v);
1252 r = sd_bus_message_append_basic(m, t, &z);
1256 case SD_BUS_TYPE_INT64: {
1259 r = safe_atoi64(v, &z);
1261 log_error("Failed to parse as signed 64bit integer: %s", v);
1265 r = sd_bus_message_append_basic(m, t, &z);
1269 case SD_BUS_TYPE_UINT64: {
1272 r = safe_atou64(v, &z);
1274 log_error("Failed to parse as unsigned 64bit integer: %s", v);
1278 r = sd_bus_message_append_basic(m, t, &z);
1283 case SD_BUS_TYPE_DOUBLE: {
1286 r = safe_atod(v, &z);
1288 log_error("Failed to parse as double precision floating point: %s", v);
1292 r = sd_bus_message_append_basic(m, t, &z);
1296 case SD_BUS_TYPE_STRING:
1297 case SD_BUS_TYPE_OBJECT_PATH:
1298 case SD_BUS_TYPE_SIGNATURE:
1300 r = sd_bus_message_append_basic(m, t, v);
1303 case SD_BUS_TYPE_ARRAY: {
1307 r = safe_atou32(v, &n);
1309 log_error("Failed to parse number of array entries: %s", v);
1313 r = signature_element_length(signature, &k);
1315 log_error("Invalid array signature.");
1322 memcpy(s, signature, k);
1325 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1327 return bus_log_create_error(r);
1329 for (i = 0; i < n; i++) {
1330 r = message_append_cmdline(m, s, &p);
1338 r = sd_bus_message_close_container(m);
1342 case SD_BUS_TYPE_VARIANT:
1343 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v);
1345 return bus_log_create_error(r);
1347 r = message_append_cmdline(m, v, &p);
1351 r = sd_bus_message_close_container(m);
1354 case SD_BUS_TYPE_STRUCT_BEGIN:
1355 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1361 r = signature_element_length(signature, &k);
1363 log_error("Invalid struct/dict entry signature.");
1369 memcpy(s, signature + 1, k - 2);
1372 r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1374 return bus_log_create_error(r);
1376 r = message_append_cmdline(m, s, &p);
1383 r = sd_bus_message_close_container(m);
1387 case SD_BUS_TYPE_UNIX_FD:
1388 log_error("UNIX file descriptor not supported as type.");
1392 log_error("Unknown signature type %c.", t);
1397 return bus_log_create_error(r);
1404 static int call(sd_bus *bus, char *argv[]) {
1405 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1406 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1411 if (strv_length(argv) < 5) {
1412 log_error("Expects at least four arguments.");
1416 r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
1418 log_error("Failed to prepare bus message: %s", strerror(-r));
1422 if (!isempty(argv[5])) {
1427 r = message_append_cmdline(m, argv[5], &p);
1432 log_error("Too many parameters for signature.");
1437 r = sd_bus_call(bus, m, 0, &error, &reply);
1439 log_error("%s", bus_error_message(&error, r));
1443 r = sd_bus_message_is_empty(reply);
1445 return bus_log_parse_error(r);
1446 if (r == 0 && !arg_quiet) {
1447 pager_open_if_enabled();
1448 bus_message_dump(reply, stdout, false);
1454 static int help(void) {
1455 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1456 "Introspect the bus.\n\n"
1457 " -h --help Show this help\n"
1458 " --version Show package version\n"
1459 " --no-pager Do not pipe output into a pager\n"
1460 " --no-legend Do not show the headers and footers\n"
1461 " --system Connect to system bus\n"
1462 " --user Connect to user bus\n"
1463 " -H --host=[USER@]HOST Operate on remote host\n"
1464 " -M --machine=CONTAINER Operate on local container\n"
1465 " --address=ADDRESS Connect to bus specified by address\n"
1466 " --show-machine Show machine ID column in list\n"
1467 " --unique Only show unique names\n"
1468 " --acquired Only show acquired names\n"
1469 " --activatable Only show activatable names\n"
1470 " --match=MATCH Only show matching messages\n"
1471 " --list Don't show tree, but simple object path list\n"
1472 " --quiet Don't show method call reply\n\n"
1474 " list List bus names\n"
1475 " tree [SERVICE...] Show object tree of service\n"
1476 " monitor [SERVICE...] Show bus traffic\n"
1477 " capture [SERVICE...] Capture bus traffic as pcap\n"
1478 " status SERVICE Show service name status\n"
1479 " call SERVICE PATH INTERFACE METHOD [SIGNATURE] [ARGUMENTS...]\n"
1481 " help Show this help\n"
1482 , program_invocation_short_name);
1487 static int parse_argv(int argc, char *argv[]) {
1490 ARG_VERSION = 0x100,
1505 static const struct option options[] = {
1506 { "help", no_argument, NULL, 'h' },
1507 { "version", no_argument, NULL, ARG_VERSION },
1508 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
1509 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1510 { "system", no_argument, NULL, ARG_SYSTEM },
1511 { "user", no_argument, NULL, ARG_USER },
1512 { "address", required_argument, NULL, ARG_ADDRESS },
1513 { "show-machine", no_argument, NULL, ARG_SHOW_MACHINE },
1514 { "unique", no_argument, NULL, ARG_UNIQUE },
1515 { "acquired", no_argument, NULL, ARG_ACQUIRED },
1516 { "activatable", no_argument, NULL, ARG_ACTIVATABLE },
1517 { "match", required_argument, NULL, ARG_MATCH },
1518 { "host", required_argument, NULL, 'H' },
1519 { "machine", required_argument, NULL, 'M' },
1520 { "size", required_argument, NULL, ARG_SIZE },
1521 { "list", no_argument, NULL, ARG_LIST },
1522 { "quiet", no_argument, NULL, 'q' },
1531 while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0)
1539 puts(PACKAGE_STRING);
1540 puts(SYSTEMD_FEATURES);
1544 arg_no_pager = true;
1560 arg_address = optarg;
1563 case ARG_SHOW_MACHINE:
1564 arg_show_machine = true;
1572 arg_acquired = true;
1575 case ARG_ACTIVATABLE:
1576 arg_activatable = true;
1580 if (strv_extend(&arg_matches, optarg) < 0)
1587 r = parse_size(optarg, 0, &o);
1589 log_error("Failed to parse size: %s", optarg);
1593 if ((off_t) (size_t) o != o) {
1594 log_error("Size out of range.");
1598 arg_snaplen = (size_t) o;
1607 arg_transport = BUS_TRANSPORT_REMOTE;
1612 arg_transport = BUS_TRANSPORT_CONTAINER;
1624 assert_not_reached("Unhandled option");
1630 static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
1633 if (optind >= argc ||
1634 streq(argv[optind], "list"))
1635 return list_bus_names(bus, argv + optind);
1637 if (streq(argv[optind], "monitor"))
1638 return monitor(bus, argv + optind, message_dump);
1640 if (streq(argv[optind], "capture"))
1641 return capture(bus, argv + optind);
1643 if (streq(argv[optind], "status"))
1644 return status(bus, argv + optind);
1646 if (streq(argv[optind], "tree"))
1647 return tree(bus, argv + optind);
1649 if (streq(argv[optind], "call"))
1650 return call(bus, argv + optind);
1652 if (streq(argv[optind], "help"))
1655 log_error("Unknown command '%s'", argv[optind]);
1659 int main(int argc, char *argv[]) {
1660 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1663 log_parse_environment();
1666 r = parse_argv(argc, argv);
1670 r = sd_bus_new(&bus);
1672 log_error("Failed to allocate bus: %s", strerror(-r));
1676 if (streq_ptr(argv[optind], "monitor") ||
1677 streq_ptr(argv[optind], "capture")) {
1679 r = sd_bus_set_monitor(bus, true);
1681 log_error("Failed to set monitor mode: %s", strerror(-r));
1685 r = sd_bus_negotiate_creds(bus, _SD_BUS_CREDS_ALL);
1687 log_error("Failed to enable credentials: %s", strerror(-r));
1691 r = sd_bus_negotiate_timestamp(bus, true);
1693 log_error("Failed to enable timestamps: %s", strerror(-r));
1697 r = sd_bus_negotiate_fds(bus, true);
1699 log_error("Failed to enable fds: %s", strerror(-r));
1705 r = sd_bus_set_address(bus, arg_address);
1707 switch (arg_transport) {
1709 case BUS_TRANSPORT_LOCAL:
1711 r = bus_set_address_user(bus);
1713 r = bus_set_address_system(bus);
1716 case BUS_TRANSPORT_REMOTE:
1717 r = bus_set_address_system_remote(bus, arg_host);
1720 case BUS_TRANSPORT_CONTAINER:
1721 r = bus_set_address_system_container(bus, arg_host);
1725 assert_not_reached("Hmm, unknown transport type.");
1729 log_error("Failed to set address: %s", strerror(-r));
1733 r = sd_bus_set_bus_client(bus, true);
1735 log_error("Failed to set bus client: %s", strerror(-r));
1739 r = sd_bus_start(bus);
1741 log_error("Failed to connect to bus: %s", strerror(-r));
1745 r = busctl_main(bus, argc, argv);
1750 strv_free(arg_matches);
1752 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;