giomodule test: force shared library build
[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 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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
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 #include <gi18n.h>
33
34 #ifdef G_OS_WIN32
35 #include "glib/glib-private.h"
36 #endif
37
38 /* ---------------------------------------------------------------------------------------------------- */
39
40 G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
41
42 /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
43  * to not have it interfere with stdout/stderr)
44  */
45 #if 0
46 G_GNUC_UNUSED static void
47 completion_debug (const gchar *format, ...)
48 {
49   va_list var_args;
50   gchar *s;
51   static FILE *f = NULL;
52
53   va_start (var_args, format);
54   s = g_strdup_vprintf (format, var_args);
55   if (f == NULL)
56     {
57       f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
58     }
59   fprintf (f, "%s\n", s);
60   g_free (s);
61 }
62 #else
63 static void
64 completion_debug (const gchar *format, ...)
65 {
66 }
67 #endif
68
69 /* ---------------------------------------------------------------------------------------------------- */
70
71
72 static void
73 remove_arg (gint num, gint *argc, gchar **argv[])
74 {
75   gint n;
76
77   g_assert (num <= (*argc));
78
79   for (n = num; (*argv)[n] != NULL; n++)
80     (*argv)[n] = (*argv)[n+1];
81   (*argv)[n] = NULL;
82   (*argc) = (*argc) - 1;
83 }
84
85 static void
86 usage (gint *argc, gchar **argv[], gboolean use_stdout)
87 {
88   GOptionContext *o;
89   gchar *s;
90   gchar *program_name;
91
92   o = g_option_context_new (_("COMMAND"));
93   g_option_context_set_help_enabled (o, FALSE);
94   /* Ignore parsing result */
95   g_option_context_parse (o, argc, argv, NULL);
96   program_name = g_path_get_basename ((*argv)[0]);
97   s = g_strdup_printf (_("Commands:\n"
98                          "  help         Shows this information\n"
99                          "  introspect   Introspect a remote object\n"
100                          "  monitor      Monitor a remote object\n"
101                          "  call         Invoke a method on a remote object\n"
102                          "  emit         Emit a signal\n"
103                          "\n"
104                          "Use \"%s COMMAND --help\" to get help on each command.\n"),
105                        program_name);
106   g_free (program_name);
107   g_option_context_set_description (o, s);
108   g_free (s);
109   s = g_option_context_get_help (o, FALSE, NULL);
110   if (use_stdout)
111     g_print ("%s", s);
112   else
113     g_printerr ("%s", s);
114   g_free (s);
115   g_option_context_free (o);
116 }
117
118 static void
119 modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
120 {
121   gchar *s;
122   gchar *program_name;
123
124   /* TODO:
125    *  1. get a g_set_prgname() ?; or
126    *  2. save old argv[0] and restore later
127    */
128
129   g_assert (g_strcmp0 ((*argv)[1], command) == 0);
130   remove_arg (1, argc, argv);
131
132   program_name = g_path_get_basename ((*argv)[0]);
133   s = g_strdup_printf ("%s %s", (*argv)[0], command);
134   (*argv)[0] = s;
135   g_free (program_name);
136 }
137
138 /* ---------------------------------------------------------------------------------------------------- */
139
140 static void
141 print_methods (GDBusConnection *c,
142                const gchar *name,
143                const gchar *path)
144 {
145   GVariant *result;
146   GError *error;
147   const gchar *xml_data;
148   GDBusNodeInfo *node;
149   guint n;
150   guint m;
151
152   error = NULL;
153   result = g_dbus_connection_call_sync (c,
154                                         name,
155                                         path,
156                                         "org.freedesktop.DBus.Introspectable",
157                                         "Introspect",
158                                         NULL,
159                                         G_VARIANT_TYPE ("(s)"),
160                                         G_DBUS_CALL_FLAGS_NONE,
161                                         3000, /* 3 secs */
162                                         NULL,
163                                         &error);
164   if (result == NULL)
165     {
166       g_printerr (_("Error: %s\n"), error->message);
167       g_error_free (error);
168       goto out;
169     }
170   g_variant_get (result, "(&s)", &xml_data);
171
172   error = NULL;
173   node = g_dbus_node_info_new_for_xml (xml_data, &error);
174   g_variant_unref (result);
175   if (node == NULL)
176     {
177       g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
178       g_error_free (error);
179       goto out;
180     }
181
182   for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++)
183     {
184       const GDBusInterfaceInfo *iface = node->interfaces[n];
185       for (m = 0; iface->methods != NULL && iface->methods[m] != NULL; m++)
186         {
187           const GDBusMethodInfo *method = iface->methods[m];
188           g_print ("%s.%s \n", iface->name, method->name);
189         }
190     }
191   g_dbus_node_info_unref (node);
192
193  out:
194   ;
195 }
196
197 static void
198 print_paths (GDBusConnection *c,
199              const gchar *name,
200              const gchar *path)
201 {
202   GVariant *result;
203   GError *error;
204   const gchar *xml_data;
205   GDBusNodeInfo *node;
206   guint n;
207
208   error = NULL;
209   result = g_dbus_connection_call_sync (c,
210                                         name,
211                                         path,
212                                         "org.freedesktop.DBus.Introspectable",
213                                         "Introspect",
214                                         NULL,
215                                         G_VARIANT_TYPE ("(s)"),
216                                         G_DBUS_CALL_FLAGS_NONE,
217                                         3000, /* 3 secs */
218                                         NULL,
219                                         &error);
220   if (result == NULL)
221     {
222       g_printerr (_("Error: %s\n"), error->message);
223       g_error_free (error);
224       goto out;
225     }
226   g_variant_get (result, "(&s)", &xml_data);
227
228   //g_printerr ("xml='%s'", xml_data);
229
230   error = NULL;
231   node = g_dbus_node_info_new_for_xml (xml_data, &error);
232   g_variant_unref (result);
233   if (node == NULL)
234     {
235       g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
236       g_error_free (error);
237       goto out;
238     }
239
240   //g_printerr ("bar '%s'\n", path);
241
242   if (node->interfaces != NULL)
243     g_print ("%s \n", path);
244
245   for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++)
246     {
247       gchar *s;
248
249       //g_printerr ("foo '%s'\n", node->nodes[n].path);
250
251       if (g_strcmp0 (path, "/") == 0)
252         s = g_strdup_printf ("/%s", node->nodes[n]->path);
253       else
254         s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path);
255
256       print_paths (c, name, s);
257
258       g_free (s);
259     }
260   g_dbus_node_info_unref (node);
261
262  out:
263   ;
264 }
265
266 static void
267 print_names (GDBusConnection *c,
268              gboolean         include_unique_names)
269 {
270   GVariant *result;
271   GError *error;
272   GVariantIter *iter;
273   gchar *str;
274   GHashTable *name_set;
275   GList *keys;
276   GList *l;
277
278   name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
279
280   error = NULL;
281   result = g_dbus_connection_call_sync (c,
282                                         "org.freedesktop.DBus",
283                                         "/org/freedesktop/DBus",
284                                         "org.freedesktop.DBus",
285                                         "ListNames",
286                                         NULL,
287                                         G_VARIANT_TYPE ("(as)"),
288                                         G_DBUS_CALL_FLAGS_NONE,
289                                         3000, /* 3 secs */
290                                         NULL,
291                                         &error);
292   if (result == NULL)
293     {
294       g_printerr (_("Error: %s\n"), error->message);
295       g_error_free (error);
296       goto out;
297     }
298   g_variant_get (result, "(as)", &iter);
299   while (g_variant_iter_loop (iter, "s", &str))
300     g_hash_table_insert (name_set, g_strdup (str), NULL);
301   g_variant_iter_free (iter);
302   g_variant_unref (result);
303
304   error = NULL;
305   result = g_dbus_connection_call_sync (c,
306                                         "org.freedesktop.DBus",
307                                         "/org/freedesktop/DBus",
308                                         "org.freedesktop.DBus",
309                                         "ListActivatableNames",
310                                         NULL,
311                                         G_VARIANT_TYPE ("(as)"),
312                                         G_DBUS_CALL_FLAGS_NONE,
313                                         3000, /* 3 secs */
314                                         NULL,
315                                         &error);
316   if (result == NULL)
317     {
318       g_printerr (_("Error: %s\n"), error->message);
319       g_error_free (error);
320       goto out;
321     }
322   g_variant_get (result, "(as)", &iter);
323   while (g_variant_iter_loop (iter, "s", &str))
324     g_hash_table_insert (name_set, g_strdup (str), NULL);
325   g_variant_iter_free (iter);
326   g_variant_unref (result);
327
328   keys = g_hash_table_get_keys (name_set);
329   keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
330   for (l = keys; l != NULL; l = l->next)
331     {
332       const gchar *name = l->data;
333       if (!include_unique_names && g_str_has_prefix (name, ":"))
334         continue;
335
336       g_print ("%s \n", name);
337     }
338   g_list_free (keys);
339
340  out:
341   g_hash_table_unref (name_set);
342 }
343
344 /* ---------------------------------------------------------------------------------------------------- */
345
346 static gboolean  opt_connection_system  = FALSE;
347 static gboolean  opt_connection_session = FALSE;
348 static gchar    *opt_connection_address = NULL;
349
350 static const GOptionEntry connection_entries[] =
351 {
352   { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL},
353   { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL},
354   { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL},
355   { NULL }
356 };
357
358 static GOptionGroup *
359 connection_get_group (void)
360 {
361   static GOptionGroup *g;
362
363   g = g_option_group_new ("connection",
364                           N_("Connection Endpoint Options:"),
365                           N_("Options specifying the connection endpoint"),
366                           NULL,
367                           NULL);
368   g_option_group_set_translation_domain (g, GETTEXT_PACKAGE);
369   g_option_group_add_entries (g, connection_entries);
370
371   return g;
372 }
373
374 static GDBusConnection *
375 connection_get_dbus_connection (GError **error)
376 {
377   GDBusConnection *c;
378
379   c = NULL;
380
381   /* First, ensure we have exactly one connect */
382   if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL)
383     {
384       g_set_error (error,
385                    G_IO_ERROR,
386                    G_IO_ERROR_FAILED,
387                    _("No connection endpoint specified"));
388       goto out;
389     }
390   else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) ||
391            (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) ||
392            (opt_connection_address != NULL && (opt_connection_system || opt_connection_session)))
393     {
394       g_set_error (error,
395                    G_IO_ERROR,
396                    G_IO_ERROR_FAILED,
397                    _("Multiple connection endpoints specified"));
398       goto out;
399     }
400
401   if (opt_connection_system)
402     {
403       c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
404     }
405   else if (opt_connection_session)
406     {
407       c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
408     }
409   else if (opt_connection_address != NULL)
410     {
411       c = g_dbus_connection_new_for_address_sync (opt_connection_address,
412                                                   G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
413                                                   NULL, /* GDBusAuthObserver */
414                                                   NULL, /* GCancellable */
415                                                   error);
416     }
417
418  out:
419   return c;
420 }
421
422 /* ---------------------------------------------------------------------------------------------------- */
423
424 static GPtrArray *
425 call_helper_get_method_in_signature (GDBusConnection  *c,
426                                      const gchar      *dest,
427                                      const gchar      *path,
428                                      const gchar      *interface_name,
429                                      const gchar      *method_name,
430                                      GError          **error)
431 {
432   GPtrArray *ret;
433   GVariant *result;
434   GDBusNodeInfo *node_info;
435   const gchar *xml_data;
436   GDBusInterfaceInfo *interface_info;
437   GDBusMethodInfo *method_info;
438   guint n;
439
440   ret = NULL;
441   result = NULL;
442   node_info = NULL;
443
444   result = g_dbus_connection_call_sync (c,
445                                         dest,
446                                         path,
447                                         "org.freedesktop.DBus.Introspectable",
448                                         "Introspect",
449                                         NULL,
450                                         G_VARIANT_TYPE ("(s)"),
451                                         G_DBUS_CALL_FLAGS_NONE,
452                                         3000, /* 3 secs */
453                                         NULL,
454                                         error);
455   if (result == NULL)
456     goto out;
457
458   g_variant_get (result, "(&s)", &xml_data);
459   node_info = g_dbus_node_info_new_for_xml (xml_data, error);
460   if (node_info == NULL)
461       goto out;
462
463   interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name);
464   if (interface_info == NULL)
465     {
466       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
467                    _("Warning: According to introspection data, interface '%s' does not exist\n"),
468                    interface_name);
469       goto out;
470     }
471
472   method_info = g_dbus_interface_info_lookup_method (interface_info, method_name);
473   if (method_info == NULL)
474     {
475       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
476                    _("Warning: According to introspection data, method '%s' does not exist on interface '%s'\n"),
477                    method_name,
478                    interface_name);
479       goto out;
480     }
481
482   ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free);
483   for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++)
484     {
485       g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature));
486     }
487
488  out:
489   if (node_info != NULL)
490     g_dbus_node_info_unref (node_info);
491   if (result != NULL)
492     g_variant_unref (result);
493
494   return ret;
495 }
496
497 /* ---------------------------------------------------------------------------------------------------- */
498
499 static GVariant *
500 _g_variant_parse_me_harder (GVariantType   *type,
501                             const gchar    *given_str,
502                             GError        **error)
503 {
504   GVariant *value;
505   gchar *s;
506   guint n;
507   GString *str;
508
509   str = g_string_new ("\"");
510   for (n = 0; given_str[n] != '\0'; n++)
511     {
512       if (G_UNLIKELY (given_str[n] == '\"'))
513         g_string_append (str, "\\\"");
514       else
515         g_string_append_c (str, given_str[n]);
516     }
517   g_string_append_c (str, '"');
518   s = g_string_free (str, FALSE);
519
520   value = g_variant_parse (type,
521                            s,
522                            NULL,
523                            NULL,
524                            error);
525   g_free (s);
526
527   return value;
528 }
529
530 /* ---------------------------------------------------------------------------------------------------- */
531
532 static gchar *opt_emit_dest = NULL;
533 static gchar *opt_emit_object_path = NULL;
534 static gchar *opt_emit_signal = NULL;
535
536 static const GOptionEntry emit_entries[] =
537 {
538   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL},
539   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL},
540   { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL},
541   { NULL }
542 };
543
544 static gboolean
545 handle_emit (gint        *argc,
546              gchar      **argv[],
547              gboolean     request_completion,
548              const gchar *completion_cur,
549              const gchar *completion_prev)
550 {
551   gint ret;
552   GOptionContext *o;
553   gchar *s;
554   GError *error;
555   GDBusConnection *c;
556   GVariant *parameters;
557   gchar *interface_name;
558   gchar *signal_name;
559   GVariantBuilder builder;
560   guint n;
561
562   ret = FALSE;
563   c = NULL;
564   parameters = NULL;
565   interface_name = NULL;
566   signal_name = NULL;
567
568   modify_argv0_for_command (argc, argv, "emit");
569
570   o = g_option_context_new (NULL);
571   g_option_context_set_help_enabled (o, FALSE);
572   g_option_context_set_summary (o, _("Emit a signal."));
573   g_option_context_add_main_entries (o, emit_entries, GETTEXT_PACKAGE);
574   g_option_context_add_group (o, connection_get_group ());
575
576   if (!g_option_context_parse (o, argc, argv, NULL))
577     {
578       if (!request_completion)
579         {
580           s = g_option_context_get_help (o, FALSE, NULL);
581           g_printerr ("%s", s);
582           g_free (s);
583           goto out;
584         }
585     }
586
587   error = NULL;
588   c = connection_get_dbus_connection (&error);
589   if (c == NULL)
590     {
591       if (request_completion)
592         {
593           if (g_strcmp0 (completion_prev, "--address") == 0)
594             {
595               g_print ("unix:\n"
596                        "tcp:\n"
597                        "nonce-tcp:\n");
598             }
599           else
600             {
601               g_print ("--system \n--session \n--address \n");
602             }
603         }
604       else
605         {
606           g_printerr (_("Error connecting: %s\n"), error->message);
607           g_error_free (error);
608         }
609       goto out;
610     }
611
612   /* All done with completion now */
613   if (request_completion)
614     goto out;
615
616   if (opt_emit_object_path == NULL)
617     {
618       g_printerr (_("Error: object path not specified.\n"));
619       goto out;
620     }
621   if (!g_variant_is_object_path (opt_emit_object_path))
622     {
623       g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path);
624       goto out;
625     }
626
627   if (opt_emit_signal == NULL)
628     {
629       g_printerr (_("Error: signal not specified.\n"));
630       goto out;
631     }
632
633   s = strrchr (opt_emit_signal, '.');
634   if (s == NULL)
635     {
636       g_printerr (_("Error: signal must be the fully-qualified name.\n"));
637       goto out;
638     }
639   signal_name = g_strdup (s + 1);
640   interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal);
641
642   if (!g_dbus_is_interface_name (interface_name))
643     {
644       g_printerr (_("Error: %s is not a valid interface name\n"), interface_name);
645       goto out;
646     }
647
648   if (!g_dbus_is_member_name (signal_name))
649     {
650       g_printerr (_("Error: %s is not a valid member name\n"), signal_name);
651       goto out;
652     }
653
654   if (opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest))
655     {
656       g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest);
657       goto out;
658     }
659
660   /* Read parameters */
661   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
662   for (n = 1; n < (guint) *argc; n++)
663     {
664       GVariant *value;
665
666       error = NULL;
667       value = g_variant_parse (NULL,
668                                (*argv)[n],
669                                NULL,
670                                NULL,
671                                &error);
672       if (value == NULL)
673         {
674           gchar *context;
675
676           context = g_variant_parse_error_print_context (error, (*argv)[n]);
677           g_error_free (error);
678           error = NULL;
679           value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error);
680           if (value == NULL)
681             {
682               /* Use the original non-"parse-me-harder" error */
683               g_printerr (_("Error parsing parameter %d: %s\n"),
684                           n,
685                           context);
686               g_error_free (error);
687               g_free (context);
688               g_variant_builder_clear (&builder);
689               goto out;
690             }
691           g_free (context);
692         }
693       g_variant_builder_add_value (&builder, value);
694     }
695   parameters = g_variant_builder_end (&builder);
696
697   if (parameters != NULL)
698     parameters = g_variant_ref_sink (parameters);
699   if (!g_dbus_connection_emit_signal (c,
700                                       opt_emit_dest,
701                                       opt_emit_object_path,
702                                       interface_name,
703                                       signal_name,
704                                       parameters,
705                                       &error))
706     {
707       g_printerr (_("Error: %s\n"), error->message);
708       g_error_free (error);
709       goto out;
710     }
711
712   if (!g_dbus_connection_flush_sync (c, NULL, &error))
713     {
714       g_printerr (_("Error flushing connection: %s\n"), error->message);
715       g_error_free (error);
716       goto out;
717     }
718
719   ret = TRUE;
720
721  out:
722   if (c != NULL)
723     g_object_unref (c);
724   if (parameters != NULL)
725     g_variant_unref (parameters);
726   g_free (interface_name);
727   g_free (signal_name);
728   g_option_context_free (o);
729   return ret;
730 }
731
732 /* ---------------------------------------------------------------------------------------------------- */
733
734 static gchar *opt_call_dest = NULL;
735 static gchar *opt_call_object_path = NULL;
736 static gchar *opt_call_method = NULL;
737 static gint opt_call_timeout = -1;
738
739 static const GOptionEntry call_entries[] =
740 {
741   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL},
742   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL},
743   { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL},
744   { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL},
745   { NULL }
746 };
747
748 static gboolean
749 handle_call (gint        *argc,
750              gchar      **argv[],
751              gboolean     request_completion,
752              const gchar *completion_cur,
753              const gchar *completion_prev)
754 {
755   gint ret;
756   GOptionContext *o;
757   gchar *s;
758   GError *error;
759   GDBusConnection *c;
760   GVariant *parameters;
761   gchar *interface_name;
762   gchar *method_name;
763   GVariant *result;
764   GPtrArray *in_signature_types;
765   gboolean complete_names;
766   gboolean complete_paths;
767   gboolean complete_methods;
768   GVariantBuilder builder;
769   guint n;
770
771   ret = FALSE;
772   c = NULL;
773   parameters = NULL;
774   interface_name = NULL;
775   method_name = NULL;
776   result = NULL;
777   in_signature_types = NULL;
778
779   modify_argv0_for_command (argc, argv, "call");
780
781   o = g_option_context_new (NULL);
782   g_option_context_set_help_enabled (o, FALSE);
783   g_option_context_set_summary (o, _("Invoke a method on a remote object."));
784   g_option_context_add_main_entries (o, call_entries, GETTEXT_PACKAGE);
785   g_option_context_add_group (o, connection_get_group ());
786
787   complete_names = FALSE;
788   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
789     {
790       complete_names = TRUE;
791       remove_arg ((*argc) - 1, argc, argv);
792     }
793
794   complete_paths = FALSE;
795   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
796     {
797       complete_paths = TRUE;
798       remove_arg ((*argc) - 1, argc, argv);
799     }
800
801   complete_methods = FALSE;
802   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0)
803     {
804       complete_methods = TRUE;
805       remove_arg ((*argc) - 1, argc, argv);
806     }
807
808   if (!g_option_context_parse (o, argc, argv, NULL))
809     {
810       if (!request_completion)
811         {
812           s = g_option_context_get_help (o, FALSE, NULL);
813           g_printerr ("%s", s);
814           g_free (s);
815           goto out;
816         }
817     }
818
819   error = NULL;
820   c = connection_get_dbus_connection (&error);
821   if (c == NULL)
822     {
823       if (request_completion)
824         {
825           if (g_strcmp0 (completion_prev, "--address") == 0)
826             {
827               g_print ("unix:\n"
828                        "tcp:\n"
829                        "nonce-tcp:\n");
830             }
831           else
832             {
833               g_print ("--system \n--session \n--address \n");
834             }
835         }
836       else
837         {
838           g_printerr (_("Error connecting: %s\n"), error->message);
839           g_error_free (error);
840         }
841       goto out;
842     }
843
844   /* validate and complete destination (bus name) */
845   if (g_dbus_connection_get_unique_name (c) != NULL)
846     {
847       /* this only makes sense on message bus connections */
848       if (complete_names)
849         {
850           print_names (c, FALSE);
851           goto out;
852         }
853       if (opt_call_dest == NULL)
854         {
855           if (request_completion)
856             g_print ("--dest \n");
857           else
858             g_printerr (_("Error: Destination is not specified\n"));
859           goto out;
860         }
861       if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
862         {
863           print_names (c, g_str_has_prefix (opt_call_dest, ":"));
864           goto out;
865         }
866     }
867
868   /* validate and complete object path */
869   if (complete_paths)
870     {
871       print_paths (c, opt_call_dest, "/");
872       goto out;
873     }
874   if (opt_call_object_path == NULL)
875     {
876       if (request_completion)
877         g_print ("--object-path \n");
878       else
879         g_printerr (_("Error: Object path is not specified\n"));
880       goto out;
881     }
882   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
883     {
884       gchar *p;
885       s = g_strdup (opt_call_object_path);
886       p = strrchr (s, '/');
887       if (p != NULL)
888         {
889           if (p == s)
890             p++;
891           *p = '\0';
892         }
893       print_paths (c, opt_call_dest, s);
894       g_free (s);
895       goto out;
896     }
897   if (!request_completion && !g_variant_is_object_path (opt_call_object_path))
898     {
899       g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path);
900       goto out;
901     }
902
903   /* validate and complete method (interface + method name) */
904   if (complete_methods)
905     {
906       print_methods (c, opt_call_dest, opt_call_object_path);
907       goto out;
908     }
909   if (opt_call_method == NULL)
910     {
911       if (request_completion)
912         g_print ("--method \n");
913       else
914         g_printerr (_("Error: Method name is not specified\n"));
915       goto out;
916     }
917   if (request_completion && g_strcmp0 ("--method", completion_prev) == 0)
918     {
919       print_methods (c, opt_call_dest, opt_call_object_path);
920       goto out;
921     }
922   s = strrchr (opt_call_method, '.');
923   if (!request_completion && s == NULL)
924     {
925       g_printerr (_("Error: Method name '%s' is invalid\n"), opt_call_method);
926       goto out;
927     }
928   method_name = g_strdup (s + 1);
929   interface_name = g_strndup (opt_call_method, s - opt_call_method);
930
931   /* All done with completion now */
932   if (request_completion)
933     goto out;
934
935   /* Introspect, for easy conversion - it's not fatal if we can't do this */
936   in_signature_types = call_helper_get_method_in_signature (c,
937                                                             opt_call_dest,
938                                                             opt_call_object_path,
939                                                             interface_name,
940                                                             method_name,
941                                                             &error);
942   if (in_signature_types == NULL)
943     {
944       //g_printerr ("Error getting introspection data: %s\n", error->message);
945       g_error_free (error);
946       error = NULL;
947     }
948
949   /* Read parameters */
950   g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
951   for (n = 1; n < (guint) *argc; n++)
952     {
953       GVariant *value;
954       GVariantType *type;
955
956       type = NULL;
957       if (in_signature_types != NULL)
958         {
959           if (n - 1 >= in_signature_types->len)
960             {
961               /* Only warn for the first param */
962               if (n - 1 == in_signature_types->len)
963                 {
964                   g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n",
965                               in_signature_types->len);
966                 }
967             }
968           else
969             {
970               type = in_signature_types->pdata[n - 1];
971             }
972         }
973
974       error = NULL;
975       value = g_variant_parse (type,
976                                (*argv)[n],
977                                NULL,
978                                NULL,
979                                &error);
980       if (value == NULL)
981         {
982           gchar *context;
983
984           context = g_variant_parse_error_print_context (error, (*argv)[n]);
985           g_error_free (error);
986           error = NULL;
987           value = _g_variant_parse_me_harder (type, (*argv)[n], &error);
988           if (value == NULL)
989             {
990               if (type != NULL)
991                 {
992                   s = g_variant_type_dup_string (type);
993                   g_printerr (_("Error parsing parameter %d of type '%s': %s\n"),
994                               n,
995                               s,
996                               context);
997                   g_free (s);
998                 }
999               else
1000                 {
1001                   g_printerr (_("Error parsing parameter %d: %s\n"),
1002                               n,
1003                               context);
1004                 }
1005               g_error_free (error);
1006               g_variant_builder_clear (&builder);
1007               g_free (context);
1008               goto out;
1009             }
1010           g_free (context);
1011         }
1012       g_variant_builder_add_value (&builder, value);
1013     }
1014   parameters = g_variant_builder_end (&builder);
1015
1016   if (parameters != NULL)
1017     parameters = g_variant_ref_sink (parameters);
1018   result = g_dbus_connection_call_sync (c,
1019                                         opt_call_dest,
1020                                         opt_call_object_path,
1021                                         interface_name,
1022                                         method_name,
1023                                         parameters,
1024                                         NULL,
1025                                         G_DBUS_CALL_FLAGS_NONE,
1026                                         opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout,
1027                                         NULL,
1028                                         &error);
1029   if (result == NULL)
1030     {
1031       if (error)
1032         {
1033           g_printerr (_("Error: %s\n"), error->message);
1034           g_error_free (error);
1035         }
1036       if (in_signature_types != NULL)
1037         {
1038           GString *s;
1039           s = g_string_new (NULL);
1040           for (n = 0; n < in_signature_types->len; n++)
1041             {
1042               GVariantType *type = in_signature_types->pdata[n];
1043               g_string_append_len (s,
1044                                    g_variant_type_peek_string (type),
1045                                    g_variant_type_get_string_length (type));
1046             }
1047           g_printerr ("(According to introspection data, you need to pass '%s')\n", s->str);
1048           g_string_free (s, TRUE);
1049         }
1050       goto out;
1051     }
1052
1053   s = g_variant_print (result, TRUE);
1054   g_print ("%s\n", s);
1055   g_free (s);
1056
1057   ret = TRUE;
1058
1059  out:
1060   if (in_signature_types != NULL)
1061     g_ptr_array_unref (in_signature_types);
1062   if (result != NULL)
1063     g_variant_unref (result);
1064   if (c != NULL)
1065     g_object_unref (c);
1066   if (parameters != NULL)
1067     g_variant_unref (parameters);
1068   g_free (interface_name);
1069   g_free (method_name);
1070   g_option_context_free (o);
1071   return ret;
1072 }
1073
1074 /* ---------------------------------------------------------------------------------------------------- */
1075
1076 static gchar *opt_introspect_dest = NULL;
1077 static gchar *opt_introspect_object_path = NULL;
1078 static gboolean opt_introspect_xml = FALSE;
1079 static gboolean opt_introspect_recurse = FALSE;
1080 static gboolean opt_introspect_only_properties = FALSE;
1081
1082 static void
1083 dump_annotation (const GDBusAnnotationInfo *o,
1084                  guint indent,
1085                  gboolean ignore_indent)
1086 {
1087   guint n;
1088   g_print ("%*s@%s(\"%s\")\n",
1089            ignore_indent ? 0 : indent, "",
1090            o->key,
1091            o->value);
1092   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1093     dump_annotation (o->annotations[n], indent + 2, FALSE);
1094 }
1095
1096 static void
1097 dump_arg (const GDBusArgInfo *o,
1098           guint indent,
1099           const gchar *direction,
1100           gboolean ignore_indent,
1101           gboolean include_newline)
1102 {
1103   guint n;
1104
1105   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1106     {
1107       dump_annotation (o->annotations[n], indent, ignore_indent);
1108       ignore_indent = FALSE;
1109     }
1110
1111   g_print ("%*s%s%s %s%s",
1112            ignore_indent ? 0 : indent, "",
1113            direction,
1114            o->signature,
1115            o->name,
1116            include_newline ? ",\n" : "");
1117 }
1118
1119 static guint
1120 count_args (GDBusArgInfo **args)
1121 {
1122   guint n;
1123   n = 0;
1124   if (args == NULL)
1125     goto out;
1126   while (args[n] != NULL)
1127     n++;
1128  out:
1129   return n;
1130 }
1131
1132 static void
1133 dump_method (const GDBusMethodInfo *o,
1134              guint                  indent)
1135 {
1136   guint n;
1137   guint m;
1138   guint name_len;
1139   guint total_num_args;
1140
1141   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1142     dump_annotation (o->annotations[n], indent, FALSE);
1143
1144   g_print ("%*s%s(", indent, "", o->name);
1145   name_len = strlen (o->name);
1146   total_num_args = count_args (o->in_args) + count_args (o->out_args);
1147   for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++)
1148     {
1149       gboolean ignore_indent = (m == 0);
1150       gboolean include_newline = (m != total_num_args - 1);
1151
1152       dump_arg (o->in_args[n],
1153                 indent + name_len + 1,
1154                 "in  ",
1155                 ignore_indent,
1156                 include_newline);
1157     }
1158   for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++)
1159     {
1160       gboolean ignore_indent = (m == 0);
1161       gboolean include_newline = (m != total_num_args - 1);
1162       dump_arg (o->out_args[n],
1163                 indent + name_len + 1,
1164                 "out ",
1165                 ignore_indent,
1166                 include_newline);
1167     }
1168   g_print (");\n");
1169 }
1170
1171 static void
1172 dump_signal (const GDBusSignalInfo *o,
1173              guint                  indent)
1174 {
1175   guint n;
1176   guint name_len;
1177   guint total_num_args;
1178
1179   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1180     dump_annotation (o->annotations[n], indent, FALSE);
1181
1182   g_print ("%*s%s(", indent, "", o->name);
1183   name_len = strlen (o->name);
1184   total_num_args = count_args (o->args);
1185   for (n = 0; o->args != NULL && o->args[n] != NULL; n++)
1186     {
1187       gboolean ignore_indent = (n == 0);
1188       gboolean include_newline = (n != total_num_args - 1);
1189       dump_arg (o->args[n],
1190                 indent + name_len + 1,
1191                 "",
1192                 ignore_indent,
1193                 include_newline);
1194     }
1195   g_print (");\n");
1196 }
1197
1198 static void
1199 dump_property (const GDBusPropertyInfo *o,
1200                guint                    indent,
1201                GVariant                *value)
1202 {
1203   const gchar *access;
1204   guint n;
1205
1206   if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
1207     access = "readonly";
1208   else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)
1209     access = "writeonly";
1210   else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
1211     access = "readwrite";
1212   else
1213     g_assert_not_reached ();
1214
1215   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1216     dump_annotation (o->annotations[n], indent, FALSE);
1217
1218   if (value != NULL)
1219     {
1220       gchar *s = g_variant_print (value, FALSE);
1221       g_print ("%*s%s %s %s = %s;\n", indent, "", access, o->signature, o->name, s);
1222       g_free (s);
1223     }
1224   else
1225     {
1226       g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name);
1227     }
1228 }
1229
1230 static void
1231 dump_interface (GDBusConnection          *c,
1232                 const gchar              *name,
1233                 const GDBusInterfaceInfo *o,
1234                 guint                     indent,
1235                 const gchar              *object_path)
1236 {
1237   guint n;
1238   GHashTable *properties;
1239
1240   properties = g_hash_table_new_full (g_str_hash,
1241                                       g_str_equal,
1242                                       g_free,
1243                                       (GDestroyNotify) g_variant_unref);
1244
1245   /* Try to get properties */
1246   if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL)
1247     {
1248       GVariant *result;
1249       result = g_dbus_connection_call_sync (c,
1250                                             name,
1251                                             object_path,
1252                                             "org.freedesktop.DBus.Properties",
1253                                             "GetAll",
1254                                             g_variant_new ("(s)", o->name),
1255                                             NULL,
1256                                             G_DBUS_CALL_FLAGS_NONE,
1257                                             3000,
1258                                             NULL,
1259                                             NULL);
1260       if (result != NULL)
1261         {
1262           if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})")))
1263             {
1264               GVariantIter *iter;
1265               GVariant *item;
1266               g_variant_get (result,
1267                              "(a{sv})",
1268                              &iter);
1269               while ((item = g_variant_iter_next_value (iter)))
1270                 {
1271                   gchar *key;
1272                   GVariant *value;
1273                   g_variant_get (item,
1274                                  "{sv}",
1275                                  &key,
1276                                  &value);
1277
1278                   g_hash_table_insert (properties, key, g_variant_ref (value));
1279                 }
1280             }
1281           g_variant_unref (result);
1282         }
1283       else
1284         {
1285           guint n;
1286           for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++)
1287             {
1288               result = g_dbus_connection_call_sync (c,
1289                                                     name,
1290                                                     object_path,
1291                                                     "org.freedesktop.DBus.Properties",
1292                                                     "Get",
1293                                                     g_variant_new ("(ss)", o->name, o->properties[n]->name),
1294                                                     G_VARIANT_TYPE ("(v)"),
1295                                                     G_DBUS_CALL_FLAGS_NONE,
1296                                                     3000,
1297                                                     NULL,
1298                                                     NULL);
1299               if (result != NULL)
1300                 {
1301                   GVariant *property_value;
1302                   g_variant_get (result,
1303                                  "(v)",
1304                                  &property_value);
1305                   g_hash_table_insert (properties,
1306                                        g_strdup (o->properties[n]->name),
1307                                        g_variant_ref (property_value));
1308                   g_variant_unref (result);
1309                 }
1310             }
1311         }
1312     }
1313
1314   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1315     dump_annotation (o->annotations[n], indent, FALSE);
1316
1317   g_print ("%*sinterface %s {\n", indent, "", o->name);
1318   if (o->methods != NULL && !opt_introspect_only_properties)
1319     {
1320       g_print ("%*s  methods:\n", indent, "");
1321       for (n = 0; o->methods[n] != NULL; n++)
1322         dump_method (o->methods[n], indent + 4);
1323     }
1324   if (o->signals != NULL && !opt_introspect_only_properties)
1325     {
1326       g_print ("%*s  signals:\n", indent, "");
1327       for (n = 0; o->signals[n] != NULL; n++)
1328         dump_signal (o->signals[n], indent + 4);
1329     }
1330   if (o->properties != NULL)
1331     {
1332       g_print ("%*s  properties:\n", indent, "");
1333       for (n = 0; o->properties[n] != NULL; n++)
1334         {
1335           dump_property (o->properties[n],
1336                          indent + 4,
1337                          g_hash_table_lookup (properties, (o->properties[n])->name));
1338         }
1339     }
1340   g_print ("%*s};\n",
1341            indent, "");
1342
1343   g_hash_table_unref (properties);
1344 }
1345
1346 static gboolean
1347 introspect_do (GDBusConnection *c,
1348                const gchar     *object_path,
1349                guint            indent);
1350
1351 static void
1352 dump_node (GDBusConnection      *c,
1353            const gchar          *name,
1354            const GDBusNodeInfo  *o,
1355            guint                 indent,
1356            const gchar          *object_path,
1357            gboolean              recurse)
1358 {
1359   guint n;
1360   const gchar *object_path_to_print;
1361
1362   object_path_to_print = object_path;
1363   if (o->path != NULL)
1364     object_path_to_print = o->path;
1365
1366   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++)
1367     dump_annotation (o->annotations[n], indent, FALSE);
1368
1369   g_print ("%*snode %s", indent, "", object_path_to_print != NULL ? object_path_to_print : "(not set)");
1370   if (o->interfaces != NULL || o->nodes != NULL)
1371     {
1372       g_print (" {\n");
1373       for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++)
1374         {
1375           if (opt_introspect_only_properties)
1376             {
1377               if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL)
1378                 dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1379             }
1380           else
1381             {
1382               dump_interface (c, name, o->interfaces[n], indent + 2, object_path);
1383             }
1384         }
1385       for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++)
1386         {
1387           if (recurse)
1388             {
1389               gchar *child_path;
1390               if (g_variant_is_object_path (o->nodes[n]->path))
1391                 {
1392                   child_path = g_strdup (o->nodes[n]->path);
1393                   /* avoid infinite loops */
1394                   if (g_str_has_prefix (child_path, object_path))
1395                     {
1396                       introspect_do (c, child_path, indent + 2);
1397                     }
1398                   else
1399                     {
1400                       g_print ("Skipping path %s that is not enclosed by parent %s\n",
1401                                child_path, object_path);
1402                     }
1403                 }
1404               else
1405                 {
1406                   if (g_strcmp0 (object_path, "/") == 0)
1407                     child_path = g_strdup_printf ("/%s", o->nodes[n]->path);
1408                   else
1409                     child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path);
1410                   introspect_do (c, child_path, indent + 2);
1411                 }
1412               g_free (child_path);
1413             }
1414           else
1415             {
1416               dump_node (NULL, NULL, o->nodes[n], indent + 2, NULL, recurse);
1417             }
1418         }
1419       g_print ("%*s};\n",
1420                indent, "");
1421     }
1422   else
1423     {
1424       g_print ("\n");
1425     }
1426 }
1427
1428 static const GOptionEntry introspect_entries[] =
1429 {
1430   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL},
1431   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL},
1432   { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL},
1433   { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL},
1434   { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL},
1435   { NULL }
1436 };
1437
1438 static gboolean
1439 introspect_do (GDBusConnection *c,
1440                const gchar     *object_path,
1441                guint            indent)
1442 {
1443   GError *error;
1444   GVariant *result;
1445   GDBusNodeInfo *node;
1446   gboolean ret;
1447   const gchar *xml_data;
1448
1449   ret = FALSE;
1450   node = NULL;
1451   result = NULL;
1452
1453   error = NULL;
1454   result = g_dbus_connection_call_sync (c,
1455                                         opt_introspect_dest,
1456                                         object_path,
1457                                         "org.freedesktop.DBus.Introspectable",
1458                                         "Introspect",
1459                                         NULL,
1460                                         G_VARIANT_TYPE ("(s)"),
1461                                         G_DBUS_CALL_FLAGS_NONE,
1462                                         3000, /* 3 sec */
1463                                         NULL,
1464                                         &error);
1465   if (result == NULL)
1466     {
1467       g_printerr (_("Error: %s\n"), error->message);
1468       g_error_free (error);
1469       goto out;
1470     }
1471   g_variant_get (result, "(&s)", &xml_data);
1472
1473   if (opt_introspect_xml)
1474     {
1475       g_print ("%s", xml_data);
1476     }
1477   else
1478     {
1479       error = NULL;
1480       node = g_dbus_node_info_new_for_xml (xml_data, &error);
1481       if (node == NULL)
1482         {
1483           g_printerr (_("Error parsing introspection XML: %s\n"), error->message);
1484           g_error_free (error);
1485           goto out;
1486         }
1487
1488       dump_node (c, opt_introspect_dest, node, indent, object_path, opt_introspect_recurse);
1489     }
1490
1491   ret = TRUE;
1492
1493  out:
1494   if (node != NULL)
1495     g_dbus_node_info_unref (node);
1496   if (result != NULL)
1497     g_variant_unref (result);
1498   return ret;
1499 }
1500
1501 static gboolean
1502 handle_introspect (gint        *argc,
1503                    gchar      **argv[],
1504                    gboolean     request_completion,
1505                    const gchar *completion_cur,
1506                    const gchar *completion_prev)
1507 {
1508   gint ret;
1509   GOptionContext *o;
1510   gchar *s;
1511   GError *error;
1512   GDBusConnection *c;
1513   gboolean complete_names;
1514   gboolean complete_paths;
1515
1516   ret = FALSE;
1517   c = NULL;
1518
1519   modify_argv0_for_command (argc, argv, "introspect");
1520
1521   o = g_option_context_new (NULL);
1522   if (request_completion)
1523     g_option_context_set_ignore_unknown_options (o, TRUE);
1524   g_option_context_set_help_enabled (o, FALSE);
1525   g_option_context_set_summary (o, _("Introspect a remote object."));
1526   g_option_context_add_main_entries (o, introspect_entries, GETTEXT_PACKAGE);
1527   g_option_context_add_group (o, connection_get_group ());
1528
1529   complete_names = FALSE;
1530   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1531     {
1532       complete_names = TRUE;
1533       remove_arg ((*argc) - 1, argc, argv);
1534     }
1535
1536   complete_paths = FALSE;
1537   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1538     {
1539       complete_paths = TRUE;
1540       remove_arg ((*argc) - 1, argc, argv);
1541     }
1542
1543   if (!g_option_context_parse (o, argc, argv, NULL))
1544     {
1545       if (!request_completion)
1546         {
1547           s = g_option_context_get_help (o, FALSE, NULL);
1548           g_printerr ("%s", s);
1549           g_free (s);
1550           goto out;
1551         }
1552     }
1553
1554   error = NULL;
1555   c = connection_get_dbus_connection (&error);
1556   if (c == NULL)
1557     {
1558       if (request_completion)
1559         {
1560           if (g_strcmp0 (completion_prev, "--address") == 0)
1561             {
1562               g_print ("unix:\n"
1563                        "tcp:\n"
1564                        "nonce-tcp:\n");
1565             }
1566           else
1567             {
1568               g_print ("--system \n--session \n--address \n");
1569             }
1570         }
1571       else
1572         {
1573           g_printerr (_("Error connecting: %s\n"), error->message);
1574           g_error_free (error);
1575         }
1576       goto out;
1577     }
1578
1579   if (g_dbus_connection_get_unique_name (c) != NULL)
1580     {
1581       if (complete_names)
1582         {
1583           print_names (c, FALSE);
1584           goto out;
1585         }
1586       /* this only makes sense on message bus connections */
1587       if (opt_introspect_dest == NULL)
1588         {
1589           if (request_completion)
1590             g_print ("--dest \n");
1591           else
1592             g_printerr (_("Error: Destination is not specified\n"));
1593           goto out;
1594         }
1595       if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1596         {
1597           print_names (c, g_str_has_prefix (opt_introspect_dest, ":"));
1598           goto out;
1599         }
1600     }
1601   if (complete_paths)
1602     {
1603       print_paths (c, opt_introspect_dest, "/");
1604       goto out;
1605     }
1606   if (opt_introspect_object_path == NULL)
1607     {
1608       if (request_completion)
1609         g_print ("--object-path \n");
1610       else
1611         g_printerr (_("Error: Object path is not specified\n"));
1612       goto out;
1613     }
1614   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1615     {
1616       gchar *p;
1617       s = g_strdup (opt_introspect_object_path);
1618       p = strrchr (s, '/');
1619       if (p != NULL)
1620         {
1621           if (p == s)
1622             p++;
1623           *p = '\0';
1624         }
1625       print_paths (c, opt_introspect_dest, s);
1626       g_free (s);
1627       goto out;
1628     }
1629   if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path))
1630     {
1631       g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path);
1632       goto out;
1633     }
1634
1635   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse)
1636     {
1637       g_print ("--recurse \n");
1638     }
1639
1640   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties)
1641     {
1642       g_print ("--only-properties \n");
1643     }
1644
1645   /* All done with completion now */
1646   if (request_completion)
1647     goto out;
1648
1649   if (!introspect_do (c, opt_introspect_object_path, 0))
1650     goto out;
1651
1652   ret = TRUE;
1653
1654  out:
1655   if (c != NULL)
1656     g_object_unref (c);
1657   g_option_context_free (o);
1658   return ret;
1659 }
1660
1661 /* ---------------------------------------------------------------------------------------------------- */
1662
1663 static gchar *opt_monitor_dest = NULL;
1664 static gchar *opt_monitor_object_path = NULL;
1665
1666 static guint monitor_filter_id = 0;
1667
1668 static void
1669 monitor_signal_cb (GDBusConnection *connection,
1670                    const gchar     *sender_name,
1671                    const gchar     *object_path,
1672                    const gchar     *interface_name,
1673                    const gchar     *signal_name,
1674                    GVariant        *parameters,
1675                    gpointer         user_data)
1676 {
1677   gchar *s;
1678   s = g_variant_print (parameters, TRUE);
1679   g_print ("%s: %s.%s %s\n",
1680            object_path,
1681            interface_name,
1682            signal_name,
1683            s);
1684   g_free (s);
1685 }
1686
1687 static void
1688 monitor_on_name_appeared (GDBusConnection *connection,
1689                           const gchar *name,
1690                           const gchar *name_owner,
1691                           gpointer user_data)
1692 {
1693   g_print ("The name %s is owned by %s\n", name, name_owner);
1694   g_assert (monitor_filter_id == 0);
1695   monitor_filter_id = g_dbus_connection_signal_subscribe (connection,
1696                                                           name_owner,
1697                                                           NULL,  /* any interface */
1698                                                           NULL,  /* any member */
1699                                                           opt_monitor_object_path,
1700                                                           NULL,  /* arg0 */
1701                                                           G_DBUS_SIGNAL_FLAGS_NONE,
1702                                                           monitor_signal_cb,
1703                                                           NULL,  /* user_data */
1704                                                           NULL); /* user_data destroy notify */
1705 }
1706
1707 static void
1708 monitor_on_name_vanished (GDBusConnection *connection,
1709                           const gchar *name,
1710                           gpointer user_data)
1711 {
1712   g_print ("The name %s does not have an owner\n", name);
1713
1714   if (monitor_filter_id != 0)
1715     {
1716       g_dbus_connection_signal_unsubscribe (connection, monitor_filter_id);
1717       monitor_filter_id = 0;
1718     }
1719 }
1720
1721 static const GOptionEntry monitor_entries[] =
1722 {
1723   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL},
1724   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL},
1725   { NULL }
1726 };
1727
1728 static gboolean
1729 handle_monitor (gint        *argc,
1730                 gchar      **argv[],
1731                 gboolean     request_completion,
1732                 const gchar *completion_cur,
1733                 const gchar *completion_prev)
1734 {
1735   gint ret;
1736   GOptionContext *o;
1737   gchar *s;
1738   GError *error;
1739   GDBusConnection *c;
1740   GVariant *result;
1741   GDBusNodeInfo *node;
1742   gboolean complete_names;
1743   gboolean complete_paths;
1744   GMainLoop *loop;
1745
1746   ret = FALSE;
1747   c = NULL;
1748   node = NULL;
1749   result = NULL;
1750
1751   modify_argv0_for_command (argc, argv, "monitor");
1752
1753   o = g_option_context_new (NULL);
1754   if (request_completion)
1755     g_option_context_set_ignore_unknown_options (o, TRUE);
1756   g_option_context_set_help_enabled (o, FALSE);
1757   g_option_context_set_summary (o, _("Monitor a remote object."));
1758   g_option_context_add_main_entries (o, monitor_entries, GETTEXT_PACKAGE);
1759   g_option_context_add_group (o, connection_get_group ());
1760
1761   complete_names = FALSE;
1762   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0)
1763     {
1764       complete_names = TRUE;
1765       remove_arg ((*argc) - 1, argc, argv);
1766     }
1767
1768   complete_paths = FALSE;
1769   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0)
1770     {
1771       complete_paths = TRUE;
1772       remove_arg ((*argc) - 1, argc, argv);
1773     }
1774
1775   if (!g_option_context_parse (o, argc, argv, NULL))
1776     {
1777       if (!request_completion)
1778         {
1779           s = g_option_context_get_help (o, FALSE, NULL);
1780           g_printerr ("%s", s);
1781           g_free (s);
1782           goto out;
1783         }
1784     }
1785
1786   error = NULL;
1787   c = connection_get_dbus_connection (&error);
1788   if (c == NULL)
1789     {
1790       if (request_completion)
1791         {
1792           if (g_strcmp0 (completion_prev, "--address") == 0)
1793             {
1794               g_print ("unix:\n"
1795                        "tcp:\n"
1796                        "nonce-tcp:\n");
1797             }
1798           else
1799             {
1800               g_print ("--system \n--session \n--address \n");
1801             }
1802         }
1803       else
1804         {
1805           g_printerr (_("Error connecting: %s\n"), error->message);
1806           g_error_free (error);
1807         }
1808       goto out;
1809     }
1810
1811   if (g_dbus_connection_get_unique_name (c) != NULL)
1812     {
1813       if (complete_names)
1814         {
1815           print_names (c, FALSE);
1816           goto out;
1817         }
1818       /* this only makes sense on message bus connections */
1819       if (opt_monitor_dest == NULL)
1820         {
1821           if (request_completion)
1822             g_print ("--dest \n");
1823           else
1824             g_printerr (_("Error: Destination is not specified\n"));
1825           goto out;
1826         }
1827       if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0)
1828         {
1829           print_names (c, g_str_has_prefix (opt_monitor_dest, ":"));
1830           goto out;
1831         }
1832     }
1833   if (complete_paths)
1834     {
1835       print_paths (c, opt_monitor_dest, "/");
1836       goto out;
1837     }
1838   if (opt_monitor_object_path == NULL)
1839     {
1840       if (request_completion)
1841         {
1842           g_print ("--object-path \n");
1843           goto out;
1844         }
1845       /* it's fine to not have an object path */
1846     }
1847   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0)
1848     {
1849       gchar *p;
1850       s = g_strdup (opt_monitor_object_path);
1851       p = strrchr (s, '/');
1852       if (p != NULL)
1853         {
1854           if (p == s)
1855             p++;
1856           *p = '\0';
1857         }
1858       print_paths (c, opt_monitor_dest, s);
1859       g_free (s);
1860       goto out;
1861     }
1862   if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path)))
1863     {
1864       g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path);
1865       goto out;
1866     }
1867
1868   /* All done with completion now */
1869   if (request_completion)
1870     goto out;
1871
1872   if (opt_monitor_object_path != NULL)
1873     g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest);
1874   else
1875     g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest);
1876
1877   loop = g_main_loop_new (NULL, FALSE);
1878   g_bus_watch_name_on_connection (c,
1879                                   opt_monitor_dest,
1880                                   G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
1881                                   monitor_on_name_appeared,
1882                                   monitor_on_name_vanished,
1883                                   NULL,
1884                                   NULL);
1885
1886   g_main_loop_run (loop);
1887   g_main_loop_unref (loop);
1888
1889   ret = TRUE;
1890
1891  out:
1892   if (node != NULL)
1893     g_dbus_node_info_unref (node);
1894   if (result != NULL)
1895     g_variant_unref (result);
1896   if (c != NULL)
1897     g_object_unref (c);
1898   g_option_context_free (o);
1899   return ret;
1900 }
1901
1902 /* ---------------------------------------------------------------------------------------------------- */
1903
1904 static gchar *
1905 pick_word_at (const gchar  *s,
1906               gint          cursor,
1907               gint         *out_word_begins_at)
1908 {
1909   gint begin;
1910   gint end;
1911
1912   if (s[0] == '\0')
1913     {
1914       if (out_word_begins_at != NULL)
1915         *out_word_begins_at = -1;
1916       return NULL;
1917     }
1918
1919   if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
1920     {
1921       if (out_word_begins_at != NULL)
1922         *out_word_begins_at = cursor;
1923       return g_strdup ("");
1924     }
1925
1926   while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
1927     cursor--;
1928   begin = cursor;
1929
1930   end = begin;
1931   while (!g_ascii_isspace (s[end]) && s[end] != '\0')
1932     end++;
1933
1934   if (out_word_begins_at != NULL)
1935     *out_word_begins_at = begin;
1936
1937   return g_strndup (s + begin, end - begin);
1938 }
1939
1940 gint
1941 main (gint argc, gchar *argv[])
1942 {
1943   gint ret;
1944   const gchar *command;
1945   gboolean request_completion;
1946   gchar *completion_cur;
1947   gchar *completion_prev;
1948 #ifdef G_OS_WIN32
1949   gchar *tmp;
1950 #endif
1951
1952   setlocale (LC_ALL, "");
1953   textdomain (GETTEXT_PACKAGE);
1954
1955 #ifdef G_OS_WIN32
1956   tmp = _glib_get_locale_dir ();
1957   bindtextdomain (GETTEXT_PACKAGE, tmp);
1958   g_free (tmp);
1959 #else
1960   bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
1961 #endif
1962
1963 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
1964   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1965 #endif
1966
1967   ret = 1;
1968   completion_cur = NULL;
1969   completion_prev = NULL;
1970
1971   if (argc < 2)
1972     {
1973       usage (&argc, &argv, FALSE);
1974       goto out;
1975     }
1976
1977   request_completion = FALSE;
1978
1979   //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
1980
1981  again:
1982   command = argv[1];
1983   if (g_strcmp0 (command, "help") == 0)
1984     {
1985       if (request_completion)
1986         {
1987           /* do nothing */
1988         }
1989       else
1990         {
1991           usage (&argc, &argv, TRUE);
1992           ret = 0;
1993         }
1994       goto out;
1995     }
1996   else if (g_strcmp0 (command, "emit") == 0)
1997     {
1998       if (handle_emit (&argc,
1999                        &argv,
2000                        request_completion,
2001                        completion_cur,
2002                        completion_prev))
2003         ret = 0;
2004       goto out;
2005     }
2006   else if (g_strcmp0 (command, "call") == 0)
2007     {
2008       if (handle_call (&argc,
2009                        &argv,
2010                        request_completion,
2011                        completion_cur,
2012                        completion_prev))
2013         ret = 0;
2014       goto out;
2015     }
2016   else if (g_strcmp0 (command, "introspect") == 0)
2017     {
2018       if (handle_introspect (&argc,
2019                              &argv,
2020                              request_completion,
2021                              completion_cur,
2022                              completion_prev))
2023         ret = 0;
2024       goto out;
2025     }
2026   else if (g_strcmp0 (command, "monitor") == 0)
2027     {
2028       if (handle_monitor (&argc,
2029                           &argv,
2030                           request_completion,
2031                           completion_cur,
2032                           completion_prev))
2033         ret = 0;
2034       goto out;
2035     }
2036   else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
2037     {
2038       const gchar *completion_line;
2039       gchar **completion_argv;
2040       gint completion_argc;
2041       gint completion_point;
2042       gchar *endp;
2043       gint cur_begin;
2044
2045       request_completion = TRUE;
2046
2047       completion_line = argv[2];
2048       completion_point = strtol (argv[3], &endp, 10);
2049       if (endp == argv[3] || *endp != '\0')
2050         goto out;
2051
2052 #if 0
2053       completion_debug ("completion_point=%d", completion_point);
2054       completion_debug ("----");
2055       completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
2056       completion_debug ("'%s'", completion_line);
2057       completion_debug (" %*s^",
2058                          completion_point, "");
2059       completion_debug ("----");
2060 #endif
2061
2062       if (!g_shell_parse_argv (completion_line,
2063                                &completion_argc,
2064                                &completion_argv,
2065                                NULL))
2066         {
2067           /* it's very possible the command line can't be parsed (for
2068            * example, missing quotes etc) - in that case, we just
2069            * don't autocomplete at all
2070            */
2071           goto out;
2072         }
2073
2074       /* compute cur and prev */
2075       completion_prev = NULL;
2076       completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
2077       if (cur_begin > 0)
2078         {
2079           gint prev_end;
2080           for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
2081             {
2082               if (!g_ascii_isspace (completion_line[prev_end]))
2083                 {
2084                   completion_prev = pick_word_at (completion_line, prev_end, NULL);
2085                   break;
2086                 }
2087             }
2088         }
2089 #if 0
2090       completion_debug (" cur='%s'", completion_cur);
2091       completion_debug ("prev='%s'", completion_prev);
2092 #endif
2093
2094       argc = completion_argc;
2095       argv = completion_argv;
2096
2097       ret = 0;
2098
2099       goto again;
2100     }
2101   else
2102     {
2103       if (request_completion)
2104         {
2105           g_print ("help \nemit \ncall \nintrospect \nmonitor \n");
2106           ret = 0;
2107           goto out;
2108         }
2109       else
2110         {
2111           g_printerr ("Unknown command '%s'\n", command);
2112           usage (&argc, &argv, FALSE);
2113           goto out;
2114         }
2115     }
2116
2117  out:
2118   g_free (completion_cur);
2119   g_free (completion_prev);
2120   return ret;
2121 }