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