From 41dd15e474accdeb643c8319e257e6414c1c498a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Nov 2013 17:07:07 +0100 Subject: [PATCH 1/1] systemctl: restore ability to directly connect to PID1 from systemctl --- TODO | 2 +- src/libsystemd-bus/bus-util.c | 75 +++++++++++++++++++++++++++++++++++ src/libsystemd-bus/bus-util.h | 2 + src/systemctl/systemctl.c | 18 ++++----- 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index 9b8df458b..e08e11e2d 100644 --- a/TODO +++ b/TODO @@ -48,7 +48,7 @@ Features: * add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt -* direct connections to PID 1/XDG_RUNTIME_DIR, wait filter, reboot() filter unification, unify dispatch table in systemctl_main() and friends, convert all to bus_log_create_error() +* wait filter, reboot() filter unification, unify dispatch table in systemctl_main() and friends, convert all to bus_log_create_error() * bus: access policy as vtable flag diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 2cf718b09..3dd208d0c 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -440,6 +440,46 @@ int bus_open_system_systemd(sd_bus **_bus) { return 0; } +int bus_open_user_systemd(sd_bus **_bus) { + _cleanup_bus_unref_ sd_bus *bus = NULL; + _cleanup_free_ char *p = NULL; + const char *e; + int r; + + /* If we are supposed to talk to the instance, try via + * XDG_RUNTIME_DIR first, then fallback to normal bus + * access */ + + assert(_bus); + + e = secure_getenv("XDG_RUNTIME_DIR"); + if (e) { + if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) + return -ENOMEM; + } + + r = sd_bus_new(&bus); + if (r < 0) + return r; + + r = sd_bus_set_address(bus, p); + if (r < 0) + return r; + + r = sd_bus_start(bus); + if (r < 0) + return r; + + r = bus_check_peercred(bus); + if (r < 0) + return r; + + *_bus = bus; + bus = NULL; + + return 0; +} + int bus_print_property(const char *name, sd_bus_message *property, bool all) { char type; const char *contents; @@ -924,6 +964,41 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b return r; } +int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { + int r; + + assert(transport >= 0); + assert(transport < _BUS_TRANSPORT_MAX); + assert(bus); + + assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); + assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP); + + switch (transport) { + + case BUS_TRANSPORT_LOCAL: + if (user) + r = bus_open_user_systemd(bus); + else + r = bus_open_system_systemd(bus); + + break; + + case BUS_TRANSPORT_REMOTE: + r = sd_bus_open_system_remote(host, bus); + break; + + case BUS_TRANSPORT_CONTAINER: + r = sd_bus_open_system_container(host, bus); + break; + + default: + assert_not_reached("Hmm, unknown transport type."); + } + + return r; +} + int bus_property_get_bool( sd_bus *bus, const char *path, diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h index 21a483fb0..314c2f786 100644 --- a/src/libsystemd-bus/bus-util.h +++ b/src/libsystemd-bus/bus-util.h @@ -63,8 +63,10 @@ int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry); int bus_open_system_systemd(sd_bus **_bus); +int bus_open_user_systemd(sd_bus **_bus); int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_print_property(const char *name, sd_bus_message *property, bool all); int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7a2431986..73fdbdbed 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5354,7 +5354,7 @@ static int talk_initctl(void) { return 1; } -static int systemctl_main(sd_bus *bus, int argc, char *argv[], const int r) { +static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) { static const struct { const char* verb; @@ -5505,14 +5505,14 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], const int r) { if (((!streq(verbs[i].verb, "reboot") && !streq(verbs[i].verb, "halt") && !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) { - log_error("Failed to get D-Bus connection: %s", strerror (-r)); + log_error("Failed to get D-Bus connection: %s", strerror (-bus_error)); return -EIO; } } else { if (!bus && !avoid_bus()) { - log_error("Failed to get D-Bus connection: %s", strerror (-r)); + log_error("Failed to get D-Bus connection: %s", strerror (-bus_error)); return -EIO; } } @@ -5764,13 +5764,11 @@ int main(int argc, char*argv[]) { goto finish; } - if (!avoid_bus()) { - r = bus_open_transport(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus); - if (r < 0) { - log_error("Failed to create bus connection: %s", strerror(-r)); - goto finish; - } - } + if (!avoid_bus()) + r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus); + + /* systemctl_main() will print an error message for the bus + * connection, but only if it needs to */ switch (arg_action) { -- 2.30.2