]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
busctl: introduce 'emit' command to emit a signal
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 2 Feb 2019 17:01:05 +0000 (18:01 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 6 Feb 2019 12:30:48 +0000 (13:30 +0100)
Closes #11622.

man/busctl.xml
src/busctl/busctl.c

index a5e3d92cf02d2b6f09c56b7f89d70b4b6ce2e8a3..04f05294f9a01398d05d1f3d39275202756b889d 100644 (file)
         <term><option>--auto-start=</option><replaceable>BOOL</replaceable></term>
 
         <listitem>
-          <para>When used with the <command>call</command> command, specifies
+          <para>When used with the <command>call</command> or <command>emit</command> command, specifies
           whether the method call should implicitly activate the
           called service, should it not be running yet but is
           configured to be auto-started. Defaults to
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--destination=</option><replaceable>SERVICE</replaceable></term>
+
+        <listitem>
+          <para>Takes a service name. When used with the <command>emit</command> command, a signal is
+          emitted to the specified service.</para>
+        </listitem>
+      </varlistentry>
+
       <xi:include href="user-system-options.xml" xpointer="user" />
       <xi:include href="user-system-options.xml" xpointer="system" />
       <xi:include href="user-system-options.xml" xpointer="host" />
         <option>--quiet</option> option.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><command>emit</command> <arg choice="plain"><replaceable>OBJECT</replaceable></arg> <arg choice="plain"><replaceable>INTERFACE</replaceable></arg> <arg choice="plain"><replaceable>SIGNAL</replaceable></arg> <arg choice="opt"><replaceable>SIGNATURE</replaceable> <arg choice="opt" rep="repeat"><replaceable>ARGUMENT</replaceable></arg></arg></term>
+
+        <listitem><para>Emit a signal. Takes a object path, interface name and method name. If parameters
+        shall be passed, a signature string is required, followed by the arguments, individually formatted as
+        strings. For details on the formatting used, see below. To specify the destination of the signal,
+        use the <option>--destination=</option> option.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><command>get-property</command> <arg choice="plain"><replaceable>SERVICE</replaceable></arg> <arg choice="plain"><replaceable>OBJECT</replaceable></arg> <arg choice="plain"><replaceable>INTERFACE</replaceable></arg> <arg choice="plain" rep="repeat"><replaceable>PROPERTY</replaceable></arg></term>
 
index 3ff8fff612d163e67086ac99861c999774be60c8..46263bd6b2d78863c8d4551252eb64edcca97379 100644 (file)
@@ -57,6 +57,7 @@ static bool arg_allow_interactive_authorization = true;
 static bool arg_augment_creds = true;
 static bool arg_watch_bind = false;
 static usec_t arg_timeout = 0;
+static const char *arg_destination = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_matches, strv_freep);
 
@@ -2036,6 +2037,49 @@ static int call(int argc, char **argv, void *userdata) {
         return 0;
 }
 
+static int emit_signal(int argc, char **argv, void *userdata) {
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        int r;
+
+        r = acquire_bus(false, &bus);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_new_signal(bus, &m, argv[1], argv[2], argv[3]);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (arg_destination) {
+                r = sd_bus_message_set_destination(m, arg_destination);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        r = sd_bus_message_set_auto_start(m, arg_auto_start);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (!isempty(argv[4])) {
+                char **p;
+
+                p = argv+5;
+
+                r = message_append_cmdline(m, argv[4], &p);
+                if (r < 0)
+                        return r;
+
+                if (*p)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature.");
+        }
+
+        r = sd_bus_send(bus, m, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to send signal: %m");
+
+        return 0;
+}
+
 static int get_property(int argc, char **argv, void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -2182,6 +2226,7 @@ static int help(void) {
                "     --augment-creds=BOOL  Extend credential data with data read from /proc/$PID\n"
                "     --watch-bind=BOOL     Wait for bus AF_UNIX socket to be bound in the file\n"
                "                           system\n"
+               "     --destination=SERVICE Destination service of a signal\n"
                "\nCommands:\n"
                "  list                     List bus names\n"
                "  status [SERVICE]         Show bus service, process or bus owner credentials\n"
@@ -2191,6 +2236,8 @@ static int help(void) {
                "  introspect SERVICE OBJECT [INTERFACE]\n"
                "  call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
                "                           Call a method\n"
+               "  emit OBJECT INTERFACE SIGNAL [SIGNATURE [ARGUMENT...]]\n"
+               "                           Emit a signal\n"
                "  get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
                "                           Get property value\n"
                "  set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n"
@@ -2232,6 +2279,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_AUGMENT_CREDS,
                 ARG_WATCH_BIND,
                 ARG_JSON,
+                ARG_DESTINATION,
         };
 
         static const struct option options[] = {
@@ -2260,6 +2308,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "augment-creds",                   required_argument, NULL, ARG_AUGMENT_CREDS                   },
                 { "watch-bind",                      required_argument, NULL, ARG_WATCH_BIND                      },
                 { "json",                            required_argument, NULL, ARG_JSON                            },
+                { "destination",                     required_argument, NULL, ARG_DESTINATION                     },
                 {},
         };
 
@@ -2426,6 +2475,10 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_DESTINATION:
+                        arg_destination = optarg;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -2446,6 +2499,7 @@ static int busctl_main(int argc, char *argv[]) {
                 { "tree",         VERB_ANY, VERB_ANY, 0,            tree           },
                 { "introspect",   3,        4,        0,            introspect     },
                 { "call",         5,        VERB_ANY, 0,            call           },
+                { "emit",         4,        VERB_ANY, 0,            emit_signal    },
                 { "get-property", 5,        VERB_ANY, 0,            get_property   },
                 { "set-property", 6,        VERB_ANY, 0,            set_property   },
                 { "help",         VERB_ANY, VERB_ANY, 0,            verb_help      },