shutdown: convert to VERB_COMMAND and add --introspect-cli
systemd-shutdown parsed a bunch of options, but had no way to print them. Add the standard --help and --version options and the CLI introspection. parse_argv() is moved before the PID 1 check, so that the new options also work when the binary is invoked manually. As PID 1 we can never return from main() (the kernel would panic), so in that case parse errors still freeze(), and the help output is followed by a freeze() too. Ctrl-Alt-Delete and console reopening are re-enabled before freezing, so that the freeze can be escaped through the kernel and the error is visible, as before. The --help/--version/introspect-cli option names are already listed in the kernel command line exclusion list in proc-cmdline.c.
This commit is contained in:
+37
-7
@@ -16,6 +16,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "async.h"
|
||||
#include "binfmt-util.h"
|
||||
#include "build.h"
|
||||
#include "cgroup-setup.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "constants.h"
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
#include "umount.h"
|
||||
#include "verbs.h"
|
||||
#include "virt.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
@@ -60,6 +62,13 @@ static const char *arg_verb = NULL;
|
||||
static uint8_t arg_exit_code = 0;
|
||||
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
|
||||
|
||||
COMMAND(
|
||||
"systemd-shutdown\0",
|
||||
"Execute the final phase of system shutdown.",
|
||||
.argspec = "reboot|poweroff|halt|kexec|exit\0",
|
||||
.man_pages = "systemd-shutdown.8\0",
|
||||
);
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 1);
|
||||
assert(argv);
|
||||
@@ -75,6 +84,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
FOREACH_OPTION_OR_RETURN(c, &opts)
|
||||
switch (c) {
|
||||
|
||||
OPTION_COMMON_HELP:
|
||||
return command_print_help();
|
||||
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
OPTION_COMMON_INTROSPECT_CLI:
|
||||
return introspect_cli(SD_JSON_FORMAT_OFF);
|
||||
|
||||
OPTION_COMMON_LOG_LEVEL:
|
||||
r = log_set_max_level_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
@@ -149,7 +167,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (!arg_verb)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Verb argument missing.");
|
||||
|
||||
return 0;
|
||||
return 1; /* Further action */
|
||||
}
|
||||
|
||||
static int switch_root_initramfs(void) {
|
||||
@@ -403,9 +421,17 @@ static int run(int argc, char *argv[]) {
|
||||
log_set_prohibit_ipc(true);
|
||||
log_parse_environment();
|
||||
|
||||
if (getpid_cached() != 1)
|
||||
r = parse_argv(argc, argv);
|
||||
if (getpid_cached() != 1) {
|
||||
/* If we're a normal user space process, our work is done. Either we hit an error, or were
|
||||
* called with --help, --version, or another option that was handled by parse_argv(), or it
|
||||
* looks like we're being asked to do some real work, but we should do that only as part of
|
||||
* the real shutdown sequence. */
|
||||
if (r <= 0)
|
||||
return r;
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Not executed by init (PID 1). Refusing to operate.");
|
||||
}
|
||||
|
||||
log_set_always_reopen_console(true);
|
||||
|
||||
@@ -414,8 +440,7 @@ static int run(int argc, char *argv[]) {
|
||||
* through kernel. */
|
||||
(void) reboot(RB_ENABLE_CAD);
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r < 0)
|
||||
if (r <= 0)
|
||||
goto error;
|
||||
|
||||
log_open();
|
||||
@@ -711,9 +736,14 @@ static int run(int argc, char *argv[]) {
|
||||
r = log_error_errno(errno, "Failed to invoke reboot(): %m");
|
||||
|
||||
error:
|
||||
log_struct_errno(LOG_EMERG, r,
|
||||
LOG_MESSAGE("Critical error while doing system shutdown: %m"),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN_ERROR_STR));
|
||||
if (r == 0)
|
||||
log_struct(LOG_EMERG,
|
||||
LOG_MESSAGE("Non-shutdown operation requested, cannot operate."),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN_ERROR_STR));
|
||||
else
|
||||
log_struct_errno(LOG_EMERG, r,
|
||||
LOG_MESSAGE("Critical error while doing system shutdown: %m"),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN_ERROR_STR));
|
||||
freeze();
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ INTROSPECTABLE=(
|
||||
systemd-resolved
|
||||
systemd-run
|
||||
systemd-sbsign
|
||||
systemd-shutdown
|
||||
systemd-sleep
|
||||
systemd-socket-activate
|
||||
systemd-socket-proxyd
|
||||
|
||||
Reference in New Issue
Block a user