00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include <ctype.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027
00028 #include <dbus/dbus.h>
00029 #include <glib.h>
00030 #include "dbus-gparser.h"
00031
00032 static void
00033 print_services (DBusConnection *connection)
00034 {
00035 DBusMessage *message;
00036 DBusMessage *reply;
00037 DBusError error;
00038 DBusMessageIter iter;
00039 DBusMessageIter iter_array;
00040 const char *name;
00041
00042
00043
00044
00045
00046
00047 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00048 DBUS_PATH_DBUS,
00049 DBUS_INTERFACE_DBUS,
00050 "ListNames");
00051 dbus_error_init (&error);
00052 reply = dbus_connection_send_with_reply_and_block (connection,
00053 message,
00054 -1,
00055 &error);
00056 dbus_message_unref (message);
00057 dbus_message_iter_init (reply, &iter);
00058 dbus_message_iter_recurse (&iter, &iter_array);
00059 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
00060 {
00061 dbus_message_iter_get_basic (&iter_array, &name);
00062 if (name[0] != ':')
00063 printf ("%s \n", name);
00064 dbus_message_iter_next (&iter_array);
00065 }
00066 dbus_message_unref (reply);
00067
00068 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00069 DBUS_PATH_DBUS,
00070 DBUS_INTERFACE_DBUS,
00071 "ListActivatableNames");
00072 dbus_error_init (&error);
00073 reply = dbus_connection_send_with_reply_and_block (connection,
00074 message,
00075 -1,
00076 &error);
00077 dbus_message_unref (message);
00078 dbus_message_iter_init (reply, &iter);
00079 dbus_message_iter_recurse (&iter, &iter_array);
00080 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
00081 {
00082 dbus_message_iter_get_basic (&iter_array, &name);
00083 printf ("%s \n", name);
00084 dbus_message_iter_next (&iter_array);
00085 }
00086 dbus_message_unref (reply);
00087 }
00088
00089 static gboolean
00090 have_option (char **tokens, const char *option)
00091 {
00092 int n;
00093 for (n = 0; tokens[n] != NULL; n++)
00094 if (strcmp (tokens[n], option) == 0)
00095 return TRUE;
00096 return FALSE;
00097 }
00098
00099 static gboolean
00100 have_option_with_value (char **tokens, const char *option, const char **value)
00101 {
00102 int n;
00103 for (n = 0; tokens[n] != NULL; n++)
00104 {
00105 if (g_str_has_prefix (tokens[n], option))
00106 {
00107 if (strlen (tokens[n]) > strlen (option))
00108 *value = tokens[n] + strlen (option);
00109 return TRUE;
00110 }
00111 }
00112 return FALSE;
00113 }
00114
00115 static void
00116 print_objects (DBusConnection *connection, const char *service_name, const char *cur)
00117 {
00118 DBusMessage *message;
00119 DBusMessage *reply;
00120 DBusError error;
00121 DBusMessageIter iter;
00122 const char *introspection_xml;
00123 NodeInfo *root;
00124 GSList *nodes;
00125 GSList *l;
00126
00127 if (cur == NULL)
00128 cur = "/";
00129
00130 message = dbus_message_new_method_call (service_name,
00131 cur,
00132 DBUS_INTERFACE_INTROSPECTABLE,
00133 "Introspect");
00134 dbus_error_init (&error);
00135 reply = dbus_connection_send_with_reply_and_block (connection,
00136 message,
00137 -1,
00138 &error);
00139 dbus_message_unref (message);
00140 dbus_message_iter_init (reply, &iter);
00141 dbus_message_iter_get_basic (&iter, &introspection_xml);
00142
00143 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
00144 nodes = node_info_get_nodes (root);
00145
00146 if (g_slist_length (node_info_get_interfaces (root)) > 0)
00147 printf ("%s \n", cur);
00148
00149 for (l = nodes; l != NULL; l = l->next)
00150 {
00151 NodeInfo *node = (NodeInfo *) l->data;
00152 const char *name;
00153 char *new_path;
00154
00155 name = node_info_get_name (node);
00156 if (strcmp (cur, "/") == 0)
00157 new_path = g_strdup_printf ("/%s", name);
00158 else
00159 new_path = g_strdup_printf ("%s/%s", cur, name);
00160
00161 print_objects (connection, service_name, new_path);
00162
00163 g_free (new_path);
00164 }
00165 node_info_unref (root);
00166
00167 dbus_message_unref (reply);
00168 }
00169
00170 static gboolean
00171 is_object_path_with_interfaces (DBusConnection *connection, const char *service_name, const char *object_path)
00172 {
00173 DBusMessage *message;
00174 DBusMessage *reply;
00175 DBusError error;
00176 DBusMessageIter iter;
00177 const char *introspection_xml;
00178 NodeInfo *root;
00179 gboolean ret;
00180
00181 ret = FALSE;
00182
00183 message = dbus_message_new_method_call (service_name,
00184 object_path,
00185 DBUS_INTERFACE_INTROSPECTABLE,
00186 "Introspect");
00187 dbus_error_init (&error);
00188 reply = dbus_connection_send_with_reply_and_block (connection,
00189 message,
00190 -1,
00191 &error);
00192 dbus_message_unref (message);
00193 dbus_message_iter_init (reply, &iter);
00194 dbus_message_iter_get_basic (&iter, &introspection_xml);
00195
00196 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
00197
00198 if (g_slist_length (node_info_get_interfaces (root)) > 0)
00199 ret = TRUE;
00200
00201 node_info_unref (root);
00202 dbus_message_unref (reply);
00203
00204 return ret;
00205 }
00206
00207 static void
00208 print_methods (DBusConnection *connection, const char *service_name, const char *object_path)
00209 {
00210 DBusMessage *message;
00211 DBusMessage *reply;
00212 DBusError error;
00213 DBusMessageIter iter;
00214 const char *introspection_xml;
00215 NodeInfo *root;
00216 GSList *interfaces;
00217 GSList *l;
00218
00219 message = dbus_message_new_method_call (service_name,
00220 object_path,
00221 DBUS_INTERFACE_INTROSPECTABLE,
00222 "Introspect");
00223 dbus_error_init (&error);
00224 reply = dbus_connection_send_with_reply_and_block (connection,
00225 message,
00226 -1,
00227 &error);
00228 dbus_message_unref (message);
00229 dbus_message_iter_init (reply, &iter);
00230 dbus_message_iter_get_basic (&iter, &introspection_xml);
00231
00232 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
00233 interfaces = node_info_get_interfaces (root);
00234 for (l = interfaces; l != NULL; l = l->next)
00235 {
00236 InterfaceInfo *interface = (InterfaceInfo *) l->data;
00237 GSList *methods;
00238 GSList *ll;
00239 methods = interface_info_get_methods (interface);
00240 for (ll = methods; ll != NULL; ll = ll->next)
00241 {
00242 MethodInfo *method = (MethodInfo *) ll->data;
00243 printf ("%s.%s \n", interface_info_get_name (interface), method_info_get_name (method));
00244 }
00245 }
00246 node_info_unref (root);
00247 dbus_message_unref (reply);
00248 }
00249
00250 static void
00251 print_signature (DBusConnection *connection, const char *service_name, const char *object_path, const char *method)
00252 {
00253 DBusMessage *message;
00254 DBusMessage *reply;
00255 DBusError error;
00256 DBusMessageIter iter;
00257 const char *introspection_xml;
00258 NodeInfo *root;
00259 GSList *interfaces;
00260 GSList *l;
00261 char *s;
00262 char *method_name;
00263 char *interface_name;
00264 int n;
00265
00266 method_name = NULL;
00267 interface_name = NULL;
00268
00269 s = strrchr (method, '.');
00270 if (s == NULL || strlen (s) < 2 || s - method < 1)
00271 goto fail;
00272 method_name = g_strdup (s + 1);
00273 interface_name = g_strndup (method, s - method);
00274 printf (" \n");
00275
00276 message = dbus_message_new_method_call (service_name,
00277 object_path,
00278 DBUS_INTERFACE_INTROSPECTABLE,
00279 "Introspect");
00280 dbus_error_init (&error);
00281 reply = dbus_connection_send_with_reply_and_block (connection,
00282 message,
00283 -1,
00284 &error);
00285 dbus_message_unref (message);
00286 dbus_message_iter_init (reply, &iter);
00287 dbus_message_iter_get_basic (&iter, &introspection_xml);
00288
00289 root = description_load_from_string (introspection_xml, strlen (introspection_xml), NULL);
00290 interfaces = node_info_get_interfaces (root);
00291 for (l = interfaces; l != NULL; l = l->next)
00292 {
00293 InterfaceInfo *interface = (InterfaceInfo *) l->data;
00294
00295 if (strcmp (interface_name, interface_info_get_name (interface)) == 0)
00296 {
00297 GSList *methods;
00298 GSList *ll;
00299 methods = interface_info_get_methods (interface);
00300 for (ll = methods; ll != NULL; ll = ll->next)
00301 {
00302 MethodInfo *method = (MethodInfo *) ll->data;
00303 if (strcmp (method_name, method_info_get_name (method)) == 0)
00304 {
00305 GSList *args;
00306 GSList *lll;
00307 args = method_info_get_args (method);
00308 for (lll = args, n = 0; lll != NULL; lll = lll->next, n++)
00309 {
00310 ArgInfo *arg = (ArgInfo *) lll->data;
00311 printf ("# %s: arg %d: %s (%s) \n",
00312 arg_info_get_direction (arg) == ARG_IN ? " IN" : "OUT",
00313 n,
00314 arg_info_get_name (arg),
00315 arg_info_get_type (arg));
00316 }
00317 break;
00318 }
00319 }
00320 }
00321 }
00322 node_info_unref (root);
00323 dbus_message_unref (reply);
00324 fail:
00325 g_free (method_name);
00326 g_free (interface_name);
00327 }
00328
00329
00330 static int
00331 complete_dbus_send (char *str)
00332 {
00333 int ret;
00334 char **tokens;
00335 int num_tokens;
00336 const char *cur;
00337 const char *prev;
00338 gboolean have_system;
00339 gboolean have_session;
00340 gboolean have_print_reply;
00341 gboolean have_dest;
00342 DBusConnection *connection;
00343 DBusBusType bus_type;
00344 DBusError error;
00345 const char *target_service;
00346 const char *object_path;
00347 const char *method;
00348 int n;
00349 int object_path_index;
00350
00351 ret = 1;
00352 connection = NULL;
00353 target_service = NULL;
00354
00355 tokens = g_strsplit (str, " ", 0);
00356 num_tokens = g_strv_length (tokens);
00357 if (num_tokens >= 2) {
00358 cur = tokens[num_tokens - 1];
00359 prev = tokens[num_tokens - 2];
00360 } else if (num_tokens == 1) {
00361 cur = tokens[num_tokens - 1];
00362 prev = "";
00363 } else {
00364 cur = "";
00365 prev = "";
00366 }
00367
00368 have_system = have_option (tokens, "--system");
00369 have_session = have_option (tokens, "--session");
00370 have_print_reply = have_option (tokens, "--print-reply");
00371 have_dest = have_option_with_value (tokens, "--dest=", &target_service);
00372
00373 if (!have_print_reply)
00374 printf ("--print-reply \n");
00375
00376 if (!have_system && !have_session)
00377 {
00378 printf ("--system \n");
00379 printf ("--session \n");
00380 goto done;
00381 }
00382
00383 if (!have_dest && !g_str_has_prefix (cur, "--dest="))
00384 {
00385 printf ("--dest=\n");
00386 goto done;
00387 }
00388
00389 if (have_system || have_session)
00390 {
00391 bus_type = have_system ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION;
00392
00393 dbus_error_init (&error);
00394 connection = dbus_bus_get (bus_type, &error);
00395 if (connection == NULL)
00396 {
00397 fprintf (stderr, "Failed to open connection to %s message bus: %s: %s\n",
00398 (bus_type == DBUS_BUS_SYSTEM) ? "system" : "session",
00399 error.name, error.message);
00400 dbus_error_free (&error);
00401 goto fail;
00402 }
00403 }
00404
00405 if (connection != NULL && g_str_has_prefix (cur, "--dest="))
00406 {
00407 print_services (connection);
00408 goto done;
00409 }
00410
00411
00412 object_path = NULL;
00413 object_path_index = 0;
00414 if (connection != NULL && target_service != NULL)
00415 {
00416 for (n = 0; tokens[n] != NULL; n++)
00417 {
00418 if (tokens[n] == cur)
00419 continue;
00420
00421 if (*(tokens[n]) == '/')
00422 {
00423 if (is_object_path_with_interfaces (connection, target_service, tokens[n]))
00424 {
00425 object_path = tokens[n];
00426 object_path_index = n;
00427 }
00428 }
00429 }
00430 }
00431
00432
00433 if (connection != NULL && target_service != NULL && object_path == NULL)
00434 {
00435 print_objects (connection, target_service, NULL);
00436 goto done;
00437 }
00438
00439
00440 method = NULL;
00441 if (connection != NULL && target_service != NULL && object_path != NULL)
00442 {
00443 if ((object_path_index + 1 < num_tokens - 1) &&
00444 (strlen (tokens[object_path_index + 1]) > 0) &&
00445 !(strcmp (cur, tokens[object_path_index + 1]) == 0))
00446 method = tokens[object_path_index + 1];
00447 }
00448
00449
00450 if (connection != NULL && target_service != NULL && object_path != NULL && method == NULL)
00451 {
00452 print_methods (connection, target_service, object_path);
00453 goto done;
00454 }
00455
00456
00457 if (connection != NULL && target_service != NULL && object_path != NULL && method != NULL)
00458 {
00459 print_signature (connection, target_service, object_path, method);
00460 }
00461
00462 done:
00463 ret = 0;
00464
00465 fail:
00466
00467 g_strfreev (tokens);
00468
00469 if (connection != NULL)
00470 dbus_connection_unref (connection);
00471 return ret;
00472 }
00473
00474 int
00475 main (int argc, char *argv[])
00476 {
00477 int ret;
00478 char *cur;
00479 gboolean dbus_send;
00480
00481 ret = 1;
00482 dbus_send = FALSE;
00483
00484 if (argc != 3)
00485 {
00486 fprintf (stderr, "invalid use\n");
00487 goto out;
00488 }
00489
00490 if (strcmp (argv[1], "dbus-send") == 0)
00491 {
00492 dbus_send = TRUE;
00493 }
00494 else
00495 {
00496 fprintf (stderr, "unknown program '%s'\n", argv[1]);
00497 goto out;
00498 }
00499
00500 if (strlen (argv[2]) < strlen (argv[1]) + 1)
00501 {
00502 fprintf (stderr, "error");
00503 goto out;
00504 }
00505
00506 cur = argv[2] + strlen (argv[1]) + 1;
00507
00508 if (dbus_send)
00509 ret = complete_dbus_send (cur);
00510
00511 out:
00512 return ret;
00513 }