travis-ci: Enable/disable more features in various builds
[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 #ifdef DBUS_UNIX
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <unistd.h>
32 #include <netinet/in.h>
33 #include <netinet/ip.h>
34 #include <arpa/inet.h>
35 #endif
36
37 #include <stdlib.h>
38 #include "config.h"
39
40 #include "tool-common.h"
41
42 #ifdef HAVE_INTTYPES_H
43 #include <inttypes.h>
44 #endif
45
46 #if defined(DBUS_WIN)
47 #if !defined(PRId64)
48 #define PRId64 "I64d"
49 #endif
50 #if !defined(PRIu64)
51 #define PRIu64 "I64u"
52 #endif
53 #endif
54
55 #ifndef HAVE_SOCKLEN_T
56 #define socklen_t int
57 #endif
58
59 static const char*
60 type_to_name (int message_type)
61 {
62   switch (message_type)
63     {
64     case DBUS_MESSAGE_TYPE_SIGNAL:
65       return "signal";
66     case DBUS_MESSAGE_TYPE_METHOD_CALL:
67       return "method call";
68     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
69       return "method return";
70     case DBUS_MESSAGE_TYPE_ERROR:
71       return "error";
72     default:
73       return "(unknown message type)";
74     }
75 }
76
77 #define INDENT 3
78
79 static void
80 indent (int depth)
81 {
82   while (depth-- > 0)
83     printf ("   "); /* INDENT spaces. */
84 }
85
86 static void
87 print_hex (const unsigned char *bytes,
88            unsigned int len,
89            int depth)
90 {
91   unsigned int i, columns;
92
93   printf ("array of bytes [\n");
94
95   indent (depth + 1);
96
97   /* Each byte takes 3 cells (two hexits, and a space), except the last one. */
98   columns = (80 - ((depth + 1) * INDENT)) / 3;
99
100   if (columns < 8)
101     columns = 8;
102
103   i = 0;
104
105   while (i < len)
106     {
107       printf ("%02x", bytes[i]);
108       i++;
109
110       if (i != len)
111         {
112           if (i % columns == 0)
113             {
114               printf ("\n");
115               indent (depth + 1);
116             }
117           else
118             {
119               printf (" ");
120             }
121         }
122     }
123
124   printf ("\n");
125   indent (depth);
126   printf ("]\n");
127 }
128
129 #define DEFAULT_SIZE 100
130
131 static void
132 print_ay (DBusMessageIter *iter, int depth)
133 {
134   /* True if every byte in the bytestring (so far) is printable
135    * ASCII, with one exception: the last byte is also allowed to be \0. */
136   dbus_bool_t all_ascii = TRUE;
137   const unsigned char *bytes;
138   int len;
139   int i;
140
141   dbus_message_iter_get_fixed_array (iter, &bytes, &len);
142
143   for (i = 0; i < len; i++)
144     {
145       if ((bytes[i] < 32 || bytes[i] > 126) &&
146           (i < len - 1 || bytes[i] != '\0'))
147         {
148           all_ascii = FALSE;
149           break;
150         }
151     }
152
153   if (all_ascii && len > 0 && bytes[len - 1] == '\0')
154     {
155       printf ("array of bytes \"%s\" + \\0\n", bytes);
156     }
157   else if (all_ascii)
158     {
159       unsigned char *copy = dbus_malloc (len + 1);
160
161       if (copy == NULL)
162         tool_oom ("copying bytestring");
163
164       memcpy (copy, bytes, len);
165       copy[len] = '\0';
166       printf ("array of bytes \"%s\"\n", copy);
167       dbus_free (copy);
168     }
169   else
170     {
171       print_hex (bytes, len, depth);
172     }
173 }
174
175 #ifdef DBUS_UNIX
176 static void
177 print_fd (int fd, int depth)
178 {
179   int ret;
180   struct stat statbuf = {0,};
181   union {
182       struct sockaddr sa;
183       struct sockaddr_storage storage;
184       struct sockaddr_un un;
185       struct sockaddr_in ipv4;
186       struct sockaddr_in6 ipv6;
187   } addr, peer;
188   char hostip[INET6_ADDRSTRLEN];
189   socklen_t addrlen = sizeof (addr);
190   socklen_t peerlen = sizeof (peer);
191   int has_peer;
192
193   /* Don't print the fd number: it is different in every process and since
194    * dbus-monitor closes the fd after reading it, the same number would be
195    * printed again and again.
196    */
197   printf ("file descriptor\n");
198   if (fd == -1)
199     return;
200
201   ret = fstat (fd, &statbuf);
202   if (ret == -1)
203     return;
204
205   indent (depth+1);
206   printf ("inode: %d\n", (int) statbuf.st_ino);
207
208   indent (depth+1);
209   printf ("type: ");
210   if (S_ISREG(statbuf.st_mode))
211     printf ("file\n");
212   if (S_ISDIR(statbuf.st_mode))
213     printf ("directory\n");
214   if (S_ISCHR(statbuf.st_mode))
215     printf ("char\n");
216   if (S_ISBLK(statbuf.st_mode))
217     printf ("block\n");
218   if (S_ISFIFO(statbuf.st_mode))
219     printf ("fifo\n");
220   if (S_ISLNK(statbuf.st_mode))
221     printf ("link\n");
222   if (S_ISSOCK(statbuf.st_mode))
223     printf ("socket\n");
224
225   /* If it's not a socket, getsockname will just return -1 with errno
226    * ENOTSOCK. */
227
228   memset (&addr, 0, sizeof (addr));
229   memset (&peer, 0, sizeof (peer));
230
231   if (getsockname(fd, &addr.sa, &addrlen))
232     return;
233
234   has_peer = !getpeername(fd, &peer.sa, &peerlen);
235
236   indent (depth+1);
237   printf ("address family: ");
238   switch (addr.sa.sa_family)
239     {
240       case AF_UNIX:
241         printf("unix\n");
242         if (addr.un.sun_path[0] == '\0')
243           {
244             /* Abstract socket might not be zero-terminated and length is
245              * variable. Who designed this interface?
246              * Write the name in the same way as /proc/net/unix
247              * See manual page unix(7)
248              */
249             indent (depth+1);
250             printf ("name @%.*s\n",
251                     (int) (addrlen - sizeof (sa_family_t) - 1),
252                     &(addr.un.sun_path[1]));
253
254             if (has_peer)
255               {
256                 indent (depth+1);
257                 printf ("peer @%.*s\n",
258                         (int) (addrlen - sizeof (sa_family_t) - 1),
259                         &(addr.un.sun_path[1]));
260               }
261           }
262         else
263           {
264             indent (depth+1);
265             printf ("name %s\n", addr.un.sun_path);
266             if (has_peer)
267               {
268                 indent (depth+1);
269                 printf ("peer %s\n", peer.un.sun_path);
270               }
271           }
272         break;
273
274       case AF_INET:
275         printf ("inet\n");
276         if (inet_ntop (AF_INET, &addr.ipv4.sin_addr, hostip, sizeof (hostip)))
277           {
278             indent (depth+1);
279             printf ("name %s port %u\n", hostip, ntohs (addr.ipv4.sin_port));
280           }
281         if (has_peer && inet_ntop (AF_INET, &peer.ipv4.sin_addr, hostip, sizeof (hostip)))
282           {
283             indent (depth+1);
284             printf ("peer %s port %u\n", hostip, ntohs (peer.ipv4.sin_port));
285           }
286
287         break;
288
289 #ifdef AF_INET6
290       case AF_INET6:
291         printf ("inet6\n");
292         if (inet_ntop (AF_INET6, &addr.ipv6.sin6_addr, hostip, sizeof (hostip)))
293           {
294             indent (depth+1);
295             printf ("name %s port %u\n", hostip, ntohs (addr.ipv6.sin6_port));
296           }
297         if (has_peer && inet_ntop (AF_INET6, &peer.ipv6.sin6_addr, hostip, sizeof (hostip)))
298           {
299             indent (depth+1);
300             printf ("peer %s port %u\n", hostip, ntohs (peer.ipv6.sin6_port));
301           }
302         break;
303 #endif
304
305 #ifdef AF_BLUETOOTH
306       case AF_BLUETOOTH:
307         printf ("bluetooth\n");
308         break;
309 #endif
310
311       default:
312         printf ("unknown (%d)\n", addr.sa.sa_family);
313         break;
314     }
315 }
316 #endif
317
318 static void
319 print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
320 {
321   do
322     {
323       int type = dbus_message_iter_get_arg_type (iter);
324
325       if (type == DBUS_TYPE_INVALID)
326         break;
327       
328       indent(depth);
329
330       switch (type)
331         {
332         case DBUS_TYPE_STRING:
333           {
334             char *val;
335             dbus_message_iter_get_basic (iter, &val);
336             if (!literal)
337               printf ("string \"");
338             printf ("%s", val);
339             if (!literal)
340               printf ("\"\n");
341             break;
342           }
343
344         case DBUS_TYPE_SIGNATURE:
345           {
346             char *val;
347             dbus_message_iter_get_basic (iter, &val);
348             if (!literal)
349               printf ("signature \"");
350             printf ("%s", val);
351             if (!literal)
352               printf ("\"\n");
353             break;
354           }
355
356         case DBUS_TYPE_OBJECT_PATH:
357           {
358             char *val;
359             dbus_message_iter_get_basic (iter, &val);
360             if (!literal)
361               printf ("object path \"");
362             printf ("%s", val);
363             if (!literal)
364               printf ("\"\n");
365             break;
366           }
367
368         case DBUS_TYPE_INT16:
369           {
370             dbus_int16_t val;
371             dbus_message_iter_get_basic (iter, &val);
372             printf ("int16 %d\n", val);
373             break;
374           }
375
376         case DBUS_TYPE_UINT16:
377           {
378             dbus_uint16_t val;
379             dbus_message_iter_get_basic (iter, &val);
380             printf ("uint16 %u\n", val);
381             break;
382           }
383
384         case DBUS_TYPE_INT32:
385           {
386             dbus_int32_t val;
387             dbus_message_iter_get_basic (iter, &val);
388             printf ("int32 %d\n", val);
389             break;
390           }
391
392         case DBUS_TYPE_UINT32:
393           {
394             dbus_uint32_t val;
395             dbus_message_iter_get_basic (iter, &val);
396             printf ("uint32 %u\n", val);
397             break;
398           }
399
400         case DBUS_TYPE_INT64:
401           {
402             dbus_int64_t val;
403             dbus_message_iter_get_basic (iter, &val);
404             printf ("int64 %" PRId64 "\n", val);
405             break;
406           }
407
408         case DBUS_TYPE_UINT64:
409           {
410             dbus_uint64_t val;
411             dbus_message_iter_get_basic (iter, &val);
412             printf ("uint64 %" PRIu64 "\n", val);
413             break;
414           }
415
416         case DBUS_TYPE_DOUBLE:
417           {
418             double val;
419             dbus_message_iter_get_basic (iter, &val);
420             printf ("double %g\n", val);
421             break;
422           }
423
424         case DBUS_TYPE_BYTE:
425           {
426             unsigned char val;
427             dbus_message_iter_get_basic (iter, &val);
428             printf ("byte %d\n", val);
429             break;
430           }
431
432         case DBUS_TYPE_BOOLEAN:
433           {
434             dbus_bool_t val;
435             dbus_message_iter_get_basic (iter, &val);
436             printf ("boolean %s\n", val ? "true" : "false");
437             break;
438           }
439
440         case DBUS_TYPE_VARIANT:
441           {
442             DBusMessageIter subiter;
443
444             dbus_message_iter_recurse (iter, &subiter);
445
446             printf ("variant ");
447             print_iter (&subiter, literal, depth+1);
448             break;
449           }
450         case DBUS_TYPE_ARRAY:
451           {
452             int current_type;
453             DBusMessageIter subiter;
454
455             dbus_message_iter_recurse (iter, &subiter);
456
457             current_type = dbus_message_iter_get_arg_type (&subiter);
458
459             if (current_type == DBUS_TYPE_BYTE)
460               {
461                 print_ay (&subiter, depth);
462                 break;
463               }
464
465             printf("array [\n");
466             while (current_type != DBUS_TYPE_INVALID)
467               {
468                 print_iter (&subiter, literal, depth+1);
469
470                 dbus_message_iter_next (&subiter);
471                 current_type = dbus_message_iter_get_arg_type (&subiter);
472
473                 if (current_type != DBUS_TYPE_INVALID)
474                   printf (",");
475               }
476             indent(depth);
477             printf("]\n");
478             break;
479           }
480         case DBUS_TYPE_DICT_ENTRY:
481           {
482             DBusMessageIter subiter;
483
484             dbus_message_iter_recurse (iter, &subiter);
485
486             printf("dict entry(\n");
487             print_iter (&subiter, literal, depth+1);
488             dbus_message_iter_next (&subiter);
489             print_iter (&subiter, literal, depth+1);
490             indent(depth);
491             printf(")\n");
492             break;
493           }
494
495         case DBUS_TYPE_STRUCT:
496           {
497             int current_type;
498             DBusMessageIter subiter;
499
500             dbus_message_iter_recurse (iter, &subiter);
501
502             printf("struct {\n");
503             while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
504               {
505                 print_iter (&subiter, literal, depth+1);
506                 dbus_message_iter_next (&subiter);
507                 if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID)
508                   printf (",");
509               }
510             indent(depth);
511             printf("}\n");
512             break;
513           }
514
515 #ifdef DBUS_UNIX
516         case DBUS_TYPE_UNIX_FD:
517           {
518             int fd;
519             dbus_message_iter_get_basic (iter, &fd);
520
521             print_fd (fd, depth+1);
522
523             /* dbus_message_iter_get_basic() duplicated the fd, we need to
524              * close it after use. The original fd will be closed when the
525              * DBusMessage is released.
526              */
527             close (fd);
528
529             break;
530           }
531 #endif
532
533         default:
534           printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type);
535           break;
536         }
537     } while (dbus_message_iter_next (iter));
538 }
539
540 void
541 print_message (DBusMessage *message, dbus_bool_t literal, long sec, long usec)
542 {
543   DBusMessageIter iter;
544   const char *sender;
545   const char *destination;
546   int message_type;
547
548   message_type = dbus_message_get_type (message);
549   sender = dbus_message_get_sender (message);
550   destination = dbus_message_get_destination (message);
551   
552   if (!literal)
553     {
554       if (sec != 0 || usec != 0)
555         {
556           printf ("%s time=%ld.%06ld sender=%s -> destination=%s",
557                   type_to_name (message_type), sec, usec,
558                   sender ? sender : "(null sender)",
559                   destination ? destination : "(null destination)");
560         }
561       else
562         {
563           printf ("%s sender=%s -> destination=%s",
564                   type_to_name (message_type),
565                   sender ? sender : "(null sender)",
566                   destination ? destination : "(null destination)");
567         }
568
569       switch (message_type)
570         {
571         case DBUS_MESSAGE_TYPE_METHOD_CALL:
572         case DBUS_MESSAGE_TYPE_SIGNAL:
573           printf (" serial=%u path=%s; interface=%s; member=%s\n",
574                   dbus_message_get_serial (message),
575                   dbus_message_get_path (message),
576                   dbus_message_get_interface (message),
577                   dbus_message_get_member (message));
578           break;
579       
580         case DBUS_MESSAGE_TYPE_METHOD_RETURN:
581           printf (" serial=%u reply_serial=%u\n",
582                   dbus_message_get_serial (message),
583           dbus_message_get_reply_serial (message));
584           break;
585
586         case DBUS_MESSAGE_TYPE_ERROR:
587           printf (" error_name=%s reply_serial=%u\n",
588                   dbus_message_get_error_name (message),
589           dbus_message_get_reply_serial (message));
590           break;
591
592         default:
593           printf ("\n");
594           break;
595         }
596     }
597
598   dbus_message_iter_init (message, &iter);
599   print_iter (&iter, literal, 1);
600   fflush (stdout);
601   
602 }
603