1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
34 /* ---------------------------------------------------------------------------------------------------- */
36 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
38 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
39 * to not have it interfere with stdout/stderr)
42 G_GNUC_UNUSED static void
43 completion_debug (const gchar *format, ...)
47 static FILE *f = NULL;
49 va_start (var_args, format);
50 s = g_strdup_vprintf (format, var_args);
53 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
55 fprintf (f, "%s\n", s);
60 completion_debug (const gchar *format, ...)
65 /* ---------------------------------------------------------------------------------------------------- */
69 remove_arg (gint num, gint *argc, gchar **argv[])
73 g_assert (num <= (*argc));
75 for (n = num; (*argv)[n] != NULL; n++)
76 (*argv)[n] = (*argv)[n+1];
78 (*argc) = (*argc) - 1;
82 usage (gint *argc, gchar **argv[], gboolean use_stdout)
88 o = g_option_context_new (_("COMMAND"));
89 g_option_context_set_help_enabled (o, FALSE);
90 /* Ignore parsing result */
91 g_option_context_parse (o, argc, argv, NULL);
92 program_name = g_path_get_basename ((*argv)[0]);
93 s = g_strdup_printf (_("Commands:\n"
94 " help Shows this information\n"
95 " introspect Introspect a remote object\n"
96 " monitor Monitor a remote object\n"
97 " call Invoke a method on a remote object\n"
98 " emit Emit a signal\n"
100 "Use \"%s COMMAND --help\" to get help on each command.\n"),
102 g_free (program_name);
103 g_option_context_set_description (o, s);
105 s = g_option_context_get_help (o, FALSE, NULL);
109 g_printerr ("%s", s);
111 g_option_context_free (o);
115 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
121 * 1. get a g_set_prgname() ?; or
122 * 2. save old argv[0] and restore later
125 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
126 remove_arg (1, argc, argv);
128 program_name = g_path_get_basename ((*argv)[0]);
129 s = g_strdup_printf ("%s %s", (*argv)[0], command);
131 g_free (program_name);
134 /* ---------------------------------------------------------------------------------------------------- */
137 print_methods (GDBusConnection *c,
143 const gchar *xml_data;
149 result = g_dbus_connection_call_sync (c,
152 "org.freedesktop.DBus.Introspectable",
155 G_VARIANT_TYPE ("(s)"),
156 G_DBUS_CALL_FLAGS_NONE,
162 g_printerr (_("Error: %s\n"), error->message);
163 g_error_free (error);
166 g_variant_get (result, "(&s)", &xml_data);
169 node = g_dbus_node_info_new_for_xml (xml_data, &error);
170 g_variant_unref (result);
173 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
174 g_error_free (error);
178 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
180 const GDBusInterfaceInfo *iface = node->interfaces[n];
181 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
183 const GDBusMethodInfo *method = iface->methods[m];
184 g_print ("%s.%s \n", iface->name, method->name);
187 g_dbus_node_info_unref (node);
194 print_paths (GDBusConnection *c,
200 const gchar *xml_data;
205 result = g_dbus_connection_call_sync (c,
208 "org.freedesktop.DBus.Introspectable",
211 G_VARIANT_TYPE ("(s)"),
212 G_DBUS_CALL_FLAGS_NONE,
218 g_printerr (_("Error: %s\n"), error->message);
219 g_error_free (error);
222 g_variant_get (result, "(&s)", &xml_data);
224 //g_printerr ("xml=`%s'", xml_data);
227 node = g_dbus_node_info_new_for_xml (xml_data, &error);
228 g_variant_unref (result);
231 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
232 g_error_free (error);
236 //g_printerr ("bar `%s'\n", path);
238 if (node->interfaces != NULL)
239 g_print ("%s \n", path);
241 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
245 //g_printerr ("foo `%s'\n", node->nodes[n].path);
247 if (g_strcmp0 (path, "/") == 0)
248 s = g_strdup_printf ("/%s", node->nodes[n]->path);
250 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
252 print_paths (c, name, s);
256 g_dbus_node_info_unref (node);
263 print_names (GDBusConnection *c,
264 gboolean include_unique_names)
270 GHashTable *name_set;
274 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
277 result = g_dbus_connection_call_sync (c,
278 "org.freedesktop.DBus",
279 "/org/freedesktop/DBus",
280 "org.freedesktop.DBus",
283 G_VARIANT_TYPE ("(as)"),
284 G_DBUS_CALL_FLAGS_NONE,
290 g_printerr (_("Error: %s\n"), error->message);
291 g_error_free (error);
294 g_variant_get (result, "(as)", &iter);
295 while (g_variant_iter_loop (iter, "s", &str))
296 g_hash_table_insert (name_set, g_strdup (str), NULL);
297 g_variant_iter_free (iter);
298 g_variant_unref (result);
301 result = g_dbus_connection_call_sync (c,
302 "org.freedesktop.DBus",
303 "/org/freedesktop/DBus",
304 "org.freedesktop.DBus",
305 "ListActivatableNames",
307 G_VARIANT_TYPE ("(as)"),
308 G_DBUS_CALL_FLAGS_NONE,
314 g_printerr (_("Error: %s\n"), error->message);
315 g_error_free (error);
318 g_variant_get (result, "(as)", &iter);
319 while (g_variant_iter_loop (iter, "s", &str))
320 g_hash_table_insert (name_set, g_strdup (str), NULL);
321 g_variant_iter_free (iter);
322 g_variant_unref (result);
324 keys = g_hash_table_get_keys (name_set);
325 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
326 for (l = keys; l != NULL; l = l->next)
328 const gchar *name = l->data;
329 if (!include_unique_names && g_str_has_prefix (name, ":"))
332 g_print ("%s \n", name);
337 g_hash_table_unref (name_set);
340 /* ---------------------------------------------------------------------------------------------------- */
342 static gboolean opt_connection_system = FALSE;
343 static gboolean opt_connection_session = FALSE;
344 static gchar *opt_connection_address = NULL;
346 static const GOptionEntry connection_entries[] =
348 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
349 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
350 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
354 static GOptionGroup *
355 connection_get_group (void)
357 static GOptionGroup *g;
359 g = g_option_group_new ("connection",
360 N_("Connection Endpoint Options:"),
361 N_("Options specifying the connection endpoint"),
364 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
365 g_option_group_add_entries (g, connection_entries);
370 static GDBusConnection *
371 connection_get_dbus_connection (GError **error)
377 /* First, ensure we have exactly one connect */
378 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
383 _("No connection endpoint specified"));
386 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
387 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
388 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
393 _("Multiple connection endpoints specified"));
397 if (opt_connection_system)
399 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
401 else if (opt_connection_session)
403 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
405 else if (opt_connection_address != NULL)
407 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
408 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
409 NULL, /* GDBusAuthObserver */
410 NULL, /* GCancellable */
418 /* ---------------------------------------------------------------------------------------------------- */
421 call_helper_get_method_in_signature (GDBusConnection *c,
424 const gchar *interface_name,
425 const gchar *method_name,
430 GDBusNodeInfo *node_info;
431 const gchar *xml_data;
432 GDBusInterfaceInfo *interface_info;
433 GDBusMethodInfo *method_info;
440 result = g_dbus_connection_call_sync (c,
443 "org.freedesktop.DBus.Introspectable",
446 G_VARIANT_TYPE ("(s)"),
447 G_DBUS_CALL_FLAGS_NONE,
454 g_variant_get (result, "(&s)", &xml_data);
455 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
456 if (node_info == NULL)
459 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
460 if (interface_info == NULL)
462 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
463 _("Warning: According to introspection data, interface `%s' does not exist\n"),
468 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
469 if (method_info == NULL)
471 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
472 _("Warning: According to introspection data, method `%s' does not exist on interface `%s'\n"),
478 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
479 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
481 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
485 if (node_info != NULL)
486 g_dbus_node_info_unref (node_info);
488 g_variant_unref (result);
493 /* ---------------------------------------------------------------------------------------------------- */
496 _g_variant_parse_me_harder (GVariantType *type,
497 const gchar *given_str,
505 str = g_string_new ("\"");
506 for (n = 0; given_str[n] != '\0'; n++)
508 if (G_UNLIKELY (given_str[n] == '\"'))
509 g_string_append (str, "\\\"");
511 g_string_append_c (str, given_str[n]);
513 g_string_append_c (str, '"');
514 s = g_string_free (str, FALSE);
516 value = g_variant_parse (type,
526 /* ---------------------------------------------------------------------------------------------------- */
528 static gchar *opt_emit_dest = NULL;
529 static gchar *opt_emit_object_path = NULL;
530 static gchar *opt_emit_signal = NULL;
532 static const GOptionEntry emit_entries[] =
534 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
535 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
536 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
541 handle_emit (gint *argc,
543 gboolean request_completion,
544 const gchar *completion_cur,
545 const gchar *completion_prev)
552 GVariant *parameters;
553 gchar *interface_name;
555 GVariantBuilder builder;
561 interface_name = NULL;
564 modify_argv0_for_command (argc, argv, "emit");
566 o = g_option_context_new (NULL);
567 g_option_context_set_help_enabled (o, FALSE);
568 g_option_context_set_summary (o, _("Emit a signal."));
569 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
570 g_option_context_add_group (o, connection_get_group ());
572 if (!g_option_context_parse (o, argc, argv, NULL))
574 if (!request_completion)
576 s = g_option_context_get_help (o, FALSE, NULL);
577 g_printerr ("%s", s);
584 c = connection_get_dbus_connection (&error);
587 if (request_completion)
589 if (g_strcmp0 (completion_prev, "--address") == 0)
597 g_print ("--system \n--session \n--address \n");
602 g_printerr (_("Error connecting: %s\n"), error->message);
603 g_error_free (error);
608 /* All done with completion now */
609 if (request_completion)
612 if (opt_emit_object_path == NULL)
614 g_printerr (_("Error: object path not specified.\n"));
617 if (!g_variant_is_object_path (opt_emit_object_path))
619 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
623 if (opt_emit_signal == NULL)
625 g_printerr (_("Error: signal not specified.\n"));
628 s = strrchr (opt_emit_signal, '.');
629 signal_name = g_strdup (s + 1);
630 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
632 if (!g_dbus_is_interface_name (interface_name))
634 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
638 if (!g_dbus_is_member_name (signal_name))
640 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
644 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
646 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
650 /* Read parameters */
651 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
652 for (n = 1; n < (guint) *argc; n++)
657 value = g_variant_parse (NULL,
664 g_error_free (error);
666 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
669 g_printerr (_("Error parsing parameter %d: %s\n"),
672 g_error_free (error);
673 g_variant_builder_clear (&builder);
677 g_variant_builder_add_value (&builder, value);
679 parameters = g_variant_builder_end (&builder);
681 if (parameters != NULL)
682 parameters = g_variant_ref_sink (parameters);
683 if (!g_dbus_connection_emit_signal (c,
685 opt_emit_object_path,
691 g_printerr (_("Error: %s\n"), error->message);
692 g_error_free (error);
696 if (!g_dbus_connection_flush_sync (c, NULL, &error))
698 g_printerr (_("Error flushing connection: %s\n"), error->message);
699 g_error_free (error);
708 if (parameters != NULL)
709 g_variant_unref (parameters);
710 g_free (interface_name);
711 g_free (signal_name);
712 g_option_context_free (o);
716 /* ---------------------------------------------------------------------------------------------------- */
718 static gchar *opt_call_dest = NULL;
719 static gchar *opt_call_object_path = NULL;
720 static gchar *opt_call_method = NULL;
721 static gint opt_call_timeout = -1;
723 static const GOptionEntry call_entries[] =
725 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
726 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
727 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
728 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
733 handle_call (gint *argc,
735 gboolean request_completion,
736 const gchar *completion_cur,
737 const gchar *completion_prev)
744 GVariant *parameters;
745 gchar *interface_name;
748 GPtrArray *in_signature_types;
749 gboolean complete_names;
750 gboolean complete_paths;
751 gboolean complete_methods;
752 GVariantBuilder builder;
758 interface_name = NULL;
761 in_signature_types = NULL;
763 modify_argv0_for_command (argc, argv, "call");
765 o = g_option_context_new (NULL);
766 g_option_context_set_help_enabled (o, FALSE);
767 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
768 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
769 g_option_context_add_group (o, connection_get_group ());
771 complete_names = FALSE;
772 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
774 complete_names = TRUE;
775 remove_arg ((*argc) - 1, argc, argv);
778 complete_paths = FALSE;
779 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
781 complete_paths = TRUE;
782 remove_arg ((*argc) - 1, argc, argv);
785 complete_methods = FALSE;
786 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
788 complete_methods = TRUE;
789 remove_arg ((*argc) - 1, argc, argv);
792 if (!g_option_context_parse (o, argc, argv, NULL))
794 if (!request_completion)
796 s = g_option_context_get_help (o, FALSE, NULL);
797 g_printerr ("%s", s);
804 c = connection_get_dbus_connection (&error);
807 if (request_completion)
809 if (g_strcmp0 (completion_prev, "--address") == 0)
817 g_print ("--system \n--session \n--address \n");
822 g_printerr (_("Error connecting: %s\n"), error->message);
823 g_error_free (error);
828 /* validate and complete destination (bus name) */
829 if (g_dbus_connection_get_unique_name (c) != NULL)
831 /* this only makes sense on message bus connections */
834 print_names (c, FALSE);
837 if (opt_call_dest == NULL)
839 if (request_completion)
840 g_print ("--dest \n");
842 g_printerr (_("Error: Destination is not specified\n"));
845 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
847 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
852 /* validate and complete object path */
855 print_paths (c, opt_call_dest, "/");
858 if (opt_call_object_path == NULL)
860 if (request_completion)
861 g_print ("--object-path \n");
863 g_printerr (_("Error: Object path is not specified\n"));
866 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
869 s = g_strdup (opt_call_object_path);
870 p = strrchr (s, '/');
877 print_paths (c, opt_call_dest, s);
881 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
883 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
887 /* validate and complete method (interface + method name) */
888 if (complete_methods)
890 print_methods (c, opt_call_dest, opt_call_object_path);
893 if (opt_call_method == NULL)
895 if (request_completion)
896 g_print ("--method \n");
898 g_printerr (_("Error: Method name is not specified\n"));
901 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
903 print_methods (c, opt_call_dest, opt_call_object_path);
906 s = strrchr (opt_call_method, '.');
907 if (!request_completion && s == NULL)
909 g_printerr (_("Error: Method name `%s' is invalid\n"), opt_call_method);
912 method_name = g_strdup (s + 1);
913 interface_name = g_strndup (opt_call_method, s - opt_call_method);
915 /* All done with completion now */
916 if (request_completion)
919 /* Introspect, for easy conversion - it's not fatal if we can't do this */
920 in_signature_types = call_helper_get_method_in_signature (c,
922 opt_call_object_path,
926 if (in_signature_types == NULL)
928 //g_printerr ("Error getting introspection data: %s\n", error->message);
929 g_error_free (error);
933 /* Read parameters */
934 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
935 for (n = 1; n < (guint) *argc; n++)
941 if (in_signature_types != NULL)
943 if (n - 1 >= in_signature_types->len)
945 /* Only warn for the first param */
946 if (n - 1 == in_signature_types->len)
948 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
949 in_signature_types->len);
954 type = in_signature_types->pdata[n - 1];
959 value = g_variant_parse (type,
966 g_error_free (error);
968 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
973 s = g_variant_type_dup_string (type);
974 g_printerr (_("Error parsing parameter %d of type `%s': %s\n"),
982 g_printerr (_("Error parsing parameter %d: %s\n"),
986 g_error_free (error);
987 g_variant_builder_clear (&builder);
991 g_variant_builder_add_value (&builder, value);
993 parameters = g_variant_builder_end (&builder);
995 if (parameters != NULL)
996 parameters = g_variant_ref_sink (parameters);
997 result = g_dbus_connection_call_sync (c,
999 opt_call_object_path,
1004 G_DBUS_CALL_FLAGS_NONE,
1005 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1010 g_printerr (_("Error: %s\n"), error->message);
1011 g_error_free (error);
1012 if (in_signature_types != NULL)
1015 s = g_string_new (NULL);
1016 for (n = 0; n < in_signature_types->len; n++)
1018 GVariantType *type = in_signature_types->pdata[n];
1019 g_string_append_len (s,
1020 g_variant_type_peek_string (type),
1021 g_variant_type_get_string_length (type));
1023 g_printerr ("(According to introspection data, you need to pass `%s')\n", s->str);
1024 g_string_free (s, TRUE);
1029 s = g_variant_print (result, TRUE);
1030 g_print ("%s\n", s);
1036 if (in_signature_types != NULL)
1037 g_ptr_array_unref (in_signature_types);
1039 g_variant_unref (result);
1042 if (parameters != NULL)
1043 g_variant_unref (parameters);
1044 g_free (interface_name);
1045 g_free (method_name);
1046 g_option_context_free (o);
1050 /* ---------------------------------------------------------------------------------------------------- */
1052 static gchar *opt_introspect_dest = NULL;
1053 static gchar *opt_introspect_object_path = NULL;
1054 static gboolean opt_introspect_xml = FALSE;
1055 static gboolean opt_introspect_recurse = FALSE;
1056 static gboolean opt_introspect_only_properties = FALSE;
1059 dump_annotation (const GDBusAnnotationInfo *o,
1061 gboolean ignore_indent)
1064 g_print ("%*s@%s(\"%s\")\n",
1065 ignore_indent ? 0 : indent, "",
1068 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1069 dump_annotation (o->annotations[n], indent + 2, FALSE);
1073 dump_arg (const GDBusArgInfo *o,
1075 const gchar *direction,
1076 gboolean ignore_indent,
1077 gboolean include_newline)
1081 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1083 dump_annotation (o->annotations[n], indent, ignore_indent);
1084 ignore_indent = FALSE;
1087 g_print ("%*s%s%s %s%s",
1088 ignore_indent ? 0 : indent, "",
1092 include_newline ? ",\n" : "");
1096 count_args (GDBusArgInfo **args)
1102 while (args[n] != NULL)
1109 dump_method (const GDBusMethodInfo *o,
1115 guint total_num_args;
1117 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1118 dump_annotation (o->annotations[n], indent, FALSE);
1120 g_print ("%*s%s(", indent, "", o->name);
1121 name_len = strlen (o->name);
1122 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1123 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1125 gboolean ignore_indent = (m == 0);
1126 gboolean include_newline = (m != total_num_args - 1);
1128 dump_arg (o->in_args[n],
1129 indent + name_len + 1,
1134 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1136 gboolean ignore_indent = (m == 0);
1137 gboolean include_newline = (m != total_num_args - 1);
1138 dump_arg (o->out_args[n],
1139 indent + name_len + 1,
1148 dump_signal (const GDBusSignalInfo *o,
1153 guint total_num_args;
1155 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1156 dump_annotation (o->annotations[n], indent, FALSE);
1158 g_print ("%*s%s(", indent, "", o->name);
1159 name_len = strlen (o->name);
1160 total_num_args = count_args (o->args);
1161 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1163 gboolean ignore_indent = (n == 0);
1164 gboolean include_newline = (n != total_num_args - 1);
1165 dump_arg (o->args[n],
1166 indent + name_len + 1,
1175 dump_property (const GDBusPropertyInfo *o,
1179 const gchar *access;
1182 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1183 access = "readonly";
1184 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1185 access = "writeonly";
1186 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1187 access = "readwrite";
1189 g_assert_not_reached ();
1191 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1192 dump_annotation (o->annotations[n], indent, FALSE);
1196 gchar *s = g_variant_print (value, FALSE);
1197 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1202 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1207 dump_interface (GDBusConnection *c,
1209 const GDBusInterfaceInfo *o,
1211 const gchar *object_path)
1214 GHashTable *properties;
1216 properties = g_hash_table_new_full (g_str_hash,
1219 (GDestroyNotify) g_variant_unref);
1221 /* Try to get properties */
1222 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1225 result = g_dbus_connection_call_sync (c,
1228 "org.freedesktop.DBus.Properties",
1230 g_variant_new ("(s)", o->name),
1232 G_DBUS_CALL_FLAGS_NONE,
1238 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1242 g_variant_get (result,
1245 while ((item = g_variant_iter_next_value (iter)))
1249 g_variant_get (item,
1254 g_hash_table_insert (properties, key, g_variant_ref (value));
1257 g_variant_unref (result);
1262 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1264 result = g_dbus_connection_call_sync (c,
1267 "org.freedesktop.DBus.Properties",
1269 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1270 G_VARIANT_TYPE ("(v)"),
1271 G_DBUS_CALL_FLAGS_NONE,
1277 GVariant *property_value;
1278 g_variant_get (result,
1281 g_hash_table_insert (properties,
1282 g_strdup (o->properties[n]->name),
1283 g_variant_ref (property_value));
1284 g_variant_unref (result);
1290 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1291 dump_annotation (o->annotations[n], indent, FALSE);
1293 g_print ("%*sinterface %s {\n", indent, "", o->name);
1294 if (o->methods != NULL && !opt_introspect_only_properties)
1296 g_print ("%*s methods:\n", indent, "");
1297 for (n = 0; o->methods[n] != NULL; n++)
1298 dump_method (o->methods[n], indent + 4);
1300 if (o->signals != NULL && !opt_introspect_only_properties)
1302 g_print ("%*s signals:\n", indent, "");
1303 for (n = 0; o->signals[n] != NULL; n++)
1304 dump_signal (o->signals[n], indent + 4);
1306 if (o->properties != NULL)
1308 g_print ("%*s properties:\n", indent, "");
1309 for (n = 0; o->properties[n] != NULL; n++)
1311 dump_property (o->properties[n],
1313 g_hash_table_lookup (properties, (o->properties[n])->name));
1319 g_hash_table_unref (properties);
1323 introspect_do (GDBusConnection *c,
1324 const gchar *object_path,
1328 dump_node (GDBusConnection *c,
1330 const GDBusNodeInfo *o,
1332 const gchar *object_path,
1336 const gchar *object_path_to_print;
1338 object_path_to_print = object_path;
1339 if (o->path != NULL)
1340 object_path_to_print = o->path;
1342 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1343 dump_annotation (o->annotations[n], indent, FALSE);
1345 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1346 if (o->interfaces != NULL || o->nodes != NULL)
1349 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1351 if (opt_introspect_only_properties)
1353 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1354 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1358 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1361 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1366 if (g_variant_is_object_path (o->nodes[n]->path))
1368 child_path = g_strdup (o->nodes[n]->path);
1369 /* avoid infinite loops */
1370 if (g_str_has_prefix (child_path, object_path))
1372 introspect_do (c, child_path, indent + 2);
1376 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1377 child_path, object_path);
1382 if (g_strcmp0 (object_path, "/") == 0)
1383 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1385 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1386 introspect_do (c, child_path, indent + 2);
1388 g_free (child_path);
1392 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1404 static const GOptionEntry introspect_entries[] =
1406 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1407 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1408 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1409 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1410 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1415 introspect_do (GDBusConnection *c,
1416 const gchar *object_path,
1421 GDBusNodeInfo *node;
1423 const gchar *xml_data;
1430 result = g_dbus_connection_call_sync (c,
1431 opt_introspect_dest,
1433 "org.freedesktop.DBus.Introspectable",
1436 G_VARIANT_TYPE ("(s)"),
1437 G_DBUS_CALL_FLAGS_NONE,
1443 g_printerr (_("Error: %s\n"), error->message);
1444 g_error_free (error);
1447 g_variant_get (result, "(&s)", &xml_data);
1449 if (opt_introspect_xml)
1451 g_print ("%s", xml_data);
1456 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1459 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1460 g_error_free (error);
1464 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1471 g_dbus_node_info_unref (node);
1473 g_variant_unref (result);
1478 handle_introspect (gint *argc,
1480 gboolean request_completion,
1481 const gchar *completion_cur,
1482 const gchar *completion_prev)
1489 gboolean complete_names;
1490 gboolean complete_paths;
1495 modify_argv0_for_command (argc, argv, "introspect");
1497 o = g_option_context_new (NULL);
1498 if (request_completion)
1499 g_option_context_set_ignore_unknown_options (o, TRUE);
1500 g_option_context_set_help_enabled (o, FALSE);
1501 g_option_context_set_summary (o, _("Introspect a remote object."));
1502 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1503 g_option_context_add_group (o, connection_get_group ());
1505 complete_names = FALSE;
1506 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1508 complete_names = TRUE;
1509 remove_arg ((*argc) - 1, argc, argv);
1512 complete_paths = FALSE;
1513 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1515 complete_paths = TRUE;
1516 remove_arg ((*argc) - 1, argc, argv);
1519 if (!g_option_context_parse (o, argc, argv, NULL))
1521 if (!request_completion)
1523 s = g_option_context_get_help (o, FALSE, NULL);
1524 g_printerr ("%s", s);
1531 c = connection_get_dbus_connection (&error);
1534 if (request_completion)
1536 if (g_strcmp0 (completion_prev, "--address") == 0)
1544 g_print ("--system \n--session \n--address \n");
1549 g_printerr (_("Error connecting: %s\n"), error->message);
1550 g_error_free (error);
1555 if (g_dbus_connection_get_unique_name (c) != NULL)
1559 print_names (c, FALSE);
1562 /* this only makes sense on message bus connections */
1563 if (opt_introspect_dest == NULL)
1565 if (request_completion)
1566 g_print ("--dest \n");
1568 g_printerr (_("Error: Destination is not specified\n"));
1571 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1573 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1579 print_paths (c, opt_introspect_dest, "/");
1582 if (opt_introspect_object_path == NULL)
1584 if (request_completion)
1585 g_print ("--object-path \n");
1587 g_printerr (_("Error: Object path is not specified\n"));
1590 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1593 s = g_strdup (opt_introspect_object_path);
1594 p = strrchr (s, '/');
1601 print_paths (c, opt_introspect_dest, s);
1605 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1607 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1611 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1613 g_print ("--recurse \n");
1616 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1618 g_print ("--only-properties \n");
1621 /* All done with completion now */
1622 if (request_completion)
1625 if (!introspect_do (c, opt_introspect_object_path, 0))
1633 g_option_context_free (o);
1637 /* ---------------------------------------------------------------------------------------------------- */
1639 static gchar *opt_monitor_dest = NULL;
1640 static gchar *opt_monitor_object_path = NULL;
1642 static guint monitor_filter_id = 0;
1645 monitor_signal_cb (GDBusConnection *connection,
1646 const gchar *sender_name,
1647 const gchar *object_path,
1648 const gchar *interface_name,
1649 const gchar *signal_name,
1650 GVariant *parameters,
1654 s = g_variant_print (parameters, TRUE);
1655 g_print ("%s: %s.%s %s\n",
1664 monitor_on_name_appeared (GDBusConnection *connection,
1666 const gchar *name_owner,
1669 g_print ("The name %s is owned by %s\n", name, name_owner);
1670 g_assert (monitor_filter_id == 0);
1671 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1673 NULL, /* any interface */
1674 NULL, /* any member */
1675 opt_monitor_object_path,
1677 G_DBUS_SIGNAL_FLAGS_NONE,
1679 NULL, /* user_data */
1680 NULL); /* user_data destroy notify */
1684 monitor_on_name_vanished (GDBusConnection *connection,
1688 g_print ("The name %s does not have an owner\n", name);
1690 if (monitor_filter_id != 0)
1692 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1693 monitor_filter_id = 0;
1697 static const GOptionEntry monitor_entries[] =
1699 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1700 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1705 handle_monitor (gint *argc,
1707 gboolean request_completion,
1708 const gchar *completion_cur,
1709 const gchar *completion_prev)
1717 GDBusNodeInfo *node;
1718 gboolean complete_names;
1719 gboolean complete_paths;
1727 modify_argv0_for_command (argc, argv, "monitor");
1729 o = g_option_context_new (NULL);
1730 if (request_completion)
1731 g_option_context_set_ignore_unknown_options (o, TRUE);
1732 g_option_context_set_help_enabled (o, FALSE);
1733 g_option_context_set_summary (o, _("Monitor a remote object."));
1734 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1735 g_option_context_add_group (o, connection_get_group ());
1737 complete_names = FALSE;
1738 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1740 complete_names = TRUE;
1741 remove_arg ((*argc) - 1, argc, argv);
1744 complete_paths = FALSE;
1745 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1747 complete_paths = TRUE;
1748 remove_arg ((*argc) - 1, argc, argv);
1751 if (!g_option_context_parse (o, argc, argv, NULL))
1753 if (!request_completion)
1755 s = g_option_context_get_help (o, FALSE, NULL);
1756 g_printerr ("%s", s);
1763 c = connection_get_dbus_connection (&error);
1766 if (request_completion)
1768 if (g_strcmp0 (completion_prev, "--address") == 0)
1776 g_print ("--system \n--session \n--address \n");
1781 g_printerr (_("Error connecting: %s\n"), error->message);
1782 g_error_free (error);
1787 if (g_dbus_connection_get_unique_name (c) != NULL)
1791 print_names (c, FALSE);
1794 /* this only makes sense on message bus connections */
1795 if (opt_monitor_dest == NULL)
1797 if (request_completion)
1798 g_print ("--dest \n");
1800 g_printerr (_("Error: Destination is not specified\n"));
1803 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1805 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1811 print_paths (c, opt_monitor_dest, "/");
1814 if (opt_monitor_object_path == NULL)
1816 if (request_completion)
1818 g_print ("--object-path \n");
1821 /* it's fine to not have an object path */
1823 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1826 s = g_strdup (opt_monitor_object_path);
1827 p = strrchr (s, '/');
1834 print_paths (c, opt_monitor_dest, s);
1838 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1840 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1844 /* All done with completion now */
1845 if (request_completion)
1848 if (opt_monitor_object_path != NULL)
1849 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1851 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1853 loop = g_main_loop_new (NULL, FALSE);
1854 g_bus_watch_name_on_connection (c,
1856 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1857 monitor_on_name_appeared,
1858 monitor_on_name_vanished,
1862 g_main_loop_run (loop);
1863 g_main_loop_unref (loop);
1869 g_dbus_node_info_unref (node);
1871 g_variant_unref (result);
1874 g_option_context_free (o);
1878 /* ---------------------------------------------------------------------------------------------------- */
1881 pick_word_at (const gchar *s,
1883 gint *out_word_begins_at)
1890 if (out_word_begins_at != NULL)
1891 *out_word_begins_at = -1;
1895 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1897 if (out_word_begins_at != NULL)
1898 *out_word_begins_at = cursor;
1899 return g_strdup ("");
1902 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1907 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1910 if (out_word_begins_at != NULL)
1911 *out_word_begins_at = begin;
1913 return g_strndup (s + begin, end - begin);
1917 main (gint argc, gchar *argv[])
1920 const gchar *command;
1921 gboolean request_completion;
1922 gchar *completion_cur;
1923 gchar *completion_prev;
1925 setlocale (LC_ALL, "");
1926 textdomain (GETTEXT_PACKAGE);
1929 extern gchar *_glib_get_locale_dir (void);
1930 gchar *tmp = _glib_get_locale_dir ();
1931 bindtextdomain (GETTEXT_PACKAGE, tmp);
1934 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1937 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1938 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1942 completion_cur = NULL;
1943 completion_prev = NULL;
1949 usage (&argc, &argv, FALSE);
1953 request_completion = FALSE;
1955 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1959 if (g_strcmp0 (command, "help") == 0)
1961 if (request_completion)
1967 usage (&argc, &argv, TRUE);
1972 else if (g_strcmp0 (command, "emit") == 0)
1974 if (handle_emit (&argc,
1982 else if (g_strcmp0 (command, "call") == 0)
1984 if (handle_call (&argc,
1992 else if (g_strcmp0 (command, "introspect") == 0)
1994 if (handle_introspect (&argc,
2002 else if (g_strcmp0 (command, "monitor") == 0)
2004 if (handle_monitor (&argc,
2012 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2014 const gchar *completion_line;
2015 gchar **completion_argv;
2016 gint completion_argc;
2017 gint completion_point;
2021 request_completion = TRUE;
2023 completion_line = argv[2];
2024 completion_point = strtol (argv[3], &endp, 10);
2025 if (endp == argv[3] || *endp != '\0')
2029 completion_debug ("completion_point=%d", completion_point);
2030 completion_debug ("----");
2031 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2032 completion_debug ("`%s'", completion_line);
2033 completion_debug (" %*s^",
2034 completion_point, "");
2035 completion_debug ("----");
2038 if (!g_shell_parse_argv (completion_line,
2043 /* it's very possible the command line can't be parsed (for
2044 * example, missing quotes etc) - in that case, we just
2045 * don't autocomplete at all
2050 /* compute cur and prev */
2051 completion_prev = NULL;
2052 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2056 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2058 if (!g_ascii_isspace (completion_line[prev_end]))
2060 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2066 completion_debug (" cur=`%s'", completion_cur);
2067 completion_debug ("prev=`%s'", completion_prev);
2070 argc = completion_argc;
2071 argv = completion_argv;
2079 if (request_completion)
2081 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2087 g_printerr ("Unknown command `%s'\n", command);
2088 usage (&argc, &argv, FALSE);
2094 g_free (completion_cur);
2095 g_free (completion_prev);