/** * @ingroup DBusListInternals * Unit test for DBusList * @returns #TRUE on success. */ dbus_bool_t _dbus_list_test (void) { DBusList *list1; DBusList *list2; DBusList *link1; DBusList *link2; DBusList *copy1; DBusList *copy2; int i; list1 = NULL; list2 = NULL; /* Test append and prepend */ i = 0; while (i < 10) { if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("could not allocate for append"); if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("count not allocate for prepend"); ++i; verify_list (&list1); verify_list (&list2); _dbus_assert (_dbus_list_get_length (&list1) == i); _dbus_assert (_dbus_list_get_length (&list2) == i); } _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); /* Test list clear */ _dbus_list_clear (&list1); _dbus_list_clear (&list2); verify_list (&list1); verify_list (&list2); /* Test get_first, get_last, pop_first, pop_last */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { void *got_data1; void *got_data2; void *data1; void *data2; got_data1 = _dbus_list_get_last (&list1); got_data2 = _dbus_list_get_first (&list2); data1 = _dbus_list_pop_last (&list1); data2 = _dbus_list_pop_first (&list2); _dbus_assert (got_data1 == data1); _dbus_assert (got_data2 == data2); _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i); _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i); verify_list (&list1); verify_list (&list2); _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; } _dbus_assert (list1 == NULL); _dbus_assert (list2 == NULL); /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { DBusList *got_link1; DBusList *got_link2; DBusList *link1; DBusList *link2; void *data1; void *data2; got_link1 = _dbus_list_get_last_link (&list1); got_link2 = _dbus_list_get_first_link (&list2); link1 = _dbus_list_pop_last_link (&list1); link2 = _dbus_list_pop_first_link (&list2); _dbus_assert (got_link1 == link1); _dbus_assert (got_link2 == link2); data1 = link1->data; data2 = link2->data; _dbus_list_free_link (link1); _dbus_list_free_link (link2); _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i); _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i); verify_list (&list1); verify_list (&list2); _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; } _dbus_assert (list1 == NULL); _dbus_assert (list2 == NULL); /* Test iteration */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; verify_list (&list1); verify_list (&list2); _dbus_assert (_dbus_list_get_length (&list1) == i); _dbus_assert (_dbus_list_get_length (&list2) == i); } _dbus_assert (is_ascending_sequence (&list1)); _dbus_assert (is_descending_sequence (&list2)); --i; link2 = _dbus_list_get_first_link (&list2); while (link2 != NULL) { verify_list (&link2); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i); link2 = _dbus_list_get_next_link (&list2, link2); --i; } i = 0; link1 = _dbus_list_get_first_link (&list1); while (link1 != NULL) { verify_list (&link1); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); link1 = _dbus_list_get_next_link (&list1, link1); ++i; } --i; link1 = _dbus_list_get_last_link (&list1); while (link1 != NULL) { verify_list (&link1); /* pretend this link is the head */ _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); link1 = _dbus_list_get_prev_link (&list1, link1); --i; } _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* Test remove */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { if ((i % 2) == 0) { if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); verify_list (&list1); verify_list (&list2); } --i; } _dbus_assert (all_odd_values (&list1)); _dbus_assert (all_odd_values (&list2)); _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* test removing the other half of the elements */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; while (i >= 0) { if ((i % 2) != 0) { if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i))) _dbus_assert_not_reached ("element should have been in list"); verify_list (&list1); verify_list (&list2); } --i; } _dbus_assert (all_even_values (&list1)); _dbus_assert (all_even_values (&list2)); /* clear list using remove_link */ while (list1 != NULL) { _dbus_list_remove_link (&list1, list1); verify_list (&list1); } while (list2 != NULL) { _dbus_list_remove_link (&list2, list2); verify_list (&list2); } /* Test remove link more generally */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } --i; link2 = _dbus_list_get_first_link (&list2); while (link2 != NULL) { DBusList *next = _dbus_list_get_next_link (&list2, link2); _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i); if ((i % 2) == 0) _dbus_list_remove_link (&list2, link2); verify_list (&list2); link2 = next; --i; } _dbus_assert (all_odd_values (&list2)); _dbus_list_clear (&list2); i = 0; link1 = _dbus_list_get_first_link (&list1); while (link1 != NULL) { DBusList *next = _dbus_list_get_next_link (&list1, link1); _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i); if ((i % 2) != 0) _dbus_list_remove_link (&list1, link1); verify_list (&list1); link1 = next; ++i; } _dbus_assert (all_even_values (&list1)); _dbus_list_clear (&list1); /* Test copying a list */ i = 0; while (i < 10) { _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)); _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)); ++i; } /* bad pointers, because they are allowed in the copy dest */ copy1 = _DBUS_INT_TO_POINTER (0x342234); copy2 = _DBUS_INT_TO_POINTER (23); _dbus_list_copy (&list1, ©1); verify_list (&list1); verify_list (©1); _dbus_assert (lists_equal (&list1, ©1)); _dbus_list_copy (&list2, ©2); verify_list (&list2); verify_list (©2); _dbus_assert (lists_equal (&list2, ©2)); /* Now test copying empty lists */ _dbus_list_clear (&list1); _dbus_list_clear (&list2); _dbus_list_clear (©1); _dbus_list_clear (©2); /* bad pointers, because they are allowed in the copy dest */ copy1 = _DBUS_INT_TO_POINTER (0x342234); copy2 = _DBUS_INT_TO_POINTER (23); _dbus_list_copy (&list1, ©1); verify_list (&list1); verify_list (©1); _dbus_assert (lists_equal (&list1, ©1)); _dbus_list_copy (&list2, ©2); verify_list (&list2); verify_list (©2); _dbus_assert (lists_equal (&list2, ©2)); _dbus_list_clear (&list1); _dbus_list_clear (&list2); /* insert_before on empty list */ _dbus_list_insert_before (&list1, NULL, _DBUS_INT_TO_POINTER (0)); verify_list (&list1); /* inserting before first element */ _dbus_list_insert_before (&list1, list1, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); /* inserting in the middle */ _dbus_list_insert_before (&list1, list1->next, _DBUS_INT_TO_POINTER (1)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); /* using insert_before to append */ _dbus_list_insert_before (&list1, NULL, _DBUS_INT_TO_POINTER (-1)); verify_list (&list1); _dbus_assert (is_descending_sequence (&list1)); _dbus_list_clear (&list1); /* insert_after on empty list */ _dbus_list_insert_after (&list1, NULL, _DBUS_INT_TO_POINTER (0)); verify_list (&list1); /* inserting after first element */ _dbus_list_insert_after (&list1, list1, _DBUS_INT_TO_POINTER (1)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); /* inserting at the end */ _dbus_list_insert_after (&list1, list1->next, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); /* using insert_after to prepend */ _dbus_list_insert_after (&list1, NULL, _DBUS_INT_TO_POINTER (-1)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); _dbus_list_clear (&list1); /* using remove_last */ _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2)); _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1)); _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3)); _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2)); verify_list (&list1); _dbus_assert (is_ascending_sequence (&list1)); _dbus_list_clear (&list1); return TRUE; }
dbus_bool_t _dbus_data_slot_test (void) { DBusDataSlotAllocator allocator; DBusDataSlotList list; int i; DBusFreeFunction old_free_func; void *old_data; DBusMutex *mutex; if (!_dbus_data_slot_allocator_init (&allocator)) _dbus_assert_not_reached ("no memory for allocator"); _dbus_data_slot_list_init (&list); _dbus_mutex_new_at_location (&mutex); if (mutex == NULL) _dbus_assert_not_reached ("failed to alloc mutex"); #define N_SLOTS 100 i = 0; while (i < N_SLOTS) { /* we don't really want apps to rely on this ordered * allocation, but it simplifies things to rely on it * here. */ dbus_int32_t tmp = -1; _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp); if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); ++i; } i = 0; while (i < N_SLOTS) { if (!_dbus_data_slot_list_set (&allocator, &list, i, _DBUS_INT_TO_POINTER (i), test_free_slot_data_func, &old_free_func, &old_data)) _dbus_assert_not_reached ("no memory to set data"); _dbus_assert (old_free_func == NULL); _dbus_assert (old_data == NULL); _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) == _DBUS_INT_TO_POINTER (i)); ++i; } free_counter = 0; i = 0; while (i < N_SLOTS) { if (!_dbus_data_slot_list_set (&allocator, &list, i, _DBUS_INT_TO_POINTER (i), test_free_slot_data_func, &old_free_func, &old_data)) _dbus_assert_not_reached ("no memory to set data"); _dbus_assert (old_free_func == test_free_slot_data_func); _dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i); (* old_free_func) (old_data); _dbus_assert (i == (free_counter - 1)); _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) == _DBUS_INT_TO_POINTER (i)); ++i; } free_counter = 0; _dbus_data_slot_list_free (&list); _dbus_assert (N_SLOTS == free_counter); i = 0; while (i < N_SLOTS) { dbus_int32_t tmp = i; _dbus_data_slot_allocator_free (&allocator, &tmp); _dbus_assert (tmp == -1); ++i; } _dbus_mutex_free_at_location (&mutex); return TRUE; }
/** * Verifies that the range of type_str from type_pos to type_end is a * valid signature. If this function returns #TRUE, it will be safe * to iterate over the signature with a types-only #DBusTypeReader. * The range passed in should NOT include the terminating * nul/DBUS_TYPE_INVALID. * * @param type_str the string * @param type_pos where the typecodes start * @param len length of typecodes * @returns #DBUS_VALID if valid, reason why invalid otherwise */ DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str, int type_pos, int len) { const unsigned char *p; const unsigned char *end; int last; int struct_depth; int array_depth; int dict_entry_depth; DBusValidity result; int element_count; DBusList *element_count_stack; result = DBUS_VALID; element_count_stack = NULL; if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) { result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; goto out; } _dbus_assert (type_str != NULL); _dbus_assert (type_pos < _DBUS_INT32_MAX - len); _dbus_assert (len >= 0); _dbus_assert (type_pos >= 0); if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) { result = DBUS_INVALID_SIGNATURE_TOO_LONG; goto out; } p = _dbus_string_get_const_data_len (type_str, type_pos, 0); end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); struct_depth = 0; array_depth = 0; dict_entry_depth = 0; last = DBUS_TYPE_INVALID; while (p != end) { switch (*p) { case DBUS_TYPE_BYTE: case DBUS_TYPE_BOOLEAN: case DBUS_TYPE_INT16: case DBUS_TYPE_UINT16: case DBUS_TYPE_INT32: case DBUS_TYPE_UINT32: case DBUS_TYPE_INT64: case DBUS_TYPE_UINT64: case DBUS_TYPE_DOUBLE: case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_SIGNATURE: case DBUS_TYPE_VARIANT: break; case DBUS_TYPE_ARRAY: array_depth += 1; if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) { result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; goto out; } break; case DBUS_STRUCT_BEGIN_CHAR: struct_depth += 1; if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) { result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; goto out; } if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) { result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; goto out; } break; case DBUS_STRUCT_END_CHAR: if (struct_depth == 0) { result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; goto out; } if (last == DBUS_STRUCT_BEGIN_CHAR) { result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; goto out; } _dbus_list_pop_last (&element_count_stack); struct_depth -= 1; break; case DBUS_DICT_ENTRY_BEGIN_CHAR: if (last != DBUS_TYPE_ARRAY) { result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; goto out; } dict_entry_depth += 1; if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) { result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; goto out; } if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) { result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; goto out; } break; case DBUS_DICT_ENTRY_END_CHAR: if (dict_entry_depth == 0) { result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; goto out; } dict_entry_depth -= 1; element_count = _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); if (element_count != 2) { if (element_count == 0) result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; else if (element_count == 1) result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD; else result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS; goto out; } break; case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ case DBUS_TYPE_DICT_ENTRY: /* ditto */ default: result = DBUS_INVALID_UNKNOWN_TYPECODE; goto out; } if (*p != DBUS_TYPE_ARRAY && *p != DBUS_DICT_ENTRY_BEGIN_CHAR && *p != DBUS_STRUCT_BEGIN_CHAR) { element_count = _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); ++element_count; if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (element_count))) { result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; goto out; } } if (array_depth > 0) { if (*p == DBUS_TYPE_ARRAY && p != end) { const char *p1; p1 = p + 1; if (*p1 == DBUS_STRUCT_END_CHAR || *p1 == DBUS_DICT_ENTRY_END_CHAR) { result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; goto out; } } else { array_depth = 0; } } if (last == DBUS_DICT_ENTRY_BEGIN_CHAR && !dbus_type_is_basic (*p)) { result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; goto out; } last = *p; ++p; } if (array_depth > 0) { result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; goto out; } if (struct_depth > 0) { result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; goto out; } if (dict_entry_depth > 0) { result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; goto out; } _dbus_assert (last != DBUS_TYPE_ARRAY); _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); result = DBUS_VALID; out: _dbus_list_clear (&element_count_stack); return result; }
int main (int argc, char *argv[]) { DBusConnection *connection; DBusError error; DBusBusType type = DBUS_BUS_SESSION; DBusHandleMessageFunction filter_func = monitor_filter_func; char *address = NULL; dbus_bool_t seen_bus_type = FALSE; BinaryMode binary_mode = BINARY_MODE_NOT; int i = 0, j = 0, numFilters = 0; char **filters = NULL; /* Set stdout to be unbuffered; this is basically so that if people * do dbus-monitor > file, then send SIGINT via Control-C, they * don't lose the last chunk of messages. */ #ifdef DBUS_WIN setvbuf (stdout, NULL, _IONBF, 0); #else setvbuf (stdout, NULL, _IOLBF, 0); #endif for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--system")) { only_one_type (&seen_bus_type, argv[0]); type = DBUS_BUS_SYSTEM; } else if (!strcmp (arg, "--session")) { only_one_type (&seen_bus_type, argv[0]); type = DBUS_BUS_SESSION; } else if (!strcmp (arg, "--address")) { only_one_type (&seen_bus_type, argv[0]); if (i+1 < argc) { address = argv[i+1]; i++; } else usage (argv[0], 1); } else if (!strcmp (arg, "--help")) usage (argv[0], 0); else if (!strcmp (arg, "--monitor")) { filter_func = monitor_filter_func; binary_mode = BINARY_MODE_NOT; } else if (!strcmp (arg, "--profile")) { filter_func = profile_filter_func; binary_mode = BINARY_MODE_NOT; } else if (!strcmp (arg, "--binary")) { filter_func = binary_filter_func; binary_mode = BINARY_MODE_RAW; } else if (!strcmp (arg, "--pcap")) { filter_func = binary_filter_func; binary_mode = BINARY_MODE_PCAP; } else if (!strcmp (arg, "--")) continue; else if (arg[0] == '-') usage (argv[0], 1); else { unsigned int filter_len; numFilters++; /* Prepend a rule (and a comma) to enable the monitor to eavesdrop. * Prepending allows the user to add eavesdrop=false at command line * in order to disable eavesdropping when needed */ filter_len = strlen (EAVESDROPPING_RULE) + 1 + strlen (arg) + 1; filters = (char **) realloc (filters, numFilters * sizeof (char *)); if (filters == NULL) tool_oom ("adding a new filter slot"); filters[j] = (char *) malloc (filter_len); if (filters[j] == NULL) tool_oom ("adding a new filter"); snprintf (filters[j], filter_len, "%s,%s", EAVESDROPPING_RULE, arg); j++; } } dbus_error_init (&error); if (address != NULL) { connection = dbus_connection_open (address, &error); if (connection) { if (!dbus_bus_register (connection, &error)) { fprintf (stderr, "Failed to register connection to bus at %s: %s\n", address, error.message); dbus_error_free (&error); exit (1); } } } else connection = dbus_bus_get (type, &error); if (connection == NULL) { const char *where; if (address != NULL) where = address; else { switch (type) { case DBUS_BUS_SYSTEM: where = "system bus"; break; case DBUS_BUS_SESSION: where = "session bus"; break; default: where = ""; } } fprintf (stderr, "Failed to open connection to %s: %s\n", where, error.message); dbus_error_free (&error); exit (1); } /* Receive o.fd.Peer messages as normal messages, rather than having * libdbus handle them internally, which is the wrong thing for * a monitor */ dbus_connection_set_route_peer_messages (connection, TRUE); if (!dbus_connection_add_filter (connection, filter_func, _DBUS_INT_TO_POINTER (binary_mode), NULL)) { fprintf (stderr, "Couldn't add filter!\n"); exit (1); } if (become_monitor (connection, numFilters, (const char * const *) filters)) { /* no more preparation needed */ } else if (numFilters) { size_t offset = 0; for (i = 0; i < j; i++) { dbus_bus_add_match (connection, filters[i] + offset, &error); if (dbus_error_is_set (&error) && i == 0 && offset == 0) { /* We might be talking to a pre-1.5.6 dbus-daemon * which wouldn't understand eavesdrop=true. * If this works, carry on with offset > 0 * on the remaining iterations. */ offset = strlen (EAVESDROPPING_RULE) + 1; dbus_error_free (&error); dbus_bus_add_match (connection, filters[i] + offset, &error); } if (dbus_error_is_set (&error)) { fprintf (stderr, "Failed to setup match \"%s\": %s\n", filters[i], error.message); dbus_error_free (&error); exit (1); } free(filters[i]); } } else { dbus_bus_add_match (connection, EAVESDROPPING_RULE, &error); if (dbus_error_is_set (&error)) { dbus_error_free (&error); dbus_bus_add_match (connection, "", &error); if (dbus_error_is_set (&error)) goto lose; } } switch (binary_mode) { case BINARY_MODE_NOT: case BINARY_MODE_RAW: break; case BINARY_MODE_PCAP: { /* We're not using libpcap because the file format is simple * enough not to need it. * http://wiki.wireshark.org/Development/LibpcapFileFormat */ struct { dbus_uint32_t magic; dbus_uint16_t major_version; dbus_uint16_t minor_version; dbus_int32_t timezone; dbus_uint32_t precision; dbus_uint32_t max_length; dbus_uint32_t link_type; } header = { 0xA1B2C3D4U, /* magic number */ 2, 4, /* v2.4 */ 0, /* capture in GMT */ 0, /* no opinion on timestamp precision */ (1 << 27), /* D-Bus spec says so */ LINKTYPE_DBUS }; /* Assert that there is no padding */ _DBUS_STATIC_ASSERT (sizeof (header) == 24); if (!tool_write_all (STDOUT_FILENO, &header, sizeof (header))) { perror ("dbus-monitor: write"); exit (1); } } break; } while (dbus_connection_read_write_dispatch(connection, -1)) ; exit (0); lose: fprintf (stderr, "Error: %s\n", error.message); exit (1); }