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.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
33 #include "glib/glib-private.h"
34 #include "gdbusprivate.h"
37 /* ---------------------------------------------------------------------------------------------------- */
39 /* Escape values for console colors */
40 #define UNDERLINE "\033[4m"
41 #define BLUE "\033[34m"
42 #define CYAN "\033[36m"
43 #define GREEN "\033[32m"
44 #define MAGENTA "\033[35m"
45 #define RED "\033[31m"
46 #define YELLOW "\033[33m"
48 /* ---------------------------------------------------------------------------------------------------- */
50 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
52 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
53 * to not have it interfere with stdout/stderr)
56 G_GNUC_UNUSED static void
57 completion_debug (const gchar *format, ...)
61 static FILE *f = NULL;
63 va_start (var_args, format);
64 s = g_strdup_vprintf (format, var_args);
67 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
69 fprintf (f, "%s\n", s);
74 completion_debug (const gchar *format, ...)
79 /* ---------------------------------------------------------------------------------------------------- */
83 remove_arg (gint num, gint *argc, gchar **argv[])
87 g_assert (num <= (*argc));
89 for (n = num; (*argv)[n] != NULL; n++)
90 (*argv)[n] = (*argv)[n+1];
92 (*argc) = (*argc) - 1;
96 usage (gint *argc, gchar **argv[], gboolean use_stdout)
102 o = g_option_context_new (_("COMMAND"));
103 g_option_context_set_help_enabled (o, FALSE);
104 /* Ignore parsing result */
105 g_option_context_parse (o, argc, argv, NULL);
106 program_name = g_path_get_basename ((*argv)[0]);
107 s = g_strdup_printf (_("Commands:\n"
108 " help Shows this information\n"
109 " introspect Introspect a remote object\n"
110 " monitor Monitor a remote object\n"
111 " call Invoke a method on a remote object\n"
112 " emit Emit a signal\n"
113 " wait Wait for a bus name to appear\n"
115 "Use “%s COMMAND --help” to get help on each command.\n"),
117 g_free (program_name);
118 g_option_context_set_description (o, s);
120 s = g_option_context_get_help (o, FALSE, NULL);
124 g_printerr ("%s", s);
126 g_option_context_free (o);
130 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
136 * 1. get a g_set_prgname() ?; or
137 * 2. save old argv[0] and restore later
140 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
141 remove_arg (1, argc, argv);
143 program_name = g_path_get_basename ((*argv)[0]);
144 s = g_strdup_printf ("%s %s", (*argv)[0], command);
146 g_free (program_name);
149 static GOptionContext *
150 command_option_context_new (const gchar *parameter_string,
151 const gchar *summary,
152 const GOptionEntry *entries,
153 gboolean request_completion)
155 GOptionContext *o = NULL;
157 o = g_option_context_new (parameter_string);
158 if (request_completion)
159 g_option_context_set_ignore_unknown_options (o, TRUE);
160 g_option_context_set_help_enabled (o, FALSE);
161 g_option_context_set_summary (o, summary);
162 g_option_context_add_main_entries (o, entries, GETTEXT_PACKAGE);
164 return g_steal_pointer (&o);
167 /* ---------------------------------------------------------------------------------------------------- */
170 print_methods_and_signals (GDBusConnection *c,
173 gboolean print_methods,
174 gboolean print_signals)
178 const gchar *xml_data;
184 result = g_dbus_connection_call_sync (c,
187 "org.freedesktop.DBus.Introspectable",
190 G_VARIANT_TYPE ("(s)"),
191 G_DBUS_CALL_FLAGS_NONE,
197 g_printerr (_("Error: %s\n"), error->message);
198 g_error_free (error);
201 g_variant_get (result, "(&s)", &xml_data);
204 node = g_dbus_node_info_new_for_xml (xml_data, &error);
205 g_variant_unref (result);
208 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
209 g_error_free (error);
213 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
215 const GDBusInterfaceInfo *iface = node->interfaces[n];
216 for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++)
218 const GDBusMethodInfo *method = iface->methods[m];
219 g_print ("%s.%s \n", iface->name, method->name);
221 for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++)
223 const GDBusSignalInfo *signal = iface->signals[m];
224 g_print ("%s.%s \n", iface->name, signal->name);
227 g_dbus_node_info_unref (node);
234 print_paths (GDBusConnection *c,
240 const gchar *xml_data;
244 if (!g_dbus_is_name (name))
246 g_printerr (_("Error: %s is not a valid name\n"), name);
251 result = g_dbus_connection_call_sync (c,
254 "org.freedesktop.DBus.Introspectable",
257 G_VARIANT_TYPE ("(s)"),
258 G_DBUS_CALL_FLAGS_NONE,
264 g_printerr (_("Error: %s\n"), error->message);
265 g_error_free (error);
268 g_variant_get (result, "(&s)", &xml_data);
270 //g_printerr ("xml='%s'", xml_data);
273 node = g_dbus_node_info_new_for_xml (xml_data, &error);
274 g_variant_unref (result);
277 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
278 g_error_free (error);
282 //g_printerr ("bar '%s'\n", path);
284 if (node->interfaces != NULL)
285 g_print ("%s \n", path);
287 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
291 //g_printerr ("foo '%s'\n", node->nodes[n].path);
293 if (g_strcmp0 (path, "/") == 0)
294 s = g_strdup_printf ("/%s", node->nodes[n]->path);
296 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
298 print_paths (c, name, s);
302 g_dbus_node_info_unref (node);
309 print_names (GDBusConnection *c,
310 gboolean include_unique_names)
316 GHashTable *name_set;
320 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
323 result = g_dbus_connection_call_sync (c,
324 "org.freedesktop.DBus",
325 "/org/freedesktop/DBus",
326 "org.freedesktop.DBus",
329 G_VARIANT_TYPE ("(as)"),
330 G_DBUS_CALL_FLAGS_NONE,
336 g_printerr (_("Error: %s\n"), error->message);
337 g_error_free (error);
340 g_variant_get (result, "(as)", &iter);
341 while (g_variant_iter_loop (iter, "s", &str))
342 g_hash_table_add (name_set, g_strdup (str));
343 g_variant_iter_free (iter);
344 g_variant_unref (result);
347 result = g_dbus_connection_call_sync (c,
348 "org.freedesktop.DBus",
349 "/org/freedesktop/DBus",
350 "org.freedesktop.DBus",
351 "ListActivatableNames",
353 G_VARIANT_TYPE ("(as)"),
354 G_DBUS_CALL_FLAGS_NONE,
360 g_printerr (_("Error: %s\n"), error->message);
361 g_error_free (error);
364 g_variant_get (result, "(as)", &iter);
365 while (g_variant_iter_loop (iter, "s", &str))
366 g_hash_table_add (name_set, g_strdup (str));
367 g_variant_iter_free (iter);
368 g_variant_unref (result);
370 keys = g_hash_table_get_keys (name_set);
371 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
372 for (l = keys; l != NULL; l = l->next)
374 const gchar *name = l->data;
375 if (!include_unique_names && g_str_has_prefix (name, ":"))
378 g_print ("%s \n", name);
383 g_hash_table_unref (name_set);
386 /* ---------------------------------------------------------------------------------------------------- */
388 static gboolean opt_connection_system = FALSE;
389 static gboolean opt_connection_session = FALSE;
390 static gchar *opt_connection_address = NULL;
392 static const GOptionEntry connection_entries[] =
394 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
395 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
396 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
400 static GOptionGroup *
401 connection_get_group (void)
403 static GOptionGroup *g;
405 g = g_option_group_new ("connection",
406 N_("Connection Endpoint Options:"),
407 N_("Options specifying the connection endpoint"),
410 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
411 g_option_group_add_entries (g, connection_entries);
416 static GDBusConnection *
417 connection_get_dbus_connection (gboolean require_message_bus,
424 /* First, ensure we have exactly one connect */
425 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
430 _("No connection endpoint specified"));
433 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
434 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
435 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
440 _("Multiple connection endpoints specified"));
444 if (opt_connection_system)
446 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
448 else if (opt_connection_session)
450 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
452 else if (opt_connection_address != NULL)
454 GDBusConnectionFlags flags = G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT;
455 if (require_message_bus)
456 flags |= G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION;
457 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
459 NULL, /* GDBusAuthObserver */
460 NULL, /* GCancellable */
468 /* ---------------------------------------------------------------------------------------------------- */
471 call_helper_get_method_in_signature (GDBusConnection *c,
474 const gchar *interface_name,
475 const gchar *method_name,
480 GDBusNodeInfo *node_info;
481 const gchar *xml_data;
482 GDBusInterfaceInfo *interface_info;
483 GDBusMethodInfo *method_info;
490 result = g_dbus_connection_call_sync (c,
493 "org.freedesktop.DBus.Introspectable",
496 G_VARIANT_TYPE ("(s)"),
497 G_DBUS_CALL_FLAGS_NONE,
504 g_variant_get (result, "(&s)", &xml_data);
505 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
506 if (node_info == NULL)
509 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
510 if (interface_info == NULL)
512 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
513 _("Warning: According to introspection data, interface “%s” does not exist\n"),
518 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
519 if (method_info == NULL)
521 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
522 _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"),
528 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
529 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
531 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
535 if (node_info != NULL)
536 g_dbus_node_info_unref (node_info);
538 g_variant_unref (result);
543 /* ---------------------------------------------------------------------------------------------------- */
546 _g_variant_parse_me_harder (GVariantType *type,
547 const gchar *given_str,
555 str = g_string_new ("\"");
556 for (n = 0; given_str[n] != '\0'; n++)
558 if (G_UNLIKELY (given_str[n] == '\"'))
559 g_string_append (str, "\\\"");
561 g_string_append_c (str, given_str[n]);
563 g_string_append_c (str, '"');
564 s = g_string_free (str, FALSE);
566 value = g_variant_parse (type,
576 /* ---------------------------------------------------------------------------------------------------- */
578 static gchar *opt_emit_dest = NULL;
579 static gchar *opt_emit_object_path = NULL;
580 static gchar *opt_emit_signal = NULL;
582 static const GOptionEntry emit_entries[] =
584 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
585 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
586 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
591 handle_emit (gint *argc,
593 gboolean request_completion,
594 const gchar *completion_cur,
595 const gchar *completion_prev)
602 GVariant *parameters;
603 gchar *interface_name;
605 GVariantBuilder builder;
606 gboolean skip_dashes;
609 gboolean complete_names, complete_paths, complete_signals;
614 interface_name = NULL;
617 modify_argv0_for_command (argc, argv, "emit");
619 o = command_option_context_new (NULL, _("Emit a signal."),
620 emit_entries, request_completion);
621 g_option_context_add_group (o, connection_get_group ());
623 complete_names = FALSE;
624 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
626 complete_names = TRUE;
627 remove_arg ((*argc) - 1, argc, argv);
630 complete_paths = FALSE;
631 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
633 complete_paths = TRUE;
634 remove_arg ((*argc) - 1, argc, argv);
637 complete_signals = FALSE;
638 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0)
640 complete_signals = TRUE;
641 remove_arg ((*argc) - 1, argc, argv);
644 if (!g_option_context_parse (o, argc, argv, NULL))
646 if (!request_completion)
648 s = g_option_context_get_help (o, FALSE, NULL);
649 g_printerr ("%s", s);
656 c = connection_get_dbus_connection ((opt_emit_dest != NULL), &error);
659 if (request_completion)
661 if (g_strcmp0 (completion_prev, "--address") == 0)
669 g_print ("--system \n--session \n--address \n");
674 g_printerr (_("Error connecting: %s\n"), error->message);
675 g_error_free (error);
680 /* validate and complete destination (bus name) */
683 print_names (c, FALSE);
686 if (request_completion && opt_emit_dest != NULL && g_strcmp0 ("--dest", completion_prev) == 0)
688 print_names (c, g_str_has_prefix (opt_emit_dest, ":"));
692 if (!request_completion && opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
694 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
698 if (opt_emit_dest == NULL && opt_emit_object_path == NULL && request_completion)
700 g_print ("--dest \n");
702 /* validate and complete object path */
703 if (opt_emit_dest != NULL && complete_paths)
705 print_paths (c, opt_emit_dest, "/");
708 if (opt_emit_object_path == NULL)
710 if (request_completion)
711 g_print ("--object-path \n");
713 g_printerr (_("Error: Object path is not specified\n"));
716 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
718 if (opt_emit_dest != NULL)
721 s = g_strdup (opt_emit_object_path);
722 p = strrchr (s, '/');
729 print_paths (c, opt_emit_dest, s);
734 if (!request_completion && !g_variant_is_object_path (opt_emit_object_path))
736 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
740 /* validate and complete signal (interface + signal name) */
741 if (opt_emit_dest != NULL && opt_emit_object_path != NULL && complete_signals)
743 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
746 if (opt_emit_signal == NULL)
748 /* don't keep repeatedly completing --signal */
749 if (request_completion)
751 if (g_strcmp0 ("--signal", completion_prev) != 0)
752 g_print ("--signal \n");
756 g_printerr (_("Error: Signal name is not specified\n"));
761 if (request_completion && opt_emit_dest != NULL && opt_emit_object_path != NULL &&
762 g_strcmp0 ("--signal", completion_prev) == 0)
764 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
767 s = strrchr (opt_emit_signal, '.');
768 if (!request_completion && s == NULL)
770 g_printerr (_("Error: Signal name “%s” is invalid\n"), opt_emit_signal);
773 signal_name = g_strdup (s + 1);
774 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
776 /* All done with completion now */
777 if (request_completion)
780 if (!g_dbus_is_interface_name (interface_name))
782 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
786 if (!g_dbus_is_member_name (signal_name))
788 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
792 /* Read parameters */
793 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
796 for (n = 1; n < (guint) *argc; n++)
800 /* Under certain conditions, g_option_context_parse returns the "--"
801 itself (setting off unparsed arguments), too: */
802 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
809 value = g_variant_parse (NULL,
818 context = g_variant_parse_error_print_context (error, (*argv)[n]);
819 g_error_free (error);
821 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
824 /* Use the original non-"parse-me-harder" error */
825 g_printerr (_("Error parsing parameter %d: %s\n"),
828 g_error_free (error);
830 g_variant_builder_clear (&builder);
835 g_variant_builder_add_value (&builder, value);
838 parameters = g_variant_builder_end (&builder);
840 if (parameters != NULL)
841 parameters = g_variant_ref_sink (parameters);
842 if (!g_dbus_connection_emit_signal (c,
844 opt_emit_object_path,
850 g_printerr (_("Error: %s\n"), error->message);
851 g_error_free (error);
855 if (!g_dbus_connection_flush_sync (c, NULL, &error))
857 g_printerr (_("Error flushing connection: %s\n"), error->message);
858 g_error_free (error);
867 if (parameters != NULL)
868 g_variant_unref (parameters);
869 g_free (interface_name);
870 g_free (signal_name);
871 g_option_context_free (o);
875 /* ---------------------------------------------------------------------------------------------------- */
877 static gchar *opt_call_dest = NULL;
878 static gchar *opt_call_object_path = NULL;
879 static gchar *opt_call_method = NULL;
880 static gint opt_call_timeout = -1;
882 static const GOptionEntry call_entries[] =
884 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
885 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
886 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
887 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
892 handle_call (gint *argc,
894 gboolean request_completion,
895 const gchar *completion_cur,
896 const gchar *completion_prev)
903 GVariant *parameters;
904 gchar *interface_name;
907 GPtrArray *in_signature_types;
908 gboolean complete_names;
909 gboolean complete_paths;
910 gboolean complete_methods;
911 GVariantBuilder builder;
912 gboolean skip_dashes;
919 interface_name = NULL;
922 in_signature_types = NULL;
924 modify_argv0_for_command (argc, argv, "call");
926 o = command_option_context_new (NULL, _("Invoke a method on a remote object."),
927 call_entries, request_completion);
928 g_option_context_add_group (o, connection_get_group ());
930 complete_names = FALSE;
931 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
933 complete_names = TRUE;
934 remove_arg ((*argc) - 1, argc, argv);
937 complete_paths = FALSE;
938 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
940 complete_paths = TRUE;
941 remove_arg ((*argc) - 1, argc, argv);
944 complete_methods = FALSE;
945 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
947 complete_methods = TRUE;
948 remove_arg ((*argc) - 1, argc, argv);
951 if (!g_option_context_parse (o, argc, argv, NULL))
953 if (!request_completion)
955 s = g_option_context_get_help (o, FALSE, NULL);
956 g_printerr ("%s", s);
963 c = connection_get_dbus_connection (TRUE, &error);
966 if (request_completion)
968 if (g_strcmp0 (completion_prev, "--address") == 0)
976 g_print ("--system \n--session \n--address \n");
981 g_printerr (_("Error connecting: %s\n"), error->message);
982 g_error_free (error);
987 /* validate and complete destination (bus name) */
990 print_names (c, FALSE);
993 if (opt_call_dest == NULL)
995 if (request_completion)
996 g_print ("--dest \n");
998 g_printerr (_("Error: Destination is not specified\n"));
1001 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1003 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
1007 if (!request_completion && !g_dbus_is_name (opt_call_dest))
1009 g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest);
1013 /* validate and complete object path */
1016 print_paths (c, opt_call_dest, "/");
1019 if (opt_call_object_path == NULL)
1021 if (request_completion)
1022 g_print ("--object-path \n");
1024 g_printerr (_("Error: Object path is not specified\n"));
1027 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1030 s = g_strdup (opt_call_object_path);
1031 p = strrchr (s, '/');
1038 print_paths (c, opt_call_dest, s);
1042 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
1044 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
1048 /* validate and complete method (interface + method name) */
1049 if (complete_methods)
1051 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1054 if (opt_call_method == NULL)
1056 if (request_completion)
1057 g_print ("--method \n");
1059 g_printerr (_("Error: Method name is not specified\n"));
1062 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
1064 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1067 s = strrchr (opt_call_method, '.');
1068 if (!request_completion && s == NULL)
1070 g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method);
1073 method_name = g_strdup (s + 1);
1074 interface_name = g_strndup (opt_call_method, s - opt_call_method);
1076 /* All done with completion now */
1077 if (request_completion)
1080 /* Introspect, for easy conversion - it's not fatal if we can't do this */
1081 in_signature_types = call_helper_get_method_in_signature (c,
1083 opt_call_object_path,
1087 if (in_signature_types == NULL)
1089 //g_printerr ("Error getting introspection data: %s\n", error->message);
1090 g_error_free (error);
1094 /* Read parameters */
1095 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
1098 for (n = 1; n < (guint) *argc; n++)
1103 /* Under certain conditions, g_option_context_parse returns the "--"
1104 itself (setting off unparsed arguments), too: */
1105 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
1107 skip_dashes = FALSE;
1112 if (in_signature_types != NULL)
1114 if (parm >= in_signature_types->len)
1116 /* Only warn for the first param */
1117 if (parm == in_signature_types->len)
1119 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
1120 in_signature_types->len);
1125 type = in_signature_types->pdata[parm];
1130 value = g_variant_parse (type,
1139 context = g_variant_parse_error_print_context (error, (*argv)[n]);
1140 g_error_free (error);
1142 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1147 s = g_variant_type_dup_string (type);
1148 g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"),
1156 g_printerr (_("Error parsing parameter %d: %s\n"),
1160 g_error_free (error);
1161 g_variant_builder_clear (&builder);
1167 g_variant_builder_add_value (&builder, value);
1170 parameters = g_variant_builder_end (&builder);
1172 if (parameters != NULL)
1173 parameters = g_variant_ref_sink (parameters);
1174 result = g_dbus_connection_call_sync (c,
1176 opt_call_object_path,
1181 G_DBUS_CALL_FLAGS_NONE,
1182 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1187 g_printerr (_("Error: %s\n"), error->message);
1189 if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL)
1191 if (in_signature_types->len > 0)
1194 s = g_string_new (NULL);
1196 for (n = 0; n < in_signature_types->len; n++)
1198 GVariantType *type = in_signature_types->pdata[n];
1199 g_string_append_len (s,
1200 g_variant_type_peek_string (type),
1201 g_variant_type_get_string_length (type));
1204 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1205 g_string_free (s, TRUE);
1208 g_printerr ("(According to introspection data, you need to pass no arguments)\n");
1211 g_error_free (error);
1215 s = g_variant_print (result, TRUE);
1216 g_print ("%s\n", s);
1222 if (in_signature_types != NULL)
1223 g_ptr_array_unref (in_signature_types);
1225 g_variant_unref (result);
1228 if (parameters != NULL)
1229 g_variant_unref (parameters);
1230 g_free (interface_name);
1231 g_free (method_name);
1232 g_option_context_free (o);
1236 /* ---------------------------------------------------------------------------------------------------- */
1238 static gchar *opt_introspect_dest = NULL;
1239 static gchar *opt_introspect_object_path = NULL;
1240 static gboolean opt_introspect_xml = FALSE;
1241 static gboolean opt_introspect_recurse = FALSE;
1242 static gboolean opt_introspect_only_properties = FALSE;
1244 /* Introspect colors */
1245 #define RESET_COLOR (use_colors? "\033[0m": "")
1246 #define INTROSPECT_TITLE_COLOR (use_colors? UNDERLINE: "")
1247 #define INTROSPECT_NODE_COLOR (use_colors? RESET_COLOR: "")
1248 #define INTROSPECT_INTERFACE_COLOR (use_colors? YELLOW: "")
1249 #define INTROSPECT_METHOD_COLOR (use_colors? BLUE: "")
1250 #define INTROSPECT_SIGNAL_COLOR (use_colors? BLUE: "")
1251 #define INTROSPECT_PROPERTY_COLOR (use_colors? MAGENTA: "")
1252 #define INTROSPECT_INOUT_COLOR (use_colors? RESET_COLOR: "")
1253 #define INTROSPECT_TYPE_COLOR (use_colors? GREEN: "")
1254 #define INTROSPECT_ANNOTATION_COLOR (use_colors? RESET_COLOR: "")
1257 dump_annotation (const GDBusAnnotationInfo *o,
1259 gboolean ignore_indent,
1260 gboolean use_colors)
1263 g_print ("%*s%s@%s(\"%s\")%s\n",
1264 ignore_indent ? 0 : indent, "",
1265 INTROSPECT_ANNOTATION_COLOR, o->key, o->value, RESET_COLOR);
1266 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1267 dump_annotation (o->annotations[n], indent + 2, FALSE, use_colors);
1271 dump_arg (const GDBusArgInfo *o,
1273 const gchar *direction,
1274 gboolean ignore_indent,
1275 gboolean include_newline,
1276 gboolean use_colors)
1280 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1282 dump_annotation (o->annotations[n], indent, ignore_indent, use_colors);
1283 ignore_indent = FALSE;
1286 g_print ("%*s%s%s%s%s%s%s %s%s",
1287 ignore_indent ? 0 : indent, "",
1288 INTROSPECT_INOUT_COLOR, direction, RESET_COLOR,
1289 INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1291 include_newline ? ",\n" : "");
1295 count_args (GDBusArgInfo **args)
1301 while (args[n] != NULL)
1308 dump_method (const GDBusMethodInfo *o,
1310 gboolean use_colors)
1315 guint total_num_args;
1317 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1318 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1320 g_print ("%*s%s%s%s(",
1322 INTROSPECT_METHOD_COLOR, o->name, RESET_COLOR);
1323 name_len = strlen (o->name);
1324 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1325 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1327 gboolean ignore_indent = (m == 0);
1328 gboolean include_newline = (m != total_num_args - 1);
1330 dump_arg (o->in_args[n],
1331 indent + name_len + 1,
1337 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1339 gboolean ignore_indent = (m == 0);
1340 gboolean include_newline = (m != total_num_args - 1);
1341 dump_arg (o->out_args[n],
1342 indent + name_len + 1,
1352 dump_signal (const GDBusSignalInfo *o,
1354 gboolean use_colors)
1358 guint total_num_args;
1360 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1361 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1363 g_print ("%*s%s%s%s(",
1365 INTROSPECT_SIGNAL_COLOR, o->name, RESET_COLOR);
1366 name_len = strlen (o->name);
1367 total_num_args = count_args (o->args);
1368 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1370 gboolean ignore_indent = (n == 0);
1371 gboolean include_newline = (n != total_num_args - 1);
1372 dump_arg (o->args[n],
1373 indent + name_len + 1,
1383 dump_property (const GDBusPropertyInfo *o,
1385 gboolean use_colors,
1388 const gchar *access;
1391 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1392 access = "readonly";
1393 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1394 access = "writeonly";
1395 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1396 access = "readwrite";
1398 g_assert_not_reached ();
1400 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1401 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1405 gchar *s = g_variant_print (value, FALSE);
1406 g_print ("%*s%s %s%s%s %s%s%s = %s;\n", indent, "", access,
1407 INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1408 INTROSPECT_PROPERTY_COLOR, o->name, RESET_COLOR,
1414 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1419 dump_interface (GDBusConnection *c,
1421 const GDBusInterfaceInfo *o,
1423 gboolean use_colors,
1424 const gchar *object_path)
1427 GHashTable *properties;
1429 properties = g_hash_table_new_full (g_str_hash,
1432 (GDestroyNotify) g_variant_unref);
1434 /* Try to get properties */
1435 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1438 result = g_dbus_connection_call_sync (c,
1441 "org.freedesktop.DBus.Properties",
1443 g_variant_new ("(s)", o->name),
1445 G_DBUS_CALL_FLAGS_NONE,
1451 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1455 g_variant_get (result,
1458 while ((item = g_variant_iter_next_value (iter)))
1462 g_variant_get (item,
1467 g_hash_table_insert (properties, key, g_variant_ref (value));
1470 g_variant_unref (result);
1475 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1477 result = g_dbus_connection_call_sync (c,
1480 "org.freedesktop.DBus.Properties",
1482 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1483 G_VARIANT_TYPE ("(v)"),
1484 G_DBUS_CALL_FLAGS_NONE,
1490 GVariant *property_value;
1491 g_variant_get (result,
1494 g_hash_table_insert (properties,
1495 g_strdup (o->properties[n]->name),
1496 g_variant_ref (property_value));
1497 g_variant_unref (result);
1503 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1504 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1506 g_print ("%*s%sinterface %s%s {\n",
1508 INTROSPECT_INTERFACE_COLOR, o->name, RESET_COLOR);
1509 if (o->methods != NULL && !opt_introspect_only_properties)
1511 g_print ("%*s %smethods%s:\n",
1513 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1514 for (n = 0; o->methods[n] != NULL; n++)
1515 dump_method (o->methods[n], indent + 4, use_colors);
1517 if (o->signals != NULL && !opt_introspect_only_properties)
1519 g_print ("%*s %ssignals%s:\n",
1521 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1522 for (n = 0; o->signals[n] != NULL; n++)
1523 dump_signal (o->signals[n], indent + 4, use_colors);
1525 if (o->properties != NULL)
1527 g_print ("%*s %sproperties%s:\n",
1529 INTROSPECT_TITLE_COLOR, RESET_COLOR);
1530 for (n = 0; o->properties[n] != NULL; n++)
1532 dump_property (o->properties[n],
1535 g_hash_table_lookup (properties, (o->properties[n])->name));
1541 g_hash_table_unref (properties);
1545 introspect_do (GDBusConnection *c,
1546 const gchar *object_path,
1548 gboolean use_colors);
1551 dump_node (GDBusConnection *c,
1553 const GDBusNodeInfo *o,
1555 gboolean use_colors,
1556 const gchar *object_path,
1560 const gchar *object_path_to_print;
1562 object_path_to_print = object_path;
1563 if (o->path != NULL)
1564 object_path_to_print = o->path;
1566 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1567 dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1569 g_print ("%*s%snode %s%s",
1571 INTROSPECT_NODE_COLOR,
1572 object_path_to_print != NULL ? object_path_to_print : "(not set)",
1574 if (o->interfaces != NULL || o->nodes != NULL)
1577 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1579 if (opt_introspect_only_properties)
1581 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1582 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1586 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1589 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1594 if (g_variant_is_object_path (o->nodes[n]->path))
1596 child_path = g_strdup (o->nodes[n]->path);
1597 /* avoid infinite loops */
1598 if (g_str_has_prefix (child_path, object_path))
1600 introspect_do (c, child_path, indent + 2, use_colors);
1604 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1605 child_path, object_path);
1610 if (g_strcmp0 (object_path, "/") == 0)
1611 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1613 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1614 introspect_do (c, child_path, indent + 2, use_colors);
1616 g_free (child_path);
1620 dump_node (NULL, NULL, o->nodes[n], indent + 2, use_colors, NULL, recurse);
1632 static const GOptionEntry introspect_entries[] =
1634 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1635 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1636 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1637 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1638 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1643 introspect_do (GDBusConnection *c,
1644 const gchar *object_path,
1646 gboolean use_colors)
1650 GDBusNodeInfo *node;
1652 const gchar *xml_data;
1659 result = g_dbus_connection_call_sync (c,
1660 opt_introspect_dest,
1662 "org.freedesktop.DBus.Introspectable",
1665 G_VARIANT_TYPE ("(s)"),
1666 G_DBUS_CALL_FLAGS_NONE,
1672 g_printerr (_("Error: %s\n"), error->message);
1673 g_error_free (error);
1676 g_variant_get (result, "(&s)", &xml_data);
1678 if (opt_introspect_xml)
1680 g_print ("%s", xml_data);
1685 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1688 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1689 g_error_free (error);
1693 dump_node (c, opt_introspect_dest, node, indent, use_colors, object_path, opt_introspect_recurse);
1700 g_dbus_node_info_unref (node);
1702 g_variant_unref (result);
1707 handle_introspect (gint *argc,
1709 gboolean request_completion,
1710 const gchar *completion_cur,
1711 const gchar *completion_prev)
1718 gboolean complete_names;
1719 gboolean complete_paths;
1720 gboolean color_support;
1725 modify_argv0_for_command (argc, argv, "introspect");
1727 o = command_option_context_new (NULL, _("Introspect a remote object."),
1728 introspect_entries, request_completion);
1729 g_option_context_add_group (o, connection_get_group ());
1731 complete_names = FALSE;
1732 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1734 complete_names = TRUE;
1735 remove_arg ((*argc) - 1, argc, argv);
1738 complete_paths = FALSE;
1739 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1741 complete_paths = TRUE;
1742 remove_arg ((*argc) - 1, argc, argv);
1745 if (!g_option_context_parse (o, argc, argv, NULL))
1747 if (!request_completion)
1749 s = g_option_context_get_help (o, FALSE, NULL);
1750 g_printerr ("%s", s);
1757 c = connection_get_dbus_connection (TRUE, &error);
1760 if (request_completion)
1762 if (g_strcmp0 (completion_prev, "--address") == 0)
1770 g_print ("--system \n--session \n--address \n");
1775 g_printerr (_("Error connecting: %s\n"), error->message);
1776 g_error_free (error);
1783 print_names (c, FALSE);
1786 /* this only makes sense on message bus connections */
1787 if (opt_introspect_dest == NULL)
1789 if (request_completion)
1790 g_print ("--dest \n");
1792 g_printerr (_("Error: Destination is not specified\n"));
1795 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1797 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1803 print_paths (c, opt_introspect_dest, "/");
1807 if (!request_completion && !g_dbus_is_name (opt_introspect_dest))
1809 g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest);
1813 if (opt_introspect_object_path == NULL)
1815 if (request_completion)
1816 g_print ("--object-path \n");
1818 g_printerr (_("Error: Object path is not specified\n"));
1821 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1824 s = g_strdup (opt_introspect_object_path);
1825 p = strrchr (s, '/');
1832 print_paths (c, opt_introspect_dest, s);
1836 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1838 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1842 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1844 g_print ("--recurse \n");
1847 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1849 g_print ("--only-properties \n");
1852 /* All done with completion now */
1853 if (request_completion)
1856 /* Before we start printing the actual info, check if we can do colors*/
1857 color_support = g_log_writer_supports_color (fileno (stdout));
1859 if (!introspect_do (c, opt_introspect_object_path, 0, color_support))
1867 g_option_context_free (o);
1871 /* ---------------------------------------------------------------------------------------------------- */
1873 static gchar *opt_monitor_dest = NULL;
1874 static gchar *opt_monitor_object_path = NULL;
1876 static guint monitor_filter_id = 0;
1879 monitor_signal_cb (GDBusConnection *connection,
1880 const gchar *sender_name,
1881 const gchar *object_path,
1882 const gchar *interface_name,
1883 const gchar *signal_name,
1884 GVariant *parameters,
1888 s = g_variant_print (parameters, TRUE);
1889 g_print ("%s: %s.%s %s\n",
1898 monitor_on_name_appeared (GDBusConnection *connection,
1900 const gchar *name_owner,
1903 g_print ("The name %s is owned by %s\n", name, name_owner);
1904 g_assert (monitor_filter_id == 0);
1905 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1907 NULL, /* any interface */
1908 NULL, /* any member */
1909 opt_monitor_object_path,
1911 G_DBUS_SIGNAL_FLAGS_NONE,
1913 NULL, /* user_data */
1914 NULL); /* user_data destroy notify */
1918 monitor_on_name_vanished (GDBusConnection *connection,
1922 g_print ("The name %s does not have an owner\n", name);
1924 if (monitor_filter_id != 0)
1926 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1927 monitor_filter_id = 0;
1931 static const GOptionEntry monitor_entries[] =
1933 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1934 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1939 handle_monitor (gint *argc,
1941 gboolean request_completion,
1942 const gchar *completion_cur,
1943 const gchar *completion_prev)
1950 gboolean complete_names;
1951 gboolean complete_paths;
1957 modify_argv0_for_command (argc, argv, "monitor");
1959 o = command_option_context_new (NULL, _("Monitor a remote object."),
1960 monitor_entries, request_completion);
1961 g_option_context_add_group (o, connection_get_group ());
1963 complete_names = FALSE;
1964 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1966 complete_names = TRUE;
1967 remove_arg ((*argc) - 1, argc, argv);
1970 complete_paths = FALSE;
1971 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1973 complete_paths = TRUE;
1974 remove_arg ((*argc) - 1, argc, argv);
1977 if (!g_option_context_parse (o, argc, argv, NULL))
1979 if (!request_completion)
1981 s = g_option_context_get_help (o, FALSE, NULL);
1982 g_printerr ("%s", s);
1989 c = connection_get_dbus_connection (TRUE, &error);
1992 if (request_completion)
1994 if (g_strcmp0 (completion_prev, "--address") == 0)
2002 g_print ("--system \n--session \n--address \n");
2007 g_printerr (_("Error connecting: %s\n"), error->message);
2008 g_error_free (error);
2013 /* Monitoring doesn’t make sense on a non-message-bus connection. */
2014 if (g_dbus_connection_get_unique_name (c) == NULL)
2016 if (!request_completion)
2017 g_printerr (_("Error: can’t monitor a non-message-bus connection\n"));
2023 print_names (c, FALSE);
2026 /* this only makes sense on message bus connections */
2027 if (opt_monitor_dest == NULL)
2029 if (request_completion)
2030 g_print ("--dest \n");
2032 g_printerr (_("Error: Destination is not specified\n"));
2035 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
2037 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
2041 if (!request_completion && !g_dbus_is_name (opt_monitor_dest))
2043 g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest);
2049 print_paths (c, opt_monitor_dest, "/");
2052 if (opt_monitor_object_path == NULL)
2054 if (request_completion)
2056 g_print ("--object-path \n");
2059 /* it's fine to not have an object path */
2061 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
2064 s = g_strdup (opt_monitor_object_path);
2065 p = strrchr (s, '/');
2072 print_paths (c, opt_monitor_dest, s);
2076 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
2078 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
2082 /* All done with completion now */
2083 if (request_completion)
2086 if (opt_monitor_object_path != NULL)
2087 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
2089 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
2091 loop = g_main_loop_new (NULL, FALSE);
2092 g_bus_watch_name_on_connection (c,
2094 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2095 monitor_on_name_appeared,
2096 monitor_on_name_vanished,
2100 g_main_loop_run (loop);
2101 g_main_loop_unref (loop);
2108 g_option_context_free (o);
2112 /* ---------------------------------------------------------------------------------------------------- */
2114 static gboolean opt_wait_activate_set = FALSE;
2115 static gchar *opt_wait_activate_name = NULL;
2116 static gint64 opt_wait_timeout_secs = 0; /* no timeout */
2119 WAIT_STATE_RUNNING, /* waiting to see the service */
2120 WAIT_STATE_SUCCESS, /* seen it successfully */
2121 WAIT_STATE_TIMEOUT, /* timed out before seeing it */
2125 opt_wait_activate_cb (const gchar *option_name,
2130 /* @value may be NULL */
2131 opt_wait_activate_set = TRUE;
2132 opt_wait_activate_name = g_strdup (value);
2137 static const GOptionEntry wait_entries[] =
2139 { "activate", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
2140 opt_wait_activate_cb,
2141 N_("Service to activate before waiting for the other one (well-known name)"),
2143 { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout_secs,
2144 N_("Timeout to wait for before exiting with an error (seconds); 0 for "
2145 "no timeout (default)"), "SECS" },
2150 wait_name_appeared_cb (GDBusConnection *connection,
2152 const gchar *name_owner,
2155 WaitState *wait_state = user_data;
2157 *wait_state = WAIT_STATE_SUCCESS;
2161 wait_timeout_cb (gpointer user_data)
2163 WaitState *wait_state = user_data;
2165 *wait_state = WAIT_STATE_TIMEOUT;
2167 /* Removed in handle_wait(). */
2168 return G_SOURCE_CONTINUE;
2172 handle_wait (gint *argc,
2174 gboolean request_completion,
2175 const gchar *completion_cur,
2176 const gchar *completion_prev)
2183 guint watch_id, timer_id = 0, activate_watch_id;
2184 const gchar *activate_service, *wait_service;
2185 WaitState wait_state = WAIT_STATE_RUNNING;
2190 modify_argv0_for_command (argc, argv, "wait");
2192 o = command_option_context_new (_("[OPTION…] BUS-NAME"),
2193 _("Wait for a bus name to appear."),
2194 wait_entries, request_completion);
2195 g_option_context_add_group (o, connection_get_group ());
2197 if (!g_option_context_parse (o, argc, argv, NULL))
2199 if (!request_completion)
2201 s = g_option_context_get_help (o, FALSE, NULL);
2202 g_printerr ("%s", s);
2209 c = connection_get_dbus_connection (TRUE, &error);
2212 if (request_completion)
2214 if (g_strcmp0 (completion_prev, "--address") == 0)
2222 g_print ("--system \n--session \n--address \n");
2227 g_printerr (_("Error connecting: %s\n"), error->message);
2228 g_error_free (error);
2233 /* All done with completion now */
2234 if (request_completion)
2238 * Try and disentangle the command line arguments, with the aim of supporting:
2239 * gdbus wait --session --activate ActivateName WaitName
2240 * gdbus wait --session --activate ActivateAndWaitName
2241 * gdbus wait --activate --session ActivateAndWaitName
2242 * gdbus wait --session WaitName
2244 if (*argc == 2 && opt_wait_activate_set && opt_wait_activate_name != NULL)
2246 activate_service = opt_wait_activate_name;
2247 wait_service = (*argv)[1];
2249 else if (*argc == 2 &&
2250 opt_wait_activate_set && opt_wait_activate_name == NULL)
2252 activate_service = (*argv)[1];
2253 wait_service = (*argv)[1];
2255 else if (*argc == 2 && !opt_wait_activate_set)
2257 activate_service = NULL; /* disabled */
2258 wait_service = (*argv)[1];
2260 else if (*argc == 1 &&
2261 opt_wait_activate_set && opt_wait_activate_name != NULL)
2263 activate_service = opt_wait_activate_name;
2264 wait_service = opt_wait_activate_name;
2266 else if (*argc == 1 &&
2267 opt_wait_activate_set && opt_wait_activate_name == NULL)
2269 g_printerr (_("Error: A service to activate for must be specified.\n"));
2272 else if (*argc == 1 && !opt_wait_activate_set)
2274 g_printerr (_("Error: A service to wait for must be specified.\n"));
2277 else /* if (*argc > 2) */
2279 g_printerr (_("Error: Too many arguments.\n"));
2283 if (activate_service != NULL &&
2284 (!g_dbus_is_name (activate_service) ||
2285 g_dbus_is_unique_name (activate_service)))
2287 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2292 if (!g_dbus_is_name (wait_service) || g_dbus_is_unique_name (wait_service))
2294 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2299 /* Start the prerequisite service if needed. */
2300 if (activate_service != NULL)
2302 activate_watch_id = g_bus_watch_name_on_connection (c, activate_service,
2303 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2309 activate_watch_id = 0;
2312 /* Wait for the expected name to appear. */
2313 watch_id = g_bus_watch_name_on_connection (c,
2315 G_BUS_NAME_WATCHER_FLAGS_NONE,
2316 wait_name_appeared_cb,
2317 NULL, &wait_state, NULL);
2319 /* Safety timeout. */
2320 if (opt_wait_timeout_secs > 0)
2321 timer_id = g_timeout_add_seconds (opt_wait_timeout_secs, wait_timeout_cb, &wait_state);
2323 while (wait_state == WAIT_STATE_RUNNING)
2324 g_main_context_iteration (NULL, TRUE);
2326 g_bus_unwatch_name (watch_id);
2328 g_source_remove (timer_id);
2329 if (activate_watch_id != 0)
2330 g_bus_unwatch_name (activate_watch_id);
2332 ret = (wait_state == WAIT_STATE_SUCCESS);
2335 g_clear_object (&c);
2336 g_option_context_free (o);
2337 g_free (opt_wait_activate_name);
2338 opt_wait_activate_name = NULL;
2343 /* ---------------------------------------------------------------------------------------------------- */
2346 pick_word_at (const gchar *s,
2348 gint *out_word_begins_at)
2355 if (out_word_begins_at != NULL)
2356 *out_word_begins_at = -1;
2360 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
2362 if (out_word_begins_at != NULL)
2363 *out_word_begins_at = cursor;
2364 return g_strdup ("");
2367 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
2372 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
2375 if (out_word_begins_at != NULL)
2376 *out_word_begins_at = begin;
2378 return g_strndup (s + begin, end - begin);
2382 main (gint argc, gchar *argv[])
2385 const gchar *command;
2386 gboolean request_completion;
2387 gchar *completion_cur;
2388 gchar *completion_prev;
2393 setlocale (LC_ALL, "");
2394 textdomain (GETTEXT_PACKAGE);
2397 tmp = _glib_get_locale_dir ();
2398 bindtextdomain (GETTEXT_PACKAGE, tmp);
2401 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2404 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2405 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2409 completion_cur = NULL;
2410 completion_prev = NULL;
2414 usage (&argc, &argv, FALSE);
2418 request_completion = FALSE;
2420 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
2424 if (g_strcmp0 (command, "help") == 0)
2426 if (request_completion)
2432 usage (&argc, &argv, TRUE);
2437 else if (g_strcmp0 (command, "emit") == 0)
2439 if (handle_emit (&argc,
2447 else if (g_strcmp0 (command, "call") == 0)
2449 if (handle_call (&argc,
2457 else if (g_strcmp0 (command, "introspect") == 0)
2459 if (handle_introspect (&argc,
2467 else if (g_strcmp0 (command, "monitor") == 0)
2469 if (handle_monitor (&argc,
2477 else if (g_strcmp0 (command, "wait") == 0)
2479 if (handle_wait (&argc,
2488 else if (g_strcmp0 (command, _GDBUS_ARG_WIN32_RUN_SESSION_BUS) == 0)
2490 g_win32_run_session_bus (NULL, NULL, NULL, 0);
2495 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2497 const gchar *completion_line;
2498 gchar **completion_argv;
2499 gint completion_argc;
2500 gint completion_point;
2504 request_completion = TRUE;
2506 completion_line = argv[2];
2507 completion_point = strtol (argv[3], &endp, 10);
2508 if (endp == argv[3] || *endp != '\0')
2512 completion_debug ("completion_point=%d", completion_point);
2513 completion_debug ("----");
2514 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2515 completion_debug ("'%s'", completion_line);
2516 completion_debug (" %*s^",
2517 completion_point, "");
2518 completion_debug ("----");
2521 if (!g_shell_parse_argv (completion_line,
2526 /* it's very possible the command line can't be parsed (for
2527 * example, missing quotes etc) - in that case, we just
2528 * don't autocomplete at all
2533 /* compute cur and prev */
2534 completion_prev = NULL;
2535 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2539 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2541 if (!g_ascii_isspace (completion_line[prev_end]))
2543 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2549 completion_debug (" cur='%s'", completion_cur);
2550 completion_debug ("prev='%s'", completion_prev);
2553 argc = completion_argc;
2554 argv = completion_argv;
2562 if (request_completion)
2564 g_print ("help \nemit \ncall \nintrospect \nmonitor \nwait \n");
2570 g_printerr ("Unknown command '%s'\n", command);
2571 usage (&argc, &argv, FALSE);
2577 g_free (completion_cur);
2578 g_free (completion_prev);