chiark / gitweb /
busctl: exit cleanly when the bus connection is severed
[elogind.git] / src / libsystemd / sd-bus / busctl.c
index f75a9dcbd3b5e82f93db1077b3a38612079ed791..c0d51e06a3b2a068dba479ac7cc51d0742b5c27d 100644 (file)
@@ -28,6 +28,7 @@
 #include "pager.h"
 #include "xml.h"
 #include "path-util.h"
+#include "set.h"
 
 #include "sd-bus.h"
 #include "bus-message.h"
@@ -538,7 +539,7 @@ static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
                                 fprintf(f, "%s", contents);
                         }
 
-                        r = format_cmdline(m, f, true);
+                        r = format_cmdline(m, f, needs_space || IN_SET(type, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT));
                         if (r < 0)
                                 return r;
 
@@ -614,6 +615,7 @@ static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
                         assert_not_reached("Unknown basic type.");
                 }
 
+                needs_space = true;
         }
 }
 
@@ -881,13 +883,19 @@ static int introspect(sd_bus *bus, char **argv) {
         int r;
         unsigned name_width,  type_width, signature_width, result_width;
         Member **sorted = NULL;
-        unsigned k = 0, j;
+        unsigned k = 0, j, n_args;
 
-        if (strv_length(argv) != 3) {
+        n_args = strv_length(argv);
+        if (n_args < 3) {
                 log_error("Requires service and object path argument.");
                 return -EINVAL;
         }
 
+        if (n_args > 4) {
+                log_error("Too many arguments.");
+                return -EINVAL;
+        }
+
         members = set_new(&member_hash_ops);
         if (!members)
                 return log_oom();
@@ -916,6 +924,9 @@ static int introspect(sd_bus *bus, char **argv) {
                 if (m->value)
                         continue;
 
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
                 r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface);
                 if (r < 0) {
                         log_error("%s", bus_error_message(&error, r));
@@ -993,6 +1004,10 @@ static int introspect(sd_bus *bus, char **argv) {
         sorted = newa(Member*, set_size(members));
 
         SET_FOREACH(m, members, i) {
+
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
                 if (m->interface)
                         name_width = MAX(name_width, strlen(m->interface));
                 if (m->name)
@@ -1012,7 +1027,6 @@ static int introspect(sd_bus *bus, char **argv) {
         if (result_width > 40)
                 result_width = 40;
 
-        assert(k == set_size(members));
         qsort(sorted, k, sizeof(Member*), member_compare_funcp);
 
         if (arg_legend) {
@@ -1031,8 +1045,14 @@ static int introspect(sd_bus *bus, char **argv) {
 
                 m = sorted[j];
 
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
                 is_interface = streq(m->type, "interface");
 
+                if (argv[3] && is_interface)
+                        continue;
+
                 if (m->value) {
                         ellipsized = ellipsize(m->value, result_width, 100);
                         if (!ellipsized)
@@ -1107,6 +1127,8 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
                         return log_error_errno(r, "Failed to add match: %m");
         }
 
+        log_info("Monitoring bus message stream.");
+
         for (;;) {
                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
 
@@ -1116,6 +1138,12 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
 
                 if (m) {
                         dump(m, stdout);
+
+                        if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) {
+                                log_info("Connection terminated, exiting.");
+                                return 0;
+                        }
+
                         continue;
                 }
 
@@ -1176,12 +1204,16 @@ static int status(sd_bus *bus, char *argv[]) {
                                         pid,
                                         _SD_BUS_CREDS_ALL);
         } else {
-                const char *scope;
+                const char *scope, *address;
                 sd_id128_t bus_id;
 
+                r = sd_bus_get_address(bus, &address);
+                if (r >= 0)
+                        printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_highlight_off());
+
                 r = sd_bus_get_scope(bus, &scope);
                 if (r >= 0)
-                        printf("Scope=%s%s%s\n", ansi_highlight(), scope, ansi_highlight_off());
+                        printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_highlight_off());
 
                 r = sd_bus_get_bus_id(bus, &bus_id);
                 if (r >= 0)
@@ -1680,7 +1712,7 @@ static int help(void) {
                "  monitor [SERVICE...]    Show bus traffic\n"
                "  capture [SERVICE...]    Capture bus traffic as pcap\n"
                "  tree [SERVICE...]       Show object tree of service\n"
-               "  introspect SERVICE OBJECT\n"
+               "  introspect SERVICE OBJECT [INTERFACE]\n"
                "  call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
                "                          Call a method\n"
                "  get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
@@ -1830,7 +1862,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        arg_transport = BUS_TRANSPORT_CONTAINER;
+                        arg_transport = BUS_TRANSPORT_MACHINE;
                         arg_host = optarg;
                         break;
 
@@ -2011,8 +2043,8 @@ int main(int argc, char *argv[]) {
                         r = bus_set_address_system_remote(bus, arg_host);
                         break;
 
-                case BUS_TRANSPORT_CONTAINER:
-                        r = bus_set_address_system_container(bus, arg_host);
+                case BUS_TRANSPORT_MACHINE:
+                        r = bus_set_address_system_machine(bus, arg_host);
                         break;
 
                 default: