Add new api to symbol lists and docs
[glib.git] / gio / gdbus-tool.c
bloba684c7a4bc736ea8e39ac06c963dbc3121bba6a2
1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
23 #include "config.h"
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <locale.h>
30 #include <gio/gio.h>
32 #include <gi18n.h>
34 /* ---------------------------------------------------------------------------------------------------- */
36 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
38 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
39 * to not have it interfere with stdout/stderr)
41 #if 0
42 G_GNUC_UNUSED static void
43 completion_debug (const gchar *format, ...)
45 va_list var_args;
46 gchar *s;
47 static FILE *f = NULL;
49 va_start (var_args, format);
50 s = g_strdup_vprintf (format, var_args);
51 if (f == NULL)
53 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
55 fprintf (f, "%s\n", s);
56 g_free (s);
58 #else
59 static void
60 completion_debug (const gchar *format, ...)
63 #endif
65 /* ---------------------------------------------------------------------------------------------------- */
68 static void
69 remove_arg (gint num, gint *argc, gchar **argv[])
71 gint n;
73 g_assert (num <= (*argc));
75 for (n = num; (*argv)[n] != NULL; n++)
76 (*argv)[n] = (*argv)[n+1];
77 (*argv)[n] = NULL;
78 (*argc) = (*argc) - 1;
81 static void
82 usage (gint *argc, gchar **argv[], gboolean use_stdout)
84 GOptionContext *o;
85 gchar *s;
86 gchar *program_name;
88 o = g_option_context_new (_("COMMAND"));
89 g_option_context_set_help_enabled (o, FALSE);
90 /* Ignore parsing result */
91 g_option_context_parse (o, argc, argv, NULL);
92 program_name = g_path_get_basename ((*argv)[0]);
93 s = g_strdup_printf (_("Commands:\n"
94 " help Shows this information\n"
95 " introspect Introspect a remote object\n"
96 " monitor Monitor a remote object\n"
97 " call Invoke a method on a remote object\n"
98 " emit Emit a signal\n"
99 "\n"
100 "Use \"%s COMMAND --help\" to get help on each command.\n"),
101 program_name);
102 g_free (program_name);
103 g_option_context_set_description (o, s);
104 g_free (s);
105 s = g_option_context_get_help (o, FALSE, NULL);
106 if (use_stdout)
107 g_print ("%s", s);
108 else
109 g_printerr ("%s", s);
110 g_free (s);
111 g_option_context_free (o);
114 static void
115 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
117 gchar *s;
118 gchar *program_name;
120 /* TODO:
121 * 1. get a g_set_prgname() ?; or
122 * 2. save old argv[0] and restore later
125 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
126 remove_arg (1, argc, argv);
128 program_name = g_path_get_basename ((*argv)[0]);
129 s = g_strdup_printf ("%s %s", (*argv)[0], command);
130 (*argv)[0] = s;
131 g_free (program_name);
134 /* ---------------------------------------------------------------------------------------------------- */
136 static void
137 print_methods (GDBusConnection *c,
138 const gchar *name,
139 const gchar *path)
141 GVariant *result;
142 GError *error;
143 const gchar *xml_data;
144 GDBusNodeInfo *node;
145 guint n;
146 guint m;
148 error = NULL;
149 result = g_dbus_connection_call_sync (c,
150 name,
151 path,
152 "org.freedesktop.DBus.Introspectable",
153 "Introspect",
154 NULL,
155 G_VARIANT_TYPE ("(s)"),
156 G_DBUS_CALL_FLAGS_NONE,
157 3000, /* 3 secs */
158 NULL,
159 &error);
160 if (result == NULL)
162 g_printerr (_("Error: %s\n"), error->message);
163 g_error_free (error);
164 goto out;
166 g_variant_get (result, "(&s)", &xml_data);
168 error = NULL;
169 node = g_dbus_node_info_new_for_xml (xml_data, &error);
170 g_variant_unref (result);
171 if (node == NULL)
173 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
174 g_error_free (error);
175 goto out;
178 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
180 const GDBusInterfaceInfo *iface = node->interfaces[n];
181 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
183 const GDBusMethodInfo *method = iface->methods[m];
184 g_print ("%s.%s \n", iface->name, method->name);
187 g_dbus_node_info_unref (node);
189 out:
193 static void
194 print_paths (GDBusConnection *c,
195 const gchar *name,
196 const gchar *path)
198 GVariant *result;
199 GError *error;
200 const gchar *xml_data;
201 GDBusNodeInfo *node;
202 guint n;
204 error = NULL;
205 result = g_dbus_connection_call_sync (c,
206 name,
207 path,
208 "org.freedesktop.DBus.Introspectable",
209 "Introspect",
210 NULL,
211 G_VARIANT_TYPE ("(s)"),
212 G_DBUS_CALL_FLAGS_NONE,
213 3000, /* 3 secs */
214 NULL,
215 &error);
216 if (result == NULL)
218 g_printerr (_("Error: %s\n"), error->message);
219 g_error_free (error);
220 goto out;
222 g_variant_get (result, "(&s)", &xml_data);
224 //g_printerr ("xml=`%s'", xml_data);
226 error = NULL;
227 node = g_dbus_node_info_new_for_xml (xml_data, &error);
228 g_variant_unref (result);
229 if (node == NULL)
231 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
232 g_error_free (error);
233 goto out;
236 //g_printerr ("bar `%s'\n", path);
238 if (node->interfaces != NULL)
239 g_print ("%s \n", path);
241 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
243 gchar *s;
245 //g_printerr ("foo `%s'\n", node->nodes[n].path);
247 if (g_strcmp0 (path, "/") == 0)
248 s = g_strdup_printf ("/%s", node->nodes[n]->path);
249 else
250 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
252 print_paths (c, name, s);
254 g_free (s);
256 g_dbus_node_info_unref (node);
258 out:
262 static void
263 print_names (GDBusConnection *c,
264 gboolean include_unique_names)
266 GVariant *result;
267 GError *error;
268 GVariantIter *iter;
269 gchar *str;
270 GHashTable *name_set;
271 GList *keys;
272 GList *l;
274 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
276 error = NULL;
277 result = g_dbus_connection_call_sync (c,
278 "org.freedesktop.DBus",
279 "/org/freedesktop/DBus",
280 "org.freedesktop.DBus",
281 "ListNames",
282 NULL,
283 G_VARIANT_TYPE ("(as)"),
284 G_DBUS_CALL_FLAGS_NONE,
285 3000, /* 3 secs */
286 NULL,
287 &error);
288 if (result == NULL)
290 g_printerr (_("Error: %s\n"), error->message);
291 g_error_free (error);
292 goto out;
294 g_variant_get (result, "(as)", &iter);
295 while (g_variant_iter_loop (iter, "s", &str))
296 g_hash_table_insert (name_set, g_strdup (str), NULL);
297 g_variant_iter_free (iter);
298 g_variant_unref (result);
300 error = NULL;
301 result = g_dbus_connection_call_sync (c,
302 "org.freedesktop.DBus",
303 "/org/freedesktop/DBus",
304 "org.freedesktop.DBus",
305 "ListActivatableNames",
306 NULL,
307 G_VARIANT_TYPE ("(as)"),
308 G_DBUS_CALL_FLAGS_NONE,
309 3000, /* 3 secs */
310 NULL,
311 &error);
312 if (result == NULL)
314 g_printerr (_("Error: %s\n"), error->message);
315 g_error_free (error);
316 goto out;
318 g_variant_get (result, "(as)", &iter);
319 while (g_variant_iter_loop (iter, "s", &str))
320 g_hash_table_insert (name_set, g_strdup (str), NULL);
321 g_variant_iter_free (iter);
322 g_variant_unref (result);
324 keys = g_hash_table_get_keys (name_set);
325 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
326 for (l = keys; l != NULL; l = l->next)
328 const gchar *name = l->data;
329 if (!include_unique_names && g_str_has_prefix (name, ":"))
330 continue;
332 g_print ("%s \n", name);
334 g_list_free (keys);
336 out:
337 g_hash_table_unref (name_set);
340 /* ---------------------------------------------------------------------------------------------------- */
342 static gboolean opt_connection_system = FALSE;
343 static gboolean opt_connection_session = FALSE;
344 static gchar *opt_connection_address = NULL;
346 static const GOptionEntry connection_entries[] =
348 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
349 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
350 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
351 { NULL }
354 static GOptionGroup *
355 connection_get_group (void)
357 static GOptionGroup *g;
359 g = g_option_group_new ("connection",
360 N_("Connection Endpoint Options:"),
361 N_("Options specifying the connection endpoint"),
362 NULL,
363 NULL);
364 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
365 g_option_group_add_entries (g, connection_entries);
367 return g;
370 static GDBusConnection *
371 connection_get_dbus_connection (GError **error)
373 GDBusConnection *c;
375 c = NULL;
377 /* First, ensure we have exactly one connect */
378 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
380 g_set_error (error,
381 G_IO_ERROR,
382 G_IO_ERROR_FAILED,
383 _("No connection endpoint specified"));
384 goto out;
386 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
387 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
388 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
390 g_set_error (error,
391 G_IO_ERROR,
392 G_IO_ERROR_FAILED,
393 _("Multiple connection endpoints specified"));
394 goto out;
397 if (opt_connection_system)
399 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
401 else if (opt_connection_session)
403 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
405 else if (opt_connection_address != NULL)
407 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
408 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
409 NULL, /* GDBusAuthObserver */
410 NULL, /* GCancellable */
411 error);
414 out:
415 return c;
418 /* ---------------------------------------------------------------------------------------------------- */
420 static GPtrArray *
421 call_helper_get_method_in_signature (GDBusConnection *c,
422 const gchar *dest,
423 const gchar *path,
424 const gchar *interface_name,
425 const gchar *method_name,
426 GError **error)
428 GPtrArray *ret;
429 GVariant *result;
430 GDBusNodeInfo *node_info;
431 const gchar *xml_data;
432 GDBusInterfaceInfo *interface_info;
433 GDBusMethodInfo *method_info;
434 guint n;
436 ret = NULL;
437 result = NULL;
438 node_info = NULL;
440 result = g_dbus_connection_call_sync (c,
441 dest,
442 path,
443 "org.freedesktop.DBus.Introspectable",
444 "Introspect",
445 NULL,
446 G_VARIANT_TYPE ("(s)"),
447 G_DBUS_CALL_FLAGS_NONE,
448 3000, /* 3 secs */
449 NULL,
450 error);
451 if (result == NULL)
452 goto out;
454 g_variant_get (result, "(&s)", &xml_data);
455 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
456 if (node_info == NULL)
457 goto out;
459 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
460 if (interface_info == NULL)
462 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
463 _("Warning: According to introspection data, interface `%s' does not exist\n"),
464 interface_name);
465 goto out;
468 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
469 if (method_info == NULL)
471 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
472 _("Warning: According to introspection data, method `%s' does not exist on interface `%s'\n"),
473 method_name,
474 interface_name);
475 goto out;
478 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
479 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
481 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
484 out:
485 if (node_info != NULL)
486 g_dbus_node_info_unref (node_info);
487 if (result != NULL)
488 g_variant_unref (result);
490 return ret;
493 /* ---------------------------------------------------------------------------------------------------- */
495 static GVariant *
496 _g_variant_parse_me_harder (GVariantType *type,
497 const gchar *given_str,
498 GError **error)
500 GVariant *value;
501 gchar *s;
502 guint n;
503 GString *str;
505 str = g_string_new ("\"");
506 for (n = 0; given_str[n] != '\0'; n++)
508 if (G_UNLIKELY (given_str[n] == '\"'))
509 g_string_append (str, "\\\"");
510 else
511 g_string_append_c (str, given_str[n]);
513 g_string_append_c (str, '"');
514 s = g_string_free (str, FALSE);
516 value = g_variant_parse (type,
518 NULL,
519 NULL,
520 error);
521 g_free (s);
523 return value;
526 /* ---------------------------------------------------------------------------------------------------- */
528 static gchar *opt_emit_dest = NULL;
529 static gchar *opt_emit_object_path = NULL;
530 static gchar *opt_emit_signal = NULL;
532 static const GOptionEntry emit_entries[] =
534 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
535 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
536 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
537 { NULL }
540 static gboolean
541 handle_emit (gint *argc,
542 gchar **argv[],
543 gboolean request_completion,
544 const gchar *completion_cur,
545 const gchar *completion_prev)
547 gint ret;
548 GOptionContext *o;
549 gchar *s;
550 GError *error;
551 GDBusConnection *c;
552 GVariant *parameters;
553 gchar *interface_name;
554 gchar *signal_name;
555 GVariantBuilder builder;
556 guint n;
558 ret = FALSE;
559 c = NULL;
560 parameters = NULL;
561 interface_name = NULL;
562 signal_name = NULL;
564 modify_argv0_for_command (argc, argv, "emit");
566 o = g_option_context_new (NULL);
567 g_option_context_set_help_enabled (o, FALSE);
568 g_option_context_set_summary (o, _("Emit a signal."));
569 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
570 g_option_context_add_group (o, connection_get_group ());
572 if (!g_option_context_parse (o, argc, argv, NULL))
574 if (!request_completion)
576 s = g_option_context_get_help (o, FALSE, NULL);
577 g_printerr ("%s", s);
578 g_free (s);
579 goto out;
583 error = NULL;
584 c = connection_get_dbus_connection (&error);
585 if (c == NULL)
587 if (request_completion)
589 if (g_strcmp0 (completion_prev, "--address") == 0)
591 g_print ("unix:\n"
592 "tcp:\n"
593 "nonce-tcp:\n");
595 else
597 g_print ("--system \n--session \n--address \n");
600 else
602 g_printerr (_("Error connecting: %s\n"), error->message);
603 g_error_free (error);
605 goto out;
608 /* All done with completion now */
609 if (request_completion)
610 goto out;
612 if (opt_emit_object_path == NULL)
614 g_printerr (_("Error: object path not specified.\n"));
615 goto out;
617 if (!g_variant_is_object_path (opt_emit_object_path))
619 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
620 goto out;
623 if (opt_emit_signal == NULL)
625 g_printerr (_("Error: signal not specified.\n"));
626 goto out;
629 s = strrchr (opt_emit_signal, '.');
630 if (s == NULL)
632 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
633 goto out;
635 signal_name = g_strdup (s + 1);
636 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
638 if (!g_dbus_is_interface_name (interface_name))
640 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
641 goto out;
644 if (!g_dbus_is_member_name (signal_name))
646 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
647 goto out;
650 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
652 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
653 goto out;
656 /* Read parameters */
657 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
658 for (n = 1; n < (guint) *argc; n++)
660 GVariant *value;
662 error = NULL;
663 value = g_variant_parse (NULL,
664 (*argv)[n],
665 NULL,
666 NULL,
667 &error);
668 if (value == NULL)
670 g_error_free (error);
671 error = NULL;
672 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
673 if (value == NULL)
675 g_printerr (_("Error parsing parameter %d: %s\n"),
677 error->message);
678 g_error_free (error);
679 g_variant_builder_clear (&builder);
680 goto out;
683 g_variant_builder_add_value (&builder, value);
685 parameters = g_variant_builder_end (&builder);
687 if (parameters != NULL)
688 parameters = g_variant_ref_sink (parameters);
689 if (!g_dbus_connection_emit_signal (c,
690 opt_emit_dest,
691 opt_emit_object_path,
692 interface_name,
693 signal_name,
694 parameters,
695 &error))
697 g_printerr (_("Error: %s\n"), error->message);
698 g_error_free (error);
699 goto out;
702 if (!g_dbus_connection_flush_sync (c, NULL, &error))
704 g_printerr (_("Error flushing connection: %s\n"), error->message);
705 g_error_free (error);
706 goto out;
709 ret = TRUE;
711 out:
712 if (c != NULL)
713 g_object_unref (c);
714 if (parameters != NULL)
715 g_variant_unref (parameters);
716 g_free (interface_name);
717 g_free (signal_name);
718 g_option_context_free (o);
719 return ret;
722 /* ---------------------------------------------------------------------------------------------------- */
724 static gchar *opt_call_dest = NULL;
725 static gchar *opt_call_object_path = NULL;
726 static gchar *opt_call_method = NULL;
727 static gint opt_call_timeout = -1;
729 static const GOptionEntry call_entries[] =
731 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
732 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
733 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
734 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
735 { NULL }
738 static gboolean
739 handle_call (gint *argc,
740 gchar **argv[],
741 gboolean request_completion,
742 const gchar *completion_cur,
743 const gchar *completion_prev)
745 gint ret;
746 GOptionContext *o;
747 gchar *s;
748 GError *error;
749 GDBusConnection *c;
750 GVariant *parameters;
751 gchar *interface_name;
752 gchar *method_name;
753 GVariant *result;
754 GPtrArray *in_signature_types;
755 gboolean complete_names;
756 gboolean complete_paths;
757 gboolean complete_methods;
758 GVariantBuilder builder;
759 guint n;
761 ret = FALSE;
762 c = NULL;
763 parameters = NULL;
764 interface_name = NULL;
765 method_name = NULL;
766 result = NULL;
767 in_signature_types = NULL;
769 modify_argv0_for_command (argc, argv, "call");
771 o = g_option_context_new (NULL);
772 g_option_context_set_help_enabled (o, FALSE);
773 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
774 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
775 g_option_context_add_group (o, connection_get_group ());
777 complete_names = FALSE;
778 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
780 complete_names = TRUE;
781 remove_arg ((*argc) - 1, argc, argv);
784 complete_paths = FALSE;
785 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
787 complete_paths = TRUE;
788 remove_arg ((*argc) - 1, argc, argv);
791 complete_methods = FALSE;
792 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
794 complete_methods = TRUE;
795 remove_arg ((*argc) - 1, argc, argv);
798 if (!g_option_context_parse (o, argc, argv, NULL))
800 if (!request_completion)
802 s = g_option_context_get_help (o, FALSE, NULL);
803 g_printerr ("%s", s);
804 g_free (s);
805 goto out;
809 error = NULL;
810 c = connection_get_dbus_connection (&error);
811 if (c == NULL)
813 if (request_completion)
815 if (g_strcmp0 (completion_prev, "--address") == 0)
817 g_print ("unix:\n"
818 "tcp:\n"
819 "nonce-tcp:\n");
821 else
823 g_print ("--system \n--session \n--address \n");
826 else
828 g_printerr (_("Error connecting: %s\n"), error->message);
829 g_error_free (error);
831 goto out;
834 /* validate and complete destination (bus name) */
835 if (g_dbus_connection_get_unique_name (c) != NULL)
837 /* this only makes sense on message bus connections */
838 if (complete_names)
840 print_names (c, FALSE);
841 goto out;
843 if (opt_call_dest == NULL)
845 if (request_completion)
846 g_print ("--dest \n");
847 else
848 g_printerr (_("Error: Destination is not specified\n"));
849 goto out;
851 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
853 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
854 goto out;
858 /* validate and complete object path */
859 if (complete_paths)
861 print_paths (c, opt_call_dest, "/");
862 goto out;
864 if (opt_call_object_path == NULL)
866 if (request_completion)
867 g_print ("--object-path \n");
868 else
869 g_printerr (_("Error: Object path is not specified\n"));
870 goto out;
872 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
874 gchar *p;
875 s = g_strdup (opt_call_object_path);
876 p = strrchr (s, '/');
877 if (p != NULL)
879 if (p == s)
880 p++;
881 *p = '\0';
883 print_paths (c, opt_call_dest, s);
884 g_free (s);
885 goto out;
887 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
889 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
890 goto out;
893 /* validate and complete method (interface + method name) */
894 if (complete_methods)
896 print_methods (c, opt_call_dest, opt_call_object_path);
897 goto out;
899 if (opt_call_method == NULL)
901 if (request_completion)
902 g_print ("--method \n");
903 else
904 g_printerr (_("Error: Method name is not specified\n"));
905 goto out;
907 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
909 print_methods (c, opt_call_dest, opt_call_object_path);
910 goto out;
912 s = strrchr (opt_call_method, '.');
913 if (!request_completion && s == NULL)
915 g_printerr (_("Error: Method name `%s' is invalid\n"), opt_call_method);
916 goto out;
918 method_name = g_strdup (s + 1);
919 interface_name = g_strndup (opt_call_method, s - opt_call_method);
921 /* All done with completion now */
922 if (request_completion)
923 goto out;
925 /* Introspect, for easy conversion - it's not fatal if we can't do this */
926 in_signature_types = call_helper_get_method_in_signature (c,
927 opt_call_dest,
928 opt_call_object_path,
929 interface_name,
930 method_name,
931 &error);
932 if (in_signature_types == NULL)
934 //g_printerr ("Error getting introspection data: %s\n", error->message);
935 g_error_free (error);
936 error = NULL;
939 /* Read parameters */
940 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
941 for (n = 1; n < (guint) *argc; n++)
943 GVariant *value;
944 GVariantType *type;
946 type = NULL;
947 if (in_signature_types != NULL)
949 if (n - 1 >= in_signature_types->len)
951 /* Only warn for the first param */
952 if (n - 1 == in_signature_types->len)
954 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
955 in_signature_types->len);
958 else
960 type = in_signature_types->pdata[n - 1];
964 error = NULL;
965 value = g_variant_parse (type,
966 (*argv)[n],
967 NULL,
968 NULL,
969 &error);
970 if (value == NULL)
972 g_error_free (error);
973 error = NULL;
974 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
975 if (value == NULL)
977 if (type != NULL)
979 s = g_variant_type_dup_string (type);
980 g_printerr (_("Error parsing parameter %d of type `%s': %s\n"),
983 error->message);
984 g_free (s);
986 else
988 g_printerr (_("Error parsing parameter %d: %s\n"),
990 error->message);
992 g_error_free (error);
993 g_variant_builder_clear (&builder);
994 goto out;
997 g_variant_builder_add_value (&builder, value);
999 parameters = g_variant_builder_end (&builder);
1001 if (parameters != NULL)
1002 parameters = g_variant_ref_sink (parameters);
1003 result = g_dbus_connection_call_sync (c,
1004 opt_call_dest,
1005 opt_call_object_path,
1006 interface_name,
1007 method_name,
1008 parameters,
1009 NULL,
1010 G_DBUS_CALL_FLAGS_NONE,
1011 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1012 NULL,
1013 &error);
1014 if (result == NULL)
1016 g_printerr (_("Error: %s\n"), error->message);
1017 g_error_free (error);
1018 if (in_signature_types != NULL)
1020 GString *s;
1021 s = g_string_new (NULL);
1022 for (n = 0; n < in_signature_types->len; n++)
1024 GVariantType *type = in_signature_types->pdata[n];
1025 g_string_append_len (s,
1026 g_variant_type_peek_string (type),
1027 g_variant_type_get_string_length (type));
1029 g_printerr ("(According to introspection data, you need to pass `%s')\n", s->str);
1030 g_string_free (s, TRUE);
1032 goto out;
1035 s = g_variant_print (result, TRUE);
1036 g_print ("%s\n", s);
1037 g_free (s);
1039 ret = TRUE;
1041 out:
1042 if (in_signature_types != NULL)
1043 g_ptr_array_unref (in_signature_types);
1044 if (result != NULL)
1045 g_variant_unref (result);
1046 if (c != NULL)
1047 g_object_unref (c);
1048 if (parameters != NULL)
1049 g_variant_unref (parameters);
1050 g_free (interface_name);
1051 g_free (method_name);
1052 g_option_context_free (o);
1053 return ret;
1056 /* ---------------------------------------------------------------------------------------------------- */
1058 static gchar *opt_introspect_dest = NULL;
1059 static gchar *opt_introspect_object_path = NULL;
1060 static gboolean opt_introspect_xml = FALSE;
1061 static gboolean opt_introspect_recurse = FALSE;
1062 static gboolean opt_introspect_only_properties = FALSE;
1064 static void
1065 dump_annotation (const GDBusAnnotationInfo *o,
1066 guint indent,
1067 gboolean ignore_indent)
1069 guint n;
1070 g_print ("%*s@%s(\"%s\")\n",
1071 ignore_indent ? 0 : indent, "",
1072 o->key,
1073 o->value);
1074 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1075 dump_annotation (o->annotations[n], indent + 2, FALSE);
1078 static void
1079 dump_arg (const GDBusArgInfo *o,
1080 guint indent,
1081 const gchar *direction,
1082 gboolean ignore_indent,
1083 gboolean include_newline)
1085 guint n;
1087 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1089 dump_annotation (o->annotations[n], indent, ignore_indent);
1090 ignore_indent = FALSE;
1093 g_print ("%*s%s%s %s%s",
1094 ignore_indent ? 0 : indent, "",
1095 direction,
1096 o->signature,
1097 o->name,
1098 include_newline ? ",\n" : "");
1101 static guint
1102 count_args (GDBusArgInfo **args)
1104 guint n;
1105 n = 0;
1106 if (args == NULL)
1107 goto out;
1108 while (args[n] != NULL)
1109 n++;
1110 out:
1111 return n;
1114 static void
1115 dump_method (const GDBusMethodInfo *o,
1116 guint indent)
1118 guint n;
1119 guint m;
1120 guint name_len;
1121 guint total_num_args;
1123 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1124 dump_annotation (o->annotations[n], indent, FALSE);
1126 g_print ("%*s%s(", indent, "", o->name);
1127 name_len = strlen (o->name);
1128 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1129 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1131 gboolean ignore_indent = (m == 0);
1132 gboolean include_newline = (m != total_num_args - 1);
1134 dump_arg (o->in_args[n],
1135 indent + name_len + 1,
1136 "in ",
1137 ignore_indent,
1138 include_newline);
1140 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1142 gboolean ignore_indent = (m == 0);
1143 gboolean include_newline = (m != total_num_args - 1);
1144 dump_arg (o->out_args[n],
1145 indent + name_len + 1,
1146 "out ",
1147 ignore_indent,
1148 include_newline);
1150 g_print (");\n");
1153 static void
1154 dump_signal (const GDBusSignalInfo *o,
1155 guint indent)
1157 guint n;
1158 guint name_len;
1159 guint total_num_args;
1161 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1162 dump_annotation (o->annotations[n], indent, FALSE);
1164 g_print ("%*s%s(", indent, "", o->name);
1165 name_len = strlen (o->name);
1166 total_num_args = count_args (o->args);
1167 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1169 gboolean ignore_indent = (n == 0);
1170 gboolean include_newline = (n != total_num_args - 1);
1171 dump_arg (o->args[n],
1172 indent + name_len + 1,
1174 ignore_indent,
1175 include_newline);
1177 g_print (");\n");
1180 static void
1181 dump_property (const GDBusPropertyInfo *o,
1182 guint indent,
1183 GVariant *value)
1185 const gchar *access;
1186 guint n;
1188 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1189 access = "readonly";
1190 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1191 access = "writeonly";
1192 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1193 access = "readwrite";
1194 else
1195 g_assert_not_reached ();
1197 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1198 dump_annotation (o->annotations[n], indent, FALSE);
1200 if (value != NULL)
1202 gchar *s = g_variant_print (value, FALSE);
1203 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1204 g_free (s);
1206 else
1208 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1212 static void
1213 dump_interface (GDBusConnection *c,
1214 const gchar *name,
1215 const GDBusInterfaceInfo *o,
1216 guint indent,
1217 const gchar *object_path)
1219 guint n;
1220 GHashTable *properties;
1222 properties = g_hash_table_new_full (g_str_hash,
1223 g_str_equal,
1224 g_free,
1225 (GDestroyNotify) g_variant_unref);
1227 /* Try to get properties */
1228 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1230 GVariant *result;
1231 result = g_dbus_connection_call_sync (c,
1232 name,
1233 object_path,
1234 "org.freedesktop.DBus.Properties",
1235 "GetAll",
1236 g_variant_new ("(s)", o->name),
1237 NULL,
1238 G_DBUS_CALL_FLAGS_NONE,
1239 3000,
1240 NULL,
1241 NULL);
1242 if (result != NULL)
1244 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1246 GVariantIter *iter;
1247 GVariant *item;
1248 g_variant_get (result,
1249 "(a{sv})",
1250 &iter);
1251 while ((item = g_variant_iter_next_value (iter)))
1253 gchar *key;
1254 GVariant *value;
1255 g_variant_get (item,
1256 "{sv}",
1257 &key,
1258 &value);
1260 g_hash_table_insert (properties, key, g_variant_ref (value));
1263 g_variant_unref (result);
1265 else
1267 guint n;
1268 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1270 result = g_dbus_connection_call_sync (c,
1271 name,
1272 object_path,
1273 "org.freedesktop.DBus.Properties",
1274 "Get",
1275 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1276 G_VARIANT_TYPE ("(v)"),
1277 G_DBUS_CALL_FLAGS_NONE,
1278 3000,
1279 NULL,
1280 NULL);
1281 if (result != NULL)
1283 GVariant *property_value;
1284 g_variant_get (result,
1285 "(v)",
1286 &property_value);
1287 g_hash_table_insert (properties,
1288 g_strdup (o->properties[n]->name),
1289 g_variant_ref (property_value));
1290 g_variant_unref (result);
1296 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1297 dump_annotation (o->annotations[n], indent, FALSE);
1299 g_print ("%*sinterface %s {\n", indent, "", o->name);
1300 if (o->methods != NULL && !opt_introspect_only_properties)
1302 g_print ("%*s methods:\n", indent, "");
1303 for (n = 0; o->methods[n] != NULL; n++)
1304 dump_method (o->methods[n], indent + 4);
1306 if (o->signals != NULL && !opt_introspect_only_properties)
1308 g_print ("%*s signals:\n", indent, "");
1309 for (n = 0; o->signals[n] != NULL; n++)
1310 dump_signal (o->signals[n], indent + 4);
1312 if (o->properties != NULL)
1314 g_print ("%*s properties:\n", indent, "");
1315 for (n = 0; o->properties[n] != NULL; n++)
1317 dump_property (o->properties[n],
1318 indent + 4,
1319 g_hash_table_lookup (properties, (o->properties[n])->name));
1322 g_print ("%*s};\n",
1323 indent, "");
1325 g_hash_table_unref (properties);
1328 static gboolean
1329 introspect_do (GDBusConnection *c,
1330 const gchar *object_path,
1331 guint indent);
1333 static void
1334 dump_node (GDBusConnection *c,
1335 const gchar *name,
1336 const GDBusNodeInfo *o,
1337 guint indent,
1338 const gchar *object_path,
1339 gboolean recurse)
1341 guint n;
1342 const gchar *object_path_to_print;
1344 object_path_to_print = object_path;
1345 if (o->path != NULL)
1346 object_path_to_print = o->path;
1348 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1349 dump_annotation (o->annotations[n], indent, FALSE);
1351 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1352 if (o->interfaces != NULL || o->nodes != NULL)
1354 g_print (" {\n");
1355 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1357 if (opt_introspect_only_properties)
1359 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1360 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1362 else
1364 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1367 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1369 if (recurse)
1371 gchar *child_path;
1372 if (g_variant_is_object_path (o->nodes[n]->path))
1374 child_path = g_strdup (o->nodes[n]->path);
1375 /* avoid infinite loops */
1376 if (g_str_has_prefix (child_path, object_path))
1378 introspect_do (c, child_path, indent + 2);
1380 else
1382 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1383 child_path, object_path);
1386 else
1388 if (g_strcmp0 (object_path, "/") == 0)
1389 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1390 else
1391 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1392 introspect_do (c, child_path, indent + 2);
1394 g_free (child_path);
1396 else
1398 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1401 g_print ("%*s};\n",
1402 indent, "");
1404 else
1406 g_print ("\n");
1410 static const GOptionEntry introspect_entries[] =
1412 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1413 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1414 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1415 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1416 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1417 { NULL }
1420 static gboolean
1421 introspect_do (GDBusConnection *c,
1422 const gchar *object_path,
1423 guint indent)
1425 GError *error;
1426 GVariant *result;
1427 GDBusNodeInfo *node;
1428 gboolean ret;
1429 const gchar *xml_data;
1431 ret = FALSE;
1432 node = NULL;
1433 result = NULL;
1435 error = NULL;
1436 result = g_dbus_connection_call_sync (c,
1437 opt_introspect_dest,
1438 object_path,
1439 "org.freedesktop.DBus.Introspectable",
1440 "Introspect",
1441 NULL,
1442 G_VARIANT_TYPE ("(s)"),
1443 G_DBUS_CALL_FLAGS_NONE,
1444 3000, /* 3 sec */
1445 NULL,
1446 &error);
1447 if (result == NULL)
1449 g_printerr (_("Error: %s\n"), error->message);
1450 g_error_free (error);
1451 goto out;
1453 g_variant_get (result, "(&s)", &xml_data);
1455 if (opt_introspect_xml)
1457 g_print ("%s", xml_data);
1459 else
1461 error = NULL;
1462 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1463 if (node == NULL)
1465 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1466 g_error_free (error);
1467 goto out;
1470 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1473 ret = TRUE;
1475 out:
1476 if (node != NULL)
1477 g_dbus_node_info_unref (node);
1478 if (result != NULL)
1479 g_variant_unref (result);
1480 return ret;
1483 static gboolean
1484 handle_introspect (gint *argc,
1485 gchar **argv[],
1486 gboolean request_completion,
1487 const gchar *completion_cur,
1488 const gchar *completion_prev)
1490 gint ret;
1491 GOptionContext *o;
1492 gchar *s;
1493 GError *error;
1494 GDBusConnection *c;
1495 gboolean complete_names;
1496 gboolean complete_paths;
1498 ret = FALSE;
1499 c = NULL;
1501 modify_argv0_for_command (argc, argv, "introspect");
1503 o = g_option_context_new (NULL);
1504 if (request_completion)
1505 g_option_context_set_ignore_unknown_options (o, TRUE);
1506 g_option_context_set_help_enabled (o, FALSE);
1507 g_option_context_set_summary (o, _("Introspect a remote object."));
1508 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1509 g_option_context_add_group (o, connection_get_group ());
1511 complete_names = FALSE;
1512 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1514 complete_names = TRUE;
1515 remove_arg ((*argc) - 1, argc, argv);
1518 complete_paths = FALSE;
1519 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1521 complete_paths = TRUE;
1522 remove_arg ((*argc) - 1, argc, argv);
1525 if (!g_option_context_parse (o, argc, argv, NULL))
1527 if (!request_completion)
1529 s = g_option_context_get_help (o, FALSE, NULL);
1530 g_printerr ("%s", s);
1531 g_free (s);
1532 goto out;
1536 error = NULL;
1537 c = connection_get_dbus_connection (&error);
1538 if (c == NULL)
1540 if (request_completion)
1542 if (g_strcmp0 (completion_prev, "--address") == 0)
1544 g_print ("unix:\n"
1545 "tcp:\n"
1546 "nonce-tcp:\n");
1548 else
1550 g_print ("--system \n--session \n--address \n");
1553 else
1555 g_printerr (_("Error connecting: %s\n"), error->message);
1556 g_error_free (error);
1558 goto out;
1561 if (g_dbus_connection_get_unique_name (c) != NULL)
1563 if (complete_names)
1565 print_names (c, FALSE);
1566 goto out;
1568 /* this only makes sense on message bus connections */
1569 if (opt_introspect_dest == NULL)
1571 if (request_completion)
1572 g_print ("--dest \n");
1573 else
1574 g_printerr (_("Error: Destination is not specified\n"));
1575 goto out;
1577 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1579 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1580 goto out;
1583 if (complete_paths)
1585 print_paths (c, opt_introspect_dest, "/");
1586 goto out;
1588 if (opt_introspect_object_path == NULL)
1590 if (request_completion)
1591 g_print ("--object-path \n");
1592 else
1593 g_printerr (_("Error: Object path is not specified\n"));
1594 goto out;
1596 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1598 gchar *p;
1599 s = g_strdup (opt_introspect_object_path);
1600 p = strrchr (s, '/');
1601 if (p != NULL)
1603 if (p == s)
1604 p++;
1605 *p = '\0';
1607 print_paths (c, opt_introspect_dest, s);
1608 g_free (s);
1609 goto out;
1611 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1613 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1614 goto out;
1617 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1619 g_print ("--recurse \n");
1622 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1624 g_print ("--only-properties \n");
1627 /* All done with completion now */
1628 if (request_completion)
1629 goto out;
1631 if (!introspect_do (c, opt_introspect_object_path, 0))
1632 goto out;
1634 ret = TRUE;
1636 out:
1637 if (c != NULL)
1638 g_object_unref (c);
1639 g_option_context_free (o);
1640 return ret;
1643 /* ---------------------------------------------------------------------------------------------------- */
1645 static gchar *opt_monitor_dest = NULL;
1646 static gchar *opt_monitor_object_path = NULL;
1648 static guint monitor_filter_id = 0;
1650 static void
1651 monitor_signal_cb (GDBusConnection *connection,
1652 const gchar *sender_name,
1653 const gchar *object_path,
1654 const gchar *interface_name,
1655 const gchar *signal_name,
1656 GVariant *parameters,
1657 gpointer user_data)
1659 gchar *s;
1660 s = g_variant_print (parameters, TRUE);
1661 g_print ("%s: %s.%s %s\n",
1662 object_path,
1663 interface_name,
1664 signal_name,
1666 g_free (s);
1669 static void
1670 monitor_on_name_appeared (GDBusConnection *connection,
1671 const gchar *name,
1672 const gchar *name_owner,
1673 gpointer user_data)
1675 g_print ("The name %s is owned by %s\n", name, name_owner);
1676 g_assert (monitor_filter_id == 0);
1677 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1678 name_owner,
1679 NULL, /* any interface */
1680 NULL, /* any member */
1681 opt_monitor_object_path,
1682 NULL, /* arg0 */
1683 G_DBUS_SIGNAL_FLAGS_NONE,
1684 monitor_signal_cb,
1685 NULL, /* user_data */
1686 NULL); /* user_data destroy notify */
1689 static void
1690 monitor_on_name_vanished (GDBusConnection *connection,
1691 const gchar *name,
1692 gpointer user_data)
1694 g_print ("The name %s does not have an owner\n", name);
1696 if (monitor_filter_id != 0)
1698 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1699 monitor_filter_id = 0;
1703 static const GOptionEntry monitor_entries[] =
1705 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1706 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1707 { NULL }
1710 static gboolean
1711 handle_monitor (gint *argc,
1712 gchar **argv[],
1713 gboolean request_completion,
1714 const gchar *completion_cur,
1715 const gchar *completion_prev)
1717 gint ret;
1718 GOptionContext *o;
1719 gchar *s;
1720 GError *error;
1721 GDBusConnection *c;
1722 GVariant *result;
1723 GDBusNodeInfo *node;
1724 gboolean complete_names;
1725 gboolean complete_paths;
1726 GMainLoop *loop;
1728 ret = FALSE;
1729 c = NULL;
1730 node = NULL;
1731 result = NULL;
1733 modify_argv0_for_command (argc, argv, "monitor");
1735 o = g_option_context_new (NULL);
1736 if (request_completion)
1737 g_option_context_set_ignore_unknown_options (o, TRUE);
1738 g_option_context_set_help_enabled (o, FALSE);
1739 g_option_context_set_summary (o, _("Monitor a remote object."));
1740 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1741 g_option_context_add_group (o, connection_get_group ());
1743 complete_names = FALSE;
1744 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1746 complete_names = TRUE;
1747 remove_arg ((*argc) - 1, argc, argv);
1750 complete_paths = FALSE;
1751 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1753 complete_paths = TRUE;
1754 remove_arg ((*argc) - 1, argc, argv);
1757 if (!g_option_context_parse (o, argc, argv, NULL))
1759 if (!request_completion)
1761 s = g_option_context_get_help (o, FALSE, NULL);
1762 g_printerr ("%s", s);
1763 g_free (s);
1764 goto out;
1768 error = NULL;
1769 c = connection_get_dbus_connection (&error);
1770 if (c == NULL)
1772 if (request_completion)
1774 if (g_strcmp0 (completion_prev, "--address") == 0)
1776 g_print ("unix:\n"
1777 "tcp:\n"
1778 "nonce-tcp:\n");
1780 else
1782 g_print ("--system \n--session \n--address \n");
1785 else
1787 g_printerr (_("Error connecting: %s\n"), error->message);
1788 g_error_free (error);
1790 goto out;
1793 if (g_dbus_connection_get_unique_name (c) != NULL)
1795 if (complete_names)
1797 print_names (c, FALSE);
1798 goto out;
1800 /* this only makes sense on message bus connections */
1801 if (opt_monitor_dest == NULL)
1803 if (request_completion)
1804 g_print ("--dest \n");
1805 else
1806 g_printerr (_("Error: Destination is not specified\n"));
1807 goto out;
1809 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1811 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1812 goto out;
1815 if (complete_paths)
1817 print_paths (c, opt_monitor_dest, "/");
1818 goto out;
1820 if (opt_monitor_object_path == NULL)
1822 if (request_completion)
1824 g_print ("--object-path \n");
1825 goto out;
1827 /* it's fine to not have an object path */
1829 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1831 gchar *p;
1832 s = g_strdup (opt_monitor_object_path);
1833 p = strrchr (s, '/');
1834 if (p != NULL)
1836 if (p == s)
1837 p++;
1838 *p = '\0';
1840 print_paths (c, opt_monitor_dest, s);
1841 g_free (s);
1842 goto out;
1844 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1846 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1847 goto out;
1850 /* All done with completion now */
1851 if (request_completion)
1852 goto out;
1854 if (opt_monitor_object_path != NULL)
1855 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1856 else
1857 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1859 loop = g_main_loop_new (NULL, FALSE);
1860 g_bus_watch_name_on_connection (c,
1861 opt_monitor_dest,
1862 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1863 monitor_on_name_appeared,
1864 monitor_on_name_vanished,
1865 NULL,
1866 NULL);
1868 g_main_loop_run (loop);
1869 g_main_loop_unref (loop);
1871 ret = TRUE;
1873 out:
1874 if (node != NULL)
1875 g_dbus_node_info_unref (node);
1876 if (result != NULL)
1877 g_variant_unref (result);
1878 if (c != NULL)
1879 g_object_unref (c);
1880 g_option_context_free (o);
1881 return ret;
1884 /* ---------------------------------------------------------------------------------------------------- */
1886 static gchar *
1887 pick_word_at (const gchar *s,
1888 gint cursor,
1889 gint *out_word_begins_at)
1891 gint begin;
1892 gint end;
1894 if (s[0] == '\0')
1896 if (out_word_begins_at != NULL)
1897 *out_word_begins_at = -1;
1898 return NULL;
1901 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1903 if (out_word_begins_at != NULL)
1904 *out_word_begins_at = cursor;
1905 return g_strdup ("");
1908 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1909 cursor--;
1910 begin = cursor;
1912 end = begin;
1913 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1914 end++;
1916 if (out_word_begins_at != NULL)
1917 *out_word_begins_at = begin;
1919 return g_strndup (s + begin, end - begin);
1922 gint
1923 main (gint argc, gchar *argv[])
1925 gint ret;
1926 const gchar *command;
1927 gboolean request_completion;
1928 gchar *completion_cur;
1929 gchar *completion_prev;
1931 setlocale (LC_ALL, "");
1932 textdomain (GETTEXT_PACKAGE);
1934 #ifdef G_OS_WIN32
1935 extern gchar *_glib_get_locale_dir (void);
1936 gchar *tmp = _glib_get_locale_dir ();
1937 bindtextdomain (GETTEXT_PACKAGE, tmp);
1938 g_free (tmp);
1939 #else
1940 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1941 #endif
1943 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1944 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1945 #endif
1947 ret = 1;
1948 completion_cur = NULL;
1949 completion_prev = NULL;
1951 g_type_init ();
1953 if (argc < 2)
1955 usage (&argc, &argv, FALSE);
1956 goto out;
1959 request_completion = FALSE;
1961 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1963 again:
1964 command = argv[1];
1965 if (g_strcmp0 (command, "help") == 0)
1967 if (request_completion)
1969 /* do nothing */
1971 else
1973 usage (&argc, &argv, TRUE);
1974 ret = 0;
1976 goto out;
1978 else if (g_strcmp0 (command, "emit") == 0)
1980 if (handle_emit (&argc,
1981 &argv,
1982 request_completion,
1983 completion_cur,
1984 completion_prev))
1985 ret = 0;
1986 goto out;
1988 else if (g_strcmp0 (command, "call") == 0)
1990 if (handle_call (&argc,
1991 &argv,
1992 request_completion,
1993 completion_cur,
1994 completion_prev))
1995 ret = 0;
1996 goto out;
1998 else if (g_strcmp0 (command, "introspect") == 0)
2000 if (handle_introspect (&argc,
2001 &argv,
2002 request_completion,
2003 completion_cur,
2004 completion_prev))
2005 ret = 0;
2006 goto out;
2008 else if (g_strcmp0 (command, "monitor") == 0)
2010 if (handle_monitor (&argc,
2011 &argv,
2012 request_completion,
2013 completion_cur,
2014 completion_prev))
2015 ret = 0;
2016 goto out;
2018 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2020 const gchar *completion_line;
2021 gchar **completion_argv;
2022 gint completion_argc;
2023 gint completion_point;
2024 gchar *endp;
2025 gint cur_begin;
2027 request_completion = TRUE;
2029 completion_line = argv[2];
2030 completion_point = strtol (argv[3], &endp, 10);
2031 if (endp == argv[3] || *endp != '\0')
2032 goto out;
2034 #if 0
2035 completion_debug ("completion_point=%d", completion_point);
2036 completion_debug ("----");
2037 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2038 completion_debug ("`%s'", completion_line);
2039 completion_debug (" %*s^",
2040 completion_point, "");
2041 completion_debug ("----");
2042 #endif
2044 if (!g_shell_parse_argv (completion_line,
2045 &completion_argc,
2046 &completion_argv,
2047 NULL))
2049 /* it's very possible the command line can't be parsed (for
2050 * example, missing quotes etc) - in that case, we just
2051 * don't autocomplete at all
2053 goto out;
2056 /* compute cur and prev */
2057 completion_prev = NULL;
2058 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2059 if (cur_begin > 0)
2061 gint prev_end;
2062 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2064 if (!g_ascii_isspace (completion_line[prev_end]))
2066 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2067 break;
2071 #if 0
2072 completion_debug (" cur=`%s'", completion_cur);
2073 completion_debug ("prev=`%s'", completion_prev);
2074 #endif
2076 argc = completion_argc;
2077 argv = completion_argv;
2079 ret = 0;
2081 goto again;
2083 else
2085 if (request_completion)
2087 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2088 ret = 0;
2089 goto out;
2091 else
2093 g_printerr ("Unknown command `%s'\n", command);
2094 usage (&argc, &argv, FALSE);
2095 goto out;
2099 out:
2100 g_free (completion_cur);
2101 g_free (completion_prev);
2102 return ret;