Add some more cases to the app-id unit tests
[glib.git] / gio / gdbus-tool.c
blob7503528ca17a7b8baa8f17cc6dfbdbabad6209b7
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, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <locale.h>
28 #include <gio/gio.h>
30 #include <gi18n.h>
32 #ifdef G_OS_WIN32
33 #include "glib/glib-private.h"
34 #endif
36 /* ---------------------------------------------------------------------------------------------------- */
38 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
40 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
41 * to not have it interfere with stdout/stderr)
43 #if 0
44 G_GNUC_UNUSED static void
45 completion_debug (const gchar *format, ...)
47 va_list var_args;
48 gchar *s;
49 static FILE *f = NULL;
51 va_start (var_args, format);
52 s = g_strdup_vprintf (format, var_args);
53 if (f == NULL)
55 f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
57 fprintf (f, "%s\n", s);
58 g_free (s);
60 #else
61 static void
62 completion_debug (const gchar *format, ...)
65 #endif
67 /* ---------------------------------------------------------------------------------------------------- */
70 static void
71 remove_arg (gint num, gint *argc, gchar **argv[])
73 gint n;
75 g_assert (num <= (*argc));
77 for (n = num; (*argv)[n] != NULL; n++)
78 (*argv)[n] = (*argv)[n+1];
79 (*argv)[n] = NULL;
80 (*argc) = (*argc) - 1;
83 static void
84 usage (gint *argc, gchar **argv[], gboolean use_stdout)
86 GOptionContext *o;
87 gchar *s;
88 gchar *program_name;
90 o = g_option_context_new (_("COMMAND"));
91 g_option_context_set_help_enabled (o, FALSE);
92 /* Ignore parsing result */
93 g_option_context_parse (o, argc, argv, NULL);
94 program_name = g_path_get_basename ((*argv)[0]);
95 s = g_strdup_printf (_("Commands:\n"
96 " help Shows this information\n"
97 " introspect Introspect a remote object\n"
98 " monitor Monitor a remote object\n"
99 " call Invoke a method on a remote object\n"
100 " emit Emit a signal\n"
101 "\n"
102 "Use “%s COMMAND --help” to get help on each command.\n"),
103 program_name);
104 g_free (program_name);
105 g_option_context_set_description (o, s);
106 g_free (s);
107 s = g_option_context_get_help (o, FALSE, NULL);
108 if (use_stdout)
109 g_print ("%s", s);
110 else
111 g_printerr ("%s", s);
112 g_free (s);
113 g_option_context_free (o);
116 static void
117 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
119 gchar *s;
120 gchar *program_name;
122 /* TODO:
123 * 1. get a g_set_prgname() ?; or
124 * 2. save old argv[0] and restore later
127 g_assert (g_strcmp0 ((*argv)[1], command) == 0);
128 remove_arg (1, argc, argv);
130 program_name = g_path_get_basename ((*argv)[0]);
131 s = g_strdup_printf ("%s %s", (*argv)[0], command);
132 (*argv)[0] = s;
133 g_free (program_name);
136 /* ---------------------------------------------------------------------------------------------------- */
138 static void
139 print_methods (GDBusConnection *c,
140 const gchar *name,
141 const gchar *path)
143 GVariant *result;
144 GError *error;
145 const gchar *xml_data;
146 GDBusNodeInfo *node;
147 guint n;
148 guint m;
150 error = NULL;
151 result = g_dbus_connection_call_sync (c,
152 name,
153 path,
154 "org.freedesktop.DBus.Introspectable",
155 "Introspect",
156 NULL,
157 G_VARIANT_TYPE ("(s)"),
158 G_DBUS_CALL_FLAGS_NONE,
159 3000, /* 3 secs */
160 NULL,
161 &error);
162 if (result == NULL)
164 g_printerr (_("Error: %s\n"), error->message);
165 g_error_free (error);
166 goto out;
168 g_variant_get (result, "(&s)", &xml_data);
170 error = NULL;
171 node = g_dbus_node_info_new_for_xml (xml_data, &error);
172 g_variant_unref (result);
173 if (node == NULL)
175 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
176 g_error_free (error);
177 goto out;
180 for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
182 const GDBusInterfaceInfo *iface = node->interfaces[n];
183 for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
185 const GDBusMethodInfo *method = iface->methods[m];
186 g_print ("%s.%s \n", iface->name, method->name);
189 g_dbus_node_info_unref (node);
191 out:
195 static void
196 print_paths (GDBusConnection *c,
197 const gchar *name,
198 const gchar *path)
200 GVariant *result;
201 GError *error;
202 const gchar *xml_data;
203 GDBusNodeInfo *node;
204 guint n;
206 if (!g_dbus_is_name (name))
208 g_printerr (_("Error: %s is not a valid name\n"), name);
209 goto out;
212 error = NULL;
213 result = g_dbus_connection_call_sync (c,
214 name,
215 path,
216 "org.freedesktop.DBus.Introspectable",
217 "Introspect",
218 NULL,
219 G_VARIANT_TYPE ("(s)"),
220 G_DBUS_CALL_FLAGS_NONE,
221 3000, /* 3 secs */
222 NULL,
223 &error);
224 if (result == NULL)
226 g_printerr (_("Error: %s\n"), error->message);
227 g_error_free (error);
228 goto out;
230 g_variant_get (result, "(&s)", &xml_data);
232 //g_printerr ("xml='%s'", xml_data);
234 error = NULL;
235 node = g_dbus_node_info_new_for_xml (xml_data, &error);
236 g_variant_unref (result);
237 if (node == NULL)
239 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
240 g_error_free (error);
241 goto out;
244 //g_printerr ("bar '%s'\n", path);
246 if (node->interfaces != NULL)
247 g_print ("%s \n", path);
249 for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
251 gchar *s;
253 //g_printerr ("foo '%s'\n", node->nodes[n].path);
255 if (g_strcmp0 (path, "/") == 0)
256 s = g_strdup_printf ("/%s", node->nodes[n]->path);
257 else
258 s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
260 print_paths (c, name, s);
262 g_free (s);
264 g_dbus_node_info_unref (node);
266 out:
270 static void
271 print_names (GDBusConnection *c,
272 gboolean include_unique_names)
274 GVariant *result;
275 GError *error;
276 GVariantIter *iter;
277 gchar *str;
278 GHashTable *name_set;
279 GList *keys;
280 GList *l;
282 name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
284 error = NULL;
285 result = g_dbus_connection_call_sync (c,
286 "org.freedesktop.DBus",
287 "/org/freedesktop/DBus",
288 "org.freedesktop.DBus",
289 "ListNames",
290 NULL,
291 G_VARIANT_TYPE ("(as)"),
292 G_DBUS_CALL_FLAGS_NONE,
293 3000, /* 3 secs */
294 NULL,
295 &error);
296 if (result == NULL)
298 g_printerr (_("Error: %s\n"), error->message);
299 g_error_free (error);
300 goto out;
302 g_variant_get (result, "(as)", &iter);
303 while (g_variant_iter_loop (iter, "s", &str))
304 g_hash_table_insert (name_set, g_strdup (str), NULL);
305 g_variant_iter_free (iter);
306 g_variant_unref (result);
308 error = NULL;
309 result = g_dbus_connection_call_sync (c,
310 "org.freedesktop.DBus",
311 "/org/freedesktop/DBus",
312 "org.freedesktop.DBus",
313 "ListActivatableNames",
314 NULL,
315 G_VARIANT_TYPE ("(as)"),
316 G_DBUS_CALL_FLAGS_NONE,
317 3000, /* 3 secs */
318 NULL,
319 &error);
320 if (result == NULL)
322 g_printerr (_("Error: %s\n"), error->message);
323 g_error_free (error);
324 goto out;
326 g_variant_get (result, "(as)", &iter);
327 while (g_variant_iter_loop (iter, "s", &str))
328 g_hash_table_insert (name_set, g_strdup (str), NULL);
329 g_variant_iter_free (iter);
330 g_variant_unref (result);
332 keys = g_hash_table_get_keys (name_set);
333 keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
334 for (l = keys; l != NULL; l = l->next)
336 const gchar *name = l->data;
337 if (!include_unique_names && g_str_has_prefix (name, ":"))
338 continue;
340 g_print ("%s \n", name);
342 g_list_free (keys);
344 out:
345 g_hash_table_unref (name_set);
348 /* ---------------------------------------------------------------------------------------------------- */
350 static gboolean opt_connection_system = FALSE;
351 static gboolean opt_connection_session = FALSE;
352 static gchar *opt_connection_address = NULL;
354 static const GOptionEntry connection_entries[] =
356 { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
357 { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
358 { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
359 { NULL }
362 static GOptionGroup *
363 connection_get_group (void)
365 static GOptionGroup *g;
367 g = g_option_group_new ("connection",
368 N_("Connection Endpoint Options:"),
369 N_("Options specifying the connection endpoint"),
370 NULL,
371 NULL);
372 g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
373 g_option_group_add_entries (g, connection_entries);
375 return g;
378 static GDBusConnection *
379 connection_get_dbus_connection (GError **error)
381 GDBusConnection *c;
383 c = NULL;
385 /* First, ensure we have exactly one connect */
386 if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
388 g_set_error (error,
389 G_IO_ERROR,
390 G_IO_ERROR_FAILED,
391 _("No connection endpoint specified"));
392 goto out;
394 else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
395 (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
396 (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
398 g_set_error (error,
399 G_IO_ERROR,
400 G_IO_ERROR_FAILED,
401 _("Multiple connection endpoints specified"));
402 goto out;
405 if (opt_connection_system)
407 c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
409 else if (opt_connection_session)
411 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
413 else if (opt_connection_address != NULL)
415 c = g_dbus_connection_new_for_address_sync (opt_connection_address,
416 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
417 NULL, /* GDBusAuthObserver */
418 NULL, /* GCancellable */
419 error);
422 out:
423 return c;
426 /* ---------------------------------------------------------------------------------------------------- */
428 static GPtrArray *
429 call_helper_get_method_in_signature (GDBusConnection *c,
430 const gchar *dest,
431 const gchar *path,
432 const gchar *interface_name,
433 const gchar *method_name,
434 GError **error)
436 GPtrArray *ret;
437 GVariant *result;
438 GDBusNodeInfo *node_info;
439 const gchar *xml_data;
440 GDBusInterfaceInfo *interface_info;
441 GDBusMethodInfo *method_info;
442 guint n;
444 ret = NULL;
445 result = NULL;
446 node_info = NULL;
448 result = g_dbus_connection_call_sync (c,
449 dest,
450 path,
451 "org.freedesktop.DBus.Introspectable",
452 "Introspect",
453 NULL,
454 G_VARIANT_TYPE ("(s)"),
455 G_DBUS_CALL_FLAGS_NONE,
456 3000, /* 3 secs */
457 NULL,
458 error);
459 if (result == NULL)
460 goto out;
462 g_variant_get (result, "(&s)", &xml_data);
463 node_info = g_dbus_node_info_new_for_xml (xml_data, error);
464 if (node_info == NULL)
465 goto out;
467 interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
468 if (interface_info == NULL)
470 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
471 _("Warning: According to introspection data, interface “%s” does not exist\n"),
472 interface_name);
473 goto out;
476 method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
477 if (method_info == NULL)
479 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
480 _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"),
481 method_name,
482 interface_name);
483 goto out;
486 ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
487 for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
489 g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
492 out:
493 if (node_info != NULL)
494 g_dbus_node_info_unref (node_info);
495 if (result != NULL)
496 g_variant_unref (result);
498 return ret;
501 /* ---------------------------------------------------------------------------------------------------- */
503 static GVariant *
504 _g_variant_parse_me_harder (GVariantType *type,
505 const gchar *given_str,
506 GError **error)
508 GVariant *value;
509 gchar *s;
510 guint n;
511 GString *str;
513 str = g_string_new ("\"");
514 for (n = 0; given_str[n] != '\0'; n++)
516 if (G_UNLIKELY (given_str[n] == '\"'))
517 g_string_append (str, "\\\"");
518 else
519 g_string_append_c (str, given_str[n]);
521 g_string_append_c (str, '"');
522 s = g_string_free (str, FALSE);
524 value = g_variant_parse (type,
526 NULL,
527 NULL,
528 error);
529 g_free (s);
531 return value;
534 /* ---------------------------------------------------------------------------------------------------- */
536 static gchar *opt_emit_dest = NULL;
537 static gchar *opt_emit_object_path = NULL;
538 static gchar *opt_emit_signal = NULL;
540 static const GOptionEntry emit_entries[] =
542 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
543 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
544 { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
545 { NULL }
548 static gboolean
549 handle_emit (gint *argc,
550 gchar **argv[],
551 gboolean request_completion,
552 const gchar *completion_cur,
553 const gchar *completion_prev)
555 gint ret;
556 GOptionContext *o;
557 gchar *s;
558 GError *error;
559 GDBusConnection *c;
560 GVariant *parameters;
561 gchar *interface_name;
562 gchar *signal_name;
563 GVariantBuilder builder;
564 gboolean skip_dashes;
565 guint parm;
566 guint n;
568 ret = FALSE;
569 c = NULL;
570 parameters = NULL;
571 interface_name = NULL;
572 signal_name = NULL;
574 modify_argv0_for_command (argc, argv, "emit");
576 o = g_option_context_new (NULL);
577 g_option_context_set_help_enabled (o, FALSE);
578 g_option_context_set_summary (o, _("Emit a signal."));
579 g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
580 g_option_context_add_group (o, connection_get_group ());
582 if (!g_option_context_parse (o, argc, argv, NULL))
584 if (!request_completion)
586 s = g_option_context_get_help (o, FALSE, NULL);
587 g_printerr ("%s", s);
588 g_free (s);
589 goto out;
593 error = NULL;
594 c = connection_get_dbus_connection (&error);
595 if (c == NULL)
597 if (request_completion)
599 if (g_strcmp0 (completion_prev, "--address") == 0)
601 g_print ("unix:\n"
602 "tcp:\n"
603 "nonce-tcp:\n");
605 else
607 g_print ("--system \n--session \n--address \n");
610 else
612 g_printerr (_("Error connecting: %s\n"), error->message);
613 g_error_free (error);
615 goto out;
618 /* All done with completion now */
619 if (request_completion)
620 goto out;
622 if (opt_emit_object_path == NULL)
624 g_printerr (_("Error: object path not specified.\n"));
625 goto out;
627 if (!g_variant_is_object_path (opt_emit_object_path))
629 g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
630 goto out;
633 if (opt_emit_signal == NULL)
635 g_printerr (_("Error: signal not specified.\n"));
636 goto out;
639 s = strrchr (opt_emit_signal, '.');
640 if (s == NULL)
642 g_printerr (_("Error: signal must be the fully-qualified name.\n"));
643 goto out;
645 signal_name = g_strdup (s + 1);
646 interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
648 if (!g_dbus_is_interface_name (interface_name))
650 g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
651 goto out;
654 if (!g_dbus_is_member_name (signal_name))
656 g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
657 goto out;
660 if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
662 g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
663 goto out;
666 /* Read parameters */
667 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
668 skip_dashes = TRUE;
669 parm = 0;
670 for (n = 1; n < (guint) *argc; n++)
672 GVariant *value;
674 /* Under certain conditions, g_option_context_parse returns the "--"
675 itself (setting off unparsed arguments), too: */
676 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
678 skip_dashes = FALSE;
679 continue;
682 error = NULL;
683 value = g_variant_parse (NULL,
684 (*argv)[n],
685 NULL,
686 NULL,
687 &error);
688 if (value == NULL)
690 gchar *context;
692 context = g_variant_parse_error_print_context (error, (*argv)[n]);
693 g_error_free (error);
694 error = NULL;
695 value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
696 if (value == NULL)
698 /* Use the original non-"parse-me-harder" error */
699 g_printerr (_("Error parsing parameter %d: %s\n"),
700 parm + 1,
701 context);
702 g_error_free (error);
703 g_free (context);
704 g_variant_builder_clear (&builder);
705 goto out;
707 g_free (context);
709 g_variant_builder_add_value (&builder, value);
710 ++parm;
712 parameters = g_variant_builder_end (&builder);
714 if (parameters != NULL)
715 parameters = g_variant_ref_sink (parameters);
716 if (!g_dbus_connection_emit_signal (c,
717 opt_emit_dest,
718 opt_emit_object_path,
719 interface_name,
720 signal_name,
721 parameters,
722 &error))
724 g_printerr (_("Error: %s\n"), error->message);
725 g_error_free (error);
726 goto out;
729 if (!g_dbus_connection_flush_sync (c, NULL, &error))
731 g_printerr (_("Error flushing connection: %s\n"), error->message);
732 g_error_free (error);
733 goto out;
736 ret = TRUE;
738 out:
739 if (c != NULL)
740 g_object_unref (c);
741 if (parameters != NULL)
742 g_variant_unref (parameters);
743 g_free (interface_name);
744 g_free (signal_name);
745 g_option_context_free (o);
746 return ret;
749 /* ---------------------------------------------------------------------------------------------------- */
751 static gchar *opt_call_dest = NULL;
752 static gchar *opt_call_object_path = NULL;
753 static gchar *opt_call_method = NULL;
754 static gint opt_call_timeout = -1;
756 static const GOptionEntry call_entries[] =
758 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
759 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
760 { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
761 { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
762 { NULL }
765 static gboolean
766 handle_call (gint *argc,
767 gchar **argv[],
768 gboolean request_completion,
769 const gchar *completion_cur,
770 const gchar *completion_prev)
772 gint ret;
773 GOptionContext *o;
774 gchar *s;
775 GError *error;
776 GDBusConnection *c;
777 GVariant *parameters;
778 gchar *interface_name;
779 gchar *method_name;
780 GVariant *result;
781 GPtrArray *in_signature_types;
782 gboolean complete_names;
783 gboolean complete_paths;
784 gboolean complete_methods;
785 GVariantBuilder builder;
786 gboolean skip_dashes;
787 guint parm;
788 guint n;
790 ret = FALSE;
791 c = NULL;
792 parameters = NULL;
793 interface_name = NULL;
794 method_name = NULL;
795 result = NULL;
796 in_signature_types = NULL;
798 modify_argv0_for_command (argc, argv, "call");
800 o = g_option_context_new (NULL);
801 g_option_context_set_help_enabled (o, FALSE);
802 g_option_context_set_summary (o, _("Invoke a method on a remote object."));
803 g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
804 g_option_context_add_group (o, connection_get_group ());
806 complete_names = FALSE;
807 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
809 complete_names = TRUE;
810 remove_arg ((*argc) - 1, argc, argv);
813 complete_paths = FALSE;
814 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
816 complete_paths = TRUE;
817 remove_arg ((*argc) - 1, argc, argv);
820 complete_methods = FALSE;
821 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
823 complete_methods = TRUE;
824 remove_arg ((*argc) - 1, argc, argv);
827 if (!g_option_context_parse (o, argc, argv, NULL))
829 if (!request_completion)
831 s = g_option_context_get_help (o, FALSE, NULL);
832 g_printerr ("%s", s);
833 g_free (s);
834 goto out;
838 error = NULL;
839 c = connection_get_dbus_connection (&error);
840 if (c == NULL)
842 if (request_completion)
844 if (g_strcmp0 (completion_prev, "--address") == 0)
846 g_print ("unix:\n"
847 "tcp:\n"
848 "nonce-tcp:\n");
850 else
852 g_print ("--system \n--session \n--address \n");
855 else
857 g_printerr (_("Error connecting: %s\n"), error->message);
858 g_error_free (error);
860 goto out;
863 /* validate and complete destination (bus name) */
864 if (g_dbus_connection_get_unique_name (c) != NULL)
866 /* this only makes sense on message bus connections */
867 if (complete_names)
869 print_names (c, FALSE);
870 goto out;
872 if (opt_call_dest == NULL)
874 if (request_completion)
875 g_print ("--dest \n");
876 else
877 g_printerr (_("Error: Destination is not specified\n"));
878 goto out;
880 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
882 print_names (c, g_str_has_prefix (opt_call_dest, ":"));
883 goto out;
887 if (!request_completion && !g_dbus_is_name (opt_call_dest))
889 g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest);
890 goto out;
893 /* validate and complete object path */
894 if (complete_paths)
896 print_paths (c, opt_call_dest, "/");
897 goto out;
899 if (opt_call_object_path == NULL)
901 if (request_completion)
902 g_print ("--object-path \n");
903 else
904 g_printerr (_("Error: Object path is not specified\n"));
905 goto out;
907 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
909 gchar *p;
910 s = g_strdup (opt_call_object_path);
911 p = strrchr (s, '/');
912 if (p != NULL)
914 if (p == s)
915 p++;
916 *p = '\0';
918 print_paths (c, opt_call_dest, s);
919 g_free (s);
920 goto out;
922 if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
924 g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
925 goto out;
928 /* validate and complete method (interface + method name) */
929 if (complete_methods)
931 print_methods (c, opt_call_dest, opt_call_object_path);
932 goto out;
934 if (opt_call_method == NULL)
936 if (request_completion)
937 g_print ("--method \n");
938 else
939 g_printerr (_("Error: Method name is not specified\n"));
940 goto out;
942 if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
944 print_methods (c, opt_call_dest, opt_call_object_path);
945 goto out;
947 s = strrchr (opt_call_method, '.');
948 if (!request_completion && s == NULL)
950 g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method);
951 goto out;
953 method_name = g_strdup (s + 1);
954 interface_name = g_strndup (opt_call_method, s - opt_call_method);
956 /* All done with completion now */
957 if (request_completion)
958 goto out;
960 /* Introspect, for easy conversion - it's not fatal if we can't do this */
961 in_signature_types = call_helper_get_method_in_signature (c,
962 opt_call_dest,
963 opt_call_object_path,
964 interface_name,
965 method_name,
966 &error);
967 if (in_signature_types == NULL)
969 //g_printerr ("Error getting introspection data: %s\n", error->message);
970 g_error_free (error);
971 error = NULL;
974 /* Read parameters */
975 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
976 skip_dashes = TRUE;
977 parm = 0;
978 for (n = 1; n < (guint) *argc; n++)
980 GVariant *value;
981 GVariantType *type;
983 /* Under certain conditions, g_option_context_parse returns the "--"
984 itself (setting off unparsed arguments), too: */
985 if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
987 skip_dashes = FALSE;
988 continue;
991 type = NULL;
992 if (in_signature_types != NULL)
994 if (parm >= in_signature_types->len)
996 /* Only warn for the first param */
997 if (parm == in_signature_types->len)
999 g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
1000 in_signature_types->len);
1003 else
1005 type = in_signature_types->pdata[parm];
1009 error = NULL;
1010 value = g_variant_parse (type,
1011 (*argv)[n],
1012 NULL,
1013 NULL,
1014 &error);
1015 if (value == NULL)
1017 gchar *context;
1019 context = g_variant_parse_error_print_context (error, (*argv)[n]);
1020 g_error_free (error);
1021 error = NULL;
1022 value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1023 if (value == NULL)
1025 if (type != NULL)
1027 s = g_variant_type_dup_string (type);
1028 g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"),
1029 parm + 1,
1031 context);
1032 g_free (s);
1034 else
1036 g_printerr (_("Error parsing parameter %d: %s\n"),
1037 parm + 1,
1038 context);
1040 g_error_free (error);
1041 g_variant_builder_clear (&builder);
1042 g_free (context);
1043 goto out;
1045 g_free (context);
1047 g_variant_builder_add_value (&builder, value);
1048 ++parm;
1050 parameters = g_variant_builder_end (&builder);
1052 if (parameters != NULL)
1053 parameters = g_variant_ref_sink (parameters);
1054 result = g_dbus_connection_call_sync (c,
1055 opt_call_dest,
1056 opt_call_object_path,
1057 interface_name,
1058 method_name,
1059 parameters,
1060 NULL,
1061 G_DBUS_CALL_FLAGS_NONE,
1062 opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1063 NULL,
1064 &error);
1065 if (result == NULL)
1067 g_printerr (_("Error: %s\n"), error->message);
1069 if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL)
1071 if (in_signature_types->len > 0)
1073 GString *s;
1074 s = g_string_new (NULL);
1076 for (n = 0; n < in_signature_types->len; n++)
1078 GVariantType *type = in_signature_types->pdata[n];
1079 g_string_append_len (s,
1080 g_variant_type_peek_string (type),
1081 g_variant_type_get_string_length (type));
1084 g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1085 g_string_free (s, TRUE);
1087 else
1088 g_printerr ("(According to introspection data, you need to pass no arguments)\n");
1091 g_error_free (error);
1092 goto out;
1095 s = g_variant_print (result, TRUE);
1096 g_print ("%s\n", s);
1097 g_free (s);
1099 ret = TRUE;
1101 out:
1102 if (in_signature_types != NULL)
1103 g_ptr_array_unref (in_signature_types);
1104 if (result != NULL)
1105 g_variant_unref (result);
1106 if (c != NULL)
1107 g_object_unref (c);
1108 if (parameters != NULL)
1109 g_variant_unref (parameters);
1110 g_free (interface_name);
1111 g_free (method_name);
1112 g_option_context_free (o);
1113 return ret;
1116 /* ---------------------------------------------------------------------------------------------------- */
1118 static gchar *opt_introspect_dest = NULL;
1119 static gchar *opt_introspect_object_path = NULL;
1120 static gboolean opt_introspect_xml = FALSE;
1121 static gboolean opt_introspect_recurse = FALSE;
1122 static gboolean opt_introspect_only_properties = FALSE;
1124 static void
1125 dump_annotation (const GDBusAnnotationInfo *o,
1126 guint indent,
1127 gboolean ignore_indent)
1129 guint n;
1130 g_print ("%*s@%s(\"%s\")\n",
1131 ignore_indent ? 0 : indent, "",
1132 o->key,
1133 o->value);
1134 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1135 dump_annotation (o->annotations[n], indent + 2, FALSE);
1138 static void
1139 dump_arg (const GDBusArgInfo *o,
1140 guint indent,
1141 const gchar *direction,
1142 gboolean ignore_indent,
1143 gboolean include_newline)
1145 guint n;
1147 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1149 dump_annotation (o->annotations[n], indent, ignore_indent);
1150 ignore_indent = FALSE;
1153 g_print ("%*s%s%s %s%s",
1154 ignore_indent ? 0 : indent, "",
1155 direction,
1156 o->signature,
1157 o->name,
1158 include_newline ? ",\n" : "");
1161 static guint
1162 count_args (GDBusArgInfo **args)
1164 guint n;
1165 n = 0;
1166 if (args == NULL)
1167 goto out;
1168 while (args[n] != NULL)
1169 n++;
1170 out:
1171 return n;
1174 static void
1175 dump_method (const GDBusMethodInfo *o,
1176 guint indent)
1178 guint n;
1179 guint m;
1180 guint name_len;
1181 guint total_num_args;
1183 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1184 dump_annotation (o->annotations[n], indent, FALSE);
1186 g_print ("%*s%s(", indent, "", o->name);
1187 name_len = strlen (o->name);
1188 total_num_args = count_args (o->in_args) + count_args (o->out_args);
1189 for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1191 gboolean ignore_indent = (m == 0);
1192 gboolean include_newline = (m != total_num_args - 1);
1194 dump_arg (o->in_args[n],
1195 indent + name_len + 1,
1196 "in ",
1197 ignore_indent,
1198 include_newline);
1200 for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1202 gboolean ignore_indent = (m == 0);
1203 gboolean include_newline = (m != total_num_args - 1);
1204 dump_arg (o->out_args[n],
1205 indent + name_len + 1,
1206 "out ",
1207 ignore_indent,
1208 include_newline);
1210 g_print (");\n");
1213 static void
1214 dump_signal (const GDBusSignalInfo *o,
1215 guint indent)
1217 guint n;
1218 guint name_len;
1219 guint total_num_args;
1221 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1222 dump_annotation (o->annotations[n], indent, FALSE);
1224 g_print ("%*s%s(", indent, "", o->name);
1225 name_len = strlen (o->name);
1226 total_num_args = count_args (o->args);
1227 for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1229 gboolean ignore_indent = (n == 0);
1230 gboolean include_newline = (n != total_num_args - 1);
1231 dump_arg (o->args[n],
1232 indent + name_len + 1,
1234 ignore_indent,
1235 include_newline);
1237 g_print (");\n");
1240 static void
1241 dump_property (const GDBusPropertyInfo *o,
1242 guint indent,
1243 GVariant *value)
1245 const gchar *access;
1246 guint n;
1248 if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1249 access = "readonly";
1250 else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1251 access = "writeonly";
1252 else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1253 access = "readwrite";
1254 else
1255 g_assert_not_reached ();
1257 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1258 dump_annotation (o->annotations[n], indent, FALSE);
1260 if (value != NULL)
1262 gchar *s = g_variant_print (value, FALSE);
1263 g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1264 g_free (s);
1266 else
1268 g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1272 static void
1273 dump_interface (GDBusConnection *c,
1274 const gchar *name,
1275 const GDBusInterfaceInfo *o,
1276 guint indent,
1277 const gchar *object_path)
1279 guint n;
1280 GHashTable *properties;
1282 properties = g_hash_table_new_full (g_str_hash,
1283 g_str_equal,
1284 g_free,
1285 (GDestroyNotify) g_variant_unref);
1287 /* Try to get properties */
1288 if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1290 GVariant *result;
1291 result = g_dbus_connection_call_sync (c,
1292 name,
1293 object_path,
1294 "org.freedesktop.DBus.Properties",
1295 "GetAll",
1296 g_variant_new ("(s)", o->name),
1297 NULL,
1298 G_DBUS_CALL_FLAGS_NONE,
1299 3000,
1300 NULL,
1301 NULL);
1302 if (result != NULL)
1304 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1306 GVariantIter *iter;
1307 GVariant *item;
1308 g_variant_get (result,
1309 "(a{sv})",
1310 &iter);
1311 while ((item = g_variant_iter_next_value (iter)))
1313 gchar *key;
1314 GVariant *value;
1315 g_variant_get (item,
1316 "{sv}",
1317 &key,
1318 &value);
1320 g_hash_table_insert (properties, key, g_variant_ref (value));
1323 g_variant_unref (result);
1325 else
1327 guint n;
1328 for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1330 result = g_dbus_connection_call_sync (c,
1331 name,
1332 object_path,
1333 "org.freedesktop.DBus.Properties",
1334 "Get",
1335 g_variant_new ("(ss)", o->name, o->properties[n]->name),
1336 G_VARIANT_TYPE ("(v)"),
1337 G_DBUS_CALL_FLAGS_NONE,
1338 3000,
1339 NULL,
1340 NULL);
1341 if (result != NULL)
1343 GVariant *property_value;
1344 g_variant_get (result,
1345 "(v)",
1346 &property_value);
1347 g_hash_table_insert (properties,
1348 g_strdup (o->properties[n]->name),
1349 g_variant_ref (property_value));
1350 g_variant_unref (result);
1356 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1357 dump_annotation (o->annotations[n], indent, FALSE);
1359 g_print ("%*sinterface %s {\n", indent, "", o->name);
1360 if (o->methods != NULL && !opt_introspect_only_properties)
1362 g_print ("%*s methods:\n", indent, "");
1363 for (n = 0; o->methods[n] != NULL; n++)
1364 dump_method (o->methods[n], indent + 4);
1366 if (o->signals != NULL && !opt_introspect_only_properties)
1368 g_print ("%*s signals:\n", indent, "");
1369 for (n = 0; o->signals[n] != NULL; n++)
1370 dump_signal (o->signals[n], indent + 4);
1372 if (o->properties != NULL)
1374 g_print ("%*s properties:\n", indent, "");
1375 for (n = 0; o->properties[n] != NULL; n++)
1377 dump_property (o->properties[n],
1378 indent + 4,
1379 g_hash_table_lookup (properties, (o->properties[n])->name));
1382 g_print ("%*s};\n",
1383 indent, "");
1385 g_hash_table_unref (properties);
1388 static gboolean
1389 introspect_do (GDBusConnection *c,
1390 const gchar *object_path,
1391 guint indent);
1393 static void
1394 dump_node (GDBusConnection *c,
1395 const gchar *name,
1396 const GDBusNodeInfo *o,
1397 guint indent,
1398 const gchar *object_path,
1399 gboolean recurse)
1401 guint n;
1402 const gchar *object_path_to_print;
1404 object_path_to_print = object_path;
1405 if (o->path != NULL)
1406 object_path_to_print = o->path;
1408 for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1409 dump_annotation (o->annotations[n], indent, FALSE);
1411 g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1412 if (o->interfaces != NULL || o->nodes != NULL)
1414 g_print (" {\n");
1415 for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1417 if (opt_introspect_only_properties)
1419 if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1420 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1422 else
1424 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1427 for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1429 if (recurse)
1431 gchar *child_path;
1432 if (g_variant_is_object_path (o->nodes[n]->path))
1434 child_path = g_strdup (o->nodes[n]->path);
1435 /* avoid infinite loops */
1436 if (g_str_has_prefix (child_path, object_path))
1438 introspect_do (c, child_path, indent + 2);
1440 else
1442 g_print ("Skipping path %s that is not enclosed by parent %s\n",
1443 child_path, object_path);
1446 else
1448 if (g_strcmp0 (object_path, "/") == 0)
1449 child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1450 else
1451 child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1452 introspect_do (c, child_path, indent + 2);
1454 g_free (child_path);
1456 else
1458 dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1461 g_print ("%*s};\n",
1462 indent, "");
1464 else
1466 g_print ("\n");
1470 static const GOptionEntry introspect_entries[] =
1472 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1473 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1474 { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1475 { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1476 { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1477 { NULL }
1480 static gboolean
1481 introspect_do (GDBusConnection *c,
1482 const gchar *object_path,
1483 guint indent)
1485 GError *error;
1486 GVariant *result;
1487 GDBusNodeInfo *node;
1488 gboolean ret;
1489 const gchar *xml_data;
1491 ret = FALSE;
1492 node = NULL;
1493 result = NULL;
1495 error = NULL;
1496 result = g_dbus_connection_call_sync (c,
1497 opt_introspect_dest,
1498 object_path,
1499 "org.freedesktop.DBus.Introspectable",
1500 "Introspect",
1501 NULL,
1502 G_VARIANT_TYPE ("(s)"),
1503 G_DBUS_CALL_FLAGS_NONE,
1504 3000, /* 3 sec */
1505 NULL,
1506 &error);
1507 if (result == NULL)
1509 g_printerr (_("Error: %s\n"), error->message);
1510 g_error_free (error);
1511 goto out;
1513 g_variant_get (result, "(&s)", &xml_data);
1515 if (opt_introspect_xml)
1517 g_print ("%s", xml_data);
1519 else
1521 error = NULL;
1522 node = g_dbus_node_info_new_for_xml (xml_data, &error);
1523 if (node == NULL)
1525 g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1526 g_error_free (error);
1527 goto out;
1530 dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1533 ret = TRUE;
1535 out:
1536 if (node != NULL)
1537 g_dbus_node_info_unref (node);
1538 if (result != NULL)
1539 g_variant_unref (result);
1540 return ret;
1543 static gboolean
1544 handle_introspect (gint *argc,
1545 gchar **argv[],
1546 gboolean request_completion,
1547 const gchar *completion_cur,
1548 const gchar *completion_prev)
1550 gint ret;
1551 GOptionContext *o;
1552 gchar *s;
1553 GError *error;
1554 GDBusConnection *c;
1555 gboolean complete_names;
1556 gboolean complete_paths;
1558 ret = FALSE;
1559 c = NULL;
1561 modify_argv0_for_command (argc, argv, "introspect");
1563 o = g_option_context_new (NULL);
1564 if (request_completion)
1565 g_option_context_set_ignore_unknown_options (o, TRUE);
1566 g_option_context_set_help_enabled (o, FALSE);
1567 g_option_context_set_summary (o, _("Introspect a remote object."));
1568 g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1569 g_option_context_add_group (o, connection_get_group ());
1571 complete_names = FALSE;
1572 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1574 complete_names = TRUE;
1575 remove_arg ((*argc) - 1, argc, argv);
1578 complete_paths = FALSE;
1579 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1581 complete_paths = TRUE;
1582 remove_arg ((*argc) - 1, argc, argv);
1585 if (!g_option_context_parse (o, argc, argv, NULL))
1587 if (!request_completion)
1589 s = g_option_context_get_help (o, FALSE, NULL);
1590 g_printerr ("%s", s);
1591 g_free (s);
1592 goto out;
1596 error = NULL;
1597 c = connection_get_dbus_connection (&error);
1598 if (c == NULL)
1600 if (request_completion)
1602 if (g_strcmp0 (completion_prev, "--address") == 0)
1604 g_print ("unix:\n"
1605 "tcp:\n"
1606 "nonce-tcp:\n");
1608 else
1610 g_print ("--system \n--session \n--address \n");
1613 else
1615 g_printerr (_("Error connecting: %s\n"), error->message);
1616 g_error_free (error);
1618 goto out;
1621 if (g_dbus_connection_get_unique_name (c) != NULL)
1623 if (complete_names)
1625 print_names (c, FALSE);
1626 goto out;
1628 /* this only makes sense on message bus connections */
1629 if (opt_introspect_dest == NULL)
1631 if (request_completion)
1632 g_print ("--dest \n");
1633 else
1634 g_printerr (_("Error: Destination is not specified\n"));
1635 goto out;
1637 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1639 print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1640 goto out;
1643 if (complete_paths)
1645 print_paths (c, opt_introspect_dest, "/");
1646 goto out;
1649 if (!request_completion && !g_dbus_is_name (opt_introspect_dest))
1651 g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest);
1652 goto out;
1655 if (opt_introspect_object_path == NULL)
1657 if (request_completion)
1658 g_print ("--object-path \n");
1659 else
1660 g_printerr (_("Error: Object path is not specified\n"));
1661 goto out;
1663 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1665 gchar *p;
1666 s = g_strdup (opt_introspect_object_path);
1667 p = strrchr (s, '/');
1668 if (p != NULL)
1670 if (p == s)
1671 p++;
1672 *p = '\0';
1674 print_paths (c, opt_introspect_dest, s);
1675 g_free (s);
1676 goto out;
1678 if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1680 g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1681 goto out;
1684 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1686 g_print ("--recurse \n");
1689 if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1691 g_print ("--only-properties \n");
1694 /* All done with completion now */
1695 if (request_completion)
1696 goto out;
1698 if (!introspect_do (c, opt_introspect_object_path, 0))
1699 goto out;
1701 ret = TRUE;
1703 out:
1704 if (c != NULL)
1705 g_object_unref (c);
1706 g_option_context_free (o);
1707 return ret;
1710 /* ---------------------------------------------------------------------------------------------------- */
1712 static gchar *opt_monitor_dest = NULL;
1713 static gchar *opt_monitor_object_path = NULL;
1715 static guint monitor_filter_id = 0;
1717 static void
1718 monitor_signal_cb (GDBusConnection *connection,
1719 const gchar *sender_name,
1720 const gchar *object_path,
1721 const gchar *interface_name,
1722 const gchar *signal_name,
1723 GVariant *parameters,
1724 gpointer user_data)
1726 gchar *s;
1727 s = g_variant_print (parameters, TRUE);
1728 g_print ("%s: %s.%s %s\n",
1729 object_path,
1730 interface_name,
1731 signal_name,
1733 g_free (s);
1736 static void
1737 monitor_on_name_appeared (GDBusConnection *connection,
1738 const gchar *name,
1739 const gchar *name_owner,
1740 gpointer user_data)
1742 g_print ("The name %s is owned by %s\n", name, name_owner);
1743 g_assert (monitor_filter_id == 0);
1744 monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1745 name_owner,
1746 NULL, /* any interface */
1747 NULL, /* any member */
1748 opt_monitor_object_path,
1749 NULL, /* arg0 */
1750 G_DBUS_SIGNAL_FLAGS_NONE,
1751 monitor_signal_cb,
1752 NULL, /* user_data */
1753 NULL); /* user_data destroy notify */
1756 static void
1757 monitor_on_name_vanished (GDBusConnection *connection,
1758 const gchar *name,
1759 gpointer user_data)
1761 g_print ("The name %s does not have an owner\n", name);
1763 if (monitor_filter_id != 0)
1765 g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1766 monitor_filter_id = 0;
1770 static const GOptionEntry monitor_entries[] =
1772 { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1773 { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1774 { NULL }
1777 static gboolean
1778 handle_monitor (gint *argc,
1779 gchar **argv[],
1780 gboolean request_completion,
1781 const gchar *completion_cur,
1782 const gchar *completion_prev)
1784 gint ret;
1785 GOptionContext *o;
1786 gchar *s;
1787 GError *error;
1788 GDBusConnection *c;
1789 gboolean complete_names;
1790 gboolean complete_paths;
1791 GMainLoop *loop;
1793 ret = FALSE;
1794 c = NULL;
1796 modify_argv0_for_command (argc, argv, "monitor");
1798 o = g_option_context_new (NULL);
1799 if (request_completion)
1800 g_option_context_set_ignore_unknown_options (o, TRUE);
1801 g_option_context_set_help_enabled (o, FALSE);
1802 g_option_context_set_summary (o, _("Monitor a remote object."));
1803 g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1804 g_option_context_add_group (o, connection_get_group ());
1806 complete_names = FALSE;
1807 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1809 complete_names = TRUE;
1810 remove_arg ((*argc) - 1, argc, argv);
1813 complete_paths = FALSE;
1814 if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1816 complete_paths = TRUE;
1817 remove_arg ((*argc) - 1, argc, argv);
1820 if (!g_option_context_parse (o, argc, argv, NULL))
1822 if (!request_completion)
1824 s = g_option_context_get_help (o, FALSE, NULL);
1825 g_printerr ("%s", s);
1826 g_free (s);
1827 goto out;
1831 error = NULL;
1832 c = connection_get_dbus_connection (&error);
1833 if (c == NULL)
1835 if (request_completion)
1837 if (g_strcmp0 (completion_prev, "--address") == 0)
1839 g_print ("unix:\n"
1840 "tcp:\n"
1841 "nonce-tcp:\n");
1843 else
1845 g_print ("--system \n--session \n--address \n");
1848 else
1850 g_printerr (_("Error connecting: %s\n"), error->message);
1851 g_error_free (error);
1853 goto out;
1856 if (g_dbus_connection_get_unique_name (c) != NULL)
1858 if (complete_names)
1860 print_names (c, FALSE);
1861 goto out;
1863 /* this only makes sense on message bus connections */
1864 if (opt_monitor_dest == NULL)
1866 if (request_completion)
1867 g_print ("--dest \n");
1868 else
1869 g_printerr (_("Error: Destination is not specified\n"));
1870 goto out;
1872 if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1874 print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1875 goto out;
1879 if (!request_completion && !g_dbus_is_name (opt_monitor_dest))
1881 g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest);
1882 goto out;
1885 if (complete_paths)
1887 print_paths (c, opt_monitor_dest, "/");
1888 goto out;
1890 if (opt_monitor_object_path == NULL)
1892 if (request_completion)
1894 g_print ("--object-path \n");
1895 goto out;
1897 /* it's fine to not have an object path */
1899 if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1901 gchar *p;
1902 s = g_strdup (opt_monitor_object_path);
1903 p = strrchr (s, '/');
1904 if (p != NULL)
1906 if (p == s)
1907 p++;
1908 *p = '\0';
1910 print_paths (c, opt_monitor_dest, s);
1911 g_free (s);
1912 goto out;
1914 if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1916 g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1917 goto out;
1920 /* All done with completion now */
1921 if (request_completion)
1922 goto out;
1924 if (opt_monitor_object_path != NULL)
1925 g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1926 else
1927 g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1929 loop = g_main_loop_new (NULL, FALSE);
1930 g_bus_watch_name_on_connection (c,
1931 opt_monitor_dest,
1932 G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1933 monitor_on_name_appeared,
1934 monitor_on_name_vanished,
1935 NULL,
1936 NULL);
1938 g_main_loop_run (loop);
1939 g_main_loop_unref (loop);
1941 ret = TRUE;
1943 out:
1944 if (c != NULL)
1945 g_object_unref (c);
1946 g_option_context_free (o);
1947 return ret;
1950 /* ---------------------------------------------------------------------------------------------------- */
1952 static gchar *
1953 pick_word_at (const gchar *s,
1954 gint cursor,
1955 gint *out_word_begins_at)
1957 gint begin;
1958 gint end;
1960 if (s[0] == '\0')
1962 if (out_word_begins_at != NULL)
1963 *out_word_begins_at = -1;
1964 return NULL;
1967 if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1969 if (out_word_begins_at != NULL)
1970 *out_word_begins_at = cursor;
1971 return g_strdup ("");
1974 while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1975 cursor--;
1976 begin = cursor;
1978 end = begin;
1979 while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1980 end++;
1982 if (out_word_begins_at != NULL)
1983 *out_word_begins_at = begin;
1985 return g_strndup (s + begin, end - begin);
1988 gint
1989 main (gint argc, gchar *argv[])
1991 gint ret;
1992 const gchar *command;
1993 gboolean request_completion;
1994 gchar *completion_cur;
1995 gchar *completion_prev;
1996 #ifdef G_OS_WIN32
1997 gchar *tmp;
1998 #endif
2000 setlocale (LC_ALL, "");
2001 textdomain (GETTEXT_PACKAGE);
2003 #ifdef G_OS_WIN32
2004 tmp = _glib_get_locale_dir ();
2005 bindtextdomain (GETTEXT_PACKAGE, tmp);
2006 g_free (tmp);
2007 #else
2008 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2009 #endif
2011 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2012 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2013 #endif
2015 ret = 1;
2016 completion_cur = NULL;
2017 completion_prev = NULL;
2019 if (argc < 2)
2021 usage (&argc, &argv, FALSE);
2022 goto out;
2025 request_completion = FALSE;
2027 //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
2029 again:
2030 command = argv[1];
2031 if (g_strcmp0 (command, "help") == 0)
2033 if (request_completion)
2035 /* do nothing */
2037 else
2039 usage (&argc, &argv, TRUE);
2040 ret = 0;
2042 goto out;
2044 else if (g_strcmp0 (command, "emit") == 0)
2046 if (handle_emit (&argc,
2047 &argv,
2048 request_completion,
2049 completion_cur,
2050 completion_prev))
2051 ret = 0;
2052 goto out;
2054 else if (g_strcmp0 (command, "call") == 0)
2056 if (handle_call (&argc,
2057 &argv,
2058 request_completion,
2059 completion_cur,
2060 completion_prev))
2061 ret = 0;
2062 goto out;
2064 else if (g_strcmp0 (command, "introspect") == 0)
2066 if (handle_introspect (&argc,
2067 &argv,
2068 request_completion,
2069 completion_cur,
2070 completion_prev))
2071 ret = 0;
2072 goto out;
2074 else if (g_strcmp0 (command, "monitor") == 0)
2076 if (handle_monitor (&argc,
2077 &argv,
2078 request_completion,
2079 completion_cur,
2080 completion_prev))
2081 ret = 0;
2082 goto out;
2084 else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2086 const gchar *completion_line;
2087 gchar **completion_argv;
2088 gint completion_argc;
2089 gint completion_point;
2090 gchar *endp;
2091 gint cur_begin;
2093 request_completion = TRUE;
2095 completion_line = argv[2];
2096 completion_point = strtol (argv[3], &endp, 10);
2097 if (endp == argv[3] || *endp != '\0')
2098 goto out;
2100 #if 0
2101 completion_debug ("completion_point=%d", completion_point);
2102 completion_debug ("----");
2103 completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2104 completion_debug ("'%s'", completion_line);
2105 completion_debug (" %*s^",
2106 completion_point, "");
2107 completion_debug ("----");
2108 #endif
2110 if (!g_shell_parse_argv (completion_line,
2111 &completion_argc,
2112 &completion_argv,
2113 NULL))
2115 /* it's very possible the command line can't be parsed (for
2116 * example, missing quotes etc) - in that case, we just
2117 * don't autocomplete at all
2119 goto out;
2122 /* compute cur and prev */
2123 completion_prev = NULL;
2124 completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2125 if (cur_begin > 0)
2127 gint prev_end;
2128 for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2130 if (!g_ascii_isspace (completion_line[prev_end]))
2132 completion_prev = pick_word_at (completion_line, prev_end, NULL);
2133 break;
2137 #if 0
2138 completion_debug (" cur='%s'", completion_cur);
2139 completion_debug ("prev='%s'", completion_prev);
2140 #endif
2142 argc = completion_argc;
2143 argv = completion_argv;
2145 ret = 0;
2147 goto again;
2149 else
2151 if (request_completion)
2153 g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2154 ret = 0;
2155 goto out;
2157 else
2159 g_printerr ("Unknown command '%s'\n", command);
2160 usage (&argc, &argv, FALSE);
2161 goto out;
2165 out:
2166 g_free (completion_cur);
2167 g_free (completion_prev);
2168 return ret;