From: Lennart Poettering Date: Mon, 27 Jan 2014 20:34:54 +0000 (+0100) Subject: bus: add API calls for connecting to starter bus X-Git-Tag: v209~325 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=af08d2f9cde8f46d9d3e731dbd1f06ffb3b08942 bus: add API calls for connecting to starter bus Add new calls sd_bus_open() and sd_bus_default() for connecting to the starter bus a service was invoked for, or -- if the process is not a bus-activated service -- the appropriate bus for the scope the process has been started in. --- diff --git a/src/bus-driverd/bus-driverd.c b/src/bus-driverd/bus-driverd.c index 319596a40..acb5e6ba0 100644 --- a/src/bus-driverd/bus-driverd.c +++ b/src/bus-driverd/bus-driverd.c @@ -847,11 +847,7 @@ static int connect_bus(Context *c) { assert(c); - 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); + r = sd_bus_default(&c->bus); if (r < 0) { log_error("Failed to create bus: %s", strerror(-r)); return r; diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 9416f223e..a5aa1d1ca 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -80,8 +80,10 @@ global: /* Same order as in sd-bus.h should be used */ /* Connections */ + sd_bus_default; sd_bus_default_user; sd_bus_default_system; + sd_bus_open; sd_bus_open_user; sd_bus_open_system; sd_bus_open_system_remote; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 9f8c244bf..420393054 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -35,6 +35,7 @@ #include "set.h" #include "missing.h" #include "def.h" +#include "cgroup-util.h" #include "sd-bus.h" #include "bus-internal.h" @@ -1052,6 +1053,60 @@ _public_ int sd_bus_start(sd_bus *bus) { return bus_send_hello(bus); } +_public_ int sd_bus_open(sd_bus **ret) { + const char *e; + sd_bus *b; + int r; + + assert_return(ret, -EINVAL); + + /* Let's connect to the starter bus if it is set, and + * otherwise to the bus that is appropropriate for the scope + * we are running in */ + + e = secure_getenv("DBUS_STARTER_BUS_TYPE"); + if (e) { + if (streq(e, "system")) + return sd_bus_open_system(ret); + else if (streq(e, "session") || streq(e, "user")) + return sd_bus_open_user(ret); + } + + e = secure_getenv("DBUS_STARTER_ADDRESS"); + if (!e) { + if (cg_pid_get_owner_uid(0, NULL) >= 0) + return sd_bus_open_user(ret); + else + return sd_bus_open_system(ret); + } + + r = sd_bus_new(&b); + if (r < 0) + return r; + + r = sd_bus_set_address(b, e); + if (r < 0) + goto fail; + + b->bus_client = true; + + /* We don't know whether the bus is trusted or not, so better + * be safe, and authenticate everything */ + b->trusted = false; + b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS; + + r = sd_bus_start(b); + if (r < 0) + goto fail; + + *ret = b; + return 0; + +fail: + bus_free(b); + return r; +} + _public_ int sd_bus_open_system(sd_bus **ret) { const char *e; sd_bus *b; @@ -2913,6 +2968,43 @@ _public_ int sd_bus_default_user(sd_bus **ret) { return bus_default(sd_bus_open_user, &default_user_bus, ret); } +_public_ int sd_bus_default(sd_bus **ret) { + + const char *e; + + /* Let's try our best to reuse another cached connection. If + * the starter bus type is set, connect via our normal + * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that + * we can share the connection with the user/system default + * bus. */ + + e = secure_getenv("DBUS_STARTER_BUS_TYPE"); + if (e) { + if (streq(e, "system")) + return sd_bus_default_system(ret); + else if (streq(e, "user") || streq(e, "session")) + return sd_bus_default_user(ret); + } + + /* No type is specified, so we have not other option than to + * use the starter address if it is set. */ + + e = secure_getenv("DBUS_STARTER_ADDRESS"); + if (e) { + static thread_local sd_bus *default_starter_bus = NULL; + + return bus_default(sd_bus_open, &default_starter_bus, ret); + } + + /* Finally, if nothing is set use the cached connection for + * the right scope */ + + if (cg_pid_get_owner_uid(0, NULL) >= 0) + return sd_bus_default_user(ret); + else + return sd_bus_default_system(ret); +} + _public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) { assert_return(b, -EINVAL); assert_return(tid, -EINVAL); diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 855c9cd16..4ce885601 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -1332,11 +1332,10 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) { int cg_path_get_session(const char *path, char **session) { const char *e, *n, *x; - char *s, *r; + char *s; size_t l; assert(path); - assert(session); /* Skip slices, if there are any */ e = skip_slices(path); @@ -1358,11 +1357,16 @@ int cg_path_get_session(const char *path, char **session) { if (l <= 6) return -ENOENT; - r = strndup(x, l - 6); - if (!r) - return -ENOMEM; + if (session) { + char *r; + + r = strndup(x, l - 6); + if (!r) + return -ENOMEM; + + *session = r; + } - *session = r; return 0; } @@ -1370,8 +1374,6 @@ int cg_pid_get_session(pid_t pid, char **session) { _cleanup_free_ char *cgroup = NULL; int r; - assert(session); - r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 52481c6fc..94cb21c24 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -97,7 +97,9 @@ typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, void *us int sd_bus_default_user(sd_bus **ret); int sd_bus_default_system(sd_bus **ret); +int sd_bus_default(sd_bus **ret); +int sd_bus_open(sd_bus **ret); int sd_bus_open_user(sd_bus **ret); int sd_bus_open_system(sd_bus **ret); int sd_bus_open_system_remote(const char *host, sd_bus **ret);