1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
34 /* ---------------------------------------------------------------------------------------------------- */
36 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
38 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
39 * to not have it interfere with stdout/stderr)
42 G_GNUC_UNUSED static void
43 completion_debug (const gchar *format, ...)
47 static FILE *f = NULL;
49 va_start (var_args, format);
50 s = g_strdup_vprintf (format, var_args);
53 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
55 fprintf (f, "%s\n", s);
60 completion_debug (const gchar *format, ...)
65 /* ---------------------------------------------------------------------------------------------------- */
69 remove_arg (gint num, gint *argc, gchar **argv[])
73 g_assert (num <= (*argc));
75 for (n = num; (*argv)[n] != NULL; n++)
76 (*argv)[n] = (*argv)[n+1];
78 (*argc) = (*argc) - 1;
82 usage (gint *argc, gchar **argv[], gboolean use_stdout)
88 o = g_option_context_new (_("COMMAND"));
89 g_option_context_set_help_enabled (o, FALSE);
90 /* Ignore parsing result */
91 g_option_context_parse (o, argc, argv, NULL);
92 program_name = g_path_get_basename ((*argv)[0]);
93 s = g_strdup_printf (_("Commands:\n"
94 " help Shows this information\n"
95 " introspect Introspect a remote object\n"
96 " monitor Monitor a remote object\n"
97 " call Invoke a method on a remote object\n"
99 "Use \"%s COMMAND --help\" to get help on each command.\n"),
101 g_free (program_name);
102 g_option_context_set_description (o, s);
104 s = g_option_context_get_help (o, FALSE, NULL);
108 g_printerr ("%s", s);
110 g_option_context_free (o);
114 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
120 * 1. get a g_set_prgname() ?; or
121 * 2. save old argv[0] and restore later
124 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
125 remove_arg (1, argc, argv);
127 program_name = g_path_get_basename ((*argv)[0]);
128 s = g_strdup_printf ("%s %s", (*argv)[0], command);
130 g_free (program_name);
133 /* ---------------------------------------------------------------------------------------------------- */
136 print_methods (GDBusConnection *c,
142 const gchar *xml_data;
148 result = g_dbus_connection_call_sync (c,
151 "org.freedesktop.DBus.Introspectable",
154 G_VARIANT_TYPE ("(s)"),
155 G_DBUS_CALL_FLAGS_NONE,
161 g_printerr (_("Error: %s\n"), error->message);
162 g_error_free (error);
165 g_variant_get (result, "(&s)", &xml_data);
168 node = g_dbus_node_info_new_for_xml (xml_data, &error);
169 g_variant_unref (result);
172 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
173 g_error_free (error);
177 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
179 const GDBusInterfaceInfo *iface = node->interfaces[n];
180 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
182 const GDBusMethodInfo *method = iface->methods[m];
183 g_print ("%s.%s \n", iface->name, method->name);
186 g_dbus_node_info_unref (node);
193 print_paths (GDBusConnection *c,
199 const gchar *xml_data;
204 result = g_dbus_connection_call_sync (c,
207 "org.freedesktop.DBus.Introspectable",
210 G_VARIANT_TYPE ("(s)"),
211 G_DBUS_CALL_FLAGS_NONE,
217 g_printerr (_("Error: %s\n"), error->message);
218 g_error_free (error);
221 g_variant_get (result, "(&s)", &xml_data);
223 //g_printerr ("xml=`%s'", xml_data);
226 node = g_dbus_node_info_new_for_xml (xml_data, &error);
227 g_variant_unref (result);
230 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
231 g_error_free (error);
235 //g_printerr ("bar `%s'\n", path);
237 if (node->interfaces != NULL)
238 g_print ("%s \n", path);
240 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
244 //g_printerr ("foo `%s'\n", node->nodes[n].path);
246 if (g_strcmp0 (path, "/") == 0)
247 s = g_strdup_printf ("/%s", node->nodes[n]->path);
249 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
251 print_paths (c, name, s);
255 g_dbus_node_info_unref (node);
262 print_names (GDBusConnection *c,
263 gboolean include_unique_names)
269 GHashTable *name_set;
273 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
276 result = g_dbus_connection_call_sync (c,
277 "org.freedesktop.DBus",
278 "/org/freedesktop/DBus",
279 "org.freedesktop.DBus",
282 G_VARIANT_TYPE ("(as)"),
283 G_DBUS_CALL_FLAGS_NONE,
289 g_printerr (_("Error: %s\n"), error->message);
290 g_error_free (error);
293 g_variant_get (result, "(as)", &iter);
294 while (g_variant_iter_loop (iter, "s", &str))
295 g_hash_table_insert (name_set, g_strdup (str), NULL);
296 g_variant_iter_free (iter);
297 g_variant_unref (result);
300 result = g_dbus_connection_call_sync (c,
301 "org.freedesktop.DBus",
302 "/org/freedesktop/DBus",
303 "org.freedesktop.DBus",
304 "ListActivatableNames",
306 G_VARIANT_TYPE ("(as)"),
307 G_DBUS_CALL_FLAGS_NONE,
313 g_printerr (_("Error: %s\n"), error->message);
314 g_error_free (error);
317 g_variant_get (result, "(as)", &iter);
318 while (g_variant_iter_loop (iter, "s", &str))
319 g_hash_table_insert (name_set, g_strdup (str), NULL);
320 g_variant_iter_free (iter);
321 g_variant_unref (result);
323 keys = g_hash_table_get_keys (name_set);
324 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
325 for (l = keys; l != NULL; l = l->next)
327 const gchar *name = l->data;
328 if (!include_unique_names && g_str_has_prefix (name, ":"))
331 g_print ("%s \n", name);
336 g_hash_table_unref (name_set);
339 /* ---------------------------------------------------------------------------------------------------- */
341 static gboolean opt_connection_system = FALSE;
342 static gboolean opt_connection_session = FALSE;
343 static gchar *opt_connection_address = NULL;
345 static const GOptionEntry connection_entries[] =
347 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
348 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
349 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
353 static GOptionGroup *
354 connection_get_group (void)
356 static GOptionGroup *g;
358 g = g_option_group_new ("connection",
359 N_("Connection Endpoint Options:"),
360 N_("Options specifying the connection endpoint"),
363 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
364 g_option_group_add_entries (g, connection_entries);
369 static GDBusConnection *
370 connection_get_dbus_connection (GError **error)
376 /* First, ensure we have exactly one connect */
377 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
382 _("No connection endpoint specified"));
385 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
386 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
387 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
392 _("Multiple connection endpoints specified"));
396 if (opt_connection_system)
398 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
400 else if (opt_connection_session)
402 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
404 else if (opt_connection_address != NULL)
406 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
407 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
408 NULL, /* GDBusAuthObserver */
409 NULL, /* GCancellable */
417 /* ---------------------------------------------------------------------------------------------------- */
420 call_helper_get_method_in_signature (GDBusConnection *c,
423 const gchar *interface_name,
424 const gchar *method_name,
429 GDBusNodeInfo *node_info;
430 const gchar *xml_data;
431 GDBusInterfaceInfo *interface_info;
432 GDBusMethodInfo *method_info;
439 result = g_dbus_connection_call_sync (c,
442 "org.freedesktop.DBus.Introspectable",
445 G_VARIANT_TYPE ("(s)"),
446 G_DBUS_CALL_FLAGS_NONE,
453 g_variant_get (result, "(&s)", &xml_data);
454 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
455 if (node_info == NULL)
458 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
459 if (interface_info == NULL)
461 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
462 _("Warning: According to introspection data, interface `%s' does not exist\n"),
467 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
468 if (method_info == NULL)
470 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
471 _("Warning: According to introspection data, method `%s' does not exist on interface `%s'\n"),
477 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
478 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
480 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
484 if (node_info != NULL)
485 g_dbus_node_info_unref (node_info);
487 g_variant_unref (result);
492 /* ---------------------------------------------------------------------------------------------------- */
495 _g_variant_parse_me_harder (GVariantType *type,
496 const gchar *given_str,
504 str = g_string_new ("\"");
505 for (n = 0; given_str[n] != '\0'; n++)
507 if (G_UNLIKELY (given_str[n] == '\"'))
508 g_string_append (str, "\\\"");
510 g_string_append_c (str, given_str[n]);
512 g_string_append_c (str, '"');
513 s = g_string_free (str, FALSE);
515 value = g_variant_parse (type,
525 /* ---------------------------------------------------------------------------------------------------- */
527 static gchar *opt_call_dest = NULL;
528 static gchar *opt_call_object_path = NULL;
529 static gchar *opt_call_method = NULL;
530 static gint opt_call_timeout = -1;
532 static const GOptionEntry call_entries[] =
534 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
535 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
536 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
537 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
542 handle_call (gint *argc,
544 gboolean request_completion,
545 const gchar *completion_cur,
546 const gchar *completion_prev)
553 GVariant *parameters;
554 gchar *interface_name;
557 GPtrArray *in_signature_types;
558 gboolean complete_names;
559 gboolean complete_paths;
560 gboolean complete_methods;
561 GVariantBuilder builder;
567 interface_name = NULL;
570 in_signature_types = NULL;
572 modify_argv0_for_command (argc, argv, "call");
574 o = g_option_context_new (NULL);
575 g_option_context_set_help_enabled (o, FALSE);
576 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
577 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
578 g_option_context_add_group (o, connection_get_group ());
580 complete_names = FALSE;
581 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
583 complete_names = TRUE;
584 remove_arg ((*argc) - 1, argc, argv);
587 complete_paths = FALSE;
588 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
590 complete_paths = TRUE;
591 remove_arg ((*argc) - 1, argc, argv);
594 complete_methods = FALSE;
595 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
597 complete_methods = TRUE;
598 remove_arg ((*argc) - 1, argc, argv);
601 if (!g_option_context_parse (o, argc, argv, NULL))
603 if (!request_completion)
605 s = g_option_context_get_help (o, FALSE, NULL);
606 g_printerr ("%s", s);
613 c = connection_get_dbus_connection (&error);
616 if (request_completion)
618 if (g_strcmp0 (completion_prev, "--address") == 0)
626 g_print ("--system \n--session \n--address \n");
631 g_printerr (_("Error connecting: %s\n"), error->message);
632 g_error_free (error);
637 /* validate and complete destination (bus name) */
638 if (g_dbus_connection_get_unique_name (c) != NULL)
640 /* this only makes sense on message bus connections */
643 print_names (c, FALSE);
646 if (opt_call_dest == NULL)
648 if (request_completion)
649 g_print ("--dest \n");
651 g_printerr (_("Error: Destination is not specified\n"));
654 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
656 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
661 /* validate and complete object path */
664 print_paths (c, opt_call_dest, "/");
667 if (opt_call_object_path == NULL)
669 if (request_completion)
670 g_print ("--object-path \n");
672 g_printerr (_("Error: Object path is not specified\n"));
675 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
678 s = g_strdup (opt_call_object_path);
679 p = strrchr (s, '/');
686 print_paths (c, opt_call_dest, s);
690 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
692 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
696 /* validate and complete method (interface + method name) */
697 if (complete_methods)
699 print_methods (c, opt_call_dest, opt_call_object_path);
702 if (opt_call_method == NULL)
704 if (request_completion)
705 g_print ("--method \n");
707 g_printerr (_("Error: Method name is not specified\n"));
710 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
712 print_methods (c, opt_call_dest, opt_call_object_path);
715 s = strrchr (opt_call_method, '.');
716 if (!request_completion && s == NULL)
718 g_printerr (_("Error: Method name `%s' is invalid\n"), opt_call_method);
721 method_name = g_strdup (s + 1);
722 interface_name = g_strndup (opt_call_method, s - opt_call_method);
724 /* All done with completion now */
725 if (request_completion)
728 /* Introspect, for easy conversion - it's not fatal if we can't do this */
729 in_signature_types = call_helper_get_method_in_signature (c,
731 opt_call_object_path,
735 if (in_signature_types == NULL)
737 //g_printerr ("Error getting introspection data: %s\n", error->message);
738 g_error_free (error);
742 /* Read parameters */
743 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
744 for (n = 1; n < (guint) *argc; n++)
750 if (in_signature_types != NULL)
752 if (n - 1 >= in_signature_types->len)
754 /* Only warn for the first param */
755 if (n - 1 == in_signature_types->len)
757 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
758 in_signature_types->len);
763 type = in_signature_types->pdata[n - 1];
768 value = g_variant_parse (type,
775 g_error_free (error);
777 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
782 s = g_variant_type_dup_string (type);
783 g_printerr (_("Error parsing parameter %d of type `%s': %s\n"),
791 g_printerr (_("Error parsing parameter %d: %s\n"),
795 g_error_free (error);
796 g_variant_builder_clear (&builder);
800 g_variant_builder_add_value (&builder, value);
802 parameters = g_variant_builder_end (&builder);
804 if (parameters != NULL)
805 parameters = g_variant_ref_sink (parameters);
806 result = g_dbus_connection_call_sync (c,
808 opt_call_object_path,
813 G_DBUS_CALL_FLAGS_NONE,
814 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
819 g_printerr (_("Error: %s\n"), error->message);
820 g_error_free (error);
821 if (in_signature_types != NULL)
824 s = g_string_new (NULL);
825 for (n = 0; n < in_signature_types->len; n++)
827 GVariantType *type = in_signature_types->pdata[n];
828 g_string_append_len (s,
829 g_variant_type_peek_string (type),
830 g_variant_type_get_string_length (type));
832 g_printerr ("(According to introspection data, you need to pass `%s')\n", s->str);
833 g_string_free (s, TRUE);
838 s = g_variant_print (result, TRUE);
845 if (in_signature_types != NULL)
846 g_ptr_array_unref (in_signature_types);
848 g_variant_unref (result);
851 if (parameters != NULL)
852 g_variant_unref (parameters);
853 g_free (interface_name);
854 g_free (method_name);
855 g_option_context_free (o);
859 /* ---------------------------------------------------------------------------------------------------- */
861 /* TODO: dump annotations */
864 dump_annotation (const GDBusAnnotationInfo *o,
866 gboolean ignore_indent)
869 g_print ("%*s@%s(\"%s\")\n",
870 ignore_indent ? 0 : indent, "",
873 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
874 dump_annotation (o->annotations[n], indent + 2, FALSE);
878 dump_arg (const GDBusArgInfo *o,
880 const gchar *direction,
881 gboolean ignore_indent,
882 gboolean include_newline)
886 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
888 dump_annotation (o->annotations[n], indent, ignore_indent);
889 ignore_indent = FALSE;
892 g_print ("%*s%s%s %s%s",
893 ignore_indent ? 0 : indent, "",
897 include_newline ? ",\n" : "");
901 count_args (GDBusArgInfo **args)
907 while (args[n] != NULL)
914 dump_method (const GDBusMethodInfo *o,
920 guint total_num_args;
922 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
923 dump_annotation (o->annotations[n], indent, FALSE);
925 g_print ("%*s%s(", indent, "", o->name);
926 name_len = strlen (o->name);
927 total_num_args = count_args (o->in_args) + count_args (o->out_args);
928 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
930 gboolean ignore_indent = (m == 0);
931 gboolean include_newline = (m != total_num_args - 1);
933 dump_arg (o->in_args[n],
934 indent + name_len + 1,
939 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
941 gboolean ignore_indent = (m == 0);
942 gboolean include_newline = (m != total_num_args - 1);
943 dump_arg (o->out_args[n],
944 indent + name_len + 1,
953 dump_signal (const GDBusSignalInfo *o,
958 guint total_num_args;
960 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
961 dump_annotation (o->annotations[n], indent, FALSE);
963 g_print ("%*s%s(", indent, "", o->name);
964 name_len = strlen (o->name);
965 total_num_args = count_args (o->args);
966 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
968 gboolean ignore_indent = (n == 0);
969 gboolean include_newline = (n != total_num_args - 1);
970 dump_arg (o->args[n],
971 indent + name_len + 1,
980 dump_property (const GDBusPropertyInfo *o,
987 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
989 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
990 access = "writeonly";
991 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
992 access = "readwrite";
994 g_assert_not_reached ();
996 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
997 dump_annotation (o->annotations[n], indent, FALSE);
1001 gchar *s = g_variant_print (value, FALSE);
1002 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1007 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1012 dump_interface (GDBusConnection *c,
1014 const GDBusInterfaceInfo *o,
1016 const gchar *object_path)
1019 GHashTable *properties;
1021 properties = g_hash_table_new_full (g_str_hash,
1024 (GDestroyNotify) g_variant_unref);
1026 /* Try to get properties */
1027 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1030 result = g_dbus_connection_call_sync (c,
1033 "org.freedesktop.DBus.Properties",
1035 g_variant_new ("(s)", o->name),
1037 G_DBUS_CALL_FLAGS_NONE,
1043 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1047 g_variant_get (result,
1050 while ((item = g_variant_iter_next_value (iter)))
1054 g_variant_get (item,
1059 g_hash_table_insert (properties, key, g_variant_ref (value));
1062 g_variant_unref (result);
1067 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1069 result = g_dbus_connection_call_sync (c,
1072 "org.freedesktop.DBus.Properties",
1074 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1075 G_VARIANT_TYPE ("(v)"),
1076 G_DBUS_CALL_FLAGS_NONE,
1082 GVariant *property_value;
1083 g_variant_get (result,
1086 g_hash_table_insert (properties,
1087 g_strdup (o->properties[n]->name),
1088 g_variant_ref (property_value));
1089 g_variant_unref (result);
1095 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1096 dump_annotation (o->annotations[n], indent, FALSE);
1098 g_print ("%*sinterface %s {\n", indent, "", o->name);
1099 if (o->methods != NULL)
1101 g_print ("%*s methods:\n", indent, "");
1102 for (n = 0; o->methods[n] != NULL; n++)
1103 dump_method (o->methods[n], indent + 4);
1105 if (o->signals != NULL)
1107 g_print ("%*s signals:\n", indent, "");
1108 for (n = 0; o->signals[n] != NULL; n++)
1109 dump_signal (o->signals[n], indent + 4);
1111 if (o->properties != NULL)
1113 g_print ("%*s properties:\n", indent, "");
1114 for (n = 0; o->properties[n] != NULL; n++)
1116 dump_property (o->properties[n],
1118 g_hash_table_lookup (properties, (o->properties[n])->name));
1124 g_hash_table_unref (properties);
1128 dump_node (GDBusConnection *c,
1130 const GDBusNodeInfo *o,
1132 const gchar *object_path)
1135 const gchar *object_path_to_print;
1137 object_path_to_print = object_path;
1138 if (o->path != NULL)
1139 object_path_to_print = o->path;
1141 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1142 dump_annotation (o->annotations[n], indent, FALSE);
1144 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1145 if (o->interfaces != NULL || o->nodes != NULL)
1148 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1149 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1150 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1151 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL);
1161 static gchar *opt_introspect_dest = NULL;
1162 static gchar *opt_introspect_object_path = NULL;
1163 static gboolean opt_introspect_xml = FALSE;
1165 static const GOptionEntry introspect_entries[] =
1167 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1168 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1169 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1174 handle_introspect (gint *argc,
1176 gboolean request_completion,
1177 const gchar *completion_cur,
1178 const gchar *completion_prev)
1186 const gchar *xml_data;
1187 GDBusNodeInfo *node;
1188 gboolean complete_names;
1189 gboolean complete_paths;
1196 modify_argv0_for_command (argc, argv, "introspect");
1198 o = g_option_context_new (NULL);
1199 if (request_completion)
1200 g_option_context_set_ignore_unknown_options (o, TRUE);
1201 g_option_context_set_help_enabled (o, FALSE);
1202 g_option_context_set_summary (o, _("Introspect a remote object."));
1203 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1204 g_option_context_add_group (o, connection_get_group ());
1206 complete_names = FALSE;
1207 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1209 complete_names = TRUE;
1210 remove_arg ((*argc) - 1, argc, argv);
1213 complete_paths = FALSE;
1214 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1216 complete_paths = TRUE;
1217 remove_arg ((*argc) - 1, argc, argv);
1220 if (!g_option_context_parse (o, argc, argv, NULL))
1222 if (!request_completion)
1224 s = g_option_context_get_help (o, FALSE, NULL);
1225 g_printerr ("%s", s);
1232 c = connection_get_dbus_connection (&error);
1235 if (request_completion)
1237 if (g_strcmp0 (completion_prev, "--address") == 0)
1245 g_print ("--system \n--session \n--address \n");
1250 g_printerr (_("Error connecting: %s\n"), error->message);
1251 g_error_free (error);
1256 if (g_dbus_connection_get_unique_name (c) != NULL)
1260 print_names (c, FALSE);
1263 /* this only makes sense on message bus connections */
1264 if (opt_introspect_dest == NULL)
1266 if (request_completion)
1267 g_print ("--dest \n");
1269 g_printerr (_("Error: Destination is not specified\n"));
1272 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1274 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1280 print_paths (c, opt_introspect_dest, "/");
1283 if (opt_introspect_object_path == NULL)
1285 if (request_completion)
1286 g_print ("--object-path \n");
1288 g_printerr (_("Error: Object path is not specified\n"));
1291 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1294 s = g_strdup (opt_introspect_object_path);
1295 p = strrchr (s, '/');
1302 print_paths (c, opt_introspect_dest, s);
1306 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1308 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1312 /* All done with completion now */
1313 if (request_completion)
1316 result = g_dbus_connection_call_sync (c,
1317 opt_introspect_dest,
1318 opt_introspect_object_path,
1319 "org.freedesktop.DBus.Introspectable",
1322 G_VARIANT_TYPE ("(s)"),
1323 G_DBUS_CALL_FLAGS_NONE,
1329 g_printerr (_("Error: %s\n"), error->message);
1330 g_error_free (error);
1333 g_variant_get (result, "(&s)", &xml_data);
1335 if (opt_introspect_xml)
1337 g_print ("%s", xml_data);
1342 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1345 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1346 g_error_free (error);
1350 dump_node (c, opt_introspect_dest, node, 0, opt_introspect_object_path);
1357 g_dbus_node_info_unref (node);
1359 g_variant_unref (result);
1362 g_option_context_free (o);
1366 /* ---------------------------------------------------------------------------------------------------- */
1368 static gchar *opt_monitor_dest = NULL;
1369 static gchar *opt_monitor_object_path = NULL;
1371 static guint monitor_filter_id = 0;
1374 monitor_signal_cb (GDBusConnection *connection,
1375 const gchar *sender_name,
1376 const gchar *object_path,
1377 const gchar *interface_name,
1378 const gchar *signal_name,
1379 GVariant *parameters,
1383 s = g_variant_print (parameters, TRUE);
1384 g_print ("%s: %s.%s %s\n",
1393 monitor_on_name_appeared (GDBusConnection *connection,
1395 const gchar *name_owner,
1398 g_print ("The name %s is owned by %s\n", name, name_owner);
1399 g_assert (monitor_filter_id == 0);
1400 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1402 NULL, /* any interface */
1403 NULL, /* any member */
1404 opt_monitor_object_path,
1406 G_DBUS_SIGNAL_FLAGS_NONE,
1408 NULL, /* user_data */
1409 NULL); /* user_data destroy notify */
1413 monitor_on_name_vanished (GDBusConnection *connection,
1417 g_print ("The name %s does not have an owner\n", name);
1419 if (monitor_filter_id != 0)
1421 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1422 monitor_filter_id = 0;
1426 static const GOptionEntry monitor_entries[] =
1428 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1429 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1434 handle_monitor (gint *argc,
1436 gboolean request_completion,
1437 const gchar *completion_cur,
1438 const gchar *completion_prev)
1446 GDBusNodeInfo *node;
1447 gboolean complete_names;
1448 gboolean complete_paths;
1456 modify_argv0_for_command (argc, argv, "monitor");
1458 o = g_option_context_new (NULL);
1459 if (request_completion)
1460 g_option_context_set_ignore_unknown_options (o, TRUE);
1461 g_option_context_set_help_enabled (o, FALSE);
1462 g_option_context_set_summary (o, _("Monitor a remote object."));
1463 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1464 g_option_context_add_group (o, connection_get_group ());
1466 complete_names = FALSE;
1467 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1469 complete_names = TRUE;
1470 remove_arg ((*argc) - 1, argc, argv);
1473 complete_paths = FALSE;
1474 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1476 complete_paths = TRUE;
1477 remove_arg ((*argc) - 1, argc, argv);
1480 if (!g_option_context_parse (o, argc, argv, NULL))
1482 if (!request_completion)
1484 s = g_option_context_get_help (o, FALSE, NULL);
1485 g_printerr ("%s", s);
1492 c = connection_get_dbus_connection (&error);
1495 if (request_completion)
1497 if (g_strcmp0 (completion_prev, "--address") == 0)
1505 g_print ("--system \n--session \n--address \n");
1510 g_printerr (_("Error connecting: %s\n"), error->message);
1511 g_error_free (error);
1516 if (g_dbus_connection_get_unique_name (c) != NULL)
1520 print_names (c, FALSE);
1523 /* this only makes sense on message bus connections */
1524 if (opt_monitor_dest == NULL)
1526 if (request_completion)
1527 g_print ("--dest \n");
1529 g_printerr (_("Error: Destination is not specified\n"));
1532 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1534 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1540 print_paths (c, opt_monitor_dest, "/");
1543 if (opt_monitor_object_path == NULL)
1545 if (request_completion)
1547 g_print ("--object-path \n");
1550 /* it's fine to not have an object path */
1552 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1555 s = g_strdup (opt_monitor_object_path);
1556 p = strrchr (s, '/');
1563 print_paths (c, opt_monitor_dest, s);
1567 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1569 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1573 /* All done with completion now */
1574 if (request_completion)
1577 if (opt_monitor_object_path != NULL)
1578 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1580 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1582 loop = g_main_loop_new (NULL, FALSE);
1583 g_bus_watch_name_on_connection (c,
1585 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1586 monitor_on_name_appeared,
1587 monitor_on_name_vanished,
1591 g_main_loop_run (loop);
1592 g_main_loop_unref (loop);
1598 g_dbus_node_info_unref (node);
1600 g_variant_unref (result);
1603 g_option_context_free (o);
1607 /* ---------------------------------------------------------------------------------------------------- */
1610 pick_word_at (const gchar *s,
1612 gint *out_word_begins_at)
1619 if (out_word_begins_at != NULL)
1620 *out_word_begins_at = -1;
1624 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1626 if (out_word_begins_at != NULL)
1627 *out_word_begins_at = cursor;
1628 return g_strdup ("");
1631 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1636 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1639 if (out_word_begins_at != NULL)
1640 *out_word_begins_at = begin;
1642 return g_strndup (s + begin, end - begin);
1646 main (gint argc, gchar *argv[])
1649 const gchar *command;
1650 gboolean request_completion;
1651 gchar *completion_cur;
1652 gchar *completion_prev;
1654 setlocale (LC_ALL, "");
1655 textdomain (GETTEXT_PACKAGE);
1658 extern gchar *_glib_get_locale_dir (void);
1659 gchar *tmp = _glib_get_locale_dir ();
1660 bindtextdomain (GETTEXT_PACKAGE, tmp);
1663 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1666 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1667 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1671 completion_cur = NULL;
1672 completion_prev = NULL;
1678 usage (&argc, &argv, FALSE);
1682 request_completion = FALSE;
1684 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1688 if (g_strcmp0 (command, "help") == 0)
1690 if (request_completion)
1696 usage (&argc, &argv, TRUE);
1701 else if (g_strcmp0 (command, "call") == 0)
1703 if (handle_call (&argc,
1711 else if (g_strcmp0 (command, "introspect") == 0)
1713 if (handle_introspect (&argc,
1721 else if (g_strcmp0 (command, "monitor") == 0)
1723 if (handle_monitor (&argc,
1731 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
1733 const gchar *completion_line;
1734 gchar **completion_argv;
1735 gint completion_argc;
1736 gint completion_point;
1740 request_completion = TRUE;
1742 completion_line = argv[2];
1743 completion_point = strtol (argv[3], &endp, 10);
1744 if (endp == argv[3] || *endp != '\0')
1748 completion_debug ("completion_point=%d", completion_point);
1749 completion_debug ("----");
1750 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
1751 completion_debug ("`%s'", completion_line);
1752 completion_debug (" %*s^",
1753 completion_point, "");
1754 completion_debug ("----");
1757 if (!g_shell_parse_argv (completion_line,
1762 /* it's very possible the command line can't be parsed (for
1763 * example, missing quotes etc) - in that case, we just
1764 * don't autocomplete at all
1769 /* compute cur and prev */
1770 completion_prev = NULL;
1771 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
1775 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
1777 if (!g_ascii_isspace (completion_line[prev_end]))
1779 completion_prev = pick_word_at (completion_line, prev_end, NULL);
1785 completion_debug (" cur=`%s'", completion_cur);
1786 completion_debug ("prev=`%s'", completion_prev);
1789 argc = completion_argc;
1790 argv = completion_argv;
1798 if (request_completion)
1800 g_print ("help \ncall \nintrospect \nmonitor \n");
1806 g_printerr ("Unknown command `%s'\n", command);
1807 usage (&argc, &argv, FALSE);
1813 g_free (completion_cur);
1814 g_free (completion_prev);