systemctl: describe the halt/poweroff/reboot/shutdown compat commands

The custom halt_help() and shutdown_help() are replaced by COMMAND()
descriptions (one per command name, halt/poweroff/reboot sharing the
"halt" option namespace), and --introspect-cli is added to both parsers.
halt/poweroff/reboot now each reference their own man page name.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-08-25 09:33:51 +02:00
parent 4cf46d47a2
commit 2364f0d7c8
3 changed files with 71 additions and 68 deletions
+38 -35
View File
@@ -1,12 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-daemon.h"
#include "sd-json.h"
#include "ansi-color.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "process-util.h"
#include "reboot-util.h"
#include "systemctl.h"
@@ -15,40 +13,35 @@
#include "systemctl-start-unit.h"
#include "systemctl-util.h"
#include "utmp-wtmp.h"
#include "verbs.h"
static int halt_help(void) {
_cleanup_(table_unrefp) Table *options = NULL;
int r;
COMMAND(
"halt\0",
"Halt the system.",
.footer = "This is a compatibility interface, please use the more powerful "
"'systemctl halt' command instead.",
.man_pages = "halt.8\0",
.option_namespace = "halt",
);
r = option_parser_get_help_table_ns("halt", &options);
if (r < 0)
return r;
COMMAND(
"poweroff\0",
"Power off the system.",
.footer = "This is a compatibility interface, please use the more powerful "
"'systemctl poweroff' command instead.",
.man_pages = "poweroff.8\0",
.option_namespace = "halt",
);
/* Note: if you are tempted to add new command line switches here, please do not. Let this
* compatibility command rest in peace. Its interface is not even owned by us as much as it is by
* sysvinit. If you add something new, add it to "systemctl halt", "systemctl reboot", "systemctl
* poweroff" instead. */
help_cmdline(arg_action == ACTION_REBOOT ? "[OPTIONS…] [ARG]" : "[OPTIONS…]");
help_abstract(arg_action == ACTION_REBOOT ? "Reboot the system." :
arg_action == ACTION_POWEROFF ? "Power off the system." :
"Halt the system.");
help_section("Options");
r = table_print_or_warn(options);
if (r < 0)
return r;
printf("\n%sThis is a compatibility interface, please use the more powerful 'systemctl %s' command instead.%s\n",
ansi_highlight_red(),
arg_action == ACTION_REBOOT ? "reboot" :
arg_action == ACTION_POWEROFF ? "poweroff" :
"halt",
ansi_normal());
help_man_page_reference("halt", "8");
return 0;
}
COMMAND(
"reboot\0",
"Reboot the system.",
.argspec = "[ARG]\0",
.footer = "This is a compatibility interface, please use the more powerful "
"'systemctl reboot' command instead.",
.man_pages = "reboot.8\0",
.option_namespace = "halt",
);
int halt_parse_argv(int argc, char *argv[], int log_level_shift) {
int r;
@@ -62,13 +55,20 @@ int halt_parse_argv(int argc, char *argv[], int log_level_shift) {
.log_level_shift = log_level_shift,
};
/* Note: if you are tempted to add new command line switches here, please do not. Let this
* compatibility command rest in peace. Its interface is not even owned by us as much as it
* is by sysvinit. If you add something new, add it to "systemctl halt", "systemctl
* reboot", "systemctl poweroff" instead. */
FOREACH_OPTION_OR_RETURN(c, &opts)
switch (c) {
OPTION_NAMESPACE("halt"): {}
OPTION_LONG("help", NULL, "Show this help"):
return halt_help();
return command_print_help_full(
action_table[arg_action].verb,
/* footer_ansi_seq= */ ansi_highlight_red());
OPTION_LONG("halt", NULL, "Halt the machine"):
arg_action = ACTION_HALT;
@@ -108,6 +108,9 @@ int halt_parse_argv(int argc, char *argv[], int log_level_shift) {
OPTION_SHORT('h', NULL, /* help= */ NULL):
/* Compatibility nops */
break;
OPTION_COMMON_INTROSPECT_CLI:
return introspect_cli(SD_JSON_FORMAT_OFF);
}
char **args = option_parser_get_args(&opts);
+23 -32
View File
@@ -1,10 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-json.h"
#include "ansi-color.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "parse-util.h"
#include "reboot-util.h"
#include "string-util.h"
@@ -12,35 +11,17 @@
#include "systemctl.h"
#include "systemctl-compat-shutdown.h"
#include "time-util.h"
#include "verbs.h"
static int shutdown_help(void) {
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("shutdown", &options);
if (r < 0)
return r;
/* Note: if you are tempted to add new command line switches here, please do not. Let this
* compatibility command rest in peace. Its interface is not even owned by us as much as it is by
* sysvinit. If you add something new, add it to "systemctl halt", "systemctl reboot", "systemctl
* poweroff" instead. */
help_cmdline("[OPTIONS…] [TIME] [WALL…]");
help_abstract("Shut down the system.");
help_section("Options");
r = table_print_or_warn(options);
if (r < 0)
return r;
printf("\n%sThis is a compatibility interface, please use the more powerful 'systemctl halt',\n"
"'systemctl poweroff', 'systemctl reboot' commands instead.%s\n",
ansi_highlight_red(), ansi_normal());
help_man_page_reference("shutdown", "8");
return 0;
}
COMMAND(
"shutdown\0",
"Shut down the system.",
.argspec = "[TIME] [WALL…]\0",
.footer = "This is a compatibility interface, please use the more powerful 'systemctl halt', "
"'systemctl poweroff', 'systemctl reboot' commands instead.",
.man_pages = "shutdown.8\0",
.option_namespace = "shutdown",
);
static int parse_shutdown_time_spec(const char *t, usec_t *ret) {
int r;
@@ -128,13 +109,20 @@ int shutdown_parse_argv(int argc, char *argv[], int log_level_shift) {
.log_level_shift = log_level_shift,
};
/* Note: if you are tempted to add new command line switches here, please do not. Let this
* compatibility command rest in peace. Its interface is not even owned by us as much as it
* is by sysvinit. If you add something new, add it to "systemctl halt", "systemctl
* reboot", "systemctl poweroff" instead. */
FOREACH_OPTION_OR_RETURN(c, &opts)
switch (c) {
OPTION_NAMESPACE("shutdown"): {}
OPTION_LONG("help", NULL, "Show this help"):
return shutdown_help();
return command_print_help_full(
"shutdown",
/* footer_ansi_seq= */ ansi_highlight_red());
OPTION('H', "halt", NULL, "Halt the machine"):
arg_action = ACTION_HALT;
@@ -182,6 +170,9 @@ int shutdown_parse_argv(int argc, char *argv[], int log_level_shift) {
OPTION_SHORT('F', NULL, /* help= */ NULL): {}
OPTION_SHORT('t', "ARG", /* help= */ NULL):
break;
OPTION_COMMON_INTROSPECT_CLI:
return introspect_cli(SD_JSON_FORMAT_OFF);
}
char **args = option_parser_get_args(&opts);
+10 -1
View File
@@ -18,6 +18,7 @@ INTROSPECTABLE=(
coredumpctl
dmi_memory_id
fido_id
halt
homectl
hostnamectl
importctl
@@ -30,9 +31,12 @@ INTROSPECTABLE=(
networkctl
oomctl
portablectl
poweroff
reboot
resolvectl
run0
scsi_id
shutdown
storagectl
systemctl
systemd-ac-power
@@ -138,7 +142,9 @@ for i in "${INTROSPECTABLE[@]}"; do
$i --intro | grep -e --help
# If the tool has a "help" verb, it must work too
if $i --introspect-cli | jq -e 'any(.commands[]; (.verbs // []) | any(.names[0] == "help"))' >/dev/null; then
if $i --introspect-cli | jq -e --arg name "$i" \
'any(.commands[]; any(.names[]; . == $name) and ((.verbs // []) | any(.names[0] == "help")))' \
>/dev/null; then
# 'systemctl help' shows unit manuals
[[ "$i" == systemctl ]] && continue
@@ -172,3 +178,6 @@ systemd-mstack --introspect-cli | jq -e \
systemd-run --introspect-cli | jq -e \
'[.commands[].names[0]] | sort == ["run0", "systemd-run"]'
systemctl --introspect-cli | jq -e \
'[.commands[].names[0]] | sort == ["halt", "poweroff", "reboot", "shutdown", "systemctl"]'