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)
272 GHashTable *name_set;
276 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
279 result = g_dbus_connection_call_sync (c,
280 "org.freedesktop.DBus",
281 "/org/freedesktop/DBus",
282 "org.freedesktop.DBus",
285 G_VARIANT_TYPE ("(as)"),
286 G_DBUS_CALL_FLAGS_NONE,
292 g_printerr (_("Error: %s\n"), error->message);
293 g_error_free (error);
296 g_variant_get (result, "(as)", &iter);
297 while (g_variant_iter_loop (iter, "s", &str))
298 g_hash_table_insert (name_set, g_strdup (str), NULL);
299 g_variant_iter_free (iter);
300 g_variant_unref (result);
303 result = g_dbus_connection_call_sync (c,
304 "org.freedesktop.DBus",
305 "/org/freedesktop/DBus",
306 "org.freedesktop.DBus",
307 "ListActivatableNames",
309 G_VARIANT_TYPE ("(as)"),
310 G_DBUS_CALL_FLAGS_NONE,
316 g_printerr (_("Error: %s\n"), error->message);
317 g_error_free (error);
320 g_variant_get (result, "(as)", &iter);
321 while (g_variant_iter_loop (iter, "s", &str))
322 g_hash_table_insert (name_set, g_strdup (str), NULL);
323 g_variant_iter_free (iter);
324 g_variant_unref (result);
326 keys = g_hash_table_get_keys (name_set);
327 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
328 for (l = keys; l != NULL; l = l->next)
330 const gchar *name = l->data;
331 if (!include_unique_names && g_str_has_prefix (name, ":"))
334 g_print ("%s \n", name);
339 g_hash_table_unref (name_set);
342 /* ---------------------------------------------------------------------------------------------------- */
344 static gboolean opt_connection_system = FALSE;
345 static gboolean opt_connection_session = FALSE;
346 static gboolean opt_connection_user = FALSE;
347 static gboolean opt_connection_machine = 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 { "machine", 'm', 0, G_OPTION_ARG_NONE, &opt_connection_machine, N_("Connect to the machine bus"), NULL},
355 { "user", 'u', 0, G_OPTION_ARG_NONE, &opt_connection_user, N_("Connect to the user bus"), NULL},
356 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
360 static GOptionGroup *
361 connection_get_group (void)
363 static GOptionGroup *g;
365 g = g_option_group_new ("connection",
366 N_("Connection Endpoint Options:"),
367 N_("Options specifying the connection endpoint"),
370 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
371 g_option_group_add_entries (g, connection_entries);
376 static GDBusConnection *
377 connection_get_dbus_connection (GError **error)
384 count = !!opt_connection_system +
385 !!opt_connection_session +
386 !!opt_connection_machine +
387 !!opt_connection_user +
388 !!opt_connection_address;
390 /* First, ensure we have exactly one connect */
396 _("No connection endpoint specified"));
404 _("Multiple connection endpoints specified"));
408 if (opt_connection_system)
410 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
412 else if (opt_connection_session)
414 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
416 else if (opt_connection_machine)
418 c = g_bus_get_sync (G_BUS_TYPE_MACHINE, NULL, error);
420 else if (opt_connection_user)
422 c = g_bus_get_sync (G_BUS_TYPE_USER, NULL, error);
424 else if (opt_connection_address != NULL)
426 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
427 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
428 NULL, /* GDBusAuthObserver */
429 NULL, /* GCancellable */
437 /* ---------------------------------------------------------------------------------------------------- */
440 call_helper_get_method_in_signature (GDBusConnection *c,
443 const gchar *interface_name,
444 const gchar *method_name,
449 GDBusNodeInfo *node_info;
450 const gchar *xml_data;
451 GDBusInterfaceInfo *interface_info;
452 GDBusMethodInfo *method_info;
459 result = g_dbus_connection_call_sync (c,
462 "org.freedesktop.DBus.Introspectable",
465 G_VARIANT_TYPE ("(s)"),
466 G_DBUS_CALL_FLAGS_NONE,
473 g_variant_get (result, "(&s)", &xml_data);
474 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
475 if (node_info == NULL)
478 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
479 if (interface_info == NULL)
481 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
482 _("Warning: According to introspection data, interface '%s' does not exist\n"),
487 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
488 if (method_info == NULL)
490 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
491 _("Warning: According to introspection data, method '%s' does not exist on interface '%s'\n"),
497 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
498 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
500 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
504 if (node_info != NULL)
505 g_dbus_node_info_unref (node_info);
507 g_variant_unref (result);
512 /* ---------------------------------------------------------------------------------------------------- */
515 _g_variant_parse_me_harder (GVariantType *type,
516 const gchar *given_str,
524 str = g_string_new ("\"");
525 for (n = 0; given_str[n] != '\0'; n++)
527 if (G_UNLIKELY (given_str[n] == '\"'))
528 g_string_append (str, "\\\"");
530 g_string_append_c (str, given_str[n]);
532 g_string_append_c (str, '"');
533 s = g_string_free (str, FALSE);
535 value = g_variant_parse (type,
545 /* ---------------------------------------------------------------------------------------------------- */
547 static gchar *opt_emit_dest = NULL;
548 static gchar *opt_emit_object_path = NULL;
549 static gchar *opt_emit_signal = NULL;
551 static const GOptionEntry emit_entries[] =
553 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
554 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
555 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
560 handle_emit (gint *argc,
562 gboolean request_completion,
563 const gchar *completion_cur,
564 const gchar *completion_prev)
571 GVariant *parameters;
572 gchar *interface_name;
574 GVariantBuilder builder;
580 interface_name = NULL;
583 modify_argv0_for_command (argc, argv, "emit");
585 o = g_option_context_new (NULL);
586 g_option_context_set_help_enabled (o, FALSE);
587 g_option_context_set_summary (o, _("Emit a signal."));
588 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
589 g_option_context_add_group (o, connection_get_group ());
591 if (!g_option_context_parse (o, argc, argv, NULL))
593 if (!request_completion)
595 s = g_option_context_get_help (o, FALSE, NULL);
596 g_printerr ("%s", s);
603 c = connection_get_dbus_connection (&error);
606 if (request_completion)
608 if (g_strcmp0 (completion_prev, "--address") == 0)
616 g_print ("--system \n--session \n--machine \n--user \n--address \n");
621 g_printerr (_("Error connecting: %s\n"), error->message);
622 g_error_free (error);
627 /* All done with completion now */
628 if (request_completion)
631 if (opt_emit_object_path == NULL)
633 g_printerr (_("Error: object path not specified.\n"));
636 if (!g_variant_is_object_path (opt_emit_object_path))
638 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
642 if (opt_emit_signal == NULL)
644 g_printerr (_("Error: signal not specified.\n"));
648 s = strrchr (opt_emit_signal, '.');
651 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
654 signal_name = g_strdup (s + 1);
655 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
657 if (!g_dbus_is_interface_name (interface_name))
659 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
663 if (!g_dbus_is_member_name (signal_name))
665 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
669 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
671 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
675 /* Read parameters */
676 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
677 for (n = 1; n < (guint) *argc; n++)
682 value = g_variant_parse (NULL,
691 context = g_variant_parse_error_print_context (error, (*argv)[n]);
692 g_error_free (error);
694 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
697 /* Use the original non-"parse-me-harder" error */
698 g_printerr (_("Error parsing parameter %d: %s\n"),
701 g_error_free (error);
703 g_variant_builder_clear (&builder);
708 g_variant_builder_add_value (&builder, value);
710 parameters = g_variant_builder_end (&builder);
712 if (parameters != NULL)
713 parameters = g_variant_ref_sink (parameters);
714 if (!g_dbus_connection_emit_signal (c,
716 opt_emit_object_path,
722 g_printerr (_("Error: %s\n"), error->message);
723 g_error_free (error);
727 if (!g_dbus_connection_flush_sync (c, NULL, &error))
729 g_printerr (_("Error flushing connection: %s\n"), error->message);
730 g_error_free (error);
739 if (parameters != NULL)
740 g_variant_unref (parameters);
741 g_free (interface_name);
742 g_free (signal_name);
743 g_option_context_free (o);
747 /* ---------------------------------------------------------------------------------------------------- */
749 static gchar *opt_call_dest = NULL;
750 static gchar *opt_call_object_path = NULL;
751 static gchar *opt_call_method = NULL;
752 static gint opt_call_timeout = -1;
754 static const GOptionEntry call_entries[] =
756 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
757 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
758 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
759 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
764 handle_call (gint *argc,
766 gboolean request_completion,
767 const gchar *completion_cur,
768 const gchar *completion_prev)
775 GVariant *parameters;
776 gchar *interface_name;
779 GPtrArray *in_signature_types;
780 gboolean complete_names;
781 gboolean complete_paths;
782 gboolean complete_methods;
783 GVariantBuilder builder;
789 interface_name = NULL;
792 in_signature_types = NULL;
794 modify_argv0_for_command (argc, argv, "call");
796 o = g_option_context_new (NULL);
797 g_option_context_set_help_enabled (o, FALSE);
798 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
799 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
800 g_option_context_add_group (o, connection_get_group ());
802 complete_names = FALSE;
803 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
805 complete_names = TRUE;
806 remove_arg ((*argc) - 1, argc, argv);
809 complete_paths = FALSE;
810 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
812 complete_paths = TRUE;
813 remove_arg ((*argc) - 1, argc, argv);
816 complete_methods = FALSE;
817 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
819 complete_methods = TRUE;
820 remove_arg ((*argc) - 1, argc, argv);
823 if (!g_option_context_parse (o, argc, argv, NULL))
825 if (!request_completion)
827 s = g_option_context_get_help (o, FALSE, NULL);
828 g_printerr ("%s", s);
835 c = connection_get_dbus_connection (&error);
838 if (request_completion)
840 if (g_strcmp0 (completion_prev, "--address") == 0)
848 g_print ("--system \n--session \n--machine \n--user \n--address \n");
853 g_printerr (_("Error connecting: %s\n"), error->message);
854 g_error_free (error);
859 /* validate and complete destination (bus name) */
860 if (g_dbus_connection_get_unique_name (c) != NULL)
862 /* this only makes sense on message bus connections */
865 print_names (c, FALSE);
868 if (opt_call_dest == NULL)
870 if (request_completion)
871 g_print ("--dest \n");
873 g_printerr (_("Error: Destination is not specified\n"));
876 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
878 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
883 /* validate and complete object path */
886 print_paths (c, opt_call_dest, "/");
889 if (opt_call_object_path == NULL)
891 if (request_completion)
892 g_print ("--object-path \n");
894 g_printerr (_("Error: Object path is not specified\n"));
897 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
900 s = g_strdup (opt_call_object_path);
901 p = strrchr (s, '/');
908 print_paths (c, opt_call_dest, s);
912 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
914 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
918 /* validate and complete method (interface + method name) */
919 if (complete_methods)
921 print_methods (c, opt_call_dest, opt_call_object_path);
924 if (opt_call_method == NULL)
926 if (request_completion)
927 g_print ("--method \n");
929 g_printerr (_("Error: Method name is not specified\n"));
932 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
934 print_methods (c, opt_call_dest, opt_call_object_path);
937 s = strrchr (opt_call_method, '.');
938 if (!request_completion && s == NULL)
940 g_printerr (_("Error: Method name '%s' is invalid\n"), opt_call_method);
943 method_name = g_strdup (s + 1);
944 interface_name = g_strndup (opt_call_method, s - opt_call_method);
946 /* All done with completion now */
947 if (request_completion)
950 /* Introspect, for easy conversion - it's not fatal if we can't do this */
951 in_signature_types = call_helper_get_method_in_signature (c,
953 opt_call_object_path,
957 if (in_signature_types == NULL)
959 //g_printerr ("Error getting introspection data: %s\n", error->message);
960 g_error_free (error);
964 /* Read parameters */
965 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
966 for (n = 1; n < (guint) *argc; n++)
972 if (in_signature_types != NULL)
974 if (n - 1 >= in_signature_types->len)
976 /* Only warn for the first param */
977 if (n - 1 == in_signature_types->len)
979 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
980 in_signature_types->len);
985 type = in_signature_types->pdata[n - 1];
990 value = g_variant_parse (type,
999 context = g_variant_parse_error_print_context (error, (*argv)[n]);
1000 g_error_free (error);
1002 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1007 s = g_variant_type_dup_string (type);
1008 g_printerr (_("Error parsing parameter %d of type '%s': %s\n"),
1016 g_printerr (_("Error parsing parameter %d: %s\n"),
1020 g_error_free (error);
1021 g_variant_builder_clear (&builder);
1027 g_variant_builder_add_value (&builder, value);
1029 parameters = g_variant_builder_end (&builder);
1031 if (parameters != NULL)
1032 parameters = g_variant_ref_sink (parameters);
1033 result = g_dbus_connection_call_sync (c,
1035 opt_call_object_path,
1040 G_DBUS_CALL_FLAGS_NONE,
1041 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1048 g_printerr (_("Error: %s\n"), error->message);
1049 g_error_free (error);
1051 if (in_signature_types != NULL)
1054 s = g_string_new (NULL);
1055 for (n = 0; n < in_signature_types->len; n++)
1057 GVariantType *type = in_signature_types->pdata[n];
1058 g_string_append_len (s,
1059 g_variant_type_peek_string (type),
1060 g_variant_type_get_string_length (type));
1062 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1063 g_string_free (s, TRUE);
1068 s = g_variant_print (result, TRUE);
1069 g_print ("%s\n", s);
1075 if (in_signature_types != NULL)
1076 g_ptr_array_unref (in_signature_types);
1078 g_variant_unref (result);
1081 if (parameters != NULL)
1082 g_variant_unref (parameters);
1083 g_free (interface_name);
1084 g_free (method_name);
1085 g_option_context_free (o);
1089 /* ---------------------------------------------------------------------------------------------------- */
1091 static gchar *opt_introspect_dest = NULL;
1092 static gchar *opt_introspect_object_path = NULL;
1093 static gboolean opt_introspect_xml = FALSE;
1094 static gboolean opt_introspect_recurse = FALSE;
1095 static gboolean opt_introspect_only_properties = FALSE;
1098 dump_annotation (const GDBusAnnotationInfo *o,
1100 gboolean ignore_indent)
1103 g_print ("%*s@%s(\"%s\")\n",
1104 ignore_indent ? 0 : indent, "",
1107 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1108 dump_annotation (o->annotations[n], indent + 2, FALSE);
1112 dump_arg (const GDBusArgInfo *o,
1114 const gchar *direction,
1115 gboolean ignore_indent,
1116 gboolean include_newline)
1120 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1122 dump_annotation (o->annotations[n], indent, ignore_indent);
1123 ignore_indent = FALSE;
1126 g_print ("%*s%s%s %s%s",
1127 ignore_indent ? 0 : indent, "",
1131 include_newline ? ",\n" : "");
1135 count_args (GDBusArgInfo **args)
1141 while (args[n] != NULL)
1148 dump_method (const GDBusMethodInfo *o,
1154 guint total_num_args;
1156 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1157 dump_annotation (o->annotations[n], indent, FALSE);
1159 g_print ("%*s%s(", indent, "", o->name);
1160 name_len = strlen (o->name);
1161 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1162 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1164 gboolean ignore_indent = (m == 0);
1165 gboolean include_newline = (m != total_num_args - 1);
1167 dump_arg (o->in_args[n],
1168 indent + name_len + 1,
1173 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1175 gboolean ignore_indent = (m == 0);
1176 gboolean include_newline = (m != total_num_args - 1);
1177 dump_arg (o->out_args[n],
1178 indent + name_len + 1,
1187 dump_signal (const GDBusSignalInfo *o,
1192 guint total_num_args;
1194 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1195 dump_annotation (o->annotations[n], indent, FALSE);
1197 g_print ("%*s%s(", indent, "", o->name);
1198 name_len = strlen (o->name);
1199 total_num_args = count_args (o->args);
1200 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1202 gboolean ignore_indent = (n == 0);
1203 gboolean include_newline = (n != total_num_args - 1);
1204 dump_arg (o->args[n],
1205 indent + name_len + 1,
1214 dump_property (const GDBusPropertyInfo *o,
1218 const gchar *access;
1221 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1222 access = "readonly";
1223 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1224 access = "writeonly";
1225 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1226 access = "readwrite";
1228 g_assert_not_reached ();
1230 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1231 dump_annotation (o->annotations[n], indent, FALSE);
1235 gchar *s = g_variant_print (value, FALSE);
1236 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1241 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1246 dump_interface (GDBusConnection *c,
1248 const GDBusInterfaceInfo *o,
1250 const gchar *object_path)
1253 GHashTable *properties;
1255 properties = g_hash_table_new_full (g_str_hash,
1258 (GDestroyNotify) g_variant_unref);
1260 /* Try to get properties */
1261 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1264 result = g_dbus_connection_call_sync (c,
1267 "org.freedesktop.DBus.Properties",
1269 g_variant_new ("(s)", o->name),
1271 G_DBUS_CALL_FLAGS_NONE,
1277 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1281 g_variant_get (result,
1284 while ((item = g_variant_iter_next_value (iter)))
1288 g_variant_get (item,
1293 g_hash_table_insert (properties, key, g_variant_ref (value));
1296 g_variant_unref (result);
1301 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1303 result = g_dbus_connection_call_sync (c,
1306 "org.freedesktop.DBus.Properties",
1308 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1309 G_VARIANT_TYPE ("(v)"),
1310 G_DBUS_CALL_FLAGS_NONE,
1316 GVariant *property_value;
1317 g_variant_get (result,
1320 g_hash_table_insert (properties,
1321 g_strdup (o->properties[n]->name),
1322 g_variant_ref (property_value));
1323 g_variant_unref (result);
1329 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1330 dump_annotation (o->annotations[n], indent, FALSE);
1332 g_print ("%*sinterface %s {\n", indent, "", o->name);
1333 if (o->methods != NULL && !opt_introspect_only_properties)
1335 g_print ("%*s methods:\n", indent, "");
1336 for (n = 0; o->methods[n] != NULL; n++)
1337 dump_method (o->methods[n], indent + 4);
1339 if (o->signals != NULL && !opt_introspect_only_properties)
1341 g_print ("%*s signals:\n", indent, "");
1342 for (n = 0; o->signals[n] != NULL; n++)
1343 dump_signal (o->signals[n], indent + 4);
1345 if (o->properties != NULL)
1347 g_print ("%*s properties:\n", indent, "");
1348 for (n = 0; o->properties[n] != NULL; n++)
1350 dump_property (o->properties[n],
1352 g_hash_table_lookup (properties, (o->properties[n])->name));
1358 g_hash_table_unref (properties);
1362 introspect_do (GDBusConnection *c,
1363 const gchar *object_path,
1367 dump_node (GDBusConnection *c,
1369 const GDBusNodeInfo *o,
1371 const gchar *object_path,
1375 const gchar *object_path_to_print;
1377 object_path_to_print = object_path;
1378 if (o->path != NULL)
1379 object_path_to_print = o->path;
1381 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1382 dump_annotation (o->annotations[n], indent, FALSE);
1384 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1385 if (o->interfaces != NULL || o->nodes != NULL)
1388 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1390 if (opt_introspect_only_properties)
1392 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1393 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1397 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1400 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1405 if (g_variant_is_object_path (o->nodes[n]->path))
1407 child_path = g_strdup (o->nodes[n]->path);
1408 /* avoid infinite loops */
1409 if (g_str_has_prefix (child_path, object_path))
1411 introspect_do (c, child_path, indent + 2);
1415 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1416 child_path, object_path);
1421 if (g_strcmp0 (object_path, "/") == 0)
1422 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1424 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1425 introspect_do (c, child_path, indent + 2);
1427 g_free (child_path);
1431 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1443 static const GOptionEntry introspect_entries[] =
1445 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1446 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1447 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1448 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1449 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1454 introspect_do (GDBusConnection *c,
1455 const gchar *object_path,
1460 GDBusNodeInfo *node;
1462 const gchar *xml_data;
1469 result = g_dbus_connection_call_sync (c,
1470 opt_introspect_dest,
1472 "org.freedesktop.DBus.Introspectable",
1475 G_VARIANT_TYPE ("(s)"),
1476 G_DBUS_CALL_FLAGS_NONE,
1482 g_printerr (_("Error: %s\n"), error->message);
1483 g_error_free (error);
1486 g_variant_get (result, "(&s)", &xml_data);
1488 if (opt_introspect_xml)
1490 g_print ("%s", xml_data);
1495 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1498 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1499 g_error_free (error);
1503 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1510 g_dbus_node_info_unref (node);
1512 g_variant_unref (result);
1517 handle_introspect (gint *argc,
1519 gboolean request_completion,
1520 const gchar *completion_cur,
1521 const gchar *completion_prev)
1528 gboolean complete_names;
1529 gboolean complete_paths;
1534 modify_argv0_for_command (argc, argv, "introspect");
1536 o = g_option_context_new (NULL);
1537 if (request_completion)
1538 g_option_context_set_ignore_unknown_options (o, TRUE);
1539 g_option_context_set_help_enabled (o, FALSE);
1540 g_option_context_set_summary (o, _("Introspect a remote object."));
1541 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1542 g_option_context_add_group (o, connection_get_group ());
1544 complete_names = FALSE;
1545 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1547 complete_names = TRUE;
1548 remove_arg ((*argc) - 1, argc, argv);
1551 complete_paths = FALSE;
1552 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1554 complete_paths = TRUE;
1555 remove_arg ((*argc) - 1, argc, argv);
1558 if (!g_option_context_parse (o, argc, argv, NULL))
1560 if (!request_completion)
1562 s = g_option_context_get_help (o, FALSE, NULL);
1563 g_printerr ("%s", s);
1570 c = connection_get_dbus_connection (&error);
1573 if (request_completion)
1575 if (g_strcmp0 (completion_prev, "--address") == 0)
1583 g_print ("--system \n--session \n--machine \n--user \n--address \n");
1588 g_printerr (_("Error connecting: %s\n"), error->message);
1589 g_error_free (error);
1594 if (g_dbus_connection_get_unique_name (c) != NULL)
1598 print_names (c, FALSE);
1601 /* this only makes sense on message bus connections */
1602 if (opt_introspect_dest == NULL)
1604 if (request_completion)
1605 g_print ("--dest \n");
1607 g_printerr (_("Error: Destination is not specified\n"));
1610 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1612 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1618 print_paths (c, opt_introspect_dest, "/");
1621 if (opt_introspect_object_path == NULL)
1623 if (request_completion)
1624 g_print ("--object-path \n");
1626 g_printerr (_("Error: Object path is not specified\n"));
1629 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1632 s = g_strdup (opt_introspect_object_path);
1633 p = strrchr (s, '/');
1640 print_paths (c, opt_introspect_dest, s);
1644 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1646 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1650 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1652 g_print ("--recurse \n");
1655 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1657 g_print ("--only-properties \n");
1660 /* All done with completion now */
1661 if (request_completion)
1664 if (!introspect_do (c, opt_introspect_object_path, 0))
1672 g_option_context_free (o);
1676 /* ---------------------------------------------------------------------------------------------------- */
1678 static gchar *opt_monitor_dest = NULL;
1679 static gchar *opt_monitor_object_path = NULL;
1681 static guint monitor_filter_id = 0;
1684 monitor_signal_cb (GDBusConnection *connection,
1685 const gchar *sender_name,
1686 const gchar *object_path,
1687 const gchar *interface_name,
1688 const gchar *signal_name,
1689 GVariant *parameters,
1693 s = g_variant_print (parameters, TRUE);
1694 g_print ("%s: %s.%s %s\n",
1703 monitor_on_name_appeared (GDBusConnection *connection,
1705 const gchar *name_owner,
1708 g_print ("The name %s is owned by %s\n", name, name_owner);
1709 g_assert (monitor_filter_id == 0);
1710 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1712 NULL, /* any interface */
1713 NULL, /* any member */
1714 opt_monitor_object_path,
1716 G_DBUS_SIGNAL_FLAGS_NONE,
1718 NULL, /* user_data */
1719 NULL); /* user_data destroy notify */
1723 monitor_on_name_vanished (GDBusConnection *connection,
1727 g_print ("The name %s does not have an owner\n", name);
1729 if (monitor_filter_id != 0)
1731 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1732 monitor_filter_id = 0;
1736 static const GOptionEntry monitor_entries[] =
1738 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1739 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1744 handle_monitor (gint *argc,
1746 gboolean request_completion,
1747 const gchar *completion_cur,
1748 const gchar *completion_prev)
1755 gboolean complete_names;
1756 gboolean complete_paths;
1762 modify_argv0_for_command (argc, argv, "monitor");
1764 o = g_option_context_new (NULL);
1765 if (request_completion)
1766 g_option_context_set_ignore_unknown_options (o, TRUE);
1767 g_option_context_set_help_enabled (o, FALSE);
1768 g_option_context_set_summary (o, _("Monitor a remote object."));
1769 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1770 g_option_context_add_group (o, connection_get_group ());
1772 complete_names = FALSE;
1773 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1775 complete_names = TRUE;
1776 remove_arg ((*argc) - 1, argc, argv);
1779 complete_paths = FALSE;
1780 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1782 complete_paths = TRUE;
1783 remove_arg ((*argc) - 1, argc, argv);
1786 if (!g_option_context_parse (o, argc, argv, NULL))
1788 if (!request_completion)
1790 s = g_option_context_get_help (o, FALSE, NULL);
1791 g_printerr ("%s", s);
1798 c = connection_get_dbus_connection (&error);
1801 if (request_completion)
1803 if (g_strcmp0 (completion_prev, "--address") == 0)
1811 g_print ("--system \n--session \n--machine \n--user \n--address \n");
1816 g_printerr (_("Error connecting: %s\n"), error->message);
1817 g_error_free (error);
1822 if (g_dbus_connection_get_unique_name (c) != NULL)
1826 print_names (c, FALSE);
1829 /* this only makes sense on message bus connections */
1830 if (opt_monitor_dest == NULL)
1832 if (request_completion)
1833 g_print ("--dest \n");
1835 g_printerr (_("Error: Destination is not specified\n"));
1838 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1840 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1846 print_paths (c, opt_monitor_dest, "/");
1849 if (opt_monitor_object_path == NULL)
1851 if (request_completion)
1853 g_print ("--object-path \n");
1856 /* it's fine to not have an object path */
1858 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1861 s = g_strdup (opt_monitor_object_path);
1862 p = strrchr (s, '/');
1869 print_paths (c, opt_monitor_dest, s);
1873 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1875 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1879 /* All done with completion now */
1880 if (request_completion)
1883 if (opt_monitor_object_path != NULL)
1884 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1886 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1888 loop = g_main_loop_new (NULL, FALSE);
1889 g_bus_watch_name_on_connection (c,
1891 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1892 monitor_on_name_appeared,
1893 monitor_on_name_vanished,
1897 g_main_loop_run (loop);
1898 g_main_loop_unref (loop);
1905 g_option_context_free (o);
1909 /* ---------------------------------------------------------------------------------------------------- */
1912 pick_word_at (const gchar *s,
1914 gint *out_word_begins_at)
1921 if (out_word_begins_at != NULL)
1922 *out_word_begins_at = -1;
1926 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1928 if (out_word_begins_at != NULL)
1929 *out_word_begins_at = cursor;
1930 return g_strdup ("");
1933 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1938 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1941 if (out_word_begins_at != NULL)
1942 *out_word_begins_at = begin;
1944 return g_strndup (s + begin, end - begin);
1948 main (gint argc, gchar *argv[])
1951 const gchar *command;
1952 gboolean request_completion;
1953 gchar *completion_cur;
1954 gchar *completion_prev;
1959 setlocale (LC_ALL, "");
1960 textdomain (GETTEXT_PACKAGE);
1963 tmp = _glib_get_locale_dir ();
1964 bindtextdomain (GETTEXT_PACKAGE, tmp);
1967 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1970 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1971 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1975 completion_cur = NULL;
1976 completion_prev = NULL;
1980 usage (&argc, &argv, FALSE);
1984 request_completion = FALSE;
1986 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1990 if (g_strcmp0 (command, "help") == 0)
1992 if (request_completion)
1998 usage (&argc, &argv, TRUE);
2003 else if (g_strcmp0 (command, "emit") == 0)
2005 if (handle_emit (&argc,
2013 else if (g_strcmp0 (command, "call") == 0)
2015 if (handle_call (&argc,
2023 else if (g_strcmp0 (command, "introspect") == 0)
2025 if (handle_introspect (&argc,
2033 else if (g_strcmp0 (command, "monitor") == 0)
2035 if (handle_monitor (&argc,
2043 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2045 const gchar *completion_line;
2046 gchar **completion_argv;
2047 gint completion_argc;
2048 gint completion_point;
2052 request_completion = TRUE;
2054 completion_line = argv[2];
2055 completion_point = strtol (argv[3], &endp, 10);
2056 if (endp == argv[3] || *endp != '\0')
2060 completion_debug ("completion_point=%d", completion_point);
2061 completion_debug ("----");
2062 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2063 completion_debug ("'%s'", completion_line);
2064 completion_debug (" %*s^",
2065 completion_point, "");
2066 completion_debug ("----");
2069 if (!g_shell_parse_argv (completion_line,
2074 /* it's very possible the command line can't be parsed (for
2075 * example, missing quotes etc) - in that case, we just
2076 * don't autocomplete at all
2081 /* compute cur and prev */
2082 completion_prev = NULL;
2083 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2087 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2089 if (!g_ascii_isspace (completion_line[prev_end]))
2091 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2097 completion_debug (" cur='%s'", completion_cur);
2098 completion_debug ("prev='%s'", completion_prev);
2101 argc = completion_argc;
2102 argv = completion_argv;
2110 if (request_completion)
2112 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2118 g_printerr ("Unknown command '%s'\n", command);
2119 usage (&argc, &argv, FALSE);
2125 g_free (completion_cur);
2126 g_free (completion_prev);