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>
35 #include "glib/glib-private.h"
38 /* ---------------------------------------------------------------------------------------------------- */
40 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
42 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
43 * to not have it interfere with stdout/stderr)
46 G_GNUC_UNUSED static void
47 completion_debug (const gchar *format, ...)
51 static FILE *f = NULL;
53 va_start (var_args, format);
54 s = g_strdup_vprintf (format, var_args);
57 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
59 fprintf (f, "%s\n", s);
64 completion_debug (const gchar *format, ...)
69 /* ---------------------------------------------------------------------------------------------------- */
73 remove_arg (gint num, gint *argc, gchar **argv[])
77 g_assert (num <= (*argc));
79 for (n = num; (*argv)[n] != NULL; n++)
80 (*argv)[n] = (*argv)[n+1];
82 (*argc) = (*argc) - 1;
86 usage (gint *argc, gchar **argv[], gboolean use_stdout)
92 o = g_option_context_new (_("COMMAND"));
93 g_option_context_set_help_enabled (o, FALSE);
94 /* Ignore parsing result */
95 g_option_context_parse (o, argc, argv, NULL);
96 program_name = g_path_get_basename ((*argv)[0]);
97 s = g_strdup_printf (_("Commands:\n"
98 " help Shows this information\n"
99 " introspect Introspect a remote object\n"
100 " monitor Monitor a remote object\n"
101 " call Invoke a method on a remote object\n"
102 " emit Emit a signal\n"
104 "Use \"%s COMMAND --help\" to get help on each command.\n"),
106 g_free (program_name);
107 g_option_context_set_description (o, s);
109 s = g_option_context_get_help (o, FALSE, NULL);
113 g_printerr ("%s", s);
115 g_option_context_free (o);
119 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
125 * 1. get a g_set_prgname() ?; or
126 * 2. save old argv[0] and restore later
129 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
130 remove_arg (1, argc, argv);
132 program_name = g_path_get_basename ((*argv)[0]);
133 s = g_strdup_printf ("%s %s", (*argv)[0], command);
135 g_free (program_name);
138 /* ---------------------------------------------------------------------------------------------------- */
141 print_methods (GDBusConnection *c,
147 const gchar *xml_data;
153 result = g_dbus_connection_call_sync (c,
156 "org.freedesktop.DBus.Introspectable",
159 G_VARIANT_TYPE ("(s)"),
160 G_DBUS_CALL_FLAGS_NONE,
166 g_printerr (_("Error: %s\n"), error->message);
167 g_error_free (error);
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_VARIANT_TYPE ("(s)"),
216 G_DBUS_CALL_FLAGS_NONE,
222 g_printerr (_("Error: %s\n"), error->message);
223 g_error_free (error);
226 g_variant_get (result, "(&s)", &xml_data);
228 //g_printerr ("xml='%s'", xml_data);
231 node = g_dbus_node_info_new_for_xml (xml_data, &error);
232 g_variant_unref (result);
235 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
236 g_error_free (error);
240 //g_printerr ("bar '%s'\n", path);
242 if (node->interfaces != NULL)
243 g_print ("%s \n", path);
245 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
249 //g_printerr ("foo '%s'\n", node->nodes[n].path);
251 if (g_strcmp0 (path, "/") == 0)
252 s = g_strdup_printf ("/%s", node->nodes[n]->path);
254 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
256 print_paths (c, name, s);
260 g_dbus_node_info_unref (node);
267 print_names (GDBusConnection *c,
268 gboolean include_unique_names)
274 GHashTable *name_set;
278 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
281 result = g_dbus_connection_call_sync (c,
282 "org.freedesktop.DBus",
283 "/org/freedesktop/DBus",
284 "org.freedesktop.DBus",
287 G_VARIANT_TYPE ("(as)"),
288 G_DBUS_CALL_FLAGS_NONE,
294 g_printerr (_("Error: %s\n"), error->message);
295 g_error_free (error);
298 g_variant_get (result, "(as)", &iter);
299 while (g_variant_iter_loop (iter, "s", &str))
300 g_hash_table_insert (name_set, g_strdup (str), NULL);
301 g_variant_iter_free (iter);
302 g_variant_unref (result);
305 result = g_dbus_connection_call_sync (c,
306 "org.freedesktop.DBus",
307 "/org/freedesktop/DBus",
308 "org.freedesktop.DBus",
309 "ListActivatableNames",
311 G_VARIANT_TYPE ("(as)"),
312 G_DBUS_CALL_FLAGS_NONE,
318 g_printerr (_("Error: %s\n"), error->message);
319 g_error_free (error);
322 g_variant_get (result, "(as)", &iter);
323 while (g_variant_iter_loop (iter, "s", &str))
324 g_hash_table_insert (name_set, g_strdup (str), NULL);
325 g_variant_iter_free (iter);
326 g_variant_unref (result);
328 keys = g_hash_table_get_keys (name_set);
329 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
330 for (l = keys; l != NULL; l = l->next)
332 const gchar *name = l->data;
333 if (!include_unique_names && g_str_has_prefix (name, ":"))
336 g_print ("%s \n", name);
341 g_hash_table_unref (name_set);
344 /* ---------------------------------------------------------------------------------------------------- */
346 static gboolean opt_connection_system = FALSE;
347 static gboolean opt_connection_session = FALSE;
348 static gchar *opt_connection_address = NULL;
350 static const GOptionEntry connection_entries[] =
352 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
353 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
354 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
358 static GOptionGroup *
359 connection_get_group (void)
361 static GOptionGroup *g;
363 g = g_option_group_new ("connection",
364 N_("Connection Endpoint Options:"),
365 N_("Options specifying the connection endpoint"),
368 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
369 g_option_group_add_entries (g, connection_entries);
374 static GDBusConnection *
375 connection_get_dbus_connection (GError **error)
381 /* First, ensure we have exactly one connect */
382 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
387 _("No connection endpoint specified"));
390 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
391 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
392 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
397 _("Multiple connection endpoints specified"));
401 if (opt_connection_system)
403 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
405 else if (opt_connection_session)
407 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
409 else if (opt_connection_address != NULL)
411 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
412 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
413 NULL, /* GDBusAuthObserver */
414 NULL, /* GCancellable */
422 /* ---------------------------------------------------------------------------------------------------- */
425 call_helper_get_method_in_signature (GDBusConnection *c,
428 const gchar *interface_name,
429 const gchar *method_name,
434 GDBusNodeInfo *node_info;
435 const gchar *xml_data;
436 GDBusInterfaceInfo *interface_info;
437 GDBusMethodInfo *method_info;
444 result = g_dbus_connection_call_sync (c,
447 "org.freedesktop.DBus.Introspectable",
450 G_VARIANT_TYPE ("(s)"),
451 G_DBUS_CALL_FLAGS_NONE,
458 g_variant_get (result, "(&s)", &xml_data);
459 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
460 if (node_info == NULL)
463 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
464 if (interface_info == NULL)
466 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
467 _("Warning: According to introspection data, interface '%s' does not exist\n"),
472 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
473 if (method_info == NULL)
475 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
476 _("Warning: According to introspection data, method '%s' does not exist on interface '%s'\n"),
482 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
483 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
485 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
489 if (node_info != NULL)
490 g_dbus_node_info_unref (node_info);
492 g_variant_unref (result);
497 /* ---------------------------------------------------------------------------------------------------- */
500 _g_variant_parse_me_harder (GVariantType *type,
501 const gchar *given_str,
509 str = g_string_new ("\"");
510 for (n = 0; given_str[n] != '\0'; n++)
512 if (G_UNLIKELY (given_str[n] == '\"'))
513 g_string_append (str, "\\\"");
515 g_string_append_c (str, given_str[n]);
517 g_string_append_c (str, '"');
518 s = g_string_free (str, FALSE);
520 value = g_variant_parse (type,
530 /* ---------------------------------------------------------------------------------------------------- */
532 static gchar *opt_emit_dest = NULL;
533 static gchar *opt_emit_object_path = NULL;
534 static gchar *opt_emit_signal = NULL;
536 static const GOptionEntry emit_entries[] =
538 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
539 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
540 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
545 handle_emit (gint *argc,
547 gboolean request_completion,
548 const gchar *completion_cur,
549 const gchar *completion_prev)
556 GVariant *parameters;
557 gchar *interface_name;
559 GVariantBuilder builder;
565 interface_name = NULL;
568 modify_argv0_for_command (argc, argv, "emit");
570 o = g_option_context_new (NULL);
571 g_option_context_set_help_enabled (o, FALSE);
572 g_option_context_set_summary (o, _("Emit a signal."));
573 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
574 g_option_context_add_group (o, connection_get_group ());
576 if (!g_option_context_parse (o, argc, argv, NULL))
578 if (!request_completion)
580 s = g_option_context_get_help (o, FALSE, NULL);
581 g_printerr ("%s", s);
588 c = connection_get_dbus_connection (&error);
591 if (request_completion)
593 if (g_strcmp0 (completion_prev, "--address") == 0)
601 g_print ("--system \n--session \n--address \n");
606 g_printerr (_("Error connecting: %s\n"), error->message);
607 g_error_free (error);
612 /* All done with completion now */
613 if (request_completion)
616 if (opt_emit_object_path == NULL)
618 g_printerr (_("Error: object path not specified.\n"));
621 if (!g_variant_is_object_path (opt_emit_object_path))
623 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
627 if (opt_emit_signal == NULL)
629 g_printerr (_("Error: signal not specified.\n"));
633 s = strrchr (opt_emit_signal, '.');
636 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
639 signal_name = g_strdup (s + 1);
640 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
642 if (!g_dbus_is_interface_name (interface_name))
644 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
648 if (!g_dbus_is_member_name (signal_name))
650 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
654 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
656 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
660 /* Read parameters */
661 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
662 for (n = 1; n < (guint) *argc; n++)
667 value = g_variant_parse (NULL,
676 context = g_variant_parse_error_print_context (error, (*argv)[n]);
677 g_error_free (error);
679 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
682 /* Use the original non-"parse-me-harder" error */
683 g_printerr (_("Error parsing parameter %d: %s\n"),
686 g_error_free (error);
688 g_variant_builder_clear (&builder);
693 g_variant_builder_add_value (&builder, value);
695 parameters = g_variant_builder_end (&builder);
697 if (parameters != NULL)
698 parameters = g_variant_ref_sink (parameters);
699 if (!g_dbus_connection_emit_signal (c,
701 opt_emit_object_path,
707 g_printerr (_("Error: %s\n"), error->message);
708 g_error_free (error);
712 if (!g_dbus_connection_flush_sync (c, NULL, &error))
714 g_printerr (_("Error flushing connection: %s\n"), error->message);
715 g_error_free (error);
724 if (parameters != NULL)
725 g_variant_unref (parameters);
726 g_free (interface_name);
727 g_free (signal_name);
728 g_option_context_free (o);
732 /* ---------------------------------------------------------------------------------------------------- */
734 static gchar *opt_call_dest = NULL;
735 static gchar *opt_call_object_path = NULL;
736 static gchar *opt_call_method = NULL;
737 static gint opt_call_timeout = -1;
739 static const GOptionEntry call_entries[] =
741 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
742 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
743 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
744 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
749 handle_call (gint *argc,
751 gboolean request_completion,
752 const gchar *completion_cur,
753 const gchar *completion_prev)
760 GVariant *parameters;
761 gchar *interface_name;
764 GPtrArray *in_signature_types;
765 gboolean complete_names;
766 gboolean complete_paths;
767 gboolean complete_methods;
768 GVariantBuilder builder;
774 interface_name = NULL;
777 in_signature_types = NULL;
779 modify_argv0_for_command (argc, argv, "call");
781 o = g_option_context_new (NULL);
782 g_option_context_set_help_enabled (o, FALSE);
783 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
784 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
785 g_option_context_add_group (o, connection_get_group ());
787 complete_names = FALSE;
788 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
790 complete_names = TRUE;
791 remove_arg ((*argc) - 1, argc, argv);
794 complete_paths = FALSE;
795 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
797 complete_paths = TRUE;
798 remove_arg ((*argc) - 1, argc, argv);
801 complete_methods = FALSE;
802 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
804 complete_methods = TRUE;
805 remove_arg ((*argc) - 1, argc, argv);
808 if (!g_option_context_parse (o, argc, argv, NULL))
810 if (!request_completion)
812 s = g_option_context_get_help (o, FALSE, NULL);
813 g_printerr ("%s", s);
820 c = connection_get_dbus_connection (&error);
823 if (request_completion)
825 if (g_strcmp0 (completion_prev, "--address") == 0)
833 g_print ("--system \n--session \n--address \n");
838 g_printerr (_("Error connecting: %s\n"), error->message);
839 g_error_free (error);
844 /* validate and complete destination (bus name) */
845 if (g_dbus_connection_get_unique_name (c) != NULL)
847 /* this only makes sense on message bus connections */
850 print_names (c, FALSE);
853 if (opt_call_dest == NULL)
855 if (request_completion)
856 g_print ("--dest \n");
858 g_printerr (_("Error: Destination is not specified\n"));
861 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
863 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
868 /* validate and complete object path */
871 print_paths (c, opt_call_dest, "/");
874 if (opt_call_object_path == NULL)
876 if (request_completion)
877 g_print ("--object-path \n");
879 g_printerr (_("Error: Object path is not specified\n"));
882 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
885 s = g_strdup (opt_call_object_path);
886 p = strrchr (s, '/');
893 print_paths (c, opt_call_dest, s);
897 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
899 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
903 /* validate and complete method (interface + method name) */
904 if (complete_methods)
906 print_methods (c, opt_call_dest, opt_call_object_path);
909 if (opt_call_method == NULL)
911 if (request_completion)
912 g_print ("--method \n");
914 g_printerr (_("Error: Method name is not specified\n"));
917 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
919 print_methods (c, opt_call_dest, opt_call_object_path);
922 s = strrchr (opt_call_method, '.');
923 if (!request_completion && s == NULL)
925 g_printerr (_("Error: Method name '%s' is invalid\n"), opt_call_method);
928 method_name = g_strdup (s + 1);
929 interface_name = g_strndup (opt_call_method, s - opt_call_method);
931 /* All done with completion now */
932 if (request_completion)
935 /* Introspect, for easy conversion - it's not fatal if we can't do this */
936 in_signature_types = call_helper_get_method_in_signature (c,
938 opt_call_object_path,
942 if (in_signature_types == NULL)
944 //g_printerr ("Error getting introspection data: %s\n", error->message);
945 g_error_free (error);
949 /* Read parameters */
950 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
951 for (n = 1; n < (guint) *argc; n++)
957 if (in_signature_types != NULL)
959 if (n - 1 >= in_signature_types->len)
961 /* Only warn for the first param */
962 if (n - 1 == in_signature_types->len)
964 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
965 in_signature_types->len);
970 type = in_signature_types->pdata[n - 1];
975 value = g_variant_parse (type,
984 context = g_variant_parse_error_print_context (error, (*argv)[n]);
985 g_error_free (error);
987 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
992 s = g_variant_type_dup_string (type);
993 g_printerr (_("Error parsing parameter %d of type '%s': %s\n"),
1001 g_printerr (_("Error parsing parameter %d: %s\n"),
1005 g_error_free (error);
1006 g_variant_builder_clear (&builder);
1012 g_variant_builder_add_value (&builder, value);
1014 parameters = g_variant_builder_end (&builder);
1016 if (parameters != NULL)
1017 parameters = g_variant_ref_sink (parameters);
1018 result = g_dbus_connection_call_sync (c,
1020 opt_call_object_path,
1025 G_DBUS_CALL_FLAGS_NONE,
1026 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1033 g_printerr (_("Error: %s\n"), error->message);
1034 g_error_free (error);
1036 if (in_signature_types != NULL)
1039 s = g_string_new (NULL);
1040 for (n = 0; n < in_signature_types->len; n++)
1042 GVariantType *type = in_signature_types->pdata[n];
1043 g_string_append_len (s,
1044 g_variant_type_peek_string (type),
1045 g_variant_type_get_string_length (type));
1047 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1048 g_string_free (s, TRUE);
1053 s = g_variant_print (result, TRUE);
1054 g_print ("%s\n", s);
1060 if (in_signature_types != NULL)
1061 g_ptr_array_unref (in_signature_types);
1063 g_variant_unref (result);
1066 if (parameters != NULL)
1067 g_variant_unref (parameters);
1068 g_free (interface_name);
1069 g_free (method_name);
1070 g_option_context_free (o);
1074 /* ---------------------------------------------------------------------------------------------------- */
1076 static gchar *opt_introspect_dest = NULL;
1077 static gchar *opt_introspect_object_path = NULL;
1078 static gboolean opt_introspect_xml = FALSE;
1079 static gboolean opt_introspect_recurse = FALSE;
1080 static gboolean opt_introspect_only_properties = FALSE;
1083 dump_annotation (const GDBusAnnotationInfo *o,
1085 gboolean ignore_indent)
1088 g_print ("%*s@%s(\"%s\")\n",
1089 ignore_indent ? 0 : indent, "",
1092 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1093 dump_annotation (o->annotations[n], indent + 2, FALSE);
1097 dump_arg (const GDBusArgInfo *o,
1099 const gchar *direction,
1100 gboolean ignore_indent,
1101 gboolean include_newline)
1105 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1107 dump_annotation (o->annotations[n], indent, ignore_indent);
1108 ignore_indent = FALSE;
1111 g_print ("%*s%s%s %s%s",
1112 ignore_indent ? 0 : indent, "",
1116 include_newline ? ",\n" : "");
1120 count_args (GDBusArgInfo **args)
1126 while (args[n] != NULL)
1133 dump_method (const GDBusMethodInfo *o,
1139 guint total_num_args;
1141 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1142 dump_annotation (o->annotations[n], indent, FALSE);
1144 g_print ("%*s%s(", indent, "", o->name);
1145 name_len = strlen (o->name);
1146 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1147 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1149 gboolean ignore_indent = (m == 0);
1150 gboolean include_newline = (m != total_num_args - 1);
1152 dump_arg (o->in_args[n],
1153 indent + name_len + 1,
1158 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1160 gboolean ignore_indent = (m == 0);
1161 gboolean include_newline = (m != total_num_args - 1);
1162 dump_arg (o->out_args[n],
1163 indent + name_len + 1,
1172 dump_signal (const GDBusSignalInfo *o,
1177 guint total_num_args;
1179 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1180 dump_annotation (o->annotations[n], indent, FALSE);
1182 g_print ("%*s%s(", indent, "", o->name);
1183 name_len = strlen (o->name);
1184 total_num_args = count_args (o->args);
1185 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1187 gboolean ignore_indent = (n == 0);
1188 gboolean include_newline = (n != total_num_args - 1);
1189 dump_arg (o->args[n],
1190 indent + name_len + 1,
1199 dump_property (const GDBusPropertyInfo *o,
1203 const gchar *access;
1206 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1207 access = "readonly";
1208 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1209 access = "writeonly";
1210 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1211 access = "readwrite";
1213 g_assert_not_reached ();
1215 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1216 dump_annotation (o->annotations[n], indent, FALSE);
1220 gchar *s = g_variant_print (value, FALSE);
1221 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1226 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1231 dump_interface (GDBusConnection *c,
1233 const GDBusInterfaceInfo *o,
1235 const gchar *object_path)
1238 GHashTable *properties;
1240 properties = g_hash_table_new_full (g_str_hash,
1243 (GDestroyNotify) g_variant_unref);
1245 /* Try to get properties */
1246 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1249 result = g_dbus_connection_call_sync (c,
1252 "org.freedesktop.DBus.Properties",
1254 g_variant_new ("(s)", o->name),
1256 G_DBUS_CALL_FLAGS_NONE,
1262 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1266 g_variant_get (result,
1269 while ((item = g_variant_iter_next_value (iter)))
1273 g_variant_get (item,
1278 g_hash_table_insert (properties, key, g_variant_ref (value));
1281 g_variant_unref (result);
1286 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1288 result = g_dbus_connection_call_sync (c,
1291 "org.freedesktop.DBus.Properties",
1293 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1294 G_VARIANT_TYPE ("(v)"),
1295 G_DBUS_CALL_FLAGS_NONE,
1301 GVariant *property_value;
1302 g_variant_get (result,
1305 g_hash_table_insert (properties,
1306 g_strdup (o->properties[n]->name),
1307 g_variant_ref (property_value));
1308 g_variant_unref (result);
1314 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1315 dump_annotation (o->annotations[n], indent, FALSE);
1317 g_print ("%*sinterface %s {\n", indent, "", o->name);
1318 if (o->methods != NULL && !opt_introspect_only_properties)
1320 g_print ("%*s methods:\n", indent, "");
1321 for (n = 0; o->methods[n] != NULL; n++)
1322 dump_method (o->methods[n], indent + 4);
1324 if (o->signals != NULL && !opt_introspect_only_properties)
1326 g_print ("%*s signals:\n", indent, "");
1327 for (n = 0; o->signals[n] != NULL; n++)
1328 dump_signal (o->signals[n], indent + 4);
1330 if (o->properties != NULL)
1332 g_print ("%*s properties:\n", indent, "");
1333 for (n = 0; o->properties[n] != NULL; n++)
1335 dump_property (o->properties[n],
1337 g_hash_table_lookup (properties, (o->properties[n])->name));
1343 g_hash_table_unref (properties);
1347 introspect_do (GDBusConnection *c,
1348 const gchar *object_path,
1352 dump_node (GDBusConnection *c,
1354 const GDBusNodeInfo *o,
1356 const gchar *object_path,
1360 const gchar *object_path_to_print;
1362 object_path_to_print = object_path;
1363 if (o->path != NULL)
1364 object_path_to_print = o->path;
1366 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1367 dump_annotation (o->annotations[n], indent, FALSE);
1369 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1370 if (o->interfaces != NULL || o->nodes != NULL)
1373 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1375 if (opt_introspect_only_properties)
1377 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1378 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1382 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1385 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1390 if (g_variant_is_object_path (o->nodes[n]->path))
1392 child_path = g_strdup (o->nodes[n]->path);
1393 /* avoid infinite loops */
1394 if (g_str_has_prefix (child_path, object_path))
1396 introspect_do (c, child_path, indent + 2);
1400 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1401 child_path, object_path);
1406 if (g_strcmp0 (object_path, "/") == 0)
1407 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1409 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1410 introspect_do (c, child_path, indent + 2);
1412 g_free (child_path);
1416 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1428 static const GOptionEntry introspect_entries[] =
1430 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1431 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1432 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1433 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1434 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1439 introspect_do (GDBusConnection *c,
1440 const gchar *object_path,
1445 GDBusNodeInfo *node;
1447 const gchar *xml_data;
1454 result = g_dbus_connection_call_sync (c,
1455 opt_introspect_dest,
1457 "org.freedesktop.DBus.Introspectable",
1460 G_VARIANT_TYPE ("(s)"),
1461 G_DBUS_CALL_FLAGS_NONE,
1467 g_printerr (_("Error: %s\n"), error->message);
1468 g_error_free (error);
1471 g_variant_get (result, "(&s)", &xml_data);
1473 if (opt_introspect_xml)
1475 g_print ("%s", xml_data);
1480 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1483 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1484 g_error_free (error);
1488 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1495 g_dbus_node_info_unref (node);
1497 g_variant_unref (result);
1502 handle_introspect (gint *argc,
1504 gboolean request_completion,
1505 const gchar *completion_cur,
1506 const gchar *completion_prev)
1513 gboolean complete_names;
1514 gboolean complete_paths;
1519 modify_argv0_for_command (argc, argv, "introspect");
1521 o = g_option_context_new (NULL);
1522 if (request_completion)
1523 g_option_context_set_ignore_unknown_options (o, TRUE);
1524 g_option_context_set_help_enabled (o, FALSE);
1525 g_option_context_set_summary (o, _("Introspect a remote object."));
1526 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1527 g_option_context_add_group (o, connection_get_group ());
1529 complete_names = FALSE;
1530 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1532 complete_names = TRUE;
1533 remove_arg ((*argc) - 1, argc, argv);
1536 complete_paths = FALSE;
1537 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1539 complete_paths = TRUE;
1540 remove_arg ((*argc) - 1, argc, argv);
1543 if (!g_option_context_parse (o, argc, argv, NULL))
1545 if (!request_completion)
1547 s = g_option_context_get_help (o, FALSE, NULL);
1548 g_printerr ("%s", s);
1555 c = connection_get_dbus_connection (&error);
1558 if (request_completion)
1560 if (g_strcmp0 (completion_prev, "--address") == 0)
1568 g_print ("--system \n--session \n--address \n");
1573 g_printerr (_("Error connecting: %s\n"), error->message);
1574 g_error_free (error);
1579 if (g_dbus_connection_get_unique_name (c) != NULL)
1583 print_names (c, FALSE);
1586 /* this only makes sense on message bus connections */
1587 if (opt_introspect_dest == NULL)
1589 if (request_completion)
1590 g_print ("--dest \n");
1592 g_printerr (_("Error: Destination is not specified\n"));
1595 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1597 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1603 print_paths (c, opt_introspect_dest, "/");
1606 if (opt_introspect_object_path == NULL)
1608 if (request_completion)
1609 g_print ("--object-path \n");
1611 g_printerr (_("Error: Object path is not specified\n"));
1614 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1617 s = g_strdup (opt_introspect_object_path);
1618 p = strrchr (s, '/');
1625 print_paths (c, opt_introspect_dest, s);
1629 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1631 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1635 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1637 g_print ("--recurse \n");
1640 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1642 g_print ("--only-properties \n");
1645 /* All done with completion now */
1646 if (request_completion)
1649 if (!introspect_do (c, opt_introspect_object_path, 0))
1657 g_option_context_free (o);
1661 /* ---------------------------------------------------------------------------------------------------- */
1663 static gchar *opt_monitor_dest = NULL;
1664 static gchar *opt_monitor_object_path = NULL;
1666 static guint monitor_filter_id = 0;
1669 monitor_signal_cb (GDBusConnection *connection,
1670 const gchar *sender_name,
1671 const gchar *object_path,
1672 const gchar *interface_name,
1673 const gchar *signal_name,
1674 GVariant *parameters,
1678 s = g_variant_print (parameters, TRUE);
1679 g_print ("%s: %s.%s %s\n",
1688 monitor_on_name_appeared (GDBusConnection *connection,
1690 const gchar *name_owner,
1693 g_print ("The name %s is owned by %s\n", name, name_owner);
1694 g_assert (monitor_filter_id == 0);
1695 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1697 NULL, /* any interface */
1698 NULL, /* any member */
1699 opt_monitor_object_path,
1701 G_DBUS_SIGNAL_FLAGS_NONE,
1703 NULL, /* user_data */
1704 NULL); /* user_data destroy notify */
1708 monitor_on_name_vanished (GDBusConnection *connection,
1712 g_print ("The name %s does not have an owner\n", name);
1714 if (monitor_filter_id != 0)
1716 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1717 monitor_filter_id = 0;
1721 static const GOptionEntry monitor_entries[] =
1723 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1724 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1729 handle_monitor (gint *argc,
1731 gboolean request_completion,
1732 const gchar *completion_cur,
1733 const gchar *completion_prev)
1741 GDBusNodeInfo *node;
1742 gboolean complete_names;
1743 gboolean complete_paths;
1751 modify_argv0_for_command (argc, argv, "monitor");
1753 o = g_option_context_new (NULL);
1754 if (request_completion)
1755 g_option_context_set_ignore_unknown_options (o, TRUE);
1756 g_option_context_set_help_enabled (o, FALSE);
1757 g_option_context_set_summary (o, _("Monitor a remote object."));
1758 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1759 g_option_context_add_group (o, connection_get_group ());
1761 complete_names = FALSE;
1762 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1764 complete_names = TRUE;
1765 remove_arg ((*argc) - 1, argc, argv);
1768 complete_paths = FALSE;
1769 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1771 complete_paths = TRUE;
1772 remove_arg ((*argc) - 1, argc, argv);
1775 if (!g_option_context_parse (o, argc, argv, NULL))
1777 if (!request_completion)
1779 s = g_option_context_get_help (o, FALSE, NULL);
1780 g_printerr ("%s", s);
1787 c = connection_get_dbus_connection (&error);
1790 if (request_completion)
1792 if (g_strcmp0 (completion_prev, "--address") == 0)
1800 g_print ("--system \n--session \n--address \n");
1805 g_printerr (_("Error connecting: %s\n"), error->message);
1806 g_error_free (error);
1811 if (g_dbus_connection_get_unique_name (c) != NULL)
1815 print_names (c, FALSE);
1818 /* this only makes sense on message bus connections */
1819 if (opt_monitor_dest == NULL)
1821 if (request_completion)
1822 g_print ("--dest \n");
1824 g_printerr (_("Error: Destination is not specified\n"));
1827 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1829 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1835 print_paths (c, opt_monitor_dest, "/");
1838 if (opt_monitor_object_path == NULL)
1840 if (request_completion)
1842 g_print ("--object-path \n");
1845 /* it's fine to not have an object path */
1847 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1850 s = g_strdup (opt_monitor_object_path);
1851 p = strrchr (s, '/');
1858 print_paths (c, opt_monitor_dest, s);
1862 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1864 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1868 /* All done with completion now */
1869 if (request_completion)
1872 if (opt_monitor_object_path != NULL)
1873 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1875 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1877 loop = g_main_loop_new (NULL, FALSE);
1878 g_bus_watch_name_on_connection (c,
1880 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1881 monitor_on_name_appeared,
1882 monitor_on_name_vanished,
1886 g_main_loop_run (loop);
1887 g_main_loop_unref (loop);
1893 g_dbus_node_info_unref (node);
1895 g_variant_unref (result);
1898 g_option_context_free (o);
1902 /* ---------------------------------------------------------------------------------------------------- */
1905 pick_word_at (const gchar *s,
1907 gint *out_word_begins_at)
1914 if (out_word_begins_at != NULL)
1915 *out_word_begins_at = -1;
1919 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1921 if (out_word_begins_at != NULL)
1922 *out_word_begins_at = cursor;
1923 return g_strdup ("");
1926 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1931 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1934 if (out_word_begins_at != NULL)
1935 *out_word_begins_at = begin;
1937 return g_strndup (s + begin, end - begin);
1941 main (gint argc, gchar *argv[])
1944 const gchar *command;
1945 gboolean request_completion;
1946 gchar *completion_cur;
1947 gchar *completion_prev;
1952 setlocale (LC_ALL, "");
1953 textdomain (GETTEXT_PACKAGE);
1956 tmp = _glib_get_locale_dir ();
1957 bindtextdomain (GETTEXT_PACKAGE, tmp);
1960 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1963 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1964 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1968 completion_cur = NULL;
1969 completion_prev = NULL;
1973 usage (&argc, &argv, FALSE);
1977 request_completion = FALSE;
1979 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1983 if (g_strcmp0 (command, "help") == 0)
1985 if (request_completion)
1991 usage (&argc, &argv, TRUE);
1996 else if (g_strcmp0 (command, "emit") == 0)
1998 if (handle_emit (&argc,
2006 else if (g_strcmp0 (command, "call") == 0)
2008 if (handle_call (&argc,
2016 else if (g_strcmp0 (command, "introspect") == 0)
2018 if (handle_introspect (&argc,
2026 else if (g_strcmp0 (command, "monitor") == 0)
2028 if (handle_monitor (&argc,
2036 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2038 const gchar *completion_line;
2039 gchar **completion_argv;
2040 gint completion_argc;
2041 gint completion_point;
2045 request_completion = TRUE;
2047 completion_line = argv[2];
2048 completion_point = strtol (argv[3], &endp, 10);
2049 if (endp == argv[3] || *endp != '\0')
2053 completion_debug ("completion_point=%d", completion_point);
2054 completion_debug ("----");
2055 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2056 completion_debug ("'%s'", completion_line);
2057 completion_debug (" %*s^",
2058 completion_point, "");
2059 completion_debug ("----");
2062 if (!g_shell_parse_argv (completion_line,
2067 /* it's very possible the command line can't be parsed (for
2068 * example, missing quotes etc) - in that case, we just
2069 * don't autocomplete at all
2074 /* compute cur and prev */
2075 completion_prev = NULL;
2076 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2080 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2082 if (!g_ascii_isspace (completion_line[prev_end]))
2084 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2090 completion_debug (" cur='%s'", completion_cur);
2091 completion_debug ("prev='%s'", completion_prev);
2094 argc = completion_argc;
2095 argv = completion_argv;
2103 if (request_completion)
2105 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2111 g_printerr ("Unknown command '%s'\n", command);
2112 usage (&argc, &argv, FALSE);
2118 g_free (completion_cur);
2119 g_free (completion_prev);