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