systemctl: restore ability to directly connect to PID1 from systemctl

This commit is contained in:
Lennart Poettering 2013-11-08 17:07:07 +01:00
parent 3f41e1e595
commit 41dd15e474
4 changed files with 86 additions and 11 deletions

2
TODO
View File

@ -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

View 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,

View 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);

View 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) {