chiark / gitweb /
busctl: when introspecting objects, optionally limit output by interface name
[elogind.git] / src / libsystemd / sd-bus / busctl.c
index 1ba4e8adacfe0b7f83495989f9a01175fc8b772e..009739fc0fdff230e622c2c3af2eeb2f69dcc874 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)
@@ -1684,7 +1704,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"