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