1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
10 #include "bus-internal.h"
11 #include "bus-signature.h"
14 #include "busctl-introspect.h"
19 #include "locale-util.h"
21 #include "main-func.h"
23 #include "parse-util.h"
24 #include "path-util.h"
25 #include "pretty-print.h"
28 #include "terminal-util.h"
29 #include "user-util.h"
37 } arg_json
= JSON_OFF
;
38 static PagerFlags arg_pager_flags
= 0;
39 static bool arg_legend
= true;
40 static const char *arg_address
= NULL
;
41 static bool arg_unique
= false;
42 static bool arg_acquired
= false;
43 static bool arg_activatable
= false;
44 static bool arg_show_machine
= false;
45 static char **arg_matches
= NULL
;
46 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
47 static const char *arg_host
= NULL
;
48 static bool arg_user
= false;
49 static size_t arg_snaplen
= 4096;
50 static bool arg_list
= false;
51 static bool arg_quiet
= false;
52 static bool arg_verbose
= false;
53 static bool arg_expect_reply
= true;
54 static bool arg_auto_start
= true;
55 static bool arg_allow_interactive_authorization
= true;
56 static bool arg_augment_creds
= true;
57 static bool arg_watch_bind
= false;
58 static usec_t arg_timeout
= 0;
60 STATIC_DESTRUCTOR_REGISTER(arg_matches
, strv_freep
);
62 #define NAME_IS_ACQUIRED INT_TO_PTR(1)
63 #define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
65 static int acquire_bus(bool set_monitor
, sd_bus
**ret
) {
66 _cleanup_(sd_bus_unrefp
) sd_bus
*bus
= NULL
;
71 return log_error_errno(r
, "Failed to allocate bus: %m");
74 r
= sd_bus_set_monitor(bus
, true);
76 return log_error_errno(r
, "Failed to set monitor mode: %m");
78 r
= sd_bus_negotiate_creds(bus
, true, _SD_BUS_CREDS_ALL
);
80 return log_error_errno(r
, "Failed to enable credentials: %m");
82 r
= sd_bus_negotiate_timestamp(bus
, true);
84 return log_error_errno(r
, "Failed to enable timestamps: %m");
86 r
= sd_bus_negotiate_fds(bus
, true);
88 return log_error_errno(r
, "Failed to enable fds: %m");
91 r
= sd_bus_set_bus_client(bus
, true);
93 return log_error_errno(r
, "Failed to set bus client: %m");
95 r
= sd_bus_set_watch_bind(bus
, arg_watch_bind
);
97 return log_error_errno(r
, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind
));
100 r
= sd_bus_set_address(bus
, arg_address
);
102 switch (arg_transport
) {
104 case BUS_TRANSPORT_LOCAL
:
107 r
= bus_set_address_user(bus
);
109 bus
->is_system
= true;
110 r
= bus_set_address_system(bus
);
114 case BUS_TRANSPORT_REMOTE
:
115 r
= bus_set_address_system_remote(bus
, arg_host
);
118 case BUS_TRANSPORT_MACHINE
:
119 r
= bus_set_address_system_machine(bus
, arg_host
);
123 assert_not_reached("Hmm, unknown transport type.");
127 return log_error_errno(r
, "Failed to set address: %m");
129 r
= sd_bus_start(bus
);
131 return log_error_errno(r
, "Failed to connect to bus: %m");
133 *ret
= TAKE_PTR(bus
);
138 static int list_bus_names(int argc
, char **argv
, void *userdata
) {
139 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
140 _cleanup_strv_free_
char **acquired
= NULL
, **activatable
= NULL
;
141 _cleanup_free_
char **merged
= NULL
;
142 _cleanup_hashmap_free_ Hashmap
*names
= NULL
;
151 if (!arg_unique
&& !arg_acquired
&& !arg_activatable
)
152 arg_unique
= arg_acquired
= arg_activatable
= true;
154 r
= acquire_bus(false, &bus
);
158 r
= sd_bus_list_names(bus
, (arg_acquired
|| arg_unique
) ? &acquired
: NULL
, arg_activatable
? &activatable
: NULL
);
160 return log_error_errno(r
, "Failed to list names: %m");
162 (void) pager_open(arg_pager_flags
);
164 names
= hashmap_new(&string_hash_ops
);
168 STRV_FOREACH(i
, acquired
) {
169 max_i
= MAX(max_i
, strlen(*i
));
171 r
= hashmap_put(names
, *i
, NAME_IS_ACQUIRED
);
173 return log_error_errno(r
, "Failed to add to hashmap: %m");
176 STRV_FOREACH(i
, activatable
) {
177 max_i
= MAX(max_i
, strlen(*i
));
179 r
= hashmap_put(names
, *i
, NAME_IS_ACTIVATABLE
);
180 if (r
< 0 && r
!= -EEXIST
)
181 return log_error_errno(r
, "Failed to add to hashmap: %m");
184 merged
= new(char*, hashmap_size(names
) + 1);
188 HASHMAP_FOREACH_KEY(v
, k
, names
, iterator
)
195 printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
196 (int) max_i
, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
198 if (arg_show_machine
)
204 STRV_FOREACH(i
, merged
) {
205 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
208 if (hashmap_get(names
, *i
) == NAME_IS_ACTIVATABLE
) {
211 printf("%-*s", (int) max_i
, *i
);
212 printf(" - - - (activatable) - - ");
213 if (arg_show_machine
)
221 if (!arg_unique
&& (*i
)[0] == ':')
224 if (!arg_acquired
&& (*i
)[0] != ':')
227 printf("%-*s", (int) max_i
, *i
);
229 r
= sd_bus_get_name_creds(
231 (arg_augment_creds
? SD_BUS_CREDS_AUGMENT
: 0) |
232 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
|SD_BUS_CREDS_COMM
|
233 SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_UNIT
|SD_BUS_CREDS_SESSION
|
234 SD_BUS_CREDS_DESCRIPTION
, &creds
);
236 const char *unique
, *session
, *unit
, *cn
;
240 r
= sd_bus_creds_get_pid(creds
, &pid
);
242 const char *comm
= NULL
;
244 sd_bus_creds_get_comm(creds
, &comm
);
246 printf(" %10lu %-15s", (unsigned long) pid
, strna(comm
));
248 fputs(" - - ", stdout
);
250 r
= sd_bus_creds_get_euid(creds
, &uid
);
252 _cleanup_free_
char *u
= NULL
;
254 u
= uid_to_name(uid
);
263 fputs(" - ", stdout
);
265 r
= sd_bus_creds_get_unique_name(creds
, &unique
);
267 printf(" %-13s", unique
);
269 fputs(" - ", stdout
);
271 r
= sd_bus_creds_get_unit(creds
, &unit
);
273 _cleanup_free_
char *e
;
275 e
= ellipsize(unit
, 25, 100);
281 fputs(" - ", stdout
);
283 r
= sd_bus_creds_get_session(creds
, &session
);
285 printf(" %-10s", session
);
287 fputs(" - ", stdout
);
289 r
= sd_bus_creds_get_description(creds
, &cn
);
291 printf(" %-19s", cn
);
293 fputs(" - ", stdout
);
296 printf(" - - - - - - - ");
298 if (arg_show_machine
) {
299 r
= sd_bus_get_name_machine_id(bus
, *i
, &mid
);
301 char m
[SD_ID128_STRING_MAX
];
302 printf(" %s\n", sd_id128_to_string(mid
, m
));
312 static void print_subtree(const char *prefix
, const char *path
, char **l
) {
313 const char *vertical
, *space
;
316 /* We assume the list is sorted. Let's first skip over the
317 * entry we are looking at. */
322 if (!streq(*l
, path
))
328 vertical
= strjoina(prefix
, special_glyph(TREE_VERTICAL
));
329 space
= strjoina(prefix
, special_glyph(TREE_SPACE
));
332 bool has_more
= false;
334 if (!*l
|| !path_startswith(*l
, path
))
339 if (!*n
|| !path_startswith(*n
, path
))
342 if (!path_startswith(*n
, *l
)) {
350 printf("%s%s%s\n", prefix
, special_glyph(has_more
? TREE_BRANCH
: TREE_RIGHT
), *l
);
352 print_subtree(has_more
? vertical
: space
, *l
, l
);
357 static void print_tree(const char *prefix
, char **l
) {
359 prefix
= strempty(prefix
);
365 printf("%s%s\n", prefix
, *i
);
369 if (strv_isempty(l
)) {
370 printf("No objects discovered.\n");
374 if (streq(l
[0], "/") && !l
[1]) {
375 printf("Only root object discovered.\n");
379 print_subtree(prefix
, "/", l
);
382 static int on_path(const char *path
, void *userdata
) {
383 Set
*paths
= userdata
;
388 r
= set_put_strdup(paths
, path
);
395 static int find_nodes(sd_bus
*bus
, const char *service
, const char *path
, Set
*paths
, bool many
) {
396 static const XMLIntrospectOps ops
= {
400 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
401 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
405 r
= sd_bus_call_method(bus
, service
, path
, "org.freedesktop.DBus.Introspectable", "Introspect", &error
, &reply
, "");
408 printf("Failed to introspect object %s of service %s: %s\n", path
, service
, bus_error_message(&error
, r
));
410 log_error_errno(r
, "Failed to introspect object %s of service %s: %s", path
, service
, bus_error_message(&error
, r
));
414 r
= sd_bus_message_read(reply
, "s", &xml
);
416 return bus_log_parse_error(r
);
418 return parse_xml_introspect(path
, xml
, &ops
, paths
);
421 static int tree_one(sd_bus
*bus
, const char *service
, const char *prefix
, bool many
) {
422 _cleanup_set_free_free_ Set
*paths
= NULL
, *done
= NULL
, *failed
= NULL
;
423 _cleanup_free_
char **l
= NULL
;
427 paths
= set_new(&string_hash_ops
);
431 done
= set_new(&string_hash_ops
);
435 failed
= set_new(&string_hash_ops
);
443 r
= set_put(paths
, m
);
450 _cleanup_free_
char *p
= NULL
;
453 p
= set_steal_first(paths
);
457 if (set_contains(done
, p
) ||
458 set_contains(failed
, p
))
461 q
= find_nodes(bus
, service
, p
, paths
, many
);
466 q
= set_put(failed
, p
);
468 q
= set_put(done
, p
);
477 (void) pager_open(arg_pager_flags
);
479 l
= set_get_strv(done
);
484 print_tree(prefix
, l
);
491 static int tree(int argc
, char **argv
, void *userdata
) {
492 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
496 if (!arg_unique
&& !arg_acquired
)
499 r
= acquire_bus(false, &bus
);
504 _cleanup_strv_free_
char **names
= NULL
;
505 bool not_first
= false;
507 r
= sd_bus_list_names(bus
, &names
, NULL
);
509 return log_error_errno(r
, "Failed to get name list: %m");
511 (void) pager_open(arg_pager_flags
);
513 STRV_FOREACH(i
, names
) {
516 if (!arg_unique
&& (*i
)[0] == ':')
519 if (!arg_acquired
&& (*i
)[0] == ':')
525 printf("Service %s%s%s:\n", ansi_highlight(), *i
, ansi_normal());
527 q
= tree_one(bus
, *i
, NULL
, true);
534 STRV_FOREACH(i
, argv
+1) {
541 (void) pager_open(arg_pager_flags
);
542 printf("Service %s%s%s:\n", ansi_highlight(), *i
, ansi_normal());
545 q
= tree_one(bus
, *i
, NULL
, !!argv
[2]);
554 static int format_cmdline(sd_bus_message
*m
, FILE *f
, bool needs_space
) {
558 const char *contents
= NULL
;
573 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
579 if (bus_type_is_container(type
) > 0) {
581 r
= sd_bus_message_enter_container(m
, type
, contents
);
585 if (type
== SD_BUS_TYPE_ARRAY
) {
588 /* count array entries */
591 r
= sd_bus_message_skip(m
, contents
);
600 r
= sd_bus_message_rewind(m
, false);
610 } else if (type
== SD_BUS_TYPE_VARIANT
) {
615 fprintf(f
, "%s", contents
);
619 r
= format_cmdline(m
, f
, needs_space
);
625 r
= sd_bus_message_exit_container(m
);
632 r
= sd_bus_message_read_basic(m
, type
, &basic
);
640 case SD_BUS_TYPE_BYTE
:
641 fprintf(f
, "%u", basic
.u8
);
644 case SD_BUS_TYPE_BOOLEAN
:
645 fputs(true_false(basic
.i
), f
);
648 case SD_BUS_TYPE_INT16
:
649 fprintf(f
, "%i", basic
.s16
);
652 case SD_BUS_TYPE_UINT16
:
653 fprintf(f
, "%u", basic
.u16
);
656 case SD_BUS_TYPE_INT32
:
657 fprintf(f
, "%i", basic
.s32
);
660 case SD_BUS_TYPE_UINT32
:
661 fprintf(f
, "%u", basic
.u32
);
664 case SD_BUS_TYPE_INT64
:
665 fprintf(f
, "%" PRIi64
, basic
.s64
);
668 case SD_BUS_TYPE_UINT64
:
669 fprintf(f
, "%" PRIu64
, basic
.u64
);
672 case SD_BUS_TYPE_DOUBLE
:
673 fprintf(f
, "%g", basic
.d64
);
676 case SD_BUS_TYPE_STRING
:
677 case SD_BUS_TYPE_OBJECT_PATH
:
678 case SD_BUS_TYPE_SIGNATURE
: {
679 _cleanup_free_
char *b
= NULL
;
681 b
= cescape(basic
.string
);
685 fprintf(f
, "\"%s\"", b
);
689 case SD_BUS_TYPE_UNIX_FD
:
690 fprintf(f
, "%i", basic
.i
);
694 assert_not_reached("Unknown basic type.");
701 typedef struct Member
{
712 static void member_hash_func(const void *p
, struct siphash
*state
) {
719 string_hash_func(m
->type
, state
);
721 arity
+= !!m
->name
+ !!m
->interface
;
723 uint64_hash_func(&arity
, state
);
726 string_hash_func(m
->name
, state
);
729 string_hash_func(m
->interface
, state
);
732 static int member_compare_func(const Member
*x
, const Member
*y
) {
740 d
= strcmp_ptr(x
->interface
, y
->interface
);
744 d
= strcmp(x
->type
, y
->type
);
748 return strcmp_ptr(x
->name
, y
->name
);
751 static int member_compare_funcp(Member
* const *a
, Member
* const *b
) {
752 return member_compare_func(*a
, *b
);
755 static void member_free(Member
*m
) {
767 DEFINE_TRIVIAL_CLEANUP_FUNC(Member
*, member_free
);
769 static void member_set_free(Set
*s
) {
770 set_free_with_destructor(s
, member_free
);
773 DEFINE_TRIVIAL_CLEANUP_FUNC(Set
*, member_set_free
);
775 static int on_interface(const char *interface
, uint64_t flags
, void *userdata
) {
776 _cleanup_(member_freep
) Member
*m
;
777 Set
*members
= userdata
;
787 m
->type
= "interface";
790 r
= free_and_strdup(&m
->interface
, interface
);
794 r
= set_put(members
, m
);
796 log_error("Duplicate interface");
804 static int on_method(const char *interface
, const char *name
, const char *signature
, const char *result
, uint64_t flags
, void *userdata
) {
805 _cleanup_(member_freep
) Member
*m
;
806 Set
*members
= userdata
;
819 r
= free_and_strdup(&m
->interface
, interface
);
823 r
= free_and_strdup(&m
->name
, name
);
827 r
= free_and_strdup(&m
->signature
, signature
);
831 r
= free_and_strdup(&m
->result
, result
);
835 r
= set_put(members
, m
);
837 log_error("Duplicate method");
845 static int on_signal(const char *interface
, const char *name
, const char *signature
, uint64_t flags
, void *userdata
) {
846 _cleanup_(member_freep
) Member
*m
;
847 Set
*members
= userdata
;
860 r
= free_and_strdup(&m
->interface
, interface
);
864 r
= free_and_strdup(&m
->name
, name
);
868 r
= free_and_strdup(&m
->signature
, signature
);
872 r
= set_put(members
, m
);
874 log_error("Duplicate signal");
882 static int on_property(const char *interface
, const char *name
, const char *signature
, bool writable
, uint64_t flags
, void *userdata
) {
883 _cleanup_(member_freep
) Member
*m
;
884 Set
*members
= userdata
;
894 m
->type
= "property";
896 m
->writable
= writable
;
898 r
= free_and_strdup(&m
->interface
, interface
);
902 r
= free_and_strdup(&m
->name
, name
);
906 r
= free_and_strdup(&m
->signature
, signature
);
910 r
= set_put(members
, m
);
912 log_error("Duplicate property");
920 static int introspect(int argc
, char **argv
, void *userdata
) {
921 static const struct hash_ops member_hash_ops
= {
922 .hash
= member_hash_func
,
923 .compare
= (__compar_fn_t
) member_compare_func
,
926 static const XMLIntrospectOps ops
= {
927 .on_interface
= on_interface
,
928 .on_method
= on_method
,
929 .on_signal
= on_signal
,
930 .on_property
= on_property
,
933 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
934 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply_xml
= NULL
;
935 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
936 _cleanup_(member_set_freep
) Set
*members
= NULL
;
937 unsigned name_width
, type_width
, signature_width
, result_width
, j
, k
= 0;
938 Member
*m
, **sorted
= NULL
;
943 r
= acquire_bus(false, &bus
);
947 members
= set_new(&member_hash_ops
);
951 r
= sd_bus_call_method(bus
, argv
[1], argv
[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error
, &reply_xml
, "");
953 return log_error_errno(r
, "Failed to introspect object %s of service %s: %s", argv
[2], argv
[1], bus_error_message(&error
, r
));
955 r
= sd_bus_message_read(reply_xml
, "s", &xml
);
957 return bus_log_parse_error(r
);
959 /* First, get list of all properties */
960 r
= parse_xml_introspect(argv
[2], xml
, &ops
, members
);
964 /* Second, find the current values for them */
965 SET_FOREACH(m
, members
, i
) {
966 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
968 if (!streq(m
->type
, "property"))
974 if (argv
[3] && !streq(argv
[3], m
->interface
))
977 r
= sd_bus_call_method(bus
, argv
[1], argv
[2], "org.freedesktop.DBus.Properties", "GetAll", &error
, &reply
, "s", m
->interface
);
979 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
981 r
= sd_bus_message_enter_container(reply
, 'a', "{sv}");
983 return bus_log_parse_error(r
);
987 _cleanup_free_
char *buf
= NULL
;
988 _cleanup_fclose_
FILE *mf
= NULL
;
992 r
= sd_bus_message_enter_container(reply
, 'e', "sv");
994 return bus_log_parse_error(r
);
999 r
= sd_bus_message_read(reply
, "s", &name
);
1001 return bus_log_parse_error(r
);
1003 r
= sd_bus_message_enter_container(reply
, 'v', NULL
);
1005 return bus_log_parse_error(r
);
1007 mf
= open_memstream(&buf
, &sz
);
1011 (void) __fsetlocking(mf
, FSETLOCKING_BYCALLER
);
1013 r
= format_cmdline(reply
, mf
, false);
1015 return bus_log_parse_error(r
);
1017 mf
= safe_fclose(mf
);
1019 z
= set_get(members
, &((Member
) {
1021 .interface
= m
->interface
,
1022 .name
= (char*) name
}));
1024 free_and_replace(z
->value
, buf
);
1026 r
= sd_bus_message_exit_container(reply
);
1028 return bus_log_parse_error(r
);
1030 r
= sd_bus_message_exit_container(reply
);
1032 return bus_log_parse_error(r
);
1035 r
= sd_bus_message_exit_container(reply
);
1037 return bus_log_parse_error(r
);
1040 (void) pager_open(arg_pager_flags
);
1042 name_width
= STRLEN("NAME");
1043 type_width
= STRLEN("TYPE");
1044 signature_width
= STRLEN("SIGNATURE");
1045 result_width
= STRLEN("RESULT/VALUE");
1047 sorted
= newa(Member
*, set_size(members
));
1049 SET_FOREACH(m
, members
, i
) {
1051 if (argv
[3] && !streq(argv
[3], m
->interface
))
1055 name_width
= MAX(name_width
, strlen(m
->interface
));
1057 name_width
= MAX(name_width
, strlen(m
->name
) + 1);
1059 type_width
= MAX(type_width
, strlen(m
->type
));
1061 signature_width
= MAX(signature_width
, strlen(m
->signature
));
1063 result_width
= MAX(result_width
, strlen(m
->result
));
1065 result_width
= MAX(result_width
, strlen(m
->value
));
1070 if (result_width
> 40)
1073 typesafe_qsort(sorted
, k
, member_compare_funcp
);
1076 printf("%-*s %-*s %-*s %-*s %s\n",
1077 (int) name_width
, "NAME",
1078 (int) type_width
, "TYPE",
1079 (int) signature_width
, "SIGNATURE",
1080 (int) result_width
, "RESULT/VALUE",
1084 for (j
= 0; j
< k
; j
++) {
1085 _cleanup_free_
char *ellipsized
= NULL
;
1091 if (argv
[3] && !streq(argv
[3], m
->interface
))
1094 is_interface
= streq(m
->type
, "interface");
1096 if (argv
[3] && is_interface
)
1100 ellipsized
= ellipsize(m
->value
, result_width
, 100);
1106 rv
= empty_to_dash(m
->result
);
1108 printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
1109 is_interface
? ansi_highlight() : "",
1110 is_interface
? "" : ".",
1111 - !is_interface
+ (int) name_width
, empty_to_dash(streq_ptr(m
->type
, "interface") ? m
->interface
: m
->name
),
1112 is_interface
? ansi_normal() : "",
1113 (int) type_width
, empty_to_dash(m
->type
),
1114 (int) signature_width
, empty_to_dash(m
->signature
),
1115 (int) result_width
, rv
,
1116 (m
->flags
& SD_BUS_VTABLE_DEPRECATED
) ? " deprecated" : (m
->flags
|| m
->writable
? "" : " -"),
1117 (m
->flags
& SD_BUS_VTABLE_METHOD_NO_REPLY
) ? " no-reply" : "",
1118 (m
->flags
& SD_BUS_VTABLE_PROPERTY_CONST
) ? " const" : "",
1119 (m
->flags
& SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
) ? " emits-change" : "",
1120 (m
->flags
& SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
) ? " emits-invalidation" : "",
1121 m
->writable
? " writable" : "");
1127 static int message_dump(sd_bus_message
*m
, FILE *f
) {
1128 return bus_message_dump(m
, f
, BUS_MESSAGE_DUMP_WITH_HEADER
);
1131 static int message_pcap(sd_bus_message
*m
, FILE *f
) {
1132 return bus_message_pcap_frame(m
, arg_snaplen
, f
);
1135 static int monitor(int argc
, char **argv
, int (*dump
)(sd_bus_message
*m
, FILE *f
)) {
1136 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1137 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*message
= NULL
;
1138 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1141 const char *unique_name
;
1142 bool is_monitor
= false;
1145 r
= acquire_bus(true, &bus
);
1149 /* upgrade connection; it's not used for anything else after this call */
1150 r
= sd_bus_message_new_method_call(bus
, &message
, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
1152 return bus_log_create_error(r
);
1154 r
= sd_bus_message_open_container(message
, 'a', "s");
1156 return bus_log_create_error(r
);
1158 STRV_FOREACH(i
, argv
+1) {
1159 _cleanup_free_
char *m
= NULL
;
1161 if (!service_name_is_valid(*i
)) {
1162 log_error("Invalid service name '%s'", *i
);
1166 m
= strjoin("sender='", *i
, "'");
1170 r
= sd_bus_message_append_basic(message
, 's', m
);
1172 return bus_log_create_error(r
);
1175 m
= strjoin("destination='", *i
, "'");
1179 r
= sd_bus_message_append_basic(message
, 's', m
);
1181 return bus_log_create_error(r
);
1184 STRV_FOREACH(i
, arg_matches
) {
1185 r
= sd_bus_message_append_basic(message
, 's', *i
);
1187 return bus_log_create_error(r
);
1190 r
= sd_bus_message_close_container(message
);
1192 return bus_log_create_error(r
);
1194 r
= sd_bus_message_append_basic(message
, 'u', &flags
);
1196 return bus_log_create_error(r
);
1198 r
= sd_bus_call(bus
, message
, arg_timeout
, &error
, NULL
);
1200 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
1202 r
= sd_bus_get_unique_name(bus
, &unique_name
);
1204 return log_error_errno(r
, "Failed to get unique name: %m");
1206 log_info("Monitoring bus message stream.");
1209 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1211 r
= sd_bus_process(bus
, &m
);
1213 return log_error_errno(r
, "Failed to process bus: %m");
1218 /* wait until we lose our unique name */
1219 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus", "NameLost") <= 0)
1222 r
= sd_bus_message_read(m
, "s", &name
);
1224 return log_error_errno(r
, "Failed to read lost name: %m");
1226 if (streq(name
, unique_name
))
1236 if (sd_bus_message_is_signal(m
, "org.freedesktop.DBus.Local", "Disconnected") > 0) {
1237 log_info("Connection terminated, exiting.");
1247 r
= sd_bus_wait(bus
, (uint64_t) -1);
1249 return log_error_errno(r
, "Failed to wait for bus: %m");
1253 static int verb_monitor(int argc
, char **argv
, void *userdata
) {
1254 return monitor(argc
, argv
, message_dump
);
1257 static int verb_capture(int argc
, char **argv
, void *userdata
) {
1260 if (isatty(fileno(stdout
)) > 0)
1261 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1262 "Refusing to write message data to console, please redirect output to a file.");
1264 bus_pcap_header(arg_snaplen
, stdout
);
1266 r
= monitor(argc
, argv
, message_pcap
);
1270 r
= fflush_and_check(stdout
);
1272 return log_error_errno(r
, "Couldn't write capture file: %m");
1277 static int status(int argc
, char **argv
, void *userdata
) {
1278 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1279 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1283 r
= acquire_bus(false, &bus
);
1287 if (!isempty(argv
[1])) {
1288 r
= parse_pid(argv
[1], &pid
);
1290 r
= sd_bus_get_name_creds(
1293 (arg_augment_creds
? SD_BUS_CREDS_AUGMENT
: 0) | _SD_BUS_CREDS_ALL
,
1296 r
= sd_bus_creds_new_from_pid(
1301 const char *scope
, *address
;
1304 r
= sd_bus_get_address(bus
, &address
);
1306 printf("BusAddress=%s%s%s\n", ansi_highlight(), address
, ansi_normal());
1308 r
= sd_bus_get_scope(bus
, &scope
);
1310 printf("BusScope=%s%s%s\n", ansi_highlight(), scope
, ansi_normal());
1312 r
= sd_bus_get_bus_id(bus
, &bus_id
);
1314 printf("BusID=%s" SD_ID128_FORMAT_STR
"%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id
), ansi_normal());
1316 r
= sd_bus_get_owner_creds(
1318 (arg_augment_creds
? SD_BUS_CREDS_AUGMENT
: 0) | _SD_BUS_CREDS_ALL
,
1323 return log_error_errno(r
, "Failed to get credentials: %m");
1325 bus_creds_dump(creds
, NULL
, false);
1329 static int message_append_cmdline(sd_bus_message
*m
, const char *signature
, char ***x
) {
1349 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1350 "Too few parameters for signature.");
1357 case SD_BUS_TYPE_BOOLEAN
:
1359 r
= parse_boolean(v
);
1361 return log_error_errno(r
, "Failed to parse '%s' as boolean: %m", v
);
1363 r
= sd_bus_message_append_basic(m
, t
, &r
);
1366 case SD_BUS_TYPE_BYTE
: {
1369 r
= safe_atou8(v
, &z
);
1371 return log_error_errno(r
, "Failed to parse '%s' as byte (unsigned 8bit integer): %m", v
);
1373 r
= sd_bus_message_append_basic(m
, t
, &z
);
1377 case SD_BUS_TYPE_INT16
: {
1380 r
= safe_atoi16(v
, &z
);
1382 return log_error_errno(r
, "Failed to parse '%s' as signed 16bit integer: %m", v
);
1384 r
= sd_bus_message_append_basic(m
, t
, &z
);
1388 case SD_BUS_TYPE_UINT16
: {
1391 r
= safe_atou16(v
, &z
);
1393 return log_error_errno(r
, "Failed to parse '%s' as unsigned 16bit integer: %m", v
);
1395 r
= sd_bus_message_append_basic(m
, t
, &z
);
1399 case SD_BUS_TYPE_INT32
: {
1402 r
= safe_atoi32(v
, &z
);
1404 return log_error_errno(r
, "Failed to parse '%s' as signed 32bit integer: %m", v
);
1406 r
= sd_bus_message_append_basic(m
, t
, &z
);
1410 case SD_BUS_TYPE_UINT32
: {
1413 r
= safe_atou32(v
, &z
);
1415 return log_error_errno(r
, "Failed to parse '%s' as unsigned 32bit integer: %m", v
);
1417 r
= sd_bus_message_append_basic(m
, t
, &z
);
1421 case SD_BUS_TYPE_INT64
: {
1424 r
= safe_atoi64(v
, &z
);
1426 return log_error_errno(r
, "Failed to parse '%s' as signed 64bit integer: %m", v
);
1428 r
= sd_bus_message_append_basic(m
, t
, &z
);
1432 case SD_BUS_TYPE_UINT64
: {
1435 r
= safe_atou64(v
, &z
);
1437 return log_error_errno(r
, "Failed to parse '%s' as unsigned 64bit integer: %m", v
);
1439 r
= sd_bus_message_append_basic(m
, t
, &z
);
1443 case SD_BUS_TYPE_DOUBLE
: {
1446 r
= safe_atod(v
, &z
);
1448 return log_error_errno(r
, "Failed to parse '%s' as double precision floating point: %m", v
);
1450 r
= sd_bus_message_append_basic(m
, t
, &z
);
1454 case SD_BUS_TYPE_STRING
:
1455 case SD_BUS_TYPE_OBJECT_PATH
:
1456 case SD_BUS_TYPE_SIGNATURE
:
1458 r
= sd_bus_message_append_basic(m
, t
, v
);
1461 case SD_BUS_TYPE_ARRAY
: {
1465 r
= safe_atou32(v
, &n
);
1467 return log_error_errno(r
, "Failed to parse '%s' number of array entries: %m", v
);
1469 r
= signature_element_length(signature
, &k
);
1471 return log_error_errno(r
, "Invalid array signature: %m");
1476 memcpy(s
, signature
, k
);
1479 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
1481 return bus_log_create_error(r
);
1483 for (i
= 0; i
< n
; i
++) {
1484 r
= message_append_cmdline(m
, s
, &p
);
1492 r
= sd_bus_message_close_container(m
);
1496 case SD_BUS_TYPE_VARIANT
:
1497 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, v
);
1499 return bus_log_create_error(r
);
1501 r
= message_append_cmdline(m
, v
, &p
);
1505 r
= sd_bus_message_close_container(m
);
1508 case SD_BUS_TYPE_STRUCT_BEGIN
:
1509 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
1515 r
= signature_element_length(signature
, &k
);
1517 return log_error_errno(r
, "Invalid struct/dict entry signature: %m");
1521 memcpy(s
, signature
+ 1, k
- 2);
1524 r
= sd_bus_message_open_container(m
, t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
1526 return bus_log_create_error(r
);
1528 r
= message_append_cmdline(m
, s
, &p
);
1535 r
= sd_bus_message_close_container(m
);
1539 case SD_BUS_TYPE_UNIX_FD
:
1540 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1541 "UNIX file descriptor not supported as type.");
1544 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1545 "Unknown signature type %c.", t
);
1549 return bus_log_create_error(r
);
1556 static int json_transform_one(sd_bus_message
*m
, JsonVariant
**ret
);
1558 static int json_transform_array_or_struct(sd_bus_message
*m
, JsonVariant
**ret
) {
1559 size_t n_elements
= 0, n_allocated
= 0;
1560 JsonVariant
**elements
= NULL
;
1567 r
= sd_bus_message_at_end(m
, false);
1569 bus_log_parse_error(r
);
1575 if (!GREEDY_REALLOC(elements
, n_allocated
, n_elements
+ 1)) {
1580 r
= json_transform_one(m
, elements
+ n_elements
);
1587 r
= json_variant_new_array(ret
, elements
, n_elements
);
1590 json_variant_unref_many(elements
, n_elements
);
1596 static int json_transform_variant(sd_bus_message
*m
, const char *contents
, JsonVariant
**ret
) {
1597 _cleanup_(json_variant_unrefp
) JsonVariant
*value
= NULL
;
1604 r
= json_transform_one(m
, &value
);
1608 r
= json_build(ret
, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("type", JSON_BUILD_STRING(contents
)),
1609 JSON_BUILD_PAIR("data", JSON_BUILD_VARIANT(value
))));
1616 static int json_transform_dict_array(sd_bus_message
*m
, JsonVariant
**ret
) {
1617 size_t n_elements
= 0, n_allocated
= 0;
1618 JsonVariant
**elements
= NULL
;
1625 const char *contents
;
1628 r
= sd_bus_message_at_end(m
, false);
1630 bus_log_parse_error(r
);
1636 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
1640 assert(type
== 'e');
1642 if (!GREEDY_REALLOC(elements
, n_allocated
, n_elements
+ 2)) {
1647 r
= sd_bus_message_enter_container(m
, type
, contents
);
1649 bus_log_parse_error(r
);
1653 r
= json_transform_one(m
, elements
+ n_elements
);
1659 r
= json_transform_one(m
, elements
+ n_elements
);
1665 r
= sd_bus_message_exit_container(m
);
1667 bus_log_parse_error(r
);
1672 r
= json_variant_new_object(ret
, elements
, n_elements
);
1675 json_variant_unref_many(elements
, n_elements
);
1681 static int json_transform_one(sd_bus_message
*m
, JsonVariant
**ret
) {
1682 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
1683 const char *contents
;
1690 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
1692 return bus_log_parse_error(r
);
1696 case SD_BUS_TYPE_BYTE
: {
1699 r
= sd_bus_message_read_basic(m
, type
, &b
);
1701 return bus_log_parse_error(r
);
1703 r
= json_variant_new_unsigned(&v
, b
);
1705 return log_error_errno(r
, "Failed to transform byte: %m");
1710 case SD_BUS_TYPE_BOOLEAN
: {
1713 r
= sd_bus_message_read_basic(m
, type
, &b
);
1715 return bus_log_parse_error(r
);
1717 r
= json_variant_new_boolean(&v
, b
);
1719 return log_error_errno(r
, "Failed to transform boolean: %m");
1724 case SD_BUS_TYPE_INT16
: {
1727 r
= sd_bus_message_read_basic(m
, type
, &b
);
1729 return bus_log_parse_error(r
);
1731 r
= json_variant_new_integer(&v
, b
);
1733 return log_error_errno(r
, "Failed to transform int16: %m");
1738 case SD_BUS_TYPE_UINT16
: {
1741 r
= sd_bus_message_read_basic(m
, type
, &b
);
1743 return bus_log_parse_error(r
);
1745 r
= json_variant_new_unsigned(&v
, b
);
1747 return log_error_errno(r
, "Failed to transform uint16: %m");
1752 case SD_BUS_TYPE_INT32
: {
1755 r
= sd_bus_message_read_basic(m
, type
, &b
);
1757 return bus_log_parse_error(r
);
1759 r
= json_variant_new_integer(&v
, b
);
1761 return log_error_errno(r
, "Failed to transform int32: %m");
1766 case SD_BUS_TYPE_UINT32
: {
1769 r
= sd_bus_message_read_basic(m
, type
, &b
);
1771 return bus_log_parse_error(r
);
1773 r
= json_variant_new_unsigned(&v
, b
);
1775 return log_error_errno(r
, "Failed to transform uint32: %m");
1780 case SD_BUS_TYPE_INT64
: {
1783 r
= sd_bus_message_read_basic(m
, type
, &b
);
1785 return bus_log_parse_error(r
);
1787 r
= json_variant_new_integer(&v
, b
);
1789 return log_error_errno(r
, "Failed to transform int64: %m");
1794 case SD_BUS_TYPE_UINT64
: {
1797 r
= sd_bus_message_read_basic(m
, type
, &b
);
1799 return bus_log_parse_error(r
);
1801 r
= json_variant_new_unsigned(&v
, b
);
1803 return log_error_errno(r
, "Failed to transform uint64: %m");
1808 case SD_BUS_TYPE_DOUBLE
: {
1811 r
= sd_bus_message_read_basic(m
, type
, &d
);
1813 return bus_log_parse_error(r
);
1815 r
= json_variant_new_real(&v
, d
);
1817 return log_error_errno(r
, "Failed to transform double: %m");
1822 case SD_BUS_TYPE_STRING
:
1823 case SD_BUS_TYPE_OBJECT_PATH
:
1824 case SD_BUS_TYPE_SIGNATURE
: {
1827 r
= sd_bus_message_read_basic(m
, type
, &s
);
1829 return bus_log_parse_error(r
);
1831 r
= json_variant_new_string(&v
, s
);
1833 return log_error_errno(r
, "Failed to transform double: %m");
1838 case SD_BUS_TYPE_UNIX_FD
:
1839 r
= sd_bus_message_read_basic(m
, type
, NULL
);
1841 return bus_log_parse_error(r
);
1843 r
= json_variant_new_null(&v
);
1845 return log_error_errno(r
, "Failed to transform fd: %m");
1849 case SD_BUS_TYPE_ARRAY
:
1850 case SD_BUS_TYPE_VARIANT
:
1851 case SD_BUS_TYPE_STRUCT
:
1852 r
= sd_bus_message_enter_container(m
, type
, contents
);
1854 return bus_log_parse_error(r
);
1856 if (type
== SD_BUS_TYPE_VARIANT
)
1857 r
= json_transform_variant(m
, contents
, &v
);
1858 else if (type
== SD_BUS_TYPE_ARRAY
&& contents
[0] == '{')
1859 r
= json_transform_dict_array(m
, &v
);
1861 r
= json_transform_array_or_struct(m
, &v
);
1865 r
= sd_bus_message_exit_container(m
);
1867 return bus_log_parse_error(r
);
1872 assert_not_reached("Unexpected element type");
1879 static int json_transform_message(sd_bus_message
*m
, JsonVariant
**ret
) {
1880 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
1887 assert_se(type
= sd_bus_message_get_signature(m
, false));
1889 r
= json_transform_array_or_struct(m
, &v
);
1893 r
= json_build(ret
, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("type", JSON_BUILD_STRING(type
)),
1894 JSON_BUILD_PAIR("data", JSON_BUILD_VARIANT(v
))));
1901 static void json_dump_with_flags(JsonVariant
*v
, FILE *f
) {
1903 json_variant_dump(v
,
1904 (arg_json
== JSON_PRETTY
? JSON_FORMAT_PRETTY
: JSON_FORMAT_NEWLINE
) |
1905 colors_enabled() * JSON_FORMAT_COLOR
,
1909 static int call(int argc
, char **argv
, void *userdata
) {
1910 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1911 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1912 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
1915 r
= acquire_bus(false, &bus
);
1919 r
= sd_bus_message_new_method_call(bus
, &m
, argv
[1], argv
[2], argv
[3], argv
[4]);
1921 return bus_log_create_error(r
);
1923 r
= sd_bus_message_set_expect_reply(m
, arg_expect_reply
);
1925 return bus_log_create_error(r
);
1927 r
= sd_bus_message_set_auto_start(m
, arg_auto_start
);
1929 return bus_log_create_error(r
);
1931 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_allow_interactive_authorization
);
1933 return bus_log_create_error(r
);
1935 if (!isempty(argv
[5])) {
1940 r
= message_append_cmdline(m
, argv
[5], &p
);
1945 log_error("Too many parameters for signature.");
1950 if (!arg_expect_reply
) {
1951 r
= sd_bus_send(bus
, m
, NULL
);
1953 return log_error_errno(r
, "Failed to send message: %m");
1958 r
= sd_bus_call(bus
, m
, arg_timeout
, &error
, &reply
);
1960 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
1962 r
= sd_bus_message_is_empty(reply
);
1964 return bus_log_parse_error(r
);
1966 if (r
== 0 && !arg_quiet
) {
1968 if (arg_json
!= JSON_OFF
) {
1969 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
1971 if (arg_json
!= JSON_SHORT
)
1972 (void) pager_open(arg_pager_flags
);
1974 r
= json_transform_message(reply
, &v
);
1978 json_dump_with_flags(v
, stdout
);
1980 } else if (arg_verbose
) {
1981 (void) pager_open(arg_pager_flags
);
1983 r
= bus_message_dump(reply
, stdout
, 0);
1988 fputs(sd_bus_message_get_signature(reply
, true), stdout
);
1991 r
= format_cmdline(reply
, stdout
, false);
1993 return bus_log_parse_error(r
);
1995 fputc('\n', stdout
);
2002 static int get_property(int argc
, char **argv
, void *userdata
) {
2003 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2004 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2008 r
= acquire_bus(false, &bus
);
2012 STRV_FOREACH(i
, argv
+ 4) {
2013 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2014 const char *contents
= NULL
;
2017 r
= sd_bus_call_method(bus
, argv
[1], argv
[2], "org.freedesktop.DBus.Properties", "Get", &error
, &reply
, "ss", argv
[3], *i
);
2019 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
2021 r
= sd_bus_message_peek_type(reply
, &type
, &contents
);
2023 return bus_log_parse_error(r
);
2025 r
= sd_bus_message_enter_container(reply
, 'v', contents
);
2027 return bus_log_parse_error(r
);
2029 if (arg_json
!= JSON_OFF
) {
2030 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
2032 if (arg_json
!= JSON_SHORT
)
2033 (void) pager_open(arg_pager_flags
);
2035 r
= json_transform_variant(reply
, contents
, &v
);
2039 json_dump_with_flags(v
, stdout
);
2041 } else if (arg_verbose
) {
2042 (void) pager_open(arg_pager_flags
);
2044 r
= bus_message_dump(reply
, stdout
, BUS_MESSAGE_DUMP_SUBTREE_ONLY
);
2048 fputs(contents
, stdout
);
2051 r
= format_cmdline(reply
, stdout
, false);
2053 return bus_log_parse_error(r
);
2055 fputc('\n', stdout
);
2058 r
= sd_bus_message_exit_container(reply
);
2060 return bus_log_parse_error(r
);
2066 static int set_property(int argc
, char **argv
, void *userdata
) {
2067 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2068 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
2069 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2073 r
= acquire_bus(false, &bus
);
2077 r
= sd_bus_message_new_method_call(bus
, &m
, argv
[1], argv
[2], "org.freedesktop.DBus.Properties", "Set");
2079 return bus_log_create_error(r
);
2081 r
= sd_bus_message_append(m
, "ss", argv
[3], argv
[4]);
2083 return bus_log_create_error(r
);
2085 r
= sd_bus_message_open_container(m
, 'v', argv
[5]);
2087 return bus_log_create_error(r
);
2090 r
= message_append_cmdline(m
, argv
[5], &p
);
2094 r
= sd_bus_message_close_container(m
);
2096 return bus_log_create_error(r
);
2099 log_error("Too many parameters for signature.");
2103 r
= sd_bus_call(bus
, m
, arg_timeout
, &error
, NULL
);
2105 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
2110 static int help(void) {
2111 _cleanup_free_
char *link
= NULL
;
2114 r
= terminal_urlify_man("busctl", "1", &link
);
2118 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
2119 "Introspect the bus.\n\n"
2120 " -h --help Show this help\n"
2121 " --version Show package version\n"
2122 " --no-pager Do not pipe output into a pager\n"
2123 " --no-legend Do not show the headers and footers\n"
2124 " --system Connect to system bus\n"
2125 " --user Connect to user bus\n"
2126 " -H --host=[USER@]HOST Operate on remote host\n"
2127 " -M --machine=CONTAINER Operate on local container\n"
2128 " --address=ADDRESS Connect to bus specified by address\n"
2129 " --show-machine Show machine ID column in list\n"
2130 " --unique Only show unique names\n"
2131 " --acquired Only show acquired names\n"
2132 " --activatable Only show activatable names\n"
2133 " --match=MATCH Only show matching messages\n"
2134 " --size=SIZE Maximum length of captured packet\n"
2135 " --list Don't show tree, but simple object path list\n"
2136 " -q --quiet Don't show method call reply\n"
2137 " --verbose Show result values in long format\n"
2138 " --json=MODE Output as JSON\n"
2139 " -j Same as --json=pretty on tty, --json=short otherwise\n"
2140 " --expect-reply=BOOL Expect a method call reply\n"
2141 " --auto-start=BOOL Auto-start destination service\n"
2142 " --allow-interactive-authorization=BOOL\n"
2143 " Allow interactive authorization for operation\n"
2144 " --timeout=SECS Maximum time to wait for method call completion\n"
2145 " --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n"
2146 " --watch-bind=BOOL Wait for bus AF_UNIX socket to be bound in the file\n"
2149 " list List bus names\n"
2150 " status [SERVICE] Show bus service, process or bus owner credentials\n"
2151 " monitor [SERVICE...] Show bus traffic\n"
2152 " capture [SERVICE...] Capture bus traffic as pcap\n"
2153 " tree [SERVICE...] Show object tree of service\n"
2154 " introspect SERVICE OBJECT [INTERFACE]\n"
2155 " call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
2157 " get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
2158 " Get property value\n"
2159 " set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n"
2160 " Set property value\n"
2161 " help Show this help\n"
2162 "\nSee the %s for details.\n"
2163 , program_invocation_short_name
2170 static int verb_help(int argc
, char **argv
, void *userdata
) {
2174 static int parse_argv(int argc
, char *argv
[]) {
2177 ARG_VERSION
= 0x100,
2193 ARG_ALLOW_INTERACTIVE_AUTHORIZATION
,
2200 static const struct option options
[] = {
2201 { "help", no_argument
, NULL
, 'h' },
2202 { "version", no_argument
, NULL
, ARG_VERSION
},
2203 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
2204 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
2205 { "system", no_argument
, NULL
, ARG_SYSTEM
},
2206 { "user", no_argument
, NULL
, ARG_USER
},
2207 { "address", required_argument
, NULL
, ARG_ADDRESS
},
2208 { "show-machine", no_argument
, NULL
, ARG_SHOW_MACHINE
},
2209 { "unique", no_argument
, NULL
, ARG_UNIQUE
},
2210 { "acquired", no_argument
, NULL
, ARG_ACQUIRED
},
2211 { "activatable", no_argument
, NULL
, ARG_ACTIVATABLE
},
2212 { "match", required_argument
, NULL
, ARG_MATCH
},
2213 { "host", required_argument
, NULL
, 'H' },
2214 { "machine", required_argument
, NULL
, 'M' },
2215 { "size", required_argument
, NULL
, ARG_SIZE
},
2216 { "list", no_argument
, NULL
, ARG_LIST
},
2217 { "quiet", no_argument
, NULL
, 'q' },
2218 { "verbose", no_argument
, NULL
, ARG_VERBOSE
},
2219 { "expect-reply", required_argument
, NULL
, ARG_EXPECT_REPLY
},
2220 { "auto-start", required_argument
, NULL
, ARG_AUTO_START
},
2221 { "allow-interactive-authorization", required_argument
, NULL
, ARG_ALLOW_INTERACTIVE_AUTHORIZATION
},
2222 { "timeout", required_argument
, NULL
, ARG_TIMEOUT
},
2223 { "augment-creds", required_argument
, NULL
, ARG_AUGMENT_CREDS
},
2224 { "watch-bind", required_argument
, NULL
, ARG_WATCH_BIND
},
2225 { "json", required_argument
, NULL
, ARG_JSON
},
2234 while ((c
= getopt_long(argc
, argv
, "hH:M:qj", options
, NULL
)) >= 0)
2245 arg_pager_flags
|= PAGER_DISABLE
;
2261 arg_address
= optarg
;
2264 case ARG_SHOW_MACHINE
:
2265 arg_show_machine
= true;
2273 arg_acquired
= true;
2276 case ARG_ACTIVATABLE
:
2277 arg_activatable
= true;
2281 if (strv_extend(&arg_matches
, optarg
) < 0)
2288 r
= parse_size(optarg
, 1024, &sz
);
2290 return log_error_errno(r
, "Failed to parse size '%s': %m", optarg
);
2292 if ((uint64_t) (size_t) sz
!= sz
)
2293 return log_error_errno(SYNTHETIC_ERRNO(E2BIG
),
2294 "Size out of range.");
2296 arg_snaplen
= (size_t) sz
;
2305 arg_transport
= BUS_TRANSPORT_REMOTE
;
2310 arg_transport
= BUS_TRANSPORT_MACHINE
;
2322 case ARG_EXPECT_REPLY
:
2323 r
= parse_boolean(optarg
);
2325 return log_error_errno(r
, "Failed to parse --expect-reply= parameter '%s': %m", optarg
);
2327 arg_expect_reply
= r
;
2330 case ARG_AUTO_START
:
2331 r
= parse_boolean(optarg
);
2333 return log_error_errno(r
, "Failed to parse --auto-start= parameter '%s': %m", optarg
);
2338 case ARG_ALLOW_INTERACTIVE_AUTHORIZATION
:
2339 r
= parse_boolean(optarg
);
2341 return log_error_errno(r
, "Failed to parse --allow-interactive-authorization= parameter '%s': %m", optarg
);
2343 arg_allow_interactive_authorization
= r
;
2347 r
= parse_sec(optarg
, &arg_timeout
);
2349 return log_error_errno(r
, "Failed to parse --timeout= parameter '%s': %m", optarg
);
2353 case ARG_AUGMENT_CREDS
:
2354 r
= parse_boolean(optarg
);
2356 return log_error_errno(r
, "Failed to parse --augment-creds= parameter '%s': %m", optarg
);
2358 arg_augment_creds
= r
;
2361 case ARG_WATCH_BIND
:
2362 r
= parse_boolean(optarg
);
2364 return log_error_errno(r
, "Failed to parse --watch-bind= parameter '%s': %m", optarg
);
2371 arg_json
= JSON_PRETTY
;
2373 arg_json
= JSON_SHORT
;
2377 if (streq(optarg
, "short"))
2378 arg_json
= JSON_SHORT
;
2379 else if (streq(optarg
, "pretty"))
2380 arg_json
= JSON_PRETTY
;
2381 else if (streq(optarg
, "help")) {
2383 "pretty\n", stdout
);
2386 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2387 "Unknown JSON out mode: %s",
2396 assert_not_reached("Unhandled option");
2402 static int busctl_main(int argc
, char *argv
[]) {
2404 static const Verb verbs
[] = {
2405 { "list", VERB_ANY
, 1, VERB_DEFAULT
, list_bus_names
},
2406 { "status", VERB_ANY
, 2, 0, status
},
2407 { "monitor", VERB_ANY
, VERB_ANY
, 0, verb_monitor
},
2408 { "capture", VERB_ANY
, VERB_ANY
, 0, verb_capture
},
2409 { "tree", VERB_ANY
, VERB_ANY
, 0, tree
},
2410 { "introspect", 3, 4, 0, introspect
},
2411 { "call", 5, VERB_ANY
, 0, call
},
2412 { "get-property", 5, VERB_ANY
, 0, get_property
},
2413 { "set-property", 6, VERB_ANY
, 0, set_property
},
2414 { "help", VERB_ANY
, VERB_ANY
, 0, verb_help
},
2418 return dispatch_verb(argc
, argv
, verbs
, NULL
);
2421 static int run(int argc
, char *argv
[]) {
2424 log_parse_environment();
2427 r
= parse_argv(argc
, argv
);
2431 return busctl_main(argc
, argv
);
2434 DEFINE_MAIN_FUNCTION(run
);