Imported Upstream version 2.66.6
[platform/upstream/glib.git] / gio / gdbus-tool.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
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.
14  *
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/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <locale.h>
27
28 #include <gio/gio.h>
29
30 #include <gi18n.h>
31
32 #ifdef G_OS_WIN32
33 #include "glib/glib-private.h"
34 #include "gdbusprivate.h"
35 #endif
36
37 /* ---------------------------------------------------------------------------------------------------- */
38
39 /* Escape values for console colors */
40 #define UNDERLINE     "\033[4m"
41 #define BLUE          "\033[34m"
42 #define CYAN          "\033[36m"
43 #define GREEN         "\033[32m"
44 #define MAGENTA       "\033[35m"
45 #define RED           "\033[31m"
46 #define YELLOW        "\033[33m"
47
48 /* ---------------------------------------------------------------------------------------------------- */
49
50 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
51
52 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
53  * to not have it interfere with stdout/stderr)
54  */
55 #if 0
56 G_GNUC_UNUSED static void
57 completion_debug (const gchar *format, ...)
58 {
59   va_list var_args;
60   gchar *s;
61   static FILE *f = NULL;
62
63   va_start (var_args, format);
64   s = g_strdup_vprintf (format, var_args);
65   if (f == NULL)
66     {
67       f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
68     }
69   fprintf (f, "%s\n", s);
70   g_free (s);
71 }
72 #else
73 static void
74 completion_debug (const gchar *format, ...)
75 {
76 }
77 #endif
78
79 /* ---------------------------------------------------------------------------------------------------- */
80
81
82 static void
83 remove_arg (gint num, gint *argc, gchar **argv[])
84 {
85   gint n;
86
87   g_assert (num <= (*argc));
88
89   for (n = num; (*argv)[n] != NULL; n++)
90     (*argv)[n] = (*argv)[n+1];
91   (*argv)[n] = NULL;
92   (*argc) = (*argc) - 1;
93 }
94
95 static void
96 usage (gint *argc, gchar **argv[], gboolean use_stdout)
97 {
98   GOptionContext *o;
99   gchar *s;
100   gchar *program_name;
101
102   o = g_option_context_new (_("COMMAND"));
103   g_option_context_set_help_enabled (o, FALSE);
104   /* Ignore parsing result */
105   g_option_context_parse (o, argc, argv, NULL);
106   program_name = g_path_get_basename ((*argv)[0]);
107   s = g_strdup_printf (_("Commands:\n"
108                          "  help         Shows this information\n"
109                          "  introspect   Introspect a remote object\n"
110                          "  monitor      Monitor a remote object\n"
111                          "  call         Invoke a method on a remote object\n"
112                          "  emit         Emit a signal\n"
113                          "  wait         Wait for a bus name to appear\n"
114                          "\n"
115                          "Use “%s COMMAND --help” to get help on each command.\n"),
116                        program_name);
117   g_free (program_name);
118   g_option_context_set_description (o, s);
119   g_free (s);
120   s = g_option_context_get_help (o, FALSE, NULL);
121   if (use_stdout)
122     g_print ("%s", s);
123   else
124     g_printerr ("%s", s);
125   g_free (s);
126   g_option_context_free (o);
127 }
128
129 static void
130 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
131 {
132   gchar *s;
133   gchar *program_name;
134
135   /* TODO:
136    *  1. get a g_set_prgname() ?; or
137    *  2. save old argv[0] and restore later
138    */
139
140   g_assert (g_strcmp0 ((*argv)[1], command) == 0);
141   remove_arg (1, argc, argv);
142
143   program_name = g_path_get_basename ((*argv)[0]);
144   s = g_strdup_printf ("%s %s", (*argv)[0], command);
145   (*argv)[0] = s;
146   g_free (program_name);
147 }
148
149 static GOptionContext *
150 command_option_context_new (const gchar        *parameter_string,
151                             const gchar        *summary,
152                             const GOptionEntry *entries,
153                             gboolean            request_completion)
154 {
155   GOptionContext *o = NULL;
156
157   o = g_option_context_new (parameter_string);
158   if (request_completion)
159     g_option_context_set_ignore_unknown_options (o, TRUE);
160   g_option_context_set_help_enabled (o, FALSE);
161   g_option_context_set_summary (o, summary);
162   g_option_context_add_main_entries (o, entries, GETTEXT_PACKAGE);
163
164   return g_steal_pointer (&o);
165 }
166
167 /* ---------------------------------------------------------------------------------------------------- */
168
169 static void
170 print_methods_and_signals (GDBusConnection *c,
171                            const gchar     *name,
172                            const gchar     *path,
173                            gboolean         print_methods,
174                            gboolean         print_signals)
175 {
176   GVariant *result;
177   GError *error;
178   const gchar *xml_data;
179   GDBusNodeInfo *node;
180   guint n;
181   guint m;
182
183   error = NULL;
184   result = g_dbus_connection_call_sync (c,
185                                         name,
186                                         path,
187                                         "org.freedesktop.DBus.Introspectable",
188                                         "Introspect",
189                                         NULL,
190                                         G_VARIANT_TYPE ("(s)"),
191                                         G_DBUS_CALL_FLAGS_NONE,
192                                         3000, /* 3 secs */
193                                         NULL,
194                                         &error);
195   if (result == NULL)
196     {
197       g_printerr (_("Error: %s\n"), error->message);
198       g_error_free (error);
199       goto out;
200     }
201   g_variant_get (result, "(&s)", &xml_data);
202
203   error = NULL;
204   node = g_dbus_node_info_new_for_xml (xml_data, &error);
205   g_variant_unref (result);
206   if (node == NULL)
207     {
208       g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
209       g_error_free (error);
210       goto out;
211     }
212
213   for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
214     {
215       const GDBusInterfaceInfo *iface = node->interfaces[n];
216       for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++)
217         {
218           const GDBusMethodInfo *method = iface->methods[m];
219           g_print ("%s.%s \n", iface->name, method->name);
220         }
221       for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++)
222         {
223           const GDBusSignalInfo *signal = iface->signals[m];
224           g_print ("%s.%s \n", iface->name, signal->name);
225         }
226     }
227   g_dbus_node_info_unref (node);
228
229  out:
230   ;
231 }
232
233 static void
234 print_paths (GDBusConnection *c,
235              const gchar *name,
236              const gchar *path)
237 {
238   GVariant *result;
239   GError *error;
240   const gchar *xml_data;
241   GDBusNodeInfo *node;
242   guint n;
243
244   if (!g_dbus_is_name (name))
245     {
246       g_printerr (_("Error: %s is not a valid name\n"), name);
247       goto out;
248     }
249
250   error = NULL;
251   result = g_dbus_connection_call_sync (c,
252                                         name,
253                                         path,
254                                         "org.freedesktop.DBus.Introspectable",
255                                         "Introspect",
256                                         NULL,
257                                         G_VARIANT_TYPE ("(s)"),
258                                         G_DBUS_CALL_FLAGS_NONE,
259                                         3000, /* 3 secs */
260                                         NULL,
261                                         &error);
262   if (result == NULL)
263     {
264       g_printerr (_("Error: %s\n"), error->message);
265       g_error_free (error);
266       goto out;
267     }
268   g_variant_get (result, "(&s)", &xml_data);
269
270   //g_printerr ("xml='%s'", xml_data);
271
272   error = NULL;
273   node = g_dbus_node_info_new_for_xml (xml_data, &error);
274   g_variant_unref (result);
275   if (node == NULL)
276     {
277       g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
278       g_error_free (error);
279       goto out;
280     }
281
282   //g_printerr ("bar '%s'\n", path);
283
284   if (node->interfaces != NULL)
285     g_print ("%s \n", path);
286
287   for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
288     {
289       gchar *s;
290
291       //g_printerr ("foo '%s'\n", node->nodes[n].path);
292
293       if (g_strcmp0 (path, "/") == 0)
294         s = g_strdup_printf ("/%s", node->nodes[n]->path);
295       else
296         s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
297
298       print_paths (c, name, s);
299
300       g_free (s);
301     }
302   g_dbus_node_info_unref (node);
303
304  out:
305   ;
306 }
307
308 static void
309 print_names (GDBusConnection *c,
310              gboolean         include_unique_names)
311 {
312   GVariant *result;
313   GError *error;
314   GVariantIter *iter;
315   gchar *str;
316   GHashTable *name_set;
317   GList *keys;
318   GList *l;
319
320   name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
321
322   error = NULL;
323   result = g_dbus_connection_call_sync (c,
324                                         "org.freedesktop.DBus",
325                                         "/org/freedesktop/DBus",
326                                         "org.freedesktop.DBus",
327                                         "ListNames",
328                                         NULL,
329                                         G_VARIANT_TYPE ("(as)"),
330                                         G_DBUS_CALL_FLAGS_NONE,
331                                         3000, /* 3 secs */
332                                         NULL,
333                                         &error);
334   if (result == NULL)
335     {
336       g_printerr (_("Error: %s\n"), error->message);
337       g_error_free (error);
338       goto out;
339     }
340   g_variant_get (result, "(as)", &iter);
341   while (g_variant_iter_loop (iter, "s", &str))
342     g_hash_table_add (name_set, g_strdup (str));
343   g_variant_iter_free (iter);
344   g_variant_unref (result);
345
346   error = NULL;
347   result = g_dbus_connection_call_sync (c,
348                                         "org.freedesktop.DBus",
349                                         "/org/freedesktop/DBus",
350                                         "org.freedesktop.DBus",
351                                         "ListActivatableNames",
352                                         NULL,
353                                         G_VARIANT_TYPE ("(as)"),
354                                         G_DBUS_CALL_FLAGS_NONE,
355                                         3000, /* 3 secs */
356                                         NULL,
357                                         &error);
358   if (result == NULL)
359     {
360       g_printerr (_("Error: %s\n"), error->message);
361       g_error_free (error);
362       goto out;
363     }
364   g_variant_get (result, "(as)", &iter);
365   while (g_variant_iter_loop (iter, "s", &str))
366     g_hash_table_add (name_set, g_strdup (str));
367   g_variant_iter_free (iter);
368   g_variant_unref (result);
369
370   keys = g_hash_table_get_keys (name_set);
371   keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
372   for (l = keys; l != NULL; l = l->next)
373     {
374       const gchar *name = l->data;
375       if (!include_unique_names && g_str_has_prefix (name, ":"))
376         continue;
377
378       g_print ("%s \n", name);
379     }
380   g_list_free (keys);
381
382  out:
383   g_hash_table_unref (name_set);
384 }
385
386 /* ---------------------------------------------------------------------------------------------------- */
387
388 static gboolean  opt_connection_system  = FALSE;
389 static gboolean  opt_connection_session = FALSE;
390 static gchar    *opt_connection_address = NULL;
391
392 static const GOptionEntry connection_entries[] =
393 {
394   { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
395   { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
396   { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
397   { NULL }
398 };
399
400 static GOptionGroup *
401 connection_get_group (void)
402 {
403   static GOptionGroup *g;
404
405   g = g_option_group_new ("connection",
406                           N_("Connection Endpoint Options:"),
407                           N_("Options specifying the connection endpoint"),
408                           NULL,
409                           NULL);
410   g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
411   g_option_group_add_entries (g, connection_entries);
412
413   return g;
414 }
415
416 static GDBusConnection *
417 connection_get_dbus_connection (gboolean   require_message_bus,
418                                 GError   **error)
419 {
420   GDBusConnection *c;
421
422   c = NULL;
423
424   /* First, ensure we have exactly one connect */
425   if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
426     {
427       g_set_error (error,
428                    G_IO_ERROR,
429                    G_IO_ERROR_FAILED,
430                    _("No connection endpoint specified"));
431       goto out;
432     }
433   else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
434            (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
435            (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
436     {
437       g_set_error (error,
438                    G_IO_ERROR,
439                    G_IO_ERROR_FAILED,
440                    _("Multiple connection endpoints specified"));
441       goto out;
442     }
443
444   if (opt_connection_system)
445     {
446       c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
447     }
448   else if (opt_connection_session)
449     {
450       c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
451     }
452   else if (opt_connection_address != NULL)
453     {
454       GDBusConnectionFlags flags = G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT;
455       if (require_message_bus)
456         flags |= G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION;
457       c = g_dbus_connection_new_for_address_sync (opt_connection_address,
458                                                   flags,
459                                                   NULL, /* GDBusAuthObserver */
460                                                   NULL, /* GCancellable */
461                                                   error);
462     }
463
464  out:
465   return c;
466 }
467
468 /* ---------------------------------------------------------------------------------------------------- */
469
470 static GPtrArray *
471 call_helper_get_method_in_signature (GDBusConnection  *c,
472                                      const gchar      *dest,
473                                      const gchar      *path,
474                                      const gchar      *interface_name,
475                                      const gchar      *method_name,
476                                      GError          **error)
477 {
478   GPtrArray *ret;
479   GVariant *result;
480   GDBusNodeInfo *node_info;
481   const gchar *xml_data;
482   GDBusInterfaceInfo *interface_info;
483   GDBusMethodInfo *method_info;
484   guint n;
485
486   ret = NULL;
487   result = NULL;
488   node_info = NULL;
489
490   result = g_dbus_connection_call_sync (c,
491                                         dest,
492                                         path,
493                                         "org.freedesktop.DBus.Introspectable",
494                                         "Introspect",
495                                         NULL,
496                                         G_VARIANT_TYPE ("(s)"),
497                                         G_DBUS_CALL_FLAGS_NONE,
498                                         3000, /* 3 secs */
499                                         NULL,
500                                         error);
501   if (result == NULL)
502     goto out;
503
504   g_variant_get (result, "(&s)", &xml_data);
505   node_info = g_dbus_node_info_new_for_xml (xml_data, error);
506   if (node_info == NULL)
507       goto out;
508
509   interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
510   if (interface_info == NULL)
511     {
512       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
513                    _("Warning: According to introspection data, interface “%s” does not exist\n"),
514                    interface_name);
515       goto out;
516     }
517
518   method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
519   if (method_info == NULL)
520     {
521       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
522                    _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"),
523                    method_name,
524                    interface_name);
525       goto out;
526     }
527
528   ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
529   for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
530     {
531       g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
532     }
533
534  out:
535   if (node_info != NULL)
536     g_dbus_node_info_unref (node_info);
537   if (result != NULL)
538     g_variant_unref (result);
539
540   return ret;
541 }
542
543 /* ---------------------------------------------------------------------------------------------------- */
544
545 static GVariant *
546 _g_variant_parse_me_harder (GVariantType   *type,
547                             const gchar    *given_str,
548                             GError        **error)
549 {
550   GVariant *value;
551   gchar *s;
552   guint n;
553   GString *str;
554
555   str = g_string_new ("\"");
556   for (n = 0; given_str[n] != '\0'; n++)
557     {
558       if (G_UNLIKELY (given_str[n] == '\"'))
559         g_string_append (str, "\\\"");
560       else
561         g_string_append_c (str, given_str[n]);
562     }
563   g_string_append_c (str, '"');
564   s = g_string_free (str, FALSE);
565
566   value = g_variant_parse (type,
567                            s,
568                            NULL,
569                            NULL,
570                            error);
571   g_free (s);
572
573   return value;
574 }
575
576 /* ---------------------------------------------------------------------------------------------------- */
577
578 static gchar *opt_emit_dest = NULL;
579 static gchar *opt_emit_object_path = NULL;
580 static gchar *opt_emit_signal = NULL;
581
582 static const GOptionEntry emit_entries[] =
583 {
584   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
585   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
586   { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
587   { NULL }
588 };
589
590 static gboolean
591 handle_emit (gint        *argc,
592              gchar      **argv[],
593              gboolean     request_completion,
594              const gchar *completion_cur,
595              const gchar *completion_prev)
596 {
597   gint ret;
598   GOptionContext *o;
599   gchar *s;
600   GError *error;
601   GDBusConnection *c;
602   GVariant *parameters;
603   gchar *interface_name;
604   gchar *signal_name;
605   GVariantBuilder builder;
606   gboolean skip_dashes;
607   guint parm;
608   guint n;
609   gboolean complete_names, complete_paths, complete_signals;
610
611   ret = FALSE;
612   c = NULL;
613   parameters = NULL;
614   interface_name = NULL;
615   signal_name = NULL;
616
617   modify_argv0_for_command (argc, argv, "emit");
618
619   o = command_option_context_new (NULL, _("Emit a signal."),
620                                   emit_entries, request_completion);
621   g_option_context_add_group (o, connection_get_group ());
622
623   complete_names = FALSE;
624   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
625     {
626       complete_names = TRUE;
627       remove_arg ((*argc) - 1, argc, argv);
628     }
629
630   complete_paths = FALSE;
631   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
632     {
633       complete_paths = TRUE;
634       remove_arg ((*argc) - 1, argc, argv);
635     }
636
637   complete_signals = FALSE;
638   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0)
639     {
640       complete_signals = TRUE;
641       remove_arg ((*argc) - 1, argc, argv);
642     }
643
644   if (!g_option_context_parse (o, argc, argv, NULL))
645     {
646       if (!request_completion)
647         {
648           s = g_option_context_get_help (o, FALSE, NULL);
649           g_printerr ("%s", s);
650           g_free (s);
651           goto out;
652         }
653     }
654
655   error = NULL;
656   c = connection_get_dbus_connection ((opt_emit_dest != NULL), &error);
657   if (c == NULL)
658     {
659       if (request_completion)
660         {
661           if (g_strcmp0 (completion_prev, "--address") == 0)
662             {
663               g_print ("unix:\n"
664                        "tcp:\n"
665                        "nonce-tcp:\n");
666             }
667           else
668             {
669               g_print ("--system \n--session \n--address \n");
670             }
671         }
672       else
673         {
674           g_printerr (_("Error connecting: %s\n"), error->message);
675           g_error_free (error);
676         }
677       goto out;
678     }
679
680   /* validate and complete destination (bus name) */
681   if (complete_names)
682     {
683       print_names (c, FALSE);
684       goto out;
685     }
686   if (request_completion && opt_emit_dest != NULL && g_strcmp0 ("--dest", completion_prev) == 0)
687     {
688       print_names (c, g_str_has_prefix (opt_emit_dest, ":"));
689       goto out;
690     }
691
692   if (!request_completion && opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
693     {
694       g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
695       goto out;
696     }
697
698   if (opt_emit_dest == NULL && opt_emit_object_path == NULL && request_completion)
699     {
700       g_print ("--dest \n");
701     }
702   /* validate and complete object path */
703   if (opt_emit_dest != NULL && complete_paths)
704     {
705       print_paths (c, opt_emit_dest, "/");
706       goto out;
707     }
708   if (opt_emit_object_path == NULL)
709     {
710       if (request_completion)
711         g_print ("--object-path \n");
712       else
713         g_printerr (_("Error: Object path is not specified\n"));
714       goto out;
715     }
716   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
717     {
718       if (opt_emit_dest != NULL)
719         {
720           gchar *p;
721           s = g_strdup (opt_emit_object_path);
722           p = strrchr (s, '/');
723           if (p != NULL)
724             {
725               if (p == s)
726                 p++;
727               *p = '\0';
728             }
729           print_paths (c, opt_emit_dest, s);
730           g_free (s);
731         }
732       goto out;
733     }
734   if (!request_completion && !g_variant_is_object_path (opt_emit_object_path))
735     {
736       g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
737       goto out;
738     }
739
740   /* validate and complete signal (interface + signal name) */
741   if (opt_emit_dest != NULL && opt_emit_object_path != NULL && complete_signals)
742     {
743       print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
744       goto out;
745     }
746   if (opt_emit_signal == NULL)
747     {
748       /* don't keep repeatedly completing --signal */
749       if (request_completion)
750         {
751           if (g_strcmp0 ("--signal", completion_prev) != 0)
752             g_print ("--signal \n");
753         }
754       else
755         {
756           g_printerr (_("Error: Signal name is not specified\n"));
757         }
758
759       goto out;
760     }
761   if (request_completion && opt_emit_dest != NULL && opt_emit_object_path != NULL &&
762       g_strcmp0 ("--signal", completion_prev) == 0)
763     {
764       print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE);
765       goto out;
766     }
767   s = strrchr (opt_emit_signal, '.');
768   if (!request_completion && s == NULL)
769     {
770       g_printerr (_("Error: Signal name “%s” is invalid\n"), opt_emit_signal);
771       goto out;
772     }
773   signal_name = g_strdup (s + 1);
774   interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
775
776   /* All done with completion now */
777   if (request_completion)
778     goto out;
779
780   if (!g_dbus_is_interface_name (interface_name))
781     {
782       g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
783       goto out;
784     }
785
786   if (!g_dbus_is_member_name (signal_name))
787     {
788       g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
789       goto out;
790     }
791
792   /* Read parameters */
793   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
794   skip_dashes = TRUE;
795   parm = 0;
796   for (n = 1; n < (guint) *argc; n++)
797     {
798       GVariant *value;
799
800       /* Under certain conditions, g_option_context_parse returns the "--"
801          itself (setting off unparsed arguments), too: */
802       if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
803         {
804           skip_dashes = FALSE;
805           continue;
806         }
807
808       error = NULL;
809       value = g_variant_parse (NULL,
810                                (*argv)[n],
811                                NULL,
812                                NULL,
813                                &error);
814       if (value == NULL)
815         {
816           gchar *context;
817
818           context = g_variant_parse_error_print_context (error, (*argv)[n]);
819           g_error_free (error);
820           error = NULL;
821           value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
822           if (value == NULL)
823             {
824               /* Use the original non-"parse-me-harder" error */
825               g_printerr (_("Error parsing parameter %d: %s\n"),
826                           parm + 1,
827                           context);
828               g_error_free (error);
829               g_free (context);
830               g_variant_builder_clear (&builder);
831               goto out;
832             }
833           g_free (context);
834         }
835       g_variant_builder_add_value (&builder, value);
836       ++parm;
837     }
838   parameters = g_variant_builder_end (&builder);
839
840   if (parameters != NULL)
841     parameters = g_variant_ref_sink (parameters);
842   if (!g_dbus_connection_emit_signal (c,
843                                       opt_emit_dest,
844                                       opt_emit_object_path,
845                                       interface_name,
846                                       signal_name,
847                                       parameters,
848                                       &error))
849     {
850       g_printerr (_("Error: %s\n"), error->message);
851       g_error_free (error);
852       goto out;
853     }
854
855   if (!g_dbus_connection_flush_sync (c, NULL, &error))
856     {
857       g_printerr (_("Error flushing connection: %s\n"), error->message);
858       g_error_free (error);
859       goto out;
860     }
861
862   ret = TRUE;
863
864  out:
865   if (c != NULL)
866     g_object_unref (c);
867   if (parameters != NULL)
868     g_variant_unref (parameters);
869   g_free (interface_name);
870   g_free (signal_name);
871   g_option_context_free (o);
872   return ret;
873 }
874
875 /* ---------------------------------------------------------------------------------------------------- */
876
877 static gchar *opt_call_dest = NULL;
878 static gchar *opt_call_object_path = NULL;
879 static gchar *opt_call_method = NULL;
880 static gint opt_call_timeout = -1;
881
882 static const GOptionEntry call_entries[] =
883 {
884   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
885   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
886   { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
887   { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
888   { NULL }
889 };
890
891 static gboolean
892 handle_call (gint        *argc,
893              gchar      **argv[],
894              gboolean     request_completion,
895              const gchar *completion_cur,
896              const gchar *completion_prev)
897 {
898   gint ret;
899   GOptionContext *o;
900   gchar *s;
901   GError *error;
902   GDBusConnection *c;
903   GVariant *parameters;
904   gchar *interface_name;
905   gchar *method_name;
906   GVariant *result;
907   GPtrArray *in_signature_types;
908   gboolean complete_names;
909   gboolean complete_paths;
910   gboolean complete_methods;
911   GVariantBuilder builder;
912   gboolean skip_dashes;
913   guint parm;
914   guint n;
915
916   ret = FALSE;
917   c = NULL;
918   parameters = NULL;
919   interface_name = NULL;
920   method_name = NULL;
921   result = NULL;
922   in_signature_types = NULL;
923
924   modify_argv0_for_command (argc, argv, "call");
925
926   o = command_option_context_new (NULL, _("Invoke a method on a remote object."),
927                                   call_entries, request_completion);
928   g_option_context_add_group (o, connection_get_group ());
929
930   complete_names = FALSE;
931   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
932     {
933       complete_names = TRUE;
934       remove_arg ((*argc) - 1, argc, argv);
935     }
936
937   complete_paths = FALSE;
938   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
939     {
940       complete_paths = TRUE;
941       remove_arg ((*argc) - 1, argc, argv);
942     }
943
944   complete_methods = FALSE;
945   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
946     {
947       complete_methods = TRUE;
948       remove_arg ((*argc) - 1, argc, argv);
949     }
950
951   if (!g_option_context_parse (o, argc, argv, NULL))
952     {
953       if (!request_completion)
954         {
955           s = g_option_context_get_help (o, FALSE, NULL);
956           g_printerr ("%s", s);
957           g_free (s);
958           goto out;
959         }
960     }
961
962   error = NULL;
963   c = connection_get_dbus_connection (TRUE, &error);
964   if (c == NULL)
965     {
966       if (request_completion)
967         {
968           if (g_strcmp0 (completion_prev, "--address") == 0)
969             {
970               g_print ("unix:\n"
971                        "tcp:\n"
972                        "nonce-tcp:\n");
973             }
974           else
975             {
976               g_print ("--system \n--session \n--address \n");
977             }
978         }
979       else
980         {
981           g_printerr (_("Error connecting: %s\n"), error->message);
982           g_error_free (error);
983         }
984       goto out;
985     }
986
987   /* validate and complete destination (bus name) */
988   if (complete_names)
989     {
990       print_names (c, FALSE);
991       goto out;
992     }
993   if (opt_call_dest == NULL)
994     {
995       if (request_completion)
996         g_print ("--dest \n");
997       else
998         g_printerr (_("Error: Destination is not specified\n"));
999       goto out;
1000     }
1001   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1002     {
1003       print_names (c, g_str_has_prefix (opt_call_dest, ":"));
1004       goto out;
1005     }
1006
1007   if (!request_completion && !g_dbus_is_name (opt_call_dest))
1008     {
1009       g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest);
1010       goto out;
1011     }
1012
1013   /* validate and complete object path */
1014   if (complete_paths)
1015     {
1016       print_paths (c, opt_call_dest, "/");
1017       goto out;
1018     }
1019   if (opt_call_object_path == NULL)
1020     {
1021       if (request_completion)
1022         g_print ("--object-path \n");
1023       else
1024         g_printerr (_("Error: Object path is not specified\n"));
1025       goto out;
1026     }
1027   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1028     {
1029       gchar *p;
1030       s = g_strdup (opt_call_object_path);
1031       p = strrchr (s, '/');
1032       if (p != NULL)
1033         {
1034           if (p == s)
1035             p++;
1036           *p = '\0';
1037         }
1038       print_paths (c, opt_call_dest, s);
1039       g_free (s);
1040       goto out;
1041     }
1042   if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
1043     {
1044       g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
1045       goto out;
1046     }
1047
1048   /* validate and complete method (interface + method name) */
1049   if (complete_methods)
1050     {
1051       print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1052       goto out;
1053     }
1054   if (opt_call_method == NULL)
1055     {
1056       if (request_completion)
1057         g_print ("--method \n");
1058       else
1059         g_printerr (_("Error: Method name is not specified\n"));
1060       goto out;
1061     }
1062   if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
1063     {
1064       print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE);
1065       goto out;
1066     }
1067   s = strrchr (opt_call_method, '.');
1068   if (!request_completion && s == NULL)
1069     {
1070       g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method);
1071       goto out;
1072     }
1073   method_name = g_strdup (s + 1);
1074   interface_name = g_strndup (opt_call_method, s - opt_call_method);
1075
1076   /* All done with completion now */
1077   if (request_completion)
1078     goto out;
1079
1080   /* Introspect, for easy conversion - it's not fatal if we can't do this */
1081   in_signature_types = call_helper_get_method_in_signature (c,
1082                                                             opt_call_dest,
1083                                                             opt_call_object_path,
1084                                                             interface_name,
1085                                                             method_name,
1086                                                             &error);
1087   if (in_signature_types == NULL)
1088     {
1089       //g_printerr ("Error getting introspection data: %s\n", error->message);
1090       g_error_free (error);
1091       error = NULL;
1092     }
1093
1094   /* Read parameters */
1095   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
1096   skip_dashes = TRUE;
1097   parm = 0;
1098   for (n = 1; n < (guint) *argc; n++)
1099     {
1100       GVariant *value;
1101       GVariantType *type;
1102
1103       /* Under certain conditions, g_option_context_parse returns the "--"
1104          itself (setting off unparsed arguments), too: */
1105       if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0)
1106         {
1107           skip_dashes = FALSE;
1108           continue;
1109         }
1110
1111       type = NULL;
1112       if (in_signature_types != NULL)
1113         {
1114           if (parm >= in_signature_types->len)
1115             {
1116               /* Only warn for the first param */
1117               if (parm == in_signature_types->len)
1118                 {
1119                   g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
1120                               in_signature_types->len);
1121                 }
1122             }
1123           else
1124             {
1125               type = in_signature_types->pdata[parm];
1126             }
1127         }
1128
1129       error = NULL;
1130       value = g_variant_parse (type,
1131                                (*argv)[n],
1132                                NULL,
1133                                NULL,
1134                                &error);
1135       if (value == NULL)
1136         {
1137           gchar *context;
1138
1139           context = g_variant_parse_error_print_context (error, (*argv)[n]);
1140           g_error_free (error);
1141           error = NULL;
1142           value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
1143           if (value == NULL)
1144             {
1145               if (type != NULL)
1146                 {
1147                   s = g_variant_type_dup_string (type);
1148                   g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"),
1149                               parm + 1,
1150                               s,
1151                               context);
1152                   g_free (s);
1153                 }
1154               else
1155                 {
1156                   g_printerr (_("Error parsing parameter %d: %s\n"),
1157                               parm + 1,
1158                               context);
1159                 }
1160               g_error_free (error);
1161               g_variant_builder_clear (&builder);
1162               g_free (context);
1163               goto out;
1164             }
1165           g_free (context);
1166         }
1167       g_variant_builder_add_value (&builder, value);
1168       ++parm;
1169     }
1170   parameters = g_variant_builder_end (&builder);
1171
1172   if (parameters != NULL)
1173     parameters = g_variant_ref_sink (parameters);
1174   result = g_dbus_connection_call_sync (c,
1175                                         opt_call_dest,
1176                                         opt_call_object_path,
1177                                         interface_name,
1178                                         method_name,
1179                                         parameters,
1180                                         NULL,
1181                                         G_DBUS_CALL_FLAGS_NONE,
1182                                         opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1183                                         NULL,
1184                                         &error);
1185   if (result == NULL)
1186     {
1187       g_printerr (_("Error: %s\n"), error->message);
1188
1189       if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL)
1190         {
1191           if (in_signature_types->len > 0)
1192             {
1193               GString *s;
1194               s = g_string_new (NULL);
1195
1196               for (n = 0; n < in_signature_types->len; n++)
1197                 {
1198                   GVariantType *type = in_signature_types->pdata[n];
1199                   g_string_append_len (s,
1200                                        g_variant_type_peek_string (type),
1201                                        g_variant_type_get_string_length (type));
1202                 }
1203
1204               g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1205               g_string_free (s, TRUE);
1206             }
1207           else
1208             g_printerr ("(According to introspection data, you need to pass no arguments)\n");
1209         }
1210
1211       g_error_free (error);
1212       goto out;
1213     }
1214
1215   s = g_variant_print (result, TRUE);
1216   g_print ("%s\n", s);
1217   g_free (s);
1218
1219   ret = TRUE;
1220
1221  out:
1222   if (in_signature_types != NULL)
1223     g_ptr_array_unref (in_signature_types);
1224   if (result != NULL)
1225     g_variant_unref (result);
1226   if (c != NULL)
1227     g_object_unref (c);
1228   if (parameters != NULL)
1229     g_variant_unref (parameters);
1230   g_free (interface_name);
1231   g_free (method_name);
1232   g_option_context_free (o);
1233   return ret;
1234 }
1235
1236 /* ---------------------------------------------------------------------------------------------------- */
1237
1238 static gchar *opt_introspect_dest = NULL;
1239 static gchar *opt_introspect_object_path = NULL;
1240 static gboolean opt_introspect_xml = FALSE;
1241 static gboolean opt_introspect_recurse = FALSE;
1242 static gboolean opt_introspect_only_properties = FALSE;
1243
1244 /* Introspect colors */
1245 #define RESET_COLOR                 (use_colors? "\033[0m": "")
1246 #define INTROSPECT_TITLE_COLOR      (use_colors? UNDERLINE: "")
1247 #define INTROSPECT_NODE_COLOR       (use_colors? RESET_COLOR: "")
1248 #define INTROSPECT_INTERFACE_COLOR  (use_colors? YELLOW: "")
1249 #define INTROSPECT_METHOD_COLOR     (use_colors? BLUE: "")
1250 #define INTROSPECT_SIGNAL_COLOR     (use_colors? BLUE: "")
1251 #define INTROSPECT_PROPERTY_COLOR   (use_colors? MAGENTA: "")
1252 #define INTROSPECT_INOUT_COLOR      (use_colors? RESET_COLOR: "")
1253 #define INTROSPECT_TYPE_COLOR       (use_colors? GREEN: "")
1254 #define INTROSPECT_ANNOTATION_COLOR (use_colors? RESET_COLOR: "")
1255
1256 static void
1257 dump_annotation (const GDBusAnnotationInfo *o,
1258                  guint indent,
1259                  gboolean ignore_indent,
1260                  gboolean use_colors)
1261 {
1262   guint n;
1263   g_print ("%*s%s@%s(\"%s\")%s\n",
1264            ignore_indent ? 0 : indent, "",
1265            INTROSPECT_ANNOTATION_COLOR, o->key, o->value, RESET_COLOR);
1266   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1267     dump_annotation (o->annotations[n], indent + 2, FALSE, use_colors);
1268 }
1269
1270 static void
1271 dump_arg (const GDBusArgInfo *o,
1272           guint indent,
1273           const gchar *direction,
1274           gboolean ignore_indent,
1275           gboolean include_newline,
1276           gboolean use_colors)
1277 {
1278   guint n;
1279
1280   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1281     {
1282       dump_annotation (o->annotations[n], indent, ignore_indent, use_colors);
1283       ignore_indent = FALSE;
1284     }
1285
1286   g_print ("%*s%s%s%s%s%s%s %s%s",
1287            ignore_indent ? 0 : indent, "",
1288            INTROSPECT_INOUT_COLOR, direction, RESET_COLOR,
1289            INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1290            o->name,
1291            include_newline ? ",\n" : "");
1292 }
1293
1294 static guint
1295 count_args (GDBusArgInfo **args)
1296 {
1297   guint n;
1298   n = 0;
1299   if (args == NULL)
1300     goto out;
1301   while (args[n] != NULL)
1302     n++;
1303  out:
1304   return n;
1305 }
1306
1307 static void
1308 dump_method (const GDBusMethodInfo *o,
1309              guint                  indent,
1310              gboolean               use_colors)
1311 {
1312   guint n;
1313   guint m;
1314   guint name_len;
1315   guint total_num_args;
1316
1317   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1318     dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1319
1320   g_print ("%*s%s%s%s(",
1321            indent, "",
1322            INTROSPECT_METHOD_COLOR, o->name, RESET_COLOR);
1323   name_len = strlen (o->name);
1324   total_num_args = count_args (o->in_args) + count_args (o->out_args);
1325   for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1326     {
1327       gboolean ignore_indent = (m == 0);
1328       gboolean include_newline = (m != total_num_args - 1);
1329
1330       dump_arg (o->in_args[n],
1331                 indent + name_len + 1,
1332                 "in  ",
1333                 ignore_indent,
1334                 include_newline,
1335                 use_colors);
1336     }
1337   for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1338     {
1339       gboolean ignore_indent = (m == 0);
1340       gboolean include_newline = (m != total_num_args - 1);
1341       dump_arg (o->out_args[n],
1342                 indent + name_len + 1,
1343                 "out ",
1344                 ignore_indent,
1345                 include_newline,
1346                 use_colors);
1347     }
1348   g_print (");\n");
1349 }
1350
1351 static void
1352 dump_signal (const GDBusSignalInfo *o,
1353              guint                  indent,
1354              gboolean               use_colors)
1355 {
1356   guint n;
1357   guint name_len;
1358   guint total_num_args;
1359
1360   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1361     dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1362
1363   g_print ("%*s%s%s%s(",
1364            indent, "",
1365            INTROSPECT_SIGNAL_COLOR, o->name, RESET_COLOR);
1366   name_len = strlen (o->name);
1367   total_num_args = count_args (o->args);
1368   for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1369     {
1370       gboolean ignore_indent = (n == 0);
1371       gboolean include_newline = (n != total_num_args - 1);
1372       dump_arg (o->args[n],
1373                 indent + name_len + 1,
1374                 "",
1375                 ignore_indent,
1376                 include_newline,
1377                 use_colors);
1378     }
1379   g_print (");\n");
1380 }
1381
1382 static void
1383 dump_property (const GDBusPropertyInfo *o,
1384                guint                    indent,
1385                gboolean                 use_colors,
1386                GVariant                *value)
1387 {
1388   const gchar *access;
1389   guint n;
1390
1391   if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1392     access = "readonly";
1393   else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1394     access = "writeonly";
1395   else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1396     access = "readwrite";
1397   else
1398     g_assert_not_reached ();
1399
1400   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1401     dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1402
1403   if (value != NULL)
1404     {
1405       gchar *s = g_variant_print (value, FALSE);
1406       g_print ("%*s%s %s%s%s %s%s%s = %s;\n", indent, "", access,
1407                INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR,
1408                INTROSPECT_PROPERTY_COLOR, o->name, RESET_COLOR,
1409                s);
1410       g_free (s);
1411     }
1412   else
1413     {
1414       g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1415     }
1416 }
1417
1418 static void
1419 dump_interface (GDBusConnection          *c,
1420                 const gchar              *name,
1421                 const GDBusInterfaceInfo *o,
1422                 guint                     indent,
1423                 gboolean                  use_colors,
1424                 const gchar              *object_path)
1425 {
1426   guint n;
1427   GHashTable *properties;
1428
1429   properties = g_hash_table_new_full (g_str_hash,
1430                                       g_str_equal,
1431                                       g_free,
1432                                       (GDestroyNotify) g_variant_unref);
1433
1434   /* Try to get properties */
1435   if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1436     {
1437       GVariant *result;
1438       result = g_dbus_connection_call_sync (c,
1439                                             name,
1440                                             object_path,
1441                                             "org.freedesktop.DBus.Properties",
1442                                             "GetAll",
1443                                             g_variant_new ("(s)", o->name),
1444                                             NULL,
1445                                             G_DBUS_CALL_FLAGS_NONE,
1446                                             3000,
1447                                             NULL,
1448                                             NULL);
1449       if (result != NULL)
1450         {
1451           if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1452             {
1453               GVariantIter *iter;
1454               GVariant *item;
1455               g_variant_get (result,
1456                              "(a{sv})",
1457                              &iter);
1458               while ((item = g_variant_iter_next_value (iter)))
1459                 {
1460                   gchar *key;
1461                   GVariant *value;
1462                   g_variant_get (item,
1463                                  "{sv}",
1464                                  &key,
1465                                  &value);
1466
1467                   g_hash_table_insert (properties, key, g_variant_ref (value));
1468                 }
1469             }
1470           g_variant_unref (result);
1471         }
1472       else
1473         {
1474           guint n;
1475           for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1476             {
1477               result = g_dbus_connection_call_sync (c,
1478                                                     name,
1479                                                     object_path,
1480                                                     "org.freedesktop.DBus.Properties",
1481                                                     "Get",
1482                                                     g_variant_new ("(ss)", o->name, o->properties[n]->name),
1483                                                     G_VARIANT_TYPE ("(v)"),
1484                                                     G_DBUS_CALL_FLAGS_NONE,
1485                                                     3000,
1486                                                     NULL,
1487                                                     NULL);
1488               if (result != NULL)
1489                 {
1490                   GVariant *property_value;
1491                   g_variant_get (result,
1492                                  "(v)",
1493                                  &property_value);
1494                   g_hash_table_insert (properties,
1495                                        g_strdup (o->properties[n]->name),
1496                                        g_variant_ref (property_value));
1497                   g_variant_unref (result);
1498                 }
1499             }
1500         }
1501     }
1502
1503   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1504     dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1505
1506   g_print ("%*s%sinterface %s%s {\n",
1507            indent, "",
1508            INTROSPECT_INTERFACE_COLOR, o->name, RESET_COLOR);
1509   if (o->methods != NULL && !opt_introspect_only_properties)
1510     {
1511       g_print ("%*s  %smethods%s:\n",
1512                indent, "",
1513                INTROSPECT_TITLE_COLOR, RESET_COLOR);
1514       for (n = 0; o->methods[n] != NULL; n++)
1515         dump_method (o->methods[n], indent + 4, use_colors);
1516     }
1517   if (o->signals != NULL && !opt_introspect_only_properties)
1518     {
1519       g_print ("%*s  %ssignals%s:\n",
1520                indent, "",
1521                INTROSPECT_TITLE_COLOR, RESET_COLOR);
1522       for (n = 0; o->signals[n] != NULL; n++)
1523         dump_signal (o->signals[n], indent + 4, use_colors);
1524     }
1525   if (o->properties != NULL)
1526     {
1527       g_print ("%*s  %sproperties%s:\n",
1528                indent, "",
1529                INTROSPECT_TITLE_COLOR, RESET_COLOR);
1530       for (n = 0; o->properties[n] != NULL; n++)
1531         {
1532           dump_property (o->properties[n],
1533                          indent + 4,
1534                          use_colors,
1535                          g_hash_table_lookup (properties, (o->properties[n])->name));
1536         }
1537     }
1538   g_print ("%*s};\n",
1539            indent, "");
1540
1541   g_hash_table_unref (properties);
1542 }
1543
1544 static gboolean
1545 introspect_do (GDBusConnection *c,
1546                const gchar     *object_path,
1547                guint            indent,
1548                gboolean         use_colors);
1549
1550 static void
1551 dump_node (GDBusConnection      *c,
1552            const gchar          *name,
1553            const GDBusNodeInfo  *o,
1554            guint                 indent,
1555            gboolean              use_colors,
1556            const gchar          *object_path,
1557            gboolean              recurse)
1558 {
1559   guint n;
1560   const gchar *object_path_to_print;
1561
1562   object_path_to_print = object_path;
1563   if (o->path != NULL)
1564     object_path_to_print = o->path;
1565
1566   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1567     dump_annotation (o->annotations[n], indent, FALSE, use_colors);
1568
1569   g_print ("%*s%snode %s%s",
1570            indent, "",
1571            INTROSPECT_NODE_COLOR,
1572            object_path_to_print != NULL ? object_path_to_print : "(not set)",
1573            RESET_COLOR);
1574   if (o->interfaces != NULL || o->nodes != NULL)
1575     {
1576       g_print (" {\n");
1577       for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1578         {
1579           if (opt_introspect_only_properties)
1580             {
1581               if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1582                 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1583             }
1584           else
1585             {
1586               dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path);
1587             }
1588         }
1589       for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1590         {
1591           if (recurse)
1592             {
1593               gchar *child_path;
1594               if (g_variant_is_object_path (o->nodes[n]->path))
1595                 {
1596                   child_path = g_strdup (o->nodes[n]->path);
1597                   /* avoid infinite loops */
1598                   if (g_str_has_prefix (child_path, object_path))
1599                     {
1600                       introspect_do (c, child_path, indent + 2, use_colors);
1601                     }
1602                   else
1603                     {
1604                       g_print ("Skipping path %s that is not enclosed by parent %s\n",
1605                                child_path, object_path);
1606                     }
1607                 }
1608               else
1609                 {
1610                   if (g_strcmp0 (object_path, "/") == 0)
1611                     child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1612                   else
1613                     child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1614                   introspect_do (c, child_path, indent + 2, use_colors);
1615                 }
1616               g_free (child_path);
1617             }
1618           else
1619             {
1620               dump_node (NULL, NULL, o->nodes[n], indent + 2, use_colors, NULL, recurse);
1621             }
1622         }
1623       g_print ("%*s};\n",
1624                indent, "");
1625     }
1626   else
1627     {
1628       g_print ("\n");
1629     }
1630 }
1631
1632 static const GOptionEntry introspect_entries[] =
1633 {
1634   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1635   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1636   { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1637   { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1638   { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1639   { NULL }
1640 };
1641
1642 static gboolean
1643 introspect_do (GDBusConnection *c,
1644                const gchar     *object_path,
1645                guint            indent,
1646                gboolean         use_colors)
1647 {
1648   GError *error;
1649   GVariant *result;
1650   GDBusNodeInfo *node;
1651   gboolean ret;
1652   const gchar *xml_data;
1653
1654   ret = FALSE;
1655   node = NULL;
1656   result = NULL;
1657
1658   error = NULL;
1659   result = g_dbus_connection_call_sync (c,
1660                                         opt_introspect_dest,
1661                                         object_path,
1662                                         "org.freedesktop.DBus.Introspectable",
1663                                         "Introspect",
1664                                         NULL,
1665                                         G_VARIANT_TYPE ("(s)"),
1666                                         G_DBUS_CALL_FLAGS_NONE,
1667                                         3000, /* 3 sec */
1668                                         NULL,
1669                                         &error);
1670   if (result == NULL)
1671     {
1672       g_printerr (_("Error: %s\n"), error->message);
1673       g_error_free (error);
1674       goto out;
1675     }
1676   g_variant_get (result, "(&s)", &xml_data);
1677
1678   if (opt_introspect_xml)
1679     {
1680       g_print ("%s", xml_data);
1681     }
1682   else
1683     {
1684       error = NULL;
1685       node = g_dbus_node_info_new_for_xml (xml_data, &error);
1686       if (node == NULL)
1687         {
1688           g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1689           g_error_free (error);
1690           goto out;
1691         }
1692
1693       dump_node (c, opt_introspect_dest, node, indent, use_colors, object_path, opt_introspect_recurse);
1694     }
1695
1696   ret = TRUE;
1697
1698  out:
1699   if (node != NULL)
1700     g_dbus_node_info_unref (node);
1701   if (result != NULL)
1702     g_variant_unref (result);
1703   return ret;
1704 }
1705
1706 static gboolean
1707 handle_introspect (gint        *argc,
1708                    gchar      **argv[],
1709                    gboolean     request_completion,
1710                    const gchar *completion_cur,
1711                    const gchar *completion_prev)
1712 {
1713   gint ret;
1714   GOptionContext *o;
1715   gchar *s;
1716   GError *error;
1717   GDBusConnection *c;
1718   gboolean complete_names;
1719   gboolean complete_paths;
1720   gboolean color_support;
1721
1722   ret = FALSE;
1723   c = NULL;
1724
1725   modify_argv0_for_command (argc, argv, "introspect");
1726
1727   o = command_option_context_new (NULL, _("Introspect a remote object."),
1728                                   introspect_entries, request_completion);
1729   g_option_context_add_group (o, connection_get_group ());
1730
1731   complete_names = FALSE;
1732   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1733     {
1734       complete_names = TRUE;
1735       remove_arg ((*argc) - 1, argc, argv);
1736     }
1737
1738   complete_paths = FALSE;
1739   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1740     {
1741       complete_paths = TRUE;
1742       remove_arg ((*argc) - 1, argc, argv);
1743     }
1744
1745   if (!g_option_context_parse (o, argc, argv, NULL))
1746     {
1747       if (!request_completion)
1748         {
1749           s = g_option_context_get_help (o, FALSE, NULL);
1750           g_printerr ("%s", s);
1751           g_free (s);
1752           goto out;
1753         }
1754     }
1755
1756   error = NULL;
1757   c = connection_get_dbus_connection (TRUE, &error);
1758   if (c == NULL)
1759     {
1760       if (request_completion)
1761         {
1762           if (g_strcmp0 (completion_prev, "--address") == 0)
1763             {
1764               g_print ("unix:\n"
1765                        "tcp:\n"
1766                        "nonce-tcp:\n");
1767             }
1768           else
1769             {
1770               g_print ("--system \n--session \n--address \n");
1771             }
1772         }
1773       else
1774         {
1775           g_printerr (_("Error connecting: %s\n"), error->message);
1776           g_error_free (error);
1777         }
1778       goto out;
1779     }
1780
1781   if (complete_names)
1782     {
1783       print_names (c, FALSE);
1784       goto out;
1785     }
1786   /* this only makes sense on message bus connections */
1787   if (opt_introspect_dest == NULL)
1788     {
1789       if (request_completion)
1790         g_print ("--dest \n");
1791       else
1792         g_printerr (_("Error: Destination is not specified\n"));
1793       goto out;
1794     }
1795   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1796     {
1797       print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1798       goto out;
1799     }
1800
1801   if (complete_paths)
1802     {
1803       print_paths (c, opt_introspect_dest, "/");
1804       goto out;
1805     }
1806
1807   if (!request_completion && !g_dbus_is_name (opt_introspect_dest))
1808     {
1809       g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest);
1810       goto out;
1811     }
1812
1813   if (opt_introspect_object_path == NULL)
1814     {
1815       if (request_completion)
1816         g_print ("--object-path \n");
1817       else
1818         g_printerr (_("Error: Object path is not specified\n"));
1819       goto out;
1820     }
1821   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1822     {
1823       gchar *p;
1824       s = g_strdup (opt_introspect_object_path);
1825       p = strrchr (s, '/');
1826       if (p != NULL)
1827         {
1828           if (p == s)
1829             p++;
1830           *p = '\0';
1831         }
1832       print_paths (c, opt_introspect_dest, s);
1833       g_free (s);
1834       goto out;
1835     }
1836   if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1837     {
1838       g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1839       goto out;
1840     }
1841
1842   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1843     {
1844       g_print ("--recurse \n");
1845     }
1846
1847   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1848     {
1849       g_print ("--only-properties \n");
1850     }
1851
1852   /* All done with completion now */
1853   if (request_completion)
1854     goto out;
1855
1856   /* Before we start printing the actual info, check if we can do colors*/
1857   color_support = g_log_writer_supports_color (fileno (stdout));
1858
1859   if (!introspect_do (c, opt_introspect_object_path, 0, color_support))
1860     goto out;
1861
1862   ret = TRUE;
1863
1864  out:
1865   if (c != NULL)
1866     g_object_unref (c);
1867   g_option_context_free (o);
1868   return ret;
1869 }
1870
1871 /* ---------------------------------------------------------------------------------------------------- */
1872
1873 static gchar *opt_monitor_dest = NULL;
1874 static gchar *opt_monitor_object_path = NULL;
1875
1876 static guint monitor_filter_id = 0;
1877
1878 static void
1879 monitor_signal_cb (GDBusConnection *connection,
1880                    const gchar     *sender_name,
1881                    const gchar     *object_path,
1882                    const gchar     *interface_name,
1883                    const gchar     *signal_name,
1884                    GVariant        *parameters,
1885                    gpointer         user_data)
1886 {
1887   gchar *s;
1888   s = g_variant_print (parameters, TRUE);
1889   g_print ("%s: %s.%s %s\n",
1890            object_path,
1891            interface_name,
1892            signal_name,
1893            s);
1894   g_free (s);
1895 }
1896
1897 static void
1898 monitor_on_name_appeared (GDBusConnection *connection,
1899                           const gchar *name,
1900                           const gchar *name_owner,
1901                           gpointer user_data)
1902 {
1903   g_print ("The name %s is owned by %s\n", name, name_owner);
1904   g_assert (monitor_filter_id == 0);
1905   monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1906                                                           name_owner,
1907                                                           NULL,  /* any interface */
1908                                                           NULL,  /* any member */
1909                                                           opt_monitor_object_path,
1910                                                           NULL,  /* arg0 */
1911                                                           G_DBUS_SIGNAL_FLAGS_NONE,
1912                                                           monitor_signal_cb,
1913                                                           NULL,  /* user_data */
1914                                                           NULL); /* user_data destroy notify */
1915 }
1916
1917 static void
1918 monitor_on_name_vanished (GDBusConnection *connection,
1919                           const gchar *name,
1920                           gpointer user_data)
1921 {
1922   g_print ("The name %s does not have an owner\n", name);
1923
1924   if (monitor_filter_id != 0)
1925     {
1926       g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1927       monitor_filter_id = 0;
1928     }
1929 }
1930
1931 static const GOptionEntry monitor_entries[] =
1932 {
1933   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1934   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1935   { NULL }
1936 };
1937
1938 static gboolean
1939 handle_monitor (gint        *argc,
1940                 gchar      **argv[],
1941                 gboolean     request_completion,
1942                 const gchar *completion_cur,
1943                 const gchar *completion_prev)
1944 {
1945   gint ret;
1946   GOptionContext *o;
1947   gchar *s;
1948   GError *error;
1949   GDBusConnection *c;
1950   gboolean complete_names;
1951   gboolean complete_paths;
1952   GMainLoop *loop;
1953
1954   ret = FALSE;
1955   c = NULL;
1956
1957   modify_argv0_for_command (argc, argv, "monitor");
1958
1959   o = command_option_context_new (NULL, _("Monitor a remote object."),
1960                                   monitor_entries, request_completion);
1961   g_option_context_add_group (o, connection_get_group ());
1962
1963   complete_names = FALSE;
1964   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1965     {
1966       complete_names = TRUE;
1967       remove_arg ((*argc) - 1, argc, argv);
1968     }
1969
1970   complete_paths = FALSE;
1971   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1972     {
1973       complete_paths = TRUE;
1974       remove_arg ((*argc) - 1, argc, argv);
1975     }
1976
1977   if (!g_option_context_parse (o, argc, argv, NULL))
1978     {
1979       if (!request_completion)
1980         {
1981           s = g_option_context_get_help (o, FALSE, NULL);
1982           g_printerr ("%s", s);
1983           g_free (s);
1984           goto out;
1985         }
1986     }
1987
1988   error = NULL;
1989   c = connection_get_dbus_connection (TRUE, &error);
1990   if (c == NULL)
1991     {
1992       if (request_completion)
1993         {
1994           if (g_strcmp0 (completion_prev, "--address") == 0)
1995             {
1996               g_print ("unix:\n"
1997                        "tcp:\n"
1998                        "nonce-tcp:\n");
1999             }
2000           else
2001             {
2002               g_print ("--system \n--session \n--address \n");
2003             }
2004         }
2005       else
2006         {
2007           g_printerr (_("Error connecting: %s\n"), error->message);
2008           g_error_free (error);
2009         }
2010       goto out;
2011     }
2012
2013   /* Monitoring doesn’t make sense on a non-message-bus connection. */
2014   if (g_dbus_connection_get_unique_name (c) == NULL)
2015     {
2016       if (!request_completion)
2017         g_printerr (_("Error: can’t monitor a non-message-bus connection\n"));
2018       goto out;
2019     }
2020
2021   if (complete_names)
2022     {
2023       print_names (c, FALSE);
2024       goto out;
2025     }
2026   /* this only makes sense on message bus connections */
2027   if (opt_monitor_dest == NULL)
2028     {
2029       if (request_completion)
2030         g_print ("--dest \n");
2031       else
2032         g_printerr (_("Error: Destination is not specified\n"));
2033       goto out;
2034     }
2035   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
2036     {
2037       print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
2038       goto out;
2039     }
2040
2041   if (!request_completion && !g_dbus_is_name (opt_monitor_dest))
2042     {
2043       g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest);
2044       goto out;
2045     }
2046
2047   if (complete_paths)
2048     {
2049       print_paths (c, opt_monitor_dest, "/");
2050       goto out;
2051     }
2052   if (opt_monitor_object_path == NULL)
2053     {
2054       if (request_completion)
2055         {
2056           g_print ("--object-path \n");
2057           goto out;
2058         }
2059       /* it's fine to not have an object path */
2060     }
2061   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
2062     {
2063       gchar *p;
2064       s = g_strdup (opt_monitor_object_path);
2065       p = strrchr (s, '/');
2066       if (p != NULL)
2067         {
2068           if (p == s)
2069             p++;
2070           *p = '\0';
2071         }
2072       print_paths (c, opt_monitor_dest, s);
2073       g_free (s);
2074       goto out;
2075     }
2076   if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
2077     {
2078       g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
2079       goto out;
2080     }
2081
2082   /* All done with completion now */
2083   if (request_completion)
2084     goto out;
2085
2086   if (opt_monitor_object_path != NULL)
2087     g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
2088   else
2089     g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
2090
2091   loop = g_main_loop_new (NULL, FALSE);
2092   g_bus_watch_name_on_connection (c,
2093                                   opt_monitor_dest,
2094                                   G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2095                                   monitor_on_name_appeared,
2096                                   monitor_on_name_vanished,
2097                                   NULL,
2098                                   NULL);
2099
2100   g_main_loop_run (loop);
2101   g_main_loop_unref (loop);
2102
2103   ret = TRUE;
2104
2105  out:
2106   if (c != NULL)
2107     g_object_unref (c);
2108   g_option_context_free (o);
2109   return ret;
2110 }
2111
2112 /* ---------------------------------------------------------------------------------------------------- */
2113
2114 static gboolean opt_wait_activate_set = FALSE;
2115 static gchar *opt_wait_activate_name = NULL;
2116 static gint64 opt_wait_timeout_secs = 0;  /* no timeout */
2117
2118 typedef enum {
2119   WAIT_STATE_RUNNING,  /* waiting to see the service */
2120   WAIT_STATE_SUCCESS,  /* seen it successfully */
2121   WAIT_STATE_TIMEOUT,  /* timed out before seeing it */
2122 } WaitState;
2123
2124 static gboolean
2125 opt_wait_activate_cb (const gchar  *option_name,
2126                       const gchar  *value,
2127                       gpointer      data,
2128                       GError      **error)
2129 {
2130   /* @value may be NULL */
2131   opt_wait_activate_set = TRUE;
2132   opt_wait_activate_name = g_strdup (value);
2133
2134   return TRUE;
2135 }
2136
2137 static const GOptionEntry wait_entries[] =
2138 {
2139   { "activate", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
2140     opt_wait_activate_cb,
2141     N_("Service to activate before waiting for the other one (well-known name)"),
2142     "[NAME]" },
2143   { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout_secs,
2144     N_("Timeout to wait for before exiting with an error (seconds); 0 for "
2145        "no timeout (default)"), "SECS" },
2146   { NULL }
2147 };
2148
2149 static void
2150 wait_name_appeared_cb (GDBusConnection *connection,
2151                        const gchar     *name,
2152                        const gchar     *name_owner,
2153                        gpointer         user_data)
2154 {
2155   WaitState *wait_state = user_data;
2156
2157   *wait_state = WAIT_STATE_SUCCESS;
2158 }
2159
2160 static gboolean
2161 wait_timeout_cb (gpointer user_data)
2162 {
2163   WaitState *wait_state = user_data;
2164
2165   *wait_state = WAIT_STATE_TIMEOUT;
2166
2167   /* Removed in handle_wait(). */
2168   return G_SOURCE_CONTINUE;
2169 }
2170
2171 static gboolean
2172 handle_wait (gint        *argc,
2173              gchar      **argv[],
2174              gboolean     request_completion,
2175              const gchar *completion_cur,
2176              const gchar *completion_prev)
2177 {
2178   gint ret;
2179   GOptionContext *o;
2180   gchar *s;
2181   GError *error;
2182   GDBusConnection *c;
2183   guint watch_id, timer_id = 0, activate_watch_id;
2184   const gchar *activate_service, *wait_service;
2185   WaitState wait_state = WAIT_STATE_RUNNING;
2186
2187   ret = FALSE;
2188   c = NULL;
2189
2190   modify_argv0_for_command (argc, argv, "wait");
2191
2192   o = command_option_context_new (_("[OPTION…] BUS-NAME"),
2193                                   _("Wait for a bus name to appear."),
2194                                   wait_entries, request_completion);
2195   g_option_context_add_group (o, connection_get_group ());
2196
2197   if (!g_option_context_parse (o, argc, argv, NULL))
2198     {
2199       if (!request_completion)
2200         {
2201           s = g_option_context_get_help (o, FALSE, NULL);
2202           g_printerr ("%s", s);
2203           g_free (s);
2204           goto out;
2205         }
2206     }
2207
2208   error = NULL;
2209   c = connection_get_dbus_connection (TRUE, &error);
2210   if (c == NULL)
2211     {
2212       if (request_completion)
2213         {
2214           if (g_strcmp0 (completion_prev, "--address") == 0)
2215             {
2216               g_print ("unix:\n"
2217                        "tcp:\n"
2218                        "nonce-tcp:\n");
2219             }
2220           else
2221             {
2222               g_print ("--system \n--session \n--address \n");
2223             }
2224         }
2225       else
2226         {
2227           g_printerr (_("Error connecting: %s\n"), error->message);
2228           g_error_free (error);
2229         }
2230       goto out;
2231     }
2232
2233   /* All done with completion now */
2234   if (request_completion)
2235     goto out;
2236
2237   /*
2238    * Try and disentangle the command line arguments, with the aim of supporting:
2239    *    gdbus wait --session --activate ActivateName WaitName
2240    *    gdbus wait --session --activate ActivateAndWaitName
2241    *    gdbus wait --activate --session ActivateAndWaitName
2242    *    gdbus wait --session WaitName
2243    */
2244   if (*argc == 2 && opt_wait_activate_set && opt_wait_activate_name != NULL)
2245     {
2246       activate_service = opt_wait_activate_name;
2247       wait_service = (*argv)[1];
2248     }
2249   else if (*argc == 2 &&
2250            opt_wait_activate_set && opt_wait_activate_name == NULL)
2251     {
2252       activate_service = (*argv)[1];
2253       wait_service = (*argv)[1];
2254     }
2255   else if (*argc == 2 && !opt_wait_activate_set)
2256     {
2257       activate_service = NULL;  /* disabled */
2258       wait_service = (*argv)[1];
2259     }
2260   else if (*argc == 1 &&
2261            opt_wait_activate_set && opt_wait_activate_name != NULL)
2262     {
2263       activate_service = opt_wait_activate_name;
2264       wait_service = opt_wait_activate_name;
2265     }
2266   else if (*argc == 1 &&
2267            opt_wait_activate_set && opt_wait_activate_name == NULL)
2268     {
2269       g_printerr (_("Error: A service to activate for must be specified.\n"));
2270       goto out;
2271     }
2272   else if (*argc == 1 && !opt_wait_activate_set)
2273     {
2274       g_printerr (_("Error: A service to wait for must be specified.\n"));
2275       goto out;
2276     }
2277   else /* if (*argc > 2) */
2278     {
2279       g_printerr (_("Error: Too many arguments.\n"));
2280       goto out;
2281     }
2282
2283   if (activate_service != NULL &&
2284       (!g_dbus_is_name (activate_service) ||
2285        g_dbus_is_unique_name (activate_service)))
2286     {
2287       g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2288                   activate_service);
2289       goto out;
2290     }
2291
2292   if (!g_dbus_is_name (wait_service) || g_dbus_is_unique_name (wait_service))
2293     {
2294       g_printerr (_("Error: %s is not a valid well-known bus name.\n"),
2295                   wait_service);
2296       goto out;
2297     }
2298
2299   /* Start the prerequisite service if needed. */
2300   if (activate_service != NULL)
2301     {
2302       activate_watch_id = g_bus_watch_name_on_connection (c, activate_service,
2303                                                           G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
2304                                                           NULL, NULL,
2305                                                           NULL, NULL);
2306     }
2307   else
2308     {
2309       activate_watch_id = 0;
2310     }
2311
2312   /* Wait for the expected name to appear. */
2313   watch_id = g_bus_watch_name_on_connection (c,
2314                                              wait_service,
2315                                              G_BUS_NAME_WATCHER_FLAGS_NONE,
2316                                              wait_name_appeared_cb,
2317                                              NULL, &wait_state, NULL);
2318
2319   /* Safety timeout. */
2320   if (opt_wait_timeout_secs > 0)
2321     timer_id = g_timeout_add_seconds (opt_wait_timeout_secs, wait_timeout_cb, &wait_state);
2322
2323   while (wait_state == WAIT_STATE_RUNNING)
2324     g_main_context_iteration (NULL, TRUE);
2325
2326   g_bus_unwatch_name (watch_id);
2327   if (timer_id != 0)
2328       g_source_remove (timer_id);
2329   if (activate_watch_id != 0)
2330       g_bus_unwatch_name (activate_watch_id);
2331
2332   ret = (wait_state == WAIT_STATE_SUCCESS);
2333
2334  out:
2335   g_clear_object (&c);
2336   g_option_context_free (o);
2337   g_free (opt_wait_activate_name);
2338   opt_wait_activate_name = NULL;
2339
2340   return ret;
2341 }
2342
2343 /* ---------------------------------------------------------------------------------------------------- */
2344
2345 static gchar *
2346 pick_word_at (const gchar  *s,
2347               gint          cursor,
2348               gint         *out_word_begins_at)
2349 {
2350   gint begin;
2351   gint end;
2352
2353   if (s[0] == '\0')
2354     {
2355       if (out_word_begins_at != NULL)
2356         *out_word_begins_at = -1;
2357       return NULL;
2358     }
2359
2360   if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
2361     {
2362       if (out_word_begins_at != NULL)
2363         *out_word_begins_at = cursor;
2364       return g_strdup ("");
2365     }
2366
2367   while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
2368     cursor--;
2369   begin = cursor;
2370
2371   end = begin;
2372   while (!g_ascii_isspace (s[end]) && s[end] != '\0')
2373     end++;
2374
2375   if (out_word_begins_at != NULL)
2376     *out_word_begins_at = begin;
2377
2378   return g_strndup (s + begin, end - begin);
2379 }
2380
2381 gint
2382 main (gint argc, gchar *argv[])
2383 {
2384   gint ret;
2385   const gchar *command;
2386   gboolean request_completion;
2387   gchar *completion_cur;
2388   gchar *completion_prev;
2389 #ifdef G_OS_WIN32
2390   gchar *tmp;
2391 #endif
2392
2393   setlocale (LC_ALL, "");
2394   textdomain (GETTEXT_PACKAGE);
2395
2396 #ifdef G_OS_WIN32
2397   tmp = _glib_get_locale_dir ();
2398   bindtextdomain (GETTEXT_PACKAGE, tmp);
2399   g_free (tmp);
2400 #else
2401   bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2402 #endif
2403
2404 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2405   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2406 #endif
2407
2408   ret = 1;
2409   completion_cur = NULL;
2410   completion_prev = NULL;
2411
2412   if (argc < 2)
2413     {
2414       usage (&argc, &argv, FALSE);
2415       goto out;
2416     }
2417
2418   request_completion = FALSE;
2419
2420   //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
2421
2422  again:
2423   command = argv[1];
2424   if (g_strcmp0 (command, "help") == 0)
2425     {
2426       if (request_completion)
2427         {
2428           /* do nothing */
2429         }
2430       else
2431         {
2432           usage (&argc, &argv, TRUE);
2433           ret = 0;
2434         }
2435       goto out;
2436     }
2437   else if (g_strcmp0 (command, "emit") == 0)
2438     {
2439       if (handle_emit (&argc,
2440                        &argv,
2441                        request_completion,
2442                        completion_cur,
2443                        completion_prev))
2444         ret = 0;
2445       goto out;
2446     }
2447   else if (g_strcmp0 (command, "call") == 0)
2448     {
2449       if (handle_call (&argc,
2450                        &argv,
2451                        request_completion,
2452                        completion_cur,
2453                        completion_prev))
2454         ret = 0;
2455       goto out;
2456     }
2457   else if (g_strcmp0 (command, "introspect") == 0)
2458     {
2459       if (handle_introspect (&argc,
2460                              &argv,
2461                              request_completion,
2462                              completion_cur,
2463                              completion_prev))
2464         ret = 0;
2465       goto out;
2466     }
2467   else if (g_strcmp0 (command, "monitor") == 0)
2468     {
2469       if (handle_monitor (&argc,
2470                           &argv,
2471                           request_completion,
2472                           completion_cur,
2473                           completion_prev))
2474         ret = 0;
2475       goto out;
2476     }
2477   else if (g_strcmp0 (command, "wait") == 0)
2478     {
2479       if (handle_wait (&argc,
2480                        &argv,
2481                        request_completion,
2482                        completion_cur,
2483                        completion_prev))
2484         ret = 0;
2485       goto out;
2486     }
2487 #ifdef G_OS_WIN32
2488   else if (g_strcmp0 (command, _GDBUS_ARG_WIN32_RUN_SESSION_BUS) == 0)
2489     {
2490       g_win32_run_session_bus (NULL, NULL, NULL, 0);
2491       ret = 0;
2492       goto out;
2493     }
2494 #endif
2495   else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2496     {
2497       const gchar *completion_line;
2498       gchar **completion_argv;
2499       gint completion_argc;
2500       gint completion_point;
2501       gchar *endp;
2502       gint cur_begin;
2503
2504       request_completion = TRUE;
2505
2506       completion_line = argv[2];
2507       completion_point = strtol (argv[3], &endp, 10);
2508       if (endp == argv[3] || *endp != '\0')
2509         goto out;
2510
2511 #if 0
2512       completion_debug ("completion_point=%d", completion_point);
2513       completion_debug ("----");
2514       completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2515       completion_debug ("'%s'", completion_line);
2516       completion_debug (" %*s^",
2517                          completion_point, "");
2518       completion_debug ("----");
2519 #endif
2520
2521       if (!g_shell_parse_argv (completion_line,
2522                                &completion_argc,
2523                                &completion_argv,
2524                                NULL))
2525         {
2526           /* it's very possible the command line can't be parsed (for
2527            * example, missing quotes etc) - in that case, we just
2528            * don't autocomplete at all
2529            */
2530           goto out;
2531         }
2532
2533       /* compute cur and prev */
2534       completion_prev = NULL;
2535       completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2536       if (cur_begin > 0)
2537         {
2538           gint prev_end;
2539           for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2540             {
2541               if (!g_ascii_isspace (completion_line[prev_end]))
2542                 {
2543                   completion_prev = pick_word_at (completion_line, prev_end, NULL);
2544                   break;
2545                 }
2546             }
2547         }
2548 #if 0
2549       completion_debug (" cur='%s'", completion_cur);
2550       completion_debug ("prev='%s'", completion_prev);
2551 #endif
2552
2553       argc = completion_argc;
2554       argv = completion_argv;
2555
2556       ret = 0;
2557
2558       goto again;
2559     }
2560   else
2561     {
2562       if (request_completion)
2563         {
2564           g_print ("help \nemit \ncall \nintrospect \nmonitor \nwait \n");
2565           ret = 0;
2566           goto out;
2567         }
2568       else
2569         {
2570           g_printerr ("Unknown command '%s'\n", command);
2571           usage (&argc, &argv, FALSE);
2572           goto out;
2573         }
2574     }
2575
2576  out:
2577   g_free (completion_cur);
2578   g_free (completion_prev);
2579   return ret;
2580 }