From 1cf40c9c72f8bb192431e0421143fc30bc3b7a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 23 Aug 2026 16:13:30 +0200 Subject: [PATCH 1/9] shared/verbs: stop requiring an explicit program name Almost all programs are simple and have only a single command. When printing options, let's just use the first COMMAND block found by default. This means we can drop the explicit program-name argument and reduce copy&paste boilerplate. --- src/ac-power/ac-power.c | 2 +- src/analyze/analyze.c | 4 ++-- src/ask-password/ask-password.c | 2 +- src/backlight/backlight.c | 4 ++-- src/battery-check/battery-check.c | 2 +- src/binfmt/binfmt.c | 2 +- src/bless-boot/bless-boot.c | 4 ++-- src/bless-boot/boot-check-no-failures.c | 2 +- src/bootctl/bootctl.c | 4 ++-- src/busctl/busctl.c | 4 ++-- src/cgls/cgls.c | 2 +- src/cgtop/cgtop.c | 2 +- src/clonesetup/clonesetup.c | 2 +- src/coredump/coredumpctl.c | 4 ++-- src/creds/creds.c | 4 ++-- src/cryptenroll/cryptenroll.c | 2 +- src/cryptsetup/cryptsetup.c | 4 ++-- src/delta/delta.c | 2 +- src/detect-virt/detect-virt.c | 2 +- src/dissect/dissect.c | 2 +- src/escape/escape-tool.c | 2 +- src/factory-reset/factory-reset-tool.c | 2 +- src/firstboot/firstboot.c | 2 +- src/growfs/growfs.c | 2 +- src/hibernate-resume/hibernate-resume.c | 2 +- src/home/homectl.c | 4 ++-- src/hostname/hostnamectl.c | 4 ++-- src/hwdb/hwdb.c | 4 ++-- src/id128/id128.c | 4 ++-- src/imds/imds-tool.c | 2 +- src/imds/imdsd.c | 2 +- src/import/export.c | 4 ++-- src/import/import-fs.c | 4 ++-- src/import/import.c | 4 ++-- src/import/importctl.c | 4 ++-- src/import/pull.c | 4 ++-- src/journal-remote/journal-gatewayd.c | 2 +- src/journal-remote/journal-remote-main.c | 2 +- src/journal-remote/journal-upload.c | 2 +- src/journal/bsod.c | 2 +- src/journal/cat.c | 2 +- src/journal/journalctl.c | 2 +- src/keyutil/keyutil.c | 4 ++-- src/locale/localectl.c | 4 ++-- src/login/inhibit.c | 2 +- src/login/loginctl.c | 4 ++-- src/machine-id-setup/machine-id-setup-main.c | 2 +- src/machine/machinectl.c | 4 ++-- src/measure/measure-tool.c | 4 ++-- src/modules-load/modules-load.c | 2 +- src/mstack/mstack-tool.c | 2 +- src/mute-console/mute-console.c | 2 +- .../generator/network-generator-main.c | 2 +- src/network/networkctl.c | 4 ++-- src/network/wait-online/wait-online.c | 2 +- src/notify/notify.c | 2 +- src/nspawn/nspawn.c | 2 +- src/oom/oomctl.c | 4 ++-- src/oom/oomd.c | 2 +- src/path/path-tool.c | 2 +- src/pcrextend/pcrextend.c | 2 +- src/pcrlock/pcrlock.c | 4 ++-- src/portable/portablectl.c | 4 ++-- src/ptyfwd/ptyfwd-tool.c | 2 +- src/random-seed/random-seed-tool.c | 2 +- src/repart/repart.c | 2 +- src/report/report-basic-server.c | 2 +- src/report/report-cgroup-server.c | 2 +- src/report/report-files-server.c | 2 +- src/report/report-sign-plain.c | 2 +- src/report/report-sign-tsm.c | 2 +- src/report/report.c | 4 ++-- src/resolve/resolvconf-compat.c | 2 +- src/resolve/resolvectl.c | 4 ++-- src/run/run.c | 4 ++-- src/sbsign/sbsign.c | 4 ++-- src/shared/verbs.c | 5 ++--- src/shared/verbs.h | 20 ++++++++++--------- src/sleep/sleep.c | 2 +- src/socket-activate/socket-activate.c | 2 +- src/socket-proxy/socket-proxyd.c | 2 +- src/ssh-generator/ssh-issue.c | 2 +- src/stdio-bridge/stdio-bridge.c | 2 +- src/storage/storage-block.c | 2 +- src/storage/storage-fs.c | 2 +- src/storage/storagectl.c | 4 ++-- src/storagetm/storagetm.c | 2 +- src/sysctl/sysctl.c | 2 +- src/sysinstall/sysinstall.c | 2 +- src/sysupdate/sysupdate.c | 4 ++-- src/sysupdate/updatectl.c | 4 ++-- src/sysusers/sysusers.c | 2 +- src/timedate/timedatectl.c | 4 ++-- src/tmpfiles/tmpfiles.c | 2 +- src/tpm2-setup/tpm2-clear.c | 2 +- src/tpm2-setup/tpm2-setup.c | 2 +- .../tty-ask-password-agent.c | 2 +- src/udev/ata_id/ata_id.c | 2 +- src/udev/cdrom_id/cdrom_id.c | 2 +- src/udev/dmi_memory_id/dmi_memory_id.c | 2 +- src/udev/fido_id/fido_id.c | 2 +- src/udev/iocost/iocost.c | 4 ++-- src/udev/mtd_probe/mtd_probe.c | 2 +- src/udev/scsi_id/scsi_id.c | 2 +- src/udev/v4l_id/v4l_id.c | 2 +- src/update-done/update-done.c | 2 +- src/userdb/userdbctl.c | 4 ++-- src/validatefs/validatefs.c | 2 +- src/varlinkctl/varlinkctl.c | 4 ++-- src/veritysetup/veritysetup.c | 4 ++-- src/vmspawn/vmspawn.c | 2 +- src/vpick/vpick-tool.c | 2 +- 112 files changed, 161 insertions(+), 160 deletions(-) diff --git a/src/ac-power/ac-power.c b/src/ac-power/ac-power.c index e52074bcf5..916bb19759 100644 --- a/src/ac-power/ac-power.c +++ b/src/ac-power/ac-power.c @@ -32,7 +32,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-ac-power"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 38c17606d7..d48413b795 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -203,7 +203,7 @@ COMMAND( .pager_flags = &arg_pager_flags, ); -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-analyze"); +VERB_COMMON_HELP_AUTO_HIDDEN(); /* When updating this list, including descriptions, apply changes to * shell-completion/bash/systemd-analyze and shell-completion/zsh/_systemd-analyze too. */ @@ -336,7 +336,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return command_print_help("systemd-analyze"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c index 725e72ba44..6b04e6e902 100644 --- a/src/ask-password/ask-password.c +++ b/src/ask-password/ask-password.c @@ -55,7 +55,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-ask-password"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index 42b7936abe..dbfd2a3038 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -625,7 +625,7 @@ static int verb_save(int argc, char *argv[], uintptr_t _data, void *userdata) { return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-backlight"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -638,7 +638,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-backlight"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/battery-check/battery-check.c b/src/battery-check/battery-check.c index 1ad4bbf584..589cfab1fe 100644 --- a/src/battery-check/battery-check.c +++ b/src/battery-check/battery-check.c @@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-battery-check"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 1566bd025f..900d583f47 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -126,7 +126,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-binfmt"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/bless-boot/bless-boot.c b/src/bless-boot/bless-boot.c index 3457655b51..8e6abdfc91 100644 --- a/src/bless-boot/bless-boot.c +++ b/src/bless-boot/bless-boot.c @@ -39,7 +39,7 @@ typedef enum Status { STATUS_INDETERMINATE, } Status; -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-bless-boot"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int check_support(void) { if (detect_container() > 0) @@ -65,7 +65,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-bless-boot"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/bless-boot/boot-check-no-failures.c b/src/bless-boot/boot-check-no-failures.c index a54bd62096..ad7d02e5f6 100644 --- a/src/bless-boot/boot-check-no-failures.c +++ b/src/bless-boot/boot-check-no-failures.c @@ -25,7 +25,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-boot-check-no-failures"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/bootctl/bootctl.c b/src/bootctl/bootctl.c index e397b2aab1..d3cd61d4cb 100644 --- a/src/bootctl/bootctl.c +++ b/src/bootctl/bootctl.c @@ -295,7 +295,7 @@ GracefulMode arg_graceful(void) { return _arg_graceful; } -VERB_COMMON_HELP_AUTO_HIDDEN("bootctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); VERB_GROUP("Generic EFI Firmware/Boot Loader Commands"); @@ -413,7 +413,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_GROUP("Options"): {} OPTION_COMMON_HELP: - return command_print_help("bootctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index a369edb399..ccffaec8e2 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -2081,7 +2081,7 @@ static int verb_set_property(int argc, char *argv[], uintptr_t _data, void *user return 0; } -VERB_COMMON_HELP_AUTO("busctl"); +VERB_COMMON_HELP_AUTO(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -2095,7 +2095,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("busctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index ec452789bb..f41953be01 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -56,7 +56,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-cgls"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index f77b26d65b..9ab6c7bf7b 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -703,7 +703,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-cgtop"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/clonesetup/clonesetup.c b/src/clonesetup/clonesetup.c index 569aa4f245..85ca03f97c 100644 --- a/src/clonesetup/clonesetup.c +++ b/src/clonesetup/clonesetup.c @@ -150,7 +150,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-clonesetup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index c0f4b9cd03..350479e8df 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -183,7 +183,7 @@ static int acquire_journal(sd_journal **ret, char **matches) { return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("coredumpctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -198,7 +198,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("coredumpctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/creds/creds.c b/src/creds/creds.c index c0908d89ec..50d8ec8a30 100644 --- a/src/creds/creds.c +++ b/src/creds/creds.c @@ -779,7 +779,7 @@ static int verb_has_tpm2(int argc, char *argv[], uintptr_t _data, void *userdata return verb_has_tpm2_generic(arg_quiet); } -VERB_COMMON_HELP_AUTO("systemd-creds"); +VERB_COMMON_HELP_AUTO(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -792,7 +792,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-creds"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 1d087a9b74..b64c6d5da3 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -365,7 +365,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-cryptenroll"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 598bfd5b31..5c711010be 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -2379,7 +2379,7 @@ static int attach_luks_or_plain_or_bitlk( return attach_luks_or_plain_or_bitlk_by_passphrase(cd, name, passwords, flags, pass_volume_key); } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-cryptsetup"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -2392,7 +2392,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-cryptsetup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/delta/delta.c b/src/delta/delta.c index 2a5143e0bb..ed4fee237d 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -513,7 +513,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-delta"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c index 56be6d8477..36fc4f63b0 100644 --- a/src/detect-virt/detect-virt.c +++ b/src/detect-virt/detect-virt.c @@ -36,7 +36,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-detect-virt"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 55f36b1d86..2d117c726d 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -404,7 +404,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-dissect"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/escape/escape-tool.c b/src/escape/escape-tool.c index 8446528d11..79d79d740d 100644 --- a/src/escape/escape-tool.c +++ b/src/escape/escape-tool.c @@ -44,7 +44,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-escape"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/factory-reset/factory-reset-tool.c b/src/factory-reset/factory-reset-tool.c index c055f26e40..7c86b1619c 100644 --- a/src/factory-reset/factory-reset-tool.c +++ b/src/factory-reset/factory-reset-tool.c @@ -39,7 +39,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-factory-reset"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 504fc23ebd..b7d30baf3c 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -1394,7 +1394,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-firstboot"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/growfs/growfs.c b/src/growfs/growfs.c index 15077f1bd7..9f750a9d5f 100644 --- a/src/growfs/growfs.c +++ b/src/growfs/growfs.c @@ -145,7 +145,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-growfs"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c index fa7f9bdbaa..b70c0b2255 100644 --- a/src/hibernate-resume/hibernate-resume.c +++ b/src/hibernate-resume/hibernate-resume.c @@ -42,7 +42,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-hibernate-resume"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/home/homectl.c b/src/home/homectl.c index e5c2857134..9d33af696d 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -4009,7 +4009,7 @@ static int parse_fido2_device_field(const char *arg) { return 1; } -VERB_COMMON_HELP_AUTO_HIDDEN("homectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { _cleanup_strv_free_ char **arg_languages = NULL; @@ -4038,7 +4038,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("homectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index e15d121f6a..5ede1cb1bf 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -853,7 +853,7 @@ static int verb_get_or_set_tags(int argc, char *argv[], uintptr_t _data, void *u return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("hostnamectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -866,7 +866,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("hostnamectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 5b16679452..4f1049865a 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -35,7 +35,7 @@ static int verb_update(int argc, char *argv[], uintptr_t _data, void *userdata) return hwdb_update(arg_root, arg_hwdb_bin_dir, arg_strict, false); } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-hwdb"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -48,7 +48,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-hwdb"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/id128/id128.c b/src/id128/id128.c index 54d41b24c9..39bffd3156 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -234,7 +234,7 @@ static int verb_show(int argc, char *argv[], uintptr_t _data, void *userdata) { return 0; } -VERB_COMMON_HELP_AUTO("systemd-id128"); +VERB_COMMON_HELP_AUTO(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -247,7 +247,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-id128"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/imds/imds-tool.c b/src/imds/imds-tool.c index 5791e41c6e..44315f3391 100644 --- a/src/imds/imds-tool.c +++ b/src/imds/imds-tool.c @@ -70,7 +70,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-imds"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/imds/imdsd.c b/src/imds/imdsd.c index 4324864aa5..7e510f9c50 100644 --- a/src/imds/imdsd.c +++ b/src/imds/imdsd.c @@ -2213,7 +2213,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-imdsd"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/import/export.c b/src/import/export.c index 9ad625e8b3..41d3d247e1 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -197,7 +197,7 @@ static int verb_export_raw(int argc, char *argv[], uintptr_t _data, void *userda return -r; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-export"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -210,7 +210,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-export"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/import/import-fs.c b/src/import/import-fs.c index a4ea7e6b1a..b1b9b637aa 100644 --- a/src/import/import-fs.c +++ b/src/import/import-fs.c @@ -272,7 +272,7 @@ static int verb_import_fs(int argc, char *argv[], uintptr_t _data, void *userdat return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-import-fs"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -286,7 +286,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-import-fs"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/import/import.c b/src/import/import.c index 2b4aad9b05..37eda8711f 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -275,7 +275,7 @@ static int verb_raw(int argc, char *argv[], uintptr_t _data, void *userdata) { return -r; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-import"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -289,7 +289,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-import"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/import/importctl.c b/src/import/importctl.c index ad64b8ffcb..3d15cb67e6 100644 --- a/src/import/importctl.c +++ b/src/import/importctl.c @@ -1066,7 +1066,7 @@ static int verb_list_images(int argc, char *argv[], uintptr_t _data, void *userd return 0; } -VERB_COMMON_HELP_AUTO("importctl"); +VERB_COMMON_HELP_AUTO(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -1080,7 +1080,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("importctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/import/pull.c b/src/import/pull.c index 30b87c6d88..3960a6e683 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -320,7 +320,7 @@ static int verb_oci(int argc, char *argv[], uintptr_t _data, void *userdata) { return -r; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-pull"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -335,7 +335,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-pull"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index e135bf1c9b..3023b134a8 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -1112,7 +1112,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-journal-gatewayd"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index 09f010728d..a689e9bb92 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -889,7 +889,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-journal-remote"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 2516d3fa6c..0fb4e5ac61 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -703,7 +703,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-journal-upload"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal/bsod.c b/src/journal/bsod.c index 5e63a7dd52..756f70f051 100644 --- a/src/journal/bsod.c +++ b/src/journal/bsod.c @@ -231,7 +231,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-bsod"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal/cat.c b/src/journal/cat.c index 67591d7e83..5452c4abf4 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -43,7 +43,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-cat"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e37ee113fd..58728f508c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -793,7 +793,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return command_print_help("journalctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index c442cf30e9..76c2654f94 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -42,7 +42,7 @@ COMMAND( .man_pages = "systemd-keyutil.1\0", ); -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-keyutil"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -56,7 +56,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-keyutil"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 3a172b22b0..e746fd5722 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -426,7 +426,7 @@ static int verb_list_x11_keymaps(int argc, char *argv[], uintptr_t _data, void * return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("localectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -440,7 +440,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("localectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/login/inhibit.c b/src/login/inhibit.c index 600f98c4ef..2157f1561e 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -190,7 +190,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-inhibit"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index f7e1b88e10..555034069e 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -1499,7 +1499,7 @@ static int verb_terminate_seat(int argc, char *argv[], uintptr_t _data, void *us return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("loginctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -1514,7 +1514,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("loginctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c index d932d00b0d..fbbbb5115e 100644 --- a/src/machine-id-setup/machine-id-setup-main.c +++ b/src/machine-id-setup/machine-id-setup-main.c @@ -47,7 +47,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-machine-id-setup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 8275eb6a03..93722baa1c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -2376,7 +2376,7 @@ static int chainload_importctl(char **args) { return log_error_errno(r, "Failed to invoke 'importctl': %m"); } -VERB_COMMON_HELP_AUTO_HIDDEN("machinectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -2409,7 +2409,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return command_print_help("machinectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/measure/measure-tool.c b/src/measure/measure-tool.c index 02bba3866c..b6ec21df35 100644 --- a/src/measure/measure-tool.c +++ b/src/measure/measure-tool.c @@ -72,7 +72,7 @@ COMMAND( .pager_flags = &arg_pager_flags, ); -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-measure"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static char *normalize_phase(const char *s) { _cleanup_strv_free_ char **l = NULL; @@ -101,7 +101,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-measure"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 9ae6531472..3997447463 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -350,7 +350,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-modules-load"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/mstack/mstack-tool.c b/src/mstack/mstack-tool.c index ea2aa404c3..2b3b5496b9 100644 --- a/src/mstack/mstack-tool.c +++ b/src/mstack/mstack-tool.c @@ -70,7 +70,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-mstack"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/mute-console/mute-console.c b/src/mute-console/mute-console.c index 0a5ef85ec2..a3bf83fef7 100644 --- a/src/mute-console/mute-console.c +++ b/src/mute-console/mute-console.c @@ -44,7 +44,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-mute-console"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/network/generator/network-generator-main.c b/src/network/generator/network-generator-main.c index fb5c54bd13..c667200aa4 100644 --- a/src/network/generator/network-generator-main.c +++ b/src/network/generator/network-generator-main.c @@ -169,7 +169,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-network-generator"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/network/networkctl.c b/src/network/networkctl.c index e307d78c9c..d6b0f3bad4 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -80,7 +80,7 @@ VERB_SCOPE(, verb_unmask, "unmask", "FILES...", VERB_SCOPE(, verb_persistent_storage, "persistent-storage", "BOOL", 2, 2, 0, "Notify systemd-networkd if persistent storage is ready"); -VERB_COMMON_HELP_AUTO_HIDDEN("networkctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -95,7 +95,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("networkctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/network/wait-online/wait-online.c b/src/network/wait-online/wait-online.c index 7f6b315bf2..a531213665 100644 --- a/src/network/wait-online/wait-online.c +++ b/src/network/wait-online/wait-online.c @@ -92,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-networkd-wait-online"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/notify/notify.c b/src/notify/notify.c index 46acaec6f1..7f6e45636a 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -146,7 +146,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-notify"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 82b366eb43..76560392f2 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -559,7 +559,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-nspawn"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/oom/oomctl.c b/src/oom/oomctl.c index 7238a0554b..e8eb5900a3 100644 --- a/src/oom/oomctl.c +++ b/src/oom/oomctl.c @@ -21,7 +21,7 @@ COMMAND( .pager_flags = &arg_pager_flags, ); -VERB_COMMON_HELP_AUTO_HIDDEN("oomctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); VERB_DEFAULT_NOARG(verb_dump_state, "dump", "Output the current state of systemd-oomd"); static int verb_dump_state(int argc, char *argv[], uintptr_t _data, void *userdata) { @@ -54,7 +54,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("oomctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/oom/oomd.c b/src/oom/oomd.c index 4bf29e7af6..df53879582 100644 --- a/src/oom/oomd.c +++ b/src/oom/oomd.c @@ -37,7 +37,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-oomd"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/path/path-tool.c b/src/path/path-tool.c index 1ca79b6238..7840a7e36d 100644 --- a/src/path/path-tool.c +++ b/src/path/path-tool.c @@ -192,7 +192,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-path"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c index 0ec2943042..2356936753 100644 --- a/src/pcrextend/pcrextend.c +++ b/src/pcrextend/pcrextend.c @@ -68,7 +68,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-pcrextend"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index f0c92ba197..5bb1db429c 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -5325,7 +5325,7 @@ static int verb_lock_raw(int argc, char *argv[], uintptr_t _data, void *userdata VERB_NOARG(verb_unlock_simple, "unlock-raw", "Remove .pcrlock file for raw data"); -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-pcrlock"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -5340,7 +5340,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-pcrlock"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c index dd4c435691..18e23a137e 100644 --- a/src/portable/portablectl.c +++ b/src/portable/portablectl.c @@ -1537,7 +1537,7 @@ static int dump_profiles(void) { return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("portablectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -1551,7 +1551,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("portablectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/ptyfwd/ptyfwd-tool.c b/src/ptyfwd/ptyfwd-tool.c index 243d84e92d..ff94ba0448 100644 --- a/src/ptyfwd/ptyfwd-tool.c +++ b/src/ptyfwd/ptyfwd-tool.c @@ -46,7 +46,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-pty-forward"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/random-seed/random-seed-tool.c b/src/random-seed/random-seed-tool.c index dd8281f041..b15c1e882e 100644 --- a/src/random-seed/random-seed-tool.c +++ b/src/random-seed/random-seed-tool.c @@ -322,7 +322,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-random-seed"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/repart/repart.c b/src/repart/repart.c index cb48e457dd..821c8393e7 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -10189,7 +10189,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_GROUP("Options"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-repart"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report-basic-server.c b/src/report/report-basic-server.c index 4db1552a55..32dca32ba9 100644 --- a/src/report/report-basic-server.c +++ b/src/report/report-basic-server.c @@ -53,7 +53,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report-basic"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report-cgroup-server.c b/src/report/report-cgroup-server.c index c6a851ce6a..47c289e3fc 100644 --- a/src/report/report-cgroup-server.c +++ b/src/report/report-cgroup-server.c @@ -54,7 +54,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report-cgroup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report-files-server.c b/src/report/report-files-server.c index 70604d5214..423c8dd3f5 100644 --- a/src/report/report-files-server.c +++ b/src/report/report-files-server.c @@ -54,7 +54,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report-files"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report-sign-plain.c b/src/report/report-sign-plain.c index 1f7c760f8c..7923ce523f 100644 --- a/src/report/report-sign-plain.c +++ b/src/report/report-sign-plain.c @@ -354,7 +354,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report-sign-plain"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report-sign-tsm.c b/src/report/report-sign-tsm.c index 2e9f2b2f40..d276a1e031 100644 --- a/src/report/report-sign-tsm.c +++ b/src/report/report-sign-tsm.c @@ -117,7 +117,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report-sign-tsm"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/report/report.c b/src/report/report.c index 86bf9c77d7..df79ac6e38 100644 --- a/src/report/report.c +++ b/src/report/report.c @@ -924,7 +924,7 @@ static int vl_server(void) { return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-report"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -937,7 +937,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-report"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c index b85fc9ada7..cacd92c664 100644 --- a/src/resolve/resolvconf-compat.c +++ b/src/resolve/resolvconf-compat.c @@ -181,7 +181,7 @@ int resolvconf_parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("resolvconf"): {} OPTION_COMMON_HELP: - return command_print_help("resolvconf"); + return command_print_help_full("resolvconf"); OPTION_COMMON_VERSION: return version(); diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 58ff70c9a3..48b4e19a60 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -3229,7 +3229,7 @@ static void help_dns_classes(void) { DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX); } -VERB_COMMON_HELP_AUTO_HIDDEN("resolvectl"); +VERB_COMMON_HELP_AUTO_PROGRAM_HIDDEN("resolvectl"); COMMAND( "systemd-resolve\0", @@ -3498,7 +3498,7 @@ static int native_parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_NAMESPACE("resolvectl"): {} OPTION_COMMON_HELP: - return command_print_help("resolvectl"); + return command_print_help_full("resolvectl"); OPTION_COMMON_VERSION: return version(); diff --git a/src/run/run.c b/src/run/run.c index 63994775a8..9b14048d56 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -208,7 +208,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("systemd-run"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-run"); + return command_print_help_full("systemd-run"); OPTION_COMMON_VERSION: return version(); @@ -784,7 +784,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { OPTION_NAMESPACE("run0"): {} OPTION_COMMON_HELP: - return command_print_help("run0"); + return command_print_help_full("run0"); OPTION('V', "version", NULL, "Show package version"): return version(); diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index dd50afb63f..5a0bf94daa 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -52,7 +52,7 @@ COMMAND( .man_pages = "systemd-sbsign.1\0", ); -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-sbsign"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-sbsign"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/shared/verbs.c b/src/shared/verbs.c index 0508272544..f84612ceb3 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -229,14 +229,13 @@ static const Verb* verbs_get_command(const Verb verbs[], const Verb verbs_end[], assert(verbs_end > verbs); assert((uintptr_t) verbs % sizeof(void*) == 0); assert(FLAGS_SET(verbs[0].flags, VERB_COMMAND_MARKER) || verbs[0].verb); - assert(name); for (const Verb *verb = verbs; verb < verbs_end; verb++) { if (!FLAGS_SET(verb->flags, VERB_COMMAND_MARKER)) continue; const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(verb->data); - if (nulstr_contains(cmd->names, name)) + if (!name || nulstr_contains(cmd->names, name)) return verb; } @@ -469,7 +468,7 @@ static int print_wrapped(const char *text, bool abstract) { return 0; } -int _command_print_help( +int _command_print_help_full( const Verb verbs[], const Verb verbs_end[], const Option options[], diff --git a/src/shared/verbs.h b/src/shared/verbs.h index cbe5b4e9cb..5a5e31e23b 100644 --- a/src/shared/verbs.h +++ b/src/shared/verbs.h @@ -131,26 +131,28 @@ int _verbs_get_help_table( VERB(verb_help, "help", NULL, VERB_ANY, VERB_ANY, 0, NULL); \ _VERB_COMMON_HELP_IMPL(impl) -#define VERB_COMMON_HELP_AUTO(program) \ - VERB_FULL(verb_help_auto, "help", NULL, VERB_ANY, VERB_ANY, 0, (uintptr_t) program, "Show this help") +#define VERB_COMMON_HELP_AUTO_FULL(program, help) \ + VERB_FULL(verb_help_auto, "help", NULL, VERB_ANY, VERB_ANY, 0, /* dat= */ (uintptr_t) program, /* help= */ help) +#define VERB_COMMON_HELP_AUTO_PROGRAM(program) VERB_COMMON_HELP_AUTO_FULL(program, "Show this help") +#define VERB_COMMON_HELP_AUTO_PROGRAM_HIDDEN(program) VERB_COMMON_HELP_AUTO_FULL(program, /* help= */ NULL) +#define VERB_COMMON_HELP_AUTO() VERB_COMMON_HELP_AUTO_PROGRAM(/* program= */ NULL) +#define VERB_COMMON_HELP_AUTO_HIDDEN() VERB_COMMON_HELP_AUTO_PROGRAM_HIDDEN(/* program= */ NULL) -#define VERB_COMMON_HELP_AUTO_HIDDEN(program) \ - VERB_FULL(verb_help_auto, "help", NULL, VERB_ANY, VERB_ANY, 0, (uintptr_t) program, NULL) - -int _command_print_help( +int _command_print_help_full( const Verb verbs[], const Verb verbs_end[], const Option options[], const Option options_end[], const char *name); -#define command_print_help(name) \ - _command_print_help( \ +#define command_print_help_full(name) \ + _command_print_help_full( \ __start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, \ __start_SYSTEMD_OPTIONS, __stop_SYSTEMD_OPTIONS, \ name) +#define command_print_help() command_print_help_full(/* name= */ NULL) static inline int verb_help_auto(int argc, char **argv, uintptr_t data, void *userdata) { - return command_print_help((const char*) ASSERT_PTR(data)); + return command_print_help_full((const char*) data); } /* Print a machine-readable description of the program's commands, verbs, and options in the format diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index d56d1ffc26..cc169c2383 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -699,7 +699,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-sleep"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/socket-activate/socket-activate.c b/src/socket-activate/socket-activate.c index 8b4ea230b5..c363954528 100644 --- a/src/socket-activate/socket-activate.c +++ b/src/socket-activate/socket-activate.c @@ -339,7 +339,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-socket-activate"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index aa101e9f65..58c282be0c 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -506,7 +506,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-socket-proxyd"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/ssh-generator/ssh-issue.c b/src/ssh-generator/ssh-issue.c index 1d87624aae..9039047346 100644 --- a/src/ssh-generator/ssh-issue.c +++ b/src/ssh-generator/ssh-issue.c @@ -130,7 +130,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-ssh-issue"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 25e6f49a35..903b11b094 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -40,7 +40,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-stdio-bridge"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/storage/storage-block.c b/src/storage/storage-block.c index 363fad66da..bf620fa13d 100644 --- a/src/storage/storage-block.c +++ b/src/storage/storage-block.c @@ -395,7 +395,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-storage-block"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/storage/storage-fs.c b/src/storage/storage-fs.c index ef0cc7b66c..b77222f766 100644 --- a/src/storage/storage-fs.c +++ b/src/storage/storage-fs.c @@ -755,7 +755,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-storage-fs"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/storage/storagectl.c b/src/storage/storagectl.c index 51292fc66a..cca94a63ba 100644 --- a/src/storage/storagectl.c +++ b/src/storage/storagectl.c @@ -53,7 +53,7 @@ COMMAND( .pager_flags = &arg_pager_flags, ); -VERB_COMMON_HELP_AUTO_HIDDEN("storagectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static const char *ro_color(int ro) { if (ro > 0) @@ -391,7 +391,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_NAMESPACE("storagectl"): {} OPTION_COMMON_HELP: - return command_print_help("storagectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/storagetm/storagetm.c b/src/storagetm/storagetm.c index 91a4763307..9c2038b52c 100644 --- a/src/storagetm/storagetm.c +++ b/src/storagetm/storagetm.c @@ -67,7 +67,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-storagetm"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index fa95932985..f18ced3418 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -338,7 +338,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-sysctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/sysinstall/sysinstall.c b/src/sysinstall/sysinstall.c index d981be03d0..9ed3419ced 100644 --- a/src/sysinstall/sysinstall.c +++ b/src/sysinstall/sysinstall.c @@ -174,7 +174,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-sysinstall"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c index 49a0f1b37a..0792d91eb1 100644 --- a/src/sysupdate/sysupdate.c +++ b/src/sysupdate/sysupdate.c @@ -3306,7 +3306,7 @@ static int verb_enable_component(int argc, char *argv[], uintptr_t _data, void * return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-sysupdate"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -3320,7 +3320,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-sysupdate"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/sysupdate/updatectl.c b/src/sysupdate/updatectl.c index 70902697cf..8fc2f55111 100644 --- a/src/sysupdate/updatectl.c +++ b/src/sysupdate/updatectl.c @@ -1641,7 +1641,7 @@ static int verb_enable(int argc, char *argv[], uintptr_t _data, void *userdata) return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("updatectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -1653,7 +1653,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("updatectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 489a2697e9..b1e1fd7e7d 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -2124,7 +2124,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return command_print_help("systemd-sysusers"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 9926748cbc..f5fe36c9ef 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -899,7 +899,7 @@ static int verb_revert(int argc, char *argv[], uintptr_t _data, void *userdata) return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("timedatectl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -912,7 +912,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("timedatectl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index e567bd63f2..8dc09c47e0 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -4963,7 +4963,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return command_print_help("systemd-tmpfiles"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/tpm2-setup/tpm2-clear.c b/src/tpm2-setup/tpm2-clear.c index de0959572b..917a74531a 100644 --- a/src/tpm2-setup/tpm2-clear.c +++ b/src/tpm2-setup/tpm2-clear.c @@ -31,7 +31,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-tpm2-clear"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/tpm2-setup/tpm2-setup.c b/src/tpm2-setup/tpm2-setup.c index 9435147778..9309613037 100644 --- a/src/tpm2-setup/tpm2-setup.c +++ b/src/tpm2-setup/tpm2-setup.c @@ -64,7 +64,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-tpm2-setup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 343fffaef1..34ddd5a07c 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -459,7 +459,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-tty-ask-password-agent"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c index 78c403c08b..a88f4cdcbb 100644 --- a/src/udev/ata_id/ata_id.c +++ b/src/udev/ata_id/ata_id.c @@ -375,7 +375,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("ata_id"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c index 22a723d119..c030be28db 100644 --- a/src/udev/cdrom_id/cdrom_id.c +++ b/src/udev/cdrom_id/cdrom_id.c @@ -916,7 +916,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("cdrom_id"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c b/src/udev/dmi_memory_id/dmi_memory_id.c index b39981dbf9..3a7b22941e 100644 --- a/src/udev/dmi_memory_id/dmi_memory_id.c +++ b/src/udev/dmi_memory_id/dmi_memory_id.c @@ -659,7 +659,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("dmi_memory_id"); + return command_print_help(); OPTION_COMMON_VERSION_WITH_HIDDEN_V: return version(); diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c index 96bdcbd6c1..774c398f73 100644 --- a/src/udev/fido_id/fido_id.c +++ b/src/udev/fido_id/fido_id.c @@ -44,7 +44,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("fido_id"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/iocost/iocost.c b/src/udev/iocost/iocost.c index 9da7e1e9a8..376e5d8209 100644 --- a/src/udev/iocost/iocost.c +++ b/src/udev/iocost/iocost.c @@ -55,7 +55,7 @@ static int parse_config(void) { return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("iocost"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -68,7 +68,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("iocost"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/mtd_probe/mtd_probe.c b/src/udev/mtd_probe/mtd_probe.c index cc14475743..e929fa501f 100644 --- a/src/udev/mtd_probe/mtd_probe.c +++ b/src/udev/mtd_probe/mtd_probe.c @@ -51,7 +51,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("mtd_probe"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c index bee527962b..7f1267d09d 100644 --- a/src/udev/scsi_id/scsi_id.c +++ b/src/udev/scsi_id/scsi_id.c @@ -223,7 +223,7 @@ static int set_options(int argc, char **argv, char *maj_min_dev) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("scsi_id"); + return command_print_help(); OPTION_COMMON_VERSION_WITH_HIDDEN_V: return version(); diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c index 45a1f52bd2..6843a50b75 100644 --- a/src/udev/v4l_id/v4l_id.c +++ b/src/udev/v4l_id/v4l_id.c @@ -38,7 +38,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("v4l_id"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index c3545e1b57..44718b4414 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -79,7 +79,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-update-done"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index cf185d924f..81048c7352 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -1558,7 +1558,7 @@ static int verb_load_credentials(int argc, char *argv[], uintptr_t _data, void * return r; } -VERB_COMMON_HELP_AUTO_HIDDEN("userdbctl"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_from_file(const char *arg, sd_json_variant **ret) { sd_json_variant *v = NULL; @@ -1612,7 +1612,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("userdbctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/validatefs/validatefs.c b/src/validatefs/validatefs.c index 179274b43d..616ebd5d90 100644 --- a/src/validatefs/validatefs.c +++ b/src/validatefs/validatefs.c @@ -49,7 +49,7 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-validatefs"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/varlinkctl/varlinkctl.c b/src/varlinkctl/varlinkctl.c index 2a1c9a1ce2..e1e86da289 100644 --- a/src/varlinkctl/varlinkctl.c +++ b/src/varlinkctl/varlinkctl.c @@ -92,7 +92,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("varlinkctl"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); @@ -1458,7 +1458,7 @@ static int verb_serve(int argc, char *argv[], uintptr_t _data, void *userdata) { return 0; } -VERB_COMMON_HELP_AUTO("varlinkctl"); +VERB_COMMON_HELP_AUTO(); static int run(int argc, char *argv[]) { int r; diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c index afce00bbe7..d1aefb7aa6 100644 --- a/src/veritysetup/veritysetup.c +++ b/src/veritysetup/veritysetup.c @@ -471,7 +471,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata) return 0; } -VERB_COMMON_HELP_AUTO_HIDDEN("systemd-veritysetup"); +VERB_COMMON_HELP_AUTO_HIDDEN(); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -484,7 +484,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-veritysetup"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index b274fe69b5..a6bfdf7889 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -311,7 +311,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return command_print_help("systemd-vmspawn"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); diff --git a/src/vpick/vpick-tool.c b/src/vpick/vpick-tool.c index fb1c4d0329..2a0dd1a575 100644 --- a/src/vpick/vpick-tool.c +++ b/src/vpick/vpick-tool.c @@ -143,7 +143,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_GROUP("Output"): {} OPTION_COMMON_HELP: - return command_print_help("systemd-vpick"); + return command_print_help(); OPTION_COMMON_VERSION: return version(); From 16d0cbf04b52c49f6a637344d3dcfa80469906af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:48:16 +0200 Subject: [PATCH 2/9] systemctl: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. The generic help-verb check in the test is filtered out, since systemctl's "help" verb shows unit manuals and fails without arguments. --- src/systemctl/systemctl.c | 69 ++++--------------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 4 ++ 2 files changed, 17 insertions(+), 56 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index ef90e62a00..9d70999545 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3,17 +3,16 @@ #include #include +#include "sd-json.h" + #include "argv-util.h" #include "build.h" #include "bus-print-properties.h" #include "bus-util.h" #include "capsule-util.h" #include "extract-word.h" -#include "format-table.h" -#include "help-util.h" #include "image-policy.h" #include "install.h" -#include "options.h" #include "output-mode.h" #include "pager.h" #include "parse-argument.h" @@ -112,58 +111,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_kill_subgroup, freep); -static int systemctl_help(void) { - static const char *const vgroups[] = { - "Unit Commands", - "Unit File Commands", - "Machine Commands", - "Job Commands", - "Environment Commands", - "Manager State Commands", - "System Commands", - }; - - Table *vtables[ELEMENTSOF(vgroups)] = {}; - CLEANUP_ELEMENTS(vtables, table_unref_array_clear); - _cleanup_(table_unrefp) Table *options_table = NULL; - int r; - - for (size_t i = 0; i < ELEMENTSOF(vgroups); i++) { - r = verbs_get_help_table_group(vgroups[i], &vtables[i]); - if (r < 0) - return r; - } - - r = option_parser_get_help_table_ns("systemctl", &options_table); - if (r < 0) - return r; - - assert_cc(ELEMENTSOF(vtables) == 7); - (void) table_sync_column_widths(0, options_table, - vtables[0], vtables[1], vtables[2], vtables[3], - vtables[4], vtables[5], vtables[6]); - - pager_open(arg_pager_flags); - - help_cmdline("[OPTIONS…] COMMAND …"); - help_abstract("Query or send control commands to the system manager."); - - for (size_t i = 0; i < ELEMENTSOF(vgroups); i++) { - help_section(vgroups[i]); - r = table_print_or_warn(vtables[i]); - if (r < 0) - return r; - } - - help_section("Options"); - r = table_print_or_warn(options_table); - if (r < 0) - return r; - - help_man_page_reference("systemctl", "1"); - - return 0; -} +COMMAND( + "systemctl\0", + "Query or send control commands to the system manager.", + .man_pages = "systemctl.1\0", + .option_namespace = "systemctl", + .pager_flags = &arg_pager_flags, +); static int parse_property_argument(const char *value, char ***properties) { int r; @@ -397,7 +351,7 @@ static int systemctl_parse_argv(int argc, char *argv[], int log_level_shift, cha OPTION_NAMESPACE("systemctl"): {} OPTION_COMMON_HELP: - return systemctl_help(); + return command_print_help_full("systemctl"); OPTION_COMMON_VERSION: return version(); @@ -880,6 +834,9 @@ static int systemctl_parse_argv(int argc, char *argv[], int log_level_shift, cha " %s [OPTIONS…] COMMAND -- -.%s …", program_invocation_name, opts.arg ?: "mount"); return -EINVAL; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } /* If we are in --user mode, there's no point in talking to PolicyKit or the infra to query system diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 4a7d61cae3..284182fcfe 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -34,6 +34,7 @@ INTROSPECTABLE=( run0 scsi_id storagectl + systemctl systemd-ac-power systemd-analyze systemd-ask-password @@ -138,6 +139,9 @@ for i in "${INTROSPECTABLE[@]}"; do # 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 + # 'systemctl help' shows unit manuals + [[ "$i" == systemctl ]] && continue + $i help >/dev/null fi done From 4cf46d47a2d1902c34cd26d2d8981bbea8712223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 20 Aug 2026 00:14:29 +0200 Subject: [PATCH 3/9] shared/verbs: allow commands to specify footer highlighting In practice I think this will ever only be used with ansi_highlight_red(), but it's cleaner to add this generic extension rather than e.g. a boolean highlight_footer_red. The options is passed through via command_print_help_full(), not through the COMMAND structure, which means that commands with 'help' verb are not covered by this. The red footer highligting is used for legacy commands, which don't have verbs, so I think this is OK. Making it generic and covering 'help' verbs would require more refactoring, and I think it doesn't make sense to add it until it's actually needed. --- src/resolve/resolvconf-compat.c | 2 +- src/resolve/resolvectl.c | 2 +- src/run/run.c | 4 ++-- src/shared/verbs.c | 17 +++++++++-------- src/shared/verbs.h | 11 ++++++----- src/systemctl/systemctl.c | 2 +- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c index cacd92c664..8a07124573 100644 --- a/src/resolve/resolvconf-compat.c +++ b/src/resolve/resolvconf-compat.c @@ -181,7 +181,7 @@ int resolvconf_parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("resolvconf"): {} OPTION_COMMON_HELP: - return command_print_help_full("resolvconf"); + return command_print_help_full("resolvconf", /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 48b4e19a60..f2d5946ae6 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -3498,7 +3498,7 @@ static int native_parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_NAMESPACE("resolvectl"): {} OPTION_COMMON_HELP: - return command_print_help_full("resolvectl"); + return command_print_help_full("resolvectl", /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); diff --git a/src/run/run.c b/src/run/run.c index 9b14048d56..6aa58f8b5c 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -208,7 +208,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("systemd-run"): {} OPTION_COMMON_HELP: - return command_print_help_full("systemd-run"); + return command_print_help_full("systemd-run", /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); @@ -784,7 +784,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { OPTION_NAMESPACE("run0"): {} OPTION_COMMON_HELP: - return command_print_help_full("run0"); + return command_print_help_full("run0", /* footer_ansi_seq= */ NULL); OPTION('V', "version", NULL, "Show package version"): return version(); diff --git a/src/shared/verbs.c b/src/shared/verbs.c index f84612ceb3..f4985fc775 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -430,7 +430,7 @@ static bool verbs_array_has_verbs(const Verb verbs[], const Verb verbs_end[]) { return false; } -static int print_wrapped(const char *text, bool abstract) { +static int print_wrapped(const char *text, const char *ansi_seq) { /* Print the text wrapped at spaces to the specified width. Newlines embedded in the text * are preserved and each line is wrapped independently, so explicit line breaks (e.g. @@ -456,10 +456,9 @@ static int print_wrapped(const char *text, bool abstract) { putchar('\n'); STRV_FOREACH(line, lines2) - if (abstract) - printf("%s%s%s%s\n", - ansi_highlight(), - ansi_add_italics(), + if (ansi_seq) + printf("%s%s%s\n", + ansi_seq, *line, ansi_normal()); else @@ -473,7 +472,8 @@ int _command_print_help_full( const Verb verbs_end[], const Option options[], const Option options_end[], - const char *name) { + const char *name, + const char *footer_ansi_seq) { int r; const Verb *cmdverb = verbs_get_command(verbs, verbs_end, name); @@ -498,7 +498,8 @@ int _command_print_help_full( help_cmdline(have_verbs ? "[OPTION…] COMMAND …" : "[OPTION…]"); } - r = print_wrapped(cmd->abstract, /* abstract= */ true); + const char *seq = strjoina(ansi_highlight(), ansi_add_italics()); + r = print_wrapped(cmd->abstract, seq); if (r < 0) return r; @@ -506,7 +507,7 @@ int _command_print_help_full( if (r < 0) return log_error_errno(r, "Failed to print verb&option help: %m"); - r = print_wrapped(cmd->footer, /* abstract= */ false); + r = print_wrapped(cmd->footer, footer_ansi_seq); if (r < 0) return r; diff --git a/src/shared/verbs.h b/src/shared/verbs.h index 5a5e31e23b..8c9e7baaf2 100644 --- a/src/shared/verbs.h +++ b/src/shared/verbs.h @@ -143,16 +143,17 @@ int _command_print_help_full( const Verb verbs_end[], const Option options[], const Option options_end[], - const char *name); -#define command_print_help_full(name) \ + const char *name, + const char *footer_ansi_seq); +#define command_print_help_full(name, footer_ansi_seq) \ _command_print_help_full( \ __start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, \ __start_SYSTEMD_OPTIONS, __stop_SYSTEMD_OPTIONS, \ - name) -#define command_print_help() command_print_help_full(/* name= */ NULL) + name, footer_ansi_seq) +#define command_print_help() command_print_help_full(/* name= */ NULL, /* footer_ansi_seq= */ NULL) static inline int verb_help_auto(int argc, char **argv, uintptr_t data, void *userdata) { - return command_print_help_full((const char*) data); + return command_print_help_full((const char*) data, /* footer_ansi_seq= */ NULL); } /* Print a machine-readable description of the program's commands, verbs, and options in the format diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9d70999545..659de527d3 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -351,7 +351,7 @@ static int systemctl_parse_argv(int argc, char *argv[], int log_level_shift, cha OPTION_NAMESPACE("systemctl"): {} OPTION_COMMON_HELP: - return command_print_help_full("systemctl"); + return command_print_help_full("systemctl", /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); From 2364f0d7c80cf3d9f2b1237d80b2b3cb7d2cdfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:49:23 +0200 Subject: [PATCH 4/9] 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. --- src/systemctl/systemctl-compat-halt.c | 73 ++++++++++--------- src/systemctl/systemctl-compat-shutdown.c | 55 ++++++-------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 11 ++- 3 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/systemctl/systemctl-compat-halt.c b/src/systemctl/systemctl-compat-halt.c index 217487b643..8893cd514f 100644 --- a/src/systemctl/systemctl-compat-halt.c +++ b/src/systemctl/systemctl-compat-halt.c @@ -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); diff --git a/src/systemctl/systemctl-compat-shutdown.c b/src/systemctl/systemctl-compat-shutdown.c index d93fa91ca0..9e5ccdb885 100644 --- a/src/systemctl/systemctl-compat-shutdown.c +++ b/src/systemctl/systemctl-compat-shutdown.c @@ -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); diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 284182fcfe..2bae9e03b5 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -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"]' From 2b4c6dda9d6115cb9c5fb784e9c64a1a8d0a96b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:50:03 +0200 Subject: [PATCH 5/9] kernel-install: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. The note about invocation as 'installkernel' is kept as the footer. Verb and option column widths are kept separate, since the verb table is very wide. --help now goes through the pager, like other commands with --no-pager. A separate COMMAND block is included for installkernel, but it is only used for introspection data. --- src/kernel-install/kernel-install.c | 70 ++++++++----------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 6 ++ 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index f9cc40fd7d..d35ff931b2 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -4,6 +4,8 @@ #include #include +#include "sd-json.h" + #include "ansi-color.h" #include "argv-util.h" #include "boot-entry.h" @@ -22,7 +24,6 @@ #include "find-esp.h" #include "format-table.h" #include "fs-util.h" -#include "help-util.h" #include "id128-util.h" #include "image-policy.h" #include "kernel-config.h" @@ -30,7 +31,6 @@ #include "loop-util.h" #include "main-func.h" #include "mount-util.h" -#include "options.h" #include "parse-argument.h" #include "path-util.h" #include "recurse-dir.h" @@ -64,6 +64,17 @@ STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep); +COMMAND( + "kernel-install\0", + "Add and remove kernel and initrd images to and from the boot partition.", + .footer = "This program may also be invoked as 'installkernel':\n" + " installkernel [OPTION…] VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\n" + "(The optional arguments are passed by kernel build system, but ignored.)", + .man_pages = "kernel-install.8\0", + .pager_flags = &arg_pager_flags, + .flags = COMMAND_HELP_SEPARATE, /* the verb table is very wide */ +); + typedef enum Action { ACTION_ADD, ACTION_REMOVE, @@ -1599,44 +1610,7 @@ static int verb_list(int argc, char *argv[], uintptr_t _data, void *userdata) { return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend); } -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL; - int r; - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - /* Note: column widths are not synced, because the verbs table is very wide. */ - - help_cmdline("[OPTIONS…] COMMAND …"); - help_abstract("Add and remove kernel and initrd images to and from the boot partition."); - - help_section("Commands"); - r = table_print_or_warn(verbs); - if (r < 0) - return r; - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - printf("\n" - "This program may also be invoked as 'installkernel':\n" - " installkernel [OPTIONS...] VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\n" - "(The optional arguments are passed by kernel build system, but ignored.)\n"); - - help_man_page_reference("kernel-install", "8"); - - return 0; -} - -VERB_COMMON_HELP(help); +VERB_COMMON_HELP_AUTO_PROGRAM("kernel-install"); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -1650,7 +1624,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help_full("kernel-install", /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); @@ -1735,6 +1709,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { if (r < 0) return r; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } if (arg_image && arg_root) @@ -1745,6 +1722,17 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { return 1; } +/* Definition for the compat interface to populate introspection data. + * Keep below the VERB definitions for the main command. */ +COMMAND( + "installkernel\0", + "Add and remove kernel and initrd images to and from the boot partition.", + .argspec = "VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\0", + .footer = "This is a compat interface intended only to be called from kernel Makefiles.", + .man_pages = "kernel-install.8\0", + .pager_flags = &arg_pager_flags, +); + static int run(int argc, char* argv[]) { int r; diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 2bae9e03b5..f7bdb6c2f0 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -24,6 +24,7 @@ INTROSPECTABLE=( importctl iocost journalctl + kernel-install localectl loginctl machinectl @@ -158,6 +159,11 @@ if command -v systemd-hwdb >/dev/null; then '.commands[0].verbs | map(.names[0]) | sort == ["help", "query", "update"]' fi +if command -v kernel-install >/dev/null; then + kernel-install --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["installkernel", "kernel-install"]' +fi + resolvectl --introspect-cli | jq -e \ '[.commands[].names[0]] | sort == ["resolvconf", "resolvectl", "systemd-resolve"]' From b62d32c7b557dc74108f9f7644b623c3dec143fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 20 Aug 2026 10:10:05 +0200 Subject: [PATCH 6/9] shared/verbs: add concept of "shared verbs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows commands like systemd-sysext + systemd-confext to be handled without duplicating entries in the verbs table. The basic idea is to have the following layout in the SYSTEMD_VERBS section: VERB_COMMAND_MARKER → "systemd-sysext", .flags = COMMAND_VERBS_SHARED VERB_COMMAND_MARKER → "systemd-confext", .flags = COMMAND_VERBS_SHARED VERB("status"), VERB("merge"), ... And then in places where we want to work on the verbs, we skip over the verb entries with VERB_COMMAND_MARKER and COMMAND_VERBS_SHARED flag set. --- src/shared/verbs.c | 30 +++++++++++++++++++++++++++--- src/shared/verbs.h | 5 +++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/shared/verbs.c b/src/shared/verbs.c index f4985fc775..1d568d60ac 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -467,6 +467,27 @@ static int print_wrapped(const char *text, const char *ansi_seq) { return 0; } +static const Verb* verbs_find_cmd_verbs(const Verb *cmdverb, const Verb verbs_end[]) { + assert(cmdverb); + assert(FLAGS_SET(cmdverb->flags, VERB_COMMAND_MARKER)); + assert(cmdverb < verbs_end); + + const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(cmdverb->data); + + /* With COMMAND_VERBS_SHARED, we have a group of VERB_COMMAND_MARKER entries, and + * then the shared verbs below. Thus, we need to skip over them to locate the + * first actual verb. Without COMMAND_VERBS_SHARED, the verbs start immediately + * after the VERB_COMMAND_MARKER entry. */ + const Verb *actual = cmdverb + 1; + if (FLAGS_SET(cmd->flags, COMMAND_VERBS_SHARED)) + while (actual < verbs_end && + FLAGS_SET(actual->flags, VERB_COMMAND_MARKER) && + FLAGS_SET(((const CommandDescription*) ASSERT_PTR(actual->data))->flags, + COMMAND_VERBS_SHARED)) + actual++; + return actual; +} + int _command_print_help_full( const Verb verbs[], const Verb verbs_end[], @@ -482,6 +503,7 @@ int _command_print_help_full( "Command %s not known", name); const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(cmdverb->data); + const Verb *verbverbs = verbs_find_cmd_verbs(cmdverb, verbs_end); if (cmd->pager_flags) pager_open(*cmd->pager_flags); @@ -494,7 +516,7 @@ int _command_print_help_full( help_cmdline(line); } else { - bool have_verbs = verbs_array_has_verbs(cmdverb + 1, verbs_end); + bool have_verbs = verbs_array_has_verbs(verbverbs, verbs_end); help_cmdline(have_verbs ? "[OPTION…] COMMAND …" : "[OPTION…]"); } @@ -503,7 +525,7 @@ int _command_print_help_full( if (r < 0) return r; - r = print_verb_option_help(cmd, cmdverb + 1, verbs_end, options, options_end); + r = print_verb_option_help(cmd, verbverbs, verbs_end, options, options_end); if (r < 0) return log_error_errno(r, "Failed to print verb&option help: %m"); @@ -568,9 +590,11 @@ static int command_build_json( assert(cmdverb); assert(FLAGS_SET(cmdverb->flags, VERB_COMMAND_MARKER)); + assert(cmdverb < verbs_end); assert(ret); const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(cmdverb->data); + const Verb *verbverbs = verbs_find_cmd_verbs(cmdverb, verbs_end); NULSTR_FOREACH(name, cmd->names) { r = sd_json_variant_append_arrayb(&names, SD_JSON_BUILD_STRING(name)); @@ -583,7 +607,7 @@ static int command_build_json( if (r < 0) return r; - for (const Verb *verb = cmdverb + 1; verb < verbs_end; verb++) { + for (const Verb *verb = verbverbs; verb < verbs_end; verb++) { if (FLAGS_SET(verb->flags, VERB_COMMAND_MARKER)) break; /* Start of entries for another command */ diff --git a/src/shared/verbs.h b/src/shared/verbs.h index 8c9e7baaf2..99efd2523d 100644 --- a/src/shared/verbs.h +++ b/src/shared/verbs.h @@ -8,6 +8,11 @@ typedef enum CommandFlags { COMMAND_HELP_SEPARATE = 1 << 0, /* Do not synchronize the width between verbs and options */ + COMMAND_VERBS_SHARED = 1 << 1, /* We have a group of COMMANDs with this flag set, and then + * the VERB definitions below. The commands share the same + * set of actual VERB definitions. This is useful for programs + * which are registered under multiple names, but each one + * behaves very similarly. */ } CommandFlags; typedef struct CommandDescription { From dfe557dc7cc7c225c910434cc6ad366519754687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:50:53 +0200 Subject: [PATCH 7/9] sysext: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. --help now goes through the pager, like other commands with --no-pager. Also, previously, -h/--help/--version were listed in the "Commands" section. This was cute, but recreating this in the new scheme would be complicated. Also, it seems unnecessary. --help/--version and some other commands terminate the program in all binaries, so they could be considered "commands" in all cases. But we printed them together with verbs only in a few cases. So I think it's fine to move them back to the "Options" section. This makes the description of options much more consistent between different programs. --- src/sysext/sysext.c | 75 +++++++------------ .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 12 +++ 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 7b4dee1bba..b0e668a38a 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -38,7 +38,6 @@ #include "format-table.h" #include "fs-util.h" #include "hashmap.h" -#include "help-util.h" #include "image-policy.h" #include "initrd-util.h" #include "label-util.h" /* IWYU pragma: keep */ @@ -49,7 +48,6 @@ #include "mkdir.h" #include "mount-util.h" #include "mountpoint-util.h" -#include "options.h" #include "os-util.h" #include "pager.h" #include "parse-argument.h" @@ -133,14 +131,27 @@ static ImageClass arg_image_class = IMAGE_SYSEXT; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); +COMMAND( + "systemd-sysext\0", + "Merge system extension images into /usr/ and /opt/.", + .man_pages = "systemd-sysext.8\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); +COMMAND( + "systemd-confext\0", + "Merge configuration extension images into /etc/.", + .man_pages = "systemd-confext.8\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); + /* Helper struct for naming simplicity and reusability */ static const struct { - const char *full_identifier; const char *short_identifier; const char *short_identifier_plural; const char *polkit_rw_action_id; const char *polkit_ro_action_id; - const char *blurb; const char *dot_directory_name; const char *directory_name; const char *level_env; @@ -152,12 +163,10 @@ static const struct { unsigned long default_mount_flags; } image_class_info[_IMAGE_CLASS_MAX] = { [IMAGE_SYSEXT] = { - .full_identifier = "systemd-sysext", .short_identifier = "sysext", .short_identifier_plural = "extensions", .polkit_rw_action_id = "io.systemd.sysext.manage", .polkit_ro_action_id = "io.systemd.sysext.read", - .blurb = "Merge system extension images into /usr/ and /opt/.", .dot_directory_name = ".systemd-sysext", .level_env = "SYSEXT_LEVEL", .scope_env = "SYSEXT_SCOPE", @@ -168,12 +177,10 @@ static const struct { .default_mount_flags = MS_RDONLY|MS_NODEV, }, [IMAGE_CONFEXT] = { - .full_identifier = "systemd-confext", .short_identifier = "confext", .short_identifier_plural = "confexts", .polkit_rw_action_id = "io.systemd.confext.manage", .polkit_ro_action_id = "io.systemd.confext.read", - .blurb = "Merge configuration extension images into /etc/.", .dot_directory_name = ".systemd-confext", .level_env = "CONFEXT_LEVEL", .scope_env = "CONFEXT_SCOPE", @@ -3129,46 +3136,13 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl return 0; } -static int help(void) { - _cleanup_(table_unrefp) Table *verbs = NULL, *commands = NULL, *options = NULL; - int r; - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - r = option_parser_get_help_table(&commands); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Options", &options); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, verbs, commands, options); - - help_cmdline("[OPTIONS...] COMMAND"); - help_abstract(image_class_info[arg_image_class].blurb); - - help_section("Commands"); - r = table_print_or_warn(verbs); - if (r < 0) - return r; - r = table_print_or_warn(commands); - if (r < 0) - return r; - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference(image_class_info[arg_image_class].full_identifier, "8"); - return 0; +VERB_FULL(verb_help, "help", NULL, VERB_ANY, VERB_ANY, 0, /* dat= */ 0u, /* help= */ NULL); +static int verb_help(int argc, char **argv, uintptr_t data, void *userdata) { + return command_print_help_full( + arg_image_class == IMAGE_SYSEXT ? "systemd-sysext" : "systemd-confext", + /* footer_ansi_seq= */ NULL); } -VERB_COMMON_HELP_HIDDEN(help); - static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -3182,13 +3156,13 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help_full( + arg_image_class == IMAGE_SYSEXT ? "systemd-sysext" : "systemd-confext", + /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); - OPTION_GROUP("Options"): {} - OPTION_LONG("root", "PATH", "Operate relative to root PATH"): r = parse_path_argument(opts.arg, false, &arg_root); if (r < 0) @@ -3255,6 +3229,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { if (r <= 0) return r; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT); diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index f7bdb6c2f0..47847d6e8d 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -53,6 +53,7 @@ INTROSPECTABLE=( systemd-cgls systemd-cgtop systemd-clonesetup + systemd-confext systemd-creds systemd-cryptenroll systemd-cryptsetup @@ -110,6 +111,7 @@ INTROSPECTABLE=( systemd-storage-fs systemd-storagetm systemd-sysctl + systemd-sysext systemd-sysinstall systemd-sysupdate systemd-sysusers @@ -185,5 +187,15 @@ systemd-mstack --introspect-cli | jq -e \ systemd-run --introspect-cli | jq -e \ '[.commands[].names[0]] | sort == ["run0", "systemd-run"]' +if command -v systemd-sysext >/dev/null; then + systemd-sysext --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["systemd-confext", "systemd-sysext"]' + + systemd-sysext --introspect-cli | jq -e \ + '.commands[0].verbs | map(.names[0]) | contains(["status", "merge", "unmerge"])' + systemd-confext --introspect-cli | jq -e \ + '.commands[0].verbs | map(.names[0]) | contains(["status", "merge", "unmerge"])' +fi + systemctl --introspect-cli | jq -e \ '[.commands[].names[0]] | sort == ["halt", "poweroff", "reboot", "shutdown", "systemctl"]' From 5f45122e758e27d96e53aad4911d2b05daf2fda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 24 Aug 2026 10:32:23 +0200 Subject: [PATCH 8/9] shared/verbs: allow commands to filter option groups So far, option groups were only used for display: when parsing options, the group markers were ignored and all options within a namespace were considered as potential matches. The group was reported in introspection data and used as section seperator in help display. To allow a single option namespace to be used for two commands, pipe through a nulstr with option group names to look at when parsing options. The field is set in the Command description and used in various option-handling contexts: - when parsing and looking for an option, do not consider the entries that are in the group that is not listed in the nulstr, - when listing options in help or introspection, skip over unlisted groups. The verbs_find_verb and verbs_find_command helpers are adjusted to have a consistent interface. --- src/shared/options.c | 62 ++++++++++++++++++++++++++++++++++----- src/shared/options.h | 4 +++ src/shared/verbs.c | 52 +++++++++++++++++++------------- src/shared/verbs.h | 11 +++++-- src/systemctl/systemctl.c | 3 +- 5 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/shared/options.c b/src/shared/options.c index 2bc160f4cd..72fc93245f 100644 --- a/src/shared/options.c +++ b/src/shared/options.c @@ -4,6 +4,7 @@ #include "format-table.h" #include "log.h" +#include "nulstr-util.h" #include "options.h" #include "stdio-util.h" #include "string-util.h" @@ -198,18 +199,27 @@ int option_parse( * First, figure out if we have a long option or a short option. */ assert(handling_positional_arg || state->argv[state->optind][0] == '-'); - if (handling_positional_arg) - /* We are supposed to return the positional arg to be handled. */ + if (handling_positional_arg) { + /* Find the positional arg to be handled. */ + + const char *group = NULL; /* We start in the default unnamed group. */ + for (option = state->namespace_start;; option++) { /* If OPTION_PARSER_RETURN_POSITIONAL_ARGS is specified, * OPTION_POSITIONAL must be used. */ assert(option < state->namespace_end); + /* If state.option_groups are specified, ignore options outside of the group */ + if (FLAGS_SET(option->flags, OPTION_GROUP_MARKER)) /* Start of a new option group */ + group = option->long_code; + if (state->option_groups && !(group && nulstr_contains(state->option_groups, group))) + continue; + if (FLAGS_SET(option->flags, OPTION_POSITIONAL_ENTRY)) break; } - else if (state->argv[state->optind][1] == '-') { + } else if (state->argv[state->optind][1] == '-') { /* We have a long option. */ char *eq = strchr(state->argv[state->optind], '='); if (eq) { @@ -238,6 +248,8 @@ int option_parse( const Option *last_partial = NULL; unsigned n_partial_matches = 0; /* The commandline option matches a defined prefix. */ + const char *group = NULL; /* We start in the default unnamed group. */ + for (option = state->namespace_start;; option++) { if (option >= state->namespace_end) { if (n_partial_matches == 0) { @@ -262,6 +274,12 @@ int option_parse( break; } + /* If state.option_groups are specified, ignore options outside of the group */ + if (FLAGS_SET(option->flags, OPTION_GROUP_MARKER)) /* Start of a new option group */ + group = option->long_code; + if (state->option_groups && !(group && nulstr_contains(state->option_groups, group))) + continue; + if (option_is_metadata(option) || !option->long_code) continue; @@ -290,6 +308,8 @@ int option_parse( } optname = _optname; + const char *group = NULL; /* We start in the default unnamed group. */ + for (option = state->namespace_start;; option++) { if (option >= state->namespace_end) { r = log_full_errno(LOG_ERR + state->log_level_shift, @@ -299,6 +319,12 @@ int option_parse( goto fail; } + /* If state.option_groups are specified, ignore options outside of the group */ + if (FLAGS_SET(option->flags, OPTION_GROUP_MARKER)) /* Start of a new option group */ + group = option->long_code; + if (state->option_groups && !(group && nulstr_contains(state->option_groups, group))) + continue; + if (option_is_metadata(option) || optchar != option->short_code) continue; @@ -573,6 +599,7 @@ int _option_parser_get_help_table_full( int options_get_help_table_group( const Option options[], const Option options_end[], + const char *option_groups, Table **ret, const char **ret_group) { int r; @@ -580,15 +607,24 @@ int options_get_help_table_group( assert(ret); assert(ret_group); - _cleanup_(table_unrefp) Table *table = table_new("names", "help"); - if (!table) - return log_oom(); + _cleanup_(table_unrefp) Table *table = NULL; assert(options_end > options); bool group_marker = FLAGS_SET(options[0].flags, OPTION_GROUP_MARKER); const char *group = group_marker ? ASSERT_PTR(options[0].long_code) : NULL; + /* Determine if we should ignore the whole option group. We do this if the option_groups option is + * specified and the current group name is not listed. The unnamed group cannot be specified by the + * nulstr, so always ignore it. */ + bool ignore_group = option_groups && !(group && nulstr_contains(option_groups, group)); + + if (!ignore_group) { + table = table_new("names", "help"); + if (!table) + return log_oom(); + } + const Option *opt; for (opt = options + group_marker; opt < options_end; opt++) { if (FLAGS_SET(opt->flags, OPTION_NAMESPACE_MARKER)) @@ -599,6 +635,9 @@ int options_get_help_table_group( /* End of the group */ break; + if (ignore_group) + continue; + if (!opt->help) /* No help string — we do not show the option */ continue; @@ -629,9 +668,11 @@ int options_get_help_table_group( return table_log_add_error(r); } - assert(!table_isempty(table)); /* Empty group? Something is off. */ + if (!ignore_group) { + assert(!table_isempty(table)); /* Empty group? Something is off. */ + table_set_header(table, false); + } - table_set_header(table, false); *ret = TAKE_PTR(table); *ret_group = group; @@ -687,6 +728,7 @@ int options_build_json( const Option options[], const Option options_end[], const char *namespace, + const char *option_groups, sd_json_variant **ret) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL; @@ -714,6 +756,10 @@ int options_build_json( /* Positional and help entries are only used for display */ continue; + if (option_groups && !(group && nulstr_contains(option_groups, group))) + /* This group shall be ignored */ + continue; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *o = NULL; r = option_build_json(opt, group, &o); if (r < 0) diff --git a/src/shared/options.h b/src/shared/options.h index 8fe0cae2e5..5b971879c8 100644 --- a/src/shared/options.h +++ b/src/shared/options.h @@ -226,6 +226,8 @@ typedef struct OptionParser { char **argv; /* The argv array, possibly reordered. */ OptionParserMode mode; const char *namespace; /* The namespace, may be NULL. */ + const char *option_groups; /* Optional nulstr with option groups to look at. When specified, + * only named option groups found in this list are used. */ int log_level_shift; /* The log level difference from the default of LOG_ERR. * Allowed values are -3..4. * Use 4 == LOG_DEBUG - LOG_ERR to log at debug level. */ @@ -297,6 +299,7 @@ int _option_parser_get_help_table_full( int options_get_help_table_group( const Option options[], const Option options_end[], + const char *option_groups, Table **ret, const char **ret_group); @@ -306,4 +309,5 @@ int options_build_json( const Option options[], const Option options_end[], const char *namespace, + const char *option_groups, sd_json_variant **ret); diff --git a/src/shared/verbs.c b/src/shared/verbs.c index 1d568d60ac..d8f5f1ca51 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -72,7 +72,7 @@ static bool verb_is_metadata(const Verb *verb) { FLAGS_SET(ASSERT_PTR(verb)->flags, VERB_GROUP_MARKER); } -const Verb* verbs_find_verb(const char *name, const Verb verbs[], const Verb verbs_end[]) { +const Verb* _verbs_find_verb(const Verb verbs[], const Verb verbs_end[], const char *name) { assert(verbs); assert(verbs_end > verbs); assert((uintptr_t) verbs % sizeof(void*) == 0); @@ -101,7 +101,7 @@ int _dispatch_verb(char **args, const Verb verbs[], const Verb verbs_end[], void const char *name = args ? args[0] : NULL; size_t left = strv_length(args); - const Verb *verb = verbs_find_verb(name, verbs, verbs_end); + const Verb *verb = _verbs_find_verb(verbs, verbs_end, name); if (!verb) { _cleanup_strv_free_ char **verb_strv = NULL; @@ -224,7 +224,12 @@ static int verb_add_help_one(Table *table, const Verb *verb) { return 0; } -static const Verb* verbs_get_command(const Verb verbs[], const Verb verbs_end[], const char *name) { +const Verb* _verbs_find_command( + const Verb verbs[], + const Verb verbs_end[], + const char *name, + const CommandDescription **ret_cmd) { + assert(verbs); assert(verbs_end > verbs); assert((uintptr_t) verbs % sizeof(void*) == 0); @@ -235,8 +240,14 @@ static const Verb* verbs_get_command(const Verb verbs[], const Verb verbs_end[], continue; const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(verb->data); - if (!name || nulstr_contains(cmd->names, name)) - return verb; + if (name && !nulstr_contains(cmd->names, name)) + continue; + + /* This function returns the Verb slot through the return value, and the + * CommandDescription it points to in the optional output parameter. */ + if (ret_cmd) + *ret_cmd = cmd; + return verb; } /* At the end of the list? */ @@ -332,7 +343,8 @@ static int print_verb_option_help( assert(verb->verb); - /* What is the the first group? */ + /* The group marker gives us the group name. + * If it's missing, we're in the default (unnamed) group. */ const char *group = FLAGS_SET(verb->flags, VERB_GROUP_MARKER) ? verb->verb : NULL; _cleanup_(table_unrefp) Table *table = NULL; @@ -368,17 +380,19 @@ static int print_verb_option_help( /* End of our namespace */ break; - r = options_get_help_table_group(opt, options_end, &table, &group); + r = options_get_help_table_group(opt, options_end, cmd->option_groups, &table, &group); if (r < 0) return r; - if (!GREEDY_REALLOC0(tables, n_verbs + n_opts + 2)) - return -ENOMEM; - if (!GREEDY_REALLOC0(groups, n_verbs + n_opts + 2)) - return -ENOMEM; + if (table) { + if (!GREEDY_REALLOC0(tables, n_verbs + n_opts + 2)) + return -ENOMEM; + if (!GREEDY_REALLOC0(groups, n_verbs + n_opts + 2)) + return -ENOMEM; - tables[n_verbs + n_opts] = TAKE_PTR(table); - groups[n_verbs + n_opts++] = group ?: "Options"; + tables[n_verbs + n_opts] = TAKE_PTR(table); + groups[n_verbs + n_opts++] = group ?: "Options"; + } opt += r; /* Skip over the whole option group */ } @@ -497,13 +511,9 @@ int _command_print_help_full( const char *footer_ansi_seq) { int r; - const Verb *cmdverb = verbs_get_command(verbs, verbs_end, name); - if (!cmdverb) - return log_error_errno(SYNTHETIC_ERRNO(ENODATA), - "Command %s not known", name); - - const CommandDescription *cmd = (const CommandDescription*) ASSERT_PTR(cmdverb->data); - const Verb *verbverbs = verbs_find_cmd_verbs(cmdverb, verbs_end); + const CommandDescription *cmd; + const Verb *cmdverb = ASSERT_PTR(_verbs_find_command(verbs, verbs_end, name, &cmd)); + const Verb *verbverbs = ASSERT_PTR(verbs_find_cmd_verbs(cmdverb, verbs_end)); if (cmd->pager_flags) pager_open(*cmd->pager_flags); @@ -603,7 +613,7 @@ static int command_build_json( } assert(names); /* At least the primary name must be defined */ - r = options_build_json(options, options_end, cmd->option_namespace, &opts); + r = options_build_json(options, options_end, cmd->option_namespace, cmd->option_groups, &opts); if (r < 0) return r; diff --git a/src/shared/verbs.h b/src/shared/verbs.h index 99efd2523d..673ef5870b 100644 --- a/src/shared/verbs.h +++ b/src/shared/verbs.h @@ -21,7 +21,8 @@ typedef struct CommandDescription { const char *argspec; /* optional specification of positional args in synopsis */ const char *footer; /* optional footer to print right above man page links */ const char *man_pages; /* nulstr with man page names */ - const char *option_namespace; /* to be used when the options are in a namespace */ + const char *option_namespace; /* optional option namespace for this command */ + const char *option_groups; /* optional nulstr with option groups for this command */ const PagerFlags *pager_flags; /* optional pointer to the runtime pager flags variable */ CommandFlags flags; } CommandDescription; @@ -107,7 +108,13 @@ bool running_in_chroot_or_offline(void); bool should_bypass(const char *env_prefix); -const Verb* verbs_find_verb(const char *name, const Verb verbs[], const Verb verbs_end[]); +const Verb* _verbs_find_command(const Verb verbs[], const Verb verbs_end[], const char *name, const CommandDescription **ret_cmd); +#define verbs_find_command(name, ret_cmd) \ + _verbs_find_command(__start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, name, ret_cmd) + +const Verb* _verbs_find_verb(const Verb verbs[], const Verb verbs_end[], const char *name); +#define verbs_find_verb(name) \ + _verbs_find_verb(__start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, name) int _dispatch_verb(char **args, const Verb verbs[], const Verb verbs_end[], void *userdata); #define dispatch_verb(args, userdata) \ diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 659de527d3..6a36afc6d3 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1093,8 +1093,7 @@ VERB_SCOPE(, verb_start, "condrestart", NULL, 2, VERB_ANY, VERB_SCOPE(, verb_is_active, "check", NULL, 2, VERB_ANY, VERB_ONLINE_ONLY, /* help= */ NULL); /* deprecated alias of is-active */ int systemctl_main(char **args) { - assert((uintptr_t) __start_SYSTEMD_VERBS % sizeof(void*) == 0); - const Verb *verb = verbs_find_verb(args[0], __start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS); + const Verb *verb = verbs_find_verb(args[0]); if (verb && (verb->flags & VERB_ONLINE_ONLY) && arg_root) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), From f976133dbfd138a71b3d307b75d96ba927ac4e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:51:40 +0200 Subject: [PATCH 9/9] mount: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. Options are now in two groups: "Common options" and Mount options". In --help, for systemd-mount, both groups are shown. For systemd-umount, only the first. This changes the behaviour a bit: previously, both groups were shown together as one list. I think the new behaviour is actually a bit better, because it makes it easier for the user to figure out that the commands share common options and one of the commands has its private second group. But if people think that the previous behaviour should be restored, we could add a display options to squish the groups back together. --help now goes through the pager, like other commands with --no-pager. --- src/mount/mount-tool.c | 90 +++++++++---------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 11 +++ 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 58b689190d..5ecd7c097a 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -2,6 +2,7 @@ #include "sd-bus.h" #include "sd-device.h" +#include "sd-json.h" #include "ansi-color.h" #include "argv-util.h" @@ -21,11 +22,9 @@ #include "format-table.h" #include "format-util.h" #include "fstab-util.h" -#include "help-util.h" #include "libmount-util.h" #include "main-func.h" #include "mountpoint-util.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -41,6 +40,7 @@ #include "unit-def.h" #include "unit-name.h" #include "user-util.h" +#include "verbs.h" static enum { ACTION_DEFAULT, @@ -86,6 +86,33 @@ STATIC_DESTRUCTOR_REGISTER(arg_description, freep); STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep); +COMMAND( + "systemd-mount\0", + "Establish a mount or auto-mount point.", + .argspec = + "WHAT [WHERE]\0" + "--tmpfs [NAME] WHERE\0" + "--list\0" + "--umount WHAT|WHERE…\0", + .option_groups = + "Common options\0" + "Mount options\0", + .man_pages = "systemd-mount.1\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); +COMMAND( + "systemd-umount\0", + "Unmount one or more mount points.", + .argspec = + "WHAT|WHERE…\0", + .option_groups = + "Common options\0", + .man_pages = "systemd-mount.1\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); + static int parse_where(const char *input, char **ret_where) { int r; @@ -110,46 +137,6 @@ static int parse_where(const char *input, char **ret_where) { return 0; } -static int help(char *argv[]) { - _cleanup_(table_unrefp) Table *options_common = NULL, *options_mount = NULL; - int r; - - r = option_parser_get_help_table(&options_common); - if (r < 0) - return r; - - if (invoked_as(argv, "systemd-umount")) { - help_cmdline("[OPTIONS…] WHAT|WHERE…"); - help_abstract("Unmount one or more mount points."); - } else { - help_cmdline("[OPTIONS…] WHAT [WHERE]"); - help_cmdline("[OPTIONS…] --tmpfs [NAME] WHERE"); - help_cmdline("[OPTIONS…] --list"); - help_cmdline("[OPTIONS…] --umount WHAT|WHERE…"); - help_abstract("Establish a mount or auto-mount point."); - - r = option_parser_get_help_table_group("Mount options", &options_mount); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options_common, options_mount); - } - - help_section("Options"); - r = table_print_or_warn(options_common); - if (r < 0) - return r; - - if (options_mount) { - r = table_print_or_warn(options_mount); - if (r < 0) - return r; - } - - help_man_page_reference("systemd-mount", "1"); - return 0; -} - static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -157,16 +144,26 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argv); assert(remaining_args); - if (invoked_as(argv, "systemd-umount")) + bool is_umount = invoked_as(argv, "systemd-umount"); + + const CommandDescription *cmd; + assert_se(verbs_find_command(is_umount ? "systemd-umount" : "systemd-mount", &cmd)); + + if (is_umount) arg_action = ACTION_UMOUNT; - OptionParser opts = { argc, argv }; + OptionParser opts = { + argc, argv, + .option_groups = cmd->option_groups, + }; FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Common options"): {} + OPTION_COMMON_HELP: - return help(argv); + return command_print_help_full(cmd->names, /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); @@ -227,6 +224,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { return r; break; + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); + OPTION_GROUP("Mount options"): {} OPTION_LONG("discover", NULL, "Discover mount device metadata"): diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 47847d6e8d..ce9124696b 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -80,6 +80,7 @@ INTROSPECTABLE=( systemd-machine-id-setup systemd-measure systemd-modules-load + systemd-mount systemd-mstack systemd-mute-console systemd-network-generator @@ -119,6 +120,7 @@ INTROSPECTABLE=( systemd-tpm2-clear systemd-tpm2-setup systemd-tty-ask-password-agent + systemd-umount systemd-update-done systemd-validatefs systemd-veritysetup @@ -181,6 +183,15 @@ systemd-dissect --introspect-cli | jq -e \ systemd-id128 --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' +if command -v systemd-mount >/dev/null; then + systemd-mount --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["systemd-mount", "systemd-umount"]' + + # --tmpfs is only valid for systemd-mount + (! systemd-mount --tmpfs 2>&1) | grep "one argument required" >/dev/null + (! systemd-umount --tmpfs 2>&1) | grep "unrecognized option" >/dev/null +fi + systemd-mstack --introspect-cli | jq -e \ '[.commands[].names[0]] | sort == ["mount.mstack", "systemd-mstack"]'