1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-bash-completion-helper.c Bash Completion helper routines
4 * Copyright (C) 2008 David Zeuthen <davidz@redhat.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <dbus/dbus.h>
30 #include "dbus-gparser.h"
33 print_services (DBusConnection *connection)
39 DBusMessageIter iter_array;
42 /* list both active and activatable names (the shell will sort and
43 * uniquify them) - also avoid names that are not well-known
47 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
51 dbus_error_init (&error);
52 reply = dbus_connection_send_with_reply_and_block (connection,
56 dbus_message_unref (message);
57 dbus_message_iter_init (reply, &iter);
58 dbus_message_iter_recurse (&iter, &iter_array);
59 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
61 dbus_message_iter_get_basic (&iter_array, &name);
63 printf ("%s \n", name);
64 dbus_message_iter_next (&iter_array);
66 dbus_message_unref (reply);
68 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
71 "ListActivatableNames");
72 dbus_error_init (&error);
73 reply = dbus_connection_send_with_reply_and_block (connection,
77 dbus_message_unref (message);
78 dbus_message_iter_init (reply, &iter);
79 dbus_message_iter_recurse (&iter, &iter_array);
80 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
82 dbus_message_iter_get_basic (&iter_array, &name);
83 printf ("%s \n", name);
84 dbus_message_iter_next (&iter_array);
86 dbus_message_unref (reply);
90 have_option (char **tokens, const char *option)
93 for (n = 0; tokens[n] != NULL; n++)
94 if (strcmp (tokens[n], option) == 0)
100 have_option_with_value (char **tokens, const char *option, const char **value)
103 for (n = 0; tokens[n] != NULL; n++)
105 if (g_str_has_prefix (tokens[n], option))
107 if (strlen (tokens[n]) > strlen (option))
108 *value = tokens[n] + strlen (option);
116 print_objects (DBusConnection *connection, const char *service_name, const char *cur)
118 DBusMessage *message;
121 DBusMessageIter iter;
122 const char *introspection_xml;
130 message = dbus_message_new_method_call (service_name,
132 DBUS_INTERFACE_INTROSPECTABLE,
134 dbus_error_init (&error);
135 reply = dbus_connection_send_with_reply_and_block (connection,
139 dbus_message_unref (message);
140 dbus_message_iter_init (reply, &iter);
141 dbus_message_iter_get_basic (&iter, &introspection_xml);
143 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
144 nodes = node_info_get_nodes (root);
146 if (g_slist_length (node_info_get_interfaces (root)) > 0)
147 printf ("%s \n", cur);
149 for (l = nodes; l != NULL; l = l->next)
151 NodeInfo *node = (NodeInfo *) l->data;
155 name = node_info_get_name (node);
156 if (strcmp (cur, "/") == 0)
157 new_path = g_strdup_printf ("/%s", name);
159 new_path = g_strdup_printf ("%s/%s", cur, name);
161 print_objects (connection, service_name, new_path);
165 node_info_unref (root);
167 dbus_message_unref (reply);
171 is_object_path_with_interfaces (DBusConnection *connection, const char *service_name, const char *object_path)
173 DBusMessage *message;
176 DBusMessageIter iter;
177 const char *introspection_xml;
183 message = dbus_message_new_method_call (service_name,
185 DBUS_INTERFACE_INTROSPECTABLE,
187 dbus_error_init (&error);
188 reply = dbus_connection_send_with_reply_and_block (connection,
192 dbus_message_unref (message);
193 dbus_message_iter_init (reply, &iter);
194 dbus_message_iter_get_basic (&iter, &introspection_xml);
196 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
198 if (g_slist_length (node_info_get_interfaces (root)) > 0)
201 node_info_unref (root);
202 dbus_message_unref (reply);
208 print_methods (DBusConnection *connection, const char *service_name, const char *object_path)
210 DBusMessage *message;
213 DBusMessageIter iter;
214 const char *introspection_xml;
219 message = dbus_message_new_method_call (service_name,
221 DBUS_INTERFACE_INTROSPECTABLE,
223 dbus_error_init (&error);
224 reply = dbus_connection_send_with_reply_and_block (connection,
228 dbus_message_unref (message);
229 dbus_message_iter_init (reply, &iter);
230 dbus_message_iter_get_basic (&iter, &introspection_xml);
232 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
233 interfaces = node_info_get_interfaces (root);
234 for (l = interfaces; l != NULL; l = l->next)
236 InterfaceInfo *interface = (InterfaceInfo *) l->data;
239 methods = interface_info_get_methods (interface);
240 for (ll = methods; ll != NULL; ll = ll->next)
242 MethodInfo *method = (MethodInfo *) ll->data;
243 printf ("%s.%s \n", interface_info_get_name (interface), method_info_get_name (method));
246 node_info_unref (root);
247 dbus_message_unref (reply);
251 print_signature (DBusConnection *connection, const char *service_name, const char *object_path, const char *method)
253 DBusMessage *message;
256 DBusMessageIter iter;
257 const char *introspection_xml;
263 char *interface_name;
267 interface_name = NULL;
269 s = strrchr (method, '.');
270 if (s == NULL || strlen (s) < 2 || s - method < 1)
272 method_name = g_strdup (s + 1);
273 interface_name = g_strndup (method, s - method);
276 message = dbus_message_new_method_call (service_name,
278 DBUS_INTERFACE_INTROSPECTABLE,
280 dbus_error_init (&error);
281 reply = dbus_connection_send_with_reply_and_block (connection,
285 dbus_message_unref (message);
286 dbus_message_iter_init (reply, &iter);
287 dbus_message_iter_get_basic (&iter, &introspection_xml);
289 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
290 interfaces = node_info_get_interfaces (root);
291 for (l = interfaces; l != NULL; l = l->next)
293 InterfaceInfo *interface = (InterfaceInfo *) l->data;
295 if (strcmp (interface_name, interface_info_get_name (interface)) == 0)
299 methods = interface_info_get_methods (interface);
300 for (ll = methods; ll != NULL; ll = ll->next)
302 MethodInfo *method = (MethodInfo *) ll->data;
303 if (strcmp (method_name, method_info_get_name (method)) == 0)
307 args = method_info_get_args (method);
308 for (lll = args, n = 0; lll != NULL; lll = lll->next, n++)
310 ArgInfo *arg = (ArgInfo *) lll->data;
311 printf ("# %s: arg %d: %s (%s) \n",
312 arg_info_get_direction (arg) == ARG_IN ? " IN" : "OUT",
314 arg_info_get_name (arg),
315 arg_info_get_type (arg));
322 node_info_unref (root);
323 dbus_message_unref (reply);
325 g_free (method_name);
326 g_free (interface_name);
331 complete_dbus_send (char *str)
337 gboolean have_system;
338 gboolean have_session;
339 gboolean have_print_reply;
341 DBusConnection *connection;
342 DBusBusType bus_type;
344 const char *target_service;
345 const char *object_path;
348 int object_path_index;
352 target_service = NULL;
354 tokens = g_strsplit (str, " ", 0);
355 num_tokens = g_strv_length (tokens);
356 if (num_tokens >= 1) {
357 cur = tokens[num_tokens - 1];
362 have_system = have_option (tokens, "--system");
363 have_session = have_option (tokens, "--session");
364 have_print_reply = have_option (tokens, "--print-reply");
365 have_dest = have_option_with_value (tokens, "--dest=", &target_service);
367 if (!have_print_reply)
368 printf ("--print-reply \n");
370 if (!have_system && !have_session)
372 printf ("--system \n");
373 printf ("--session \n");
377 if (!have_dest && !g_str_has_prefix (cur, "--dest="))
379 printf ("--dest=\n");
383 if (have_system || have_session)
385 bus_type = have_system ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION;
387 dbus_error_init (&error);
388 connection = dbus_bus_get (bus_type, &error);
389 if (connection == NULL)
391 fprintf (stderr, "Failed to open connection to %s message bus: %s: %s\n",
392 (bus_type == DBUS_BUS_SYSTEM) ? "system" : "session",
393 error.name, error.message);
394 dbus_error_free (&error);
399 if (connection != NULL && g_str_has_prefix (cur, "--dest="))
401 print_services (connection);
405 /* see if we have an object path */
407 object_path_index = 0;
408 if (connection != NULL && target_service != NULL)
410 for (n = 0; tokens[n] != NULL; n++)
412 if (tokens[n] == cur)
415 if (*(tokens[n]) == '/')
417 if (is_object_path_with_interfaces (connection, target_service, tokens[n]))
419 object_path = tokens[n];
420 object_path_index = n;
426 /* if we have a connection and a destination but no object path, go ahead and list the object paths */
427 if (connection != NULL && target_service != NULL && object_path == NULL)
429 print_objects (connection, target_service, NULL);
433 /* see if we have a method; it's directly after the object_path */
435 if (connection != NULL && target_service != NULL && object_path != NULL)
437 if ((object_path_index + 1 < num_tokens - 1) &&
438 (strlen (tokens[object_path_index + 1]) > 0) &&
439 !(strcmp (cur, tokens[object_path_index + 1]) == 0))
440 method = tokens[object_path_index + 1];
443 /* if we have connection, destination and object path but no method yet, list the methods */
444 if (connection != NULL && target_service != NULL && object_path != NULL && method == NULL)
446 print_methods (connection, target_service, object_path);
450 /* print signature as comment */
451 if (connection != NULL && target_service != NULL && object_path != NULL && method != NULL)
453 print_signature (connection, target_service, object_path, method);
463 if (connection != NULL)
464 dbus_connection_unref (connection);
469 main (int argc, char *argv[])
480 fprintf (stderr, "invalid use\n");
484 if (strcmp (argv[1], "dbus-send") == 0)
490 fprintf (stderr, "unknown program '%s'\n", argv[1]);
494 if (strlen (argv[2]) < strlen (argv[1]) + 1)
496 fprintf (stderr, "error");
500 cur = argv[2] + strlen (argv[1]) + 1;
503 ret = complete_dbus_send (cur);