GSettings: properly support 'extends'
[glib.git] / gio / gdbus-tool.c
blob2714dd7758cdf759e12e8a4bc6327ff53584ea73
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 #ifdef G_OS_WIN32
35 #include "glib/glib-private.h"
36 #endif
38 /* ---------------------------------------------------------------------------------------------------- */
40 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
42 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
43 * to not have it interfere with stdout/stderr)
45 #if 0
46 G_GNUC_UNUSED static void
47 completion_debug (const gchar *format, ...)
49 va_list var_args;
50 gchar *s;
51 static FILE *f = NULL;
53 va_start (var_args, format);
54 s = g_strdup_vprintf (format, var_args);
55 if (f == NULL)
57 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
59 fprintf (f, "%s\n", s);
60 g_free (s);
62 #else
63 static void
64 completion_debug (const gchar *format, ...)
67 #endif
69 /* ---------------------------------------------------------------------------------------------------- */
72 static void
73 remove_arg (gint num, gint *argc, gchar **argv[])
75 gint n;
77 g_assert (num <= (*argc));
79 for (n = num; (*argv)[n] != NULL; n++)
80 (*argv)[n] = (*argv)[n+1];
81 (*argv)[n] = NULL;
82 (*argc) = (*argc) - 1;
85 static void
86 usage (gint *argc, gchar **argv[], gboolean use_stdout)
88 GOptionContext *o;
89 gchar *s;
90 gchar *program_name;
92 o = g_option_context_new (_("COMMAND"));
93 g_option_context_set_help_enabled (o, FALSE);
94 /* Ignore parsing result */
95 g_option_context_parse (o, argc, argv, NULL);
96 program_name = g_path_get_basename ((*argv)[0]);
97 s = g_strdup_printf (_("Commands:\n"
98 " help Shows this information\n"
99 " introspect Introspect a remote object\n"
100 " monitor Monitor a remote object\n"
101 " call Invoke a method on a remote object\n"
102 " emit Emit a signal\n"
103 "\n"
104 "Use \"%s COMMAND --help\" to get help on each command.\n"),
105 program_name);
106 g_free (program_name);
107 g_option_context_set_description (o, s);
108 g_free (s);
109 s = g_option_context_get_help (o, FALSE, NULL);
110 if (use_stdout)
111 g_print ("%s", s);
112 else
113 g_printerr ("%s", s);
114 g_free (s);
115 g_option_context_free (o);
118 static void
119 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
121 gchar *s;
122 gchar *program_name;
124 /* TODO:
125 * 1. get a g_set_prgname() ?; or
126 * 2. save old argv[0] and restore later
129 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
130 remove_arg (1, argc, argv);
132 program_name = g_path_get_basename ((*argv)[0]);
133 s = g_strdup_printf ("%s %s", (*argv)[0], command);
134 (*argv)[0] = s;
135 g_free (program_name);
138 /* ---------------------------------------------------------------------------------------------------- */
140 static void
141 print_methods (GDBusConnection *c,
142 const gchar *name,
143 const gchar *path)
145 GVariant *result;
146 GError *error;
147 const gchar *xml_data;
148 GDBusNodeInfo *node;
149 guint n;
150 guint m;
152 error = NULL;
153 result = g_dbus_connection_call_sync (c,
154 name,
155 path,
156 "org.freedesktop.DBus.Introspectable",
157 "Introspect",
158 NULL,
159 G_VARIANT_TYPE ("(s)"),
160 G_DBUS_CALL_FLAGS_NONE,
161 3000, /* 3 secs */
162 NULL,
163 &error);
164 if (result == NULL)
166 g_printerr (_("Error: %s\n"), error->message);
167 g_error_free (error);
168 goto out;
170 g_variant_get (result, "(&s)", &xml_data);
172 error = NULL;
173 node = g_dbus_node_info_new_for_xml (xml_data, &error);
174 g_variant_unref (result);
175 if (node == NULL)
177 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
178 g_error_free (error);
179 goto out;
182 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
184 const GDBusInterfaceInfo *iface = node->interfaces[n];
185 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
187 const GDBusMethodInfo *method = iface->methods[m];
188 g_print ("%s.%s \n", iface->name, method->name);
191 g_dbus_node_info_unref (node);
193 out:
197 static void
198 print_paths (GDBusConnection *c,
199 const gchar *name,
200 const gchar *path)
202 GVariant *result;
203 GError *error;
204 const gchar *xml_data;
205 GDBusNodeInfo *node;
206 guint n;
208 error = NULL;
209 result = g_dbus_connection_call_sync (c,
210 name,
211 path,
212 "org.freedesktop.DBus.Introspectable",
213 "Introspect",
214 NULL,
215 G_VARIANT_TYPE ("(s)"),
216 G_DBUS_CALL_FLAGS_NONE,
217 3000, /* 3 secs */
218 NULL,
219 &error);
220 if (result == NULL)
222 g_printerr (_("Error: %s\n"), error->message);
223 g_error_free (error);
224 goto out;
226 g_variant_get (result, "(&s)", &xml_data);
228 //g_printerr ("xml='%s'", xml_data);
230 error = NULL;
231 node = g_dbus_node_info_new_for_xml (xml_data, &error);
232 g_variant_unref (result);
233 if (node == NULL)
235 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
236 g_error_free (error);
237 goto out;
240 //g_printerr ("bar '%s'\n", path);
242 if (node->interfaces != NULL)
243 g_print ("%s \n", path);
245 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
247 gchar *s;
249 //g_printerr ("foo '%s'\n", node->nodes[n].path);
251 if (g_strcmp0 (path, "/") == 0)
252 s = g_strdup_printf ("/%s", node->nodes[n]->path);
253 else
254 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
256 print_paths (c, name, s);
258 g_free (s);
260 g_dbus_node_info_unref (node);
262 out:
266 static void
267 print_names (GDBusConnection *c,
268 gboolean include_unique_names)
270 GVariant *result;
271 GError *error;
272 GVariantIter *iter;
273 gchar *str;
274 GHashTable *name_set;
275 GList *keys;
276 GList *l;
278 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
280 error = NULL;
281 result = g_dbus_connection_call_sync (c,
282 "org.freedesktop.DBus",
283 "/org/freedesktop/DBus",
284 "org.freedesktop.DBus",
285 "ListNames",
286 NULL,
287 G_VARIANT_TYPE ("(as)"),
288 G_DBUS_CALL_FLAGS_NONE,
289 3000, /* 3 secs */
290 NULL,
291 &error);
292 if (result == NULL)
294 g_printerr (_("Error: %s\n"), error->message);
295 g_error_free (error);
296 goto out;
298 g_variant_get (result, "(as)", &iter);
299 while (g_variant_iter_loop (iter, "s", &str))
300 g_hash_table_insert (name_set, g_strdup (str), NULL);
301 g_variant_iter_free (iter);
302 g_variant_unref (result);
304 error = NULL;
305 result = g_dbus_connection_call_sync (c,
306 "org.freedesktop.DBus",
307 "/org/freedesktop/DBus",
308 "org.freedesktop.DBus",
309 "ListActivatableNames",
310 NULL,
311 G_VARIANT_TYPE ("(as)"),
312 G_DBUS_CALL_FLAGS_NONE,
313 3000, /* 3 secs */
314 NULL,
315 &error);
316 if (result == NULL)
318 g_printerr (_("Error: %s\n"), error->message);
319 g_error_free (error);
320 goto out;
322 g_variant_get (result, "(as)", &iter);
323 while (g_variant_iter_loop (iter, "s", &str))
324 g_hash_table_insert (name_set, g_strdup (str), NULL);
325 g_variant_iter_free (iter);
326 g_variant_unref (result);
328 keys = g_hash_table_get_keys (name_set);
329 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
330 for (l = keys; l != NULL; l = l->next)
332 const gchar *name = l->data;
333 if (!include_unique_names && g_str_has_prefix (name, ":"))
334 continue;
336 g_print ("%s \n", name);
338 g_list_free (keys);
340 out:
341 g_hash_table_unref (name_set);
344 /* ---------------------------------------------------------------------------------------------------- */
346 static gboolean opt_connection_system = FALSE;
347 static gboolean opt_connection_session = FALSE;
348 static gchar *opt_connection_address = NULL;
350 static const GOptionEntry connection_entries[] =
352 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
353 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
354 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
355 { NULL }
358 static GOptionGroup *
359 connection_get_group (void)
361 static GOptionGroup *g;
363 g = g_option_group_new ("connection",
364 N_("Connection Endpoint Options:"),
365 N_("Options specifying the connection endpoint"),
366 NULL,
367 NULL);
368 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
369 g_option_group_add_entries (g, connection_entries);
371 return g;
374 static GDBusConnection *
375 connection_get_dbus_connection (GError **error)
377 GDBusConnection *c;
379 c = NULL;
381 /* First, ensure we have exactly one connect */
382 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
384 g_set_error (error,
385 G_IO_ERROR,
386 G_IO_ERROR_FAILED,
387 _("No connection endpoint specified"));
388 goto out;
390 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
391 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
392 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
394 g_set_error (error,
395 G_IO_ERROR,
396 G_IO_ERROR_FAILED,
397 _("Multiple connection endpoints specified"));
398 goto out;
401 if (opt_connection_system)
403 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
405 else if (opt_connection_session)
407 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
409 else if (opt_connection_address != NULL)
411 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
412 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
413 NULL, /* GDBusAuthObserver */
414 NULL, /* GCancellable */
415 error);
418 out:
419 return c;
422 /* ---------------------------------------------------------------------------------------------------- */
424 static GPtrArray *
425 call_helper_get_method_in_signature (GDBusConnection *c,
426 const gchar *dest,
427 const gchar *path,
428 const gchar *interface_name,
429 const gchar *method_name,
430 GError **error)
432 GPtrArray *ret;
433 GVariant *result;
434 GDBusNodeInfo *node_info;
435 const gchar *xml_data;
436 GDBusInterfaceInfo *interface_info;
437 GDBusMethodInfo *method_info;
438 guint n;
440 ret = NULL;
441 result = NULL;
442 node_info = NULL;
444 result = g_dbus_connection_call_sync (c,
445 dest,
446 path,
447 "org.freedesktop.DBus.Introspectable",
448 "Introspect",
449 NULL,
450 G_VARIANT_TYPE ("(s)"),
451 G_DBUS_CALL_FLAGS_NONE,
452 3000, /* 3 secs */
453 NULL,
454 error);
455 if (result == NULL)
456 goto out;
458 g_variant_get (result, "(&s)", &xml_data);
459 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
460 if (node_info == NULL)
461 goto out;
463 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
464 if (interface_info == NULL)
466 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
467 _("Warning: According to introspection data, interface '%s' does not exist\n"),
468 interface_name);
469 goto out;
472 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
473 if (method_info == NULL)
475 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
476 _("Warning: According to introspection data, method '%s' does not exist on interface '%s'\n"),
477 method_name,
478 interface_name);
479 goto out;
482 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
483 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
485 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
488 out:
489 if (node_info != NULL)
490 g_dbus_node_info_unref (node_info);
491 if (result != NULL)
492 g_variant_unref (result);
494 return ret;
497 /* ---------------------------------------------------------------------------------------------------- */
499 static GVariant *
500 _g_variant_parse_me_harder (GVariantType *type,
501 const gchar *given_str,
502 GError **error)
504 GVariant *value;
505 gchar *s;
506 guint n;
507 GString *str;
509 str = g_string_new ("\"");
510 for (n = 0; given_str[n] != '\0'; n++)
512 if (G_UNLIKELY (given_str[n] == '\"'))
513 g_string_append (str, "\\\"");
514 else
515 g_string_append_c (str, given_str[n]);
517 g_string_append_c (str, '"');
518 s = g_string_free (str, FALSE);
520 value = g_variant_parse (type,
522 NULL,
523 NULL,
524 error);
525 g_free (s);
527 return value;
530 /* ---------------------------------------------------------------------------------------------------- */
532 static gchar *opt_emit_dest = NULL;
533 static gchar *opt_emit_object_path = NULL;
534 static gchar *opt_emit_signal = NULL;
536 static const GOptionEntry emit_entries[] =
538 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
539 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
540 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
541 { NULL }
544 static gboolean
545 handle_emit (gint *argc,
546 gchar **argv[],
547 gboolean request_completion,
548 const gchar *completion_cur,
549 const gchar *completion_prev)
551 gint ret;
552 GOptionContext *o;
553 gchar *s;
554 GError *error;
555 GDBusConnection *c;
556 GVariant *parameters;
557 gchar *interface_name;
558 gchar *signal_name;
559 GVariantBuilder builder;
560 guint n;
562 ret = FALSE;
563 c = NULL;
564 parameters = NULL;
565 interface_name = NULL;
566 signal_name = NULL;
568 modify_argv0_for_command (argc, argv, "emit");
570 o = g_option_context_new (NULL);
571 g_option_context_set_help_enabled (o, FALSE);
572 g_option_context_set_summary (o, _("Emit a signal."));
573 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
574 g_option_context_add_group (o, connection_get_group ());
576 if (!g_option_context_parse (o, argc, argv, NULL))
578 if (!request_completion)
580 s = g_option_context_get_help (o, FALSE, NULL);
581 g_printerr ("%s", s);
582 g_free (s);
583 goto out;
587 error = NULL;
588 c = connection_get_dbus_connection (&error);
589 if (c == NULL)
591 if (request_completion)
593 if (g_strcmp0 (completion_prev, "--address") == 0)
595 g_print ("unix:\n"
596 "tcp:\n"
597 "nonce-tcp:\n");
599 else
601 g_print ("--system \n--session \n--address \n");
604 else
606 g_printerr (_("Error connecting: %s\n"), error->message);
607 g_error_free (error);
609 goto out;
612 /* All done with completion now */
613 if (request_completion)
614 goto out;
616 if (opt_emit_object_path == NULL)
618 g_printerr (_("Error: object path not specified.\n"));
619 goto out;
621 if (!g_variant_is_object_path (opt_emit_object_path))
623 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
624 goto out;
627 if (opt_emit_signal == NULL)
629 g_printerr (_("Error: signal not specified.\n"));
630 goto out;
633 s = strrchr (opt_emit_signal, '.');
634 if (s == NULL)
636 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
637 goto out;
639 signal_name = g_strdup (s + 1);
640 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
642 if (!g_dbus_is_interface_name (interface_name))
644 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
645 goto out;
648 if (!g_dbus_is_member_name (signal_name))
650 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
651 goto out;
654 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
656 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
657 goto out;
660 /* Read parameters */
661 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
662 for (n = 1; n < (guint) *argc; n++)
664 GVariant *value;
666 error = NULL;
667 value = g_variant_parse (NULL,
668 (*argv)[n],
669 NULL,
670 NULL,
671 &error);
672 if (value == NULL)
674 g_error_free (error);
675 error = NULL;
676 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
677 if (value == NULL)
679 g_printerr (_("Error parsing parameter %d: %s\n"),
681 error->message);
682 g_error_free (error);
683 g_variant_builder_clear (&builder);
684 goto out;
687 g_variant_builder_add_value (&builder, value);
689 parameters = g_variant_builder_end (&builder);
691 if (parameters != NULL)
692 parameters = g_variant_ref_sink (parameters);
693 if (!g_dbus_connection_emit_signal (c,
694 opt_emit_dest,
695 opt_emit_object_path,
696 interface_name,
697 signal_name,
698 parameters,
699 &error))
701 g_printerr (_("Error: %s\n"), error->message);
702 g_error_free (error);
703 goto out;
706 if (!g_dbus_connection_flush_sync (c, NULL, &error))
708 g_printerr (_("Error flushing connection: %s\n"), error->message);
709 g_error_free (error);
710 goto out;
713 ret = TRUE;
715 out:
716 if (c != NULL)
717 g_object_unref (c);
718 if (parameters != NULL)
719 g_variant_unref (parameters);
720 g_free (interface_name);
721 g_free (signal_name);
722 g_option_context_free (o);
723 return ret;
726 /* ---------------------------------------------------------------------------------------------------- */
728 static gchar *opt_call_dest = NULL;
729 static gchar *opt_call_object_path = NULL;
730 static gchar *opt_call_method = NULL;
731 static gint opt_call_timeout = -1;
733 static const GOptionEntry call_entries[] =
735 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
736 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
737 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
738 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
739 { NULL }
742 static gboolean
743 handle_call (gint *argc,
744 gchar **argv[],
745 gboolean request_completion,
746 const gchar *completion_cur,
747 const gchar *completion_prev)
749 gint ret;
750 GOptionContext *o;
751 gchar *s;
752 GError *error;
753 GDBusConnection *c;
754 GVariant *parameters;
755 gchar *interface_name;
756 gchar *method_name;
757 GVariant *result;
758 GPtrArray *in_signature_types;
759 gboolean complete_names;
760 gboolean complete_paths;
761 gboolean complete_methods;
762 GVariantBuilder builder;
763 guint n;
765 ret = FALSE;
766 c = NULL;
767 parameters = NULL;
768 interface_name = NULL;
769 method_name = NULL;
770 result = NULL;
771 in_signature_types = NULL;
773 modify_argv0_for_command (argc, argv, "call");
775 o = g_option_context_new (NULL);
776 g_option_context_set_help_enabled (o, FALSE);
777 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
778 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
779 g_option_context_add_group (o, connection_get_group ());
781 complete_names = FALSE;
782 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
784 complete_names = TRUE;
785 remove_arg ((*argc) - 1, argc, argv);
788 complete_paths = FALSE;
789 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
791 complete_paths = TRUE;
792 remove_arg ((*argc) - 1, argc, argv);
795 complete_methods = FALSE;
796 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
798 complete_methods = TRUE;
799 remove_arg ((*argc) - 1, argc, argv);
802 if (!g_option_context_parse (o, argc, argv, NULL))
804 if (!request_completion)
806 s = g_option_context_get_help (o, FALSE, NULL);
807 g_printerr ("%s", s);
808 g_free (s);
809 goto out;
813 error = NULL;
814 c = connection_get_dbus_connection (&error);
815 if (c == NULL)
817 if (request_completion)
819 if (g_strcmp0 (completion_prev, "--address") == 0)
821 g_print ("unix:\n"
822 "tcp:\n"
823 "nonce-tcp:\n");
825 else
827 g_print ("--system \n--session \n--address \n");
830 else
832 g_printerr (_("Error connecting: %s\n"), error->message);
833 g_error_free (error);
835 goto out;
838 /* validate and complete destination (bus name) */
839 if (g_dbus_connection_get_unique_name (c) != NULL)
841 /* this only makes sense on message bus connections */
842 if (complete_names)
844 print_names (c, FALSE);
845 goto out;
847 if (opt_call_dest == NULL)
849 if (request_completion)
850 g_print ("--dest \n");
851 else
852 g_printerr (_("Error: Destination is not specified\n"));
853 goto out;
855 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
857 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
858 goto out;
862 /* validate and complete object path */
863 if (complete_paths)
865 print_paths (c, opt_call_dest, "/");
866 goto out;
868 if (opt_call_object_path == NULL)
870 if (request_completion)
871 g_print ("--object-path \n");
872 else
873 g_printerr (_("Error: Object path is not specified\n"));
874 goto out;
876 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
878 gchar *p;
879 s = g_strdup (opt_call_object_path);
880 p = strrchr (s, '/');
881 if (p != NULL)
883 if (p == s)
884 p++;
885 *p = '\0';
887 print_paths (c, opt_call_dest, s);
888 g_free (s);
889 goto out;
891 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
893 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
894 goto out;
897 /* validate and complete method (interface + method name) */
898 if (complete_methods)
900 print_methods (c, opt_call_dest, opt_call_object_path);
901 goto out;
903 if (opt_call_method == NULL)
905 if (request_completion)
906 g_print ("--method \n");
907 else
908 g_printerr (_("Error: Method name is not specified\n"));
909 goto out;
911 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
913 print_methods (c, opt_call_dest, opt_call_object_path);
914 goto out;
916 s = strrchr (opt_call_method, '.');
917 if (!request_completion && s == NULL)
919 g_printerr (_("Error: Method name '%s' is invalid\n"), opt_call_method);
920 goto out;
922 method_name = g_strdup (s + 1);
923 interface_name = g_strndup (opt_call_method, s - opt_call_method);
925 /* All done with completion now */
926 if (request_completion)
927 goto out;
929 /* Introspect, for easy conversion - it's not fatal if we can't do this */
930 in_signature_types = call_helper_get_method_in_signature (c,
931 opt_call_dest,
932 opt_call_object_path,
933 interface_name,
934 method_name,
935 &error);
936 if (in_signature_types == NULL)
938 //g_printerr ("Error getting introspection data: %s\n", error->message);
939 g_error_free (error);
940 error = NULL;
943 /* Read parameters */
944 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
945 for (n = 1; n < (guint) *argc; n++)
947 GVariant *value;
948 GVariantType *type;
950 type = NULL;
951 if (in_signature_types != NULL)
953 if (n - 1 >= in_signature_types->len)
955 /* Only warn for the first param */
956 if (n - 1 == in_signature_types->len)
958 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
959 in_signature_types->len);
962 else
964 type = in_signature_types->pdata[n - 1];
968 error = NULL;
969 value = g_variant_parse (type,
970 (*argv)[n],
971 NULL,
972 NULL,
973 &error);
974 if (value == NULL)
976 g_error_free (error);
977 error = NULL;
978 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
979 if (value == NULL)
981 if (type != NULL)
983 s = g_variant_type_dup_string (type);
984 g_printerr (_("Error parsing parameter %d of type '%s': %s\n"),
987 error->message);
988 g_free (s);
990 else
992 g_printerr (_("Error parsing parameter %d: %s\n"),
994 error->message);
996 g_error_free (error);
997 g_variant_builder_clear (&builder);
998 goto out;
1001 g_variant_builder_add_value (&builder, value);
1003 parameters = g_variant_builder_end (&builder);
1005 if (parameters != NULL)
1006 parameters = g_variant_ref_sink (parameters);
1007 result = g_dbus_connection_call_sync (c,
1008 opt_call_dest,
1009 opt_call_object_path,
1010 interface_name,
1011 method_name,
1012 parameters,
1013 NULL,
1014 G_DBUS_CALL_FLAGS_NONE,
1015 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1016 NULL,
1017 &error);
1018 if (result == NULL)
1020 if (error)
1022 g_printerr (_("Error: %s\n"), error->message);
1023 g_error_free (error);
1025 if (in_signature_types != NULL)
1027 GString *s;
1028 s = g_string_new (NULL);
1029 for (n = 0; n < in_signature_types->len; n++)
1031 GVariantType *type = in_signature_types->pdata[n];
1032 g_string_append_len (s,
1033 g_variant_type_peek_string (type),
1034 g_variant_type_get_string_length (type));
1036 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1037 g_string_free (s, TRUE);
1039 goto out;
1042 s = g_variant_print (result, TRUE);
1043 g_print ("%s\n", s);
1044 g_free (s);
1046 ret = TRUE;
1048 out:
1049 if (in_signature_types != NULL)
1050 g_ptr_array_unref (in_signature_types);
1051 if (result != NULL)
1052 g_variant_unref (result);
1053 if (c != NULL)
1054 g_object_unref (c);
1055 if (parameters != NULL)
1056 g_variant_unref (parameters);
1057 g_free (interface_name);
1058 g_free (method_name);
1059 g_option_context_free (o);
1060 return ret;
1063 /* ---------------------------------------------------------------------------------------------------- */
1065 static gchar *opt_introspect_dest = NULL;
1066 static gchar *opt_introspect_object_path = NULL;
1067 static gboolean opt_introspect_xml = FALSE;
1068 static gboolean opt_introspect_recurse = FALSE;
1069 static gboolean opt_introspect_only_properties = FALSE;
1071 static void
1072 dump_annotation (const GDBusAnnotationInfo *o,
1073 guint indent,
1074 gboolean ignore_indent)
1076 guint n;
1077 g_print ("%*s@%s(\"%s\")\n",
1078 ignore_indent ? 0 : indent, "",
1079 o->key,
1080 o->value);
1081 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1082 dump_annotation (o->annotations[n], indent + 2, FALSE);
1085 static void
1086 dump_arg (const GDBusArgInfo *o,
1087 guint indent,
1088 const gchar *direction,
1089 gboolean ignore_indent,
1090 gboolean include_newline)
1092 guint n;
1094 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1096 dump_annotation (o->annotations[n], indent, ignore_indent);
1097 ignore_indent = FALSE;
1100 g_print ("%*s%s%s %s%s",
1101 ignore_indent ? 0 : indent, "",
1102 direction,
1103 o->signature,
1104 o->name,
1105 include_newline ? ",\n" : "");
1108 static guint
1109 count_args (GDBusArgInfo **args)
1111 guint n;
1112 n = 0;
1113 if (args == NULL)
1114 goto out;
1115 while (args[n] != NULL)
1116 n++;
1117 out:
1118 return n;
1121 static void
1122 dump_method (const GDBusMethodInfo *o,
1123 guint indent)
1125 guint n;
1126 guint m;
1127 guint name_len;
1128 guint total_num_args;
1130 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1131 dump_annotation (o->annotations[n], indent, FALSE);
1133 g_print ("%*s%s(", indent, "", o->name);
1134 name_len = strlen (o->name);
1135 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1136 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1138 gboolean ignore_indent = (m == 0);
1139 gboolean include_newline = (m != total_num_args - 1);
1141 dump_arg (o->in_args[n],
1142 indent + name_len + 1,
1143 "in ",
1144 ignore_indent,
1145 include_newline);
1147 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1149 gboolean ignore_indent = (m == 0);
1150 gboolean include_newline = (m != total_num_args - 1);
1151 dump_arg (o->out_args[n],
1152 indent + name_len + 1,
1153 "out ",
1154 ignore_indent,
1155 include_newline);
1157 g_print (");\n");
1160 static void
1161 dump_signal (const GDBusSignalInfo *o,
1162 guint indent)
1164 guint n;
1165 guint name_len;
1166 guint total_num_args;
1168 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1169 dump_annotation (o->annotations[n], indent, FALSE);
1171 g_print ("%*s%s(", indent, "", o->name);
1172 name_len = strlen (o->name);
1173 total_num_args = count_args (o->args);
1174 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1176 gboolean ignore_indent = (n == 0);
1177 gboolean include_newline = (n != total_num_args - 1);
1178 dump_arg (o->args[n],
1179 indent + name_len + 1,
1181 ignore_indent,
1182 include_newline);
1184 g_print (");\n");
1187 static void
1188 dump_property (const GDBusPropertyInfo *o,
1189 guint indent,
1190 GVariant *value)
1192 const gchar *access;
1193 guint n;
1195 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1196 access = "readonly";
1197 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1198 access = "writeonly";
1199 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1200 access = "readwrite";
1201 else
1202 g_assert_not_reached ();
1204 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1205 dump_annotation (o->annotations[n], indent, FALSE);
1207 if (value != NULL)
1209 gchar *s = g_variant_print (value, FALSE);
1210 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1211 g_free (s);
1213 else
1215 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1219 static void
1220 dump_interface (GDBusConnection *c,
1221 const gchar *name,
1222 const GDBusInterfaceInfo *o,
1223 guint indent,
1224 const gchar *object_path)
1226 guint n;
1227 GHashTable *properties;
1229 properties = g_hash_table_new_full (g_str_hash,
1230 g_str_equal,
1231 g_free,
1232 (GDestroyNotify) g_variant_unref);
1234 /* Try to get properties */
1235 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1237 GVariant *result;
1238 result = g_dbus_connection_call_sync (c,
1239 name,
1240 object_path,
1241 "org.freedesktop.DBus.Properties",
1242 "GetAll",
1243 g_variant_new ("(s)", o->name),
1244 NULL,
1245 G_DBUS_CALL_FLAGS_NONE,
1246 3000,
1247 NULL,
1248 NULL);
1249 if (result != NULL)
1251 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1253 GVariantIter *iter;
1254 GVariant *item;
1255 g_variant_get (result,
1256 "(a{sv})",
1257 &iter);
1258 while ((item = g_variant_iter_next_value (iter)))
1260 gchar *key;
1261 GVariant *value;
1262 g_variant_get (item,
1263 "{sv}",
1264 &key,
1265 &value);
1267 g_hash_table_insert (properties, key, g_variant_ref (value));
1270 g_variant_unref (result);
1272 else
1274 guint n;
1275 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1277 result = g_dbus_connection_call_sync (c,
1278 name,
1279 object_path,
1280 "org.freedesktop.DBus.Properties",
1281 "Get",
1282 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1283 G_VARIANT_TYPE ("(v)"),
1284 G_DBUS_CALL_FLAGS_NONE,
1285 3000,
1286 NULL,
1287 NULL);
1288 if (result != NULL)
1290 GVariant *property_value;
1291 g_variant_get (result,
1292 "(v)",
1293 &property_value);
1294 g_hash_table_insert (properties,
1295 g_strdup (o->properties[n]->name),
1296 g_variant_ref (property_value));
1297 g_variant_unref (result);
1303 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1304 dump_annotation (o->annotations[n], indent, FALSE);
1306 g_print ("%*sinterface %s {\n", indent, "", o->name);
1307 if (o->methods != NULL && !opt_introspect_only_properties)
1309 g_print ("%*s methods:\n", indent, "");
1310 for (n = 0; o->methods[n] != NULL; n++)
1311 dump_method (o->methods[n], indent + 4);
1313 if (o->signals != NULL && !opt_introspect_only_properties)
1315 g_print ("%*s signals:\n", indent, "");
1316 for (n = 0; o->signals[n] != NULL; n++)
1317 dump_signal (o->signals[n], indent + 4);
1319 if (o->properties != NULL)
1321 g_print ("%*s properties:\n", indent, "");
1322 for (n = 0; o->properties[n] != NULL; n++)
1324 dump_property (o->properties[n],
1325 indent + 4,
1326 g_hash_table_lookup (properties, (o->properties[n])->name));
1329 g_print ("%*s};\n",
1330 indent, "");
1332 g_hash_table_unref (properties);
1335 static gboolean
1336 introspect_do (GDBusConnection *c,
1337 const gchar *object_path,
1338 guint indent);
1340 static void
1341 dump_node (GDBusConnection *c,
1342 const gchar *name,
1343 const GDBusNodeInfo *o,
1344 guint indent,
1345 const gchar *object_path,
1346 gboolean recurse)
1348 guint n;
1349 const gchar *object_path_to_print;
1351 object_path_to_print = object_path;
1352 if (o->path != NULL)
1353 object_path_to_print = o->path;
1355 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1356 dump_annotation (o->annotations[n], indent, FALSE);
1358 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1359 if (o->interfaces != NULL || o->nodes != NULL)
1361 g_print (" {\n");
1362 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1364 if (opt_introspect_only_properties)
1366 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1367 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1369 else
1371 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1374 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1376 if (recurse)
1378 gchar *child_path;
1379 if (g_variant_is_object_path (o->nodes[n]->path))
1381 child_path = g_strdup (o->nodes[n]->path);
1382 /* avoid infinite loops */
1383 if (g_str_has_prefix (child_path, object_path))
1385 introspect_do (c, child_path, indent + 2);
1387 else
1389 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1390 child_path, object_path);
1393 else
1395 if (g_strcmp0 (object_path, "/") == 0)
1396 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1397 else
1398 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1399 introspect_do (c, child_path, indent + 2);
1401 g_free (child_path);
1403 else
1405 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1408 g_print ("%*s};\n",
1409 indent, "");
1411 else
1413 g_print ("\n");
1417 static const GOptionEntry introspect_entries[] =
1419 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1420 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1421 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1422 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1423 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1424 { NULL }
1427 static gboolean
1428 introspect_do (GDBusConnection *c,
1429 const gchar *object_path,
1430 guint indent)
1432 GError *error;
1433 GVariant *result;
1434 GDBusNodeInfo *node;
1435 gboolean ret;
1436 const gchar *xml_data;
1438 ret = FALSE;
1439 node = NULL;
1440 result = NULL;
1442 error = NULL;
1443 result = g_dbus_connection_call_sync (c,
1444 opt_introspect_dest,
1445 object_path,
1446 "org.freedesktop.DBus.Introspectable",
1447 "Introspect",
1448 NULL,
1449 G_VARIANT_TYPE ("(s)"),
1450 G_DBUS_CALL_FLAGS_NONE,
1451 3000, /* 3 sec */
1452 NULL,
1453 &error);
1454 if (result == NULL)
1456 g_printerr (_("Error: %s\n"), error->message);
1457 g_error_free (error);
1458 goto out;
1460 g_variant_get (result, "(&s)", &xml_data);
1462 if (opt_introspect_xml)
1464 g_print ("%s", xml_data);
1466 else
1468 error = NULL;
1469 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1470 if (node == NULL)
1472 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1473 g_error_free (error);
1474 goto out;
1477 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1480 ret = TRUE;
1482 out:
1483 if (node != NULL)
1484 g_dbus_node_info_unref (node);
1485 if (result != NULL)
1486 g_variant_unref (result);
1487 return ret;
1490 static gboolean
1491 handle_introspect (gint *argc,
1492 gchar **argv[],
1493 gboolean request_completion,
1494 const gchar *completion_cur,
1495 const gchar *completion_prev)
1497 gint ret;
1498 GOptionContext *o;
1499 gchar *s;
1500 GError *error;
1501 GDBusConnection *c;
1502 gboolean complete_names;
1503 gboolean complete_paths;
1505 ret = FALSE;
1506 c = NULL;
1508 modify_argv0_for_command (argc, argv, "introspect");
1510 o = g_option_context_new (NULL);
1511 if (request_completion)
1512 g_option_context_set_ignore_unknown_options (o, TRUE);
1513 g_option_context_set_help_enabled (o, FALSE);
1514 g_option_context_set_summary (o, _("Introspect a remote object."));
1515 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1516 g_option_context_add_group (o, connection_get_group ());
1518 complete_names = FALSE;
1519 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1521 complete_names = TRUE;
1522 remove_arg ((*argc) - 1, argc, argv);
1525 complete_paths = FALSE;
1526 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1528 complete_paths = TRUE;
1529 remove_arg ((*argc) - 1, argc, argv);
1532 if (!g_option_context_parse (o, argc, argv, NULL))
1534 if (!request_completion)
1536 s = g_option_context_get_help (o, FALSE, NULL);
1537 g_printerr ("%s", s);
1538 g_free (s);
1539 goto out;
1543 error = NULL;
1544 c = connection_get_dbus_connection (&error);
1545 if (c == NULL)
1547 if (request_completion)
1549 if (g_strcmp0 (completion_prev, "--address") == 0)
1551 g_print ("unix:\n"
1552 "tcp:\n"
1553 "nonce-tcp:\n");
1555 else
1557 g_print ("--system \n--session \n--address \n");
1560 else
1562 g_printerr (_("Error connecting: %s\n"), error->message);
1563 g_error_free (error);
1565 goto out;
1568 if (g_dbus_connection_get_unique_name (c) != NULL)
1570 if (complete_names)
1572 print_names (c, FALSE);
1573 goto out;
1575 /* this only makes sense on message bus connections */
1576 if (opt_introspect_dest == NULL)
1578 if (request_completion)
1579 g_print ("--dest \n");
1580 else
1581 g_printerr (_("Error: Destination is not specified\n"));
1582 goto out;
1584 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1586 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1587 goto out;
1590 if (complete_paths)
1592 print_paths (c, opt_introspect_dest, "/");
1593 goto out;
1595 if (opt_introspect_object_path == NULL)
1597 if (request_completion)
1598 g_print ("--object-path \n");
1599 else
1600 g_printerr (_("Error: Object path is not specified\n"));
1601 goto out;
1603 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1605 gchar *p;
1606 s = g_strdup (opt_introspect_object_path);
1607 p = strrchr (s, '/');
1608 if (p != NULL)
1610 if (p == s)
1611 p++;
1612 *p = '\0';
1614 print_paths (c, opt_introspect_dest, s);
1615 g_free (s);
1616 goto out;
1618 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1620 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1621 goto out;
1624 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1626 g_print ("--recurse \n");
1629 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1631 g_print ("--only-properties \n");
1634 /* All done with completion now */
1635 if (request_completion)
1636 goto out;
1638 if (!introspect_do (c, opt_introspect_object_path, 0))
1639 goto out;
1641 ret = TRUE;
1643 out:
1644 if (c != NULL)
1645 g_object_unref (c);
1646 g_option_context_free (o);
1647 return ret;
1650 /* ---------------------------------------------------------------------------------------------------- */
1652 static gchar *opt_monitor_dest = NULL;
1653 static gchar *opt_monitor_object_path = NULL;
1655 static guint monitor_filter_id = 0;
1657 static void
1658 monitor_signal_cb (GDBusConnection *connection,
1659 const gchar *sender_name,
1660 const gchar *object_path,
1661 const gchar *interface_name,
1662 const gchar *signal_name,
1663 GVariant *parameters,
1664 gpointer user_data)
1666 gchar *s;
1667 s = g_variant_print (parameters, TRUE);
1668 g_print ("%s: %s.%s %s\n",
1669 object_path,
1670 interface_name,
1671 signal_name,
1673 g_free (s);
1676 static void
1677 monitor_on_name_appeared (GDBusConnection *connection,
1678 const gchar *name,
1679 const gchar *name_owner,
1680 gpointer user_data)
1682 g_print ("The name %s is owned by %s\n", name, name_owner);
1683 g_assert (monitor_filter_id == 0);
1684 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1685 name_owner,
1686 NULL, /* any interface */
1687 NULL, /* any member */
1688 opt_monitor_object_path,
1689 NULL, /* arg0 */
1690 G_DBUS_SIGNAL_FLAGS_NONE,
1691 monitor_signal_cb,
1692 NULL, /* user_data */
1693 NULL); /* user_data destroy notify */
1696 static void
1697 monitor_on_name_vanished (GDBusConnection *connection,
1698 const gchar *name,
1699 gpointer user_data)
1701 g_print ("The name %s does not have an owner\n", name);
1703 if (monitor_filter_id != 0)
1705 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1706 monitor_filter_id = 0;
1710 static const GOptionEntry monitor_entries[] =
1712 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1713 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1714 { NULL }
1717 static gboolean
1718 handle_monitor (gint *argc,
1719 gchar **argv[],
1720 gboolean request_completion,
1721 const gchar *completion_cur,
1722 const gchar *completion_prev)
1724 gint ret;
1725 GOptionContext *o;
1726 gchar *s;
1727 GError *error;
1728 GDBusConnection *c;
1729 GVariant *result;
1730 GDBusNodeInfo *node;
1731 gboolean complete_names;
1732 gboolean complete_paths;
1733 GMainLoop *loop;
1735 ret = FALSE;
1736 c = NULL;
1737 node = NULL;
1738 result = NULL;
1740 modify_argv0_for_command (argc, argv, "monitor");
1742 o = g_option_context_new (NULL);
1743 if (request_completion)
1744 g_option_context_set_ignore_unknown_options (o, TRUE);
1745 g_option_context_set_help_enabled (o, FALSE);
1746 g_option_context_set_summary (o, _("Monitor a remote object."));
1747 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1748 g_option_context_add_group (o, connection_get_group ());
1750 complete_names = FALSE;
1751 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1753 complete_names = TRUE;
1754 remove_arg ((*argc) - 1, argc, argv);
1757 complete_paths = FALSE;
1758 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1760 complete_paths = TRUE;
1761 remove_arg ((*argc) - 1, argc, argv);
1764 if (!g_option_context_parse (o, argc, argv, NULL))
1766 if (!request_completion)
1768 s = g_option_context_get_help (o, FALSE, NULL);
1769 g_printerr ("%s", s);
1770 g_free (s);
1771 goto out;
1775 error = NULL;
1776 c = connection_get_dbus_connection (&error);
1777 if (c == NULL)
1779 if (request_completion)
1781 if (g_strcmp0 (completion_prev, "--address") == 0)
1783 g_print ("unix:\n"
1784 "tcp:\n"
1785 "nonce-tcp:\n");
1787 else
1789 g_print ("--system \n--session \n--address \n");
1792 else
1794 g_printerr (_("Error connecting: %s\n"), error->message);
1795 g_error_free (error);
1797 goto out;
1800 if (g_dbus_connection_get_unique_name (c) != NULL)
1802 if (complete_names)
1804 print_names (c, FALSE);
1805 goto out;
1807 /* this only makes sense on message bus connections */
1808 if (opt_monitor_dest == NULL)
1810 if (request_completion)
1811 g_print ("--dest \n");
1812 else
1813 g_printerr (_("Error: Destination is not specified\n"));
1814 goto out;
1816 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1818 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1819 goto out;
1822 if (complete_paths)
1824 print_paths (c, opt_monitor_dest, "/");
1825 goto out;
1827 if (opt_monitor_object_path == NULL)
1829 if (request_completion)
1831 g_print ("--object-path \n");
1832 goto out;
1834 /* it's fine to not have an object path */
1836 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1838 gchar *p;
1839 s = g_strdup (opt_monitor_object_path);
1840 p = strrchr (s, '/');
1841 if (p != NULL)
1843 if (p == s)
1844 p++;
1845 *p = '\0';
1847 print_paths (c, opt_monitor_dest, s);
1848 g_free (s);
1849 goto out;
1851 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1853 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1854 goto out;
1857 /* All done with completion now */
1858 if (request_completion)
1859 goto out;
1861 if (opt_monitor_object_path != NULL)
1862 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1863 else
1864 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1866 loop = g_main_loop_new (NULL, FALSE);
1867 g_bus_watch_name_on_connection (c,
1868 opt_monitor_dest,
1869 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1870 monitor_on_name_appeared,
1871 monitor_on_name_vanished,
1872 NULL,
1873 NULL);
1875 g_main_loop_run (loop);
1876 g_main_loop_unref (loop);
1878 ret = TRUE;
1880 out:
1881 if (node != NULL)
1882 g_dbus_node_info_unref (node);
1883 if (result != NULL)
1884 g_variant_unref (result);
1885 if (c != NULL)
1886 g_object_unref (c);
1887 g_option_context_free (o);
1888 return ret;
1891 /* ---------------------------------------------------------------------------------------------------- */
1893 static gchar *
1894 pick_word_at (const gchar *s,
1895 gint cursor,
1896 gint *out_word_begins_at)
1898 gint begin;
1899 gint end;
1901 if (s[0] == '\0')
1903 if (out_word_begins_at != NULL)
1904 *out_word_begins_at = -1;
1905 return NULL;
1908 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1910 if (out_word_begins_at != NULL)
1911 *out_word_begins_at = cursor;
1912 return g_strdup ("");
1915 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1916 cursor--;
1917 begin = cursor;
1919 end = begin;
1920 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1921 end++;
1923 if (out_word_begins_at != NULL)
1924 *out_word_begins_at = begin;
1926 return g_strndup (s + begin, end - begin);
1929 gint
1930 main (gint argc, gchar *argv[])
1932 gint ret;
1933 const gchar *command;
1934 gboolean request_completion;
1935 gchar *completion_cur;
1936 gchar *completion_prev;
1937 #ifdef G_OS_WIN32
1938 gchar *tmp;
1939 #endif
1941 setlocale (LC_ALL, "");
1942 textdomain (GETTEXT_PACKAGE);
1944 #ifdef G_OS_WIN32
1945 tmp = _glib_get_locale_dir ();
1946 bindtextdomain (GETTEXT_PACKAGE, tmp);
1947 g_free (tmp);
1948 #else
1949 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1950 #endif
1952 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1953 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1954 #endif
1956 ret = 1;
1957 completion_cur = NULL;
1958 completion_prev = NULL;
1960 if (argc < 2)
1962 usage (&argc, &argv, FALSE);
1963 goto out;
1966 request_completion = FALSE;
1968 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1970 again:
1971 command = argv[1];
1972 if (g_strcmp0 (command, "help") == 0)
1974 if (request_completion)
1976 /* do nothing */
1978 else
1980 usage (&argc, &argv, TRUE);
1981 ret = 0;
1983 goto out;
1985 else if (g_strcmp0 (command, "emit") == 0)
1987 if (handle_emit (&argc,
1988 &argv,
1989 request_completion,
1990 completion_cur,
1991 completion_prev))
1992 ret = 0;
1993 goto out;
1995 else if (g_strcmp0 (command, "call") == 0)
1997 if (handle_call (&argc,
1998 &argv,
1999 request_completion,
2000 completion_cur,
2001 completion_prev))
2002 ret = 0;
2003 goto out;
2005 else if (g_strcmp0 (command, "introspect") == 0)
2007 if (handle_introspect (&argc,
2008 &argv,
2009 request_completion,
2010 completion_cur,
2011 completion_prev))
2012 ret = 0;
2013 goto out;
2015 else if (g_strcmp0 (command, "monitor") == 0)
2017 if (handle_monitor (&argc,
2018 &argv,
2019 request_completion,
2020 completion_cur,
2021 completion_prev))
2022 ret = 0;
2023 goto out;
2025 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2027 const gchar *completion_line;
2028 gchar **completion_argv;
2029 gint completion_argc;
2030 gint completion_point;
2031 gchar *endp;
2032 gint cur_begin;
2034 request_completion = TRUE;
2036 completion_line = argv[2];
2037 completion_point = strtol (argv[3], &endp, 10);
2038 if (endp == argv[3] || *endp != '\0')
2039 goto out;
2041 #if 0
2042 completion_debug ("completion_point=%d", completion_point);
2043 completion_debug ("----");
2044 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2045 completion_debug ("'%s'", completion_line);
2046 completion_debug (" %*s^",
2047 completion_point, "");
2048 completion_debug ("----");
2049 #endif
2051 if (!g_shell_parse_argv (completion_line,
2052 &completion_argc,
2053 &completion_argv,
2054 NULL))
2056 /* it's very possible the command line can't be parsed (for
2057 * example, missing quotes etc) - in that case, we just
2058 * don't autocomplete at all
2060 goto out;
2063 /* compute cur and prev */
2064 completion_prev = NULL;
2065 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2066 if (cur_begin > 0)
2068 gint prev_end;
2069 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2071 if (!g_ascii_isspace (completion_line[prev_end]))
2073 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2074 break;
2078 #if 0
2079 completion_debug (" cur='%s'", completion_cur);
2080 completion_debug ("prev='%s'", completion_prev);
2081 #endif
2083 argc = completion_argc;
2084 argv = completion_argv;
2086 ret = 0;
2088 goto again;
2090 else
2092 if (request_completion)
2094 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2095 ret = 0;
2096 goto out;
2098 else
2100 g_printerr ("Unknown command '%s'\n", command);
2101 usage (&argc, &argv, FALSE);
2102 goto out;
2106 out:
2107 g_free (completion_cur);
2108 g_free (completion_prev);
2109 return ret;