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