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