X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbus-driverd%2Fbus-driverd.c;h=319596a40bdfc599327b7e65ebcb97d069564d28;hb=a2cc4a6c960c26f62c33c995bc648357d939bd68;hp=44172c4ed6a211c38eab21a7b32ed281151b0227;hpb=63b575175efb60d6c51bae6a91be7547153fdd8d;p=elogind.git diff --git a/src/bus-driverd/bus-driverd.c b/src/bus-driverd/bus-driverd.c index 44172c4ed..319596a40 100644 --- a/src/bus-driverd/bus-driverd.c +++ b/src/bus-driverd/bus-driverd.c @@ -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); @@ -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,62 @@ 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 = cg_pid_get_owner_uid(0, NULL); + if (r < 0) + r = sd_bus_default_system(&c->bus); + else + r = sd_bus_default_user(&c->bus); if (r < 0) { log_error("Failed to create bus: %s", strerror(-r)); return r; @@ -759,12 +862,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 +937,4 @@ finish: sd_event_unref(context.event); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; - }