chiark / gitweb /
bus: add API calls for connecting to starter bus
[elogind.git] / src / bus-driverd / bus-driverd.c
index 57023ec8773205ddad60680c00e90ef95b24bde0..acb5e6ba00d574f9a07f49cbd998602c5c89da83 100644 (file)
@@ -51,6 +51,7 @@
 #include "def.h"
 #include "unit-name.h"
 #include "bus-control.h"
+#include "cgroup-util.h"
 
 #define CLIENTS_MAX 1024
 #define MATCHES_MAX 1024
@@ -92,7 +93,7 @@ static void match_free(Match *m) {
                 first = hashmap_get(m->client->matches, m->match);
                 LIST_REMOVE(matches, first, m);
                 if (first)
-                        assert_se(hashmap_replace(m->client->matches, m->match, first) >= 0);
+                        assert_se(hashmap_replace(m->client->matches, first->match, first) >= 0);
                 else
                         hashmap_remove(m->client->matches, m->match);
 
@@ -346,7 +347,7 @@ static int driver_remove_match(sd_bus *bus, sd_bus_message *message, void *userd
 
         m = hashmap_get(c->matches, normalized);
         if (!m) {
-                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.");
+                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.", normalized);
                 goto finish;
         }
 
@@ -714,6 +715,65 @@ static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *us
         return sd_bus_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
 }
 
+static int driver_update_environment(sd_bus*bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+        _cleanup_strv_free_ char **args = NULL;
+        int r;
+
+        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
+        if (r < 0)
+                return r;
+
+       while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
+                _cleanup_free_ char *s = NULL;
+                const char *key;
+                const char *value;
+
+                r = sd_bus_message_read(m, "ss", &key, &value);
+                if (r < 0)
+                        return r;
+
+                s = strjoin(key, "=", value, NULL);
+                if (!s)
+                        return ENOMEM;
+
+                r  = strv_extend(&args, s);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(m);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_bus_message_exit_container(m);
+        if (r < 0)
+                return r;
+
+        if (!args)
+                return -EINVAL;
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "SetEnvironment",
+                        &msg);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_strv(msg, args);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_call(bus, msg, 0, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        return sd_bus_reply_method_return(m, NULL);
+}
+
 static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
 }
@@ -736,19 +796,58 @@ static const sd_bus_vtable driver_vtable[] = {
         SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0),
         SD_BUS_SIGNAL("NameAcquired", "s", SD_BUS_VTABLE_DEPRECATED),
         SD_BUS_SIGNAL("NameLost", "s", SD_BUS_VTABLE_DEPRECATED),
         SD_BUS_SIGNAL("NameOwnerChanged", "sss", 0),
         SD_BUS_VTABLE_END
 };
 
+static int find_object(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                void *userdata,
+                void **ret_found,
+                sd_bus_error *ret_error) {
+
+        /* We support the driver interface on exactly two different
+         * paths: the root and the entry point object. This is a bit
+         * different from the original dbus-daemon which supported it
+         * on any path. */
+
+        if (streq_ptr(path, "/"))
+                return 1;
+
+        if (streq_ptr(path, "/org/freedesktop/DBus"))
+                return 1;
+
+        return 0;
+}
+
+static int node_enumerator(
+                sd_bus *bus,
+                const char *path,
+                void *userdata,
+                char ***ret_nodes,
+                sd_bus_error *ret_error) {
+
+        char **l;
+
+        l = strv_new("/", "/org/freedesktop/DBus", NULL);
+        if (!l)
+                return -ENOMEM;
+
+        *ret_nodes = l;
+        return 0;
+}
+
 static int connect_bus(Context *c) {
         int r;
 
         assert(c);
 
-        r = sd_bus_default_system(&c->bus);
+        r = sd_bus_default(&c->bus);
         if (r < 0) {
                 log_error("Failed to create bus: %s", strerror(-r));
                 return r;
@@ -759,12 +858,18 @@ static int connect_bus(Context *c) {
                 return -EPERM;
         }
 
-        r = sd_bus_add_object_vtable(c->bus, "/org/freedesktop/DBus", "org.freedesktop.DBus", driver_vtable, c);
+        r = sd_bus_add_fallback_vtable(c->bus, "/", "org.freedesktop.DBus", driver_vtable, find_object, c);
         if (r < 0) {
                 log_error("Failed to add manager object vtable: %s", strerror(-r));
                 return r;
         }
 
+        r = sd_bus_add_node_enumerator(c->bus, "/", node_enumerator, c);
+        if (r < 0) {
+                log_error("Failed to add node enumerator: %s", strerror(-r));
+                return r;
+        }
+
         r = sd_bus_request_name(c->bus, "org.freedesktop.DBus", 0);
         if (r < 0) {
                 log_error("Unable to request name: %s", strerror(-r));
@@ -828,5 +933,4 @@ finish:
         sd_event_unref(context.event);
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
 }