Home | History | Annotate | Download | only in tools
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-print-message.h  Utility function to print out a message
      3  *
      4  * Copyright (C) 2003 Philip Blundell <philb (at) gnu.org>
      5  * Copyright (C) 2003 Red Hat, Inc.
      6  *
      7  * This program is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 2 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this program; if not, write to the Free Software
     19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     20  *
     21  */
     22 
     23 #include <config.h>
     24 #include "dbus-print-message.h"
     25 
     26 #include <stdlib.h>
     27 #include "config.h"
     28 
     29 static const char*
     30 type_to_name (int message_type)
     31 {
     32   switch (message_type)
     33     {
     34     case DBUS_MESSAGE_TYPE_SIGNAL:
     35       return "signal";
     36     case DBUS_MESSAGE_TYPE_METHOD_CALL:
     37       return "method call";
     38     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
     39       return "method return";
     40     case DBUS_MESSAGE_TYPE_ERROR:
     41       return "error";
     42     default:
     43       return "(unknown message type)";
     44     }
     45 }
     46 
     47 #define INDENT 3
     48 
     49 static void
     50 indent (int depth)
     51 {
     52   while (depth-- > 0)
     53     printf ("   "); /* INDENT spaces. */
     54 }
     55 
     56 static void
     57 print_hex (unsigned char *bytes, unsigned int len, int depth)
     58 {
     59   unsigned int i, columns;
     60 
     61   printf ("array of bytes [\n");
     62 
     63   indent (depth + 1);
     64 
     65   /* Each byte takes 3 cells (two hexits, and a space), except the last one. */
     66   columns = (80 - ((depth + 1) * INDENT)) / 3;
     67 
     68   if (columns < 8)
     69     columns = 8;
     70 
     71   i = 0;
     72 
     73   while (i < len)
     74     {
     75       printf ("%02x", bytes[i]);
     76       i++;
     77 
     78       if (i != len)
     79         {
     80           if (i % columns == 0)
     81             {
     82               printf ("\n");
     83               indent (depth + 1);
     84             }
     85           else
     86             {
     87               printf (" ");
     88             }
     89         }
     90     }
     91 
     92   printf ("\n");
     93   indent (depth);
     94   printf ("]\n");
     95 }
     96 
     97 #define DEFAULT_SIZE 100
     98 
     99 static void
    100 print_ay (DBusMessageIter *iter, int depth)
    101 {
    102   /* Not using DBusString because it's not public API. It's 2009, and I'm
    103    * manually growing a string chunk by chunk.
    104    */
    105   unsigned char *bytes = malloc (DEFAULT_SIZE + 1);
    106   unsigned int len = 0;
    107   unsigned int max = DEFAULT_SIZE;
    108   dbus_bool_t all_ascii = TRUE;
    109   int current_type;
    110 
    111   while ((current_type = dbus_message_iter_get_arg_type (iter))
    112           != DBUS_TYPE_INVALID)
    113     {
    114       unsigned char val;
    115 
    116       dbus_message_iter_get_basic (iter, &val);
    117       bytes[len] = val;
    118       len++;
    119 
    120       if (val < 32 || val > 126)
    121         all_ascii = FALSE;
    122 
    123       if (len == max)
    124         {
    125           max *= 2;
    126           bytes = realloc (bytes, max + 1);
    127         }
    128 
    129       dbus_message_iter_next (iter);
    130     }
    131 
    132   if (all_ascii)
    133     {
    134       bytes[len] = '\0';
    135       printf ("array of bytes \"%s\"\n", bytes);
    136     }
    137   else
    138     {
    139       print_hex (bytes, len, depth);
    140     }
    141 
    142   free (bytes);
    143 }
    144 
    145 static void
    146 print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
    147 {
    148   do
    149     {
    150       int type = dbus_message_iter_get_arg_type (iter);
    151 
    152       if (type == DBUS_TYPE_INVALID)
    153 	break;
    154 
    155       indent(depth);
    156 
    157       switch (type)
    158 	{
    159 	case DBUS_TYPE_STRING:
    160 	  {
    161 	    char *val;
    162 	    dbus_message_iter_get_basic (iter, &val);
    163 	    if (!literal)
    164 	      printf ("string \"");
    165 	    printf ("%s", val);
    166 	    if (!literal)
    167 	      printf ("\"\n");
    168 	    break;
    169 	  }
    170 
    171 	case DBUS_TYPE_SIGNATURE:
    172 	  {
    173 	    char *val;
    174 	    dbus_message_iter_get_basic (iter, &val);
    175 	    if (!literal)
    176 	      printf ("signature \"");
    177 	    printf ("%s", val);
    178 	    if (!literal)
    179 	      printf ("\"\n");
    180 	    break;
    181 	  }
    182 
    183 	case DBUS_TYPE_OBJECT_PATH:
    184 	  {
    185 	    char *val;
    186 	    dbus_message_iter_get_basic (iter, &val);
    187 	    if (!literal)
    188 	      printf ("object path \"");
    189 	    printf ("%s", val);
    190 	    if (!literal)
    191 	      printf ("\"\n");
    192 	    break;
    193 	  }
    194 
    195 	case DBUS_TYPE_INT16:
    196 	  {
    197 	    dbus_int16_t val;
    198 	    dbus_message_iter_get_basic (iter, &val);
    199 	    printf ("int16 %d\n", val);
    200 	    break;
    201 	  }
    202 
    203 	case DBUS_TYPE_UINT16:
    204 	  {
    205 	    dbus_uint16_t val;
    206 	    dbus_message_iter_get_basic (iter, &val);
    207 	    printf ("uint16 %u\n", val);
    208 	    break;
    209 	  }
    210 
    211 	case DBUS_TYPE_INT32:
    212 	  {
    213 	    dbus_int32_t val;
    214 	    dbus_message_iter_get_basic (iter, &val);
    215 	    printf ("int32 %d\n", val);
    216 	    break;
    217 	  }
    218 
    219 	case DBUS_TYPE_UINT32:
    220 	  {
    221 	    dbus_uint32_t val;
    222 	    dbus_message_iter_get_basic (iter, &val);
    223 	    printf ("uint32 %u\n", val);
    224 	    break;
    225 	  }
    226 
    227 	case DBUS_TYPE_INT64:
    228 	  {
    229 	    dbus_int64_t val;
    230 	    dbus_message_iter_get_basic (iter, &val);
    231 #ifdef DBUS_INT64_PRINTF_MODIFIER
    232         printf ("int64 %" DBUS_INT64_PRINTF_MODIFIER "d\n", val);
    233 #else
    234         printf ("int64 (omitted)\n");
    235 #endif
    236 	    break;
    237 	  }
    238 
    239 	case DBUS_TYPE_UINT64:
    240 	  {
    241 	    dbus_uint64_t val;
    242 	    dbus_message_iter_get_basic (iter, &val);
    243 #ifdef DBUS_INT64_PRINTF_MODIFIER
    244         printf ("uint64 %" DBUS_INT64_PRINTF_MODIFIER "u\n", val);
    245 #else
    246         printf ("uint64 (omitted)\n");
    247 #endif
    248 	    break;
    249 	  }
    250 
    251 	case DBUS_TYPE_DOUBLE:
    252 	  {
    253 	    double val;
    254 	    dbus_message_iter_get_basic (iter, &val);
    255 	    printf ("double %g\n", val);
    256 	    break;
    257 	  }
    258 
    259 	case DBUS_TYPE_BYTE:
    260 	  {
    261 	    unsigned char val;
    262 	    dbus_message_iter_get_basic (iter, &val);
    263 	    printf ("byte %d\n", val);
    264 	    break;
    265 	  }
    266 
    267 	case DBUS_TYPE_BOOLEAN:
    268 	  {
    269 	    dbus_bool_t val;
    270 	    dbus_message_iter_get_basic (iter, &val);
    271 	    printf ("boolean %s\n", val ? "true" : "false");
    272 	    break;
    273 	  }
    274 
    275 	case DBUS_TYPE_VARIANT:
    276 	  {
    277 	    DBusMessageIter subiter;
    278 
    279 	    dbus_message_iter_recurse (iter, &subiter);
    280 
    281 	    printf ("variant ");
    282 	    print_iter (&subiter, literal, depth+1);
    283 	    break;
    284 	  }
    285 	case DBUS_TYPE_ARRAY:
    286 	  {
    287 	    int current_type;
    288 	    DBusMessageIter subiter;
    289 
    290 	    dbus_message_iter_recurse (iter, &subiter);
    291 
    292 	    current_type = dbus_message_iter_get_arg_type (&subiter);
    293 
    294 	    if (current_type == DBUS_TYPE_BYTE)
    295 	      {
    296 		print_ay (&subiter, depth);
    297 		break;
    298 	      }
    299 
    300 	    printf("array [\n");
    301 	    while (current_type != DBUS_TYPE_INVALID)
    302 	      {
    303 		print_iter (&subiter, literal, depth+1);
    304 
    305 		dbus_message_iter_next (&subiter);
    306 		current_type = dbus_message_iter_get_arg_type (&subiter);
    307 
    308 		if (current_type != DBUS_TYPE_INVALID)
    309 		  printf (",");
    310 	      }
    311 	    indent(depth);
    312 	    printf("]\n");
    313 	    break;
    314 	  }
    315 	case DBUS_TYPE_DICT_ENTRY:
    316 	  {
    317 	    DBusMessageIter subiter;
    318 
    319 	    dbus_message_iter_recurse (iter, &subiter);
    320 
    321 	    printf("dict entry(\n");
    322 	    print_iter (&subiter, literal, depth+1);
    323 	    dbus_message_iter_next (&subiter);
    324 	    print_iter (&subiter, literal, depth+1);
    325 	    indent(depth);
    326 	    printf(")\n");
    327 	    break;
    328 	  }
    329 
    330 	case DBUS_TYPE_STRUCT:
    331 	  {
    332 	    int current_type;
    333 	    DBusMessageIter subiter;
    334 
    335 	    dbus_message_iter_recurse (iter, &subiter);
    336 
    337 	    printf("struct {\n");
    338 	    while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
    339 	      {
    340 		print_iter (&subiter, literal, depth+1);
    341 		dbus_message_iter_next (&subiter);
    342 		if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID)
    343 		  printf (",");
    344 	      }
    345 	    indent(depth);
    346 	    printf("}\n");
    347 	    break;
    348 	  }
    349 
    350 	default:
    351 	  printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type);
    352 	  break;
    353 	}
    354     } while (dbus_message_iter_next (iter));
    355 }
    356 
    357 void
    358 print_message (DBusMessage *message, dbus_bool_t literal)
    359 {
    360   DBusMessageIter iter;
    361   const char *sender;
    362   const char *destination;
    363   int message_type;
    364 
    365   message_type = dbus_message_get_type (message);
    366   sender = dbus_message_get_sender (message);
    367   destination = dbus_message_get_destination (message);
    368 
    369   if (!literal)
    370     {
    371       printf ("%s sender=%s -> dest=%s",
    372 	      type_to_name (message_type),
    373 	      sender ? sender : "(null sender)",
    374 	      destination ? destination : "(null destination)");
    375 
    376       switch (message_type)
    377 	{
    378 	case DBUS_MESSAGE_TYPE_METHOD_CALL:
    379 	case DBUS_MESSAGE_TYPE_SIGNAL:
    380 	  printf (" serial=%u path=%s; interface=%s; member=%s\n",
    381                   dbus_message_get_serial (message),
    382 		  dbus_message_get_path (message),
    383 		  dbus_message_get_interface (message),
    384 		  dbus_message_get_member (message));
    385 	  break;
    386 
    387 	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
    388 	  printf (" reply_serial=%u\n",
    389           dbus_message_get_reply_serial (message));
    390 	  break;
    391 
    392 	case DBUS_MESSAGE_TYPE_ERROR:
    393 	  printf (" error_name=%s reply_serial=%u\n",
    394 		  dbus_message_get_error_name (message),
    395           dbus_message_get_reply_serial (message));
    396 	  break;
    397 
    398 	default:
    399 	  printf ("\n");
    400 	  break;
    401 	}
    402     }
    403 
    404   dbus_message_iter_init (message, &iter);
    405   print_iter (&iter, literal, 1);
    406   fflush (stdout);
    407 
    408 }
    409 
    410