diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 1aa6760665..b346ab5278 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1409,12 +1409,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"; @@ -1822,6 +1822,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; @@ -1911,9 +1925,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; @@ -1922,6 +1939,7 @@ static void reset_scheduled_shutdown(Manager *m) { (void) unlink("/run/nologin"); m->unlink_nologin = false; } + (void) unlink("/run/systemd/shutdown/scheduled"); } @@ -1940,12 +1958,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) { @@ -2002,7 +2022,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"; @@ -2010,10 +2034,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"); @@ -2260,6 +2280,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; @@ -2612,11 +2645,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), diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index c89e40457e..27aac0dd7c 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -132,6 +132,10 @@ send_interface="org.freedesktop.login1.Manager" send_member="Reboot"/> + + @@ -152,6 +156,10 @@ send_interface="org.freedesktop.login1.Manager" send_member="CanReboot"/> + + diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in index 66cbce393c..3e8a9bbe3f 100644 --- a/src/login/org.freedesktop.login1.policy.in +++ b/src/login/org.freedesktop.login1.policy.in @@ -218,6 +218,39 @@ org.freedesktop.login1.reboot + + <_description>Halt the system + <_message>Authentication is required for halting the system. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.set-wall-message + + + + <_description>Halt the system while other users are logged in + <_message>Authentication is required for halting the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + + + <_description>Halt the system while an application asked to inhibit it + <_message>Authentication is required for halting the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + <_description>Suspend the system <_message>Authentication is required for suspending the system. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 280d786daa..2a385bf350 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3267,14 +3267,19 @@ static int logind_reboot(enum action a) { switch (a) { + case ACTION_POWEROFF: + method = "PowerOff"; + description = "power off system"; + break; + case ACTION_REBOOT: method = "Reboot"; description = "reboot system"; break; - case ACTION_POWEROFF: - method = "PowerOff"; - description = "power off system"; + case ACTION_HALT: + method = "Halt"; + description = "halt system"; break; case ACTION_SUSPEND: @@ -3568,6 +3573,7 @@ static int start_special(int argc, char *argv[], void *userdata) { if (IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT, + ACTION_HALT, ACTION_SUSPEND, ACTION_HIBERNATE, ACTION_HYBRID_SLEEP)) { @@ -8503,7 +8509,7 @@ static int halt_main(void) { /* Try logind if we are a normal user and no special * mode applies. Maybe PolicyKit allows us to shutdown * the machine. */ - if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) { + if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) { r = logind_reboot(arg_action); if (r >= 0) return r;