chiark / gitweb /
systemctl: restore ability to directly connect to PID1 from systemctl
authorLennart Poettering <lennart@poettering.net>
Fri, 8 Nov 2013 16:07:07 +0000 (17:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 8 Nov 2013 16:07:42 +0000 (17:07 +0100)
TODO
src/libsystemd-bus/bus-util.c
src/libsystemd-bus/bus-util.h
src/systemctl/systemctl.c

diff --git a/TODO b/TODO
index 9b8df458b762d946ec1c3ce3db9053fa405ca032..e08e11e2d7829e5e5ba224b44e480b2ee2b01f4c 100644 (file)
--- 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
 
index 2cf718b0964735fd64951d19014695afa4708e02..3dd208d0c1cfb22ddaf76e357e48a1bb9d489547 100644 (file)
@@ -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,
index 21a483fb013b12783d82f0e176ebe4c5d0acdcf6..314c2f786775e766d506ab4c33810f4cefe4ae58 100644 (file)
@@ -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);
index 7a2431986dfd8b650d754e1c37f434d28927acae..73fdbdbed6b6e6dda16ea307e0fd40c69a0c058b 100644 (file)
@@ -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) {