| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ |
| /* dbus-print-message.h Utility function to print out a message |
| * |
| * Copyright (C) 2003 Philip Blundell <philb@gnu.org> |
| * Copyright (C) 2003 Red Hat, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #include <config.h> |
| #include "dbus-print-message.h" |
| |
| #ifdef DBUS_UNIX |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <unistd.h> |
| #include <netinet/in.h> |
| #include <netinet/ip.h> |
| #include <arpa/inet.h> |
| #endif |
| |
| #include <stdlib.h> |
| #include "config.h" |
| |
| #include "tool-common.h" |
| |
| static const char* |
| type_to_name (int message_type) |
| { |
| switch (message_type) |
| { |
| case DBUS_MESSAGE_TYPE_SIGNAL: |
| return "signal"; |
| case DBUS_MESSAGE_TYPE_METHOD_CALL: |
| return "method call"; |
| case DBUS_MESSAGE_TYPE_METHOD_RETURN: |
| return "method return"; |
| case DBUS_MESSAGE_TYPE_ERROR: |
| return "error"; |
| default: |
| return "(unknown message type)"; |
| } |
| } |
| |
| #define INDENT 3 |
| |
| static void |
| indent (int depth) |
| { |
| while (depth-- > 0) |
| printf (" "); /* INDENT spaces. */ |
| } |
| |
| static void |
| print_hex (const unsigned char *bytes, |
| unsigned int len, |
| int depth) |
| { |
| unsigned int i, columns; |
| |
| printf ("array of bytes [\n"); |
| |
| indent (depth + 1); |
| |
| /* Each byte takes 3 cells (two hexits, and a space), except the last one. */ |
| columns = (80 - ((depth + 1) * INDENT)) / 3; |
| |
| if (columns < 8) |
| columns = 8; |
| |
| i = 0; |
| |
| while (i < len) |
| { |
| printf ("%02x", bytes[i]); |
| i++; |
| |
| if (i != len) |
| { |
| if (i % columns == 0) |
| { |
| printf ("\n"); |
| indent (depth + 1); |
| } |
| else |
| { |
| printf (" "); |
| } |
| } |
| } |
| |
| printf ("\n"); |
| indent (depth); |
| printf ("]\n"); |
| } |
| |
| #define DEFAULT_SIZE 100 |
| |
| #include <inttypes.h> |
| #define DBUS_INT64_PRINTF_ARGUMENT PRIi64 |
| #define DBUS_UINT64_PRINTF_ARGUMENT PRIu64 |
| #define MAXPFX 4096 |
| |
| static int |
| pf_can_simple(DBusMessageIter *iter) |
| { |
| switch (dbus_message_iter_get_arg_type(iter)) |
| { |
| case DBUS_TYPE_STRING: |
| case DBUS_TYPE_INT16: |
| case DBUS_TYPE_INT32: |
| case DBUS_TYPE_UINT16: |
| case DBUS_TYPE_UINT32: |
| case DBUS_TYPE_INT64: |
| case DBUS_TYPE_UINT64: |
| case DBUS_TYPE_BYTE: |
| case DBUS_TYPE_BOOLEAN: |
| case DBUS_TYPE_DOUBLE: |
| return 1; |
| default: |
| return 0; |
| } |
| } |
| |
| static void pf_key(DBusMessageIter *iter, const char *pfx, char *buf, size_t sz) |
| { |
| char *sv; |
| dbus_bool_t bv; |
| dbus_int16_t i16v; |
| dbus_int32_t i32v; |
| dbus_int64_t i64v; |
| dbus_uint16_t u16v; |
| dbus_uint32_t u32v; |
| dbus_uint64_t u64v; |
| unsigned char u8v; |
| double dv; |
| |
| switch (dbus_message_iter_get_arg_type(iter)) { |
| case DBUS_TYPE_STRING: |
| dbus_message_iter_get_basic(iter, &sv); |
| snprintf(buf, sz, "%s/%s", pfx, sv); |
| break; |
| case DBUS_TYPE_BOOLEAN: |
| dbus_message_iter_get_basic(iter, &bv); |
| snprintf(buf, sz, "%s/%s", pfx, (bv ? "true" : "false")); |
| break; |
| case DBUS_TYPE_INT16: |
| dbus_message_iter_get_basic(iter, &i16v); |
| snprintf(buf, sz, "%s/%d", pfx, i16v); |
| break; |
| case DBUS_TYPE_INT32: |
| dbus_message_iter_get_basic(iter, &i32v); |
| snprintf(buf, sz, "%s/%d", pfx, i32v); |
| break; |
| case DBUS_TYPE_INT64: |
| dbus_message_iter_get_basic(iter, &i64v); |
| #ifdef DBUS_INT64_PRINTF_ARGUMENT |
| snprintf(buf, sz, "%s/%" DBUS_INT64_PRINTF_ARGUMENT, pfx, i64v); |
| #else |
| snprintf(buf, sz, "%s/[int64]", pfx); |
| #endif |
| break; |
| case DBUS_TYPE_UINT16: |
| dbus_message_iter_get_basic(iter, &u16v); |
| snprintf(buf, sz, "%s/%u", pfx, u16v); |
| break; |
| case DBUS_TYPE_UINT32: |
| dbus_message_iter_get_basic(iter, &u32v); |
| snprintf(buf, sz, "%s/%u", pfx, u32v); |
| break; |
| case DBUS_TYPE_UINT64: |
| dbus_message_iter_get_basic(iter, &u64v); |
| #ifdef DBUS_UINT64_PRINTF_ARGUMENT |
| snprintf(buf, sz, "%s/%" DBUS_UINT64_PRINTF_ARGUMENT, pfx, u64v); |
| #else |
| snprintf(buf, sz, "%s/[uint64]", pfx); |
| #endif |
| break; |
| case DBUS_TYPE_BYTE: |
| dbus_message_iter_get_basic(iter, &u8v); |
| snprintf(buf, sz, "%s/%02x", pfx, (unsigned int)u8v & 0xFF); |
| break; |
| case DBUS_TYPE_DOUBLE: |
| dbus_message_iter_get_basic(iter, &dv); |
| snprintf(buf, sz, "%s/%g", pfx, dv); |
| break; |
| default: |
| snprintf(buf, sz, "%s/[pf-unknown]", pfx); |
| break; |
| } |
| } |
| |
| static void print_fixed_iter(DBusMessageIter *iter, const char *pfx, int all); |
| |
| static void pf_string(DBusMessageIter *iter, const char *pfx) |
| { |
| char *val; |
| dbus_message_iter_get_basic(iter, &val); |
| printf("%s%s%s\n", pfx, pfx[0] ? " " : "", val); |
| } |
| |
| static void pf_boolean(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_bool_t bv; |
| dbus_message_iter_get_basic(iter, &bv); |
| printf("%s%s%s\n", pfx, pfx[0] ? " " : "", (bv ? "true" : "false")); |
| } |
| |
| static void pf_uint16(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_uint16_t uv; |
| dbus_message_iter_get_basic(iter, &uv); |
| printf("%s%s%u\n", pfx, pfx[0] ? " " : "", uv); |
| } |
| |
| static void pf_int16(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_int16_t iv; |
| dbus_message_iter_get_basic(iter, &iv); |
| printf("%s%s%d\n", pfx, pfx[0] ? " " : "", iv); |
| } |
| |
| static void pf_uint32(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_uint32_t uv; |
| dbus_message_iter_get_basic(iter, &uv); |
| printf("%s%s%u\n", pfx, pfx[0] ? " " : "", uv); |
| } |
| |
| static void pf_int32(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_int32_t iv; |
| dbus_message_iter_get_basic(iter, &iv); |
| printf("%s%s%d\n", pfx, pfx[0] ? " " : "", iv); |
| } |
| |
| static void pf_uint64(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_uint64_t uv; |
| dbus_message_iter_get_basic(iter, &uv); |
| #ifdef DBUS_UINT64_PRINTF_ARGUMENT |
| printf("%s%s%" DBUS_UINT64_PRINTF_ARGUMENT "\n", pfx, pfx[0] ? " " : "", uv); |
| #else |
| printf("%s%s[uint64]\n", pfx, pfx[0] ? " " : ""); |
| #endif |
| } |
| |
| static void pf_int64(DBusMessageIter *iter, const char *pfx) |
| { |
| dbus_int64_t iv; |
| dbus_message_iter_get_basic(iter, &iv); |
| #ifdef DBUS_INT64_PRINTF_ARGUMENT |
| printf("%s%s%" DBUS_INT64_PRINTF_ARGUMENT "\n", pfx, pfx[0] ? " " : "", iv); |
| #else |
| printf("%s%s[int64]\n", pfx, pfx[0] ? " " : ""); |
| #endif |
| } |
| |
| static void pf_double(DBusMessageIter *iter, const char *pfx) |
| { |
| double dv; |
| dbus_message_iter_get_basic(iter, &dv); |
| printf("%s%s%g\n", pfx, pfx[0] ? " " : "", dv); |
| } |
| |
| static void pf_byte(DBusMessageIter *iter, const char *pfx) |
| { |
| unsigned char bv; |
| dbus_message_iter_get_basic(iter, &bv); |
| printf("%s%s%02x\n", pfx, pfx[0] ? " " : "", (unsigned int)bv & 0xFF); |
| } |
| |
| static void pf_array(DBusMessageIter *iter, const char *pfx) |
| { |
| int type; |
| DBusMessageIter subiter; |
| char npfx[MAXPFX]; |
| int i = 0; |
| |
| dbus_message_iter_recurse(iter, &subiter); |
| type = dbus_message_iter_get_arg_type(&subiter); |
| |
| while (type != DBUS_TYPE_INVALID) |
| { |
| snprintf(npfx, sizeof(npfx), "%s/%d", pfx, i); |
| print_fixed_iter(&subiter, npfx, 0); |
| dbus_message_iter_next(&subiter); |
| type = dbus_message_iter_get_arg_type(&subiter); |
| i++; |
| } |
| } |
| |
| static void pf_variant(DBusMessageIter *iter, const char *pfx) |
| { |
| DBusMessageIter subiter; |
| dbus_message_iter_recurse(iter, &subiter); |
| print_fixed_iter(&subiter, pfx, 0); |
| } |
| |
| static void pf_dict(DBusMessageIter *iter, const char *pfx) |
| { |
| DBusMessageIter subiter; |
| char npfx[MAXPFX]; |
| |
| dbus_message_iter_recurse(iter, &subiter); |
| /* Nasty hack to make string -> thing dicts more parseable. */ |
| if (pf_can_simple(&subiter)) |
| { |
| pf_key(&subiter, pfx, npfx, sizeof(npfx)); |
| } |
| else |
| { |
| snprintf(npfx, MAXPFX, "%s/[complex-key]", pfx); |
| } |
| dbus_message_iter_next(&subiter); |
| print_fixed_iter(&subiter, npfx, 0); |
| } |
| |
| static void print_fixed_iter(DBusMessageIter *iter, const char *pfx, int all) |
| { |
| static struct { |
| int type; |
| void (*func)(DBusMessageIter *iter, const char *pfx); |
| } printers[] = { |
| { DBUS_TYPE_STRING, pf_string }, |
| { DBUS_TYPE_ARRAY, pf_array }, |
| { DBUS_TYPE_STRUCT, pf_array }, /* yes, really. They're identical. */ |
| { DBUS_TYPE_VARIANT, pf_variant }, |
| { DBUS_TYPE_DICT_ENTRY, pf_dict }, |
| { DBUS_TYPE_BOOLEAN, pf_boolean }, |
| { DBUS_TYPE_UINT32, pf_uint32 }, |
| { DBUS_TYPE_INT32, pf_int32 }, |
| { DBUS_TYPE_SIGNATURE, pf_string }, |
| { DBUS_TYPE_OBJECT_PATH, pf_string }, |
| { DBUS_TYPE_INT16, pf_int16 }, |
| { DBUS_TYPE_UINT16, pf_uint16 }, |
| { DBUS_TYPE_INT64, pf_int64 }, |
| { DBUS_TYPE_UINT64, pf_uint64 }, |
| { DBUS_TYPE_DOUBLE, pf_double }, |
| { DBUS_TYPE_BYTE, pf_byte }, |
| { 0, NULL } |
| }; |
| int type; |
| int i; |
| |
| do |
| { |
| type = dbus_message_iter_get_arg_type(iter); |
| if (type == DBUS_TYPE_INVALID) |
| return; |
| for (i = 0; printers[i].func; i++) |
| { |
| if (printers[i].type == type) |
| { |
| printers[i].func(iter, pfx); |
| break; |
| } |
| } |
| if (!printers[i].func) |
| { |
| printf("print-fixed-iter: no idea what %d is\n", type); |
| } |
| } |
| while (all && dbus_message_iter_next(iter)); |
| } |
| |
| void print_message_fixed(DBusMessage *msg) |
| { |
| DBusMessageIter iter; |
| int type; |
| |
| type = dbus_message_get_type(msg); |
| dbus_message_iter_init(msg, &iter); |
| print_fixed_iter(&iter, "", 1); |
| } |
| |
| static void |
| print_ay (DBusMessageIter *iter, int depth) |
| { |
| /* 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; |
| const unsigned char *bytes; |
| int len; |
| int i; |
| |
| dbus_message_iter_get_fixed_array (iter, &bytes, &len); |
| |
| for (i = 0; i < len; i++) |
| { |
| if ((bytes[i] < 32 || bytes[i] > 126) && |
| (i < len - 1 || bytes[i] != '\0')) |
| { |
| all_ascii = FALSE; |
| break; |
| } |
| } |
| |
| if (all_ascii && len > 0 && bytes[len - 1] == '\0') |
| { |
| printf ("array of bytes \"%s\" + \\0\n", bytes); |
| } |
| else if (all_ascii) |
| { |
| 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); |
| } |
| } |
| |
| #ifdef DBUS_UNIX |
| static void |
| print_fd (int fd, int depth) |
| { |
| int ret; |
| struct stat statbuf = {0,}; |
| union { |
| struct sockaddr sa; |
| struct sockaddr_storage storage; |
| struct sockaddr_un un; |
| struct sockaddr_in ipv4; |
| struct sockaddr_in6 ipv6; |
| } addr, peer; |
| char hostip[INET6_ADDRSTRLEN]; |
| int addrlen = sizeof (addr); |
| int peerlen = sizeof (peer); |
| int has_peer; |
| |
| /* Don't print the fd number: it is different in every process and since |
| * dbus-monitor closes the fd after reading it, the same number would be |
| * printed again and again. |
| */ |
| printf ("file descriptor\n"); |
| if (fd == -1) |
| return; |
| |
| ret = fstat (fd, &statbuf); |
| if (ret == -1) |
| return; |
| |
| indent (depth+1); |
| printf ("inode: %d\n", (int) statbuf.st_ino); |
| |
| indent (depth+1); |
| printf ("type: "); |
| if (S_ISREG(statbuf.st_mode)) |
| printf ("file\n"); |
| if (S_ISDIR(statbuf.st_mode)) |
| printf ("directory\n"); |
| if (S_ISCHR(statbuf.st_mode)) |
| printf ("char\n"); |
| if (S_ISBLK(statbuf.st_mode)) |
| printf ("block\n"); |
| if (S_ISFIFO(statbuf.st_mode)) |
| printf ("fifo\n"); |
| if (S_ISLNK(statbuf.st_mode)) |
| printf ("link\n"); |
| if (S_ISSOCK(statbuf.st_mode)) |
| printf ("socket\n"); |
| |
| /* If it's not a socket, getsockname will just return -1 with errno |
| * ENOTSOCK. */ |
| |
| memset (&addr, 0, sizeof (addr)); |
| memset (&peer, 0, sizeof (peer)); |
| |
| if (getsockname(fd, &addr.sa, &addrlen)) |
| return; |
| |
| has_peer = !getpeername(fd, &peer.sa, &peerlen); |
| |
| indent (depth+1); |
| printf ("address family: "); |
| switch (addr.sa.sa_family) |
| { |
| case AF_UNIX: |
| printf("unix\n"); |
| if (addr.un.sun_path[0] == '\0') |
| { |
| /* Abstract socket might not be zero-terminated and length is |
| * variable. Who designed this interface? |
| * Write the name in the same way as /proc/net/unix |
| * See manual page unix(7) |
| */ |
| indent (depth+1); |
| printf ("name @%.*s\n", |
| (int) (addrlen - sizeof (sa_family_t) - 1), |
| &(addr.un.sun_path[1])); |
| |
| if (has_peer) |
| { |
| indent (depth+1); |
| printf ("peer @%.*s\n", |
| (int) (addrlen - sizeof (sa_family_t) - 1), |
| &(addr.un.sun_path[1])); |
| } |
| } |
| else |
| { |
| indent (depth+1); |
| printf ("name %s\n", addr.un.sun_path); |
| if (has_peer) |
| { |
| indent (depth+1); |
| printf ("peer %s\n", peer.un.sun_path); |
| } |
| } |
| break; |
| |
| case AF_INET: |
| printf ("inet\n"); |
| if (inet_ntop (AF_INET, &addr.ipv4.sin_addr, hostip, sizeof (hostip))) |
| { |
| indent (depth+1); |
| printf ("name %s port %u\n", hostip, ntohs (addr.ipv4.sin_port)); |
| } |
| if (has_peer && inet_ntop (AF_INET, &peer.ipv4.sin_addr, hostip, sizeof (hostip))) |
| { |
| indent (depth+1); |
| printf ("peer %s port %u\n", hostip, ntohs (peer.ipv4.sin_port)); |
| } |
| |
| break; |
| |
| #ifdef AF_INET6 |
| case AF_INET6: |
| printf ("inet6\n"); |
| if (inet_ntop (AF_INET6, &addr.ipv6.sin6_addr, hostip, sizeof (hostip))) |
| { |
| indent (depth+1); |
| printf ("name %s port %u\n", hostip, ntohs (addr.ipv6.sin6_port)); |
| } |
| if (has_peer && inet_ntop (AF_INET6, &peer.ipv6.sin6_addr, hostip, sizeof (hostip))) |
| { |
| indent (depth+1); |
| printf ("peer %s port %u\n", hostip, ntohs (peer.ipv6.sin6_port)); |
| } |
| break; |
| #endif |
| |
| #ifdef AF_BLUETOOTH |
| case AF_BLUETOOTH: |
| printf ("bluetooth\n"); |
| break; |
| #endif |
| |
| default: |
| printf ("unknown (%d)\n", addr.sa.sa_family); |
| break; |
| } |
| } |
| #endif |
| |
| static void |
| print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth) |
| { |
| do |
| { |
| int type = dbus_message_iter_get_arg_type (iter); |
| |
| if (type == DBUS_TYPE_INVALID) |
| break; |
| |
| indent(depth); |
| |
| switch (type) |
| { |
| case DBUS_TYPE_STRING: |
| { |
| char *val; |
| dbus_message_iter_get_basic (iter, &val); |
| if (!literal) |
| printf ("string \""); |
| printf ("%s", val); |
| if (!literal) |
| printf ("\"\n"); |
| break; |
| } |
| |
| case DBUS_TYPE_SIGNATURE: |
| { |
| char *val; |
| dbus_message_iter_get_basic (iter, &val); |
| if (!literal) |
| printf ("signature \""); |
| printf ("%s", val); |
| if (!literal) |
| printf ("\"\n"); |
| break; |
| } |
| |
| case DBUS_TYPE_OBJECT_PATH: |
| { |
| char *val; |
| dbus_message_iter_get_basic (iter, &val); |
| if (!literal) |
| printf ("object path \""); |
| printf ("%s", val); |
| if (!literal) |
| printf ("\"\n"); |
| break; |
| } |
| |
| case DBUS_TYPE_INT16: |
| { |
| dbus_int16_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("int16 %d\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_UINT16: |
| { |
| dbus_uint16_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("uint16 %u\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_INT32: |
| { |
| dbus_int32_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("int32 %d\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_UINT32: |
| { |
| dbus_uint32_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("uint32 %u\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_INT64: |
| { |
| dbus_int64_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| #ifdef DBUS_INT64_PRINTF_MODIFIER |
| printf ("int64 %" DBUS_INT64_PRINTF_MODIFIER "d\n", val); |
| #else |
| printf ("int64 (omitted)\n"); |
| #endif |
| break; |
| } |
| |
| case DBUS_TYPE_UINT64: |
| { |
| dbus_uint64_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| #ifdef DBUS_INT64_PRINTF_MODIFIER |
| printf ("uint64 %" DBUS_INT64_PRINTF_MODIFIER "u\n", val); |
| #else |
| printf ("uint64 (omitted)\n"); |
| #endif |
| break; |
| } |
| |
| case DBUS_TYPE_DOUBLE: |
| { |
| double val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("double %g\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_BYTE: |
| { |
| unsigned char val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("byte %d\n", val); |
| break; |
| } |
| |
| case DBUS_TYPE_BOOLEAN: |
| { |
| dbus_bool_t val; |
| dbus_message_iter_get_basic (iter, &val); |
| printf ("boolean %s\n", val ? "true" : "false"); |
| break; |
| } |
| |
| case DBUS_TYPE_VARIANT: |
| { |
| DBusMessageIter subiter; |
| |
| dbus_message_iter_recurse (iter, &subiter); |
| |
| printf ("variant "); |
| print_iter (&subiter, literal, depth+1); |
| break; |
| } |
| case DBUS_TYPE_ARRAY: |
| { |
| int current_type; |
| DBusMessageIter subiter; |
| |
| dbus_message_iter_recurse (iter, &subiter); |
| |
| current_type = dbus_message_iter_get_arg_type (&subiter); |
| |
| if (current_type == DBUS_TYPE_BYTE) |
| { |
| print_ay (&subiter, depth); |
| break; |
| } |
| |
| printf("array [\n"); |
| while (current_type != DBUS_TYPE_INVALID) |
| { |
| print_iter (&subiter, literal, depth+1); |
| |
| dbus_message_iter_next (&subiter); |
| current_type = dbus_message_iter_get_arg_type (&subiter); |
| |
| if (current_type != DBUS_TYPE_INVALID) |
| printf (","); |
| } |
| indent(depth); |
| printf("]\n"); |
| break; |
| } |
| case DBUS_TYPE_DICT_ENTRY: |
| { |
| DBusMessageIter subiter; |
| |
| dbus_message_iter_recurse (iter, &subiter); |
| |
| printf("dict entry(\n"); |
| print_iter (&subiter, literal, depth+1); |
| dbus_message_iter_next (&subiter); |
| print_iter (&subiter, literal, depth+1); |
| indent(depth); |
| printf(")\n"); |
| break; |
| } |
| |
| case DBUS_TYPE_STRUCT: |
| { |
| int current_type; |
| DBusMessageIter subiter; |
| |
| dbus_message_iter_recurse (iter, &subiter); |
| |
| printf("struct {\n"); |
| while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) |
| { |
| print_iter (&subiter, literal, depth+1); |
| dbus_message_iter_next (&subiter); |
| if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID) |
| printf (","); |
| } |
| indent(depth); |
| printf("}\n"); |
| break; |
| } |
| |
| #ifdef DBUS_UNIX |
| case DBUS_TYPE_UNIX_FD: |
| { |
| int fd; |
| dbus_message_iter_get_basic (iter, &fd); |
| |
| print_fd (fd, depth+1); |
| |
| /* dbus_message_iter_get_basic() duplicated the fd, we need to |
| * close it after use. The original fd will be closed when the |
| * DBusMessage is released. |
| */ |
| close (fd); |
| |
| break; |
| } |
| #endif |
| |
| default: |
| printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type); |
| break; |
| } |
| } while (dbus_message_iter_next (iter)); |
| } |
| |
| void |
| print_message (DBusMessage *message, dbus_bool_t literal, long sec, long usec) |
| { |
| DBusMessageIter iter; |
| const char *sender; |
| const char *destination; |
| int message_type; |
| |
| message_type = dbus_message_get_type (message); |
| sender = dbus_message_get_sender (message); |
| destination = dbus_message_get_destination (message); |
| |
| if (!literal) |
| { |
| if (sec != 0 || usec != 0) |
| { |
| printf ("%s time=%ld.%06ld sender=%s -> destination=%s", |
| type_to_name (message_type), sec, usec, |
| sender ? sender : "(null sender)", |
| destination ? destination : "(null destination)"); |
| } |
| else |
| { |
| printf ("%s sender=%s -> destination=%s", |
| type_to_name (message_type), |
| sender ? sender : "(null sender)", |
| destination ? destination : "(null destination)"); |
| } |
| |
| switch (message_type) |
| { |
| case DBUS_MESSAGE_TYPE_METHOD_CALL: |
| case DBUS_MESSAGE_TYPE_SIGNAL: |
| printf (" serial=%u path=%s; interface=%s; member=%s\n", |
| dbus_message_get_serial (message), |
| dbus_message_get_path (message), |
| dbus_message_get_interface (message), |
| dbus_message_get_member (message)); |
| break; |
| |
| case DBUS_MESSAGE_TYPE_METHOD_RETURN: |
| printf (" serial=%u reply_serial=%u\n", |
| dbus_message_get_serial (message), |
| dbus_message_get_reply_serial (message)); |
| break; |
| |
| case DBUS_MESSAGE_TYPE_ERROR: |
| printf (" error_name=%s reply_serial=%u\n", |
| dbus_message_get_error_name (message), |
| dbus_message_get_reply_serial (message)); |
| break; |
| |
| default: |
| printf ("\n"); |
| break; |
| } |
| } |
| |
| dbus_message_iter_init (message, &iter); |
| print_iter (&iter, literal, 1); |
| fflush (stdout); |
| |
| } |
| |