chiark / gitweb /
bus: various improvements for test-bus-chat
[elogind.git] / src / libsystemd-bus / sd-bus.c
index 943cd43cb1d0bb543fed7fa4d9528a4ddb8b8954..6f8d444a660e1b0a401d550a96a2c5cae59220f8 100644 (file)
@@ -1167,7 +1167,7 @@ int sd_bus_send_with_reply(
         if (r < 0)
                 return r;
 
-        c = new(struct reply_callback, 1);
+        c = new0(struct reply_callback, 1);
         if (!c)
                 return -ENOMEM;
 
@@ -1314,7 +1314,12 @@ int sd_bus_send_with_reply_and_block(
                                 /* Found a match! */
 
                                 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
-                                        *reply = incoming;
+
+                                        if (reply)
+                                                *reply = incoming;
+                                        else
+                                                sd_bus_message_unref(incoming);
+
                                         return 0;
                                 }
 
@@ -1592,7 +1597,7 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
 
                 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
         } else {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 sd_bus_error_set(&error,
                                  "org.freedesktop.DBus.Error.UnknownMethod",
@@ -1612,7 +1617,7 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
 }
 
 static int process_object(sd_bus *bus, sd_bus_message *m) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         struct object_callback *c;
         int r;
@@ -1857,7 +1862,7 @@ static int process_running(sd_bus *bus, sd_bus_message **ret) {
 
         if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 sd_bus_error_set(&error, "org.freedesktop.DBus.Error.UnknownObject", "Unknown object '%s'.", m->path);
 
@@ -2036,7 +2041,7 @@ int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *user
         if (!callback)
                 return -EINVAL;
 
-        f = new(struct filter_callback, 1);
+        f = new0(struct filter_callback, 1);
         if (!f)
                 return -ENOMEM;
         f->callback = callback;
@@ -2088,7 +2093,7 @@ static int bus_add_object(
         if (r < 0)
                 return r;
 
-        c = new(struct object_callback, 1);
+        c = new0(struct object_callback, 1);
         if (!c)
                 return -ENOMEM;
 
@@ -2208,3 +2213,123 @@ int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t
                 return r;
         return q;
 }
+
+int sd_bus_emit_signal(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *member,
+                const char *types, ...) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        va_list ap;
+        int r;
+
+        if (!bus)
+                return -EINVAL;
+
+        r = sd_bus_message_new_signal(bus, path, interface, member, &m);
+        if (r < 0)
+                return r;
+
+        va_start(ap, types);
+        r = bus_message_append_ap(m, types, ap);
+        va_end(ap);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(bus, m, NULL);
+}
+
+int sd_bus_call_method(
+                sd_bus *bus,
+                const char *destination,
+                const char *path,
+                const char *interface,
+                const char *member,
+                sd_bus_error *error,
+                sd_bus_message **reply,
+                const char *types, ...) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        va_list ap;
+        int r;
+
+        if (!bus)
+                return -EINVAL;
+
+        r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
+        if (r < 0)
+                return r;
+
+        va_start(ap, types);
+        r = bus_message_append_ap(m, types, ap);
+        va_end(ap);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
+}
+
+int sd_bus_reply_method_return(
+                sd_bus *bus,
+                sd_bus_message *call,
+                const char *types, ...) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        va_list ap;
+        int r;
+
+        if (!bus)
+                return -EINVAL;
+        if (!call)
+                return -EINVAL;
+        if (!call->sealed)
+                return -EPERM;
+        if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
+                return -EINVAL;
+
+        if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
+                return 0;
+
+        r = sd_bus_message_new_method_return(bus, call, &m);
+        if (r < 0)
+                return r;
+
+        va_start(ap, types);
+        r = bus_message_append_ap(m, types, ap);
+        va_end(ap);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(bus, m, NULL);
+}
+
+int sd_bus_reply_method_error(
+                sd_bus *bus,
+                sd_bus_message *call,
+                const sd_bus_error *e) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        int r;
+
+        if (!bus)
+                return -EINVAL;
+        if (!call)
+                return -EINVAL;
+        if (!call->sealed)
+                return -EPERM;
+        if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
+                return -EINVAL;
+        if (!sd_bus_error_is_set(e))
+                return -EINVAL;
+
+        if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
+                return 0;
+
+        r = sd_bus_message_new_method_error(bus, call, e, &m);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(bus, m, NULL);
+}