1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-send.c Utility program to send messages from the command line
4 * Copyright (C) 2003 Philip Blundell <philb@gnu.org>
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
27 #include <dbus/dbus.h>
28 #include "dbus/dbus-internals.h"
32 #define strtoll mystrtoll
38 #define strtoull mystrtoull
44 #define strdup _strdup
48 #include "dbus-print-message.h"
50 static const char *appname;
52 static void usage (int ecode) _DBUS_GNUC_NORETURN;
57 fprintf (stderr, "Usage: %s [--help] [--system | --session | --bus=ADDRESS | --peer=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
61 /* Abort on any allocation failure; there is nothing else we can do. */
63 handle_oom (dbus_bool_t success)
67 fprintf (stderr, "%s: Ran out of memory\n", appname);
73 append_arg (DBusMessageIter *iter, int type, const char *value)
83 dbus_bool_t v_BOOLEAN;
89 byte = strtoul (value, NULL, 0);
90 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &byte);
93 case DBUS_TYPE_DOUBLE:
94 d = strtod (value, NULL);
95 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &d);
99 int16 = strtol (value, NULL, 0);
100 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &int16);
103 case DBUS_TYPE_UINT16:
104 uint16 = strtoul (value, NULL, 0);
105 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &uint16);
108 case DBUS_TYPE_INT32:
109 int32 = strtol (value, NULL, 0);
110 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &int32);
113 case DBUS_TYPE_UINT32:
114 uint32 = strtoul (value, NULL, 0);
115 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &uint32);
118 case DBUS_TYPE_INT64:
119 int64 = strtoll (value, NULL, 0);
120 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &int64);
123 case DBUS_TYPE_UINT64:
124 uint64 = strtoull (value, NULL, 0);
125 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &uint64);
128 case DBUS_TYPE_STRING:
129 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
132 case DBUS_TYPE_OBJECT_PATH:
133 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &value);
136 case DBUS_TYPE_BOOLEAN:
137 if (strcmp (value, "true") == 0)
140 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
142 else if (strcmp (value, "false") == 0)
145 ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
149 fprintf (stderr, "%s: Expected \"true\" or \"false\" instead of \"%s\"\n", appname, value);
155 fprintf (stderr, "%s: Unsupported data type %c\n", appname, (char) type);
163 append_array (DBusMessageIter *iter, int type, const char *value)
166 char *dupval = strdup (value);
168 handle_oom (dupval != NULL);
170 val = strtok (dupval, ",");
173 append_arg (iter, type, val);
174 val = strtok (NULL, ",");
180 append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value)
183 char *dupval = strdup (value);
185 handle_oom (dupval != NULL);
187 val = strtok (dupval, ",");
190 DBusMessageIter subiter;
192 handle_oom (dbus_message_iter_open_container (iter,
193 DBUS_TYPE_DICT_ENTRY,
197 append_arg (&subiter, keytype, val);
198 val = strtok (NULL, ",");
201 fprintf (stderr, "%s: Malformed dictionary\n", appname);
204 append_arg (&subiter, valtype, val);
206 handle_oom (dbus_message_iter_close_container (iter, &subiter));
207 val = strtok (NULL, ",");
213 type_from_name (const char *arg)
216 if (!strcmp (arg, "string"))
217 type = DBUS_TYPE_STRING;
218 else if (!strcmp (arg, "int16"))
219 type = DBUS_TYPE_INT16;
220 else if (!strcmp (arg, "uint16"))
221 type = DBUS_TYPE_UINT16;
222 else if (!strcmp (arg, "int32"))
223 type = DBUS_TYPE_INT32;
224 else if (!strcmp (arg, "uint32"))
225 type = DBUS_TYPE_UINT32;
226 else if (!strcmp (arg, "int64"))
227 type = DBUS_TYPE_INT64;
228 else if (!strcmp (arg, "uint64"))
229 type = DBUS_TYPE_UINT64;
230 else if (!strcmp (arg, "double"))
231 type = DBUS_TYPE_DOUBLE;
232 else if (!strcmp (arg, "byte"))
233 type = DBUS_TYPE_BYTE;
234 else if (!strcmp (arg, "boolean"))
235 type = DBUS_TYPE_BOOLEAN;
236 else if (!strcmp (arg, "objpath"))
237 type = DBUS_TYPE_OBJECT_PATH;
240 fprintf (stderr, "%s: Unknown type \"%s\"\n", appname, arg);
247 main (int argc, char *argv[])
249 DBusConnection *connection;
251 DBusMessage *message;
252 dbus_bool_t print_reply;
253 dbus_bool_t print_reply_literal;
255 DBusMessageIter iter;
257 DBusBusType type = DBUS_BUS_SESSION;
258 const char *dest = NULL;
259 const char *name = NULL;
260 const char *path = NULL;
261 int message_type = DBUS_MESSAGE_TYPE_SIGNAL;
262 const char *type_str = NULL;
263 const char *address = NULL;
265 int session_or_system = FALSE;
273 print_reply_literal = FALSE;
276 for (i = 1; i < argc && name == NULL; i++)
280 if (strcmp (arg, "--system") == 0)
282 type = DBUS_BUS_SYSTEM;
283 session_or_system = TRUE;
285 else if (strcmp (arg, "--session") == 0)
287 type = DBUS_BUS_SESSION;
288 session_or_system = TRUE;
290 else if ((strstr (arg, "--bus=") == arg) || (strstr (arg, "--peer=") == arg) || (strstr (arg, "--address=") == arg))
292 /* Check for peer first, to avoid the GCC -Wduplicated-branches
295 if (arg[2] == 'p') /* peer */
299 else if (arg[2] == 'b') /* bus */
303 else /* address; keeping backwards compatibility */
308 address = strchr (arg, '=') + 1;
310 if (address[0] == '\0')
312 fprintf (stderr, "\"--peer=\" and \"--bus=\" require an ADDRESS\n");
316 else if (strncmp (arg, "--print-reply", 13) == 0)
319 message_type = DBUS_MESSAGE_TYPE_METHOD_CALL;
320 if (strcmp (arg + 13, "=literal") == 0)
321 print_reply_literal = TRUE;
322 else if (*(arg + 13) != '\0')
324 fprintf (stderr, "invalid value (%s) of \"--print-reply\"\n", arg + 13);
328 else if (strstr (arg, "--reply-timeout=") == arg)
330 if (*(strchr (arg, '=') + 1) == '\0')
332 fprintf (stderr, "\"--reply-timeout=\" requires an MSEC\n");
335 reply_timeout = strtol (strchr (arg, '=') + 1,
337 if (reply_timeout <= 0)
339 fprintf (stderr, "invalid value (%s) of \"--reply-timeout\"\n",
340 strchr (arg, '=') + 1);
344 else if (strstr (arg, "--dest=") == arg)
346 if (*(strchr (arg, '=') + 1) == '\0')
348 fprintf (stderr, "\"--dest=\" requires an NAME\n");
351 dest = strchr (arg, '=') + 1;
353 else if (strstr (arg, "--type=") == arg)
354 type_str = strchr (arg, '=') + 1;
355 else if (!strcmp(arg, "--help"))
357 else if (arg[0] == '-')
359 else if (path == NULL)
361 else /* name == NULL guaranteed by the 'while' loop */
368 if (session_or_system &&
371 fprintf (stderr, "\"--peer\" and \"--bus\" may not be used with \"--system\" or \"--session\"\n");
375 if (type_str != NULL)
377 message_type = dbus_message_type_from_string (type_str);
378 if (!(message_type == DBUS_MESSAGE_TYPE_METHOD_CALL ||
379 message_type == DBUS_MESSAGE_TYPE_SIGNAL))
381 fprintf (stderr, "Message type \"%s\" is not supported\n",
387 dbus_error_init (&error);
389 if (dest && !dbus_validate_bus_name (dest, &error))
391 fprintf (stderr, "invalid value (%s) of \"--dest\"\n", dest);
397 connection = dbus_connection_open (address, &error);
401 connection = dbus_bus_get (type, &error);
404 if (connection == NULL)
406 fprintf (stderr, "Failed to open connection to \"%s\" message bus: %s\n",
407 (address != NULL) ? address :
408 ((type == DBUS_BUS_SYSTEM) ? "system" : "session"),
410 dbus_error_free (&error);
413 else if ((address != NULL) && is_bus)
415 if (!dbus_bus_register (connection, &error))
417 fprintf (stderr, "Failed to register on connection to \"%s\" message bus: %s\n",
418 address, error.message);
419 dbus_error_free (&error);
424 if (message_type == DBUS_MESSAGE_TYPE_METHOD_CALL)
428 last_dot = strrchr (name, '.');
429 if (last_dot == NULL)
431 fprintf (stderr, "Must use org.mydomain.Interface.Method notation, no dot in \"%s\"\n",
437 message = dbus_message_new_method_call (NULL,
441 handle_oom (message != NULL);
442 dbus_message_set_auto_start (message, TRUE);
444 else if (message_type == DBUS_MESSAGE_TYPE_SIGNAL)
448 last_dot = strrchr (name, '.');
449 if (last_dot == NULL)
451 fprintf (stderr, "Must use org.mydomain.Interface.Signal notation, no dot in \"%s\"\n",
457 message = dbus_message_new_signal (path, name, last_dot + 1);
458 handle_oom (message != NULL);
462 fprintf (stderr, "Internal error, unknown message type\n");
468 fprintf (stderr, "Couldn't allocate D-Bus message\n");
472 if (dest && !dbus_message_set_destination (message, dest))
474 fprintf (stderr, "Not enough memory\n");
478 dbus_message_iter_init_append (message, &iter);
487 DBusMessageIter *target_iter;
488 DBusMessageIter container_iter;
490 type2 = DBUS_TYPE_INVALID;
491 secondary_type = DBUS_TYPE_INVALID;
493 c = strchr (arg, ':');
497 fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
503 container_type = DBUS_TYPE_INVALID;
505 if (strcmp (arg, "variant") == 0)
506 container_type = DBUS_TYPE_VARIANT;
507 else if (strcmp (arg, "array") == 0)
508 container_type = DBUS_TYPE_ARRAY;
509 else if (strcmp (arg, "dict") == 0)
510 container_type = DBUS_TYPE_DICT_ENTRY;
512 if (container_type != DBUS_TYPE_INVALID)
515 c = strchr (arg, ':');
518 fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
525 type2 = DBUS_TYPE_STRING;
527 type2 = type_from_name (arg);
529 if (container_type == DBUS_TYPE_DICT_ENTRY)
536 fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
540 secondary_type = type_from_name (arg);
541 sig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR;
543 sig[2] = secondary_type;
544 sig[3] = DBUS_DICT_ENTRY_END_CHAR;
546 handle_oom (dbus_message_iter_open_container (&iter,
550 target_iter = &container_iter;
552 else if (container_type != DBUS_TYPE_INVALID)
557 handle_oom (dbus_message_iter_open_container (&iter,
561 target_iter = &container_iter;
566 if (container_type == DBUS_TYPE_ARRAY)
568 append_array (target_iter, type2, c);
570 else if (container_type == DBUS_TYPE_DICT_ENTRY)
572 _dbus_assert (secondary_type != DBUS_TYPE_INVALID);
573 append_dict (target_iter, type2, secondary_type, c);
576 append_arg (target_iter, type2, c);
578 if (container_type != DBUS_TYPE_INVALID)
580 handle_oom (dbus_message_iter_close_container (&iter,
589 dbus_error_init (&error);
590 reply = dbus_connection_send_with_reply_and_block (connection,
591 message, reply_timeout,
593 if (dbus_error_is_set (&error))
595 fprintf (stderr, "Error %s: %s\n",
605 _dbus_get_real_time (&sec, &usec);
606 print_message (reply, print_reply_literal, sec, usec);
607 dbus_message_unref (reply);
612 dbus_connection_send (connection, message, NULL);
613 dbus_connection_flush (connection);
616 dbus_message_unref (message);
618 dbus_connection_unref (connection);