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, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
33 #include "glib/glib-private.h"
36 /* ---------------------------------------------------------------------------------------------------- */
38 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
40 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
41 * to not have it interfere with stdout/stderr)
44 G_GNUC_UNUSED static void
45 completion_debug (const gchar *format, ...)
49 static FILE *f = NULL;
51 va_start (var_args, format);
52 s = g_strdup_vprintf (format, var_args);
55 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
57 fprintf (f, "%s\n", s);
62 completion_debug (const gchar *format, ...)
67 /* ---------------------------------------------------------------------------------------------------- */
71 remove_arg (gint num, gint *argc, gchar **argv[])
75 g_assert (num <= (*argc));
77 for (n = num; (*argv)[n] != NULL; n++)
78 (*argv)[n] = (*argv)[n+1];
80 (*argc) = (*argc) - 1;
84 usage (gint *argc, gchar **argv[], gboolean use_stdout)
90 o = g_option_context_new (_("COMMAND"));
91 g_option_context_set_help_enabled (o, FALSE);
92 /* Ignore parsing result */
93 g_option_context_parse (o, argc, argv, NULL);
94 program_name = g_path_get_basename ((*argv)[0]);
95 s = g_strdup_printf (_("Commands:\n"
96 " help Shows this information\n"
97 " introspect Introspect a remote object\n"
98 " monitor Monitor a remote object\n"
99 " call Invoke a method on a remote object\n"
100 " emit Emit a signal\n"
102 "Use \"%s COMMAND --help\" to get help on each command.\n"),
104 g_free (program_name);
105 g_option_context_set_description (o, s);
107 s = g_option_context_get_help (o, FALSE, NULL);
111 g_printerr ("%s", s);
113 g_option_context_free (o);
117 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
123 * 1. get a g_set_prgname() ?; or
124 * 2. save old argv[0] and restore later
127 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
128 remove_arg (1, argc, argv);
130 program_name = g_path_get_basename ((*argv)[0]);
131 s = g_strdup_printf ("%s %s", (*argv)[0], command);
133 g_free (program_name);
136 /* ---------------------------------------------------------------------------------------------------- */
139 print_methods (GDBusConnection *c,
145 const gchar *xml_data;
151 result = g_dbus_connection_call_sync (c,
154 "org.freedesktop.DBus.Introspectable",
157 G_VARIANT_TYPE ("(s)"),
158 G_DBUS_CALL_FLAGS_NONE,
164 g_printerr (_("Error: %s\n"), error->message);
165 g_error_free (error);
168 g_variant_get (result, "(&s)", &xml_data);
171 node = g_dbus_node_info_new_for_xml (xml_data, &error);
172 g_variant_unref (result);
175 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
176 g_error_free (error);
180 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
182 const GDBusInterfaceInfo *iface = node->interfaces[n];
183 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
185 const GDBusMethodInfo *method = iface->methods[m];
186 g_print ("%s.%s \n", iface->name, method->name);
189 g_dbus_node_info_unref (node);
196 print_paths (GDBusConnection *c,
202 const gchar *xml_data;
207 result = g_dbus_connection_call_sync (c,
210 "org.freedesktop.DBus.Introspectable",
213 G_VARIANT_TYPE ("(s)"),
214 G_DBUS_CALL_FLAGS_NONE,
220 g_printerr (_("Error: %s\n"), error->message);
221 g_error_free (error);
224 g_variant_get (result, "(&s)", &xml_data);
226 //g_printerr ("xml='%s'", xml_data);
229 node = g_dbus_node_info_new_for_xml (xml_data, &error);
230 g_variant_unref (result);
233 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
234 g_error_free (error);
238 //g_printerr ("bar '%s'\n", path);
240 if (node->interfaces != NULL)
241 g_print ("%s \n", path);
243 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
247 //g_printerr ("foo '%s'\n", node->nodes[n].path);
249 if (g_strcmp0 (path, "/") == 0)
250 s = g_strdup_printf ("/%s", node->nodes[n]->path);
252 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
254 print_paths (c, name, s);
258 g_dbus_node_info_unref (node);
265 print_names (GDBusConnection *c,
266 gboolean include_unique_names)
271 GHashTable *name_set;
275 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
279 list_names = g_dbus_get_list_names (c, &error);
280 if (list_names == NULL)
282 g_printerr (_("Error: %s\n"), error->message);
283 g_error_free (error);
287 while (list_names[cnt])
288 g_hash_table_insert (name_set, g_strdup (list_names[cnt++]), NULL);
289 g_strfreev(list_names);
293 list_names = g_dbus_get_list_activatable_names (c, &error);
294 if (list_names == NULL)
296 g_printerr (_("Error: %s\n"), error->message);
297 g_error_free (error);
301 while (list_names[cnt])
302 g_hash_table_insert (name_set, g_strdup (list_names[cnt++]), NULL);
303 g_strfreev(list_names);
305 keys = g_hash_table_get_keys (name_set);
306 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
307 for (l = keys; l != NULL; l = l->next)
309 const gchar *name = l->data;
310 if (!include_unique_names && g_str_has_prefix (name, ":"))
313 g_print ("%s \n", name);
318 g_hash_table_unref (name_set);
321 /* ---------------------------------------------------------------------------------------------------- */
323 static gboolean opt_connection_system = FALSE;
324 static gboolean opt_connection_session = FALSE;
325 static gboolean opt_connection_user = FALSE;
326 static gboolean opt_connection_machine = FALSE;
327 static gchar *opt_connection_address = NULL;
329 static const GOptionEntry connection_entries[] =
331 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
332 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
333 { "machine", 'm', 0, G_OPTION_ARG_NONE, &opt_connection_machine, N_("Connect to the machine bus"), NULL},
334 { "user", 'u', 0, G_OPTION_ARG_NONE, &opt_connection_user, N_("Connect to the user bus"), NULL},
335 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
339 static GOptionGroup *
340 connection_get_group (void)
342 static GOptionGroup *g;
344 g = g_option_group_new ("connection",
345 N_("Connection Endpoint Options:"),
346 N_("Options specifying the connection endpoint"),
349 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
350 g_option_group_add_entries (g, connection_entries);
355 static GDBusConnection *
356 connection_get_dbus_connection (GError **error)
363 count = !!opt_connection_system +
364 !!opt_connection_session +
365 !!opt_connection_machine +
366 !!opt_connection_user +
367 !!opt_connection_address;
369 /* First, ensure we have exactly one connect */
375 _("No connection endpoint specified"));
383 _("Multiple connection endpoints specified"));
387 if (opt_connection_system)
389 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
391 else if (opt_connection_session)
393 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
395 else if (opt_connection_machine)
397 c = g_bus_get_sync (G_BUS_TYPE_MACHINE, NULL, error);
399 else if (opt_connection_user)
401 c = g_bus_get_sync (G_BUS_TYPE_USER, NULL, error);
403 else if (opt_connection_address != NULL)
405 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
406 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
407 NULL, /* GDBusAuthObserver */
408 NULL, /* GCancellable */
416 /* ---------------------------------------------------------------------------------------------------- */
419 call_helper_get_method_in_signature (GDBusConnection *c,
422 const gchar *interface_name,
423 const gchar *method_name,
428 GDBusNodeInfo *node_info;
429 const gchar *xml_data;
430 GDBusInterfaceInfo *interface_info;
431 GDBusMethodInfo *method_info;
438 result = g_dbus_connection_call_sync (c,
441 "org.freedesktop.DBus.Introspectable",
444 G_VARIANT_TYPE ("(s)"),
445 G_DBUS_CALL_FLAGS_NONE,
452 g_variant_get (result, "(&s)", &xml_data);
453 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
454 if (node_info == NULL)
457 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
458 if (interface_info == NULL)
460 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
461 _("Warning: According to introspection data, interface '%s' does not exist\n"),
466 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
467 if (method_info == NULL)
469 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
470 _("Warning: According to introspection data, method '%s' does not exist on interface '%s'\n"),
476 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
477 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
479 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
483 if (node_info != NULL)
484 g_dbus_node_info_unref (node_info);
486 g_variant_unref (result);
491 /* ---------------------------------------------------------------------------------------------------- */
494 _g_variant_parse_me_harder (GVariantType *type,
495 const gchar *given_str,
503 str = g_string_new ("\"");
504 for (n = 0; given_str[n] != '\0'; n++)
506 if (G_UNLIKELY (given_str[n] == '\"'))
507 g_string_append (str, "\\\"");
509 g_string_append_c (str, given_str[n]);
511 g_string_append_c (str, '"');
512 s = g_string_free (str, FALSE);
514 value = g_variant_parse (type,
524 /* ---------------------------------------------------------------------------------------------------- */
526 static gchar *opt_emit_dest = NULL;
527 static gchar *opt_emit_object_path = NULL;
528 static gchar *opt_emit_signal = NULL;
530 static const GOptionEntry emit_entries[] =
532 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
533 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
534 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
539 handle_emit (gint *argc,
541 gboolean request_completion,
542 const gchar *completion_cur,
543 const gchar *completion_prev)
550 GVariant *parameters;
551 gchar *interface_name;
553 GVariantBuilder builder;
559 interface_name = NULL;
562 modify_argv0_for_command (argc, argv, "emit");
564 o = g_option_context_new (NULL);
565 g_option_context_set_help_enabled (o, FALSE);
566 g_option_context_set_summary (o, _("Emit a signal."));
567 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
568 g_option_context_add_group (o, connection_get_group ());
570 if (!g_option_context_parse (o, argc, argv, NULL))
572 if (!request_completion)
574 s = g_option_context_get_help (o, FALSE, NULL);
575 g_printerr ("%s", s);
582 c = connection_get_dbus_connection (&error);
585 if (request_completion)
587 if (g_strcmp0 (completion_prev, "--address") == 0)
595 g_print ("--system \n--session \n--machine \n--user \n--address \n");
600 g_printerr (_("Error connecting: %s\n"), error->message);
601 g_error_free (error);
606 /* All done with completion now */
607 if (request_completion)
610 if (opt_emit_object_path == NULL)
612 g_printerr (_("Error: object path not specified.\n"));
615 if (!g_variant_is_object_path (opt_emit_object_path))
617 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
621 if (opt_emit_signal == NULL)
623 g_printerr (_("Error: signal not specified.\n"));
627 s = strrchr (opt_emit_signal, '.');
630 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
633 signal_name = g_strdup (s + 1);
634 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
636 if (!g_dbus_is_interface_name (interface_name))
638 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
642 if (!g_dbus_is_member_name (signal_name))
644 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
648 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
650 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
654 /* Read parameters */
655 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
656 for (n = 1; n < (guint) *argc; n++)
661 value = g_variant_parse (NULL,
670 context = g_variant_parse_error_print_context (error, (*argv)[n]);
671 g_error_free (error);
673 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
676 /* Use the original non-"parse-me-harder" error */
677 g_printerr (_("Error parsing parameter %d: %s\n"),
680 g_error_free (error);
682 g_variant_builder_clear (&builder);
687 g_variant_builder_add_value (&builder, value);
689 parameters = g_variant_builder_end (&builder);
691 if (parameters != NULL)
692 parameters = g_variant_ref_sink (parameters);
693 if (!g_dbus_connection_emit_signal (c,
695 opt_emit_object_path,
701 g_printerr (_("Error: %s\n"), error->message);
702 g_error_free (error);
706 if (!g_dbus_connection_flush_sync (c, NULL, &error))
708 g_printerr (_("Error flushing connection: %s\n"), error->message);
709 g_error_free (error);
718 if (parameters != NULL)
719 g_variant_unref (parameters);
720 g_free (interface_name);
721 g_free (signal_name);
722 g_option_context_free (o);
726 /* ---------------------------------------------------------------------------------------------------- */
728 static gchar *opt_call_dest = NULL;
729 static gchar *opt_call_object_path = NULL;
730 static gchar *opt_call_method = NULL;
731 static gint opt_call_timeout = -1;
733 static const GOptionEntry call_entries[] =
735 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
736 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
737 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
738 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
743 handle_call (gint *argc,
745 gboolean request_completion,
746 const gchar *completion_cur,
747 const gchar *completion_prev)
754 GVariant *parameters;
755 gchar *interface_name;
758 GPtrArray *in_signature_types;
759 gboolean complete_names;
760 gboolean complete_paths;
761 gboolean complete_methods;
762 GVariantBuilder builder;
768 interface_name = NULL;
771 in_signature_types = NULL;
773 modify_argv0_for_command (argc, argv, "call");
775 o = g_option_context_new (NULL);
776 g_option_context_set_help_enabled (o, FALSE);
777 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
778 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
779 g_option_context_add_group (o, connection_get_group ());
781 complete_names = FALSE;
782 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
784 complete_names = TRUE;
785 remove_arg ((*argc) - 1, argc, argv);
788 complete_paths = FALSE;
789 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
791 complete_paths = TRUE;
792 remove_arg ((*argc) - 1, argc, argv);
795 complete_methods = FALSE;
796 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
798 complete_methods = TRUE;
799 remove_arg ((*argc) - 1, argc, argv);
802 if (!g_option_context_parse (o, argc, argv, NULL))
804 if (!request_completion)
806 s = g_option_context_get_help (o, FALSE, NULL);
807 g_printerr ("%s", s);
814 c = connection_get_dbus_connection (&error);
817 if (request_completion)
819 if (g_strcmp0 (completion_prev, "--address") == 0)
827 g_print ("--system \n--session \n--machine \n--user \n--address \n");
832 g_printerr (_("Error connecting: %s\n"), error->message);
833 g_error_free (error);
838 /* validate and complete destination (bus name) */
839 if (g_dbus_connection_get_unique_name (c) != NULL)
841 /* this only makes sense on message bus connections */
844 print_names (c, FALSE);
847 if (opt_call_dest == NULL)
849 if (request_completion)
850 g_print ("--dest \n");
852 g_printerr (_("Error: Destination is not specified\n"));
855 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
857 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
862 /* validate and complete object path */
865 print_paths (c, opt_call_dest, "/");
868 if (opt_call_object_path == NULL)
870 if (request_completion)
871 g_print ("--object-path \n");
873 g_printerr (_("Error: Object path is not specified\n"));
876 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
879 s = g_strdup (opt_call_object_path);
880 p = strrchr (s, '/');
887 print_paths (c, opt_call_dest, s);
891 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
893 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
897 /* validate and complete method (interface + method name) */
898 if (complete_methods)
900 print_methods (c, opt_call_dest, opt_call_object_path);
903 if (opt_call_method == NULL)
905 if (request_completion)
906 g_print ("--method \n");
908 g_printerr (_("Error: Method name is not specified\n"));
911 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
913 print_methods (c, opt_call_dest, opt_call_object_path);
916 s = strrchr (opt_call_method, '.');
917 if (!request_completion && s == NULL)
919 g_printerr (_("Error: Method name '%s' is invalid\n"), opt_call_method);
922 method_name = g_strdup (s + 1);
923 interface_name = g_strndup (opt_call_method, s - opt_call_method);
925 /* All done with completion now */
926 if (request_completion)
929 /* Introspect, for easy conversion - it's not fatal if we can't do this */
930 in_signature_types = call_helper_get_method_in_signature (c,
932 opt_call_object_path,
936 if (in_signature_types == NULL)
938 //g_printerr ("Error getting introspection data: %s\n", error->message);
939 g_error_free (error);
943 /* Read parameters */
944 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
945 for (n = 1; n < (guint) *argc; n++)
951 if (in_signature_types != NULL)
953 if (n - 1 >= in_signature_types->len)
955 /* Only warn for the first param */
956 if (n - 1 == in_signature_types->len)
958 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
959 in_signature_types->len);
964 type = in_signature_types->pdata[n - 1];
969 value = g_variant_parse (type,
978 context = g_variant_parse_error_print_context (error, (*argv)[n]);
979 g_error_free (error);
981 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
986 s = g_variant_type_dup_string (type);
987 g_printerr (_("Error parsing parameter %d of type '%s': %s\n"),
995 g_printerr (_("Error parsing parameter %d: %s\n"),
999 g_error_free (error);
1000 g_variant_builder_clear (&builder);
1006 g_variant_builder_add_value (&builder, value);
1008 parameters = g_variant_builder_end (&builder);
1010 if (parameters != NULL)
1011 parameters = g_variant_ref_sink (parameters);
1012 result = g_dbus_connection_call_sync (c,
1014 opt_call_object_path,
1019 G_DBUS_CALL_FLAGS_NONE,
1020 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1027 g_printerr (_("Error: %s\n"), error->message);
1028 g_error_free (error);
1030 if (in_signature_types != NULL)
1033 s = g_string_new (NULL);
1034 for (n = 0; n < in_signature_types->len; n++)
1036 GVariantType *type = in_signature_types->pdata[n];
1037 g_string_append_len (s,
1038 g_variant_type_peek_string (type),
1039 g_variant_type_get_string_length (type));
1041 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1042 g_string_free (s, TRUE);
1047 s = g_variant_print (result, TRUE);
1048 g_print ("%s\n", s);
1054 if (in_signature_types != NULL)
1055 g_ptr_array_unref (in_signature_types);
1057 g_variant_unref (result);
1060 if (parameters != NULL)
1061 g_variant_unref (parameters);
1062 g_free (interface_name);
1063 g_free (method_name);
1064 g_option_context_free (o);
1068 /* ---------------------------------------------------------------------------------------------------- */
1070 static gchar *opt_introspect_dest = NULL;
1071 static gchar *opt_introspect_object_path = NULL;
1072 static gboolean opt_introspect_xml = FALSE;
1073 static gboolean opt_introspect_recurse = FALSE;
1074 static gboolean opt_introspect_only_properties = FALSE;
1077 dump_annotation (const GDBusAnnotationInfo *o,
1079 gboolean ignore_indent)
1082 g_print ("%*s@%s(\"%s\")\n",
1083 ignore_indent ? 0 : indent, "",
1086 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1087 dump_annotation (o->annotations[n], indent + 2, FALSE);
1091 dump_arg (const GDBusArgInfo *o,
1093 const gchar *direction,
1094 gboolean ignore_indent,
1095 gboolean include_newline)
1099 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1101 dump_annotation (o->annotations[n], indent, ignore_indent);
1102 ignore_indent = FALSE;
1105 g_print ("%*s%s%s %s%s",
1106 ignore_indent ? 0 : indent, "",
1110 include_newline ? ",\n" : "");
1114 count_args (GDBusArgInfo **args)
1120 while (args[n] != NULL)
1127 dump_method (const GDBusMethodInfo *o,
1133 guint total_num_args;
1135 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1136 dump_annotation (o->annotations[n], indent, FALSE);
1138 g_print ("%*s%s(", indent, "", o->name);
1139 name_len = strlen (o->name);
1140 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1141 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1143 gboolean ignore_indent = (m == 0);
1144 gboolean include_newline = (m != total_num_args - 1);
1146 dump_arg (o->in_args[n],
1147 indent + name_len + 1,
1152 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1154 gboolean ignore_indent = (m == 0);
1155 gboolean include_newline = (m != total_num_args - 1);
1156 dump_arg (o->out_args[n],
1157 indent + name_len + 1,
1166 dump_signal (const GDBusSignalInfo *o,
1171 guint total_num_args;
1173 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1174 dump_annotation (o->annotations[n], indent, FALSE);
1176 g_print ("%*s%s(", indent, "", o->name);
1177 name_len = strlen (o->name);
1178 total_num_args = count_args (o->args);
1179 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1181 gboolean ignore_indent = (n == 0);
1182 gboolean include_newline = (n != total_num_args - 1);
1183 dump_arg (o->args[n],
1184 indent + name_len + 1,
1193 dump_property (const GDBusPropertyInfo *o,
1197 const gchar *access;
1200 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1201 access = "readonly";
1202 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1203 access = "writeonly";
1204 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1205 access = "readwrite";
1207 g_assert_not_reached ();
1209 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1210 dump_annotation (o->annotations[n], indent, FALSE);
1214 gchar *s = g_variant_print (value, FALSE);
1215 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1220 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1225 dump_interface (GDBusConnection *c,
1227 const GDBusInterfaceInfo *o,
1229 const gchar *object_path)
1232 GHashTable *properties;
1234 properties = g_hash_table_new_full (g_str_hash,
1237 (GDestroyNotify) g_variant_unref);
1239 /* Try to get properties */
1240 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1243 result = g_dbus_connection_call_sync (c,
1246 "org.freedesktop.DBus.Properties",
1248 g_variant_new ("(s)", o->name),
1250 G_DBUS_CALL_FLAGS_NONE,
1256 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1260 g_variant_get (result,
1263 while ((item = g_variant_iter_next_value (iter)))
1267 g_variant_get (item,
1272 g_hash_table_insert (properties, key, g_variant_ref (value));
1275 g_variant_unref (result);
1280 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1282 result = g_dbus_connection_call_sync (c,
1285 "org.freedesktop.DBus.Properties",
1287 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1288 G_VARIANT_TYPE ("(v)"),
1289 G_DBUS_CALL_FLAGS_NONE,
1295 GVariant *property_value;
1296 g_variant_get (result,
1299 g_hash_table_insert (properties,
1300 g_strdup (o->properties[n]->name),
1301 g_variant_ref (property_value));
1302 g_variant_unref (result);
1308 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1309 dump_annotation (o->annotations[n], indent, FALSE);
1311 g_print ("%*sinterface %s {\n", indent, "", o->name);
1312 if (o->methods != NULL && !opt_introspect_only_properties)
1314 g_print ("%*s methods:\n", indent, "");
1315 for (n = 0; o->methods[n] != NULL; n++)
1316 dump_method (o->methods[n], indent + 4);
1318 if (o->signals != NULL && !opt_introspect_only_properties)
1320 g_print ("%*s signals:\n", indent, "");
1321 for (n = 0; o->signals[n] != NULL; n++)
1322 dump_signal (o->signals[n], indent + 4);
1324 if (o->properties != NULL)
1326 g_print ("%*s properties:\n", indent, "");
1327 for (n = 0; o->properties[n] != NULL; n++)
1329 dump_property (o->properties[n],
1331 g_hash_table_lookup (properties, (o->properties[n])->name));
1337 g_hash_table_unref (properties);
1341 introspect_do (GDBusConnection *c,
1342 const gchar *object_path,
1346 dump_node (GDBusConnection *c,
1348 const GDBusNodeInfo *o,
1350 const gchar *object_path,
1354 const gchar *object_path_to_print;
1356 object_path_to_print = object_path;
1357 if (o->path != NULL)
1358 object_path_to_print = o->path;
1360 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1361 dump_annotation (o->annotations[n], indent, FALSE);
1363 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1364 if (o->interfaces != NULL || o->nodes != NULL)
1367 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1369 if (opt_introspect_only_properties)
1371 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1372 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1376 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1379 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1384 if (g_variant_is_object_path (o->nodes[n]->path))
1386 child_path = g_strdup (o->nodes[n]->path);
1387 /* avoid infinite loops */
1388 if (g_str_has_prefix (child_path, object_path))
1390 introspect_do (c, child_path, indent + 2);
1394 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1395 child_path, object_path);
1400 if (g_strcmp0 (object_path, "/") == 0)
1401 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1403 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1404 introspect_do (c, child_path, indent + 2);
1406 g_free (child_path);
1410 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1422 static const GOptionEntry introspect_entries[] =
1424 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1425 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1426 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1427 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1428 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1433 introspect_do (GDBusConnection *c,
1434 const gchar *object_path,
1439 GDBusNodeInfo *node;
1441 const gchar *xml_data;
1448 result = g_dbus_connection_call_sync (c,
1449 opt_introspect_dest,
1451 "org.freedesktop.DBus.Introspectable",
1454 G_VARIANT_TYPE ("(s)"),
1455 G_DBUS_CALL_FLAGS_NONE,
1461 g_printerr (_("Error: %s\n"), error->message);
1462 g_error_free (error);
1465 g_variant_get (result, "(&s)", &xml_data);
1467 if (opt_introspect_xml)
1469 g_print ("%s", xml_data);
1474 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1477 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1478 g_error_free (error);
1482 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1489 g_dbus_node_info_unref (node);
1491 g_variant_unref (result);
1496 handle_introspect (gint *argc,
1498 gboolean request_completion,
1499 const gchar *completion_cur,
1500 const gchar *completion_prev)
1507 gboolean complete_names;
1508 gboolean complete_paths;
1513 modify_argv0_for_command (argc, argv, "introspect");
1515 o = g_option_context_new (NULL);
1516 if (request_completion)
1517 g_option_context_set_ignore_unknown_options (o, TRUE);
1518 g_option_context_set_help_enabled (o, FALSE);
1519 g_option_context_set_summary (o, _("Introspect a remote object."));
1520 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1521 g_option_context_add_group (o, connection_get_group ());
1523 complete_names = FALSE;
1524 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1526 complete_names = TRUE;
1527 remove_arg ((*argc) - 1, argc, argv);
1530 complete_paths = FALSE;
1531 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1533 complete_paths = TRUE;
1534 remove_arg ((*argc) - 1, argc, argv);
1537 if (!g_option_context_parse (o, argc, argv, NULL))
1539 if (!request_completion)
1541 s = g_option_context_get_help (o, FALSE, NULL);
1542 g_printerr ("%s", s);
1549 c = connection_get_dbus_connection (&error);
1552 if (request_completion)
1554 if (g_strcmp0 (completion_prev, "--address") == 0)
1562 g_print ("--system \n--session \n--machine \n--user \n--address \n");
1567 g_printerr (_("Error connecting: %s\n"), error->message);
1568 g_error_free (error);
1573 if (g_dbus_connection_get_unique_name (c) != NULL)
1577 print_names (c, FALSE);
1580 /* this only makes sense on message bus connections */
1581 if (opt_introspect_dest == NULL)
1583 if (request_completion)
1584 g_print ("--dest \n");
1586 g_printerr (_("Error: Destination is not specified\n"));
1589 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1591 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1597 print_paths (c, opt_introspect_dest, "/");
1600 if (opt_introspect_object_path == NULL)
1602 if (request_completion)
1603 g_print ("--object-path \n");
1605 g_printerr (_("Error: Object path is not specified\n"));
1608 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1611 s = g_strdup (opt_introspect_object_path);
1612 p = strrchr (s, '/');
1619 print_paths (c, opt_introspect_dest, s);
1623 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1625 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1629 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1631 g_print ("--recurse \n");
1634 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1636 g_print ("--only-properties \n");
1639 /* All done with completion now */
1640 if (request_completion)
1643 if (!introspect_do (c, opt_introspect_object_path, 0))
1651 g_option_context_free (o);
1655 /* ---------------------------------------------------------------------------------------------------- */
1657 static gchar *opt_monitor_dest = NULL;
1658 static gchar *opt_monitor_object_path = NULL;
1660 static guint monitor_filter_id = 0;
1663 monitor_signal_cb (GDBusConnection *connection,
1664 const gchar *sender_name,
1665 const gchar *object_path,
1666 const gchar *interface_name,
1667 const gchar *signal_name,
1668 GVariant *parameters,
1672 s = g_variant_print (parameters, TRUE);
1673 g_print ("%s: %s.%s %s\n",
1682 monitor_on_name_appeared (GDBusConnection *connection,
1684 const gchar *name_owner,
1687 g_print ("The name %s is owned by %s\n", name, name_owner);
1688 g_assert (monitor_filter_id == 0);
1689 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1691 NULL, /* any interface */
1692 NULL, /* any member */
1693 opt_monitor_object_path,
1695 G_DBUS_SIGNAL_FLAGS_NONE,
1697 NULL, /* user_data */
1698 NULL); /* user_data destroy notify */
1702 monitor_on_name_vanished (GDBusConnection *connection,
1706 g_print ("The name %s does not have an owner\n", name);
1708 if (monitor_filter_id != 0)
1710 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1711 monitor_filter_id = 0;
1715 static const GOptionEntry monitor_entries[] =
1717 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1718 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1723 handle_monitor (gint *argc,
1725 gboolean request_completion,
1726 const gchar *completion_cur,
1727 const gchar *completion_prev)
1734 gboolean complete_names;
1735 gboolean complete_paths;
1741 modify_argv0_for_command (argc, argv, "monitor");
1743 o = g_option_context_new (NULL);
1744 if (request_completion)
1745 g_option_context_set_ignore_unknown_options (o, TRUE);
1746 g_option_context_set_help_enabled (o, FALSE);
1747 g_option_context_set_summary (o, _("Monitor a remote object."));
1748 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1749 g_option_context_add_group (o, connection_get_group ());
1751 complete_names = FALSE;
1752 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1754 complete_names = TRUE;
1755 remove_arg ((*argc) - 1, argc, argv);
1758 complete_paths = FALSE;
1759 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1761 complete_paths = TRUE;
1762 remove_arg ((*argc) - 1, argc, argv);
1765 if (!g_option_context_parse (o, argc, argv, NULL))
1767 if (!request_completion)
1769 s = g_option_context_get_help (o, FALSE, NULL);
1770 g_printerr ("%s", s);
1777 c = connection_get_dbus_connection (&error);
1780 if (request_completion)
1782 if (g_strcmp0 (completion_prev, "--address") == 0)
1790 g_print ("--system \n--session \n--machine \n--user \n--address \n");
1795 g_printerr (_("Error connecting: %s\n"), error->message);
1796 g_error_free (error);
1801 if (g_dbus_connection_get_unique_name (c) != NULL)
1805 print_names (c, FALSE);
1808 /* this only makes sense on message bus connections */
1809 if (opt_monitor_dest == NULL)
1811 if (request_completion)
1812 g_print ("--dest \n");
1814 g_printerr (_("Error: Destination is not specified\n"));
1817 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1819 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1825 print_paths (c, opt_monitor_dest, "/");
1828 if (opt_monitor_object_path == NULL)
1830 if (request_completion)
1832 g_print ("--object-path \n");
1835 /* it's fine to not have an object path */
1837 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1840 s = g_strdup (opt_monitor_object_path);
1841 p = strrchr (s, '/');
1848 print_paths (c, opt_monitor_dest, s);
1852 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1854 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1858 /* All done with completion now */
1859 if (request_completion)
1862 if (opt_monitor_object_path != NULL)
1863 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1865 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1867 loop = g_main_loop_new (NULL, FALSE);
1868 g_bus_watch_name_on_connection (c,
1870 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1871 monitor_on_name_appeared,
1872 monitor_on_name_vanished,
1876 g_main_loop_run (loop);
1877 g_main_loop_unref (loop);
1884 g_option_context_free (o);
1888 /* ---------------------------------------------------------------------------------------------------- */
1891 pick_word_at (const gchar *s,
1893 gint *out_word_begins_at)
1900 if (out_word_begins_at != NULL)
1901 *out_word_begins_at = -1;
1905 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1907 if (out_word_begins_at != NULL)
1908 *out_word_begins_at = cursor;
1909 return g_strdup ("");
1912 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1917 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1920 if (out_word_begins_at != NULL)
1921 *out_word_begins_at = begin;
1923 return g_strndup (s + begin, end - begin);
1927 main (gint argc, gchar *argv[])
1930 const gchar *command;
1931 gboolean request_completion;
1932 gchar *completion_cur;
1933 gchar *completion_prev;
1938 setlocale (LC_ALL, "");
1939 textdomain (GETTEXT_PACKAGE);
1942 tmp = _glib_get_locale_dir ();
1943 bindtextdomain (GETTEXT_PACKAGE, tmp);
1946 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1949 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1950 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1954 completion_cur = NULL;
1955 completion_prev = NULL;
1959 usage (&argc, &argv, FALSE);
1963 request_completion = FALSE;
1965 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1969 if (g_strcmp0 (command, "help") == 0)
1971 if (request_completion)
1977 usage (&argc, &argv, TRUE);
1982 else if (g_strcmp0 (command, "emit") == 0)
1984 if (handle_emit (&argc,
1992 else if (g_strcmp0 (command, "call") == 0)
1994 if (handle_call (&argc,
2002 else if (g_strcmp0 (command, "introspect") == 0)
2004 if (handle_introspect (&argc,
2012 else if (g_strcmp0 (command, "monitor") == 0)
2014 if (handle_monitor (&argc,
2022 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2024 const gchar *completion_line;
2025 gchar **completion_argv;
2026 gint completion_argc;
2027 gint completion_point;
2031 request_completion = TRUE;
2033 completion_line = argv[2];
2034 completion_point = strtol (argv[3], &endp, 10);
2035 if (endp == argv[3] || *endp != '\0')
2039 completion_debug ("completion_point=%d", completion_point);
2040 completion_debug ("----");
2041 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2042 completion_debug ("'%s'", completion_line);
2043 completion_debug (" %*s^",
2044 completion_point, "");
2045 completion_debug ("----");
2048 if (!g_shell_parse_argv (completion_line,
2053 /* it's very possible the command line can't be parsed (for
2054 * example, missing quotes etc) - in that case, we just
2055 * don't autocomplete at all
2060 /* compute cur and prev */
2061 completion_prev = NULL;
2062 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2066 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2068 if (!g_ascii_isspace (completion_line[prev_end]))
2070 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2076 completion_debug (" cur='%s'", completion_cur);
2077 completion_debug ("prev='%s'", completion_prev);
2080 argc = completion_argc;
2081 argv = completion_argv;
2089 if (request_completion)
2091 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2097 g_printerr ("Unknown command '%s'\n", command);
2098 usage (&argc, &argv, FALSE);
2104 g_free (completion_cur);
2105 g_free (completion_prev);