From 41f52c96d651003b3d0a266a582d401228a8368e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 30 Jan 2005 05:18:44 +0000 Subject: 2005-01-30 Havoc Pennington dbus-viewer introspected and displayed the bus driver * dbus/dbus-object-tree.c (object_tree_test_iteration): add tests for a handler registered on "/" * dbus/dbus-object-tree.c (_dbus_decompose_path): fix to handle path "/" properly (run_decompose_tests): add tests for path decomposition * glib/dbus-gutils.c (_dbus_gutils_split_path): fix to handle "/" properly * glib/dbus-gobject.c (handle_introspect): fix quotes * test/glib/run-test.sh: support launching the bus, then running dbus-viewer * test/glib/test-service-glib.c (main): put in a trivial gobject subclass and register it on the connection * bus/driver.c (bus_driver_handle_introspect): implement introspection of the bus driver service * dbus/dbus-protocol.h: add #defines for the XML namespace, identifiers, doctype decl * bus/driver.c (bus_driver_handle_get_service_owner): handle attempts to get owner of DBUS_SERVICE_ORG_FREEDESKTOP_DBUS by returning the service unchanged. (bus_driver_handle_message): remove old check for reply_serial in method calls, now the message type deals with that (bus_driver_handle_message): handle NULL interface * glib/dbus-gproxy.c (dbus_g_proxy_get_bus_name): new function * glib/dbus-gloader-expat.c (description_load_from_string): allow -1 for len * tools/dbus-viewer.c: add support for introspecting a service on a bus * glib/dbus-gproxy.c (dbus_g_pending_call_ref): add (dbus_g_pending_call_unref): add --- ChangeLog | 48 +++++++- bus/driver.c | 134 +++++++++++++++++---- dbus/dbus-glib.h | 3 + dbus/dbus-marshal-validate.c | 2 +- dbus/dbus-object-tree.c | 266 ++++++++++++++++++++++++++++++++---------- dbus/dbus-protocol.h | 6 + glib/dbus-gidl.c | 14 +++ glib/dbus-gidl.h | 3 + glib/dbus-gloader-expat.c | 4 + glib/dbus-gobject.c | 16 +-- glib/dbus-gproxy.c | 62 ++++++++-- glib/dbus-gutils.c | 20 ++-- test/glib/run-test.sh | 9 ++ test/glib/test-service-glib.c | 46 ++++++++ tools/dbus-viewer.c | 145 +++++++++++++++++++++-- 15 files changed, 666 insertions(+), 112 deletions(-) diff --git a/ChangeLog b/ChangeLog index d964d45a..dcb3a6de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2005-01-30 Havoc Pennington + + dbus-viewer introspected and displayed the bus driver + + * dbus/dbus-object-tree.c + (object_tree_test_iteration): add tests for a handler registered on "/" + + * dbus/dbus-object-tree.c + (_dbus_decompose_path): fix to handle path "/" properly + (run_decompose_tests): add tests for path decomposition + + * glib/dbus-gutils.c (_dbus_gutils_split_path): fix to handle "/" + properly + + * glib/dbus-gobject.c (handle_introspect): fix quotes + + * test/glib/run-test.sh: support launching the bus, then running + dbus-viewer + + * test/glib/test-service-glib.c (main): put in a trivial gobject + subclass and register it on the connection + + * bus/driver.c (bus_driver_handle_introspect): implement + introspection of the bus driver service + + * dbus/dbus-protocol.h: add #defines for the XML namespace, + identifiers, doctype decl + + * bus/driver.c (bus_driver_handle_get_service_owner): handle + attempts to get owner of DBUS_SERVICE_ORG_FREEDESKTOP_DBUS by + returning the service unchanged. + (bus_driver_handle_message): remove old check for reply_serial in + method calls, now the message type deals with that + (bus_driver_handle_message): handle NULL interface + + * glib/dbus-gproxy.c (dbus_g_proxy_get_bus_name): new function + + * glib/dbus-gloader-expat.c (description_load_from_string): allow + -1 for len + + * tools/dbus-viewer.c: add support for introspecting a service on + a bus + + * glib/dbus-gproxy.c (dbus_g_pending_call_ref): add + (dbus_g_pending_call_unref): add + 2005-01-29 Havoc Pennington * tools/dbus-tree-view.c: add support for displaying properties. @@ -6,7 +52,7 @@ * glib/dbus-gobject.c (handle_introspect): return org.freedesktop.Properties and org.freedesktop.Introspectable - interfaces when we are introspected. + interfaces when we are introspected. * doc/dbus-specification.xml: allow empty interface name when Get/Set a property diff --git a/bus/driver.c b/bus/driver.c index 3a9e555d..58b8fcbf 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -792,24 +792,34 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, _dbus_string_init_const (&str, text); service = bus_registry_lookup (registry, &str); - if (service == NULL) + if (service == NULL && + _dbus_string_equal_c_str (&str, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS)) + { + /* ORG_FREEDESKTOP_DBUS owns itself */ + base_name = DBUS_SERVICE_ORG_FREEDESKTOP_DBUS; + } + else if (service == NULL) { dbus_set_error (error, - DBUS_ERROR_NAME_HAS_NO_OWNER, - "Could not get owner of name '%s': no such name", text); + DBUS_ERROR_NAME_HAS_NO_OWNER, + "Could not get owner of name '%s': no such name", text); goto failed; } - - base_name = bus_connection_get_name (bus_service_get_primary_owner (service)); - if (base_name == NULL) + else { - /* FIXME - how is this error possible? */ - dbus_set_error (error, - DBUS_ERROR_FAILED, - "Could not determine unique name for '%s'", text); - goto failed; + base_name = bus_connection_get_name (bus_service_get_primary_owner (service)); + if (base_name == NULL) + { + /* FIXME - how is this error possible? */ + dbus_set_error (error, + DBUS_ERROR_FAILED, + "Could not determine unique name for '%s'", text); + goto failed; + } + _dbus_assert (*base_name == ':'); } - _dbus_assert (*base_name == ':'); + + _dbus_assert (base_name != NULL); reply = dbus_message_new_method_return (message); if (reply == NULL) @@ -1040,13 +1050,89 @@ struct { "ReloadConfig", bus_driver_handle_reload_config } }; +static dbus_bool_t +bus_driver_handle_introspect (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) +{ + DBusString xml; + DBusMessage *reply; + const char *v_STRING; + + _dbus_verbose ("Introspect() on bus driver\n"); + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + reply = NULL; + + if (! dbus_message_get_args (message, error, + DBUS_TYPE_INVALID)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return FALSE; + } + + if (!_dbus_string_init (&xml)) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE)) + goto oom; + if (!_dbus_string_append (&xml, "\n")) + goto oom; + if (!_dbus_string_append (&xml, " \n")) + goto oom; + if (!_dbus_string_append (&xml, " \n")) + goto oom; + if (!_dbus_string_append (&xml, " \n")) + goto oom; + if (!_dbus_string_append (&xml, " \n")) + goto oom; + if (!_dbus_string_append (&xml, " \n")) + goto oom; + + if (!_dbus_string_append (&xml, "\n")) + goto oom; + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto oom; + + v_STRING = _dbus_string_get_const_data (&xml); + if (! dbus_message_append_args (reply, + DBUS_TYPE_STRING, &v_STRING, + DBUS_TYPE_INVALID)) + goto oom; + + if (! bus_transaction_send_from_driver (transaction, connection, reply)) + goto oom; + + dbus_message_unref (reply); + _dbus_string_free (&xml); + + return TRUE; + + oom: + BUS_SET_OOM (error); + + if (reply) + dbus_message_unref (reply); + + _dbus_string_free (&xml); + + return FALSE; +} + dbus_bool_t bus_driver_handle_message (DBusConnection *connection, BusTransaction *transaction, DBusMessage *message, DBusError *error) { - const char *name, *sender; + const char *name, *sender, *interface; int i; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -1057,17 +1143,25 @@ bus_driver_handle_message (DBusConnection *connection, return TRUE; /* we just ignore this */ } - _dbus_assert (dbus_message_get_interface (message) != NULL); + if (dbus_message_is_method_call (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, + "Introspect")) + return bus_driver_handle_introspect (connection, transaction, message, error); + + interface = dbus_message_get_interface (message); + if (interface == NULL) + interface = DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS; + _dbus_assert (dbus_message_get_member (message) != NULL); - + name = dbus_message_get_member (message); sender = dbus_message_get_sender (message); - if (strcmp (dbus_message_get_interface (message), + if (strcmp (interface, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0) { _dbus_verbose ("Driver got message to unknown interface \"%s\"\n", - dbus_message_get_interface (message)); + interface); goto unknown; } @@ -1076,12 +1170,6 @@ bus_driver_handle_message (DBusConnection *connection, /* security checks should have kept this from getting here */ _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0); - - if (dbus_message_get_reply_serial (message) != 0) - { - _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n"); - return TRUE; - } i = 0; while (i < _DBUS_N_ELEMENTS (message_handlers)) diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h index de53d14a..3e73b98f 100644 --- a/dbus/dbus-glib.h +++ b/dbus/dbus-glib.h @@ -145,7 +145,10 @@ void dbus_g_proxy_call_no_reply (DBusGProxy *proxy, const char *method, int first_arg_type, ...); +const char* dbus_g_proxy_get_bus_name (DBusGProxy *proxy); +DBusGPendingCall* dbus_g_pending_call_ref (DBusGPendingCall *call); +void dbus_g_pending_call_unref (DBusGPendingCall *call); #undef DBUS_INSIDE_DBUS_GLIB_H diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index e57be5c7..d9b85cb7 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -573,7 +573,7 @@ _dbus_validate_path (const DBusString *str, _dbus_assert (start >= 0); _dbus_assert (len >= 0); _dbus_assert (start <= _dbus_string_get_length (str)); - + if (len > _dbus_string_get_length (str) - start) return FALSE; diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c index 694185fb..f8797595 100644 --- a/dbus/dbus-object-tree.c +++ b/dbus/dbus-object-tree.c @@ -630,6 +630,9 @@ handle_default_introspect_unlocked (DBusObjectTree *tree, if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children)) goto out; + if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE)) + goto out; + if (!_dbus_string_append (&xml, "\n")) goto out; @@ -945,6 +948,7 @@ _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree, /** * Decompose an object path. A path of just "/" is * represented as an empty vector of strings. + * The path need not be nul terminated. * * @param data the path data * @param len the length of the path string @@ -962,19 +966,22 @@ _dbus_decompose_path (const char* data, int i, j, comp; _dbus_assert (data != NULL); - + #if VERBOSE_DECOMPOSE _dbus_verbose ("Decomposing path \"%s\"\n", data); #endif n_components = 0; - i = 0; - while (i < len) + if (len > 1) /* if path is not just "/" */ { - if (data[i] == '/') - n_components += 1; - ++i; + i = 0; + while (i < len) + { + if (data[i] == '/') + n_components += 1; + ++i; + } } retval = dbus_new0 (char*, n_components + 1); @@ -983,9 +990,14 @@ _dbus_decompose_path (const char* data, return FALSE; comp = 0; - i = 0; - while (i < len) + if (n_components == 0) + i = 1; + else + i = 0; + while (comp < n_components) { + _dbus_assert (i < len); + if (data[i] == '/') ++i; j = i; @@ -1037,22 +1049,31 @@ static char* flatten_path (const char **path) { DBusString str; - int i; char *s; if (!_dbus_string_init (&str)) return NULL; - i = 0; - while (path[i]) + if (path[0] == NULL) { if (!_dbus_string_append_byte (&str, '/')) goto nomem; - - if (!_dbus_string_append (&str, path[i])) - goto nomem; - - ++i; + } + else + { + int i; + + i = 0; + while (path[i]) + { + if (!_dbus_string_append_byte (&str, '/')) + goto nomem; + + if (!_dbus_string_append (&str, path[i])) + goto nomem; + + ++i; + } } if (!_dbus_string_steal_data (&str, &s)) @@ -1191,7 +1212,7 @@ do_register (DBusObjectTree *tree, { DBusObjectPathVTable vtable = { test_unregister_function, test_message_function, NULL }; - + tree_test_data[i].message_handled = FALSE; tree_test_data[i].handler_unregistered = FALSE; tree_test_data[i].handler_fallback = fallback; @@ -1278,17 +1299,82 @@ do_test_dispatch (DBusObjectTree *tree, } static size_t -string_array_length (char **array) +string_array_length (const char **array) { size_t i; for (i = 0; array[i]; i++) ; return i; } +typedef struct +{ + const char *path; + const char *result[20]; +} DecomposePathTest; + +static DecomposePathTest decompose_tests[] = { + { "/foo", { "foo", NULL } }, + { "/foo/bar", { "foo", "bar", NULL } }, + { "/", { NULL } }, + { "/a/b", { "a", "b", NULL } }, + { "/a/b/c", { "a", "b", "c", NULL } }, + { "/a/b/c/d", { "a", "b", "c", "d", NULL } }, + { "/foo/bar/q", { "foo", "bar", "q", NULL } }, + { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } } +}; + +static dbus_bool_t +run_decompose_tests (void) +{ + int i; + + i = 0; + while (i < _DBUS_N_ELEMENTS (decompose_tests)) + { + char **result; + int result_len; + int expected_len; + + if (!_dbus_decompose_path (decompose_tests[i].path, + strlen (decompose_tests[i].path), + &result, &result_len)) + return FALSE; + + expected_len = string_array_length (decompose_tests[i].result); + + if (result_len != (int) string_array_length ((const char**)result) || + expected_len != result_len || + path_contains (decompose_tests[i].result, + (const char**) result) != STR_EQUAL) + { + int real_len = string_array_length ((const char**)result); + _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n", + decompose_tests[i].path, expected_len, result_len, + real_len); + _dbus_warn ("Decompose resulted in elements: { "); + i = 0; + while (i < real_len) + { + _dbus_warn ("\"%s\"%s", result[i], + (i + 1) == real_len ? "" : ", "); + ++i; + } + _dbus_warn ("}\n"); + _dbus_assert_not_reached ("path decompose failed\n"); + } + + dbus_free_string_array (result); + + ++i; + } + + return TRUE; +} static dbus_bool_t object_tree_test_iteration (void *data) { + const char *path0[] = { NULL }; const char *path1[] = { "foo", NULL }; const char *path2[] = { "foo", "bar", NULL }; const char *path3[] = { "foo", "bar", "baz", NULL }; @@ -1298,19 +1384,46 @@ object_tree_test_iteration (void *data) const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL }; const char *path8[] = { "childless", NULL }; DBusObjectTree *tree; - TreeTestData tree_test_data[8]; + TreeTestData tree_test_data[9]; int i; dbus_bool_t exact_match; + if (!run_decompose_tests ()) + return FALSE; + tree = NULL; tree = _dbus_object_tree_new (NULL); if (tree == NULL) goto out; - if (!do_register (tree, path1, TRUE, 0, tree_test_data)) + if (!do_register (tree, path0, TRUE, 0, tree_test_data)) + goto out; + + _dbus_assert (find_subtree (tree, path0, NULL)); + _dbus_assert (!find_subtree (tree, path1, NULL)); + _dbus_assert (!find_subtree (tree, path2, NULL)); + _dbus_assert (!find_subtree (tree, path3, NULL)); + _dbus_assert (!find_subtree (tree, path4, NULL)); + _dbus_assert (!find_subtree (tree, path5, NULL)); + _dbus_assert (!find_subtree (tree, path6, NULL)); + _dbus_assert (!find_subtree (tree, path7, NULL)); + _dbus_assert (!find_subtree (tree, path8, NULL)); + + _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match); + _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match); + _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); + + if (!do_register (tree, path1, TRUE, 1, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1320,6 +1433,7 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); + _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match); _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match); _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match); _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match); @@ -1329,7 +1443,7 @@ object_tree_test_iteration (void *data) _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match); _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); - if (!do_register (tree, path2, TRUE, 1, tree_test_data)) + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) goto out; _dbus_assert (find_subtree (tree, path1, NULL)); @@ -1341,9 +1455,10 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - if (!do_register (tree, path3, TRUE, 2, tree_test_data)) + if (!do_register (tree, path3, TRUE, 3, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1353,9 +1468,10 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - if (!do_register (tree, path4, TRUE, 3, tree_test_data)) + if (!do_register (tree, path4, TRUE, 4, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1365,9 +1481,10 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - if (!do_register (tree, path5, TRUE, 4, tree_test_data)) + if (!do_register (tree, path5, TRUE, 5, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1376,7 +1493,8 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path6, NULL)); _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - + + _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match); _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); @@ -1386,9 +1504,10 @@ object_tree_test_iteration (void *data) _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match); _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); - if (!do_register (tree, path6, TRUE, 5, tree_test_data)) + if (!do_register (tree, path6, TRUE, 6, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1398,9 +1517,10 @@ object_tree_test_iteration (void *data) _dbus_assert (!find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - if (!do_register (tree, path7, TRUE, 6, tree_test_data)) + if (!do_register (tree, path7, TRUE, 7, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1410,9 +1530,10 @@ object_tree_test_iteration (void *data) _dbus_assert (find_subtree (tree, path7, NULL)); _dbus_assert (!find_subtree (tree, path8, NULL)); - if (!do_register (tree, path8, TRUE, 7, tree_test_data)) + if (!do_register (tree, path8, TRUE, 8, tree_test_data)) goto out; + _dbus_assert (find_subtree (tree, path0, NULL)); _dbus_assert (find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1421,7 +1542,8 @@ object_tree_test_iteration (void *data) _dbus_assert (find_subtree (tree, path6, NULL)); _dbus_assert (find_subtree (tree, path7, NULL)); _dbus_assert (find_subtree (tree, path8, NULL)); - + + _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match); _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); @@ -1441,7 +1563,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries); if (child_entries != NULL) { - nb = string_array_length (child_entries); + nb = string_array_length ((const char**)child_entries); _dbus_assert (nb == 1); dbus_free_string_array (child_entries); } @@ -1449,7 +1571,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries); if (child_entries != NULL) { - nb = string_array_length (child_entries); + nb = string_array_length ((const char**)child_entries); _dbus_assert (nb == 2); dbus_free_string_array (child_entries); } @@ -1457,7 +1579,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries); if (child_entries != NULL) { - nb = string_array_length (child_entries); + nb = string_array_length ((const char**)child_entries); _dbus_assert (nb == 0); dbus_free_string_array (child_entries); } @@ -1465,7 +1587,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries); if (child_entries != NULL) { - nb = string_array_length (child_entries); + nb = string_array_length ((const char**)child_entries); _dbus_assert (nb == 3); dbus_free_string_array (child_entries); } @@ -1487,25 +1609,40 @@ object_tree_test_iteration (void *data) if (tree == NULL) goto out; - if (!do_register (tree, path1, TRUE, 0, tree_test_data)) + if (!do_register (tree, path0, TRUE, 0, tree_test_data)) + goto out; + if (!do_register (tree, path1, TRUE, 1, tree_test_data)) goto out; - if (!do_register (tree, path2, TRUE, 1, tree_test_data)) + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) goto out; - if (!do_register (tree, path3, TRUE, 2, tree_test_data)) + if (!do_register (tree, path3, TRUE, 3, tree_test_data)) goto out; - if (!do_register (tree, path4, TRUE, 3, tree_test_data)) + if (!do_register (tree, path4, TRUE, 4, tree_test_data)) goto out; - if (!do_register (tree, path5, TRUE, 4, tree_test_data)) + if (!do_register (tree, path5, TRUE, 5, tree_test_data)) goto out; - if (!do_register (tree, path6, TRUE, 5, tree_test_data)) + if (!do_register (tree, path6, TRUE, 6, tree_test_data)) goto out; - if (!do_register (tree, path7, TRUE, 6, tree_test_data)) + if (!do_register (tree, path7, TRUE, 7, tree_test_data)) goto out; - if (!do_register (tree, path8, TRUE, 7, tree_test_data)) + if (!do_register (tree, path8, TRUE, 8, tree_test_data)) goto out; + + _dbus_object_tree_unregister_and_unlock (tree, path0); + + _dbus_assert (!find_subtree (tree, path0, NULL)); + _dbus_assert (find_subtree (tree, path1, NULL)); + _dbus_assert (find_subtree (tree, path2, NULL)); + _dbus_assert (find_subtree (tree, path3, NULL)); + _dbus_assert (find_subtree (tree, path4, NULL)); + _dbus_assert (find_subtree (tree, path5, NULL)); + _dbus_assert (find_subtree (tree, path6, NULL)); + _dbus_assert (find_subtree (tree, path7, NULL)); + _dbus_assert (find_subtree (tree, path8, NULL)); _dbus_object_tree_unregister_and_unlock (tree, path1); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1517,6 +1654,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path2); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (find_subtree (tree, path3, NULL)); @@ -1528,6 +1666,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path3); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1539,6 +1678,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path4); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1550,6 +1690,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path5); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1561,6 +1702,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path6); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1572,6 +1714,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path7); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1583,6 +1726,7 @@ object_tree_test_iteration (void *data) _dbus_object_tree_unregister_and_unlock (tree, path8); + _dbus_assert (!find_subtree (tree, path0, NULL)); _dbus_assert (!find_subtree (tree, path1, NULL)); _dbus_assert (!find_subtree (tree, path2, NULL)); _dbus_assert (!find_subtree (tree, path3, NULL)); @@ -1601,43 +1745,47 @@ object_tree_test_iteration (void *data) } /* Register it all again, and test dispatch */ - - if (!do_register (tree, path1, FALSE, 0, tree_test_data)) + + if (!do_register (tree, path0, TRUE, 0, tree_test_data)) + goto out; + if (!do_register (tree, path1, FALSE, 1, tree_test_data)) goto out; - if (!do_register (tree, path2, TRUE, 1, tree_test_data)) + if (!do_register (tree, path2, TRUE, 2, tree_test_data)) goto out; - if (!do_register (tree, path3, TRUE, 2, tree_test_data)) + if (!do_register (tree, path3, TRUE, 3, tree_test_data)) goto out; - if (!do_register (tree, path4, TRUE, 3, tree_test_data)) + if (!do_register (tree, path4, TRUE, 4, tree_test_data)) goto out; - if (!do_register (tree, path5, TRUE, 4, tree_test_data)) + if (!do_register (tree, path5, TRUE, 5, tree_test_data)) goto out; - if (!do_register (tree, path6, FALSE, 5, tree_test_data)) + if (!do_register (tree, path6, FALSE, 6, tree_test_data)) goto out; - if (!do_register (tree, path7, TRUE, 6, tree_test_data)) + if (!do_register (tree, path7, TRUE, 7, tree_test_data)) goto out; - if (!do_register (tree, path8, TRUE, 7, tree_test_data)) + if (!do_register (tree, path8, TRUE, 8, tree_test_data)) goto out; #if 0 spew_tree (tree); #endif - - if (!do_test_dispatch (tree, path1, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + + if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + goto out; + if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path2, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path3, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path4, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path5, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path6, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path7, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; - if (!do_test_dispatch (tree, path8, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) + if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) goto out; out: diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index f72efb60..c662d721 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -272,6 +272,12 @@ extern "C" { #define DBUS_ERROR_SPAWN_FAILED "org.freedesktop.DBus.Error.Spawn.Failed" #define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" +#define DBUS_INTROSPECT_1_0_XML_NAMESPACE "http://www.freedesktop.org/standards/dbus" +#define DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +#define DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" +#define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "\n" + + #ifdef __cplusplus } #endif diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index cabc406b..8e0dc0da 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -303,6 +303,20 @@ node_info_add_node (NodeInfo *info, info->nodes = g_slist_append (info->nodes, node); } +void +node_info_replace_node (NodeInfo *info, + NodeInfo *old_child, + NodeInfo *new_child) +{ + GSList *link; + + node_info_ref (new_child); /* before unref old_child in case they are the same */ + link = g_slist_find (info->nodes, old_child); + g_assert (link != NULL); + node_info_unref (old_child); + link->data = new_child; +} + InterfaceInfo* interface_info_new (const char *name) { diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index fffbddfc..88d5c6e7 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -83,6 +83,9 @@ void node_info_add_interface (NodeInfo *info, InterfaceInfo *interface); void node_info_add_node (NodeInfo *info, NodeInfo *child); +void node_info_replace_node (NodeInfo *info, + NodeInfo *old_child, + NodeInfo *new_child); InterfaceInfo* interface_info_new (const char *name); InterfaceInfo* interface_info_ref (InterfaceInfo *info); void interface_info_unref (InterfaceInfo *info); diff --git a/glib/dbus-gloader-expat.c b/glib/dbus-gloader-expat.c index fa7e3692..609f3164 100644 --- a/glib/dbus-gloader-expat.c +++ b/glib/dbus-gloader-expat.c @@ -23,6 +23,7 @@ #include "dbus-gparser.h" #include +#include static void* expat_g_malloc (size_t sz) @@ -192,6 +193,9 @@ description_load_from_string (const char *str, g_return_val_if_fail (error == NULL || *error == NULL, NULL); + if (len < 0) + len = strlen (str); + expat = NULL; context.parser = NULL; context.error = error; diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index f08bf39e..245ebf1e 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -289,26 +289,28 @@ handle_introspect (DBusConnection *connection, xml = g_string_new (NULL); + g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); + g_string_append (xml, "\n"); /* We are introspectable, though I guess that was pretty obvious */ g_string_append (xml, " \n"); g_string_append (xml, " \n"); - g_string_append (xml, " \n"); + g_string_append (xml, " \n"); g_string_append (xml, " \n"); g_string_append (xml, " \n"); /* We support get/set properties */ g_string_append (xml, " \n"); g_string_append (xml, " \n"); - g_string_append (xml, " \n"); - g_string_append (xml, " \n"); - g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); g_string_append (xml, " \n"); g_string_append (xml, " \n"); - g_string_append (xml, " \n"); - g_string_append (xml, " \n"); - g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append (xml, " \n"); g_string_append (xml, " \n"); g_string_append (xml, " \n"); diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 624a95ca..39f8ba86 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -1032,11 +1032,30 @@ dbus_g_proxy_new_for_peer (DBusGConnection *connection, g_return_val_if_fail (interface_name != NULL, NULL); proxy = dbus_g_proxy_new (connection, NULL, - path_name, interface_name); + path_name, interface_name); return proxy; } +/** + * Gets the bus name a proxy is bound to (may be #NULL in some cases). + * If you created the proxy with dbus_g_proxy_new_for_name(), then + * the name you passed to that will be returned. + * If you created it with dbus_g_proxy_new_for_name_owner(), then the + * unique connection name will be returned. If you created it + * with dbus_g_proxy_new_for_peer() then #NULL will be returned. + * + * @param proxy the proxy + * @returns the bus name the proxy sends messages to + */ +const char* +dbus_g_proxy_get_bus_name (DBusGProxy *proxy) +{ + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); + + return proxy->name; +} + /** * Invokes a method on a remote interface. This function does not * block; instead it returns an opaque #DBusPendingCall object that @@ -1113,23 +1132,28 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy, * * Otherwise, the "out" parameters and return value of the * method are stored in the provided varargs list. - * The list should be terminated with DBUS_TYPE_INVALID. + * The list should be terminated with #DBUS_TYPE_INVALID. * * This function doesn't affect the reference count of the * #DBusPendingCall, the caller of dbus_g_proxy_begin_call() still owns * a reference. * + * @todo this should be changed to make a g_malloc() copy of the + * data returned probably; right now the data vanishes + * when you free the PendingCall which is sort of strange. + * * @param proxy a proxy for a remote interface * @param pending the pending call from dbus_g_proxy_begin_call() * @param error return location for an error * @param first_arg_type type of first "out" argument - * @returns #FALSE if an error is set */ + * @returns #FALSE if an error is set + */ gboolean dbus_g_proxy_end_call (DBusGProxy *proxy, - DBusGPendingCall *pending, - GError **error, - int first_arg_type, - ...) + DBusGPendingCall *pending, + GError **error, + int first_arg_type, + ...) { DBusMessage *message; va_list args; @@ -1222,6 +1246,30 @@ dbus_g_proxy_call_no_reply (DBusGProxy *proxy, g_error ("Out of memory"); } +/** + * Increments refcount on a pending call. + * + * @param call the call + * @returns the same call + */ +DBusGPendingCall* +dbus_g_pending_call_ref (DBusGPendingCall *call) +{ + dbus_pending_call_ref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call)); + return call; +} + +/** + * Decrements refcount on a pending call. + * + * @param call the call + */ +void +dbus_g_pending_call_unref (DBusGPendingCall *call) +{ + dbus_pending_call_unref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call)); +} + /** * Sends a message to the interface we're proxying for. Does not * block or wait for a reply. The message is only actually written out diff --git a/glib/dbus-gutils.c b/glib/dbus-gutils.c index ff48e7f1..cf12245c 100644 --- a/glib/dbus-gutils.c +++ b/glib/dbus-gutils.c @@ -39,19 +39,25 @@ _dbus_gutils_split_path (const char *path) len = strlen (path); n_components = 0; - i = 0; - while (i < len) + if (path[1] != '\0') /* if not "/" */ { - if (path[i] == '/') - n_components += 1; - ++i; + i = 0; + while (i < len) + { + if (path[i] == '/') + n_components += 1; + ++i; + } } split = g_new0 (char*, n_components + 1); comp = 0; - i = 0; - while (i < len) + if (n_components == 0) + i = 1; + else + i = 0; + while (comp < n_components) { if (path[i] == '/') ++i; diff --git a/test/glib/run-test.sh b/test/glib/run-test.sh index eddea5f8..0a5e3f65 100755 --- a/test/glib/run-test.sh +++ b/test/glib/run-test.sh @@ -57,12 +57,21 @@ echo "Started test bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" export DBUS_TEST_GLIB_RUN_TEST_SCRIPT=1 if test x$MODE = xprofile ; then + echo "profiling type $PROFILE_TYPE" sleep 2 ## this lets the bus get started so its startup time doesn't affect the profile too much if test x$PROFILE_TYPE = x ; then PROFILE_TYPE=all fi libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/glib/test-profile $PROFILE_TYPE || die "test-profile failed" +elif test x$MODE = xviewer ; then + echo "Launching dbus-viewer" + ARGS= + if test x$DEBUG = x ; then + ARGS="--services org.freedesktop.DBus" + fi + libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/tools/dbus-viewer $ARGS || die "could not run dbus-viewer" else + echo "running test-dbus-glib" libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/glib/test-dbus-glib || die "test-dbus-glib failed" fi diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c index cad6f168..9b1be0ad 100644 --- a/test/glib/test-service-glib.c +++ b/test/glib/test-service-glib.c @@ -4,6 +4,43 @@ #include #include +typedef struct MyObject MyObject; +typedef struct MyObjectClass MyObjectClass; + +GType my_object_get_type (void); + +struct MyObject +{ + GObject parent; +}; + +struct MyObjectClass +{ + GObjectClass parent; +}; + +#define MY_TYPE_OBJECT (my_object_get_type ()) +#define MY_OBJECT_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject)) +#define MY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass)) +#define MY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT)) +#define MY_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT)) +#define MY_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass)) + +G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT) + + +static void +my_object_init (MyObject *obj) +{ + +} + +static void +my_object_class_init (MyObjectClass *obj_class) +{ + +} + static GMainLoop *loop; int @@ -11,6 +48,7 @@ main (int argc, char **argv) { DBusGConnection *connection; GError *error; + GObject *obj; g_type_init (); @@ -27,7 +65,15 @@ main (int argc, char **argv) exit (1); } + obj = g_object_new (MY_TYPE_OBJECT, NULL); + + dbus_g_connection_register_g_object (connection, + "/org/freedesktop/my_test_object", + obj); + g_print ("GLib test service entering main loop\n"); + + g_main_loop_run (loop); g_print ("Successfully completed %s\n", argv[0]); diff --git a/tools/dbus-viewer.c b/tools/dbus-viewer.c index 9c57b229..c32e6fd9 100644 --- a/tools/dbus-viewer.c +++ b/tools/dbus-viewer.c @@ -29,6 +29,7 @@ #include "dbus-tree-view.h" #include #include +#include #include #define _(x) dgettext (GETTEXT_PACKAGE, x) @@ -188,6 +189,133 @@ show_error_dialog (GtkWindow *transient_parent, } } +static gboolean +load_child_nodes (const char *service_name, + NodeInfo *parent, + GError **error) +{ + DBusGConnection *connection; + GSList *tmp; + + connection = dbus_g_bus_get (DBUS_BUS_SESSION, error); + if (connection == NULL) + return FALSE; + + tmp = node_info_get_nodes (parent); + while (tmp != NULL) + { + DBusGProxy *proxy; + DBusGPendingCall *call; + const char *data; + NodeInfo *child; + NodeInfo *complete_child; + + complete_child = NULL; + + child = tmp->data; + + g_assert (*service_name == ':'); /* so we don't need new_for_name_owner */ + proxy = dbus_g_proxy_new_for_name (connection, + service_name, + "/", + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE); + g_assert (proxy != NULL); + + call = dbus_g_proxy_begin_call (proxy, "Introspect", + DBUS_TYPE_INVALID); + + data = NULL; + if (!dbus_g_proxy_end_call (proxy, call, error, DBUS_TYPE_STRING, &data, + DBUS_TYPE_INVALID)) + goto done; + + complete_child = description_load_from_string (data, -1, error); + if (complete_child == NULL) + goto done; + + done: + dbus_g_pending_call_unref (call); + g_object_unref (proxy); + + if (complete_child == NULL) + return FALSE; + + /* change complete_child's name to relative */ + base_info_set_name ((BaseInfo*)complete_child, + base_info_get_name ((BaseInfo*)child)); + + /* Stitch in complete_child rather than child */ + node_info_replace_node (parent, child, complete_child); + node_info_unref (complete_child); /* ref still held by parent */ + + /* Now recurse */ + if (!load_child_nodes (service_name, complete_child, error)) + return FALSE; + + tmp = tmp->next; + } + + return TRUE; +} + +static NodeInfo* +load_from_service (const char *service_name, + GError **error) +{ + DBusGConnection *connection; + DBusGProxy *root_proxy; + DBusGPendingCall *call; + const char *data; + NodeInfo *node; + + node = NULL; + call = NULL; + + connection = dbus_g_bus_get (DBUS_BUS_SESSION, error); + if (connection == NULL) + return NULL; + + root_proxy = dbus_g_proxy_new_for_name_owner (connection, + service_name, + "/", + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, + error); + if (root_proxy == NULL) + return NULL; + + call = dbus_g_proxy_begin_call (root_proxy, "Introspect", + DBUS_TYPE_INVALID); + + data = NULL; + if (!dbus_g_proxy_end_call (root_proxy, call, error, DBUS_TYPE_STRING, &data, + DBUS_TYPE_INVALID)) + goto out; + + node = description_load_from_string (data, -1, error); + + /* g_print ("%s\n", data); */ + + if (node == NULL) + goto out; + + base_info_set_name ((BaseInfo*)node, "/"); + + if (!load_child_nodes (dbus_g_proxy_get_bus_name (root_proxy), + node, error)) + { + node_info_unref (node); + node = NULL; + goto out; + } + + out: + if (call) + dbus_g_pending_call_unref (call); + + g_object_unref (root_proxy); + return node; +} + static void usage (int ecode) { @@ -214,6 +342,7 @@ main (int argc, char **argv) GSList *files; gboolean end_of_args; GSList *tmp; + gboolean services; bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); @@ -221,6 +350,7 @@ main (int argc, char **argv) gtk_init (&argc, &argv); + services = FALSE; end_of_args = FALSE; files = NULL; prev_arg = NULL; @@ -237,6 +367,8 @@ main (int argc, char **argv) usage (0); else if (strcmp (arg, "--version") == 0) version (); + else if (strcmp (arg, "--services") == 0) + services = TRUE; else if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0') @@ -270,8 +402,12 @@ main (int argc, char **argv) filename = tmp->data; error = NULL; - node = description_load_from_file (filename, - &error); + if (services) + node = load_from_service (filename, &error); + else + node = description_load_from_file (filename, + &error); + if (node == NULL) { g_assert (error != NULL); @@ -313,8 +449,3 @@ main (int argc, char **argv) return 0; } - - - - - -- cgit