1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Author: David Zeuthen <davidz@redhat.com>
33 #include <gio/gunixfdlist.h>
39 #include "glib/glib-private.h"
40 #include "gdbusprivate.h"
43 /* ---------------------------------------------------------------------------------------------------- */
45 /* Escape values for console colors */
46 #define UNDERLINE "\033[4m"
47 #define BLUE "\033[34m"
48 #define CYAN "\033[36m"
49 #define GREEN "\033[32m"
50 #define MAGENTA "\033[35m"
51 #define RED "\033[31m"
52 #define YELLOW "\033[33m"
54 /* ---------------------------------------------------------------------------------------------------- */
56 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
58 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
59 * to not have it interfere with stdout/stderr)
62 G_GNUC_UNUSED static void
63 completion_debug (const gchar *format, ...)
67 static FILE *f = NULL;
69 va_start (var_args, format);
70 s = g_strdup_vprintf (format, var_args);
73 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
75 fprintf (f, "%s\n", s);
80 completion_debug (const gchar *format, ...)
85 /* ---------------------------------------------------------------------------------------------------- */
89 remove_arg (gint num, gint *argc, gchar **argv[])
93 g_assert (num <= (*argc));
95 for (n = num; (*argv)[n] != NULL; n++)
96 (*argv)[n] = (*argv)[n+1];
98 (*argc) = (*argc) - 1;
102 usage (gint *argc, gchar **argv[], gboolean use_stdout)
108 o = g_option_context_new (_("COMMAND"));
109 g_option_context_set_help_enabled (o, FALSE);
110 /* Ignore parsing result */
111 g_option_context_parse (o, argc, argv, NULL);
112 program_name = (*argc > 0) ? g_path_get_basename ((*argv)[0]) : g_strdup ("gdbus-tool");
113 s = g_strdup_printf (_("Commands:\n"
114 " help Shows this information\n"
115 " introspect Introspect a remote object\n"
116 " monitor Monitor a remote object\n"
117 " call Invoke a method on a remote object\n"
118 " emit Emit a signal\n"
119 " wait Wait for a bus name to appear\n"
121 "Use “%s COMMAND --help” to get help on each command.\n"),
123 g_free (program_name);
124 g_option_context_set_description (o, s);
126 s = g_option_context_get_help (o, FALSE, NULL);
130 g_printerr ("%s", s);
132 g_option_context_free (o);
136 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
142 * 1. get a g_set_prgname() ?; or
143 * 2. save old argv[0] and restore later
146 g_assert (*argc > 1);
147 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
148 remove_arg (1, argc, argv);
150 program_name = g_path_get_basename ((*argv)[0]);
151 s = g_strdup_printf ("%s %s", program_name, command);
153 g_free (program_name);
156 static GOptionContext *
157 command_option_context_new (const gchar *parameter_string,
158 const gchar *summary,
159 const GOptionEntry *entries,
160 gboolean request_completion)
162 GOptionContext *o = NULL;
164 o = g_option_context_new (parameter_string);
165 if (request_completion)
166 g_option_context_set_ignore_unknown_options (o, TRUE);
167 g_option_context_set_help_enabled (o, FALSE);
168 g_option_context_set_summary (o, summary);
169 g_option_context_add_main_entries (o, entries, GETTEXT_PACKAGE);
171 return g_steal_pointer (&o);
174 /* ---------------------------------------------------------------------------------------------------- */
177 print_methods_and_signals (GDBusConnection *c,
180 gboolean print_methods,
181 gboolean print_signals)
185 const gchar *xml_data;
191 result = g_dbus_connection_call_sync (c,
194 "org.freedesktop.DBus.Introspectable",
197 G_VARIANT_TYPE ("(s)"),
198 G_DBUS_CALL_FLAGS_NONE,
204 g_printerr (_("Error: %s\n"), error->message);
205 g_error_free (error);
208 g_variant_get (result, "(&s)", &xml_data);
211 node = g_dbus_node_info_new_for_xml (xml_data, &error);
212 g_variant_unref (result);
215 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
216 g_error_free (error);
220 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
222 const GDBusInterfaceInfo *iface = node->interfaces[n];
223 for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++)
225 const GDBusMethodInfo *method = iface->methods[m];
226 g_print ("%s.%s \n", iface->name, method->name);
228 for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++)
230 const GDBusSignalInfo *signal = iface->signals[m];
231 g_print ("%s.%s \n", iface->name, signal->name);
234 g_dbus_node_info_unref (node);
241 print_paths (GDBusConnection *c,
247 const gchar *xml_data;
251 if (!g_dbus_is_name (name))
253 g_printerr (_("Error: %s is not a valid name\n"), name);
256 if (!g_variant_is_object_path (path))
258 g_printerr (_("Error: %s is not a valid object path\n"), path);
263 result = g_dbus_connection_call_sync (c,
266 "org.freedesktop.DBus.Introspectable",
269 G_VARIANT_TYPE ("(s)"),
270 G_DBUS_CALL_FLAGS_NONE,
276 g_printerr (_("Error: %s\n"), error->message);
277 g_error_free (error);
280 g_variant_get (result, "(&s)", &xml_data);
282 //g_printerr ("xml='%s'", xml_data);
285 node = g_dbus_node_info_new_for_xml (xml_data, &error);
286 g_variant_unref (result);
289 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
290 g_error_free (error);
294 //g_printerr ("bar '%s'\n", path);
296 if (node->interfaces != NULL)
297 g_print ("%s \n", path);
299 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
303 //g_printerr ("foo '%s'\n", node->nodes[n].path);
305 if (g_strcmp0 (path, "/") == 0)
306 s = g_strdup_printf ("/%s", node->nodes[n]->path);
308 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
310 print_paths (c, name, s);
314 g_dbus_node_info_unref (node);
321 print_names (GDBusConnection *c,
322 gboolean include_unique_names)
328 GHashTable *name_set;
331 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
334 result = g_dbus_connection_call_sync (c,
335 "org.freedesktop.DBus",
336 "/org/freedesktop/DBus",
337 "org.freedesktop.DBus",
340 G_VARIANT_TYPE ("(as)"),
341 G_DBUS_CALL_FLAGS_NONE,
347 g_printerr (_("Error: %s\n"), error->message);
348 g_error_free (error);
351 g_variant_get (result, "(as)", &iter);
352 while (g_variant_iter_loop (iter, "s", &str))
353 g_hash_table_add (name_set, g_strdup (str));
354 g_variant_iter_free (iter);
355 g_variant_unref (result);
358 result = g_dbus_connection_call_sync (c,
359 "org.freedesktop.DBus",
360 "/org/freedesktop/DBus",
361 "org.freedesktop.DBus",
362 "ListActivatableNames",
364 G_VARIANT_TYPE ("(as)"),
365 G_DBUS_CALL_FLAGS_NONE,
371 g_printerr (_("Error: %s\n"), error->message);
372 g_error_free (error);
375 g_variant_get (result, "(as)", &iter);
376 while (g_variant_iter_loop (iter, "s", &str))
377 g_hash_table_add (name_set, g_strdup (str));
378 g_variant_iter_free (iter);
379 g_variant_unref (result);
381 keys = g_hash_table_steal_all_keys (name_set);
382 g_ptr_array_sort_values (keys, (GCompareFunc) g_strcmp0);
383 for (guint i = 0; i < keys->len; ++i)
385 const gchar *name = g_ptr_array_index (keys, i);
386 if (!include_unique_names && g_str_has_prefix (name, ":"))
389 g_print ("%s \n", name);
391 g_clear_pointer (&keys, g_ptr_array_unref);
394 g_hash_table_unref (name_set);
397 /* ---------------------------------------------------------------------------------------------------- */
399 static gboolean opt_connection_system = FALSE;
400 static gboolean opt_connection_session = FALSE;
401 static gchar *opt_connection_address = NULL;
403 static const GOptionEntry connection_entries[] =
405 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
406 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
407 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
411 static GOptionGroup *
412 connection_get_group (void)
414 static GOptionGroup *g;
416 g = g_option_group_new ("connection",
417 N_("Connection Endpoint Options:"),
418 N_("Options specifying the connection endpoint"),
421 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
422 g_option_group_add_entries (g, connection_entries);
427 static GDBusConnection *
428 connection_get_dbus_connection (gboolean require_message_bus,
435 /* First, ensure we have exactly one connect */
436 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
441 _("No connection endpoint specified"));
444 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
445 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
446 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
451 _("Multiple connection endpoints specified"));
455 if (opt_connection_system)
457 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
459 else if (opt_connection_session)
461 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
463 else if (opt_connection_address != NULL)
465 GDBusConnectionFlags flags = G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT;
466 if (require_message_bus)
467 flags |= G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION;
468 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
470 NULL, /* GDBusAuthObserver */
471 NULL, /* GCancellable */
479 /* ---------------------------------------------------------------------------------------------------- */
482 call_helper_get_method_in_signature (GDBusConnection *c,
485 const gchar *interface_name,
486 const gchar *method_name,
491 GDBusNodeInfo *node_info;
492 const gchar *xml_data;
493 GDBusInterfaceInfo *interface_info;
494 GDBusMethodInfo *method_info;
501 result = g_dbus_connection_call_sync (c,
504 "org.freedesktop.DBus.Introspectable",
507 G_VARIANT_TYPE ("(s)"),
508 G_DBUS_CALL_FLAGS_NONE,
515 g_variant_get (result, "(&s)", &xml_data);
516 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
517 if (node_info == NULL)
520 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
521 if (interface_info == NULL)
523 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
524 _("Warning: According to introspection data, interface “%s” does not exist\n"),
529 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
530 if (method_info == NULL)
532 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
533 _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"),
539 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
540 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
542 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
546 if (node_info != NULL)
547 g_dbus_node_info_unref (node_info);
549 g_variant_unref (result);
554 /* ---------------------------------------------------------------------------------------------------- */
557 _g_variant_parse_me_harder (GVariantType *type,
558 const gchar *given_str,
566 str = g_string_new ("\"");
567 for (n = 0; given_str[n] != '\0'; n++)
569 if (G_UNLIKELY (given_str[n] == '\"'))
570 g_string_append (str, "\\\"");
572 g_string_append_c (str, given_str[n]);
574 g_string_append_c (str, '"');
575 s = g_string_free (str, FALSE);
577 value = g_variant_parse (type,
587 /* ---------------------------------------------------------------------------------------------------- */
589 static gchar *opt_emit_dest = NULL;
590 static gchar *opt_emit_object_path = NULL;
591 static gchar *opt_emit_signal = NULL;
593 static const GOptionEntry emit_entries[] =
595 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
596 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
597 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
602 handle_emit (gint *argc,
604 gboolean request_completion,
605 const gchar *completion_cur,
606 const gchar *completion_prev)
613 GVariant *parameters;
614 gchar *interface_name;
616 GVariantBuilder builder;
617 gboolean skip_dashes;
620 gboolean complete_names, complete_paths, complete_signals;
625 interface_name = NULL;
628 modify_argv0_for_command (argc, argv, "emit");
630 o = command_option_context_new (NULL, _("Emit a signal."),
631 emit_entries, request_completion);
632 g_option_context_add_group (o, connection_get_group ());
634 complete_names = FALSE;
635 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
637 complete_names = TRUE;
638 remove_arg ((*argc) - 1, argc, argv);
641 complete_paths = FALSE;
642 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
644 complete_paths = TRUE;
645 remove_arg ((*argc) - 1, argc, argv);
648 complete_signals = FALSE;
649 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0)
651 complete_signals = TRUE;
652 remove_arg ((*argc) - 1, argc, argv);
655 if (!g_option_context_parse (o, argc, argv, NULL))
657 if (!request_completion)
659 s = g_option_context_get_help (o, FALSE, NULL);
660 g_printerr ("%s", s);
667 c = connection_get_dbus_connection ((opt_emit_dest != NULL), &error);
670 if (request_completion)
672 if (g_strcmp0 (completion_prev, "--address") == 0)
680 g_print ("--system \n--session \n--address \n");
685 g_printerr (_("Error connecting: %s\n"), error->message);
687 g_error_free (error);
691 /* validate and complete destination (bus name) */
694 print_names (c, FALSE);
697 if (request_completion && opt_emit_dest != NULL && g_strcmp0 ("--dest", completion_prev) == 0)
699 print_names (c, g_str_has_prefix (opt_emit_dest, ":"));
703 if (!request_completion && opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
705 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
709 if (opt_emit_dest == NULL && opt_emit_object_path == NULL && request_completion)
711 g_print ("--dest \n");
713 /* validate and complete object path */
714 if (opt_emit_dest != NULL && complete_paths)
716 print_paths (c, opt_emit_dest, "/");
719 if (opt_emit_object_path == NULL)
721 if (request_completion)
722 g_print ("--object-path \n");
724 g_printerr (_("Error: Object path is not specified\n"));
727 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
729 if (opt_emit_dest != NULL)
732 s = g_strdup (opt_emit_object_path);
733 p = strrchr (s, '/');
740 print_paths (c, opt_emit_dest, s);
745 if (!request_completion && !g_variant_is_object_path (opt_emit_object_path))
747 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
751 /* validate and complete signal (interface + signal name) */
752 if (opt_emit_dest != NULL && opt_emit_object_path != NULL && complete_signals)
754 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
757 if (opt_emit_signal == NULL)
759 /* don't keep repeatedly completing --signal */
760 if (request_completion)
762 if (g_strcmp0 ("--signal", completion_prev) != 0)
763 g_print ("--signal \n");
767 g_printerr (_("Error: Signal name is not specified\n"));
772 if (request_completion && opt_emit_dest != NULL && opt_emit_object_path != NULL &&
773 g_strcmp0 ("--signal", completion_prev) == 0)
775 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
778 s = strrchr (opt_emit_signal, '.');
779 if (!request_completion && s == NULL)
781 g_printerr (_("Error: Signal name “%s” is invalid\n"), opt_emit_signal);
784 signal_name = g_strdup (s + 1);
785 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
787 /* All done with completion now */
788 if (request_completion)
791 if (!g_dbus_is_interface_name (interface_name))
793 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
797 if (!g_dbus_is_member_name (signal_name))
799 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
803 /* Read parameters */
804 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
807 for (n = 1; n < (guint) *argc; n++)
811 /* Under certain conditions, g_option_context_parse returns the "--"
812 itself (setting off unparsed arguments), too: */
813 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
820 value = g_variant_parse (NULL,
829 context = g_variant_parse_error_print_context (error, (*argv)[n]);
830 g_error_free (error);
832 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
835 /* Use the original non-"parse-me-harder" error */
836 g_printerr (_("Error parsing parameter %d: %s\n"),
839 g_error_free (error);
841 g_variant_builder_clear (&builder);
846 g_variant_builder_add_value (&builder, value);
849 parameters = g_variant_builder_end (&builder);
851 if (parameters != NULL)
852 parameters = g_variant_ref_sink (parameters);
853 if (!g_dbus_connection_emit_signal (c,
855 opt_emit_object_path,
861 g_printerr (_("Error: %s\n"), error->message);
862 g_error_free (error);
866 if (!g_dbus_connection_flush_sync (c, NULL, &error))
868 g_printerr (_("Error flushing connection: %s\n"), error->message);
869 g_error_free (error);
878 if (parameters != NULL)
879 g_variant_unref (parameters);
880 g_free (interface_name);
881 g_free (signal_name);
882 g_option_context_free (o);
886 /* ---------------------------------------------------------------------------------------------------- */
888 static gchar *opt_call_dest = NULL;
889 static gchar *opt_call_object_path = NULL;
890 static gchar *opt_call_method = NULL;
891 static gint opt_call_timeout = -1;
892 static gboolean opt_call_interactive = FALSE;
894 static const GOptionEntry call_entries[] =
896 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
897 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
898 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
899 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
900 { "interactive", 'i', 0, G_OPTION_ARG_NONE, &opt_call_interactive, N_("Allow interactive authorization"), NULL},
905 handle_call (gint *argc,
907 gboolean request_completion,
908 const gchar *completion_cur,
909 const gchar *completion_prev)
916 GVariant *parameters;
917 gchar *interface_name;
920 GPtrArray *in_signature_types;
922 GUnixFDList *fd_list;
925 gboolean complete_names;
926 gboolean complete_paths;
927 gboolean complete_methods;
928 GVariantBuilder builder;
929 gboolean skip_dashes;
932 GDBusCallFlags flags;
937 interface_name = NULL;
940 in_signature_types = NULL;
945 modify_argv0_for_command (argc, argv, "call");
947 o = command_option_context_new (NULL, _("Invoke a method on a remote object."),
948 call_entries, request_completion);
949 g_option_context_add_group (o, connection_get_group ());
951 complete_names = FALSE;
952 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
954 complete_names = TRUE;
955 remove_arg ((*argc) - 1, argc, argv);
958 complete_paths = FALSE;
959 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
961 complete_paths = TRUE;
962 remove_arg ((*argc) - 1, argc, argv);
965 complete_methods = FALSE;
966 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
968 complete_methods = TRUE;
969 remove_arg ((*argc) - 1, argc, argv);
972 if (!g_option_context_parse (o, argc, argv, NULL))
974 if (!request_completion)
976 s = g_option_context_get_help (o, FALSE, NULL);
977 g_printerr ("%s", s);
984 c = connection_get_dbus_connection (TRUE, &error);
987 if (request_completion)
989 if (g_strcmp0 (completion_prev, "--address") == 0)
997 g_print ("--system \n--session \n--address \n");
1002 g_printerr (_("Error connecting: %s\n"), error->message);
1004 g_error_free (error);
1008 /* validate and complete destination (bus name) */
1011 print_names (c, FALSE);
1014 if (opt_call_dest == NULL)
1016 if (request_completion)
1017 g_print ("--dest \n");
1019 g_printerr (_("Error: Destination is not specified\n"));
1022 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1024 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
1028 if (!request_completion && !g_dbus_is_name (opt_call_dest))
1030 g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest);
1034 /* validate and complete object path */
1037 print_paths (c, opt_call_dest, "/");
1040 if (opt_call_object_path == NULL)
1042 if (request_completion)
1043 g_print ("--object-path \n");
1045 g_printerr (_("Error: Object path is not specified\n"));
1048 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1051 s = g_strdup (opt_call_object_path);
1052 p = strrchr (s, '/');
1059 print_paths (c, opt_call_dest, s);
1063 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
1065 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
1069 /* validate and complete method (interface + method name) */
1070 if (complete_methods)
1072 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1075 if (opt_call_method == NULL)
1077 if (request_completion)
1078 g_print ("--method \n");
1080 g_printerr (_("Error: Method name is not specified\n"));
1083 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
1085 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1088 s = strrchr (opt_call_method, '.');
1089 if (!request_completion && s == NULL)
1091 g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method);
1094 method_name = g_strdup (s + 1);
1095 interface_name = g_strndup (opt_call_method, s - opt_call_method);
1097 /* All done with completion now */
1098 if (request_completion)
1101 /* Introspect, for easy conversion - it's not fatal if we can't do this */
1102 in_signature_types = call_helper_get_method_in_signature (c,
1104 opt_call_object_path,
1108 if (in_signature_types == NULL)
1110 //g_printerr ("Error getting introspection data: %s\n", error->message);
1111 g_error_free (error);
1115 /* Read parameters */
1116 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
1119 for (n = 1; n < (guint) *argc; n++)
1124 /* Under certain conditions, g_option_context_parse returns the "--"
1125 itself (setting off unparsed arguments), too: */
1126 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
1128 skip_dashes = FALSE;
1133 if (in_signature_types != NULL)
1135 if (parm >= in_signature_types->len)
1137 /* Only warn for the first param */
1138 if (parm == in_signature_types->len)
1140 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
1141 in_signature_types->len);
1146 type = in_signature_types->pdata[parm];
1151 value = g_variant_parse (type,
1160 context = g_variant_parse_error_print_context (error, (*argv)[n]);
1161 g_error_free (error);
1163 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1168 s = g_variant_type_dup_string (type);
1169 g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"),
1177 g_printerr (_("Error parsing parameter %d: %s\n"),
1181 g_error_free (error);
1182 g_variant_builder_clear (&builder);
1189 if (g_variant_is_of_type (value, G_VARIANT_TYPE_HANDLE))
1192 fd_list = g_unix_fd_list_new ();
1193 if ((fd_id = g_unix_fd_list_append (fd_list, g_variant_get_handle (value), &error)) == -1)
1195 g_printerr (_("Error adding handle %d: %s\n"),
1196 g_variant_get_handle (value), error->message);
1197 g_variant_builder_clear (&builder);
1198 g_error_free (error);
1201 g_variant_unref (value);
1202 value = g_variant_new_handle (fd_id);
1205 g_variant_builder_add_value (&builder, value);
1208 parameters = g_variant_builder_end (&builder);
1210 if (parameters != NULL)
1211 parameters = g_variant_ref_sink (parameters);
1213 flags = G_DBUS_CALL_FLAGS_NONE;
1214 if (opt_call_interactive)
1215 flags |= G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION;
1218 result = g_dbus_connection_call_with_unix_fd_list_sync (c,
1220 opt_call_object_path,
1226 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1232 result = g_dbus_connection_call_sync (c,
1234 opt_call_object_path,
1240 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1246 g_printerr (_("Error: %s\n"), error->message);
1248 if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL)
1250 if (in_signature_types->len > 0)
1253 str = g_string_new (NULL);
1255 for (n = 0; n < in_signature_types->len; n++)
1257 GVariantType *type = in_signature_types->pdata[n];
1258 g_string_append_len (str,
1259 g_variant_type_peek_string (type),
1260 g_variant_type_get_string_length (type));
1263 g_printerr ("(According to introspection data, you need to pass '%s')\n", str->str);
1264 g_string_free (str, TRUE);
1267 g_printerr ("(According to introspection data, you need to pass no arguments)\n");
1270 g_error_free (error);
1274 s = g_variant_print (result, TRUE);
1275 g_print ("%s\n", s);
1281 if (in_signature_types != NULL)
1282 g_ptr_array_unref (in_signature_types);
1284 g_variant_unref (result);
1287 if (parameters != NULL)
1288 g_variant_unref (parameters);
1289 g_free (interface_name);
1290 g_free (method_name);
1291 g_option_context_free (o);
1293 g_clear_object (&fd_list);
1298 /* ---------------------------------------------------------------------------------------------------- */
1300 static gchar *opt_introspect_dest = NULL;
1301 static gchar *opt_introspect_object_path = NULL;
1302 static gboolean opt_introspect_xml = FALSE;
1303 static gboolean opt_introspect_recurse = FALSE;
1304 static gboolean opt_introspect_only_properties = FALSE;
1306 /* Introspect colors */
1307 #define RESET_COLOR (use_colors? "\033[0m": "")
1308 #define INTROSPECT_TITLE_COLOR (use_colors? UNDERLINE: "")
1309 #define INTROSPECT_NODE_COLOR (use_colors? RESET_COLOR: "")
1310 #define INTROSPECT_INTERFACE_COLOR (use_colors? YELLOW: "")
1311 #define INTROSPECT_METHOD_COLOR (use_colors? BLUE: "")
1312 #define INTROSPECT_SIGNAL_COLOR (use_colors? BLUE: "")
1313 #define INTROSPECT_PROPERTY_COLOR (use_colors? MAGENTA: "")
1314 #define INTROSPECT_INOUT_COLOR (use_colors? RESET_COLOR: "")
1315 #define INTROSPECT_TYPE_COLOR (use_colors? GREEN: "")
1316 #define INTROSPECT_ANNOTATION_COLOR (use_colors? RESET_COLOR: "")
1319 dump_annotation (const GDBusAnnotationInfo *o,
1321 gboolean ignore_indent,
1322 gboolean use_colors)
1325 g_print ("%*s%s@%s(\"%s\")%s\n",
1326 ignore_indent ? 0 : indent, "",
1327 INTROSPECT_ANNOTATION_COLOR, o->key, o->value, RESET_COLOR);
1328 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1329 dump_annotation (o->annotations[n], indent + 2, FALSE, use_colors);
1333 dump_arg (const GDBusArgInfo *o,
1335 const gchar *direction,
1336 gboolean ignore_indent,
1337 gboolean include_newline,
1338 gboolean use_colors)
1342 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1344 dump_annotation (o->annotations[n], indent, ignore_indent, use_colors);
1345 ignore_indent = FALSE;
1348 g_print ("%*s%s%s%s%s%s%s %s%s",
1349 ignore_indent ? 0 : indent, "",
1350 INTROSPECT_INOUT_COLOR, direction, RESET_COLOR,
1351 INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1353 include_newline ? ",\n" : "");
1357 count_args (GDBusArgInfo **args)
1363 while (args[n] != NULL)
1370 dump_method (const GDBusMethodInfo *o,
1372 gboolean use_colors)
1377 guint total_num_args;
1379 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1380 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1382 g_print ("%*s%s%s%s(",
1384 INTROSPECT_METHOD_COLOR, o->name, RESET_COLOR);
1385 name_len = strlen (o->name);
1386 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1387 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1389 gboolean ignore_indent = (m == 0);
1390 gboolean include_newline = (m != total_num_args - 1);
1392 dump_arg (o->in_args[n],
1393 indent + name_len + 1,
1399 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1401 gboolean ignore_indent = (m == 0);
1402 gboolean include_newline = (m != total_num_args - 1);
1403 dump_arg (o->out_args[n],
1404 indent + name_len + 1,
1414 dump_signal (const GDBusSignalInfo *o,
1416 gboolean use_colors)
1420 guint total_num_args;
1422 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1423 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1425 g_print ("%*s%s%s%s(",
1427 INTROSPECT_SIGNAL_COLOR, o->name, RESET_COLOR);
1428 name_len = strlen (o->name);
1429 total_num_args = count_args (o->args);
1430 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1432 gboolean ignore_indent = (n == 0);
1433 gboolean include_newline = (n != total_num_args - 1);
1434 dump_arg (o->args[n],
1435 indent + name_len + 1,
1445 dump_property (const GDBusPropertyInfo *o,
1447 gboolean use_colors,
1450 const gchar *access;
1453 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1454 access = "readonly";
1455 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1456 access = "writeonly";
1457 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1458 access = "readwrite";
1460 g_assert_not_reached ();
1462 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1463 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1467 gchar *s = g_variant_print (value, FALSE);
1468 g_print ("%*s%s %s%s%s %s%s%s = %s;\n", indent, "", access,
1469 INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1470 INTROSPECT_PROPERTY_COLOR, o->name, RESET_COLOR,
1476 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1481 dump_interface (GDBusConnection *c,
1483 const GDBusInterfaceInfo *o,
1485 gboolean use_colors,
1486 const gchar *object_path)
1489 GHashTable *properties;
1491 properties = g_hash_table_new_full (g_str_hash,
1494 (GDestroyNotify) g_variant_unref);
1496 /* Try to get properties */
1497 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1500 result = g_dbus_connection_call_sync (c,
1503 "org.freedesktop.DBus.Properties",
1505 g_variant_new ("(s)", o->name),
1507 G_DBUS_CALL_FLAGS_NONE,
1513 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1517 g_variant_get (result,
1520 while ((item = g_variant_iter_next_value (iter)))
1524 g_variant_get (item,
1529 g_hash_table_insert (properties, key, g_variant_ref (value));
1532 g_variant_unref (result);
1536 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1538 result = g_dbus_connection_call_sync (c,
1541 "org.freedesktop.DBus.Properties",
1543 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1544 G_VARIANT_TYPE ("(v)"),
1545 G_DBUS_CALL_FLAGS_NONE,
1551 GVariant *property_value;
1552 g_variant_get (result,
1555 g_hash_table_insert (properties,
1556 g_strdup (o->properties[n]->name),
1557 g_variant_ref (property_value));
1558 g_variant_unref (result);
1564 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1565 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1567 g_print ("%*s%sinterface %s%s {\n",
1569 INTROSPECT_INTERFACE_COLOR, o->name, RESET_COLOR);
1570 if (o->methods != NULL && !opt_introspect_only_properties)
1572 g_print ("%*s %smethods%s:\n",
1574 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1575 for (n = 0; o->methods[n] != NULL; n++)
1576 dump_method (o->methods[n], indent + 4, use_colors);
1578 if (o->signals != NULL && !opt_introspect_only_properties)
1580 g_print ("%*s %ssignals%s:\n",
1582 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1583 for (n = 0; o->signals[n] != NULL; n++)
1584 dump_signal (o->signals[n], indent + 4, use_colors);
1586 if (o->properties != NULL)
1588 g_print ("%*s %sproperties%s:\n",
1590 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1591 for (n = 0; o->properties[n] != NULL; n++)
1593 dump_property (o->properties[n],
1596 g_hash_table_lookup (properties, (o->properties[n])->name));
1602 g_hash_table_unref (properties);
1606 introspect_do (GDBusConnection *c,
1607 const gchar *object_path,
1609 gboolean use_colors);
1612 dump_node (GDBusConnection *c,
1614 const GDBusNodeInfo *o,
1616 gboolean use_colors,
1617 const gchar *object_path,
1621 const gchar *object_path_to_print;
1623 object_path_to_print = object_path;
1624 if (o->path != NULL)
1625 object_path_to_print = o->path;
1627 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1628 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1630 g_print ("%*s%snode %s%s",
1632 INTROSPECT_NODE_COLOR,
1633 object_path_to_print != NULL ? object_path_to_print : "(not set)",
1635 if (o->interfaces != NULL || o->nodes != NULL)
1638 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1640 if (opt_introspect_only_properties)
1642 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1643 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1647 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1650 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1655 if (g_variant_is_object_path (o->nodes[n]->path))
1657 child_path = g_strdup (o->nodes[n]->path);
1658 /* avoid infinite loops */
1659 if (g_str_has_prefix (child_path, object_path))
1661 introspect_do (c, child_path, indent + 2, use_colors);
1665 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1666 child_path, object_path);
1671 if (g_strcmp0 (object_path, "/") == 0)
1672 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1674 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1675 introspect_do (c, child_path, indent + 2, use_colors);
1677 g_free (child_path);
1681 dump_node (NULL, NULL, o->nodes[n], indent + 2, use_colors, NULL, recurse);
1693 static const GOptionEntry introspect_entries[] =
1695 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1696 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1697 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1698 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1699 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1704 introspect_do (GDBusConnection *c,
1705 const gchar *object_path,
1707 gboolean use_colors)
1711 GDBusNodeInfo *node;
1713 const gchar *xml_data;
1720 result = g_dbus_connection_call_sync (c,
1721 opt_introspect_dest,
1723 "org.freedesktop.DBus.Introspectable",
1726 G_VARIANT_TYPE ("(s)"),
1727 G_DBUS_CALL_FLAGS_NONE,
1733 g_printerr (_("Error: %s\n"), error->message);
1734 g_error_free (error);
1737 g_variant_get (result, "(&s)", &xml_data);
1739 if (opt_introspect_xml)
1741 g_print ("%s", xml_data);
1746 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1749 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1750 g_error_free (error);
1754 dump_node (c, opt_introspect_dest, node, indent, use_colors, object_path, opt_introspect_recurse);
1761 g_dbus_node_info_unref (node);
1763 g_variant_unref (result);
1768 handle_introspect (gint *argc,
1770 gboolean request_completion,
1771 const gchar *completion_cur,
1772 const gchar *completion_prev)
1779 gboolean complete_names;
1780 gboolean complete_paths;
1781 gboolean color_support;
1786 modify_argv0_for_command (argc, argv, "introspect");
1788 o = command_option_context_new (NULL, _("Introspect a remote object."),
1789 introspect_entries, request_completion);
1790 g_option_context_add_group (o, connection_get_group ());
1792 complete_names = FALSE;
1793 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1795 complete_names = TRUE;
1796 remove_arg ((*argc) - 1, argc, argv);
1799 complete_paths = FALSE;
1800 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1802 complete_paths = TRUE;
1803 remove_arg ((*argc) - 1, argc, argv);
1806 if (!g_option_context_parse (o, argc, argv, NULL))
1808 if (!request_completion)
1810 s = g_option_context_get_help (o, FALSE, NULL);
1811 g_printerr ("%s", s);
1818 c = connection_get_dbus_connection (TRUE, &error);
1821 if (request_completion)
1823 if (g_strcmp0 (completion_prev, "--address") == 0)
1831 g_print ("--system \n--session \n--address \n");
1836 g_printerr (_("Error connecting: %s\n"), error->message);
1838 g_error_free (error);
1844 print_names (c, FALSE);
1847 /* this only makes sense on message bus connections */
1848 if (opt_introspect_dest == NULL)
1850 if (request_completion)
1851 g_print ("--dest \n");
1853 g_printerr (_("Error: Destination is not specified\n"));
1856 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1858 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1864 print_paths (c, opt_introspect_dest, "/");
1868 if (!request_completion && !g_dbus_is_name (opt_introspect_dest))
1870 g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest);
1874 if (opt_introspect_object_path == NULL)
1876 if (request_completion)
1877 g_print ("--object-path \n");
1879 g_printerr (_("Error: Object path is not specified\n"));
1882 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1885 s = g_strdup (opt_introspect_object_path);
1886 p = strrchr (s, '/');
1893 print_paths (c, opt_introspect_dest, s);
1897 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1899 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1903 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1905 g_print ("--recurse \n");
1908 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1910 g_print ("--only-properties \n");
1913 /* All done with completion now */
1914 if (request_completion)
1917 /* Before we start printing the actual info, check if we can do colors*/
1918 color_support = g_log_writer_supports_color (fileno (stdout));
1920 if (!introspect_do (c, opt_introspect_object_path, 0, color_support))
1928 g_option_context_free (o);
1932 /* ---------------------------------------------------------------------------------------------------- */
1934 static gchar *opt_monitor_dest = NULL;
1935 static gchar *opt_monitor_object_path = NULL;
1937 static guint monitor_filter_id = 0;
1940 monitor_signal_cb (GDBusConnection *connection,
1941 const gchar *sender_name,
1942 const gchar *object_path,
1943 const gchar *interface_name,
1944 const gchar *signal_name,
1945 GVariant *parameters,
1949 s = g_variant_print (parameters, TRUE);
1950 g_print ("%s: %s.%s %s\n",
1959 monitor_on_name_appeared (GDBusConnection *connection,
1961 const gchar *name_owner,
1964 g_print ("The name %s is owned by %s\n", name, name_owner);
1965 g_assert (monitor_filter_id == 0);
1966 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1968 NULL, /* any interface */
1969 NULL, /* any member */
1970 opt_monitor_object_path,
1972 G_DBUS_SIGNAL_FLAGS_NONE,
1974 NULL, /* user_data */
1975 NULL); /* user_data destroy notify */
1979 monitor_on_name_vanished (GDBusConnection *connection,
1983 g_print ("The name %s does not have an owner\n", name);
1985 if (monitor_filter_id != 0)
1987 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1988 monitor_filter_id = 0;
1992 static const GOptionEntry monitor_entries[] =
1994 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1995 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
2000 handle_monitor (gint *argc,
2002 gboolean request_completion,
2003 const gchar *completion_cur,
2004 const gchar *completion_prev)
2011 gboolean complete_names;
2012 gboolean complete_paths;
2018 modify_argv0_for_command (argc, argv, "monitor");
2020 o = command_option_context_new (NULL, _("Monitor a remote object."),
2021 monitor_entries, request_completion);
2022 g_option_context_add_group (o, connection_get_group ());
2024 complete_names = FALSE;
2025 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
2027 complete_names = TRUE;
2028 remove_arg ((*argc) - 1, argc, argv);
2031 complete_paths = FALSE;
2032 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
2034 complete_paths = TRUE;
2035 remove_arg ((*argc) - 1, argc, argv);
2038 if (!g_option_context_parse (o, argc, argv, NULL))
2040 if (!request_completion)
2042 s = g_option_context_get_help (o, FALSE, NULL);
2043 g_printerr ("%s", s);
2050 c = connection_get_dbus_connection (TRUE, &error);
2053 if (request_completion)
2055 if (g_strcmp0 (completion_prev, "--address") == 0)
2063 g_print ("--system \n--session \n--address \n");
2068 g_printerr (_("Error connecting: %s\n"), error->message);
2070 g_error_free (error);
2074 /* Monitoring doesn’t make sense on a non-message-bus connection. */
2075 if (g_dbus_connection_get_unique_name (c) == NULL)
2077 if (!request_completion)
2078 g_printerr (_("Error: can’t monitor a non-message-bus connection\n"));
2084 print_names (c, FALSE);
2087 /* this only makes sense on message bus connections */
2088 if (opt_monitor_dest == NULL)
2090 if (request_completion)
2091 g_print ("--dest \n");
2093 g_printerr (_("Error: Destination is not specified\n"));
2096 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
2098 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
2102 if (!request_completion && !g_dbus_is_name (opt_monitor_dest))
2104 g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest);
2110 print_paths (c, opt_monitor_dest, "/");
2113 if (opt_monitor_object_path == NULL)
2115 if (request_completion)
2117 g_print ("--object-path \n");
2120 /* it's fine to not have an object path */
2122 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
2125 s = g_strdup (opt_monitor_object_path);
2126 p = strrchr (s, '/');
2133 print_paths (c, opt_monitor_dest, s);
2137 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
2139 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
2143 /* All done with completion now */
2144 if (request_completion)
2147 if (opt_monitor_object_path != NULL)
2148 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
2150 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
2152 loop = g_main_loop_new (NULL, FALSE);
2153 g_bus_watch_name_on_connection (c,
2155 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2156 monitor_on_name_appeared,
2157 monitor_on_name_vanished,
2161 g_main_loop_run (loop);
2162 g_main_loop_unref (loop);
2169 g_option_context_free (o);
2173 /* ---------------------------------------------------------------------------------------------------- */
2175 static gboolean opt_wait_activate_set = FALSE;
2176 static gchar *opt_wait_activate_name = NULL;
2177 static gint64 opt_wait_timeout_secs = 0; /* no timeout */
2180 WAIT_STATE_RUNNING, /* waiting to see the service */
2181 WAIT_STATE_SUCCESS, /* seen it successfully */
2182 WAIT_STATE_TIMEOUT, /* timed out before seeing it */
2186 opt_wait_activate_cb (const gchar *option_name,
2191 /* @value may be NULL */
2192 opt_wait_activate_set = TRUE;
2193 opt_wait_activate_name = g_strdup (value);
2198 static const GOptionEntry wait_entries[] =
2200 { "activate", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
2201 opt_wait_activate_cb,
2202 N_("Service to activate before waiting for the other one (well-known name)"),
2204 { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout_secs,
2205 N_("Timeout to wait for before exiting with an error (seconds); 0 for "
2206 "no timeout (default)"), "SECS" },
2211 wait_name_appeared_cb (GDBusConnection *connection,
2213 const gchar *name_owner,
2216 WaitState *wait_state = user_data;
2218 *wait_state = WAIT_STATE_SUCCESS;
2222 wait_timeout_cb (gpointer user_data)
2224 WaitState *wait_state = user_data;
2226 *wait_state = WAIT_STATE_TIMEOUT;
2228 /* Removed in handle_wait(). */
2229 return G_SOURCE_CONTINUE;
2233 handle_wait (gint *argc,
2235 gboolean request_completion,
2236 const gchar *completion_cur,
2237 const gchar *completion_prev)
2244 guint watch_id, timer_id = 0, activate_watch_id;
2245 const gchar *activate_service, *wait_service;
2246 WaitState wait_state = WAIT_STATE_RUNNING;
2251 modify_argv0_for_command (argc, argv, "wait");
2253 o = command_option_context_new (_("[OPTION…] BUS-NAME"),
2254 _("Wait for a bus name to appear."),
2255 wait_entries, request_completion);
2256 g_option_context_add_group (o, connection_get_group ());
2258 if (!g_option_context_parse (o, argc, argv, NULL))
2260 if (!request_completion)
2262 s = g_option_context_get_help (o, FALSE, NULL);
2263 g_printerr ("%s", s);
2270 c = connection_get_dbus_connection (TRUE, &error);
2273 if (request_completion)
2275 if (g_strcmp0 (completion_prev, "--address") == 0)
2283 g_print ("--system \n--session \n--address \n");
2288 g_printerr (_("Error connecting: %s\n"), error->message);
2290 g_error_free (error);
2294 /* All done with completion now */
2295 if (request_completion)
2299 * Try and disentangle the command line arguments, with the aim of supporting:
2300 * gdbus wait --session --activate ActivateName WaitName
2301 * gdbus wait --session --activate ActivateAndWaitName
2302 * gdbus wait --activate --session ActivateAndWaitName
2303 * gdbus wait --session WaitName
2305 if (*argc == 2 && opt_wait_activate_set && opt_wait_activate_name != NULL)
2307 activate_service = opt_wait_activate_name;
2308 wait_service = (*argv)[1];
2310 else if (*argc == 2 &&
2311 opt_wait_activate_set && opt_wait_activate_name == NULL)
2313 activate_service = (*argv)[1];
2314 wait_service = (*argv)[1];
2316 else if (*argc == 2 && !opt_wait_activate_set)
2318 activate_service = NULL; /* disabled */
2319 wait_service = (*argv)[1];
2321 else if (*argc == 1 &&
2322 opt_wait_activate_set && opt_wait_activate_name != NULL)
2324 activate_service = opt_wait_activate_name;
2325 wait_service = opt_wait_activate_name;
2327 else if (*argc == 1 &&
2328 opt_wait_activate_set && opt_wait_activate_name == NULL)
2330 g_printerr (_("Error: A service to activate for must be specified.\n"));
2333 else if (*argc == 1 && !opt_wait_activate_set)
2335 g_printerr (_("Error: A service to wait for must be specified.\n"));
2338 else /* if (*argc > 2) */
2340 g_printerr (_("Error: Too many arguments.\n"));
2344 if (activate_service != NULL &&
2345 (!g_dbus_is_name (activate_service) ||
2346 g_dbus_is_unique_name (activate_service)))
2348 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2353 if (!g_dbus_is_name (wait_service) || g_dbus_is_unique_name (wait_service))
2355 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2360 /* Start the prerequisite service if needed. */
2361 if (activate_service != NULL)
2363 activate_watch_id = g_bus_watch_name_on_connection (c, activate_service,
2364 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2370 activate_watch_id = 0;
2373 /* Wait for the expected name to appear. */
2374 watch_id = g_bus_watch_name_on_connection (c,
2376 G_BUS_NAME_WATCHER_FLAGS_NONE,
2377 wait_name_appeared_cb,
2378 NULL, &wait_state, NULL);
2380 /* Safety timeout. */
2381 if (opt_wait_timeout_secs > 0)
2382 timer_id = g_timeout_add_seconds (opt_wait_timeout_secs, wait_timeout_cb, &wait_state);
2384 while (wait_state == WAIT_STATE_RUNNING)
2385 g_main_context_iteration (NULL, TRUE);
2387 g_bus_unwatch_name (watch_id);
2389 g_source_remove (timer_id);
2390 if (activate_watch_id != 0)
2391 g_bus_unwatch_name (activate_watch_id);
2393 ret = (wait_state == WAIT_STATE_SUCCESS);
2396 g_clear_object (&c);
2397 g_option_context_free (o);
2398 g_free (opt_wait_activate_name);
2399 opt_wait_activate_name = NULL;
2404 /* ---------------------------------------------------------------------------------------------------- */
2407 pick_word_at (const gchar *s,
2409 gint *out_word_begins_at)
2416 if (out_word_begins_at != NULL)
2417 *out_word_begins_at = -1;
2421 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
2423 if (out_word_begins_at != NULL)
2424 *out_word_begins_at = cursor;
2425 return g_strdup ("");
2428 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
2433 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
2436 if (out_word_begins_at != NULL)
2437 *out_word_begins_at = begin;
2439 return g_strndup (s + begin, end - begin);
2443 main (gint argc, gchar *argv[])
2446 const gchar *command;
2447 gboolean request_completion;
2448 gchar *completion_cur;
2449 gchar *completion_prev;
2454 setlocale (LC_ALL, "");
2455 textdomain (GETTEXT_PACKAGE);
2458 tmp = _glib_get_locale_dir ();
2459 bindtextdomain (GETTEXT_PACKAGE, tmp);
2462 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2465 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2466 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2470 completion_cur = NULL;
2471 completion_prev = NULL;
2475 usage (&argc, &argv, FALSE);
2479 request_completion = FALSE;
2481 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
2485 if (g_strcmp0 (command, "help") == 0)
2487 if (request_completion)
2493 usage (&argc, &argv, TRUE);
2498 else if (g_strcmp0 (command, "emit") == 0)
2500 if (handle_emit (&argc,
2508 else if (g_strcmp0 (command, "call") == 0)
2510 if (handle_call (&argc,
2518 else if (g_strcmp0 (command, "introspect") == 0)
2520 if (handle_introspect (&argc,
2528 else if (g_strcmp0 (command, "monitor") == 0)
2530 if (handle_monitor (&argc,
2538 else if (g_strcmp0 (command, "wait") == 0)
2540 if (handle_wait (&argc,
2549 else if (g_strcmp0 (command, _GDBUS_ARG_WIN32_RUN_SESSION_BUS) == 0)
2551 g_win32_run_session_bus (NULL, NULL, NULL, 0);
2556 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2558 const gchar *completion_line;
2559 gchar **completion_argv;
2560 gint completion_argc;
2561 gint completion_point;
2565 request_completion = TRUE;
2567 completion_line = argv[2];
2568 completion_point = strtol (argv[3], &endp, 10);
2569 if (endp == argv[3] || *endp != '\0')
2573 completion_debug ("completion_point=%d", completion_point);
2574 completion_debug ("----");
2575 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2576 completion_debug ("'%s'", completion_line);
2577 completion_debug (" %*s^",
2578 completion_point, "");
2579 completion_debug ("----");
2582 if (!g_shell_parse_argv (completion_line,
2587 /* it's very possible the command line can't be parsed (for
2588 * example, missing quotes etc) - in that case, we just
2589 * don't autocomplete at all
2594 /* compute cur and prev */
2595 completion_prev = NULL;
2596 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2600 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2602 if (!g_ascii_isspace (completion_line[prev_end]))
2604 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2610 completion_debug (" cur='%s'", completion_cur);
2611 completion_debug ("prev='%s'", completion_prev);
2614 argc = completion_argc;
2615 argv = completion_argv;
2623 if (request_completion)
2625 g_print ("help \nemit \ncall \nintrospect \nmonitor \nwait \n");
2631 g_printerr ("Unknown command '%s'\n", command);
2632 usage (&argc, &argv, FALSE);
2638 g_free (completion_cur);
2639 g_free (completion_prev);