summaryrefslogtreecommitdiff
path: root/src/login/logind-dbus.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-10-02 16:03:55 +0200
committerSven Eden <yamakuzure@gmx.net>2017-12-08 07:30:24 +0100
commitdfa9a97253a144ff90e64d271e6d02dec6a2ebad (patch)
tree9e1695845519d0f01c2a16ec78a4a16f17ab8111 /src/login/logind-dbus.c
parent7cd8f97c73ef8e5d6f6734683b4e597307a2cb7c (diff)
logind: add Halt() and CanHalt() APIs
This adds new method calls Halt() and CanHalt() to the logind bus APIs. They aren't overly useful (as the whole concept of halting isn't really too useful), however they clean up one major asymmetry: currently, using the "shutdown" legacy commands it is possibly to enqueue a "halt" operation through logind, while logind officially doesn't actually support this. Moreover, the path through "shutdown" currently ultimately fails, since the referenced "halt" action isn't actually defined in PolicyKit. Finally, the current logic results in an unexpected asymmetry in systemctl: "systemctl poweroff", "systemctl reboot" are currently asynchronous (due to the logind involvement) while "systemctl halt" isnt. Let's clean this up, and make all three APIs implemented by logind natively, and all three hence asynchronous in "systemctl". Moreover, let's add the missing PK action. Fixes: #6957
Diffstat (limited to 'src/login/logind-dbus.c')
-rw-r--r--src/login/logind-dbus.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 8247ec494..207b4358a 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1424,12 +1424,12 @@ static int bus_manager_log_shutdown(
if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
p = "MESSAGE=System is powering down";
q = "SHUTDOWN=power-off";
- } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
- p = "MESSAGE=System is halting";
- q = "SHUTDOWN=halt";
} else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
p = "MESSAGE=System is rebooting";
q = "SHUTDOWN=reboot";
+ } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
+ p = "MESSAGE=System is halting";
+ q = "SHUTDOWN=halt";
} else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
p = "MESSAGE=System is rebooting with kexec";
q = "SHUTDOWN=kexec";
@@ -1866,6 +1866,20 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
error);
}
+static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_do_shutdown_or_sleep(
+ m, message,
+ SPECIAL_HALT_TARGET,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.halt",
+ "org.freedesktop.login1.halt-multiple-sessions",
+ "org.freedesktop.login1.halt-ignore-inhibit",
+ NULL,
+ error);
+}
+
static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
@@ -1957,9 +1971,12 @@ fail:
}
static void reset_scheduled_shutdown(Manager *m) {
+ assert(m);
+
m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
+
m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
m->scheduled_shutdown_timeout = 0;
m->shutdown_dry_run = false;
@@ -1968,6 +1985,7 @@ static void reset_scheduled_shutdown(Manager *m) {
(void) unlink("/run/nologin");
m->unlink_nologin = false;
}
+
(void) unlink("/run/systemd/shutdown/scheduled");
}
@@ -1987,12 +2005,14 @@ static int manager_scheduled_shutdown_handler(
if (isempty(m->scheduled_shutdown_type))
return 0;
- if (streq(m->scheduled_shutdown_type, "halt"))
- target = SPECIAL_HALT_TARGET;
- else if (streq(m->scheduled_shutdown_type, "poweroff"))
+ if (streq(m->scheduled_shutdown_type, "poweroff"))
target = SPECIAL_POWEROFF_TARGET;
- else
+ else if (streq(m->scheduled_shutdown_type, "reboot"))
target = SPECIAL_REBOOT_TARGET;
+ else if (streq(m->scheduled_shutdown_type, "halt"))
+ target = SPECIAL_HALT_TARGET;
+ else
+ assert_not_reached("unexpected shutdown type");
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what) {
@@ -2051,7 +2071,11 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
m->shutdown_dry_run = true;
}
- if (streq(type, "reboot")) {
+ if (streq(type, "poweroff")) {
+ action = "org.freedesktop.login1.power-off";
+ action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
+ action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
+ } else if (streq(type, "reboot")) {
action = "org.freedesktop.login1.reboot";
action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
@@ -2059,10 +2083,6 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
action = "org.freedesktop.login1.halt";
action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
- } else if (streq(type, "poweroff")) {
- action = "org.freedesktop.login1.power-off";
- action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
@@ -2333,6 +2353,19 @@ static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_err
error);
}
+static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_can_shutdown_or_sleep(
+ m, message,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.halt",
+ "org.freedesktop.login1.halt-multiple-sessions",
+ "org.freedesktop.login1.halt-ignore-inhibit",
+ NULL,
+ error);
+}
+
static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
@@ -2699,11 +2732,13 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),