dbus-send: pretty-print GVariant-style bytestrings
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 13 Feb 2015 18:55:31 +0000 (18:55 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Mon, 16 Feb 2015 11:44:16 +0000 (11:44 +0000)
dbus-send could already pretty-print bytestrings that do not have
\0 termination, but those are awkward to work with (they need copying),
so they are now discouraged. Teach it to print bytestrings that
do have \0 termination as well.

In the process, rewrite this part of the message parser
to use dbus_message_iter_get_fixed_array(), which is the Right way
to get arrays of numbers out of a message.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89109
Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
tools/Makefile.am
tools/dbus-print-message.c

index 294bbc6379cf139d39bc467329b18c711536fa6f..80025b82bb098ab3f93e3f0a9958d84d59b63e32 100644 (file)
@@ -29,7 +29,10 @@ endif
 dbus_send_SOURCES=                             \
        dbus-print-message.c                    \
        dbus-print-message.h                    \
-       dbus-send.c
+       dbus-send.c \
+       tool-common.c \
+       tool-common.h \
+       $(NULL)
 
 dbus_monitor_SOURCES = \
        dbus-monitor.c \
index 6f02ea3842dc63ebfd241dd52ca1e75ba6bd570b..216ebaeb8b685e39b55afc9822690c054629cfcf 100644 (file)
@@ -37,6 +37,8 @@
 #include <stdlib.h>
 #include "config.h"
 
+#include "tool-common.h"
+
 static const char*
 type_to_name (int message_type)
 {
@@ -65,7 +67,9 @@ indent (int depth)
 }
 
 static void
-print_hex (unsigned char *bytes, unsigned int len, int depth)
+print_hex (const unsigned char *bytes,
+           int len,
+           int depth)
 {
   unsigned int i, columns;
 
@@ -110,47 +114,45 @@ print_hex (unsigned char *bytes, unsigned int len, int depth)
 static void
 print_ay (DBusMessageIter *iter, int depth)
 {
-  /* Not using DBusString because it's not public API. It's 2009, and I'm
-   * manually growing a string chunk by chunk.
-   */
-  unsigned char *bytes = malloc (DEFAULT_SIZE + 1);
-  unsigned int len = 0;
-  unsigned int max = DEFAULT_SIZE;
+  /* True if every byte in the bytestring (so far) is printable
+   * ASCII, with one exception: the last byte is also allowed to be \0. */
   dbus_bool_t all_ascii = TRUE;
-  int current_type;
-
-  while ((current_type = dbus_message_iter_get_arg_type (iter))
-          != DBUS_TYPE_INVALID)
-    {
-      unsigned char val;
-
-      dbus_message_iter_get_basic (iter, &val);
-      bytes[len] = val;
-      len++;
+  const unsigned char *bytes;
+  int len;
+  int i;
 
-      if (val < 32 || val > 126)
-        all_ascii = FALSE;
+  dbus_message_iter_get_fixed_array (iter, &bytes, &len);
 
-      if (len == max)
+  for (i = 0; i < len; i++)
+    {
+      if ((bytes[i] < 32 || bytes[i] > 126) &&
+          (i < len - 1 || bytes[i] != '\0'))
         {
-          max *= 2;
-          bytes = realloc (bytes, max + 1);
+          all_ascii = FALSE;
+          break;
         }
-
-      dbus_message_iter_next (iter);
     }
 
-  if (all_ascii)
+  if (all_ascii && len > 0 && bytes[len - 1] == '\0')
+    {
+      printf ("array of bytes \"%s\" + \\0\n", bytes);
+    }
+  else if (all_ascii)
     {
-      bytes[len] = '\0';
-      printf ("array of bytes \"%s\"\n", bytes);
+      unsigned char *copy = dbus_malloc (len + 1);
+
+      if (copy == NULL)
+        tool_oom ("copying bytestring");
+
+      memcpy (copy, bytes, len);
+      copy[len] = '\0';
+      printf ("array of bytes \"%s\"\n", copy);
+      dbus_free (copy);
     }
   else
     {
       print_hex (bytes, len, depth);
     }
-
-  free (bytes);
 }
 
 static void