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>
33 /* ---------------------------------------------------------------------------------------------------- */
35 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
37 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
38 * to not have it interfere with stdout/stderr)
41 G_GNUC_UNUSED static void
42 completion_debug (const gchar *format, ...)
46 static FILE *f = NULL;
48 va_start (var_args, format);
49 s = g_strdup_vprintf (format, var_args);
52 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
54 fprintf (f, "%s\n", s);
59 completion_debug (const gchar *format, ...)
64 /* ---------------------------------------------------------------------------------------------------- */
68 remove_arg (gint num, gint *argc, gchar **argv[])
72 g_assert (num <= (*argc));
74 for (n = num; (*argv)[n] != NULL; n++)
75 (*argv)[n] = (*argv)[n+1];
77 (*argc) = (*argc) - 1;
81 usage (gint *argc, gchar **argv[], gboolean use_stdout)
87 o = g_option_context_new (_("COMMAND"));
88 g_option_context_set_help_enabled (o, FALSE);
89 /* Ignore parsing result */
90 g_option_context_parse (o, argc, argv, NULL);
91 program_name = g_path_get_basename ((*argv)[0]);
92 s = g_strdup_printf (_("Commands:\n"
93 " help Shows this information\n"
94 " introspect Introspect a remote object\n"
95 " monitor Monitor a remote object\n"
96 " call Invoke a method on a remote object\n"
98 "Use \"%s COMMAND --help\" to get help on each command.\n"),
100 g_free (program_name);
101 g_option_context_set_description (o, s);
103 s = g_option_context_get_help (o, FALSE, NULL);
107 g_printerr ("%s", s);
109 g_option_context_free (o);
113 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
119 * 1. get a g_set_prgname() ?; or
120 * 2. save old argv[0] and restore later
123 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
124 remove_arg (1, argc, argv);
126 program_name = g_path_get_basename ((*argv)[0]);
127 s = g_strdup_printf ("%s %s", (*argv)[0], command);
129 g_free (program_name);
132 /* ---------------------------------------------------------------------------------------------------- */
135 print_methods (GDBusConnection *c,
141 const gchar *xml_data;
147 result = g_dbus_connection_call_sync (c,
150 "org.freedesktop.DBus.Introspectable",
153 G_DBUS_CALL_FLAGS_NONE,
159 g_printerr (_("Error: %s\n"), error->message);
160 g_error_free (error);
163 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
165 g_printerr (_("Error: Result is type `%s', expected `(s)'\n"),
166 g_variant_get_type_string (result));
167 g_variant_unref (result);
170 g_variant_get (result, "(&s)", &xml_data);
173 node = g_dbus_node_info_new_for_xml (xml_data, &error);
174 g_variant_unref (result);
177 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
178 g_error_free (error);
182 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
184 const GDBusInterfaceInfo *iface = node->interfaces[n];
185 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
187 const GDBusMethodInfo *method = iface->methods[m];
188 g_print ("%s.%s \n", iface->name, method->name);
191 g_dbus_node_info_unref (node);
198 print_paths (GDBusConnection *c,
204 const gchar *xml_data;
209 result = g_dbus_connection_call_sync (c,
212 "org.freedesktop.DBus.Introspectable",
215 G_DBUS_CALL_FLAGS_NONE,
221 g_printerr (_("Error: %s\n"), error->message);
222 g_error_free (error);
225 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
227 g_printerr (_("Error: Result is type `%s', expected `(s)'\n"),
228 g_variant_get_type_string (result));
229 g_variant_unref (result);
232 g_variant_get (result, "(&s)", &xml_data);
234 //g_printerr ("xml=`%s'", xml_data);
237 node = g_dbus_node_info_new_for_xml (xml_data, &error);
238 g_variant_unref (result);
241 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
242 g_error_free (error);
246 //g_printerr ("bar `%s'\n", path);
248 if (node->interfaces != NULL)
249 g_print ("%s \n", path);
251 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
255 //g_printerr ("foo `%s'\n", node->nodes[n].path);
257 if (g_strcmp0 (path, "/") == 0)
258 s = g_strdup_printf ("/%s", node->nodes[n]->path);
260 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
262 print_paths (c, name, s);
266 g_dbus_node_info_unref (node);
273 print_names (GDBusConnection *c,
274 gboolean include_unique_names)
280 GHashTable *name_set;
284 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
287 result = g_dbus_connection_call_sync (c,
288 "org.freedesktop.DBus",
289 "/org/freedesktop/DBus",
290 "org.freedesktop.DBus",
293 G_DBUS_CALL_FLAGS_NONE,
299 g_printerr (_("Error: %s\n"), error->message);
300 g_error_free (error);
303 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(as)")))
305 g_printerr (_("Error: Result is type `%s', expected `(as)'\n"), g_variant_get_type_string (result));
306 g_variant_unref (result);
309 g_variant_get (result, "(as)", &iter);
310 while (g_variant_iter_loop (iter, "s", &str))
311 g_hash_table_insert (name_set, g_strdup (str), NULL);
312 g_variant_iter_free (iter);
313 g_variant_unref (result);
316 result = g_dbus_connection_call_sync (c,
317 "org.freedesktop.DBus",
318 "/org/freedesktop/DBus",
319 "org.freedesktop.DBus",
320 "ListActivatableNames",
322 G_DBUS_CALL_FLAGS_NONE,
328 g_printerr (_("Error: %s\n"), error->message);
329 g_error_free (error);
332 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(as)")))
334 g_printerr (_("Error: Result is type `%s', expected `(as)'\n"), g_variant_get_type_string (result));
335 g_variant_unref (result);
338 g_variant_get (result, "(as)", &iter);
339 while (g_variant_iter_loop (iter, "s", &str))
340 g_hash_table_insert (name_set, g_strdup (str), NULL);
341 g_variant_iter_free (iter);
342 g_variant_unref (result);
344 keys = g_hash_table_get_keys (name_set);
345 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
346 for (l = keys; l != NULL; l = l->next)
348 const gchar *name = l->data;
349 if (!include_unique_names && g_str_has_prefix (name, ":"))
352 g_print ("%s \n", name);
357 g_hash_table_unref (name_set);
360 /* ---------------------------------------------------------------------------------------------------- */
362 static gboolean opt_connection_system = FALSE;
363 static gboolean opt_connection_session = FALSE;
364 static gchar *opt_connection_address = NULL;
366 static const GOptionEntry connection_entries[] =
368 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
369 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
370 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
374 static GOptionGroup *
375 connection_get_group (void)
377 static GOptionGroup *g;
379 g = g_option_group_new ("connection",
380 N_("Connection Endpoint Options:"),
381 N_("Options specifying the connection endpoint"),
384 g_option_group_add_entries (g, connection_entries);
388 static GDBusConnection *
389 connection_get_dbus_connection (GError **error)
395 /* First, ensure we have exactly one connect */
396 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
401 _("No connection endpoint specified"));
404 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
405 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
406 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
411 _("Multiple connection endpoints specified"));
415 if (opt_connection_system)
417 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
419 else if (opt_connection_session)
421 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
423 else if (opt_connection_address != NULL)
425 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
426 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
427 NULL, /* GDBusAuthObserver */
428 NULL, /* GCancellable */
436 /* ---------------------------------------------------------------------------------------------------- */
439 call_helper_get_method_in_signature (GDBusConnection *c,
442 const gchar *interface_name,
443 const gchar *method_name,
448 GDBusNodeInfo *node_info;
449 const gchar *xml_data;
450 const GDBusInterfaceInfo *interface_info;
451 const GDBusMethodInfo *method_info;
458 result = g_dbus_connection_call_sync (c,
461 "org.freedesktop.DBus.Introspectable",
464 G_DBUS_CALL_FLAGS_NONE,
471 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
473 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
474 _("Error: Result is type `%s', expected `(s)'\n"),
475 g_variant_get_type_string (result));
479 g_variant_get (result, "(&s)", &xml_data);
480 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
481 if (node_info == NULL)
484 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
485 if (interface_info == NULL)
487 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
488 _("Warning: According to introspection data, interface `%s' does not exist\n"),
493 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
494 if (method_info == NULL)
496 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
497 _("Warning: According to introspection data, method `%s' does not exist on interface `%s'\n"),
503 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
504 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
506 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
510 if (node_info != NULL)
511 g_dbus_node_info_unref (node_info);
513 g_variant_unref (result);
518 /* ---------------------------------------------------------------------------------------------------- */
521 _g_variant_parse_me_harder (GVariantType *type,
522 const gchar *given_str,
530 str = g_string_new ("\"");
531 for (n = 0; given_str[n] != '\0'; n++)
533 if (G_UNLIKELY (given_str[n] == '\"'))
534 g_string_append (str, "\\\"");
536 g_string_append_c (str, given_str[n]);
538 g_string_append_c (str, '"');
539 s = g_string_free (str, FALSE);
541 value = g_variant_parse (type,
551 /* ---------------------------------------------------------------------------------------------------- */
553 static gchar *opt_call_dest = NULL;
554 static gchar *opt_call_object_path = NULL;
555 static gchar *opt_call_method = NULL;
557 static const GOptionEntry call_entries[] =
559 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
560 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
561 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
566 handle_call (gint *argc,
568 gboolean request_completion,
569 const gchar *completion_cur,
570 const gchar *completion_prev)
577 GVariant *parameters;
578 gchar *interface_name;
581 GPtrArray *in_signature_types;
582 gboolean complete_names;
583 gboolean complete_paths;
584 gboolean complete_methods;
585 GVariantBuilder builder;
591 interface_name = NULL;
594 in_signature_types = NULL;
596 modify_argv0_for_command (argc, argv, "call");
598 o = g_option_context_new (NULL);
599 g_option_context_set_help_enabled (o, FALSE);
600 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
601 g_option_context_add_main_entries (o, call_entries, NULL /* GETTEXT_PACKAGE*/);
602 g_option_context_add_group (o, connection_get_group ());
604 complete_names = FALSE;
605 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
607 complete_names = TRUE;
608 remove_arg ((*argc) - 1, argc, argv);
611 complete_paths = FALSE;
612 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
614 complete_paths = TRUE;
615 remove_arg ((*argc) - 1, argc, argv);
618 complete_methods = FALSE;
619 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
621 complete_methods = TRUE;
622 remove_arg ((*argc) - 1, argc, argv);
625 if (!g_option_context_parse (o, argc, argv, NULL))
627 if (!request_completion)
629 s = g_option_context_get_help (o, FALSE, NULL);
630 g_printerr ("%s", s);
637 c = connection_get_dbus_connection (&error);
640 if (request_completion)
642 if (g_strcmp0 (completion_prev, "--address") == 0)
650 g_print ("--system \n--session \n--address \n");
655 g_printerr (_("Error connecting: %s\n"), error->message);
656 g_error_free (error);
661 /* validate and complete destination (bus name) */
662 if (g_dbus_connection_get_unique_name (c) != NULL)
664 /* this only makes sense on message bus connections */
667 print_names (c, FALSE);
670 if (opt_call_dest == NULL)
672 if (request_completion)
673 g_print ("--dest \n");
675 g_printerr (_("Error: Destination is not specified\n"));
678 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
680 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
685 /* validate and complete object path */
688 print_paths (c, opt_call_dest, "/");
691 if (opt_call_object_path == NULL)
693 if (request_completion)
694 g_print ("--object-path \n");
696 g_printerr (_("Error: Object path is not specified\n"));
699 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
702 s = g_strdup (opt_call_object_path);
703 p = strrchr (s, '/');
710 print_paths (c, opt_call_dest, s);
714 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
716 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
720 /* validate and complete method (interface + method name) */
721 if (complete_methods)
723 print_methods (c, opt_call_dest, opt_call_object_path);
726 if (opt_call_method == NULL)
728 if (request_completion)
729 g_print ("--method \n");
731 g_printerr (_("Error: Method name is not specified\n"));
734 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
736 print_methods (c, opt_call_dest, opt_call_object_path);
739 s = strrchr (opt_call_method, '.');
740 if (!request_completion && s == NULL)
742 g_printerr (_("Error: Method name `%s' is invalid\n"), opt_call_method);
745 method_name = g_strdup (s + 1);
746 interface_name = g_strndup (opt_call_method, s - opt_call_method);
748 /* All done with completion now */
749 if (request_completion)
752 /* Introspect, for easy conversion - it's not fatal if we can't do this */
753 in_signature_types = call_helper_get_method_in_signature (c,
755 opt_call_object_path,
759 if (in_signature_types == NULL)
761 //g_printerr ("Error getting introspection data: %s\n", error->message);
762 g_error_free (error);
766 /* Read parameters */
767 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
768 for (n = 1; n < (guint) *argc; n++)
774 if (in_signature_types != NULL)
776 if (n - 1 >= in_signature_types->len)
778 /* Only warn for the first param */
779 if (n - 1 == in_signature_types->len)
781 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
782 in_signature_types->len);
787 type = in_signature_types->pdata[n - 1];
792 value = g_variant_parse (type,
799 g_error_free (error);
801 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
806 s = g_variant_type_dup_string (type);
807 g_printerr (_("Error parsing parameter %d of type `%s': %s\n"),
815 g_printerr (_("Error parsing parameter %d: %s\n"),
819 g_error_free (error);
820 g_variant_builder_clear (&builder);
824 g_variant_builder_add_value (&builder, value);
826 parameters = g_variant_builder_end (&builder);
828 if (parameters != NULL)
829 parameters = g_variant_ref_sink (parameters);
830 result = g_dbus_connection_call_sync (c,
832 opt_call_object_path,
836 G_DBUS_CALL_FLAGS_NONE,
842 g_printerr (_("Error: %s\n"), error->message);
843 g_error_free (error);
844 if (in_signature_types != NULL)
847 s = g_string_new (NULL);
848 for (n = 0; n < in_signature_types->len; n++)
850 GVariantType *type = in_signature_types->pdata[n];
851 g_string_append_len (s,
852 g_variant_type_peek_string (type),
853 g_variant_type_get_string_length (type));
855 g_printerr ("(According to introspection data, you need to pass `%s')\n", s->str);
856 g_string_free (s, TRUE);
861 s = g_variant_print (result, TRUE);
868 if (in_signature_types != NULL)
869 g_ptr_array_unref (in_signature_types);
871 g_variant_unref (result);
874 if (parameters != NULL)
875 g_variant_unref (parameters);
876 g_free (interface_name);
877 g_free (method_name);
878 g_option_context_free (o);
882 /* ---------------------------------------------------------------------------------------------------- */
884 /* TODO: dump annotations */
887 dump_annotation (const GDBusAnnotationInfo *o,
889 gboolean ignore_indent)
892 g_print ("%*s@%s(\"%s\")\n",
893 ignore_indent ? 0 : indent, "",
896 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
897 dump_annotation (o->annotations[n], indent + 2, FALSE);
901 dump_arg (const GDBusArgInfo *o,
903 const gchar *direction,
904 gboolean ignore_indent,
905 gboolean include_newline)
909 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
911 dump_annotation (o->annotations[n], indent, ignore_indent);
912 ignore_indent = FALSE;
915 g_print ("%*s%s%s %s%s",
916 ignore_indent ? 0 : indent, "",
920 include_newline ? ",\n" : "");
924 count_args (GDBusArgInfo **args)
930 while (args[n] != NULL)
937 dump_method (const GDBusMethodInfo *o,
943 guint total_num_args;
945 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
946 dump_annotation (o->annotations[n], indent, FALSE);
948 g_print ("%*s%s(", indent, "", o->name);
949 name_len = strlen (o->name);
950 total_num_args = count_args (o->in_args) + count_args (o->out_args);
951 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
953 gboolean ignore_indent = (m == 0);
954 gboolean include_newline = (m != total_num_args - 1);
956 dump_arg (o->in_args[n],
957 indent + name_len + 1,
962 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
964 gboolean ignore_indent = (m == 0);
965 gboolean include_newline = (m != total_num_args - 1);
966 dump_arg (o->out_args[n],
967 indent + name_len + 1,
976 dump_signal (const GDBusSignalInfo *o,
981 guint total_num_args;
983 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
984 dump_annotation (o->annotations[n], indent, FALSE);
986 g_print ("%*s%s(", indent, "", o->name);
987 name_len = strlen (o->name);
988 total_num_args = count_args (o->args);
989 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
991 gboolean ignore_indent = (n == 0);
992 gboolean include_newline = (n != total_num_args - 1);
993 dump_arg (o->args[n],
994 indent + name_len + 1,
1003 dump_property (const GDBusPropertyInfo *o,
1007 const gchar *access;
1010 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1011 access = "readonly";
1012 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1013 access = "writeonly";
1014 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1015 access = "readwrite";
1017 g_assert_not_reached ();
1019 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1020 dump_annotation (o->annotations[n], indent, FALSE);
1024 gchar *s = g_variant_print (value, FALSE);
1025 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1030 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1035 dump_interface (GDBusConnection *c,
1037 const GDBusInterfaceInfo *o,
1039 const gchar *object_path)
1042 GHashTable *properties;
1044 properties = g_hash_table_new_full (g_str_hash,
1047 (GDestroyNotify) g_variant_unref);
1049 /* Try to get properties */
1050 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1053 result = g_dbus_connection_call_sync (c,
1056 "org.freedesktop.DBus.Properties",
1058 g_variant_new ("(s)", o->name),
1059 G_DBUS_CALL_FLAGS_NONE,
1065 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1069 g_variant_get (result,
1072 while ((item = g_variant_iter_next_value (iter)))
1076 g_variant_get (item,
1081 g_hash_table_insert (properties, key, g_variant_ref (value));
1084 g_variant_unref (result);
1089 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1091 result = g_dbus_connection_call_sync (c,
1094 "org.freedesktop.DBus.Properties",
1096 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1097 G_DBUS_CALL_FLAGS_NONE,
1103 GVariant *property_value;
1104 g_variant_get (result,
1107 g_hash_table_insert (properties,
1108 g_strdup (o->properties[n]->name),
1109 g_variant_ref (property_value));
1110 g_variant_unref (result);
1116 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1117 dump_annotation (o->annotations[n], indent, FALSE);
1119 g_print ("%*sinterface %s {\n", indent, "", o->name);
1120 if (o->methods != NULL)
1122 g_print ("%*s methods:\n", indent, "");
1123 for (n = 0; o->methods[n] != NULL; n++)
1124 dump_method (o->methods[n], indent + 4);
1126 if (o->signals != NULL)
1128 g_print ("%*s signals:\n", indent, "");
1129 for (n = 0; o->signals[n] != NULL; n++)
1130 dump_signal (o->signals[n], indent + 4);
1132 if (o->properties != NULL)
1134 g_print ("%*s properties:\n", indent, "");
1135 for (n = 0; o->properties[n] != NULL; n++)
1137 dump_property (o->properties[n],
1139 g_hash_table_lookup (properties, (o->properties[n])->name));
1145 g_hash_table_unref (properties);
1149 dump_node (GDBusConnection *c,
1151 const GDBusNodeInfo *o,
1153 const gchar *object_path)
1156 const gchar *object_path_to_print;
1158 object_path_to_print = object_path;
1159 if (o->path != NULL)
1160 object_path_to_print = o->path;
1162 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1163 dump_annotation (o->annotations[n], indent, FALSE);
1165 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1166 if (o->interfaces != NULL || o->nodes != NULL)
1169 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1170 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1171 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1172 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL);
1182 static gchar *opt_introspect_dest = NULL;
1183 static gchar *opt_introspect_object_path = NULL;
1185 static const GOptionEntry introspect_entries[] =
1187 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1188 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1193 handle_introspect (gint *argc,
1195 gboolean request_completion,
1196 const gchar *completion_cur,
1197 const gchar *completion_prev)
1205 const gchar *xml_data;
1206 GDBusNodeInfo *node;
1207 gboolean complete_names;
1208 gboolean complete_paths;
1215 modify_argv0_for_command (argc, argv, "introspect");
1217 o = g_option_context_new (NULL);
1218 if (request_completion)
1219 g_option_context_set_ignore_unknown_options (o, TRUE);
1220 g_option_context_set_help_enabled (o, FALSE);
1221 g_option_context_set_summary (o, _("Introspect a remote object."));
1222 g_option_context_add_main_entries (o, introspect_entries, NULL /* GETTEXT_PACKAGE*/);
1223 g_option_context_add_group (o, connection_get_group ());
1225 complete_names = FALSE;
1226 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1228 complete_names = TRUE;
1229 remove_arg ((*argc) - 1, argc, argv);
1232 complete_paths = FALSE;
1233 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1235 complete_paths = TRUE;
1236 remove_arg ((*argc) - 1, argc, argv);
1239 if (!g_option_context_parse (o, argc, argv, NULL))
1241 if (!request_completion)
1243 s = g_option_context_get_help (o, FALSE, NULL);
1244 g_printerr ("%s", s);
1251 c = connection_get_dbus_connection (&error);
1254 if (request_completion)
1256 if (g_strcmp0 (completion_prev, "--address") == 0)
1264 g_print ("--system \n--session \n--address \n");
1269 g_printerr (_("Error connecting: %s\n"), error->message);
1270 g_error_free (error);
1275 if (g_dbus_connection_get_unique_name (c) != NULL)
1279 print_names (c, FALSE);
1282 /* this only makes sense on message bus connections */
1283 if (opt_introspect_dest == NULL)
1285 if (request_completion)
1286 g_print ("--dest \n");
1288 g_printerr (_("Error: Destination is not specified\n"));
1291 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1293 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1299 print_paths (c, opt_introspect_dest, "/");
1302 if (opt_introspect_object_path == NULL)
1304 if (request_completion)
1305 g_print ("--object-path \n");
1307 g_printerr (_("Error: Object path is not specified\n"));
1310 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1313 s = g_strdup (opt_introspect_object_path);
1314 p = strrchr (s, '/');
1321 print_paths (c, opt_introspect_dest, s);
1325 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1327 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1331 /* All done with completion now */
1332 if (request_completion)
1335 result = g_dbus_connection_call_sync (c,
1336 opt_introspect_dest,
1337 opt_introspect_object_path,
1338 "org.freedesktop.DBus.Introspectable",
1341 G_DBUS_CALL_FLAGS_NONE,
1347 g_printerr (_("Error: %s\n"), error->message);
1348 g_error_free (error);
1351 if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
1353 g_printerr (_("Error: Result is type `%s', expected `(s)'\n"),
1354 g_variant_get_type_string (result));
1357 g_variant_get (result, "(&s)", &xml_data);
1360 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1363 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1364 g_error_free (error);
1368 dump_node (c, opt_introspect_dest, node, 0, opt_introspect_object_path);
1374 g_dbus_node_info_unref (node);
1376 g_variant_unref (result);
1379 g_option_context_free (o);
1383 /* ---------------------------------------------------------------------------------------------------- */
1385 static gchar *opt_monitor_dest = NULL;
1386 static gchar *opt_monitor_object_path = NULL;
1388 static guint monitor_filter_id = 0;
1391 monitor_signal_cb (GDBusConnection *connection,
1392 const gchar *sender_name,
1393 const gchar *object_path,
1394 const gchar *interface_name,
1395 const gchar *signal_name,
1396 GVariant *parameters,
1400 s = g_variant_print (parameters, TRUE);
1401 g_print ("%s: %s.%s %s\n",
1410 monitor_on_name_appeared (GDBusConnection *connection,
1412 const gchar *name_owner,
1415 g_print ("The name %s is owned by %s\n", name, name_owner);
1416 g_assert (monitor_filter_id == 0);
1417 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1419 NULL, /* any interface */
1420 NULL, /* any member */
1421 opt_monitor_object_path,
1424 NULL, /* user_data */
1425 NULL); /* user_data destroy notify */
1429 monitor_on_name_vanished (GDBusConnection *connection,
1433 g_print ("The name %s does not have an owner\n", name);
1435 if (monitor_filter_id != 0)
1437 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1438 monitor_filter_id = 0;
1442 static const GOptionEntry monitor_entries[] =
1444 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1445 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1450 handle_monitor (gint *argc,
1452 gboolean request_completion,
1453 const gchar *completion_cur,
1454 const gchar *completion_prev)
1462 GDBusNodeInfo *node;
1463 gboolean complete_names;
1464 gboolean complete_paths;
1472 modify_argv0_for_command (argc, argv, "monitor");
1474 o = g_option_context_new (NULL);
1475 if (request_completion)
1476 g_option_context_set_ignore_unknown_options (o, TRUE);
1477 g_option_context_set_help_enabled (o, FALSE);
1478 g_option_context_set_summary (o, _("Monitor a remote object."));
1479 g_option_context_add_main_entries (o, monitor_entries, NULL /* GETTEXT_PACKAGE*/);
1480 g_option_context_add_group (o, connection_get_group ());
1482 complete_names = FALSE;
1483 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1485 complete_names = TRUE;
1486 remove_arg ((*argc) - 1, argc, argv);
1489 complete_paths = FALSE;
1490 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1492 complete_paths = TRUE;
1493 remove_arg ((*argc) - 1, argc, argv);
1496 if (!g_option_context_parse (o, argc, argv, NULL))
1498 if (!request_completion)
1500 s = g_option_context_get_help (o, FALSE, NULL);
1501 g_printerr ("%s", s);
1508 c = connection_get_dbus_connection (&error);
1511 if (request_completion)
1513 if (g_strcmp0 (completion_prev, "--address") == 0)
1521 g_print ("--system \n--session \n--address \n");
1526 g_printerr (_("Error connecting: %s\n"), error->message);
1527 g_error_free (error);
1532 if (g_dbus_connection_get_unique_name (c) != NULL)
1536 print_names (c, FALSE);
1539 /* this only makes sense on message bus connections */
1540 if (opt_monitor_dest == NULL)
1542 if (request_completion)
1543 g_print ("--dest \n");
1545 g_printerr (_("Error: Destination is not specified\n"));
1548 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1550 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1556 print_paths (c, opt_monitor_dest, "/");
1559 if (opt_monitor_object_path == NULL)
1561 if (request_completion)
1563 g_print ("--object-path \n");
1566 /* it's fine to not have an object path */
1568 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1571 s = g_strdup (opt_monitor_object_path);
1572 p = strrchr (s, '/');
1579 print_paths (c, opt_monitor_dest, s);
1583 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1585 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1589 /* All done with completion now */
1590 if (request_completion)
1593 if (opt_monitor_object_path != NULL)
1594 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1596 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1598 loop = g_main_loop_new (NULL, FALSE);
1599 g_bus_watch_name_on_connection (c,
1601 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1602 monitor_on_name_appeared,
1603 monitor_on_name_vanished,
1607 g_main_loop_run (loop);
1608 g_main_loop_unref (loop);
1614 g_dbus_node_info_unref (node);
1616 g_variant_unref (result);
1619 g_option_context_free (o);
1623 /* ---------------------------------------------------------------------------------------------------- */
1626 pick_word_at (const gchar *s,
1628 gint *out_word_begins_at)
1635 if (out_word_begins_at != NULL)
1636 *out_word_begins_at = -1;
1640 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1642 if (out_word_begins_at != NULL)
1643 *out_word_begins_at = cursor;
1644 return g_strdup ("");
1647 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1652 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1655 if (out_word_begins_at != NULL)
1656 *out_word_begins_at = begin;
1658 return g_strndup (s + begin, end - begin);
1662 main (gint argc, gchar *argv[])
1665 const gchar *command;
1666 gboolean request_completion;
1667 gchar *completion_cur;
1668 gchar *completion_prev;
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);