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