chiark / gitweb /
busctl: pass error output to stdout (rather than stderr) when generate tree for all...
[elogind.git] / src / libsystemd / sd-bus / busctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <getopt.h>
23
24 #include "strv.h"
25 #include "util.h"
26 #include "log.h"
27 #include "build.h"
28 #include "pager.h"
29 #include "xml.h"
30 #include "path-util.h"
31
32 #include "sd-bus.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
35 #include "bus-util.h"
36 #include "bus-dump.h"
37 #include "bus-signature.h"
38 #include "busctl-introspect.h"
39
40 static bool arg_no_pager = false;
41 static bool arg_legend = true;
42 static char *arg_address = NULL;
43 static bool arg_unique = false;
44 static bool arg_acquired = false;
45 static bool arg_activatable = false;
46 static bool arg_show_machine = false;
47 static char **arg_matches = NULL;
48 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
49 static char *arg_host = NULL;
50 static bool arg_user = false;
51 static size_t arg_snaplen = 4096;
52 static bool arg_list = false;
53 static bool arg_quiet = false;
54
55 static void pager_open_if_enabled(void) {
56
57         /* Cache result before we open the pager */
58         if (arg_no_pager)
59                 return;
60
61         pager_open(false);
62 }
63
64 static int list_bus_names(sd_bus *bus, char **argv) {
65         _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
66         _cleanup_free_ char **merged = NULL;
67         _cleanup_hashmap_free_ Hashmap *names = NULL;
68         char **i;
69         int r;
70         size_t max_i = 0;
71         unsigned n = 0;
72         void *v;
73         char *k;
74         Iterator iterator;
75
76         assert(bus);
77
78         if (!arg_unique && !arg_acquired && !arg_activatable)
79                 arg_unique = arg_acquired = arg_activatable = true;
80
81         r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
82         if (r < 0) {
83                 log_error("Failed to list names: %s", strerror(-r));
84                 return r;
85         }
86
87         pager_open_if_enabled();
88
89         names = hashmap_new(&string_hash_ops);
90         if (!names)
91                 return log_oom();
92
93         STRV_FOREACH(i, acquired) {
94                 max_i = MAX(max_i, strlen(*i));
95
96                 r = hashmap_put(names, *i, INT_TO_PTR(1));
97                 if (r < 0) {
98                         log_error("Failed to add to hashmap: %s", strerror(-r));
99                         return r;
100                 }
101         }
102
103         STRV_FOREACH(i, activatable) {
104                 max_i = MAX(max_i, strlen(*i));
105
106                 r = hashmap_put(names, *i, INT_TO_PTR(2));
107                 if (r < 0 && r != -EEXIST) {
108                         log_error("Failed to add to hashmap: %s", strerror(-r));
109                         return r;
110                 }
111         }
112
113         merged = new(char*, hashmap_size(names) + 1);
114         HASHMAP_FOREACH_KEY(v, k, names, iterator)
115                 merged[n++] = k;
116
117         merged[n] = NULL;
118         strv_sort(merged);
119
120         if (arg_legend) {
121                 printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
122                        (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
123
124                 if (arg_show_machine)
125                         puts(" MACHINE");
126                 else
127                         putchar('\n');
128         }
129
130         STRV_FOREACH(i, merged) {
131                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
132                 sd_id128_t mid;
133
134                 if (hashmap_get(names, *i) == INT_TO_PTR(2)) {
135                         /* Activatable */
136
137                         printf("%-*s", (int) max_i, *i);
138                         printf("          - -               -                (activatable) -                         -         ");
139                         if (arg_show_machine)
140                                 puts(" -");
141                         else
142                                 putchar('\n');
143                         continue;
144
145                 }
146
147                 if (!arg_unique && (*i)[0] == ':')
148                         continue;
149
150                 if (!arg_acquired && (*i)[0] != ':')
151                         continue;
152
153                 printf("%-*s", (int) max_i, *i);
154
155                 r = sd_bus_get_name_creds(bus, *i,
156                                      SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|
157                                      SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION|
158                                      SD_BUS_CREDS_DESCRIPTION, &creds);
159                 if (r >= 0) {
160                         const char *unique, *session, *unit, *cn;
161                         pid_t pid;
162                         uid_t uid;
163
164                         r = sd_bus_creds_get_pid(creds, &pid);
165                         if (r >= 0) {
166                                 const char *comm = NULL;
167
168                                 sd_bus_creds_get_comm(creds, &comm);
169
170                                 printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
171                         } else
172                                 fputs("          - -              ", stdout);
173
174                         r = sd_bus_creds_get_uid(creds, &uid);
175                         if (r >= 0) {
176                                 _cleanup_free_ char *u = NULL;
177
178                                 u = uid_to_name(uid);
179                                 if (!u)
180                                         return log_oom();
181
182                                 if (strlen(u) > 16)
183                                         u[16] = 0;
184
185                                 printf(" %-16s", u);
186                         } else
187                                 fputs(" -               ", stdout);
188
189                         r = sd_bus_creds_get_unique_name(creds, &unique);
190                         if (r >= 0)
191                                 printf(" %-13s", unique);
192                         else
193                                 fputs(" -            ", stdout);
194
195                         r = sd_bus_creds_get_unit(creds, &unit);
196                         if (r >= 0) {
197                                 _cleanup_free_ char *e;
198
199                                 e = ellipsize(unit, 25, 100);
200                                 if (!e)
201                                         return log_oom();
202
203                                 printf(" %-25s", e);
204                         } else
205                                 fputs(" -                        ", stdout);
206
207                         r = sd_bus_creds_get_session(creds, &session);
208                         if (r >= 0)
209                                 printf(" %-10s", session);
210                         else
211                                 fputs(" -         ", stdout);
212
213                         r = sd_bus_creds_get_description(creds, &cn);
214                         if (r >= 0)
215                                 printf(" %-19s", cn);
216                         else
217                                 fputs(" -                  ", stdout);
218
219                 } else
220                         printf("          - -               -                -             -                         -          -                  ");
221
222                 if (arg_show_machine) {
223                         r = sd_bus_get_name_machine_id(bus, *i, &mid);
224                         if (r >= 0) {
225                                 char m[SD_ID128_STRING_MAX];
226                                 printf(" %s\n", sd_id128_to_string(mid, m));
227                         } else
228                                 puts(" -");
229                 } else
230                         putchar('\n');
231         }
232
233         return 0;
234 }
235
236 static void print_subtree(const char *prefix, const char *path, char **l) {
237         const char *vertical, *space;
238         char **n;
239
240         /* We assume the list is sorted. Let's first skip over the
241          * entry we are looking at. */
242         for (;;) {
243                 if (!*l)
244                         return;
245
246                 if (!streq(*l, path))
247                         break;
248
249                 l++;
250         }
251
252         vertical = strappenda(prefix, draw_special_char(DRAW_TREE_VERTICAL));
253         space = strappenda(prefix, draw_special_char(DRAW_TREE_SPACE));
254
255         for (;;) {
256                 bool has_more = false;
257
258                 if (!*l || !path_startswith(*l, path))
259                         break;
260
261                 n = l + 1;
262                 for (;;) {
263                         if (!*n || !path_startswith(*n, path))
264                                 break;
265
266                         if (!path_startswith(*n, *l)) {
267                                 has_more = true;
268                                 break;
269                         }
270
271                         n++;
272                 }
273
274                 printf("%s%s%s\n", prefix, draw_special_char(has_more ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), *l);
275
276                 print_subtree(has_more ? vertical : space, *l, l);
277                 l = n;
278         }
279 }
280
281 static void print_tree(const char *prefix, char **l) {
282
283         pager_open_if_enabled();
284
285         prefix = strempty(prefix);
286
287         if (arg_list) {
288                 char **i;
289
290                 STRV_FOREACH(i, l)
291                         printf("%s%s\n", prefix, *i);
292                 return;
293         }
294
295         if (strv_isempty(l)) {
296                 printf("No objects discovered.\n");
297                 return;
298         }
299
300         if (streq(l[0], "/") && !l[1]) {
301                 printf("Only root object discovered.\n");
302                 return;
303         }
304
305         print_subtree(prefix, "/", l);
306 }
307
308 static int on_path(const char *path, void *userdata) {
309         Set *paths = userdata;
310         int r;
311
312         assert(paths);
313
314         r = set_put_strdup(paths, path);
315         if (r < 0)
316                 return log_oom();
317
318         return 0;
319 }
320
321 static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
322         static const XMLIntrospectOps ops = {
323                 .on_path = on_path,
324         };
325
326         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
327         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
328         const char *xml;
329         int r;
330
331         r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
332         if (r < 0) {
333                 if (many)
334                         printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
335                 else
336                         log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
337                 return r;
338         }
339
340         r = sd_bus_message_read(reply, "s", &xml);
341         if (r < 0)
342                 return bus_log_parse_error(r);
343
344         return parse_xml_introspect(path, xml, &ops, paths);
345 }
346
347 static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
348         _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
349         _cleanup_free_ char **l = NULL;
350         char *m;
351         int r;
352
353         paths = set_new(&string_hash_ops);
354         if (!paths)
355                 return log_oom();
356
357         done = set_new(&string_hash_ops);
358         if (!done)
359                 return log_oom();
360
361         failed = set_new(&string_hash_ops);
362         if (!failed)
363                 return log_oom();
364
365         m = strdup("/");
366         if (!m)
367                 return log_oom();
368
369         r = set_put(paths, m);
370         if (r < 0) {
371                 free(m);
372                 return log_oom();
373         }
374
375         for (;;) {
376                 _cleanup_free_ char *p = NULL;
377                 int q;
378
379                 p = set_steal_first(paths);
380                 if (!p)
381                         break;
382
383                 if (set_contains(done, p) ||
384                     set_contains(failed, p))
385                         continue;
386
387                 q = find_nodes(bus, service, p, paths, many);
388                 if (q < 0) {
389                         if (r >= 0)
390                                 r = q;
391
392                         q = set_put(failed, p);
393                 } else
394                         q = set_put(done, p);
395
396                 if (q < 0)
397                         return log_oom();
398
399                 assert(q != 0);
400                 p = NULL;
401         }
402
403         pager_open_if_enabled();
404
405         l = set_get_strv(done);
406         if (!l)
407                 return log_oom();
408
409         strv_sort(l);
410         print_tree(prefix, l);
411
412         fflush(stdout);
413
414         return r;
415 }
416
417 static int tree(sd_bus *bus, char **argv) {
418         char **i;
419         int r = 0;
420
421         if (!arg_unique && !arg_acquired)
422                 arg_acquired = true;
423
424         if (strv_length(argv) <= 1) {
425                 _cleanup_strv_free_ char **names = NULL;
426                 bool not_first = false;
427
428                 r = sd_bus_list_names(bus, &names, NULL);
429                 if (r < 0) {
430                         log_error("Failed to get name list: %s", strerror(-r));
431                         return r;
432                 }
433
434                 pager_open_if_enabled();
435
436                 STRV_FOREACH(i, names) {
437                         int q;
438
439                         if (!arg_unique && (*i)[0] == ':')
440                                 continue;
441
442                         if (!arg_acquired && (*i)[0] == ':')
443                                 continue;
444
445                         if (not_first)
446                                 printf("\n");
447
448                         printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
449
450                         q = tree_one(bus, *i, NULL, true);
451                         if (q < 0 && r >= 0)
452                                 r = q;
453
454                         not_first = true;
455                 }
456         } else {
457                 STRV_FOREACH(i, argv+1) {
458                         int q;
459
460                         if (i > argv+1)
461                                 printf("\n");
462
463                         if (argv[2]) {
464                                 pager_open_if_enabled();
465                                 printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
466                         }
467
468                         q = tree_one(bus, *i, NULL, !!argv[2]);
469                         if (q < 0 && r >= 0)
470                                 r = q;
471                 }
472         }
473
474         return r;
475 }
476
477 typedef struct Member {
478         const char *type;
479         char *interface;
480         char *name;
481         char *signature;
482         char *result;
483         bool writable;
484         uint64_t flags;
485 } Member;
486
487 static unsigned long member_hash_func(const void *p, const uint8_t hash_key[]) {
488         const Member *m = p;
489         unsigned long ul;
490
491         assert(m);
492         assert(m->type);
493
494         ul = string_hash_func(m->type, hash_key);
495
496         if (m->name)
497                 ul ^= string_hash_func(m->name, hash_key);
498
499         if (m->interface)
500                 ul ^= string_hash_func(m->interface, hash_key);
501
502         return ul;
503 }
504
505 static int member_compare_func(const void *a, const void *b) {
506         const Member *x = a, *y = b;
507         int d;
508
509         assert(x);
510         assert(y);
511         assert(x->type);
512         assert(y->type);
513
514         if (!x->interface && y->interface)
515                 return -1;
516         if (x->interface && !y->interface)
517                 return 1;
518         if (x->interface && y->interface) {
519                 d = strcmp(x->interface, y->interface);
520                 if (d != 0)
521                         return d;
522         }
523
524         d = strcmp(x->type, y->type);
525         if (d != 0)
526                 return d;
527
528         if (!x->name && y->name)
529                 return -1;
530         if (x->name && !y->name)
531                 return 1;
532         if (x->name && y->name)
533                 return strcmp(x->name, y->name);
534
535         return 0;
536 }
537
538 static int member_compare_funcp(const void *a, const void *b) {
539         const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b;
540
541         return member_compare_func(*x, *y);
542 }
543
544 static void member_free(Member *m) {
545         if (!m)
546                 return;
547
548         free(m->interface);
549         free(m->name);
550         free(m->signature);
551         free(m->result);
552         free(m);
553 }
554
555 DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
556
557 static void member_set_free(Set *s) {
558         Member *m;
559
560         while ((m = set_steal_first(s)))
561                 member_free(m);
562
563         set_free(s);
564 }
565
566 DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
567
568 static int on_interface(const char *interface, uint64_t flags, void *userdata) {
569         _cleanup_(member_freep) Member *m;
570         Set *members = userdata;
571         int r;
572
573         assert(interface);
574         assert(members);
575
576         m = new0(Member, 1);
577         if (!m)
578                 return log_oom();
579
580         m->type = "interface";
581         m->flags = flags;
582
583         r = free_and_strdup(&m->interface, interface);
584         if (r < 0)
585                 return log_oom();
586
587         r = set_put(members, m);
588         if (r <= 0) {
589                 log_error("Duplicate interface");
590                 return -EINVAL;
591         }
592
593         m = NULL;
594         return 0;
595 }
596
597 static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) {
598         _cleanup_(member_freep) Member *m;
599         Set *members = userdata;
600         int r;
601
602         assert(interface);
603         assert(name);
604
605         m = new0(Member, 1);
606         if (!m)
607                 return log_oom();
608
609         m->type = "method";
610         m->flags = flags;
611
612         r = free_and_strdup(&m->interface, interface);
613         if (r < 0)
614                 return log_oom();
615
616         r = free_and_strdup(&m->name, name);
617         if (r < 0)
618                 return log_oom();
619
620         r = free_and_strdup(&m->signature, signature);
621         if (r < 0)
622                 return log_oom();
623
624         r = free_and_strdup(&m->result, result);
625         if (r < 0)
626                 return log_oom();
627
628         r = set_put(members, m);
629         if (r <= 0) {
630                 log_error("Duplicate method");
631                 return -EINVAL;
632         }
633
634         m = NULL;
635         return 0;
636 }
637
638 static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) {
639         _cleanup_(member_freep) Member *m;
640         Set *members = userdata;
641         int r;
642
643         assert(interface);
644         assert(name);
645
646         m = new0(Member, 1);
647         if (!m)
648                 return log_oom();
649
650         m->type = "signal";
651         m->flags = flags;
652
653         r = free_and_strdup(&m->interface, interface);
654         if (r < 0)
655                 return log_oom();
656
657         r = free_and_strdup(&m->name, name);
658         if (r < 0)
659                 return log_oom();
660
661         r = free_and_strdup(&m->signature, signature);
662         if (r < 0)
663                 return log_oom();
664
665         r = set_put(members, m);
666         if (r <= 0) {
667                 log_error("Duplicate signal");
668                 return -EINVAL;
669         }
670
671         m = NULL;
672         return 0;
673 }
674
675 static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) {
676         _cleanup_(member_freep) Member *m;
677         Set *members = userdata;
678         int r;
679
680         assert(interface);
681         assert(name);
682
683         m = new0(Member, 1);
684         if (!m)
685                 return log_oom();
686
687         m->type = "property";
688         m->flags = flags;
689         m->writable = writable;
690
691         r = free_and_strdup(&m->interface, interface);
692         if (r < 0)
693                 return log_oom();
694
695         r = free_and_strdup(&m->name, name);
696         if (r < 0)
697                 return log_oom();
698
699         r = free_and_strdup(&m->signature, signature);
700         if (r < 0)
701                 return log_oom();
702
703         r = set_put(members, m);
704         if (r <= 0) {
705                 log_error("Duplicate property");
706                 return -EINVAL;
707         }
708
709         m = NULL;
710         return 0;
711 }
712
713 static const char *strdash(const char *x) {
714         return isempty(x) ? "-" : x;
715 }
716
717 static int introspect(sd_bus *bus, char **argv) {
718         static const struct hash_ops member_hash_ops = {
719                 .hash = member_hash_func,
720                 .compare = member_compare_func,
721         };
722
723         static const XMLIntrospectOps ops = {
724                 .on_interface = on_interface,
725                 .on_method = on_method,
726                 .on_signal = on_signal,
727                 .on_property = on_property,
728         };
729
730         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
731         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
732         _cleanup_(member_set_freep) Set *members = NULL;
733         Iterator i;
734         Member *m;
735         const char *xml;
736         int r;
737         unsigned name_width,  type_width, signature_width, result_width;
738         Member **sorted = NULL;
739         unsigned k = 0, j;
740
741         if (strv_length(argv) != 3) {
742                 log_error("Requires service and object path argument.");
743                 return -EINVAL;
744         }
745
746         members = set_new(&member_hash_ops);
747         if (!members)
748                 return log_oom();
749
750         r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
751         if (r < 0) {
752                 log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r));
753                 return r;
754         }
755
756         r = sd_bus_message_read(reply, "s", &xml);
757         if (r < 0)
758                 return bus_log_parse_error(r);
759
760         r = parse_xml_introspect(argv[2], xml, &ops, members);
761         if (r < 0)
762                 return r;
763
764         pager_open_if_enabled();
765
766         name_width = strlen("NAME");
767         type_width = strlen("TYPE");
768         signature_width = strlen("SIGNATURE");
769         result_width = strlen("RESULT");
770
771         sorted = newa(Member*, set_size(members));
772
773         SET_FOREACH(m, members, i) {
774                 if (m->interface)
775                         name_width = MAX(name_width, strlen(m->interface));
776                 if (m->name)
777                         name_width = MAX(name_width, strlen(m->name) + 1);
778                 if (m->type)
779                         type_width = MAX(type_width, strlen(m->type));
780                 if (m->signature)
781                         signature_width = MAX(signature_width, strlen(m->signature));
782                 if (m->result)
783                         result_width = MAX(result_width, strlen(m->result));
784
785                 sorted[k++] = m;
786         }
787
788         assert(k == set_size(members));
789         qsort(sorted, k, sizeof(Member*), member_compare_funcp);
790
791         printf("%-*s %-*s %-*s %-*s %s\n",
792                (int) name_width, "NAME",
793                (int) type_width, "TYPE",
794                (int) signature_width, "SIGNATURE",
795                (int) result_width, "RESULT",
796                "FLAGS");
797
798         for (j = 0; j < k; j++) {
799                 bool is_interface;
800
801                 m = sorted[j];
802
803                 is_interface = streq(m->type, "interface");
804
805                 printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
806                        is_interface ? ansi_highlight() : "",
807                        is_interface ? "" : ".",
808                        - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
809                        is_interface ? ansi_highlight_off() : "",
810                        (int) type_width, strdash(m->type),
811                        (int) signature_width, strdash(m->signature),
812                        (int) result_width, strdash(m->result),
813                        (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
814                        (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
815                        (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "",
816                        (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "",
817                        (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "",
818                        m->writable ? " writable" : "");
819         }
820
821         return 0;
822 }
823
824 static int message_dump(sd_bus_message *m, FILE *f) {
825         return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER);
826 }
827
828 static int message_pcap(sd_bus_message *m, FILE *f) {
829         return bus_message_pcap_frame(m, arg_snaplen, f);
830 }
831
832 static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
833         bool added_something = false;
834         char **i;
835         int r;
836
837         STRV_FOREACH(i, argv+1) {
838                 _cleanup_free_ char *m = NULL;
839
840                 if (!service_name_is_valid(*i)) {
841                         log_error("Invalid service name '%s'", *i);
842                         return -EINVAL;
843                 }
844
845                 m = strjoin("sender='", *i, "'", NULL);
846                 if (!m)
847                         return log_oom();
848
849                 r = sd_bus_add_match(bus, NULL, m, NULL, NULL);
850                 if (r < 0) {
851                         log_error("Failed to add match: %s", strerror(-r));
852                         return r;
853                 }
854
855                 added_something = true;
856         }
857
858         STRV_FOREACH(i, arg_matches) {
859                 r = sd_bus_add_match(bus, NULL, *i, NULL, NULL);
860                 if (r < 0) {
861                         log_error("Failed to add match: %s", strerror(-r));
862                         return r;
863                 }
864
865                 added_something = true;
866         }
867
868         if (!added_something) {
869                 r = sd_bus_add_match(bus, NULL, "", NULL, NULL);
870                 if (r < 0) {
871                         log_error("Failed to add match: %s", strerror(-r));
872                         return r;
873                 }
874         }
875
876         for (;;) {
877                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
878
879                 r = sd_bus_process(bus, &m);
880                 if (r < 0) {
881                         log_error("Failed to process bus: %s", strerror(-r));
882                         return r;
883                 }
884
885                 if (m) {
886                         dump(m, stdout);
887                         continue;
888                 }
889
890                 if (r > 0)
891                         continue;
892
893                 r = sd_bus_wait(bus, (uint64_t) -1);
894                 if (r < 0) {
895                         log_error("Failed to wait for bus: %s", strerror(-r));
896                         return r;
897                 }
898         }
899 }
900
901 static int capture(sd_bus *bus, char *argv[]) {
902         int r;
903
904         if (isatty(fileno(stdout)) > 0) {
905                 log_error("Refusing to write message data to console, please redirect output to a file.");
906                 return -EINVAL;
907         }
908
909         bus_pcap_header(arg_snaplen, stdout);
910
911         r = monitor(bus, argv, message_pcap);
912         if (r < 0)
913                 return r;
914
915         if (ferror(stdout)) {
916                 log_error("Couldn't write capture file.");
917                 return -EIO;
918         }
919
920         return r;
921 }
922
923 static int status(sd_bus *bus, char *argv[]) {
924         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
925         pid_t pid;
926         int r;
927
928         assert(bus);
929
930         if (strv_length(argv) != 2) {
931                 log_error("Expects one argument.");
932                 return -EINVAL;
933         }
934
935         r = parse_pid(argv[1], &pid);
936         if (r < 0)
937                 r = sd_bus_get_name_creds(bus, argv[1], _SD_BUS_CREDS_ALL, &creds);
938         else
939                 r = sd_bus_creds_new_from_pid(&creds, pid, _SD_BUS_CREDS_ALL);
940
941         if (r < 0) {
942                 log_error("Failed to get credentials: %s", strerror(-r));
943                 return r;
944         }
945
946         bus_creds_dump(creds, NULL, false);
947         return 0;
948 }
949
950 static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
951         char **p;
952         int r;
953
954         assert(m);
955         assert(signature);
956         assert(x);
957
958         p = *x;
959
960         for (;;) {
961                 const char *v;
962                 char t;
963
964                 t = *signature;
965                 v = *p;
966
967                 if (t == 0)
968                         break;
969                 if (!v) {
970                         log_error("Too few parameters for signature.");
971                         return -EINVAL;
972                 }
973
974                 signature++;
975                 p++;
976
977                 switch (t) {
978
979                 case SD_BUS_TYPE_BOOLEAN:
980
981                         r = parse_boolean(v);
982                         if (r < 0) {
983                                 log_error("Failed to parse as boolean: %s", v);
984                                 return r;
985                         }
986
987                         r = sd_bus_message_append_basic(m, t, &r);
988                         break;
989
990                 case SD_BUS_TYPE_BYTE: {
991                         uint8_t z;
992
993                         r = safe_atou8(v, &z);
994                         if (r < 0) {
995                                 log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
996                                 return r;
997                         }
998
999                         r = sd_bus_message_append_basic(m, t, &z);
1000                         break;
1001                 }
1002
1003                 case SD_BUS_TYPE_INT16: {
1004                         int16_t z;
1005
1006                         r = safe_atoi16(v, &z);
1007                         if (r < 0) {
1008                                 log_error("Failed to parse as signed 16bit integer: %s", v);
1009                                 return r;
1010                         }
1011
1012                         r = sd_bus_message_append_basic(m, t, &z);
1013                         break;
1014                 }
1015
1016                 case SD_BUS_TYPE_UINT16: {
1017                         uint16_t z;
1018
1019                         r = safe_atou16(v, &z);
1020                         if (r < 0) {
1021                                 log_error("Failed to parse as unsigned 16bit integer: %s", v);
1022                                 return r;
1023                         }
1024
1025                         r = sd_bus_message_append_basic(m, t, &z);
1026                         break;
1027                 }
1028
1029                 case SD_BUS_TYPE_INT32: {
1030                         int32_t z;
1031
1032                         r = safe_atoi32(v, &z);
1033                         if (r < 0) {
1034                                 log_error("Failed to parse as signed 32bit integer: %s", v);
1035                                 return r;
1036                         }
1037
1038                         r = sd_bus_message_append_basic(m, t, &z);
1039                         break;
1040                 }
1041
1042                 case SD_BUS_TYPE_UINT32: {
1043                         uint32_t z;
1044
1045                         r = safe_atou32(v, &z);
1046                         if (r < 0) {
1047                                 log_error("Failed to parse as unsigned 32bit integer: %s", v);
1048                                 return r;
1049                         }
1050
1051                         r = sd_bus_message_append_basic(m, t, &z);
1052                         break;
1053                 }
1054
1055                 case SD_BUS_TYPE_INT64: {
1056                         int64_t z;
1057
1058                         r = safe_atoi64(v, &z);
1059                         if (r < 0) {
1060                                 log_error("Failed to parse as signed 64bit integer: %s", v);
1061                                 return r;
1062                         }
1063
1064                         r = sd_bus_message_append_basic(m, t, &z);
1065                         break;
1066                 }
1067
1068                 case SD_BUS_TYPE_UINT64: {
1069                         uint64_t z;
1070
1071                         r = safe_atou64(v, &z);
1072                         if (r < 0) {
1073                                 log_error("Failed to parse as unsigned 64bit integer: %s", v);
1074                                 return r;
1075                         }
1076
1077                         r = sd_bus_message_append_basic(m, t, &z);
1078                         break;
1079                 }
1080
1081
1082                 case SD_BUS_TYPE_DOUBLE: {
1083                         double z;
1084
1085                         r = safe_atod(v, &z);
1086                         if (r < 0) {
1087                                 log_error("Failed to parse as double precision floating point: %s", v);
1088                                 return r;
1089                         }
1090
1091                         r = sd_bus_message_append_basic(m, t, &z);
1092                         break;
1093                 }
1094
1095                 case SD_BUS_TYPE_STRING:
1096                 case SD_BUS_TYPE_OBJECT_PATH:
1097                 case SD_BUS_TYPE_SIGNATURE:
1098
1099                         r = sd_bus_message_append_basic(m, t, v);
1100                         break;
1101
1102                 case SD_BUS_TYPE_ARRAY: {
1103                         uint32_t n;
1104                         size_t k;
1105
1106                         r = safe_atou32(v, &n);
1107                         if (r < 0) {
1108                                 log_error("Failed to parse number of array entries: %s", v);
1109                                 return r;
1110                         }
1111
1112                         r = signature_element_length(signature, &k);
1113                         if (r < 0) {
1114                                 log_error("Invalid array signature.");
1115                                 return r;
1116                         }
1117
1118                         {
1119                                 unsigned i;
1120                                 char s[k + 1];
1121                                 memcpy(s, signature, k);
1122                                 s[k] = 0;
1123
1124                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1125                                 if (r < 0)
1126                                         return bus_log_create_error(r);
1127
1128                                 for (i = 0; i < n; i++) {
1129                                         r = message_append_cmdline(m, s, &p);
1130                                         if (r < 0)
1131                                                 return r;
1132                                 }
1133                         }
1134
1135                         signature += k;
1136
1137                         r = sd_bus_message_close_container(m);
1138                         break;
1139                 }
1140
1141                 case SD_BUS_TYPE_VARIANT:
1142                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v);
1143                         if (r < 0)
1144                                 return bus_log_create_error(r);
1145
1146                         r = message_append_cmdline(m, v, &p);
1147                         if (r < 0)
1148                                 return r;
1149
1150                         r = sd_bus_message_close_container(m);
1151                         break;
1152
1153                 case SD_BUS_TYPE_STRUCT_BEGIN:
1154                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1155                         size_t k;
1156
1157                         signature--;
1158                         p--;
1159
1160                         r = signature_element_length(signature, &k);
1161                         if (r < 0) {
1162                                 log_error("Invalid struct/dict entry signature.");
1163                                 return r;
1164                         }
1165
1166                         {
1167                                 char s[k-1];
1168                                 memcpy(s, signature + 1, k - 2);
1169                                 s[k - 2] = 0;
1170
1171                                 r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1172                                 if (r < 0)
1173                                         return bus_log_create_error(r);
1174
1175                                 r = message_append_cmdline(m, s, &p);
1176                                 if (r < 0)
1177                                         return r;
1178                         }
1179
1180                         signature += k;
1181
1182                         r = sd_bus_message_close_container(m);
1183                         break;
1184                 }
1185
1186                 case SD_BUS_TYPE_UNIX_FD:
1187                         log_error("UNIX file descriptor not supported as type.");
1188                         return -EINVAL;
1189
1190                 default:
1191                         log_error("Unknown signature type %c.", t);
1192                         return -EINVAL;
1193                 }
1194
1195                 if (r < 0)
1196                         return bus_log_create_error(r);
1197         }
1198
1199         *x = p;
1200         return 0;
1201 }
1202
1203 static int call(sd_bus *bus, char *argv[]) {
1204         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1205         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1206         int r;
1207
1208         assert(bus);
1209
1210         if (strv_length(argv) < 5) {
1211                 log_error("Expects at least four arguments.");
1212                 return -EINVAL;
1213         }
1214
1215         r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
1216         if (r < 0) {
1217                 log_error("Failed to prepare bus message: %s", strerror(-r));
1218                 return r;
1219         }
1220
1221         if (!isempty(argv[5])) {
1222                 char **p;
1223
1224                 p = argv+6;
1225
1226                 r = message_append_cmdline(m, argv[5], &p);
1227                 if (r < 0)
1228                         return r;
1229
1230                 if (*p) {
1231                         log_error("Too many parameters for signature.");
1232                         return -EINVAL;
1233                 }
1234         }
1235
1236         r = sd_bus_call(bus, m, 0, &error, &reply);
1237         if (r < 0) {
1238                 log_error("%s", bus_error_message(&error, r));
1239                 return r;
1240         }
1241
1242         r = sd_bus_message_is_empty(reply);
1243         if (r < 0)
1244                 return bus_log_parse_error(r);
1245         if (r == 0 && !arg_quiet) {
1246                 pager_open_if_enabled();
1247                 bus_message_dump(reply, stdout, 0);
1248         }
1249
1250         return 0;
1251 }
1252
1253 static int get_property(sd_bus *bus, char *argv[]) {
1254         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1255         unsigned n;
1256         int r;
1257
1258         assert(bus);
1259
1260         n = strv_length(argv);
1261         if (n < 3) {
1262                 log_error("Expects at least three arguments.");
1263                 return -EINVAL;
1264         }
1265
1266         if (n < 5) {
1267                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1268                 bool not_first = false;
1269
1270                 r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", strempty(argv[3]));
1271                 if (r < 0) {
1272                         log_error("%s", bus_error_message(&error, r));
1273                         return r;
1274                 }
1275
1276                 r = sd_bus_message_enter_container(reply, 'a', "{sv}");
1277                 if (r < 0)
1278                         return bus_log_parse_error(r);
1279
1280                 for (;;) {
1281                         const char *name;
1282
1283                         r = sd_bus_message_enter_container(reply, 'e', "sv");
1284                         if (r < 0)
1285                                 return bus_log_parse_error(r);
1286
1287                         if (r == 0)
1288                                 break;
1289
1290                         r = sd_bus_message_read(reply, "s", &name);
1291                         if (r < 0)
1292                                 return bus_log_parse_error(r);
1293
1294                         if (not_first)
1295                                 printf("\n");
1296
1297                         printf("Property %s:\n", name);
1298
1299                         r = sd_bus_message_enter_container(reply, 'v', NULL);
1300                         if (r < 0)
1301                                 return bus_log_parse_error(r);
1302
1303                         pager_open_if_enabled();
1304                         bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
1305
1306                         r = sd_bus_message_exit_container(reply);
1307                         if (r < 0)
1308                                 return bus_log_parse_error(r);
1309
1310                         r = sd_bus_message_exit_container(reply);
1311                         if (r < 0)
1312                                 return bus_log_parse_error(r);
1313
1314                         not_first = true;
1315                 }
1316
1317                 r = sd_bus_message_exit_container(reply);
1318                 if (r < 0)
1319                         return bus_log_parse_error(r);
1320         } else {
1321                 char **i;
1322
1323                 STRV_FOREACH(i, argv + 4) {
1324                         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1325
1326                         r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
1327                         if (r < 0) {
1328                                 log_error("%s", bus_error_message(&error, r));
1329                                 return r;
1330                         }
1331
1332                         r = sd_bus_message_enter_container(reply, 'v', NULL);
1333                         if (r < 0)
1334                                 return bus_log_parse_error(r);
1335
1336                         if (i > argv + 4)
1337                                 printf("\n");
1338
1339                         if (argv[5])
1340                                 printf("Property %s:\n", *i);
1341
1342                         pager_open_if_enabled();
1343                         bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
1344
1345                         r = sd_bus_message_exit_container(reply);
1346                         if (r < 0)
1347                                 return bus_log_parse_error(r);
1348                 }
1349         }
1350
1351         return 0;
1352 }
1353
1354 static int help(void) {
1355         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1356                "Introspect the bus.\n\n"
1357                "  -h --help               Show this help\n"
1358                "     --version            Show package version\n"
1359                "     --no-pager           Do not pipe output into a pager\n"
1360                "     --no-legend          Do not show the headers and footers\n"
1361                "     --system             Connect to system bus\n"
1362                "     --user               Connect to user bus\n"
1363                "  -H --host=[USER@]HOST   Operate on remote host\n"
1364                "  -M --machine=CONTAINER  Operate on local container\n"
1365                "     --address=ADDRESS    Connect to bus specified by address\n"
1366                "     --show-machine       Show machine ID column in list\n"
1367                "     --unique             Only show unique names\n"
1368                "     --acquired           Only show acquired names\n"
1369                "     --activatable        Only show activatable names\n"
1370                "     --match=MATCH        Only show matching messages\n"
1371                "     --list               Don't show tree, but simple object path list\n"
1372                "     --quiet              Don't show method call reply\n\n"
1373                "Commands:\n"
1374                "  list                    List bus names\n"
1375                "  status SERVICE          Show service name status\n"
1376                "  monitor [SERVICE...]    Show bus traffic\n"
1377                "  capture [SERVICE...]    Capture bus traffic as pcap\n"
1378                "  tree [SERVICE...]       Show object tree of service\n"
1379                "  introspect SERVICE PATH\n"
1380                "  call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
1381                "                          Call a method\n"
1382                "  get-property SERVICE OBJECT [INTERFACE [PROPERTY...]]\n"
1383                "                          Get property value\n"
1384                "  help                    Show this help\n"
1385                , program_invocation_short_name);
1386
1387         return 0;
1388 }
1389
1390 static int parse_argv(int argc, char *argv[]) {
1391
1392         enum {
1393                 ARG_VERSION = 0x100,
1394                 ARG_NO_PAGER,
1395                 ARG_NO_LEGEND,
1396                 ARG_SYSTEM,
1397                 ARG_USER,
1398                 ARG_ADDRESS,
1399                 ARG_MATCH,
1400                 ARG_SHOW_MACHINE,
1401                 ARG_UNIQUE,
1402                 ARG_ACQUIRED,
1403                 ARG_ACTIVATABLE,
1404                 ARG_SIZE,
1405                 ARG_LIST,
1406         };
1407
1408         static const struct option options[] = {
1409                 { "help",         no_argument,       NULL, 'h'              },
1410                 { "version",      no_argument,       NULL, ARG_VERSION      },
1411                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
1412                 { "no-legend",    no_argument,       NULL, ARG_NO_LEGEND    },
1413                 { "system",       no_argument,       NULL, ARG_SYSTEM       },
1414                 { "user",         no_argument,       NULL, ARG_USER         },
1415                 { "address",      required_argument, NULL, ARG_ADDRESS      },
1416                 { "show-machine", no_argument,       NULL, ARG_SHOW_MACHINE },
1417                 { "unique",       no_argument,       NULL, ARG_UNIQUE       },
1418                 { "acquired",     no_argument,       NULL, ARG_ACQUIRED     },
1419                 { "activatable",  no_argument,       NULL, ARG_ACTIVATABLE  },
1420                 { "match",        required_argument, NULL, ARG_MATCH        },
1421                 { "host",         required_argument, NULL, 'H'              },
1422                 { "machine",      required_argument, NULL, 'M'              },
1423                 { "size",         required_argument, NULL, ARG_SIZE         },
1424                 { "list",         no_argument,       NULL, ARG_LIST         },
1425                 { "quiet",        no_argument,       NULL, 'q'              },
1426                 {},
1427         };
1428
1429         int c, r;
1430
1431         assert(argc >= 0);
1432         assert(argv);
1433
1434         while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0)
1435
1436                 switch (c) {
1437
1438                 case 'h':
1439                         return help();
1440
1441                 case ARG_VERSION:
1442                         puts(PACKAGE_STRING);
1443                         puts(SYSTEMD_FEATURES);
1444                         return 0;
1445
1446                 case ARG_NO_PAGER:
1447                         arg_no_pager = true;
1448                         break;
1449
1450                 case ARG_NO_LEGEND:
1451                         arg_legend = false;
1452                         break;
1453
1454                 case ARG_USER:
1455                         arg_user = true;
1456                         break;
1457
1458                 case ARG_SYSTEM:
1459                         arg_user = false;
1460                         break;
1461
1462                 case ARG_ADDRESS:
1463                         arg_address = optarg;
1464                         break;
1465
1466                 case ARG_SHOW_MACHINE:
1467                         arg_show_machine = true;
1468                         break;
1469
1470                 case ARG_UNIQUE:
1471                         arg_unique = true;
1472                         break;
1473
1474                 case ARG_ACQUIRED:
1475                         arg_acquired = true;
1476                         break;
1477
1478                 case ARG_ACTIVATABLE:
1479                         arg_activatable = true;
1480                         break;
1481
1482                 case ARG_MATCH:
1483                         if (strv_extend(&arg_matches, optarg) < 0)
1484                                 return log_oom();
1485                         break;
1486
1487                 case ARG_SIZE: {
1488                         off_t o;
1489
1490                         r = parse_size(optarg, 0, &o);
1491                         if (r < 0) {
1492                                 log_error("Failed to parse size: %s", optarg);
1493                                 return r;
1494                         }
1495
1496                         if ((off_t) (size_t) o !=  o) {
1497                                 log_error("Size out of range.");
1498                                 return -E2BIG;
1499                         }
1500
1501                         arg_snaplen = (size_t) o;
1502                         break;
1503                 }
1504
1505                 case ARG_LIST:
1506                         arg_list = true;
1507                         break;
1508
1509                 case 'H':
1510                         arg_transport = BUS_TRANSPORT_REMOTE;
1511                         arg_host = optarg;
1512                         break;
1513
1514                 case 'M':
1515                         arg_transport = BUS_TRANSPORT_CONTAINER;
1516                         arg_host = optarg;
1517                         break;
1518
1519                 case 'q':
1520                         arg_quiet = true;
1521                         break;
1522
1523                 case '?':
1524                         return -EINVAL;
1525
1526                 default:
1527                         assert_not_reached("Unhandled option");
1528                 }
1529
1530         return 1;
1531 }
1532
1533 static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
1534         assert(bus);
1535
1536         if (optind >= argc ||
1537             streq(argv[optind], "list"))
1538                 return list_bus_names(bus, argv + optind);
1539
1540         if (streq(argv[optind], "monitor"))
1541                 return monitor(bus, argv + optind, message_dump);
1542
1543         if (streq(argv[optind], "capture"))
1544                 return capture(bus, argv + optind);
1545
1546         if (streq(argv[optind], "status"))
1547                 return status(bus, argv + optind);
1548
1549         if (streq(argv[optind], "tree"))
1550                 return tree(bus, argv + optind);
1551
1552         if (streq(argv[optind], "introspect"))
1553                 return introspect(bus, argv + optind);
1554
1555         if (streq(argv[optind], "call"))
1556                 return call(bus, argv + optind);
1557
1558         if (streq(argv[optind], "get-property"))
1559                 return get_property(bus, argv + optind);
1560
1561         if (streq(argv[optind], "help"))
1562                 return help();
1563
1564         log_error("Unknown command '%s'", argv[optind]);
1565         return -EINVAL;
1566 }
1567
1568 int main(int argc, char *argv[]) {
1569         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1570         int r;
1571
1572         log_parse_environment();
1573         log_open();
1574
1575         r = parse_argv(argc, argv);
1576         if (r <= 0)
1577                 goto finish;
1578
1579         r = sd_bus_new(&bus);
1580         if (r < 0) {
1581                 log_error("Failed to allocate bus: %s", strerror(-r));
1582                 goto finish;
1583         }
1584
1585         if (streq_ptr(argv[optind], "monitor") ||
1586             streq_ptr(argv[optind], "capture")) {
1587
1588                 r = sd_bus_set_monitor(bus, true);
1589                 if (r < 0) {
1590                         log_error("Failed to set monitor mode: %s", strerror(-r));
1591                         goto finish;
1592                 }
1593
1594                 r = sd_bus_negotiate_creds(bus, _SD_BUS_CREDS_ALL);
1595                 if (r < 0) {
1596                         log_error("Failed to enable credentials: %s", strerror(-r));
1597                         goto finish;
1598                 }
1599
1600                 r = sd_bus_negotiate_timestamp(bus, true);
1601                 if (r < 0) {
1602                         log_error("Failed to enable timestamps: %s", strerror(-r));
1603                         goto finish;
1604                 }
1605
1606                 r = sd_bus_negotiate_fds(bus, true);
1607                 if (r < 0) {
1608                         log_error("Failed to enable fds: %s", strerror(-r));
1609                         goto finish;
1610                 }
1611         }
1612
1613         if (arg_address)
1614                 r = sd_bus_set_address(bus, arg_address);
1615         else {
1616                 switch (arg_transport) {
1617
1618                 case BUS_TRANSPORT_LOCAL:
1619                         if (arg_user)
1620                                 r = bus_set_address_user(bus);
1621                         else
1622                                 r = bus_set_address_system(bus);
1623                         break;
1624
1625                 case BUS_TRANSPORT_REMOTE:
1626                         r = bus_set_address_system_remote(bus, arg_host);
1627                         break;
1628
1629                 case BUS_TRANSPORT_CONTAINER:
1630                         r = bus_set_address_system_container(bus, arg_host);
1631                         break;
1632
1633                 default:
1634                         assert_not_reached("Hmm, unknown transport type.");
1635                 }
1636         }
1637         if (r < 0) {
1638                 log_error("Failed to set address: %s", strerror(-r));
1639                 goto finish;
1640         }
1641
1642         r = sd_bus_set_bus_client(bus, true);
1643         if (r < 0) {
1644                 log_error("Failed to set bus client: %s", strerror(-r));
1645                 goto finish;
1646         }
1647
1648         r = sd_bus_start(bus);
1649         if (r < 0) {
1650                 log_error("Failed to connect to bus: %s", strerror(-r));
1651                 goto finish;
1652         }
1653
1654         r = busctl_main(bus, argc, argv);
1655
1656 finish:
1657         pager_close();
1658
1659         strv_free(arg_matches);
1660
1661         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1662 }