From 38a98dbf026c93ddd4b6221e3640505e6fdccdc5 Mon Sep 17 00:00:00 2001 From: Frederik Van Bogaert Date: Sun, 18 Apr 2021 00:02:45 +0200 Subject: [PATCH] dbus-send: Add support for variants to arrays and dictionaries Adds support for: * Arrays of variants * Dictionaries with variants as keys Manually tested and confirmed working using dbus-monitor. Example usage: ``` $ dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus \ com.example.SomeExample dict:string:variant:one,int16:1 ``` In dbus-monitor: ``` method call time=1652796044.991509 sender=:1.84 -> destination=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=com.example; member=SomeExample array [ dict entry( string "one" variant int16 1 ) ] ``` Signed-off-by: Frederik Van Bogaert --- tools/dbus-send.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/tools/dbus-send.c b/tools/dbus-send.c index 65f9854e..86858c50 100644 --- a/tools/dbus-send.c +++ b/tools/dbus-send.c @@ -69,6 +69,8 @@ handle_oom (dbus_bool_t success) } } +static int type_from_name (const char *arg, dbus_bool_t allow_container_types); + static void append_arg (DBusMessageIter *iter, int type, const char *value) { @@ -151,6 +153,33 @@ append_arg (DBusMessageIter *iter, int type, const char *value) } break; + case DBUS_TYPE_VARIANT: + { + DBusMessageIter subiter; + + char sig[2] = "\0\0"; + char *subtype = strdup (value); + char *c = NULL; + + handle_oom (subtype != NULL); + c = strchr (subtype, ':'); + if (!c) + { + fprintf (stderr, "%s: missing variant subtype specifier\n", + appname); + exit (1); + } + *c = '\0'; + + sig[0] = (char) type_from_name (subtype, TRUE); + + handle_oom (dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, + sig, &subiter)); + append_arg (&subiter, sig[0], c + 1); + free (subtype); + ret = dbus_message_iter_close_container (iter, &subiter); + break; + } default: fprintf (stderr, "%s: Unsupported data type %c\n", appname, (char) type); exit (1); @@ -210,7 +239,7 @@ append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value) } static int -type_from_name (const char *arg) +type_from_name (const char *arg, dbus_bool_t allow_container_types) { int type; if (!strcmp (arg, "string")) @@ -235,6 +264,16 @@ type_from_name (const char *arg) type = DBUS_TYPE_BOOLEAN; else if (!strcmp (arg, "objpath")) type = DBUS_TYPE_OBJECT_PATH; + else if (!strcmp(arg, "variant")) + { + if (!allow_container_types) + { + fprintf (stderr, "%s: A variant cannot be the key in a dictionary\n", appname); + exit (1); + } + + type = DBUS_TYPE_VARIANT; + } else { fprintf (stderr, "%s: Unknown type \"%s\"\n", appname, arg); @@ -609,7 +648,7 @@ main (int argc, char *argv[]) if (arg[0] == 0) type2 = DBUS_TYPE_STRING; else - type2 = type_from_name (arg); + type2 = type_from_name (arg, FALSE); if (container_type == DBUS_TYPE_DICT_ENTRY) { @@ -622,7 +661,7 @@ main (int argc, char *argv[]) exit (1); } *(c++) = 0; - secondary_type = type_from_name (arg); + secondary_type = type_from_name (arg, TRUE); sig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR; sig[1] = type2; sig[2] = secondary_type;