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