meson: work around meson not passing on the threads dependency when link_with is...
[glib.git] / gio / gdbus-tool.c
blob77863a2a0fb34011ca886e06f20a88dd878144b3
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>
21 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <locale.h>
28 #include <gio/gio.h>
30 #include <gi18n.h>
32 #ifdef G_OS_WIN32
33 #include "glib/glib-private.h"
34 #endif
36 /* ---------------------------------------------------------------------------------------------------- */
38 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
40 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
41 * to not have it interfere with stdout/stderr)
43 #if 0
44 G_GNUC_UNUSED static void
45 completion_debug (const gchar *format, ...)
47 va_list var_args;
48 gchar *s;
49 static FILE *f = NULL;
51 va_start (var_args, format);
52 s = g_strdup_vprintf (format, var_args);
53 if (f == NULL)
55 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
57 fprintf (f, "%s\n", s);
58 g_free (s);
60 #else
61 static void
62 completion_debug (const gchar *format, ...)
65 #endif
67 /* ---------------------------------------------------------------------------------------------------- */
70 static void
71 remove_arg (gint num, gint *argc, gchar **argv[])
73 gint n;
75 g_assert (num <= (*argc));
77 for (n = num; (*argv)[n] != NULL; n++)
78 (*argv)[n] = (*argv)[n+1];
79 (*argv)[n] = NULL;
80 (*argc) = (*argc) - 1;
83 static void
84 usage (gint *argc, gchar **argv[], gboolean use_stdout)
86 GOptionContext *o;
87 gchar *s;
88 gchar *program_name;
90 o = g_option_context_new (_("COMMAND"));
91 g_option_context_set_help_enabled (o, FALSE);
92 /* Ignore parsing result */
93 g_option_context_parse (o, argc, argv, NULL);
94 program_name = g_path_get_basename ((*argv)[0]);
95 s = g_strdup_printf (_("Commands:\n"
96 " help Shows this information\n"
97 " introspect Introspect a remote object\n"
98 " monitor Monitor a remote object\n"
99 " call Invoke a method on a remote object\n"
100 " emit Emit a signal\n"
101 " wait Wait for a bus name to appear\n"
102 "\n"
103 "Use “%s COMMAND --help” to get help on each command.\n"),
104 program_name);
105 g_free (program_name);
106 g_option_context_set_description (o, s);
107 g_free (s);
108 s = g_option_context_get_help (o, FALSE, NULL);
109 if (use_stdout)
110 g_print ("%s", s);
111 else
112 g_printerr ("%s", s);
113 g_free (s);
114 g_option_context_free (o);
117 static void
118 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
120 gchar *s;
121 gchar *program_name;
123 /* TODO:
124 * 1. get a g_set_prgname() ?; or
125 * 2. save old argv[0] and restore later
128 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
129 remove_arg (1, argc, argv);
131 program_name = g_path_get_basename ((*argv)[0]);
132 s = g_strdup_printf ("%s %s", (*argv)[0], command);
133 (*argv)[0] = s;
134 g_free (program_name);
137 /* ---------------------------------------------------------------------------------------------------- */
139 static void
140 print_methods_and_signals (GDBusConnection *c,
141 const gchar *name,
142 const gchar *path,
143 gboolean print_methods,
144 gboolean print_signals)
146 GVariant *result;
147 GError *error;
148 const gchar *xml_data;
149 GDBusNodeInfo *node;
150 guint n;
151 guint m;
153 error = NULL;
154 result = g_dbus_connection_call_sync (c,
155 name,
156 path,
157 "org.freedesktop.DBus.Introspectable",
158 "Introspect",
159 NULL,
160 G_VARIANT_TYPE ("(s)"),
161 G_DBUS_CALL_FLAGS_NONE,
162 3000, /* 3 secs */
163 NULL,
164 &error);
165 if (result == NULL)
167 g_printerr (_("Error: %s\n"), error->message);
168 g_error_free (error);
169 goto out;
171 g_variant_get (result, "(&s)", &xml_data);
173 error = NULL;
174 node = g_dbus_node_info_new_for_xml (xml_data, &error);
175 g_variant_unref (result);
176 if (node == NULL)
178 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
179 g_error_free (error);
180 goto out;
183 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
185 const GDBusInterfaceInfo *iface = node->interfaces[n];
186 for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++)
188 const GDBusMethodInfo *method = iface->methods[m];
189 g_print ("%s.%s \n", iface->name, method->name);
191 for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++)
193 const GDBusSignalInfo *signal = iface->signals[m];
194 g_print ("%s.%s \n", iface->name, signal->name);
197 g_dbus_node_info_unref (node);
199 out:
203 static void
204 print_paths (GDBusConnection *c,
205 const gchar *name,
206 const gchar *path)
208 GVariant *result;
209 GError *error;
210 const gchar *xml_data;
211 GDBusNodeInfo *node;
212 guint n;
214 if (!g_dbus_is_name (name))
216 g_printerr (_("Error: %s is not a valid name\n"), name);
217 goto out;
220 error = NULL;
221 result = g_dbus_connection_call_sync (c,
222 name,
223 path,
224 "org.freedesktop.DBus.Introspectable",
225 "Introspect",
226 NULL,
227 G_VARIANT_TYPE ("(s)"),
228 G_DBUS_CALL_FLAGS_NONE,
229 3000, /* 3 secs */
230 NULL,
231 &error);
232 if (result == NULL)
234 g_printerr (_("Error: %s\n"), error->message);
235 g_error_free (error);
236 goto out;
238 g_variant_get (result, "(&s)", &xml_data);
240 //g_printerr ("xml='%s'", xml_data);
242 error = NULL;
243 node = g_dbus_node_info_new_for_xml (xml_data, &error);
244 g_variant_unref (result);
245 if (node == NULL)
247 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
248 g_error_free (error);
249 goto out;
252 //g_printerr ("bar '%s'\n", path);
254 if (node->interfaces != NULL)
255 g_print ("%s \n", path);
257 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
259 gchar *s;
261 //g_printerr ("foo '%s'\n", node->nodes[n].path);
263 if (g_strcmp0 (path, "/") == 0)
264 s = g_strdup_printf ("/%s", node->nodes[n]->path);
265 else
266 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
268 print_paths (c, name, s);
270 g_free (s);
272 g_dbus_node_info_unref (node);
274 out:
278 static void
279 print_names (GDBusConnection *c,
280 gboolean include_unique_names)
282 GVariant *result;
283 GError *error;
284 GVariantIter *iter;
285 gchar *str;
286 GHashTable *name_set;
287 GList *keys;
288 GList *l;
290 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
292 error = NULL;
293 result = g_dbus_connection_call_sync (c,
294 "org.freedesktop.DBus",
295 "/org/freedesktop/DBus",
296 "org.freedesktop.DBus",
297 "ListNames",
298 NULL,
299 G_VARIANT_TYPE ("(as)"),
300 G_DBUS_CALL_FLAGS_NONE,
301 3000, /* 3 secs */
302 NULL,
303 &error);
304 if (result == NULL)
306 g_printerr (_("Error: %s\n"), error->message);
307 g_error_free (error);
308 goto out;
310 g_variant_get (result, "(as)", &iter);
311 while (g_variant_iter_loop (iter, "s", &str))
312 g_hash_table_add (name_set, g_strdup (str));
313 g_variant_iter_free (iter);
314 g_variant_unref (result);
316 error = NULL;
317 result = g_dbus_connection_call_sync (c,
318 "org.freedesktop.DBus",
319 "/org/freedesktop/DBus",
320 "org.freedesktop.DBus",
321 "ListActivatableNames",
322 NULL,
323 G_VARIANT_TYPE ("(as)"),
324 G_DBUS_CALL_FLAGS_NONE,
325 3000, /* 3 secs */
326 NULL,
327 &error);
328 if (result == NULL)
330 g_printerr (_("Error: %s\n"), error->message);
331 g_error_free (error);
332 goto out;
334 g_variant_get (result, "(as)", &iter);
335 while (g_variant_iter_loop (iter, "s", &str))
336 g_hash_table_add (name_set, g_strdup (str));
337 g_variant_iter_free (iter);
338 g_variant_unref (result);
340 keys = g_hash_table_get_keys (name_set);
341 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
342 for (l = keys; l != NULL; l = l->next)
344 const gchar *name = l->data;
345 if (!include_unique_names && g_str_has_prefix (name, ":"))
346 continue;
348 g_print ("%s \n", name);
350 g_list_free (keys);
352 out:
353 g_hash_table_unref (name_set);
356 /* ---------------------------------------------------------------------------------------------------- */
358 static gboolean opt_connection_system = FALSE;
359 static gboolean opt_connection_session = FALSE;
360 static gchar *opt_connection_address = NULL;
362 static const GOptionEntry connection_entries[] =
364 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
365 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
366 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
367 { NULL }
370 static GOptionGroup *
371 connection_get_group (void)
373 static GOptionGroup *g;
375 g = g_option_group_new ("connection",
376 N_("Connection Endpoint Options:"),
377 N_("Options specifying the connection endpoint"),
378 NULL,
379 NULL);
380 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
381 g_option_group_add_entries (g, connection_entries);
383 return g;
386 static GDBusConnection *
387 connection_get_dbus_connection (GError **error)
389 GDBusConnection *c;
391 c = NULL;
393 /* First, ensure we have exactly one connect */
394 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
396 g_set_error (error,
397 G_IO_ERROR,
398 G_IO_ERROR_FAILED,
399 _("No connection endpoint specified"));
400 goto out;
402 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
403 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
404 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
406 g_set_error (error,
407 G_IO_ERROR,
408 G_IO_ERROR_FAILED,
409 _("Multiple connection endpoints specified"));
410 goto out;
413 if (opt_connection_system)
415 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
417 else if (opt_connection_session)
419 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
421 else if (opt_connection_address != NULL)
423 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
424 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
425 NULL, /* GDBusAuthObserver */
426 NULL, /* GCancellable */
427 error);
430 out:
431 return c;
434 /* ---------------------------------------------------------------------------------------------------- */
436 static GPtrArray *
437 call_helper_get_method_in_signature (GDBusConnection *c,
438 const gchar *dest,
439 const gchar *path,
440 const gchar *interface_name,
441 const gchar *method_name,
442 GError **error)
444 GPtrArray *ret;
445 GVariant *result;
446 GDBusNodeInfo *node_info;
447 const gchar *xml_data;
448 GDBusInterfaceInfo *interface_info;
449 GDBusMethodInfo *method_info;
450 guint n;
452 ret = NULL;
453 result = NULL;
454 node_info = NULL;
456 result = g_dbus_connection_call_sync (c,
457 dest,
458 path,
459 "org.freedesktop.DBus.Introspectable",
460 "Introspect",
461 NULL,
462 G_VARIANT_TYPE ("(s)"),
463 G_DBUS_CALL_FLAGS_NONE,
464 3000, /* 3 secs */
465 NULL,
466 error);
467 if (result == NULL)
468 goto out;
470 g_variant_get (result, "(&s)", &xml_data);
471 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
472 if (node_info == NULL)
473 goto out;
475 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
476 if (interface_info == NULL)
478 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
479 _("Warning: According to introspection data, interface “%s” does not exist\n"),
480 interface_name);
481 goto out;
484 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
485 if (method_info == NULL)
487 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
488 _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"),
489 method_name,
490 interface_name);
491 goto out;
494 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
495 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
497 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
500 out:
501 if (node_info != NULL)
502 g_dbus_node_info_unref (node_info);
503 if (result != NULL)
504 g_variant_unref (result);
506 return ret;
509 /* ---------------------------------------------------------------------------------------------------- */
511 static GVariant *
512 _g_variant_parse_me_harder (GVariantType *type,
513 const gchar *given_str,
514 GError **error)
516 GVariant *value;
517 gchar *s;
518 guint n;
519 GString *str;
521 str = g_string_new ("\"");
522 for (n = 0; given_str[n] != '\0'; n++)
524 if (G_UNLIKELY (given_str[n] == '\"'))
525 g_string_append (str, "\\\"");
526 else
527 g_string_append_c (str, given_str[n]);
529 g_string_append_c (str, '"');
530 s = g_string_free (str, FALSE);
532 value = g_variant_parse (type,
534 NULL,
535 NULL,
536 error);
537 g_free (s);
539 return value;
542 /* ---------------------------------------------------------------------------------------------------- */
544 static gchar *opt_emit_dest = NULL;
545 static gchar *opt_emit_object_path = NULL;
546 static gchar *opt_emit_signal = NULL;
548 static const GOptionEntry emit_entries[] =
550 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
551 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
552 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
553 { NULL }
556 static gboolean
557 handle_emit (gint *argc,
558 gchar **argv[],
559 gboolean request_completion,
560 const gchar *completion_cur,
561 const gchar *completion_prev)
563 gint ret;
564 GOptionContext *o;
565 gchar *s;
566 GError *error;
567 GDBusConnection *c;
568 GVariant *parameters;
569 gchar *interface_name;
570 gchar *signal_name;
571 GVariantBuilder builder;
572 gboolean skip_dashes;
573 guint parm;
574 guint n;
575 gboolean complete_names, complete_paths, complete_signals;
577 ret = FALSE;
578 c = NULL;
579 parameters = NULL;
580 interface_name = NULL;
581 signal_name = NULL;
583 modify_argv0_for_command (argc, argv, "emit");
585 o = g_option_context_new (NULL);
586 g_option_context_set_help_enabled (o, FALSE);
587 g_option_context_set_summary (o, _("Emit a signal."));
588 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
589 g_option_context_add_group (o, connection_get_group ());
591 complete_names = FALSE;
592 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
594 complete_names = TRUE;
595 remove_arg ((*argc) - 1, argc, argv);
598 complete_paths = FALSE;
599 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
601 complete_paths = TRUE;
602 remove_arg ((*argc) - 1, argc, argv);
605 complete_signals = FALSE;
606 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0)
608 complete_signals = TRUE;
609 remove_arg ((*argc) - 1, argc, argv);
612 if (!g_option_context_parse (o, argc, argv, NULL))
614 if (!request_completion)
616 s = g_option_context_get_help (o, FALSE, NULL);
617 g_printerr ("%s", s);
618 g_free (s);
619 goto out;
623 error = NULL;
624 c = connection_get_dbus_connection (&error);
625 if (c == NULL)
627 if (request_completion)
629 if (g_strcmp0 (completion_prev, "--address") == 0)
631 g_print ("unix:\n"
632 "tcp:\n"
633 "nonce-tcp:\n");
635 else
637 g_print ("--system \n--session \n--address \n");
640 else
642 g_printerr (_("Error connecting: %s\n"), error->message);
643 g_error_free (error);
645 goto out;
648 /* validate and complete destination (bus name) */
649 if (complete_names)
651 print_names (c, FALSE);
652 goto out;
654 if (opt_emit_dest == NULL)
656 if (request_completion)
657 g_print ("--dest \n");
658 else
659 g_printerr (_("Error: Destination is not specified\n"));
660 goto out;
662 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
664 print_names (c, g_str_has_prefix (opt_emit_dest, ":"));
665 goto out;
668 if (!request_completion && !g_dbus_is_unique_name (opt_emit_dest))
670 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
671 goto out;
674 /* validate and complete object path */
675 if (complete_paths)
677 print_paths (c, opt_emit_dest, "/");
678 goto out;
680 if (opt_emit_object_path == NULL)
682 if (request_completion)
683 g_print ("--object-path \n");
684 else
685 g_printerr (_("Error: Object path is not specified\n"));
686 goto out;
688 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
690 gchar *p;
691 s = g_strdup (opt_emit_object_path);
692 p = strrchr (s, '/');
693 if (p != NULL)
695 if (p == s)
696 p++;
697 *p = '\0';
699 print_paths (c, opt_emit_dest, s);
700 g_free (s);
701 goto out;
703 if (!request_completion && !g_variant_is_object_path (opt_emit_object_path))
705 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
706 goto out;
709 /* validate and complete signal (interface + signal name) */
710 if (complete_signals)
712 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
713 goto out;
715 if (opt_emit_signal == NULL)
717 if (request_completion)
718 g_print ("--signal \n");
719 else
720 g_printerr (_("Error: Signal name is not specified\n"));
721 goto out;
723 if (request_completion && g_strcmp0 ("--signal", completion_prev) == 0)
725 print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
726 goto out;
728 s = strrchr (opt_emit_signal, '.');
729 if (!request_completion && s == NULL)
731 g_printerr (_("Error: Signal name “%s” is invalid\n"), opt_emit_signal);
732 goto out;
734 signal_name = g_strdup (s + 1);
735 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
737 /* All done with completion now */
738 if (request_completion)
739 goto out;
741 if (!g_dbus_is_interface_name (interface_name))
743 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
744 goto out;
747 if (!g_dbus_is_member_name (signal_name))
749 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
750 goto out;
753 /* Read parameters */
754 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
755 skip_dashes = TRUE;
756 parm = 0;
757 for (n = 1; n < (guint) *argc; n++)
759 GVariant *value;
761 /* Under certain conditions, g_option_context_parse returns the "--"
762 itself (setting off unparsed arguments), too: */
763 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
765 skip_dashes = FALSE;
766 continue;
769 error = NULL;
770 value = g_variant_parse (NULL,
771 (*argv)[n],
772 NULL,
773 NULL,
774 &error);
775 if (value == NULL)
777 gchar *context;
779 context = g_variant_parse_error_print_context (error, (*argv)[n]);
780 g_error_free (error);
781 error = NULL;
782 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
783 if (value == NULL)
785 /* Use the original non-"parse-me-harder" error */
786 g_printerr (_("Error parsing parameter %d: %s\n"),
787 parm + 1,
788 context);
789 g_error_free (error);
790 g_free (context);
791 g_variant_builder_clear (&builder);
792 goto out;
794 g_free (context);
796 g_variant_builder_add_value (&builder, value);
797 ++parm;
799 parameters = g_variant_builder_end (&builder);
801 if (parameters != NULL)
802 parameters = g_variant_ref_sink (parameters);
803 if (!g_dbus_connection_emit_signal (c,
804 opt_emit_dest,
805 opt_emit_object_path,
806 interface_name,
807 signal_name,
808 parameters,
809 &error))
811 g_printerr (_("Error: %s\n"), error->message);
812 g_error_free (error);
813 goto out;
816 if (!g_dbus_connection_flush_sync (c, NULL, &error))
818 g_printerr (_("Error flushing connection: %s\n"), error->message);
819 g_error_free (error);
820 goto out;
823 ret = TRUE;
825 out:
826 if (c != NULL)
827 g_object_unref (c);
828 if (parameters != NULL)
829 g_variant_unref (parameters);
830 g_free (interface_name);
831 g_free (signal_name);
832 g_option_context_free (o);
833 return ret;
836 /* ---------------------------------------------------------------------------------------------------- */
838 static gchar *opt_call_dest = NULL;
839 static gchar *opt_call_object_path = NULL;
840 static gchar *opt_call_method = NULL;
841 static gint opt_call_timeout = -1;
843 static const GOptionEntry call_entries[] =
845 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
846 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
847 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
848 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
849 { NULL }
852 static gboolean
853 handle_call (gint *argc,
854 gchar **argv[],
855 gboolean request_completion,
856 const gchar *completion_cur,
857 const gchar *completion_prev)
859 gint ret;
860 GOptionContext *o;
861 gchar *s;
862 GError *error;
863 GDBusConnection *c;
864 GVariant *parameters;
865 gchar *interface_name;
866 gchar *method_name;
867 GVariant *result;
868 GPtrArray *in_signature_types;
869 gboolean complete_names;
870 gboolean complete_paths;
871 gboolean complete_methods;
872 GVariantBuilder builder;
873 gboolean skip_dashes;
874 guint parm;
875 guint n;
877 ret = FALSE;
878 c = NULL;
879 parameters = NULL;
880 interface_name = NULL;
881 method_name = NULL;
882 result = NULL;
883 in_signature_types = NULL;
885 modify_argv0_for_command (argc, argv, "call");
887 o = g_option_context_new (NULL);
888 g_option_context_set_help_enabled (o, FALSE);
889 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
890 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
891 g_option_context_add_group (o, connection_get_group ());
893 complete_names = FALSE;
894 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
896 complete_names = TRUE;
897 remove_arg ((*argc) - 1, argc, argv);
900 complete_paths = FALSE;
901 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
903 complete_paths = TRUE;
904 remove_arg ((*argc) - 1, argc, argv);
907 complete_methods = FALSE;
908 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
910 complete_methods = TRUE;
911 remove_arg ((*argc) - 1, argc, argv);
914 if (!g_option_context_parse (o, argc, argv, NULL))
916 if (!request_completion)
918 s = g_option_context_get_help (o, FALSE, NULL);
919 g_printerr ("%s", s);
920 g_free (s);
921 goto out;
925 error = NULL;
926 c = connection_get_dbus_connection (&error);
927 if (c == NULL)
929 if (request_completion)
931 if (g_strcmp0 (completion_prev, "--address") == 0)
933 g_print ("unix:\n"
934 "tcp:\n"
935 "nonce-tcp:\n");
937 else
939 g_print ("--system \n--session \n--address \n");
942 else
944 g_printerr (_("Error connecting: %s\n"), error->message);
945 g_error_free (error);
947 goto out;
950 /* validate and complete destination (bus name) */
951 if (complete_names)
953 print_names (c, FALSE);
954 goto out;
956 if (opt_call_dest == NULL)
958 if (request_completion)
959 g_print ("--dest \n");
960 else
961 g_printerr (_("Error: Destination is not specified\n"));
962 goto out;
964 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
966 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
967 goto out;
970 if (!request_completion && !g_dbus_is_name (opt_call_dest))
972 g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest);
973 goto out;
976 /* validate and complete object path */
977 if (complete_paths)
979 print_paths (c, opt_call_dest, "/");
980 goto out;
982 if (opt_call_object_path == NULL)
984 if (request_completion)
985 g_print ("--object-path \n");
986 else
987 g_printerr (_("Error: Object path is not specified\n"));
988 goto out;
990 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
992 gchar *p;
993 s = g_strdup (opt_call_object_path);
994 p = strrchr (s, '/');
995 if (p != NULL)
997 if (p == s)
998 p++;
999 *p = '\0';
1001 print_paths (c, opt_call_dest, s);
1002 g_free (s);
1003 goto out;
1005 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
1007 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
1008 goto out;
1011 /* validate and complete method (interface + method name) */
1012 if (complete_methods)
1014 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1015 goto out;
1017 if (opt_call_method == NULL)
1019 if (request_completion)
1020 g_print ("--method \n");
1021 else
1022 g_printerr (_("Error: Method name is not specified\n"));
1023 goto out;
1025 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
1027 print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1028 goto out;
1030 s = strrchr (opt_call_method, '.');
1031 if (!request_completion && s == NULL)
1033 g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method);
1034 goto out;
1036 method_name = g_strdup (s + 1);
1037 interface_name = g_strndup (opt_call_method, s - opt_call_method);
1039 /* All done with completion now */
1040 if (request_completion)
1041 goto out;
1043 /* Introspect, for easy conversion - it's not fatal if we can't do this */
1044 in_signature_types = call_helper_get_method_in_signature (c,
1045 opt_call_dest,
1046 opt_call_object_path,
1047 interface_name,
1048 method_name,
1049 &error);
1050 if (in_signature_types == NULL)
1052 //g_printerr ("Error getting introspection data: %s\n", error->message);
1053 g_error_free (error);
1054 error = NULL;
1057 /* Read parameters */
1058 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
1059 skip_dashes = TRUE;
1060 parm = 0;
1061 for (n = 1; n < (guint) *argc; n++)
1063 GVariant *value;
1064 GVariantType *type;
1066 /* Under certain conditions, g_option_context_parse returns the "--"
1067 itself (setting off unparsed arguments), too: */
1068 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
1070 skip_dashes = FALSE;
1071 continue;
1074 type = NULL;
1075 if (in_signature_types != NULL)
1077 if (parm >= in_signature_types->len)
1079 /* Only warn for the first param */
1080 if (parm == in_signature_types->len)
1082 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
1083 in_signature_types->len);
1086 else
1088 type = in_signature_types->pdata[parm];
1092 error = NULL;
1093 value = g_variant_parse (type,
1094 (*argv)[n],
1095 NULL,
1096 NULL,
1097 &error);
1098 if (value == NULL)
1100 gchar *context;
1102 context = g_variant_parse_error_print_context (error, (*argv)[n]);
1103 g_error_free (error);
1104 error = NULL;
1105 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1106 if (value == NULL)
1108 if (type != NULL)
1110 s = g_variant_type_dup_string (type);
1111 g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"),
1112 parm + 1,
1114 context);
1115 g_free (s);
1117 else
1119 g_printerr (_("Error parsing parameter %d: %s\n"),
1120 parm + 1,
1121 context);
1123 g_error_free (error);
1124 g_variant_builder_clear (&builder);
1125 g_free (context);
1126 goto out;
1128 g_free (context);
1130 g_variant_builder_add_value (&builder, value);
1131 ++parm;
1133 parameters = g_variant_builder_end (&builder);
1135 if (parameters != NULL)
1136 parameters = g_variant_ref_sink (parameters);
1137 result = g_dbus_connection_call_sync (c,
1138 opt_call_dest,
1139 opt_call_object_path,
1140 interface_name,
1141 method_name,
1142 parameters,
1143 NULL,
1144 G_DBUS_CALL_FLAGS_NONE,
1145 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1146 NULL,
1147 &error);
1148 if (result == NULL)
1150 g_printerr (_("Error: %s\n"), error->message);
1152 if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL)
1154 if (in_signature_types->len > 0)
1156 GString *s;
1157 s = g_string_new (NULL);
1159 for (n = 0; n < in_signature_types->len; n++)
1161 GVariantType *type = in_signature_types->pdata[n];
1162 g_string_append_len (s,
1163 g_variant_type_peek_string (type),
1164 g_variant_type_get_string_length (type));
1167 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1168 g_string_free (s, TRUE);
1170 else
1171 g_printerr ("(According to introspection data, you need to pass no arguments)\n");
1174 g_error_free (error);
1175 goto out;
1178 s = g_variant_print (result, TRUE);
1179 g_print ("%s\n", s);
1180 g_free (s);
1182 ret = TRUE;
1184 out:
1185 if (in_signature_types != NULL)
1186 g_ptr_array_unref (in_signature_types);
1187 if (result != NULL)
1188 g_variant_unref (result);
1189 if (c != NULL)
1190 g_object_unref (c);
1191 if (parameters != NULL)
1192 g_variant_unref (parameters);
1193 g_free (interface_name);
1194 g_free (method_name);
1195 g_option_context_free (o);
1196 return ret;
1199 /* ---------------------------------------------------------------------------------------------------- */
1201 static gchar *opt_introspect_dest = NULL;
1202 static gchar *opt_introspect_object_path = NULL;
1203 static gboolean opt_introspect_xml = FALSE;
1204 static gboolean opt_introspect_recurse = FALSE;
1205 static gboolean opt_introspect_only_properties = FALSE;
1207 static void
1208 dump_annotation (const GDBusAnnotationInfo *o,
1209 guint indent,
1210 gboolean ignore_indent)
1212 guint n;
1213 g_print ("%*s@%s(\"%s\")\n",
1214 ignore_indent ? 0 : indent, "",
1215 o->key,
1216 o->value);
1217 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1218 dump_annotation (o->annotations[n], indent + 2, FALSE);
1221 static void
1222 dump_arg (const GDBusArgInfo *o,
1223 guint indent,
1224 const gchar *direction,
1225 gboolean ignore_indent,
1226 gboolean include_newline)
1228 guint n;
1230 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1232 dump_annotation (o->annotations[n], indent, ignore_indent);
1233 ignore_indent = FALSE;
1236 g_print ("%*s%s%s %s%s",
1237 ignore_indent ? 0 : indent, "",
1238 direction,
1239 o->signature,
1240 o->name,
1241 include_newline ? ",\n" : "");
1244 static guint
1245 count_args (GDBusArgInfo **args)
1247 guint n;
1248 n = 0;
1249 if (args == NULL)
1250 goto out;
1251 while (args[n] != NULL)
1252 n++;
1253 out:
1254 return n;
1257 static void
1258 dump_method (const GDBusMethodInfo *o,
1259 guint indent)
1261 guint n;
1262 guint m;
1263 guint name_len;
1264 guint total_num_args;
1266 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1267 dump_annotation (o->annotations[n], indent, FALSE);
1269 g_print ("%*s%s(", indent, "", o->name);
1270 name_len = strlen (o->name);
1271 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1272 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1274 gboolean ignore_indent = (m == 0);
1275 gboolean include_newline = (m != total_num_args - 1);
1277 dump_arg (o->in_args[n],
1278 indent + name_len + 1,
1279 "in ",
1280 ignore_indent,
1281 include_newline);
1283 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1285 gboolean ignore_indent = (m == 0);
1286 gboolean include_newline = (m != total_num_args - 1);
1287 dump_arg (o->out_args[n],
1288 indent + name_len + 1,
1289 "out ",
1290 ignore_indent,
1291 include_newline);
1293 g_print (");\n");
1296 static void
1297 dump_signal (const GDBusSignalInfo *o,
1298 guint indent)
1300 guint n;
1301 guint name_len;
1302 guint total_num_args;
1304 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1305 dump_annotation (o->annotations[n], indent, FALSE);
1307 g_print ("%*s%s(", indent, "", o->name);
1308 name_len = strlen (o->name);
1309 total_num_args = count_args (o->args);
1310 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1312 gboolean ignore_indent = (n == 0);
1313 gboolean include_newline = (n != total_num_args - 1);
1314 dump_arg (o->args[n],
1315 indent + name_len + 1,
1317 ignore_indent,
1318 include_newline);
1320 g_print (");\n");
1323 static void
1324 dump_property (const GDBusPropertyInfo *o,
1325 guint indent,
1326 GVariant *value)
1328 const gchar *access;
1329 guint n;
1331 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1332 access = "readonly";
1333 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1334 access = "writeonly";
1335 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1336 access = "readwrite";
1337 else
1338 g_assert_not_reached ();
1340 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1341 dump_annotation (o->annotations[n], indent, FALSE);
1343 if (value != NULL)
1345 gchar *s = g_variant_print (value, FALSE);
1346 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1347 g_free (s);
1349 else
1351 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1355 static void
1356 dump_interface (GDBusConnection *c,
1357 const gchar *name,
1358 const GDBusInterfaceInfo *o,
1359 guint indent,
1360 const gchar *object_path)
1362 guint n;
1363 GHashTable *properties;
1365 properties = g_hash_table_new_full (g_str_hash,
1366 g_str_equal,
1367 g_free,
1368 (GDestroyNotify) g_variant_unref);
1370 /* Try to get properties */
1371 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1373 GVariant *result;
1374 result = g_dbus_connection_call_sync (c,
1375 name,
1376 object_path,
1377 "org.freedesktop.DBus.Properties",
1378 "GetAll",
1379 g_variant_new ("(s)", o->name),
1380 NULL,
1381 G_DBUS_CALL_FLAGS_NONE,
1382 3000,
1383 NULL,
1384 NULL);
1385 if (result != NULL)
1387 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1389 GVariantIter *iter;
1390 GVariant *item;
1391 g_variant_get (result,
1392 "(a{sv})",
1393 &iter);
1394 while ((item = g_variant_iter_next_value (iter)))
1396 gchar *key;
1397 GVariant *value;
1398 g_variant_get (item,
1399 "{sv}",
1400 &key,
1401 &value);
1403 g_hash_table_insert (properties, key, g_variant_ref (value));
1406 g_variant_unref (result);
1408 else
1410 guint n;
1411 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1413 result = g_dbus_connection_call_sync (c,
1414 name,
1415 object_path,
1416 "org.freedesktop.DBus.Properties",
1417 "Get",
1418 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1419 G_VARIANT_TYPE ("(v)"),
1420 G_DBUS_CALL_FLAGS_NONE,
1421 3000,
1422 NULL,
1423 NULL);
1424 if (result != NULL)
1426 GVariant *property_value;
1427 g_variant_get (result,
1428 "(v)",
1429 &property_value);
1430 g_hash_table_insert (properties,
1431 g_strdup (o->properties[n]->name),
1432 g_variant_ref (property_value));
1433 g_variant_unref (result);
1439 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1440 dump_annotation (o->annotations[n], indent, FALSE);
1442 g_print ("%*sinterface %s {\n", indent, "", o->name);
1443 if (o->methods != NULL && !opt_introspect_only_properties)
1445 g_print ("%*s methods:\n", indent, "");
1446 for (n = 0; o->methods[n] != NULL; n++)
1447 dump_method (o->methods[n], indent + 4);
1449 if (o->signals != NULL && !opt_introspect_only_properties)
1451 g_print ("%*s signals:\n", indent, "");
1452 for (n = 0; o->signals[n] != NULL; n++)
1453 dump_signal (o->signals[n], indent + 4);
1455 if (o->properties != NULL)
1457 g_print ("%*s properties:\n", indent, "");
1458 for (n = 0; o->properties[n] != NULL; n++)
1460 dump_property (o->properties[n],
1461 indent + 4,
1462 g_hash_table_lookup (properties, (o->properties[n])->name));
1465 g_print ("%*s};\n",
1466 indent, "");
1468 g_hash_table_unref (properties);
1471 static gboolean
1472 introspect_do (GDBusConnection *c,
1473 const gchar *object_path,
1474 guint indent);
1476 static void
1477 dump_node (GDBusConnection *c,
1478 const gchar *name,
1479 const GDBusNodeInfo *o,
1480 guint indent,
1481 const gchar *object_path,
1482 gboolean recurse)
1484 guint n;
1485 const gchar *object_path_to_print;
1487 object_path_to_print = object_path;
1488 if (o->path != NULL)
1489 object_path_to_print = o->path;
1491 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1492 dump_annotation (o->annotations[n], indent, FALSE);
1494 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1495 if (o->interfaces != NULL || o->nodes != NULL)
1497 g_print (" {\n");
1498 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1500 if (opt_introspect_only_properties)
1502 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1503 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1505 else
1507 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1510 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1512 if (recurse)
1514 gchar *child_path;
1515 if (g_variant_is_object_path (o->nodes[n]->path))
1517 child_path = g_strdup (o->nodes[n]->path);
1518 /* avoid infinite loops */
1519 if (g_str_has_prefix (child_path, object_path))
1521 introspect_do (c, child_path, indent + 2);
1523 else
1525 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1526 child_path, object_path);
1529 else
1531 if (g_strcmp0 (object_path, "/") == 0)
1532 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1533 else
1534 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1535 introspect_do (c, child_path, indent + 2);
1537 g_free (child_path);
1539 else
1541 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1544 g_print ("%*s};\n",
1545 indent, "");
1547 else
1549 g_print ("\n");
1553 static const GOptionEntry introspect_entries[] =
1555 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1556 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1557 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1558 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1559 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1560 { NULL }
1563 static gboolean
1564 introspect_do (GDBusConnection *c,
1565 const gchar *object_path,
1566 guint indent)
1568 GError *error;
1569 GVariant *result;
1570 GDBusNodeInfo *node;
1571 gboolean ret;
1572 const gchar *xml_data;
1574 ret = FALSE;
1575 node = NULL;
1576 result = NULL;
1578 error = NULL;
1579 result = g_dbus_connection_call_sync (c,
1580 opt_introspect_dest,
1581 object_path,
1582 "org.freedesktop.DBus.Introspectable",
1583 "Introspect",
1584 NULL,
1585 G_VARIANT_TYPE ("(s)"),
1586 G_DBUS_CALL_FLAGS_NONE,
1587 3000, /* 3 sec */
1588 NULL,
1589 &error);
1590 if (result == NULL)
1592 g_printerr (_("Error: %s\n"), error->message);
1593 g_error_free (error);
1594 goto out;
1596 g_variant_get (result, "(&s)", &xml_data);
1598 if (opt_introspect_xml)
1600 g_print ("%s", xml_data);
1602 else
1604 error = NULL;
1605 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1606 if (node == NULL)
1608 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1609 g_error_free (error);
1610 goto out;
1613 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1616 ret = TRUE;
1618 out:
1619 if (node != NULL)
1620 g_dbus_node_info_unref (node);
1621 if (result != NULL)
1622 g_variant_unref (result);
1623 return ret;
1626 static gboolean
1627 handle_introspect (gint *argc,
1628 gchar **argv[],
1629 gboolean request_completion,
1630 const gchar *completion_cur,
1631 const gchar *completion_prev)
1633 gint ret;
1634 GOptionContext *o;
1635 gchar *s;
1636 GError *error;
1637 GDBusConnection *c;
1638 gboolean complete_names;
1639 gboolean complete_paths;
1641 ret = FALSE;
1642 c = NULL;
1644 modify_argv0_for_command (argc, argv, "introspect");
1646 o = g_option_context_new (NULL);
1647 if (request_completion)
1648 g_option_context_set_ignore_unknown_options (o, TRUE);
1649 g_option_context_set_help_enabled (o, FALSE);
1650 g_option_context_set_summary (o, _("Introspect a remote object."));
1651 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1652 g_option_context_add_group (o, connection_get_group ());
1654 complete_names = FALSE;
1655 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1657 complete_names = TRUE;
1658 remove_arg ((*argc) - 1, argc, argv);
1661 complete_paths = FALSE;
1662 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1664 complete_paths = TRUE;
1665 remove_arg ((*argc) - 1, argc, argv);
1668 if (!g_option_context_parse (o, argc, argv, NULL))
1670 if (!request_completion)
1672 s = g_option_context_get_help (o, FALSE, NULL);
1673 g_printerr ("%s", s);
1674 g_free (s);
1675 goto out;
1679 error = NULL;
1680 c = connection_get_dbus_connection (&error);
1681 if (c == NULL)
1683 if (request_completion)
1685 if (g_strcmp0 (completion_prev, "--address") == 0)
1687 g_print ("unix:\n"
1688 "tcp:\n"
1689 "nonce-tcp:\n");
1691 else
1693 g_print ("--system \n--session \n--address \n");
1696 else
1698 g_printerr (_("Error connecting: %s\n"), error->message);
1699 g_error_free (error);
1701 goto out;
1704 if (complete_names)
1706 print_names (c, FALSE);
1707 goto out;
1709 /* this only makes sense on message bus connections */
1710 if (opt_introspect_dest == NULL)
1712 if (request_completion)
1713 g_print ("--dest \n");
1714 else
1715 g_printerr (_("Error: Destination is not specified\n"));
1716 goto out;
1718 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1720 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1721 goto out;
1724 if (complete_paths)
1726 print_paths (c, opt_introspect_dest, "/");
1727 goto out;
1730 if (!request_completion && !g_dbus_is_name (opt_introspect_dest))
1732 g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest);
1733 goto out;
1736 if (opt_introspect_object_path == NULL)
1738 if (request_completion)
1739 g_print ("--object-path \n");
1740 else
1741 g_printerr (_("Error: Object path is not specified\n"));
1742 goto out;
1744 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1746 gchar *p;
1747 s = g_strdup (opt_introspect_object_path);
1748 p = strrchr (s, '/');
1749 if (p != NULL)
1751 if (p == s)
1752 p++;
1753 *p = '\0';
1755 print_paths (c, opt_introspect_dest, s);
1756 g_free (s);
1757 goto out;
1759 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1761 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1762 goto out;
1765 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1767 g_print ("--recurse \n");
1770 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1772 g_print ("--only-properties \n");
1775 /* All done with completion now */
1776 if (request_completion)
1777 goto out;
1779 if (!introspect_do (c, opt_introspect_object_path, 0))
1780 goto out;
1782 ret = TRUE;
1784 out:
1785 if (c != NULL)
1786 g_object_unref (c);
1787 g_option_context_free (o);
1788 return ret;
1791 /* ---------------------------------------------------------------------------------------------------- */
1793 static gchar *opt_monitor_dest = NULL;
1794 static gchar *opt_monitor_object_path = NULL;
1796 static guint monitor_filter_id = 0;
1798 static void
1799 monitor_signal_cb (GDBusConnection *connection,
1800 const gchar *sender_name,
1801 const gchar *object_path,
1802 const gchar *interface_name,
1803 const gchar *signal_name,
1804 GVariant *parameters,
1805 gpointer user_data)
1807 gchar *s;
1808 s = g_variant_print (parameters, TRUE);
1809 g_print ("%s: %s.%s %s\n",
1810 object_path,
1811 interface_name,
1812 signal_name,
1814 g_free (s);
1817 static void
1818 monitor_on_name_appeared (GDBusConnection *connection,
1819 const gchar *name,
1820 const gchar *name_owner,
1821 gpointer user_data)
1823 g_print ("The name %s is owned by %s\n", name, name_owner);
1824 g_assert (monitor_filter_id == 0);
1825 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1826 name_owner,
1827 NULL, /* any interface */
1828 NULL, /* any member */
1829 opt_monitor_object_path,
1830 NULL, /* arg0 */
1831 G_DBUS_SIGNAL_FLAGS_NONE,
1832 monitor_signal_cb,
1833 NULL, /* user_data */
1834 NULL); /* user_data destroy notify */
1837 static void
1838 monitor_on_name_vanished (GDBusConnection *connection,
1839 const gchar *name,
1840 gpointer user_data)
1842 g_print ("The name %s does not have an owner\n", name);
1844 if (monitor_filter_id != 0)
1846 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1847 monitor_filter_id = 0;
1851 static const GOptionEntry monitor_entries[] =
1853 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1854 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1855 { NULL }
1858 static gboolean
1859 handle_monitor (gint *argc,
1860 gchar **argv[],
1861 gboolean request_completion,
1862 const gchar *completion_cur,
1863 const gchar *completion_prev)
1865 gint ret;
1866 GOptionContext *o;
1867 gchar *s;
1868 GError *error;
1869 GDBusConnection *c;
1870 gboolean complete_names;
1871 gboolean complete_paths;
1872 GMainLoop *loop;
1874 ret = FALSE;
1875 c = NULL;
1877 modify_argv0_for_command (argc, argv, "monitor");
1879 o = g_option_context_new (NULL);
1880 if (request_completion)
1881 g_option_context_set_ignore_unknown_options (o, TRUE);
1882 g_option_context_set_help_enabled (o, FALSE);
1883 g_option_context_set_summary (o, _("Monitor a remote object."));
1884 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1885 g_option_context_add_group (o, connection_get_group ());
1887 complete_names = FALSE;
1888 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1890 complete_names = TRUE;
1891 remove_arg ((*argc) - 1, argc, argv);
1894 complete_paths = FALSE;
1895 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1897 complete_paths = TRUE;
1898 remove_arg ((*argc) - 1, argc, argv);
1901 if (!g_option_context_parse (o, argc, argv, NULL))
1903 if (!request_completion)
1905 s = g_option_context_get_help (o, FALSE, NULL);
1906 g_printerr ("%s", s);
1907 g_free (s);
1908 goto out;
1912 error = NULL;
1913 c = connection_get_dbus_connection (&error);
1914 if (c == NULL)
1916 if (request_completion)
1918 if (g_strcmp0 (completion_prev, "--address") == 0)
1920 g_print ("unix:\n"
1921 "tcp:\n"
1922 "nonce-tcp:\n");
1924 else
1926 g_print ("--system \n--session \n--address \n");
1929 else
1931 g_printerr (_("Error connecting: %s\n"), error->message);
1932 g_error_free (error);
1934 goto out;
1937 /* Monitoring doesn’t make sense on a non-message-bus connection. */
1938 if (g_dbus_connection_get_unique_name (c) == NULL)
1940 if (!request_completion)
1941 g_printerr (_("Error: can’t monitor a non-message-bus connection\n"));
1942 goto out;
1945 if (complete_names)
1947 print_names (c, FALSE);
1948 goto out;
1950 /* this only makes sense on message bus connections */
1951 if (opt_monitor_dest == NULL)
1953 if (request_completion)
1954 g_print ("--dest \n");
1955 else
1956 g_printerr (_("Error: Destination is not specified\n"));
1957 goto out;
1959 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1961 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1962 goto out;
1965 if (!request_completion && !g_dbus_is_name (opt_monitor_dest))
1967 g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest);
1968 goto out;
1971 if (complete_paths)
1973 print_paths (c, opt_monitor_dest, "/");
1974 goto out;
1976 if (opt_monitor_object_path == NULL)
1978 if (request_completion)
1980 g_print ("--object-path \n");
1981 goto out;
1983 /* it's fine to not have an object path */
1985 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1987 gchar *p;
1988 s = g_strdup (opt_monitor_object_path);
1989 p = strrchr (s, '/');
1990 if (p != NULL)
1992 if (p == s)
1993 p++;
1994 *p = '\0';
1996 print_paths (c, opt_monitor_dest, s);
1997 g_free (s);
1998 goto out;
2000 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
2002 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
2003 goto out;
2006 /* All done with completion now */
2007 if (request_completion)
2008 goto out;
2010 if (opt_monitor_object_path != NULL)
2011 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
2012 else
2013 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
2015 loop = g_main_loop_new (NULL, FALSE);
2016 g_bus_watch_name_on_connection (c,
2017 opt_monitor_dest,
2018 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2019 monitor_on_name_appeared,
2020 monitor_on_name_vanished,
2021 NULL,
2022 NULL);
2024 g_main_loop_run (loop);
2025 g_main_loop_unref (loop);
2027 ret = TRUE;
2029 out:
2030 if (c != NULL)
2031 g_object_unref (c);
2032 g_option_context_free (o);
2033 return ret;
2036 /* ---------------------------------------------------------------------------------------------------- */
2038 static gboolean opt_wait_activate_set = FALSE;
2039 static gchar *opt_wait_activate_name = NULL;
2040 static gint64 opt_wait_timeout = 0; /* no timeout */
2042 typedef enum {
2043 WAIT_STATE_RUNNING, /* waiting to see the service */
2044 WAIT_STATE_SUCCESS, /* seen it successfully */
2045 WAIT_STATE_TIMEOUT, /* timed out before seeing it */
2046 } WaitState;
2048 static gboolean
2049 opt_wait_activate_cb (const gchar *option_name,
2050 const gchar *value,
2051 gpointer data,
2052 GError **error)
2054 /* @value may be NULL */
2055 opt_wait_activate_set = TRUE;
2056 opt_wait_activate_name = g_strdup (value);
2058 return TRUE;
2061 static const GOptionEntry wait_entries[] =
2063 { "activate", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
2064 opt_wait_activate_cb,
2065 N_("Service to activate before waiting for the other one (well-known name)"),
2066 "[NAME]" },
2067 { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout,
2068 N_("Timeout to wait for before exiting with an error (seconds); 0 for "
2069 "no timeout (default)"), "SECS" },
2070 { NULL }
2073 static void
2074 wait_name_appeared_cb (GDBusConnection *connection,
2075 const gchar *name,
2076 const gchar *name_owner,
2077 gpointer user_data)
2079 WaitState *wait_state = user_data;
2081 *wait_state = WAIT_STATE_SUCCESS;
2084 static gboolean
2085 wait_timeout_cb (gpointer user_data)
2087 WaitState *wait_state = user_data;
2089 *wait_state = WAIT_STATE_TIMEOUT;
2091 /* Removed in handle_wait(). */
2092 return G_SOURCE_CONTINUE;
2095 static gboolean
2096 handle_wait (gint *argc,
2097 gchar **argv[],
2098 gboolean request_completion,
2099 const gchar *completion_cur,
2100 const gchar *completion_prev)
2102 gint ret;
2103 GOptionContext *o;
2104 gchar *s;
2105 GError *error;
2106 GDBusConnection *c;
2107 guint watch_id, timer_id = 0, activate_watch_id;
2108 const gchar *activate_service, *wait_service;
2109 WaitState wait_state = WAIT_STATE_RUNNING;
2111 ret = FALSE;
2112 c = NULL;
2114 modify_argv0_for_command (argc, argv, "wait");
2116 o = g_option_context_new (_("[OPTION…] BUS-NAME"));
2117 g_option_context_set_help_enabled (o, FALSE);
2118 g_option_context_set_summary (o, _("Wait for a bus name to appear."));
2119 g_option_context_add_main_entries (o, wait_entries, GETTEXT_PACKAGE);
2120 g_option_context_add_group (o, connection_get_group ());
2122 if (!g_option_context_parse (o, argc, argv, NULL))
2124 if (!request_completion)
2126 s = g_option_context_get_help (o, FALSE, NULL);
2127 g_printerr ("%s", s);
2128 g_free (s);
2129 goto out;
2133 error = NULL;
2134 c = connection_get_dbus_connection (&error);
2135 if (c == NULL)
2137 if (request_completion)
2139 if (g_strcmp0 (completion_prev, "--address") == 0)
2141 g_print ("unix:\n"
2142 "tcp:\n"
2143 "nonce-tcp:\n");
2145 else
2147 g_print ("--system \n--session \n--address \n");
2150 else
2152 g_printerr (_("Error connecting: %s\n"), error->message);
2153 g_error_free (error);
2155 goto out;
2158 /* All done with completion now */
2159 if (request_completion)
2160 goto out;
2163 * Try and disentangle the command line arguments, with the aim of supporting:
2164 * gdbus wait --session --activate ActivateName WaitName
2165 * gdbus wait --session --activate ActivateAndWaitName
2166 * gdbus wait --activate --session ActivateAndWaitName
2167 * gdbus wait --session WaitName
2169 if (*argc == 2 && opt_wait_activate_set && opt_wait_activate_name != NULL)
2171 activate_service = opt_wait_activate_name;
2172 wait_service = (*argv)[1];
2174 else if (*argc == 2 &&
2175 opt_wait_activate_set && opt_wait_activate_name == NULL)
2177 activate_service = (*argv)[1];
2178 wait_service = (*argv)[1];
2180 else if (*argc == 2 && !opt_wait_activate_set)
2182 activate_service = NULL; /* disabled */
2183 wait_service = (*argv)[1];
2185 else if (*argc == 1 &&
2186 opt_wait_activate_set && opt_wait_activate_name != NULL)
2188 activate_service = opt_wait_activate_name;
2189 wait_service = opt_wait_activate_name;
2191 else if (*argc == 1 &&
2192 opt_wait_activate_set && opt_wait_activate_name == NULL)
2194 g_printerr (_("Error: A service to activate for must be specified.\n"));
2195 goto out;
2197 else if (*argc == 1 && !opt_wait_activate_set)
2199 g_printerr (_("Error: A service to wait for must be specified.\n"));
2200 goto out;
2202 else /* if (*argc > 2) */
2204 g_printerr (_("Error: Too many arguments.\n"));
2205 goto out;
2208 if (activate_service != NULL &&
2209 (!g_dbus_is_name (activate_service) ||
2210 g_dbus_is_unique_name (activate_service)))
2212 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2213 activate_service);
2214 goto out;
2217 if (!g_dbus_is_name (wait_service) || g_dbus_is_unique_name (wait_service))
2219 g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2220 wait_service);
2221 goto out;
2224 /* Start the prerequisite service if needed. */
2225 if (activate_service != NULL)
2227 activate_watch_id = g_bus_watch_name_on_connection (c, activate_service,
2228 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2229 NULL, NULL,
2230 NULL, NULL);
2232 else
2234 activate_watch_id = 0;
2237 /* Wait for the expected name to appear. */
2238 watch_id = g_bus_watch_name_on_connection (c,
2239 wait_service,
2240 G_BUS_NAME_WATCHER_FLAGS_NONE,
2241 wait_name_appeared_cb,
2242 NULL, &wait_state, NULL);
2244 /* Safety timeout. */
2245 if (opt_wait_timeout > 0)
2246 timer_id = g_timeout_add (opt_wait_timeout, wait_timeout_cb, &wait_state);
2248 while (wait_state == WAIT_STATE_RUNNING)
2249 g_main_context_iteration (NULL, TRUE);
2251 g_bus_unwatch_name (watch_id);
2252 if (timer_id != 0)
2253 g_source_remove (timer_id);
2254 if (activate_watch_id != 0)
2255 g_bus_unwatch_name (activate_watch_id);
2257 ret = (wait_state == WAIT_STATE_SUCCESS);
2259 out:
2260 g_clear_object (&c);
2261 g_option_context_free (o);
2262 g_free (opt_wait_activate_name);
2263 opt_wait_activate_name = NULL;
2265 return ret;
2268 /* ---------------------------------------------------------------------------------------------------- */
2270 static gchar *
2271 pick_word_at (const gchar *s,
2272 gint cursor,
2273 gint *out_word_begins_at)
2275 gint begin;
2276 gint end;
2278 if (s[0] == '\0')
2280 if (out_word_begins_at != NULL)
2281 *out_word_begins_at = -1;
2282 return NULL;
2285 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
2287 if (out_word_begins_at != NULL)
2288 *out_word_begins_at = cursor;
2289 return g_strdup ("");
2292 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
2293 cursor--;
2294 begin = cursor;
2296 end = begin;
2297 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
2298 end++;
2300 if (out_word_begins_at != NULL)
2301 *out_word_begins_at = begin;
2303 return g_strndup (s + begin, end - begin);
2306 gint
2307 main (gint argc, gchar *argv[])
2309 gint ret;
2310 const gchar *command;
2311 gboolean request_completion;
2312 gchar *completion_cur;
2313 gchar *completion_prev;
2314 #ifdef G_OS_WIN32
2315 gchar *tmp;
2316 #endif
2318 setlocale (LC_ALL, "");
2319 textdomain (GETTEXT_PACKAGE);
2321 #ifdef G_OS_WIN32
2322 tmp = _glib_get_locale_dir ();
2323 bindtextdomain (GETTEXT_PACKAGE, tmp);
2324 g_free (tmp);
2325 #else
2326 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2327 #endif
2329 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2330 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2331 #endif
2333 ret = 1;
2334 completion_cur = NULL;
2335 completion_prev = NULL;
2337 if (argc < 2)
2339 usage (&argc, &argv, FALSE);
2340 goto out;
2343 request_completion = FALSE;
2345 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
2347 again:
2348 command = argv[1];
2349 if (g_strcmp0 (command, "help") == 0)
2351 if (request_completion)
2353 /* do nothing */
2355 else
2357 usage (&argc, &argv, TRUE);
2358 ret = 0;
2360 goto out;
2362 else if (g_strcmp0 (command, "emit") == 0)
2364 if (handle_emit (&argc,
2365 &argv,
2366 request_completion,
2367 completion_cur,
2368 completion_prev))
2369 ret = 0;
2370 goto out;
2372 else if (g_strcmp0 (command, "call") == 0)
2374 if (handle_call (&argc,
2375 &argv,
2376 request_completion,
2377 completion_cur,
2378 completion_prev))
2379 ret = 0;
2380 goto out;
2382 else if (g_strcmp0 (command, "introspect") == 0)
2384 if (handle_introspect (&argc,
2385 &argv,
2386 request_completion,
2387 completion_cur,
2388 completion_prev))
2389 ret = 0;
2390 goto out;
2392 else if (g_strcmp0 (command, "monitor") == 0)
2394 if (handle_monitor (&argc,
2395 &argv,
2396 request_completion,
2397 completion_cur,
2398 completion_prev))
2399 ret = 0;
2400 goto out;
2402 else if (g_strcmp0 (command, "wait") == 0)
2404 if (handle_wait (&argc,
2405 &argv,
2406 request_completion,
2407 completion_cur,
2408 completion_prev))
2409 ret = 0;
2410 goto out;
2412 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2414 const gchar *completion_line;
2415 gchar **completion_argv;
2416 gint completion_argc;
2417 gint completion_point;
2418 gchar *endp;
2419 gint cur_begin;
2421 request_completion = TRUE;
2423 completion_line = argv[2];
2424 completion_point = strtol (argv[3], &endp, 10);
2425 if (endp == argv[3] || *endp != '\0')
2426 goto out;
2428 #if 0
2429 completion_debug ("completion_point=%d", completion_point);
2430 completion_debug ("----");
2431 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2432 completion_debug ("'%s'", completion_line);
2433 completion_debug (" %*s^",
2434 completion_point, "");
2435 completion_debug ("----");
2436 #endif
2438 if (!g_shell_parse_argv (completion_line,
2439 &completion_argc,
2440 &completion_argv,
2441 NULL))
2443 /* it's very possible the command line can't be parsed (for
2444 * example, missing quotes etc) - in that case, we just
2445 * don't autocomplete at all
2447 goto out;
2450 /* compute cur and prev */
2451 completion_prev = NULL;
2452 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2453 if (cur_begin > 0)
2455 gint prev_end;
2456 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2458 if (!g_ascii_isspace (completion_line[prev_end]))
2460 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2461 break;
2465 #if 0
2466 completion_debug (" cur='%s'", completion_cur);
2467 completion_debug ("prev='%s'", completion_prev);
2468 #endif
2470 argc = completion_argc;
2471 argv = completion_argv;
2473 ret = 0;
2475 goto again;
2477 else
2479 if (request_completion)
2481 g_print ("help \nemit \ncall \nintrospect \nmonitor \nwait \n");
2482 ret = 0;
2483 goto out;
2485 else
2487 g_printerr ("Unknown command '%s'\n", command);
2488 usage (&argc, &argv, FALSE);
2489 goto out;
2493 out:
2494 g_free (completion_cur);
2495 g_free (completion_prev);
2496 return ret;