Merge pull request #22445 from lnussel/logind
logind: post review fixes
This commit is contained in:
+90
-98
@@ -20,101 +20,99 @@
|
||||
|
||||
static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = {
|
||||
[HANDLE_POWEROFF] = {
|
||||
SPECIAL_POWEROFF_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.power-off",
|
||||
"org.freedesktop.login1.power-off-multiple-sessions",
|
||||
"org.freedesktop.login1.power-off-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is powering down",
|
||||
"power-off",
|
||||
},
|
||||
.handle = HANDLE_POWEROFF,
|
||||
.target = SPECIAL_POWEROFF_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.power-off",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is powering down",
|
||||
.log_message = "power-off",
|
||||
},
|
||||
[HANDLE_REBOOT] = {
|
||||
SPECIAL_REBOOT_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.reboot",
|
||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is rebooting",
|
||||
"reboot",
|
||||
},
|
||||
[HANDLE_HALT] = {
|
||||
SPECIAL_HALT_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.halt",
|
||||
"org.freedesktop.login1.halt-multiple-sessions",
|
||||
"org.freedesktop.login1.halt-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is halting",
|
||||
"halt",
|
||||
},
|
||||
[HANDLE_KEXEC] = {
|
||||
SPECIAL_KEXEC_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.reboot",
|
||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is rebooting with kexec",
|
||||
"kexec",
|
||||
},
|
||||
[HANDLE_SUSPEND] = {
|
||||
SPECIAL_SUSPEND_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.suspend",
|
||||
"org.freedesktop.login1.suspend-multiple-sessions",
|
||||
"org.freedesktop.login1.suspend-ignore-inhibit",
|
||||
SLEEP_SUSPEND,
|
||||
},
|
||||
[HANDLE_HIBERNATE] = {
|
||||
SPECIAL_HIBERNATE_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_HIBERNATE,
|
||||
},
|
||||
[HANDLE_HYBRID_SLEEP] = {
|
||||
SPECIAL_HYBRID_SLEEP_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_HYBRID_SLEEP,
|
||||
},
|
||||
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
||||
SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
||||
},
|
||||
[HANDLE_FACTORY_RESET] = {
|
||||
SPECIAL_FACTORY_RESET_TARGET,
|
||||
_INHIBIT_WHAT_INVALID,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_FACTORY_RESET_STR,
|
||||
"System is performing factory reset",
|
||||
NULL
|
||||
},
|
||||
.handle = HANDLE_REBOOT,
|
||||
.target = SPECIAL_REBOOT_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.reboot",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is rebooting",
|
||||
.log_message = "reboot",
|
||||
},
|
||||
[HANDLE_HALT] = {
|
||||
.handle = HANDLE_HALT,
|
||||
.target = SPECIAL_HALT_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.halt",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is halting",
|
||||
.log_message = "halt",
|
||||
},
|
||||
[HANDLE_KEXEC] = {
|
||||
.handle = HANDLE_KEXEC,
|
||||
.target = SPECIAL_KEXEC_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.reboot",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is rebooting with kexec",
|
||||
.log_message = "kexec",
|
||||
},
|
||||
[HANDLE_SUSPEND] = {
|
||||
.handle = HANDLE_SUSPEND,
|
||||
.target = SPECIAL_SUSPEND_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.suspend",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.suspend-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.suspend-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_SUSPEND,
|
||||
},
|
||||
[HANDLE_HIBERNATE] = {
|
||||
.handle = HANDLE_HIBERNATE,
|
||||
.target = SPECIAL_HIBERNATE_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_HIBERNATE,
|
||||
},
|
||||
[HANDLE_HYBRID_SLEEP] = {
|
||||
.handle = HANDLE_HYBRID_SLEEP,
|
||||
.target = SPECIAL_HYBRID_SLEEP_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_HYBRID_SLEEP,
|
||||
},
|
||||
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
||||
.handle = HANDLE_SUSPEND_THEN_HIBERNATE,
|
||||
.target = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_SUSPEND_THEN_HIBERNATE,
|
||||
},
|
||||
[HANDLE_FACTORY_RESET] = {
|
||||
.handle = HANDLE_FACTORY_RESET,
|
||||
.target = SPECIAL_FACTORY_RESET_TARGET,
|
||||
.inhibit_what = _INHIBIT_WHAT_INVALID,
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_FACTORY_RESET_STR,
|
||||
.message = "System is performing factory reset",
|
||||
},
|
||||
};
|
||||
|
||||
const char* manager_target_for_action(HandleAction handle) {
|
||||
assert(handle >= 0);
|
||||
assert(handle < (ssize_t) ELEMENTSOF(action_table));
|
||||
|
||||
return action_table[handle].target;
|
||||
}
|
||||
|
||||
const ActionTableItem* manager_item_for_handle(HandleAction handle) {
|
||||
assert(handle >= 0);
|
||||
assert(handle < (ssize_t) ELEMENTSOF(action_table));
|
||||
@@ -122,12 +120,6 @@ const ActionTableItem* manager_item_for_handle(HandleAction handle) {
|
||||
return &action_table[handle];
|
||||
}
|
||||
|
||||
HandleAction manager_handle_for_item(const ActionTableItem* a) {
|
||||
if (a && a < action_table + ELEMENTSOF(action_table))
|
||||
return a - action_table;
|
||||
return _HANDLE_ACTION_INVALID;
|
||||
}
|
||||
|
||||
int manager_handle_action(
|
||||
Manager *m,
|
||||
InhibitWhat inhibit_key,
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct ActionTableItem ActionTableItem;
|
||||
#include "sleep-config.h"
|
||||
|
||||
struct ActionTableItem {
|
||||
HandleAction handle;
|
||||
const char *target;
|
||||
InhibitWhat inhibit_what;
|
||||
const char *polkit_action;
|
||||
@@ -36,8 +37,7 @@ struct ActionTableItem {
|
||||
SleepOperation sleep_operation;
|
||||
const char* message_id;
|
||||
const char* message;
|
||||
const char* log_str;
|
||||
|
||||
const char* log_message;
|
||||
};
|
||||
|
||||
int manager_handle_action(
|
||||
@@ -50,7 +50,6 @@ int manager_handle_action(
|
||||
const char* handle_action_to_string(HandleAction h) _const_;
|
||||
HandleAction handle_action_from_string(const char *s) _pure_;
|
||||
|
||||
const char* manager_target_for_action(HandleAction handle);
|
||||
const ActionTableItem* manager_item_for_handle(HandleAction handle);
|
||||
HandleAction manager_handle_for_item(const ActionTableItem* a);
|
||||
|
||||
|
||||
+27
-21
@@ -54,6 +54,15 @@
|
||||
#include "utmp-wtmp.h"
|
||||
#include "virt.h"
|
||||
|
||||
/* As a random fun fact sysvinit had a 252 (256-(strlen(" \r\n")+1))
|
||||
* character limit for the wall message.
|
||||
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72
|
||||
* There is no real technical need for that but doesn't make sense
|
||||
* to store arbitrary amounts either. As we are not stingy here, we
|
||||
* allow 4k.
|
||||
*/
|
||||
#define WALL_MESSAGE_MAX 4096
|
||||
|
||||
static void reset_scheduled_shutdown(Manager *m);
|
||||
|
||||
static int get_sender_session(
|
||||
@@ -349,7 +358,7 @@ static int property_get_scheduled_shutdown(
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "st",
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
|
||||
m->scheduled_shutdown_type ? handle_action_to_string(m->scheduled_shutdown_type->handle) : NULL,
|
||||
m->scheduled_shutdown_timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1499,13 +1508,13 @@ static int bus_manager_log_shutdown(
|
||||
Manager *m,
|
||||
const ActionTableItem *a) {
|
||||
|
||||
const char *message, *log_str;
|
||||
const char *message, *log_message;
|
||||
|
||||
assert(m);
|
||||
assert(a);
|
||||
|
||||
message = a->message;
|
||||
log_str = a->log_str;
|
||||
log_message = a->log_message;
|
||||
|
||||
if (message)
|
||||
message = strjoina("MESSAGE=", message);
|
||||
@@ -1517,13 +1526,13 @@ static int bus_manager_log_shutdown(
|
||||
else
|
||||
message = strjoina(message, " (", m->wall_message, ").");
|
||||
|
||||
if (log_str)
|
||||
log_str = strjoina("SHUTDOWN=", log_str);
|
||||
if (log_message)
|
||||
log_message = strjoina("SHUTDOWN=", log_message);
|
||||
|
||||
return log_struct(LOG_NOTICE,
|
||||
"MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
|
||||
message,
|
||||
log_str);
|
||||
log_message);
|
||||
}
|
||||
|
||||
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
|
||||
@@ -1884,7 +1893,7 @@ static int method_do_shutdown_or_sleep(
|
||||
return r;
|
||||
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
|
||||
if (manager_handle_for_item(a) != HANDLE_REBOOT && (flags & SD_LOGIND_REBOOT_VIA_KEXEC))
|
||||
if (a->handle != HANDLE_REBOOT && (flags & SD_LOGIND_REBOOT_VIA_KEXEC))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Reboot via kexec is only applicable with reboot operations");
|
||||
} else {
|
||||
/* Old style method: no flags parameter, but interactive bool passed as boolean in
|
||||
@@ -2035,6 +2044,7 @@ static int update_schedule_file(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->scheduled_shutdown_type);
|
||||
|
||||
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
|
||||
if (r < 0)
|
||||
@@ -2052,7 +2062,7 @@ static int update_schedule_file(Manager *m) {
|
||||
"MODE=%s\n",
|
||||
m->scheduled_shutdown_timeout,
|
||||
m->enable_wall_messages,
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)));
|
||||
handle_action_to_string(m->scheduled_shutdown_type->handle));
|
||||
|
||||
if (!isempty(m->wall_message)) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
@@ -2240,9 +2250,10 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
|
||||
assert(m);
|
||||
assert(message);
|
||||
|
||||
cancelled = !IN_SET(manager_handle_for_item(m->scheduled_shutdown_type), HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
|
||||
cancelled = m->scheduled_shutdown_type
|
||||
&& !IN_SET(m->scheduled_shutdown_type->handle, HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
|
||||
if (!cancelled)
|
||||
goto done;
|
||||
return sd_bus_reply_method_return(message, "b", false);
|
||||
|
||||
a = m->scheduled_shutdown_type;
|
||||
if (!a->polkit_action)
|
||||
@@ -2281,8 +2292,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
|
||||
username, tty, logind_wall_tty_filter, m);
|
||||
}
|
||||
|
||||
done:
|
||||
return sd_bus_reply_method_return(message, "b", cancelled);
|
||||
return sd_bus_reply_method_return(message, "b", true);
|
||||
}
|
||||
|
||||
static int method_can_shutdown_or_sleep(
|
||||
@@ -2328,7 +2338,7 @@ static int method_can_shutdown_or_sleep(
|
||||
if (handle >= 0) {
|
||||
const char *target;
|
||||
|
||||
target = manager_target_for_action(handle);
|
||||
target = manager_item_for_handle(handle)->target;
|
||||
if (target) {
|
||||
_cleanup_free_ char *load_state = NULL;
|
||||
|
||||
@@ -3115,14 +3125,10 @@ static int method_set_wall_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* sysvinit has a 252 (256-(strlen(" \r\n")+1)) character
|
||||
* limit for the wall message. There is no real technical
|
||||
* need for that but doesn't make sense to store arbitrary
|
||||
* amounts either.
|
||||
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72)
|
||||
*/
|
||||
if (strlen(wall_message) > 252)
|
||||
return -EMSGSIZE;
|
||||
if (strlen(wall_message) > WALL_MESSAGE_MAX)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Wall message too long, maximum permitted length is %u characters.",
|
||||
WALL_MESSAGE_MAX);
|
||||
|
||||
/* Short-circuit the operation if the desired state is already in place, to
|
||||
* avoid an unnecessary polkit permission check. */
|
||||
|
||||
@@ -64,7 +64,7 @@ static int warn_wall(Manager *m, usec_t n) {
|
||||
|
||||
assert(m);
|
||||
|
||||
if (!m->enable_wall_messages)
|
||||
if (!m->enable_wall_messages || !m->scheduled_shutdown_type)
|
||||
return 0;
|
||||
|
||||
left = m->scheduled_shutdown_timeout > n;
|
||||
@@ -72,7 +72,7 @@ static int warn_wall(Manager *m, usec_t n) {
|
||||
r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
|
||||
strempty(m->wall_message),
|
||||
isempty(m->wall_message) ? "" : "\n",
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
|
||||
handle_action_to_string(m->scheduled_shutdown_type->handle),
|
||||
left ? "at " : "NOW",
|
||||
left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : "");
|
||||
if (r < 0) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "systemctl-compat-halt.h"
|
||||
#include "systemctl-compat-telinit.h"
|
||||
#include "systemctl-logind.h"
|
||||
#include "systemctl-start-unit.h"
|
||||
#include "systemctl-util.h"
|
||||
#include "systemctl.h"
|
||||
#include "terminal-util.h"
|
||||
@@ -144,30 +145,32 @@ int halt_parse_argv(int argc, char *argv[]) {
|
||||
int halt_main(void) {
|
||||
int r;
|
||||
|
||||
/* always try logind first */
|
||||
if (arg_when > 0)
|
||||
r = logind_schedule_shutdown();
|
||||
else {
|
||||
r = logind_check_inhibitors(arg_action);
|
||||
if (r < 0)
|
||||
if (arg_force == 0) {
|
||||
/* always try logind first */
|
||||
if (arg_when > 0)
|
||||
r = logind_schedule_shutdown();
|
||||
else {
|
||||
r = logind_check_inhibitors(arg_action);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = logind_reboot(arg_action);
|
||||
}
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||
/* Requested operation requires auth, is not supported on the local system or already in
|
||||
* progress */
|
||||
return r;
|
||||
/* on all other errors, try low-level operation */
|
||||
|
||||
r = logind_reboot(arg_action);
|
||||
/* In order to minimize the difference between operation with and without logind, we explicitly
|
||||
* enable non-blocking mode for this, as logind's shutdown operations are always non-blocking. */
|
||||
arg_no_block = true;
|
||||
|
||||
if (!arg_dry_run)
|
||||
return start_with_fallback();
|
||||
}
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||
/* Requested operation requires auth, is not supported on the local system or already in
|
||||
* progress */
|
||||
return r;
|
||||
/* on all other errors, try low-level operation */
|
||||
|
||||
/* In order to minimize the difference between operation with and without logind, we explicitly
|
||||
* enable non-blocking mode for this, as logind's shutdown operations are always non-blocking. */
|
||||
arg_no_block = true;
|
||||
|
||||
if (!arg_dry_run && !arg_force)
|
||||
return start_with_fallback();
|
||||
|
||||
if (geteuid() != 0) {
|
||||
(void) must_be_root();
|
||||
|
||||
Reference in New Issue
Block a user