| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | /* GDBus - GLib D-Bus Library
 | 
					
						
							|  |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-09 13:14:55 -04:00
										 |  |  |  |  * Copyright (C) 2008-2010 Red Hat, Inc. | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-05-18 09:12:45 +01:00
										 |  |  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
					
						
							|  |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2017-05-27 18:21:30 +02:00
										 |  |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |  * | 
					
						
							|  |  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * You should have received a copy of the GNU Lesser General | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |  * | 
					
						
							|  |  |  |  |  * Author: David Zeuthen <davidz@redhat.com> | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include "config.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-14 08:38:07 -04:00
										 |  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-06 16:34:23 -04:00
										 |  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-14 08:38:07 -04:00
										 |  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-12 12:26:26 -05:00
										 |  |  |  | #include <locale.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #include <gio/gio.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							|  |  |  |  | #include <gio/gunixfdlist.h>
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 16:34:23 -04:00
										 |  |  |  | #include <gi18n.h>
 | 
					
						
							| 
									
										
										
										
											2025-03-20 12:27:21 +00:00
										 |  |  |  | #include <glib/gstdio.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-06 16:34:23 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-10 10:51:18 -05:00
										 |  |  |  | #ifdef G_OS_WIN32
 | 
					
						
							|  |  |  |  | #include "glib/glib-private.h"
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-13 12:24:16 +01:00
										 |  |  |  | #include "gdbusprivate.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  | /* Escape values for console colors */ | 
					
						
							|  |  |  |  | #define UNDERLINE     "\033[4m"
 | 
					
						
							|  |  |  |  | #define BLUE          "\033[34m"
 | 
					
						
							|  |  |  |  | #define CYAN          "\033[36m"
 | 
					
						
							|  |  |  |  | #define GREEN         "\033[32m"
 | 
					
						
							|  |  |  |  | #define MAGENTA       "\033[35m"
 | 
					
						
							|  |  |  |  | #define RED           "\033[31m"
 | 
					
						
							|  |  |  |  | #define YELLOW        "\033[33m"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | G_GNUC_UNUSED static void completion_debug (const gchar *format, ...); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
 | 
					
						
							|  |  |  |  |  * to not have it interfere with stdout/stderr) | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | #if 0
 | 
					
						
							|  |  |  |  | G_GNUC_UNUSED static void | 
					
						
							|  |  |  |  | completion_debug (const gchar *format, ...) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   va_list var_args; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   static FILE *f = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   va_start (var_args, format); | 
					
						
							|  |  |  |  |   s = g_strdup_vprintf (format, var_args); | 
					
						
							|  |  |  |  |   if (f == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-03-20 12:27:21 +00:00
										 |  |  |  |       f = g_fopen ("/tmp/gdbus-completion-debug.txt", "a+e"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   fprintf (f, "%s\n", s); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | completion_debug (const gchar *format, ...) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | remove_arg (gint num, gint *argc, gchar **argv[]) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint n; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   g_assert (num <= (*argc)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = num; (*argv)[n] != NULL; n++) | 
					
						
							|  |  |  |  |     (*argv)[n] = (*argv)[n+1]; | 
					
						
							|  |  |  |  |   (*argv)[n] = NULL; | 
					
						
							|  |  |  |  |   (*argc) = (*argc) - 1; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | usage (gint *argc, gchar **argv[], gboolean use_stdout) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   gchar *program_name; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   o = g_option_context_new (_("COMMAND")); | 
					
						
							|  |  |  |  |   g_option_context_set_help_enabled (o, FALSE); | 
					
						
							|  |  |  |  |   /* Ignore parsing result */ | 
					
						
							|  |  |  |  |   g_option_context_parse (o, argc, argv, NULL); | 
					
						
							| 
									
										
										
										
											2022-01-31 14:47:57 +00:00
										 |  |  |  |   program_name = (*argc > 0) ? g_path_get_basename ((*argv)[0]) : g_strdup ("gdbus-tool"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   s = g_strdup_printf (_("Commands:\n" | 
					
						
							|  |  |  |  |                          "  help         Shows this information\n" | 
					
						
							|  |  |  |  |                          "  introspect   Introspect a remote object\n" | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |                          "  monitor      Monitor a remote object\n" | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                          "  call         Invoke a method on a remote object\n" | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |                          "  emit         Emit a signal\n" | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |                          "  wait         Wait for a bus name to appear\n" | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                          "\n" | 
					
						
							| 
									
										
										
										
											2016-09-30 05:47:15 +02:00
										 |  |  |  |                          "Use “%s COMMAND --help” to get help on each command.\n"), | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                        program_name); | 
					
						
							|  |  |  |  |   g_free (program_name); | 
					
						
							|  |  |  |  |   g_option_context_set_description (o, s); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  |   s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |   if (use_stdout) | 
					
						
							|  |  |  |  |     g_print ("%s", s); | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     g_printerr ("%s", s); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   gchar *program_name; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* TODO:
 | 
					
						
							|  |  |  |  |    *  1. get a g_set_prgname() ?; or | 
					
						
							|  |  |  |  |    *  2. save old argv[0] and restore later | 
					
						
							|  |  |  |  |    */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-31 14:47:57 +00:00
										 |  |  |  |   g_assert (*argc > 1); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_assert (g_strcmp0 ((*argv)[1], command) == 0); | 
					
						
							|  |  |  |  |   remove_arg (1, argc, argv); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   program_name = g_path_get_basename ((*argv)[0]); | 
					
						
							| 
									
										
										
										
											2021-04-27 15:41:57 +02:00
										 |  |  |  |   s = g_strdup_printf ("%s %s", program_name, command); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   (*argv)[0] = s; | 
					
						
							|  |  |  |  |   g_free (program_name); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  | static GOptionContext * | 
					
						
							|  |  |  |  | command_option_context_new (const gchar        *parameter_string, | 
					
						
							|  |  |  |  |                             const gchar        *summary, | 
					
						
							|  |  |  |  |                             const GOptionEntry *entries, | 
					
						
							|  |  |  |  |                             gboolean            request_completion) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GOptionContext *o = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   o = g_option_context_new (parameter_string); | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     g_option_context_set_ignore_unknown_options (o, TRUE); | 
					
						
							|  |  |  |  |   g_option_context_set_help_enabled (o, FALSE); | 
					
						
							|  |  |  |  |   g_option_context_set_summary (o, summary); | 
					
						
							|  |  |  |  |   g_option_context_add_main_entries (o, entries, GETTEXT_PACKAGE); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return g_steal_pointer (&o); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  | print_methods_and_signals (GDBusConnection *c, | 
					
						
							|  |  |  |  |                            const gchar     *name, | 
					
						
							|  |  |  |  |                            const gchar     *path, | 
					
						
							|  |  |  |  |                            gboolean         print_methods, | 
					
						
							|  |  |  |  |                            gboolean         print_signals) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   const gchar *xml_data; | 
					
						
							|  |  |  |  |   GDBusNodeInfo *node; | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   guint m; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                         name, | 
					
						
							|  |  |  |  |                                         path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                         DBUS_INTERFACE_INTROSPECTABLE, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         "Introspect", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                         G_VARIANT_TYPE ("(s)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 secs */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-13 19:20:26 +02:00
										 |  |  |  |   g_variant_get (result, "(&s)", &xml_data); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							|  |  |  |  |   node = g_dbus_node_info_new_for_xml (xml_data, &error); | 
					
						
							|  |  |  |  |   g_variant_unref (result); | 
					
						
							|  |  |  |  |   if (node == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error parsing introspection XML: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; node->interfaces != NULL && node->interfaces[n] != NULL; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       const GDBusInterfaceInfo *iface = node->interfaces[n]; | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       for (m = 0; print_methods && iface->methods != NULL && iface->methods[m] != NULL; m++) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |         { | 
					
						
							|  |  |  |  |           const GDBusMethodInfo *method = iface->methods[m]; | 
					
						
							|  |  |  |  |           g_print ("%s.%s \n", iface->name, method->name); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       for (m = 0; print_signals && iface->signals != NULL && iface->signals[m] != NULL; m++) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           const GDBusSignalInfo *signal = iface->signals[m]; | 
					
						
							|  |  |  |  |           g_print ("%s.%s \n", iface->name, signal->name); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   g_dbus_node_info_unref (node); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   ; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | print_paths (GDBusConnection *c, | 
					
						
							|  |  |  |  |              const gchar *name, | 
					
						
							|  |  |  |  |              const gchar *path) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   const gchar *xml_data; | 
					
						
							|  |  |  |  |   GDBusNodeInfo *node; | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  |   if (!g_dbus_is_name (name)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid name\n"), name); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-24 16:46:14 +01:00
										 |  |  |  |   if (!g_variant_is_object_path (path)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid object path\n"), path); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                         name, | 
					
						
							|  |  |  |  |                                         path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                         DBUS_INTERFACE_INTROSPECTABLE, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         "Introspect", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                         G_VARIANT_TYPE ("(s)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 secs */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-13 19:20:26 +02:00
										 |  |  |  |   g_variant_get (result, "(&s)", &xml_data); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |   //g_printerr ("xml='%s'", xml_data);
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							|  |  |  |  |   node = g_dbus_node_info_new_for_xml (xml_data, &error); | 
					
						
							|  |  |  |  |   g_variant_unref (result); | 
					
						
							|  |  |  |  |   if (node == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error parsing introspection XML: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |   //g_printerr ("bar '%s'\n", path);
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (node->interfaces != NULL) | 
					
						
							|  |  |  |  |     g_print ("%s \n", path); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; node->nodes != NULL && node->nodes[n] != NULL; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gchar *s; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |       //g_printerr ("foo '%s'\n", node->nodes[n].path);
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (g_strcmp0 (path, "/") == 0) | 
					
						
							|  |  |  |  |         s = g_strdup_printf ("/%s", node->nodes[n]->path); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         s = g_strdup_printf ("%s/%s", path, node->nodes[n]->path); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       print_paths (c, name, s); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_free (s); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_dbus_node_info_unref (node); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   ; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | print_names (GDBusConnection *c, | 
					
						
							|  |  |  |  |              gboolean         include_unique_names) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GVariantIter *iter; | 
					
						
							|  |  |  |  |   gchar *str; | 
					
						
							|  |  |  |  |   GHashTable *name_set; | 
					
						
							| 
									
										
										
										
											2022-12-14 04:59:24 +01:00
										 |  |  |  |   GPtrArray *keys; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   name_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							| 
									
										
										
										
											2024-05-13 12:24:16 +01:00
										 |  |  |  |                                         DBUS_SERVICE_DBUS, | 
					
						
							|  |  |  |  |                                         DBUS_PATH_DBUS, | 
					
						
							|  |  |  |  |                                         DBUS_INTERFACE_DBUS, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         "ListNames", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                         G_VARIANT_TYPE ("(as)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 secs */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_variant_get (result, "(as)", &iter); | 
					
						
							|  |  |  |  |   while (g_variant_iter_loop (iter, "s", &str)) | 
					
						
							| 
									
										
										
										
											2017-10-25 10:53:14 +01:00
										 |  |  |  |     g_hash_table_add (name_set, g_strdup (str)); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_variant_iter_free (iter); | 
					
						
							|  |  |  |  |   g_variant_unref (result); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							| 
									
										
										
										
											2024-05-13 12:24:16 +01:00
										 |  |  |  |                                         DBUS_SERVICE_DBUS, | 
					
						
							|  |  |  |  |                                         DBUS_PATH_DBUS, | 
					
						
							|  |  |  |  |                                         DBUS_INTERFACE_DBUS, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         "ListActivatableNames", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                         G_VARIANT_TYPE ("(as)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 secs */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_variant_get (result, "(as)", &iter); | 
					
						
							|  |  |  |  |   while (g_variant_iter_loop (iter, "s", &str)) | 
					
						
							| 
									
										
										
										
											2017-10-25 10:53:14 +01:00
										 |  |  |  |     g_hash_table_add (name_set, g_strdup (str)); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_variant_iter_free (iter); | 
					
						
							|  |  |  |  |   g_variant_unref (result); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 04:59:24 +01:00
										 |  |  |  |   keys = g_hash_table_steal_all_keys (name_set); | 
					
						
							| 
									
										
										
										
											2022-12-20 00:22:05 +01:00
										 |  |  |  |   g_ptr_array_sort_values (keys, (GCompareFunc) g_strcmp0); | 
					
						
							| 
									
										
										
										
											2022-12-14 04:59:24 +01:00
										 |  |  |  |   for (guint i = 0; i < keys->len; ++i) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-12-14 04:59:24 +01:00
										 |  |  |  |       const gchar *name = g_ptr_array_index (keys, i); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       if (!include_unique_names && g_str_has_prefix (name, ":")) | 
					
						
							|  |  |  |  |         continue; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_print ("%s \n", name); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-12-14 04:59:24 +01:00
										 |  |  |  |   g_clear_pointer (&keys, g_ptr_array_unref); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   g_hash_table_unref (name_set); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean  opt_connection_system  = FALSE; | 
					
						
							|  |  |  |  | static gboolean  opt_connection_session = FALSE; | 
					
						
							|  |  |  |  | static gchar    *opt_connection_address = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry connection_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL}, | 
					
						
							|  |  |  |  |   { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL}, | 
					
						
							| 
									
										
										
										
											2024-02-28 11:22:30 +00:00
										 |  |  |  |   { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), N_("ADDRESS") }, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static GOptionGroup * | 
					
						
							|  |  |  |  | connection_get_group (void) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   static GOptionGroup *g; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   g = g_option_group_new ("connection", | 
					
						
							|  |  |  |  |                           N_("Connection Endpoint Options:"), | 
					
						
							|  |  |  |  |                           N_("Options specifying the connection endpoint"), | 
					
						
							|  |  |  |  |                           NULL, | 
					
						
							|  |  |  |  |                           NULL); | 
					
						
							| 
									
										
										
										
											2011-02-12 12:26:26 -05:00
										 |  |  |  |   g_option_group_set_translation_domain (g, GETTEXT_PACKAGE); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_option_group_add_entries (g, connection_entries); | 
					
						
							| 
									
										
										
										
											2011-02-12 12:26:26 -05:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   return g; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static GDBusConnection * | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  | connection_get_dbus_connection (gboolean   require_message_bus, | 
					
						
							|  |  |  |  |                                 GError   **error) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* First, ensure we have exactly one connect */ | 
					
						
							|  |  |  |  |   if (!opt_connection_system && !opt_connection_session && opt_connection_address == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_set_error (error, | 
					
						
							|  |  |  |  |                    G_IO_ERROR, | 
					
						
							|  |  |  |  |                    G_IO_ERROR_FAILED, | 
					
						
							|  |  |  |  |                    _("No connection endpoint specified")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if ((opt_connection_system && (opt_connection_session || opt_connection_address != NULL)) || | 
					
						
							|  |  |  |  |            (opt_connection_session && (opt_connection_system || opt_connection_address != NULL)) || | 
					
						
							|  |  |  |  |            (opt_connection_address != NULL && (opt_connection_system || opt_connection_session))) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_set_error (error, | 
					
						
							|  |  |  |  |                    G_IO_ERROR, | 
					
						
							|  |  |  |  |                    G_IO_ERROR_FAILED, | 
					
						
							|  |  |  |  |                    _("Multiple connection endpoints specified")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (opt_connection_system) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (opt_connection_session) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (opt_connection_address != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |       GDBusConnectionFlags flags = G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT; | 
					
						
							|  |  |  |  |       if (require_message_bus) | 
					
						
							|  |  |  |  |         flags |= G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       c = g_dbus_connection_new_for_address_sync (opt_connection_address, | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |                                                   flags, | 
					
						
							| 
									
										
										
										
											2010-05-13 16:32:11 -04:00
										 |  |  |  |                                                   NULL, /* GDBusAuthObserver */ | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                                                   NULL, /* GCancellable */ | 
					
						
							|  |  |  |  |                                                   error); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   return c; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static GPtrArray * | 
					
						
							|  |  |  |  | call_helper_get_method_in_signature (GDBusConnection  *c, | 
					
						
							|  |  |  |  |                                      const gchar      *dest, | 
					
						
							|  |  |  |  |                                      const gchar      *path, | 
					
						
							|  |  |  |  |                                      const gchar      *interface_name, | 
					
						
							|  |  |  |  |                                      const gchar      *method_name, | 
					
						
							|  |  |  |  |                                      GError          **error) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GPtrArray *ret; | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GDBusNodeInfo *node_info; | 
					
						
							|  |  |  |  |   const gchar *xml_data; | 
					
						
							| 
									
										
										
										
											2010-07-19 15:45:27 -04:00
										 |  |  |  |   GDBusInterfaceInfo *interface_info; | 
					
						
							|  |  |  |  |   GDBusMethodInfo *method_info; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   guint n; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = NULL; | 
					
						
							|  |  |  |  |   result = NULL; | 
					
						
							|  |  |  |  |   node_info = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                         dest, | 
					
						
							|  |  |  |  |                                         path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                         DBUS_INTERFACE_INTROSPECTABLE, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         "Introspect", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                         G_VARIANT_TYPE ("(s)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 secs */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-13 19:20:26 +02:00
										 |  |  |  |   g_variant_get (result, "(&s)", &xml_data); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   node_info = g_dbus_node_info_new_for_xml (xml_data, error); | 
					
						
							|  |  |  |  |   if (node_info == NULL) | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   interface_info = g_dbus_node_info_lookup_interface (node_info, interface_name); | 
					
						
							|  |  |  |  |   if (interface_info == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							| 
									
										
										
										
											2016-09-30 05:47:15 +02:00
										 |  |  |  |                    _("Warning: According to introspection data, interface “%s” does not exist\n"), | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                    interface_name); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   method_info = g_dbus_interface_info_lookup_method (interface_info, method_name); | 
					
						
							|  |  |  |  |   if (method_info == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | 
					
						
							| 
									
										
										
										
											2016-09-30 05:47:15 +02:00
										 |  |  |  |                    _("Warning: According to introspection data, method “%s” does not exist on interface “%s”\n"), | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                    method_name, | 
					
						
							|  |  |  |  |                    interface_name); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = g_ptr_array_new_with_free_func ((GDestroyNotify) g_variant_type_free); | 
					
						
							|  |  |  |  |   for (n = 0; method_info->in_args != NULL && method_info->in_args[n] != NULL; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_ptr_array_add (ret, g_variant_type_new (method_info->in_args[n]->signature)); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (node_info != NULL) | 
					
						
							|  |  |  |  |     g_dbus_node_info_unref (node_info); | 
					
						
							|  |  |  |  |   if (result != NULL) | 
					
						
							|  |  |  |  |     g_variant_unref (result); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static GVariant * | 
					
						
							|  |  |  |  | _g_variant_parse_me_harder (GVariantType   *type, | 
					
						
							|  |  |  |  |                             const gchar    *given_str, | 
					
						
							|  |  |  |  |                             GError        **error) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   GVariant *value; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   GString *str; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   str = g_string_new ("\""); | 
					
						
							|  |  |  |  |   for (n = 0; given_str[n] != '\0'; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (G_UNLIKELY (given_str[n] == '\"')) | 
					
						
							|  |  |  |  |         g_string_append (str, "\\\""); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_string_append_c (str, given_str[n]); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_string_append_c (str, '"'); | 
					
						
							|  |  |  |  |   s = g_string_free (str, FALSE); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   value = g_variant_parse (type, | 
					
						
							|  |  |  |  |                            s, | 
					
						
							|  |  |  |  |                            NULL, | 
					
						
							|  |  |  |  |                            NULL, | 
					
						
							|  |  |  |  |                            error); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return value; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-26 18:14:51 +01:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | walk_variant_for_handle (GVariantBuilder  *builder, | 
					
						
							|  |  |  |  |                          GUnixFDList      *fd_list, | 
					
						
							|  |  |  |  |                          GVariant         *value) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   g_assert (!g_variant_is_floating (value)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (g_variant_is_container (value)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gboolean res = TRUE; | 
					
						
							|  |  |  |  |       GVariantIter iter; | 
					
						
							|  |  |  |  |       GVariant *child; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_variant_iter_init (&iter, value); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_variant_builder_open (builder, g_variant_get_type (value)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       while ((child = g_variant_iter_next_value (&iter)) && res) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           res = walk_variant_for_handle (builder, fd_list, child); | 
					
						
							|  |  |  |  |           g_variant_unref (child); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_variant_builder_close (builder); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (!res) | 
					
						
							|  |  |  |  |         return FALSE; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (g_variant_is_of_type (value, G_VARIANT_TYPE_HANDLE)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       GError *error = NULL; | 
					
						
							|  |  |  |  |       int fd_id = -1; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if ((fd_id = g_unix_fd_list_append (fd_list, g_variant_get_handle (value), &error)) < 0) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error adding handle %d: %s\n"), | 
					
						
							|  |  |  |  |                         g_variant_get_handle (value), error->message); | 
					
						
							|  |  |  |  |           g_error_free (error); | 
					
						
							|  |  |  |  |           return FALSE; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_variant_builder_add_value (builder, g_variant_new_handle (fd_id)); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_variant_builder_add_value (builder, value); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return TRUE; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  | static gchar *opt_emit_dest = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_emit_object_path = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_emit_signal = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry emit_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL}, | 
					
						
							|  |  |  |  |   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL}, | 
					
						
							|  |  |  |  |   { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL}, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | handle_emit (gint        *argc, | 
					
						
							|  |  |  |  |              gchar      **argv[], | 
					
						
							|  |  |  |  |              gboolean     request_completion, | 
					
						
							|  |  |  |  |              const gchar *completion_cur, | 
					
						
							|  |  |  |  |              const gchar *completion_prev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  |   GVariant *parameters; | 
					
						
							|  |  |  |  |   gchar *interface_name; | 
					
						
							|  |  |  |  |   gchar *signal_name; | 
					
						
							|  |  |  |  |   GVariantBuilder builder; | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |   gboolean skip_dashes; | 
					
						
							|  |  |  |  |   guint parm; | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   guint n; | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   gboolean complete_names, complete_paths, complete_signals; | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  |   parameters = NULL; | 
					
						
							|  |  |  |  |   interface_name = NULL; | 
					
						
							|  |  |  |  |   signal_name = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   modify_argv0_for_command (argc, argv, "emit"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  |   o = command_option_context_new (NULL, _("Emit a signal."), | 
					
						
							|  |  |  |  |                                   emit_entries, request_completion); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   g_option_context_add_group (o, connection_get_group ()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   complete_names = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_names = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_paths = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_paths = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_signals = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--signal") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_signals = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   if (!g_option_context_parse (o, argc, argv, NULL)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |           g_printerr ("%s", s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |   c = connection_get_dbus_connection ((opt_emit_dest != NULL), &error); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   if (c == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 (completion_prev, "--address") == 0) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("unix:\n" | 
					
						
							|  |  |  |  |                        "tcp:\n" | 
					
						
							|  |  |  |  |                        "nonce-tcp:\n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("--system \n--session \n--address \n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error connecting: %s\n"), error->message); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-26 15:43:46 +01:00
										 |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   /* validate and complete destination (bus name) */ | 
					
						
							|  |  |  |  |   if (complete_names) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, FALSE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (request_completion && opt_emit_dest != NULL && g_strcmp0 ("--dest", completion_prev) == 0) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, g_str_has_prefix (opt_emit_dest, ":")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (!request_completion && opt_emit_dest != NULL && !g_dbus_is_unique_name (opt_emit_dest)) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid unique bus name.\n"), opt_emit_dest); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (opt_emit_dest == NULL && opt_emit_object_path == NULL && request_completion) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_print ("--dest \n"); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   /* validate and complete object path */ | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (opt_emit_dest != NULL && complete_paths) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       print_paths (c, opt_emit_dest, "/"); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   if (opt_emit_object_path == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--object-path \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Object path is not specified\n")); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |       if (opt_emit_dest != NULL) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |           gchar *p; | 
					
						
							|  |  |  |  |           s = g_strdup (opt_emit_object_path); | 
					
						
							|  |  |  |  |           p = strrchr (s, '/'); | 
					
						
							|  |  |  |  |           if (p != NULL) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               if (p == s) | 
					
						
							|  |  |  |  |                 p++; | 
					
						
							|  |  |  |  |               *p = '\0'; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           print_paths (c, opt_emit_dest, s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |         } | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (!request_completion && !g_variant_is_object_path (opt_emit_object_path)) | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid object path\n"), opt_emit_object_path); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   /* validate and complete signal (interface + signal name) */ | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (opt_emit_dest != NULL && opt_emit_object_path != NULL && complete_signals) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   if (opt_emit_signal == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-21 12:23:17 +00:00
										 |  |  |  |       /* don't keep repeatedly completing --signal */ | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       if (request_completion) | 
					
						
							| 
									
										
										
										
											2018-02-21 12:23:17 +00:00
										 |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 ("--signal", completion_prev) != 0) | 
					
						
							|  |  |  |  |             g_print ("--signal \n"); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       else | 
					
						
							| 
									
										
										
										
											2018-02-21 12:23:17 +00:00
										 |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error: Signal name is not specified\n")); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-21 12:22:08 +00:00
										 |  |  |  |   if (request_completion && opt_emit_dest != NULL && opt_emit_object_path != NULL && | 
					
						
							|  |  |  |  |       g_strcmp0 ("--signal", completion_prev) == 0) | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       print_methods_and_signals (c, opt_emit_dest, opt_emit_object_path, FALSE, TRUE); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   s = strrchr (opt_emit_signal, '.'); | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   if (!request_completion && s == NULL) | 
					
						
							| 
									
										
										
										
											2012-08-29 19:18:45 +02:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       g_printerr (_("Error: Signal name “%s” is invalid\n"), opt_emit_signal); | 
					
						
							| 
									
										
										
										
											2012-08-29 19:18:45 +02:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   signal_name = g_strdup (s + 1); | 
					
						
							|  |  |  |  |   interface_name = g_strndup (opt_emit_signal, s - opt_emit_signal); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |   /* All done with completion now */ | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   if (!g_dbus_is_interface_name (interface_name)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid interface name\n"), interface_name); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_dbus_is_member_name (signal_name)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid member name\n"), signal_name); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Read parameters */ | 
					
						
							| 
									
										
										
										
											2024-09-25 11:09:07 -07:00
										 |  |  |  |   g_variant_builder_init_static (&builder, G_VARIANT_TYPE_TUPLE); | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |   skip_dashes = TRUE; | 
					
						
							|  |  |  |  |   parm = 0; | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   for (n = 1; n < (guint) *argc; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       GVariant *value; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |       /* Under certain conditions, g_option_context_parse returns the "--"
 | 
					
						
							|  |  |  |  |          itself (setting off unparsed arguments), too: */ | 
					
						
							|  |  |  |  |       if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           skip_dashes = FALSE; | 
					
						
							|  |  |  |  |           continue; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |       error = NULL; | 
					
						
							|  |  |  |  |       value = g_variant_parse (NULL, | 
					
						
							|  |  |  |  |                                (*argv)[n], | 
					
						
							|  |  |  |  |                                NULL, | 
					
						
							|  |  |  |  |                                NULL, | 
					
						
							|  |  |  |  |                                &error); | 
					
						
							|  |  |  |  |       if (value == NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |           gchar *context; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |           context = g_variant_parse_error_print_context (error, (*argv)[n]); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |           g_error_free (error); | 
					
						
							|  |  |  |  |           error = NULL; | 
					
						
							|  |  |  |  |           value = _g_variant_parse_me_harder (NULL, (*argv)[n], &error); | 
					
						
							|  |  |  |  |           if (value == NULL) | 
					
						
							|  |  |  |  |             { | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |               /* Use the original non-"parse-me-harder" error */ | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |               g_printerr (_("Error parsing parameter %d: %s\n"), | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |                           parm + 1, | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |                           context); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |               g_error_free (error); | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |               g_free (context); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |               g_variant_builder_clear (&builder); | 
					
						
							|  |  |  |  |               goto out; | 
					
						
							|  |  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |           g_free (context); | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |         } | 
					
						
							|  |  |  |  |       g_variant_builder_add_value (&builder, value); | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |       ++parm; | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   parameters = g_variant_builder_end (&builder); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (parameters != NULL) | 
					
						
							|  |  |  |  |     parameters = g_variant_ref_sink (parameters); | 
					
						
							|  |  |  |  |   if (!g_dbus_connection_emit_signal (c, | 
					
						
							|  |  |  |  |                                       opt_emit_dest, | 
					
						
							|  |  |  |  |                                       opt_emit_object_path, | 
					
						
							|  |  |  |  |                                       interface_name, | 
					
						
							|  |  |  |  |                                       signal_name, | 
					
						
							|  |  |  |  |                                       parameters, | 
					
						
							|  |  |  |  |                                       &error)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_dbus_connection_flush_sync (c, NULL, &error)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error flushing connection: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (c != NULL) | 
					
						
							|  |  |  |  |     g_object_unref (c); | 
					
						
							|  |  |  |  |   if (parameters != NULL) | 
					
						
							|  |  |  |  |     g_variant_unref (parameters); | 
					
						
							|  |  |  |  |   g_free (interface_name); | 
					
						
							|  |  |  |  |   g_free (signal_name); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | static gchar *opt_call_dest = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_call_object_path = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_call_method = NULL; | 
					
						
							| 
									
										
										
										
											2011-05-06 15:25:49 -04:00
										 |  |  |  | static gint opt_call_timeout = -1; | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  | static gboolean opt_call_interactive = FALSE; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry call_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_call_dest, N_("Destination name to invoke method on"), NULL}, | 
					
						
							|  |  |  |  |   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL}, | 
					
						
							|  |  |  |  |   { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL}, | 
					
						
							| 
									
										
										
										
											2011-05-06 15:25:49 -04:00
										 |  |  |  |   { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL}, | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  |   { "interactive", 'i', 0, G_OPTION_ARG_NONE, &opt_call_interactive, N_("Allow interactive authorization"), NULL}, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | handle_call (gint        *argc, | 
					
						
							|  |  |  |  |              gchar      **argv[], | 
					
						
							|  |  |  |  |              gboolean     request_completion, | 
					
						
							|  |  |  |  |              const gchar *completion_cur, | 
					
						
							|  |  |  |  |              const gchar *completion_prev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  |   GVariant *parameters; | 
					
						
							|  |  |  |  |   gchar *interface_name; | 
					
						
							|  |  |  |  |   gchar *method_name; | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GPtrArray *in_signature_types; | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							|  |  |  |  |   GUnixFDList *fd_list; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   gboolean complete_names; | 
					
						
							|  |  |  |  |   gboolean complete_paths; | 
					
						
							|  |  |  |  |   gboolean complete_methods; | 
					
						
							|  |  |  |  |   GVariantBuilder builder; | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |   gboolean skip_dashes; | 
					
						
							|  |  |  |  |   guint parm; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   guint n; | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  |   GDBusCallFlags flags; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  |   parameters = NULL; | 
					
						
							|  |  |  |  |   interface_name = NULL; | 
					
						
							|  |  |  |  |   method_name = NULL; | 
					
						
							|  |  |  |  |   result = NULL; | 
					
						
							|  |  |  |  |   in_signature_types = NULL; | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2025-02-26 18:14:51 +01:00
										 |  |  |  |   fd_list = g_unix_fd_list_new (); | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   modify_argv0_for_command (argc, argv, "call"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  |   o = command_option_context_new (NULL, _("Invoke a method on a remote object."), | 
					
						
							|  |  |  |  |                                   call_entries, request_completion); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_option_context_add_group (o, connection_get_group ()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_names = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_names = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_paths = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_paths = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_methods = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--method") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_methods = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_option_context_parse (o, argc, argv, NULL)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |           g_printerr ("%s", s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |   c = connection_get_dbus_connection (TRUE, &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (c == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 (completion_prev, "--address") == 0) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("unix:\n" | 
					
						
							|  |  |  |  |                        "tcp:\n" | 
					
						
							|  |  |  |  |                        "nonce-tcp:\n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("--system \n--session \n--address \n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error connecting: %s\n"), error->message); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-26 15:43:46 +01:00
										 |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* validate and complete destination (bus name) */ | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |   if (complete_names) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |       print_names (c, FALSE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (opt_call_dest == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--dest \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Destination is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, g_str_has_prefix (opt_call_dest, ":")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  |   if (!request_completion && !g_dbus_is_name (opt_call_dest)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid bus name\n"), opt_call_dest); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   /* validate and complete object path */ | 
					
						
							|  |  |  |  |   if (complete_paths) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_paths (c, opt_call_dest, "/"); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (opt_call_object_path == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--object-path \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Object path is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gchar *p; | 
					
						
							|  |  |  |  |       s = g_strdup (opt_call_object_path); | 
					
						
							|  |  |  |  |       p = strrchr (s, '/'); | 
					
						
							|  |  |  |  |       if (p != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (p == s) | 
					
						
							|  |  |  |  |             p++; | 
					
						
							|  |  |  |  |           *p = '\0'; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       print_paths (c, opt_call_dest, s); | 
					
						
							|  |  |  |  |       g_free (s); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (!request_completion && !g_variant_is_object_path (opt_call_object_path)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid object path\n"), opt_call_object_path); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* validate and complete method (interface + method name) */ | 
					
						
							|  |  |  |  |   if (complete_methods) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (opt_call_method == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--method \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Method name is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--method", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:55 +01:00
										 |  |  |  |       print_methods_and_signals (c, opt_call_dest, opt_call_object_path, TRUE, FALSE); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   s = strrchr (opt_call_method, '.'); | 
					
						
							|  |  |  |  |   if (!request_completion && s == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-09-30 05:47:15 +02:00
										 |  |  |  |       g_printerr (_("Error: Method name “%s” is invalid\n"), opt_call_method); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   method_name = g_strdup (s + 1); | 
					
						
							|  |  |  |  |   interface_name = g_strndup (opt_call_method, s - opt_call_method); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* All done with completion now */ | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Introspect, for easy conversion - it's not fatal if we can't do this */ | 
					
						
							|  |  |  |  |   in_signature_types = call_helper_get_method_in_signature (c, | 
					
						
							|  |  |  |  |                                                             opt_call_dest, | 
					
						
							|  |  |  |  |                                                             opt_call_object_path, | 
					
						
							|  |  |  |  |                                                             interface_name, | 
					
						
							|  |  |  |  |                                                             method_name, | 
					
						
							|  |  |  |  |                                                             &error); | 
					
						
							|  |  |  |  |   if (in_signature_types == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       //g_printerr ("Error getting introspection data: %s\n", error->message);
 | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       error = NULL; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Read parameters */ | 
					
						
							| 
									
										
										
										
											2024-09-25 11:09:07 -07:00
										 |  |  |  |   g_variant_builder_init_static (&builder, G_VARIANT_TYPE_TUPLE); | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |   skip_dashes = TRUE; | 
					
						
							|  |  |  |  |   parm = 0; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   for (n = 1; n < (guint) *argc; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       GVariant *value; | 
					
						
							|  |  |  |  |       GVariantType *type; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |       /* Under certain conditions, g_option_context_parse returns the "--"
 | 
					
						
							|  |  |  |  |          itself (setting off unparsed arguments), too: */ | 
					
						
							|  |  |  |  |       if (skip_dashes && g_strcmp0 ((*argv)[n], "--") == 0) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           skip_dashes = FALSE; | 
					
						
							|  |  |  |  |           continue; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       type = NULL; | 
					
						
							|  |  |  |  |       if (in_signature_types != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |           if (parm >= in_signature_types->len) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |             { | 
					
						
							|  |  |  |  |               /* Only warn for the first param */ | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |               if (parm == in_signature_types->len) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                 { | 
					
						
							|  |  |  |  |                   g_printerr ("Warning: Introspection data indicates %d parameters but more was passed\n", | 
					
						
							|  |  |  |  |                               in_signature_types->len); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |               type = in_signature_types->pdata[parm]; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       error = NULL; | 
					
						
							|  |  |  |  |       value = g_variant_parse (type, | 
					
						
							|  |  |  |  |                                (*argv)[n], | 
					
						
							|  |  |  |  |                                NULL, | 
					
						
							|  |  |  |  |                                NULL, | 
					
						
							|  |  |  |  |                                &error); | 
					
						
							|  |  |  |  |       if (value == NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |           gchar *context; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |           context = g_variant_parse_error_print_context (error, (*argv)[n]); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |           g_error_free (error); | 
					
						
							|  |  |  |  |           error = NULL; | 
					
						
							|  |  |  |  |           value = _g_variant_parse_me_harder (type, (*argv)[n], &error); | 
					
						
							|  |  |  |  |           if (value == NULL) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               if (type != NULL) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   s = g_variant_type_dup_string (type); | 
					
						
							| 
									
										
										
										
											2016-09-30 05:47:15 +02:00
										 |  |  |  |                   g_printerr (_("Error parsing parameter %d of type “%s”: %s\n"), | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |                               parm + 1, | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                               s, | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |                               context); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                   g_free (s); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |               else | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   g_printerr (_("Error parsing parameter %d: %s\n"), | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |                               parm + 1, | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |                               context); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                 } | 
					
						
							|  |  |  |  |               g_error_free (error); | 
					
						
							|  |  |  |  |               g_variant_builder_clear (&builder); | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |               g_free (context); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |               goto out; | 
					
						
							|  |  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-11-22 13:06:54 -05:00
										 |  |  |  |           g_free (context); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2025-02-26 18:14:51 +01:00
										 |  |  |  |       if (!walk_variant_for_handle (&builder, fd_list, value)) | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2025-02-26 18:14:51 +01:00
										 |  |  |  |           g_clear_pointer (&value, g_variant_unref); | 
					
						
							|  |  |  |  |           g_variant_builder_clear (&builder); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       g_variant_builder_add_value (&builder, value); | 
					
						
							| 
									
										
										
										
											2025-02-26 18:14:51 +01:00
										 |  |  |  | #endif
 | 
					
						
							|  |  |  |  |       g_clear_pointer (&value, g_variant_unref); | 
					
						
							| 
									
										
										
										
											2016-07-14 15:38:32 +02:00
										 |  |  |  |       ++parm; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   parameters = g_variant_builder_end (&builder); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (parameters != NULL) | 
					
						
							|  |  |  |  |     parameters = g_variant_ref_sink (parameters); | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   flags = G_DBUS_CALL_FLAGS_NONE; | 
					
						
							|  |  |  |  |   if (opt_call_interactive) | 
					
						
							|  |  |  |  |     flags |= G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							|  |  |  |  |   result = g_dbus_connection_call_with_unix_fd_list_sync (c, | 
					
						
							|  |  |  |  |                                                           opt_call_dest, | 
					
						
							|  |  |  |  |                                                           opt_call_object_path, | 
					
						
							|  |  |  |  |                                                           interface_name, | 
					
						
							|  |  |  |  |                                                           method_name, | 
					
						
							|  |  |  |  |                                                           parameters, | 
					
						
							|  |  |  |  |                                                           NULL, | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  |                                                           flags, | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  |                                                           opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout, | 
					
						
							|  |  |  |  |                                                           fd_list, | 
					
						
							|  |  |  |  |                                                           NULL, | 
					
						
							|  |  |  |  |                                                           NULL, | 
					
						
							|  |  |  |  |                                                           &error); | 
					
						
							|  |  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | 		  			opt_call_dest, | 
					
						
							|  |  |  |  | 					opt_call_object_path, | 
					
						
							|  |  |  |  | 					interface_name, | 
					
						
							|  |  |  |  | 					method_name, | 
					
						
							|  |  |  |  | 					parameters, | 
					
						
							|  |  |  |  | 					NULL, | 
					
						
							| 
									
										
										
										
											2021-11-11 10:37:43 +00:00
										 |  |  |  | 					flags, | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | 					opt_call_timeout > 0 ? opt_call_timeout * 1000 : opt_call_timeout, | 
					
						
							|  |  |  |  | 					NULL, | 
					
						
							|  |  |  |  | 					&error); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS) && in_signature_types != NULL) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  |           if (in_signature_types->len > 0) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-01-19 18:29:49 +01:00
										 |  |  |  |               GString *str; | 
					
						
							|  |  |  |  |               str = g_string_new (NULL); | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |               for (n = 0; n < in_signature_types->len; n++) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   GVariantType *type = in_signature_types->pdata[n]; | 
					
						
							| 
									
										
										
										
											2022-01-19 18:29:49 +01:00
										 |  |  |  |                   g_string_append_len (str, | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  |                                        g_variant_type_peek_string (type), | 
					
						
							|  |  |  |  |                                        g_variant_type_get_string_length (type)); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 18:29:49 +01:00
										 |  |  |  |               g_printerr ("(According to introspection data, you need to pass '%s')\n", str->str); | 
					
						
							|  |  |  |  |               g_string_free (str, TRUE); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  |           else | 
					
						
							|  |  |  |  |             g_printerr ("(According to introspection data, you need to pass no arguments)\n"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-28 10:48:00 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   s = g_variant_print (result, TRUE); | 
					
						
							|  |  |  |  |   g_print ("%s\n", s); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (in_signature_types != NULL) | 
					
						
							|  |  |  |  |     g_ptr_array_unref (in_signature_types); | 
					
						
							|  |  |  |  |   if (result != NULL) | 
					
						
							|  |  |  |  |     g_variant_unref (result); | 
					
						
							|  |  |  |  |   if (c != NULL) | 
					
						
							|  |  |  |  |     g_object_unref (c); | 
					
						
							|  |  |  |  |   if (parameters != NULL) | 
					
						
							|  |  |  |  |     g_variant_unref (parameters); | 
					
						
							|  |  |  |  |   g_free (interface_name); | 
					
						
							|  |  |  |  |   g_free (method_name); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							| 
									
										
										
										
											2020-11-06 17:19:27 +00:00
										 |  |  |  | #ifdef G_OS_UNIX
 | 
					
						
							|  |  |  |  |   g_clear_object (&fd_list); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  | static gchar *opt_introspect_dest = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_introspect_object_path = NULL; | 
					
						
							|  |  |  |  | static gboolean opt_introspect_xml = FALSE; | 
					
						
							|  |  |  |  | static gboolean opt_introspect_recurse = FALSE; | 
					
						
							|  |  |  |  | static gboolean opt_introspect_only_properties = FALSE; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  | /* Introspect colors */ | 
					
						
							|  |  |  |  | #define RESET_COLOR                 (use_colors? "\033[0m": "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_TITLE_COLOR      (use_colors? UNDERLINE: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_NODE_COLOR       (use_colors? RESET_COLOR: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_INTERFACE_COLOR  (use_colors? YELLOW: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_METHOD_COLOR     (use_colors? BLUE: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_SIGNAL_COLOR     (use_colors? BLUE: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_PROPERTY_COLOR   (use_colors? MAGENTA: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_INOUT_COLOR      (use_colors? RESET_COLOR: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_TYPE_COLOR       (use_colors? GREEN: "")
 | 
					
						
							|  |  |  |  | #define INTROSPECT_ANNOTATION_COLOR (use_colors? RESET_COLOR: "")
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | static void | 
					
						
							|  |  |  |  | dump_annotation (const GDBusAnnotationInfo *o, | 
					
						
							|  |  |  |  |                  guint indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                  gboolean ignore_indent, | 
					
						
							|  |  |  |  |                  gboolean use_colors) | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%s@%s(\"%s\")%s\n", | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |            ignore_indent ? 0 : indent, "", | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |            INTROSPECT_ANNOTATION_COLOR, o->key, o->value, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent + 2, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | static void | 
					
						
							|  |  |  |  | dump_arg (const GDBusArgInfo *o, | 
					
						
							|  |  |  |  |           guint indent, | 
					
						
							|  |  |  |  |           const gchar *direction, | 
					
						
							|  |  |  |  |           gboolean ignore_indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |           gboolean include_newline, | 
					
						
							|  |  |  |  |           gboolean use_colors) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |   guint n; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       dump_annotation (o->annotations[n], indent, ignore_indent, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |       ignore_indent = FALSE; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%s%s%s%s%s%s %s%s", | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |            ignore_indent ? 0 : indent, "", | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |            INTROSPECT_INOUT_COLOR, direction, RESET_COLOR, | 
					
						
							|  |  |  |  |            INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR, | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |            o->name, | 
					
						
							|  |  |  |  |            include_newline ? ",\n" : ""); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static guint | 
					
						
							|  |  |  |  | count_args (GDBusArgInfo **args) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   n = 0; | 
					
						
							|  |  |  |  |   if (args == NULL) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  |   while (args[n] != NULL) | 
					
						
							|  |  |  |  |     n++; | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   return n; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | dump_method (const GDBusMethodInfo *o, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |              guint                  indent, | 
					
						
							|  |  |  |  |              gboolean               use_colors) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   guint m; | 
					
						
							| 
									
										
										
										
											2024-04-25 00:37:47 +01:00
										 |  |  |  |   size_t name_len; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   guint total_num_args; | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%s%s%s(", | 
					
						
							|  |  |  |  |            indent, "", | 
					
						
							|  |  |  |  |            INTROSPECT_METHOD_COLOR, o->name, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   name_len = strlen (o->name); | 
					
						
							|  |  |  |  |   total_num_args = count_args (o->in_args) + count_args (o->out_args); | 
					
						
							|  |  |  |  |   for (n = 0, m = 0; o->in_args != NULL && o->in_args[n] != NULL; n++, m++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gboolean ignore_indent = (m == 0); | 
					
						
							|  |  |  |  |       gboolean include_newline = (m != total_num_args - 1); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       dump_arg (o->in_args[n], | 
					
						
							|  |  |  |  |                 indent + name_len + 1, | 
					
						
							|  |  |  |  |                 "in  ", | 
					
						
							|  |  |  |  |                 ignore_indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                 include_newline, | 
					
						
							|  |  |  |  |                 use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   for (n = 0; o->out_args != NULL && o->out_args[n] != NULL; n++, m++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gboolean ignore_indent = (m == 0); | 
					
						
							|  |  |  |  |       gboolean include_newline = (m != total_num_args - 1); | 
					
						
							|  |  |  |  |       dump_arg (o->out_args[n], | 
					
						
							|  |  |  |  |                 indent + name_len + 1, | 
					
						
							|  |  |  |  |                 "out ", | 
					
						
							|  |  |  |  |                 ignore_indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                 include_newline, | 
					
						
							|  |  |  |  |                 use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   g_print (");\n"); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | dump_signal (const GDBusSignalInfo *o, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |              guint                  indent, | 
					
						
							|  |  |  |  |              gboolean               use_colors) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   guint name_len; | 
					
						
							|  |  |  |  |   guint total_num_args; | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%s%s%s(", | 
					
						
							|  |  |  |  |            indent, "", | 
					
						
							|  |  |  |  |            INTROSPECT_SIGNAL_COLOR, o->name, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   name_len = strlen (o->name); | 
					
						
							|  |  |  |  |   total_num_args = count_args (o->args); | 
					
						
							|  |  |  |  |   for (n = 0; o->args != NULL && o->args[n] != NULL; n++) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gboolean ignore_indent = (n == 0); | 
					
						
							|  |  |  |  |       gboolean include_newline = (n != total_num_args - 1); | 
					
						
							|  |  |  |  |       dump_arg (o->args[n], | 
					
						
							|  |  |  |  |                 indent + name_len + 1, | 
					
						
							|  |  |  |  |                 "", | 
					
						
							|  |  |  |  |                 ignore_indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                 include_newline, | 
					
						
							|  |  |  |  |                 use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   g_print (");\n"); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | dump_property (const GDBusPropertyInfo *o, | 
					
						
							|  |  |  |  |                guint                    indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                gboolean                 use_colors, | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                GVariant                *value) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   const gchar *access; | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |   guint n; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_READABLE) | 
					
						
							|  |  |  |  |     access = "readonly"; | 
					
						
							|  |  |  |  |   else if (o->flags == G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE) | 
					
						
							|  |  |  |  |     access = "writeonly"; | 
					
						
							|  |  |  |  |   else if (o->flags == (G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE)) | 
					
						
							|  |  |  |  |     access = "readwrite"; | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     g_assert_not_reached (); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (value != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gchar *s = g_variant_print (value, FALSE); | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       g_print ("%*s%s %s%s%s %s%s%s = %s;\n", indent, "", access, | 
					
						
							|  |  |  |  |                INTROSPECT_TYPE_COLOR, o->signature, RESET_COLOR, | 
					
						
							|  |  |  |  |                INTROSPECT_PROPERTY_COLOR, o->name, RESET_COLOR, | 
					
						
							|  |  |  |  |                s); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       g_free (s); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_print ("%*s%s %s %s;\n", indent, "", access, o->signature, o->name); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | dump_interface (GDBusConnection          *c, | 
					
						
							|  |  |  |  |                 const gchar              *name, | 
					
						
							|  |  |  |  |                 const GDBusInterfaceInfo *o, | 
					
						
							|  |  |  |  |                 guint                     indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                 gboolean                  use_colors, | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                 const gchar              *object_path) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   GHashTable *properties; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   properties = g_hash_table_new_full (g_str_hash, | 
					
						
							|  |  |  |  |                                       g_str_equal, | 
					
						
							|  |  |  |  |                                       g_free, | 
					
						
							|  |  |  |  |                                       (GDestroyNotify) g_variant_unref); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Try to get properties */ | 
					
						
							| 
									
										
										
										
											2010-05-17 11:08:53 -04:00
										 |  |  |  |   if (c != NULL && name != NULL && object_path != NULL && o->properties != NULL) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							|  |  |  |  |       GVariant *result; | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |       result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                             name, | 
					
						
							|  |  |  |  |                                             object_path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                             DBUS_INTERFACE_PROPERTIES, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                             "GetAll", | 
					
						
							|  |  |  |  |                                             g_variant_new ("(s)", o->name), | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                             NULL, | 
					
						
							| 
									
										
										
										
											2010-05-10 11:47:08 -04:00
										 |  |  |  |                                             G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                             3000, | 
					
						
							|  |  |  |  |                                             NULL, | 
					
						
							|  |  |  |  |                                             NULL); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       if (result != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(a{sv})"))) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               GVariantIter *iter; | 
					
						
							|  |  |  |  |               GVariant *item; | 
					
						
							|  |  |  |  |               g_variant_get (result, | 
					
						
							|  |  |  |  |                              "(a{sv})", | 
					
						
							|  |  |  |  |                              &iter); | 
					
						
							|  |  |  |  |               while ((item = g_variant_iter_next_value (iter))) | 
					
						
							|  |  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2010-05-13 19:20:26 +02:00
										 |  |  |  |                   gchar *key; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                   GVariant *value; | 
					
						
							|  |  |  |  |                   g_variant_get (item, | 
					
						
							|  |  |  |  |                                  "{sv}", | 
					
						
							|  |  |  |  |                                  &key, | 
					
						
							|  |  |  |  |                                  &value); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-13 19:20:26 +02:00
										 |  |  |  |                   g_hash_table_insert (properties, key, g_variant_ref (value)); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           g_variant_unref (result); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-10 16:20:59 -04:00
										 |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           for (n = 0; o->properties != NULL && o->properties[n] != NULL; n++) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                                     name, | 
					
						
							|  |  |  |  |                                                     object_path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                                     DBUS_INTERFACE_PROPERTIES, | 
					
						
							| 
									
										
										
										
											2010-05-10 16:20:59 -04:00
										 |  |  |  |                                                     "Get", | 
					
						
							|  |  |  |  |                                                     g_variant_new ("(ss)", o->name, o->properties[n]->name), | 
					
						
							| 
									
										
										
										
											2010-05-24 16:46:24 -04:00
										 |  |  |  |                                                     G_VARIANT_TYPE ("(v)"), | 
					
						
							| 
									
										
										
										
											2010-05-10 16:20:59 -04:00
										 |  |  |  |                                                     G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                                     3000, | 
					
						
							|  |  |  |  |                                                     NULL, | 
					
						
							|  |  |  |  |                                                     NULL); | 
					
						
							|  |  |  |  |               if (result != NULL) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   GVariant *property_value; | 
					
						
							|  |  |  |  |                   g_variant_get (result, | 
					
						
							|  |  |  |  |                                  "(v)", | 
					
						
							|  |  |  |  |                                  &property_value); | 
					
						
							|  |  |  |  |                   g_hash_table_insert (properties, | 
					
						
							|  |  |  |  |                                        g_strdup (o->properties[n]->name), | 
					
						
							|  |  |  |  |                                        g_variant_ref (property_value)); | 
					
						
							|  |  |  |  |                   g_variant_unref (result); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%sinterface %s%s {\n", | 
					
						
							|  |  |  |  |            indent, "", | 
					
						
							|  |  |  |  |            INTROSPECT_INTERFACE_COLOR, o->name, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   if (o->methods != NULL && !opt_introspect_only_properties) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       g_print ("%*s  %smethods%s:\n", | 
					
						
							|  |  |  |  |                indent, "", | 
					
						
							|  |  |  |  |                INTROSPECT_TITLE_COLOR, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       for (n = 0; o->methods[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |         dump_method (o->methods[n], indent + 4, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   if (o->signals != NULL && !opt_introspect_only_properties) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       g_print ("%*s  %ssignals%s:\n", | 
					
						
							|  |  |  |  |                indent, "", | 
					
						
							|  |  |  |  |                INTROSPECT_TITLE_COLOR, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       for (n = 0; o->signals[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |         dump_signal (o->signals[n], indent + 4, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   if (o->properties != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       g_print ("%*s  %sproperties%s:\n", | 
					
						
							|  |  |  |  |                indent, "", | 
					
						
							|  |  |  |  |                INTROSPECT_TITLE_COLOR, RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       for (n = 0; o->properties[n] != NULL; n++) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           dump_property (o->properties[n], | 
					
						
							|  |  |  |  |                          indent + 4, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                          use_colors, | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |                          g_hash_table_lookup (properties, (o->properties[n])->name)); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_print ("%*s};\n", | 
					
						
							|  |  |  |  |            indent, ""); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   g_hash_table_unref (properties); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  | static gboolean | 
					
						
							|  |  |  |  | introspect_do (GDBusConnection *c, | 
					
						
							|  |  |  |  |                const gchar     *object_path, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                guint            indent, | 
					
						
							|  |  |  |  |                gboolean         use_colors); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | static void | 
					
						
							|  |  |  |  | dump_node (GDBusConnection      *c, | 
					
						
							|  |  |  |  |            const gchar          *name, | 
					
						
							|  |  |  |  |            const GDBusNodeInfo  *o, | 
					
						
							|  |  |  |  |            guint                 indent, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |            gboolean              use_colors, | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |            const gchar          *object_path, | 
					
						
							|  |  |  |  |            gboolean              recurse) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   guint n; | 
					
						
							|  |  |  |  |   const gchar *object_path_to_print; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   object_path_to_print = object_path; | 
					
						
							|  |  |  |  |   if (o->path != NULL) | 
					
						
							|  |  |  |  |     object_path_to_print = o->path; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  |   for (n = 0; o->annotations != NULL && o->annotations[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |     dump_annotation (o->annotations[n], indent, FALSE, use_colors); | 
					
						
							| 
									
										
										
										
											2010-05-12 22:09:18 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   g_print ("%*s%snode %s%s", | 
					
						
							|  |  |  |  |            indent, "", | 
					
						
							|  |  |  |  |            INTROSPECT_NODE_COLOR, | 
					
						
							|  |  |  |  |            object_path_to_print != NULL ? object_path_to_print : "(not set)", | 
					
						
							|  |  |  |  |            RESET_COLOR); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (o->interfaces != NULL || o->nodes != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_print (" {\n"); | 
					
						
							|  |  |  |  |       for (n = 0; o->interfaces != NULL && o->interfaces[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |         { | 
					
						
							|  |  |  |  |           if (opt_introspect_only_properties) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               if (o->interfaces[n]->properties != NULL && o->interfaces[n]->properties[0] != NULL) | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                 dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |               dump_interface (c, name, o->interfaces[n], indent + 2, use_colors, object_path); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       for (n = 0; o->nodes != NULL && o->nodes[n] != NULL; n++) | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |         { | 
					
						
							|  |  |  |  |           if (recurse) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               gchar *child_path; | 
					
						
							|  |  |  |  |               if (g_variant_is_object_path (o->nodes[n]->path)) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   child_path = g_strdup (o->nodes[n]->path); | 
					
						
							|  |  |  |  |                   /* avoid infinite loops */ | 
					
						
							|  |  |  |  |                   if (g_str_has_prefix (child_path, object_path)) | 
					
						
							|  |  |  |  |                     { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                       introspect_do (c, child_path, indent + 2, use_colors); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |                     } | 
					
						
							|  |  |  |  |                   else | 
					
						
							|  |  |  |  |                     { | 
					
						
							|  |  |  |  |                       g_print ("Skipping path %s that is not enclosed by parent %s\n", | 
					
						
							|  |  |  |  |                                child_path, object_path); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |               else | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   if (g_strcmp0 (object_path, "/") == 0) | 
					
						
							|  |  |  |  |                     child_path = g_strdup_printf ("/%s", o->nodes[n]->path); | 
					
						
							|  |  |  |  |                   else | 
					
						
							|  |  |  |  |                     child_path = g_strdup_printf ("%s/%s", object_path, o->nodes[n]->path); | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                   introspect_do (c, child_path, indent + 2, use_colors); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |                 } | 
					
						
							|  |  |  |  |               g_free (child_path); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |               dump_node (NULL, NULL, o->nodes[n], indent + 2, use_colors, NULL, recurse); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       g_print ("%*s};\n", | 
					
						
							|  |  |  |  |                indent, ""); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_print ("\n"); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry introspect_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_introspect_dest, N_("Destination name to introspect"), NULL}, | 
					
						
							|  |  |  |  |   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_introspect_object_path, N_("Object path to introspect"), NULL}, | 
					
						
							| 
									
										
										
										
											2010-06-13 15:16:33 +02:00
										 |  |  |  |   { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL}, | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL}, | 
					
						
							|  |  |  |  |   { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL}, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  | static gboolean | 
					
						
							|  |  |  |  | introspect_do (GDBusConnection *c, | 
					
						
							|  |  |  |  |                const gchar     *object_path, | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |                guint            indent, | 
					
						
							|  |  |  |  |                gboolean         use_colors) | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GVariant *result; | 
					
						
							|  |  |  |  |   GDBusNodeInfo *node; | 
					
						
							|  |  |  |  |   gboolean ret; | 
					
						
							|  |  |  |  |   const gchar *xml_data; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   node = NULL; | 
					
						
							|  |  |  |  |   result = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:29:58 -04:00
										 |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   result = g_dbus_connection_call_sync (c, | 
					
						
							|  |  |  |  |                                         opt_introspect_dest, | 
					
						
							|  |  |  |  |                                         object_path, | 
					
						
							| 
									
										
										
										
											2024-05-13 13:00:34 +01:00
										 |  |  |  |                                         DBUS_INTERFACE_INTROSPECTABLE, | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |                                         "Introspect", | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         G_VARIANT_TYPE ("(s)"), | 
					
						
							|  |  |  |  |                                         G_DBUS_CALL_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                         3000, /* 3 sec */ | 
					
						
							|  |  |  |  |                                         NULL, | 
					
						
							|  |  |  |  |                                         &error); | 
					
						
							|  |  |  |  |   if (result == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s\n"), error->message); | 
					
						
							|  |  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   g_variant_get (result, "(&s)", &xml_data); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (opt_introspect_xml) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_print ("%s", xml_data); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       error = NULL; | 
					
						
							|  |  |  |  |       node = g_dbus_node_info_new_for_xml (xml_data, &error); | 
					
						
							|  |  |  |  |       if (node == NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error parsing introspection XML: %s\n"), error->message); | 
					
						
							|  |  |  |  |           g_error_free (error); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |       dump_node (c, opt_introspect_dest, node, indent, use_colors, object_path, opt_introspect_recurse); | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (node != NULL) | 
					
						
							|  |  |  |  |     g_dbus_node_info_unref (node); | 
					
						
							|  |  |  |  |   if (result != NULL) | 
					
						
							|  |  |  |  |     g_variant_unref (result); | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | static gboolean | 
					
						
							|  |  |  |  | handle_introspect (gint        *argc, | 
					
						
							|  |  |  |  |                    gchar      **argv[], | 
					
						
							|  |  |  |  |                    gboolean     request_completion, | 
					
						
							|  |  |  |  |                    const gchar *completion_cur, | 
					
						
							|  |  |  |  |                    const gchar *completion_prev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  |   gboolean complete_names; | 
					
						
							|  |  |  |  |   gboolean complete_paths; | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   gboolean color_support; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   modify_argv0_for_command (argc, argv, "introspect"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  |   o = command_option_context_new (NULL, _("Introspect a remote object."), | 
					
						
							|  |  |  |  |                                   introspect_entries, request_completion); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   g_option_context_add_group (o, connection_get_group ()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_names = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_names = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_paths = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_paths = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_option_context_parse (o, argc, argv, NULL)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |           g_printerr ("%s", s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |   c = connection_get_dbus_connection (TRUE, &error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (c == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 (completion_prev, "--address") == 0) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("unix:\n" | 
					
						
							|  |  |  |  |                        "tcp:\n" | 
					
						
							|  |  |  |  |                        "nonce-tcp:\n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("--system \n--session \n--address \n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error connecting: %s\n"), error->message); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-26 15:43:46 +01:00
										 |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |   if (complete_names) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |       print_names (c, FALSE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |   /* this only makes sense on message bus connections */ | 
					
						
							|  |  |  |  |   if (opt_introspect_dest == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--dest \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Destination is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, g_str_has_prefix (opt_introspect_dest, ":")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (complete_paths) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_paths (c, opt_introspect_dest, "/"); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!request_completion && !g_dbus_is_name (opt_introspect_dest)) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:46:37 +01:00
										 |  |  |  |       g_printerr (_("Error: %s is not a valid bus name\n"), opt_introspect_dest); | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   if (opt_introspect_object_path == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--object-path \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Object path is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gchar *p; | 
					
						
							|  |  |  |  |       s = g_strdup (opt_introspect_object_path); | 
					
						
							|  |  |  |  |       p = strrchr (s, '/'); | 
					
						
							|  |  |  |  |       if (p != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (p == s) | 
					
						
							|  |  |  |  |             p++; | 
					
						
							|  |  |  |  |           *p = '\0'; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       print_paths (c, opt_introspect_dest, s); | 
					
						
							|  |  |  |  |       g_free (s); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (!request_completion && !g_variant_is_object_path (opt_introspect_object_path)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid object path\n"), opt_introspect_object_path); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_recurse) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |       g_print ("--recurse \n"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   if (request_completion && opt_introspect_object_path != NULL && !opt_introspect_only_properties) | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |       g_print ("--only-properties \n"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |   /* All done with completion now */ | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 18:11:22 +02:00
										 |  |  |  |   /* Before we start printing the actual info, check if we can do colors*/ | 
					
						
							|  |  |  |  |   color_support = g_log_writer_supports_color (fileno (stdout)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!introspect_do (c, opt_introspect_object_path, 0, color_support)) | 
					
						
							| 
									
										
										
										
											2011-06-09 13:22:18 -04:00
										 |  |  |  |     goto out; | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (c != NULL) | 
					
						
							|  |  |  |  |     g_object_unref (c); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  | static gchar *opt_monitor_dest = NULL; | 
					
						
							|  |  |  |  | static gchar *opt_monitor_object_path = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static guint monitor_filter_id = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | monitor_signal_cb (GDBusConnection *connection, | 
					
						
							|  |  |  |  |                    const gchar     *sender_name, | 
					
						
							|  |  |  |  |                    const gchar     *object_path, | 
					
						
							|  |  |  |  |                    const gchar     *interface_name, | 
					
						
							|  |  |  |  |                    const gchar     *signal_name, | 
					
						
							|  |  |  |  |                    GVariant        *parameters, | 
					
						
							|  |  |  |  |                    gpointer         user_data) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   s = g_variant_print (parameters, TRUE); | 
					
						
							|  |  |  |  |   g_print ("%s: %s.%s %s\n", | 
					
						
							|  |  |  |  |            object_path, | 
					
						
							|  |  |  |  |            interface_name, | 
					
						
							|  |  |  |  |            signal_name, | 
					
						
							|  |  |  |  |            s); | 
					
						
							|  |  |  |  |   g_free (s); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | monitor_on_name_appeared (GDBusConnection *connection, | 
					
						
							|  |  |  |  |                           const gchar *name, | 
					
						
							|  |  |  |  |                           const gchar *name_owner, | 
					
						
							|  |  |  |  |                           gpointer user_data) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   g_print ("The name %s is owned by %s\n", name, name_owner); | 
					
						
							|  |  |  |  |   g_assert (monitor_filter_id == 0); | 
					
						
							|  |  |  |  |   monitor_filter_id = g_dbus_connection_signal_subscribe (connection, | 
					
						
							|  |  |  |  |                                                           name_owner, | 
					
						
							|  |  |  |  |                                                           NULL,  /* any interface */ | 
					
						
							|  |  |  |  |                                                           NULL,  /* any member */ | 
					
						
							|  |  |  |  |                                                           opt_monitor_object_path, | 
					
						
							|  |  |  |  |                                                           NULL,  /* arg0 */ | 
					
						
							| 
									
										
										
										
											2010-07-19 15:03:00 -04:00
										 |  |  |  |                                                           G_DBUS_SIGNAL_FLAGS_NONE, | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |                                                           monitor_signal_cb, | 
					
						
							|  |  |  |  |                                                           NULL,  /* user_data */ | 
					
						
							|  |  |  |  |                                                           NULL); /* user_data destroy notify */ | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | monitor_on_name_vanished (GDBusConnection *connection, | 
					
						
							|  |  |  |  |                           const gchar *name, | 
					
						
							|  |  |  |  |                           gpointer user_data) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   g_print ("The name %s does not have an owner\n", name); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (monitor_filter_id != 0) | 
					
						
							| 
									
										
										
										
											2024-10-08 13:55:22 +01:00
										 |  |  |  |     g_dbus_connection_signal_unsubscribe (connection, g_steal_handle_id (&monitor_filter_id)); | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry monitor_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL}, | 
					
						
							|  |  |  |  |   { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL}, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | handle_monitor (gint        *argc, | 
					
						
							|  |  |  |  |                 gchar      **argv[], | 
					
						
							|  |  |  |  |                 gboolean     request_completion, | 
					
						
							|  |  |  |  |                 const gchar *completion_cur, | 
					
						
							|  |  |  |  |                 const gchar *completion_prev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  |   gboolean complete_names; | 
					
						
							|  |  |  |  |   gboolean complete_paths; | 
					
						
							|  |  |  |  |   GMainLoop *loop; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   modify_argv0_for_command (argc, argv, "monitor"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  |   o = command_option_context_new (NULL, _("Monitor a remote object."), | 
					
						
							|  |  |  |  |                                   monitor_entries, request_completion); | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |   g_option_context_add_group (o, connection_get_group ()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_names = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--dest") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_names = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   complete_paths = FALSE; | 
					
						
							|  |  |  |  |   if (request_completion && *argc > 1 && g_strcmp0 ((*argv)[(*argc)-1], "--object-path") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       complete_paths = TRUE; | 
					
						
							|  |  |  |  |       remove_arg ((*argc) - 1, argc, argv); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_option_context_parse (o, argc, argv, NULL)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |           g_printerr ("%s", s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |   c = connection_get_dbus_connection (TRUE, &error); | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |   if (c == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 (completion_prev, "--address") == 0) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("unix:\n" | 
					
						
							|  |  |  |  |                        "tcp:\n" | 
					
						
							|  |  |  |  |                        "nonce-tcp:\n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("--system \n--session \n--address \n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error connecting: %s\n"), error->message); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-26 15:43:46 +01:00
										 |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |   /* Monitoring doesn’t make sense on a non-message-bus connection. */ | 
					
						
							|  |  |  |  |   if (g_dbus_connection_get_unique_name (c) == NULL) | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-10-09 10:44:47 +01:00
										 |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         g_printerr (_("Error: can’t monitor a non-message-bus connection\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (complete_names) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, FALSE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   /* this only makes sense on message bus connections */ | 
					
						
							|  |  |  |  |   if (opt_monitor_dest == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         g_print ("--dest \n"); | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         g_printerr (_("Error: Destination is not specified\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--dest", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_names (c, g_str_has_prefix (opt_monitor_dest, ":")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-08 22:07:26 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!request_completion && !g_dbus_is_name (opt_monitor_dest)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid bus name\n"), opt_monitor_dest); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |   if (complete_paths) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       print_paths (c, opt_monitor_dest, "/"); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (opt_monitor_object_path == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_print ("--object-path \n"); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       /* it's fine to not have an object path */ | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (request_completion && g_strcmp0 ("--object-path", completion_prev) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       gchar *p; | 
					
						
							|  |  |  |  |       s = g_strdup (opt_monitor_object_path); | 
					
						
							|  |  |  |  |       p = strrchr (s, '/'); | 
					
						
							|  |  |  |  |       if (p != NULL) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (p == s) | 
					
						
							|  |  |  |  |             p++; | 
					
						
							|  |  |  |  |           *p = '\0'; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       print_paths (c, opt_monitor_dest, s); | 
					
						
							|  |  |  |  |       g_free (s); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   if (!request_completion && (opt_monitor_object_path != NULL && !g_variant_is_object_path (opt_monitor_object_path))) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid object path\n"), opt_monitor_object_path); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* All done with completion now */ | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (opt_monitor_object_path != NULL) | 
					
						
							|  |  |  |  |     g_print ("Monitoring signals on object %s owned by %s\n", opt_monitor_object_path, opt_monitor_dest); | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     g_print ("Monitoring signals from all objects owned by %s\n", opt_monitor_dest); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   loop = g_main_loop_new (NULL, FALSE); | 
					
						
							|  |  |  |  |   g_bus_watch_name_on_connection (c, | 
					
						
							|  |  |  |  |                                   opt_monitor_dest, | 
					
						
							|  |  |  |  |                                   G_BUS_NAME_WATCHER_FLAGS_AUTO_START, | 
					
						
							|  |  |  |  |                                   monitor_on_name_appeared, | 
					
						
							|  |  |  |  |                                   monitor_on_name_vanished, | 
					
						
							|  |  |  |  |                                   NULL, | 
					
						
							|  |  |  |  |                                   NULL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   g_main_loop_run (loop); | 
					
						
							|  |  |  |  |   g_main_loop_unref (loop); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   if (c != NULL) | 
					
						
							|  |  |  |  |     g_object_unref (c); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  | static gboolean opt_wait_activate_set = FALSE; | 
					
						
							|  |  |  |  | static gchar *opt_wait_activate_name = NULL; | 
					
						
							| 
									
										
										
										
											2019-03-27 17:04:58 +00:00
										 |  |  |  | static gint64 opt_wait_timeout_secs = 0;  /* no timeout */ | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | typedef enum { | 
					
						
							|  |  |  |  |   WAIT_STATE_RUNNING,  /* waiting to see the service */ | 
					
						
							|  |  |  |  |   WAIT_STATE_SUCCESS,  /* seen it successfully */ | 
					
						
							|  |  |  |  |   WAIT_STATE_TIMEOUT,  /* timed out before seeing it */ | 
					
						
							|  |  |  |  | } WaitState; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | opt_wait_activate_cb (const gchar  *option_name, | 
					
						
							|  |  |  |  |                       const gchar  *value, | 
					
						
							|  |  |  |  |                       gpointer      data, | 
					
						
							|  |  |  |  |                       GError      **error) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   /* @value may be NULL */ | 
					
						
							|  |  |  |  |   opt_wait_activate_set = TRUE; | 
					
						
							|  |  |  |  |   opt_wait_activate_name = g_strdup (value); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return TRUE; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static const GOptionEntry wait_entries[] = | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   { "activate", 'a', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, | 
					
						
							|  |  |  |  |     opt_wait_activate_cb, | 
					
						
							|  |  |  |  |     N_("Service to activate before waiting for the other one (well-known name)"), | 
					
						
							|  |  |  |  |     "[NAME]" }, | 
					
						
							| 
									
										
										
										
											2019-03-27 17:04:58 +00:00
										 |  |  |  |   { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout_secs, | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |     N_("Timeout to wait for before exiting with an error (seconds); 0 for " | 
					
						
							|  |  |  |  |        "no timeout (default)"), "SECS" }, | 
					
						
							| 
									
										
										
										
											2021-05-13 20:16:46 +00:00
										 |  |  |  |   G_OPTION_ENTRY_NULL | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | wait_name_appeared_cb (GDBusConnection *connection, | 
					
						
							|  |  |  |  |                        const gchar     *name, | 
					
						
							|  |  |  |  |                        const gchar     *name_owner, | 
					
						
							|  |  |  |  |                        gpointer         user_data) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   WaitState *wait_state = user_data; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   *wait_state = WAIT_STATE_SUCCESS; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | wait_timeout_cb (gpointer user_data) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   WaitState *wait_state = user_data; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   *wait_state = WAIT_STATE_TIMEOUT; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Removed in handle_wait(). */ | 
					
						
							|  |  |  |  |   return G_SOURCE_CONTINUE; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static gboolean | 
					
						
							|  |  |  |  | handle_wait (gint        *argc, | 
					
						
							|  |  |  |  |              gchar      **argv[], | 
					
						
							|  |  |  |  |              gboolean     request_completion, | 
					
						
							|  |  |  |  |              const gchar *completion_cur, | 
					
						
							|  |  |  |  |              const gchar *completion_prev) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   GOptionContext *o; | 
					
						
							|  |  |  |  |   gchar *s; | 
					
						
							|  |  |  |  |   GError *error; | 
					
						
							|  |  |  |  |   GDBusConnection *c; | 
					
						
							|  |  |  |  |   guint watch_id, timer_id = 0, activate_watch_id; | 
					
						
							|  |  |  |  |   const gchar *activate_service, *wait_service; | 
					
						
							|  |  |  |  |   WaitState wait_state = WAIT_STATE_RUNNING; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = FALSE; | 
					
						
							|  |  |  |  |   c = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   modify_argv0_for_command (argc, argv, "wait"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 14:20:59 +00:00
										 |  |  |  |   o = command_option_context_new (_("[OPTION…] BUS-NAME"), | 
					
						
							|  |  |  |  |                                   _("Wait for a bus name to appear."), | 
					
						
							|  |  |  |  |                                   wait_entries, request_completion); | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |   g_option_context_add_group (o, connection_get_group ()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_option_context_parse (o, argc, argv, NULL)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (!request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           s = g_option_context_get_help (o, FALSE, NULL); | 
					
						
							|  |  |  |  |           g_printerr ("%s", s); | 
					
						
							|  |  |  |  |           g_free (s); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   error = NULL; | 
					
						
							| 
									
										
										
										
											2019-06-17 14:52:12 +01:00
										 |  |  |  |   c = connection_get_dbus_connection (TRUE, &error); | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |   if (c == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           if (g_strcmp0 (completion_prev, "--address") == 0) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("unix:\n" | 
					
						
							|  |  |  |  |                        "tcp:\n" | 
					
						
							|  |  |  |  |                        "nonce-tcp:\n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |           else | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               g_print ("--system \n--session \n--address \n"); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           g_printerr (_("Error connecting: %s\n"), error->message); | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-26 15:43:46 +01:00
										 |  |  |  |       g_error_free (error); | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* All done with completion now */ | 
					
						
							|  |  |  |  |   if (request_completion) | 
					
						
							|  |  |  |  |     goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /*
 | 
					
						
							|  |  |  |  |    * Try and disentangle the command line arguments, with the aim of supporting: | 
					
						
							|  |  |  |  |    *    gdbus wait --session --activate ActivateName WaitName | 
					
						
							|  |  |  |  |    *    gdbus wait --session --activate ActivateAndWaitName | 
					
						
							|  |  |  |  |    *    gdbus wait --activate --session ActivateAndWaitName | 
					
						
							|  |  |  |  |    *    gdbus wait --session WaitName | 
					
						
							|  |  |  |  |    */ | 
					
						
							|  |  |  |  |   if (*argc == 2 && opt_wait_activate_set && opt_wait_activate_name != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_service = opt_wait_activate_name; | 
					
						
							|  |  |  |  |       wait_service = (*argv)[1]; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (*argc == 2 && | 
					
						
							|  |  |  |  |            opt_wait_activate_set && opt_wait_activate_name == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_service = (*argv)[1]; | 
					
						
							|  |  |  |  |       wait_service = (*argv)[1]; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (*argc == 2 && !opt_wait_activate_set) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_service = NULL;  /* disabled */ | 
					
						
							|  |  |  |  |       wait_service = (*argv)[1]; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (*argc == 1 && | 
					
						
							|  |  |  |  |            opt_wait_activate_set && opt_wait_activate_name != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_service = opt_wait_activate_name; | 
					
						
							|  |  |  |  |       wait_service = opt_wait_activate_name; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (*argc == 1 && | 
					
						
							|  |  |  |  |            opt_wait_activate_set && opt_wait_activate_name == NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: A service to activate for must be specified.\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (*argc == 1 && !opt_wait_activate_set) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: A service to wait for must be specified.\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else /* if (*argc > 2) */ | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: Too many arguments.\n")); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (activate_service != NULL && | 
					
						
							|  |  |  |  |       (!g_dbus_is_name (activate_service) || | 
					
						
							|  |  |  |  |        g_dbus_is_unique_name (activate_service))) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid well-known bus name.\n"), | 
					
						
							|  |  |  |  |                   activate_service); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!g_dbus_is_name (wait_service) || g_dbus_is_unique_name (wait_service)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_printerr (_("Error: %s is not a valid well-known bus name.\n"), | 
					
						
							|  |  |  |  |                   wait_service); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Start the prerequisite service if needed. */ | 
					
						
							|  |  |  |  |   if (activate_service != NULL) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_watch_id = g_bus_watch_name_on_connection (c, activate_service, | 
					
						
							|  |  |  |  |                                                           G_BUS_NAME_WATCHER_FLAGS_AUTO_START, | 
					
						
							|  |  |  |  |                                                           NULL, NULL, | 
					
						
							|  |  |  |  |                                                           NULL, NULL); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       activate_watch_id = 0; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Wait for the expected name to appear. */ | 
					
						
							|  |  |  |  |   watch_id = g_bus_watch_name_on_connection (c, | 
					
						
							|  |  |  |  |                                              wait_service, | 
					
						
							|  |  |  |  |                                              G_BUS_NAME_WATCHER_FLAGS_NONE, | 
					
						
							|  |  |  |  |                                              wait_name_appeared_cb, | 
					
						
							|  |  |  |  |                                              NULL, &wait_state, NULL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Safety timeout. */ | 
					
						
							| 
									
										
										
										
											2019-03-27 17:04:58 +00:00
										 |  |  |  |   if (opt_wait_timeout_secs > 0) | 
					
						
							|  |  |  |  |     timer_id = g_timeout_add_seconds (opt_wait_timeout_secs, wait_timeout_cb, &wait_state); | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   while (wait_state == WAIT_STATE_RUNNING) | 
					
						
							|  |  |  |  |     g_main_context_iteration (NULL, TRUE); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   g_bus_unwatch_name (watch_id); | 
					
						
							|  |  |  |  |   if (timer_id != 0) | 
					
						
							|  |  |  |  |       g_source_remove (timer_id); | 
					
						
							|  |  |  |  |   if (activate_watch_id != 0) | 
					
						
							|  |  |  |  |       g_bus_unwatch_name (activate_watch_id); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ret = (wait_state == WAIT_STATE_SUCCESS); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   g_clear_object (&c); | 
					
						
							|  |  |  |  |   g_option_context_free (o); | 
					
						
							|  |  |  |  |   g_free (opt_wait_activate_name); | 
					
						
							|  |  |  |  |   opt_wait_activate_name = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* ---------------------------------------------------------------------------------------------------- */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | static gchar * | 
					
						
							|  |  |  |  | pick_word_at (const gchar  *s, | 
					
						
							|  |  |  |  |               gint          cursor, | 
					
						
							|  |  |  |  |               gint         *out_word_begins_at) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint begin; | 
					
						
							|  |  |  |  |   gint end; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (s[0] == '\0') | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (out_word_begins_at != NULL) | 
					
						
							|  |  |  |  |         *out_word_begins_at = -1; | 
					
						
							|  |  |  |  |       return NULL; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0)) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (out_word_begins_at != NULL) | 
					
						
							|  |  |  |  |         *out_word_begins_at = cursor; | 
					
						
							|  |  |  |  |       return g_strdup (""); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0) | 
					
						
							|  |  |  |  |     cursor--; | 
					
						
							|  |  |  |  |   begin = cursor; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   end = begin; | 
					
						
							|  |  |  |  |   while (!g_ascii_isspace (s[end]) && s[end] != '\0') | 
					
						
							|  |  |  |  |     end++; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (out_word_begins_at != NULL) | 
					
						
							|  |  |  |  |     *out_word_begins_at = begin; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return g_strndup (s + begin, end - begin); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | gint | 
					
						
							|  |  |  |  | main (gint argc, gchar *argv[]) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   gint ret; | 
					
						
							|  |  |  |  |   const gchar *command; | 
					
						
							|  |  |  |  |   gboolean request_completion; | 
					
						
							|  |  |  |  |   gchar *completion_cur; | 
					
						
							|  |  |  |  |   gchar *completion_prev; | 
					
						
							| 
									
										
										
										
											2012-11-10 10:51:18 -05:00
										 |  |  |  | #ifdef G_OS_WIN32
 | 
					
						
							|  |  |  |  |   gchar *tmp; | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-12 12:26:26 -05:00
										 |  |  |  |   setlocale (LC_ALL, ""); | 
					
						
							|  |  |  |  |   textdomain (GETTEXT_PACKAGE); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #ifdef G_OS_WIN32
 | 
					
						
							| 
									
										
										
										
											2012-11-10 10:51:18 -05:00
										 |  |  |  |   tmp = _glib_get_locale_dir (); | 
					
						
							| 
									
										
										
										
											2011-02-12 12:26:26 -05:00
										 |  |  |  |   bindtextdomain (GETTEXT_PACKAGE, tmp); | 
					
						
							|  |  |  |  |   g_free (tmp); | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  |   bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
 | 
					
						
							|  |  |  |  |   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   ret = 1; | 
					
						
							|  |  |  |  |   completion_cur = NULL; | 
					
						
							|  |  |  |  |   completion_prev = NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (argc < 2) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       usage (&argc, &argv, FALSE); | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   request_completion = FALSE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  again: | 
					
						
							|  |  |  |  |   command = argv[1]; | 
					
						
							|  |  |  |  |   if (g_strcmp0 (command, "help") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           /* do nothing */ | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           usage (&argc, &argv, TRUE); | 
					
						
							|  |  |  |  |           ret = 0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-04 12:33:39 -04:00
										 |  |  |  |   else if (g_strcmp0 (command, "emit") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (handle_emit (&argc, | 
					
						
							|  |  |  |  |                        &argv, | 
					
						
							|  |  |  |  |                        request_completion, | 
					
						
							|  |  |  |  |                        completion_cur, | 
					
						
							|  |  |  |  |                        completion_prev)) | 
					
						
							|  |  |  |  |         ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   else if (g_strcmp0 (command, "call") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (handle_call (&argc, | 
					
						
							|  |  |  |  |                        &argv, | 
					
						
							|  |  |  |  |                        request_completion, | 
					
						
							|  |  |  |  |                        completion_cur, | 
					
						
							|  |  |  |  |                        completion_prev)) | 
					
						
							|  |  |  |  |         ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else if (g_strcmp0 (command, "introspect") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (handle_introspect (&argc, | 
					
						
							|  |  |  |  |                              &argv, | 
					
						
							|  |  |  |  |                              request_completion, | 
					
						
							|  |  |  |  |                              completion_cur, | 
					
						
							|  |  |  |  |                              completion_prev)) | 
					
						
							|  |  |  |  |         ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-12 23:12:14 -04:00
										 |  |  |  |   else if (g_strcmp0 (command, "monitor") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (handle_monitor (&argc, | 
					
						
							|  |  |  |  |                           &argv, | 
					
						
							|  |  |  |  |                           request_completion, | 
					
						
							|  |  |  |  |                           completion_cur, | 
					
						
							|  |  |  |  |                           completion_prev)) | 
					
						
							|  |  |  |  |         ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |   else if (g_strcmp0 (command, "wait") == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (handle_wait (&argc, | 
					
						
							|  |  |  |  |                        &argv, | 
					
						
							|  |  |  |  |                        request_completion, | 
					
						
							|  |  |  |  |                        completion_cur, | 
					
						
							|  |  |  |  |                        completion_prev)) | 
					
						
							|  |  |  |  |         ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-28 23:12:47 +03:00
										 |  |  |  | #ifdef G_OS_WIN32
 | 
					
						
							|  |  |  |  |   else if (g_strcmp0 (command, _GDBUS_ARG_WIN32_RUN_SESSION_BUS) == 0) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       g_win32_run_session_bus (NULL, NULL, NULL, 0); | 
					
						
							|  |  |  |  |       ret = 0; | 
					
						
							|  |  |  |  |       goto out; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |   else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       const gchar *completion_line; | 
					
						
							|  |  |  |  |       gchar **completion_argv; | 
					
						
							|  |  |  |  |       gint completion_argc; | 
					
						
							|  |  |  |  |       gint completion_point; | 
					
						
							|  |  |  |  |       gchar *endp; | 
					
						
							|  |  |  |  |       gint cur_begin; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       request_completion = TRUE; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       completion_line = argv[2]; | 
					
						
							|  |  |  |  |       completion_point = strtol (argv[3], &endp, 10); | 
					
						
							|  |  |  |  |       if (endp == argv[3] || *endp != '\0') | 
					
						
							|  |  |  |  |         goto out; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if 0
 | 
					
						
							|  |  |  |  |       completion_debug ("completion_point=%d", completion_point); | 
					
						
							|  |  |  |  |       completion_debug ("----"); | 
					
						
							|  |  |  |  |       completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789"); | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |       completion_debug ("'%s'", completion_line); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |       completion_debug (" %*s^", | 
					
						
							|  |  |  |  |                          completion_point, ""); | 
					
						
							|  |  |  |  |       completion_debug ("----"); | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (!g_shell_parse_argv (completion_line, | 
					
						
							|  |  |  |  |                                &completion_argc, | 
					
						
							|  |  |  |  |                                &completion_argv, | 
					
						
							|  |  |  |  |                                NULL)) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           /* it's very possible the command line can't be parsed (for
 | 
					
						
							|  |  |  |  |            * example, missing quotes etc) - in that case, we just | 
					
						
							|  |  |  |  |            * don't autocomplete at all | 
					
						
							|  |  |  |  |            */ | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* compute cur and prev */ | 
					
						
							|  |  |  |  |       completion_prev = NULL; | 
					
						
							|  |  |  |  |       completion_cur = pick_word_at (completion_line, completion_point, &cur_begin); | 
					
						
							|  |  |  |  |       if (cur_begin > 0) | 
					
						
							|  |  |  |  |         { | 
					
						
							|  |  |  |  |           gint prev_end; | 
					
						
							|  |  |  |  |           for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--) | 
					
						
							|  |  |  |  |             { | 
					
						
							|  |  |  |  |               if (!g_ascii_isspace (completion_line[prev_end])) | 
					
						
							|  |  |  |  |                 { | 
					
						
							|  |  |  |  |                   completion_prev = pick_word_at (completion_line, prev_end, NULL); | 
					
						
							|  |  |  |  |                   break; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |       completion_debug (" cur='%s'", completion_cur); | 
					
						
							|  |  |  |  |       completion_debug ("prev='%s'", completion_prev); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       argc = completion_argc; | 
					
						
							|  |  |  |  |       argv = completion_argv; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       ret = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       goto again; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       if (request_completion) | 
					
						
							|  |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-03-10 15:01:13 +00:00
										 |  |  |  |           g_print ("help \nemit \ncall \nintrospect \nmonitor \nwait \n"); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |           ret = 0; | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         { | 
					
						
							| 
									
										
										
										
											2013-05-20 17:54:48 -03:00
										 |  |  |  |           g_printerr ("Unknown command '%s'\n", command); | 
					
						
							| 
									
										
										
										
											2010-05-06 14:13:59 -04:00
										 |  |  |  |           usage (&argc, &argv, FALSE); | 
					
						
							|  |  |  |  |           goto out; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  out: | 
					
						
							|  |  |  |  |   g_free (completion_cur); | 
					
						
							|  |  |  |  |   g_free (completion_prev); | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } |