From 143af68ee15607aced66e9f5aba55899b3f4e505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 16 Apr 2026 18:32:13 +0200 Subject: [PATCH 1/6] oomctl: convert to the new option and verb parsers --help is the same, except for whitespace and common option descriptions. Co-developed-by: Claude Opus 4.6 --- src/oom/oomctl.c | 101 ++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/src/oom/oomctl.c b/src/oom/oomctl.c index ed394e42d8..703b9c3f0e 100644 --- a/src/oom/oomctl.c +++ b/src/oom/oomctl.c @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include - #include "sd-bus.h" #include "alloc-util.h" @@ -9,8 +7,10 @@ #include "bus-error.h" #include "bus-locator.h" #include "bus-message-util.h" +#include "format-table.h" #include "log.h" #include "main-func.h" +#include "options.h" #include "pager.h" #include "pretty-print.h" #include "verbs.h" @@ -19,6 +19,7 @@ static PagerFlags arg_pager_flags = 0; static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL; int r; pager_open(arg_pager_flags); @@ -27,29 +28,45 @@ static int help(void) { if (r < 0) return log_oom(); - printf("%1$s [OPTIONS...] COMMAND ...\n\n" - "%2$sManage or inspect the userspace OOM killer.%3$s\n" - "\n%4$sCommands:%5$s\n" - " dump Output the current state of systemd-oomd\n" - "\n%4$sOptions:%5$s\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - "\nSee the %6$s for details.\n", + r = verbs_get_help_table(&verbs); + if (r < 0) + return r; + + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + + (void) table_sync_column_widths(0, verbs, options); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sManage or inspect the userspace OOM killer.%s\n" + "\n%sCommands:%s\n", program_invocation_short_name, ansi_highlight(), ansi_normal(), ansi_underline(), - ansi_normal(), - link); + ansi_normal()); + r = table_print_or_warn(verbs); + if (r < 0) + return r; + + printf("\n%sOptions:%s\n", + ansi_underline(), + ansi_normal()); + + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee the %s for details.\n", link); return 0; } -static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) { - return help(); -} +VERB_COMMON_HELP_HIDDEN(help); +VERB(verb_dump_state, "dump", NULL, VERB_ANY, 1, VERB_DEFAULT, + "Output the current state of systemd-oomd"); static int verb_dump_state(int argc, char *argv[], uintptr_t _data, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; @@ -69,64 +86,42 @@ static int verb_dump_state(int argc, char *argv[], uintptr_t _data, void *userda return bus_message_dump_fd(reply); } -static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - ARG_NO_PAGER, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - {} - }; - - int c; - +static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + OptionParser state = { argc, argv }; + const char *arg; + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) switch (c) { - case 'h': - return help(); + OPTION_COMMON_HELP: + return help(); - case ARG_VERSION: - return version(); + OPTION_COMMON_VERSION: + return version(); - case ARG_NO_PAGER: - arg_pager_flags |= PAGER_DISABLE; - break; - - case '?': - return -EINVAL; - - default: - assert_not_reached(); + OPTION_COMMON_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; } + *ret_args = option_parser_get_args(&state); return 1; } static int run(int argc, char* argv[]) { - static const Verb verbs[] = { - { "help", VERB_ANY, VERB_ANY, 0, verb_help }, - { "dump", VERB_ANY, 1, VERB_DEFAULT, verb_dump_state }, - {} - }; - int r; log_setup(); - r = parse_argv(argc, argv); + char **args = NULL; + r = parse_argv(argc, argv, &args); if (r <= 0) return r; - return dispatch_verb(argc, argv, verbs, NULL); + return dispatch_verb_with_args(args, NULL); } DEFINE_MAIN_FUNCTION(run); From aeee8b952700c86f7af388cccb37407d8a4db5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 16 Apr 2026 18:33:32 +0200 Subject: [PATCH 2/6] oomd: convert to the new option parser --help output is idential except for indentation. Co-developed-by: Claude Opus 4.6 --- src/oom/oomd.c | 66 ++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/src/oom/oomd.c b/src/oom/oomd.c index b1d3efb8f5..54a3bb7a1d 100644 --- a/src/oom/oomd.c +++ b/src/oom/oomd.c @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include - #include "sd-event.h" #include "alloc-util.h" @@ -11,11 +9,13 @@ #include "cgroup-util.h" #include "daemon-util.h" #include "fileio.h" +#include "format-table.h" #include "log.h" #include "main-func.h" #include "oomd-conf.h" #include "oomd-manager.h" #include "oomd-manager-bus.h" +#include "options.h" #include "parse-util.h" #include "pretty-print.h" #include "psi-util.h" @@ -24,74 +24,60 @@ static bool arg_dry_run = false; static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL; int r; r = terminal_urlify_man("systemd-oomd", "8", &link); if (r < 0) return log_oom(); - printf("%s [OPTIONS...]\n\n" - "Run the userspace out-of-memory (OOM) killer.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --dry-run Only print destructive actions instead of doing them\n" - " --bus-introspect=PATH Write D-Bus XML introspection data\n" - "\nSee the %s for details.\n", - program_invocation_short_name, - link); + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + printf("%s [OPTIONS...]\n\n" + "Run the userspace out-of-memory (OOM) killer.\n\n", + program_invocation_short_name); + + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee the %s for details.\n", link); return 0; } static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - ARG_DRY_RUN, - ARG_BUS_INTROSPECT, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "dry-run", no_argument, NULL, ARG_DRY_RUN }, - { "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT }, - {} - }; - - int c; - assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + OptionParser state = { argc, argv }; + const char *arg; + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) switch (c) { - case 'h': + OPTION_COMMON_HELP: return help(); - case ARG_VERSION: + OPTION_COMMON_VERSION: return version(); - case ARG_DRY_RUN: + OPTION_LONG("dry-run", NULL, + "Only print destructive actions instead of doing them"): arg_dry_run = true; break; - case ARG_BUS_INTROSPECT: + OPTION_LONG("bus-introspect", "PATH", + "Write D-Bus XML introspection data"): return bus_introspect_implementations( stdout, - optarg, + arg, BUS_IMPLEMENTATIONS(&manager_object, &log_control_object)); - - case '?': - return -EINVAL; - - default: - assert_not_reached(); } - if (optind < argc) + if (option_parser_get_n_args(&state) > 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); From 33a9e2dfcca92010ed1423ef1136e5161cc55eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 16 Apr 2026 18:34:53 +0200 Subject: [PATCH 3/6] path-tool: convert to the new option parser --help output is identical except for indentation and common option strings. Co-developed-by: Claude Opus 4.6 --- src/path/path-tool.c | 74 +++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/src/path/path-tool.c b/src/path/path-tool.c index 62eade3b05..797a7d06af 100644 --- a/src/path/path-tool.c +++ b/src/path/path-tool.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include "sd-path.h" @@ -8,12 +7,15 @@ #include "alloc-util.h" #include "build.h" #include "errno-util.h" +#include "format-table.h" #include "log.h" #include "main-func.h" +#include "options.h" #include "pager.h" #include "pretty-print.h" #include "sort-util.h" #include "string-util.h" +#include "strv.h" static const char *arg_suffix = NULL; static PagerFlags arg_pager_flags = 0; @@ -172,72 +174,57 @@ static int print_path(const char *n) { static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL; int r; r = terminal_urlify_man("systemd-path", "1", &link); if (r < 0) return log_oom(); - printf("%s [OPTIONS...] [NAME...]\n" - "\n%sShow system and user paths.%s\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --suffix=SUFFIX Suffix to append to paths\n" - " --no-pager Do not pipe output into a pager\n" - "\nSee the %s for details.\n", + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + + printf("%s [OPTIONS...] [NAME...]\n\n" + "%sShow system and user paths.%s\n\n", program_invocation_short_name, ansi_highlight(), - ansi_normal(), - link); + ansi_normal()); + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee the %s for details.\n", link); return 0; } -static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - ARG_SUFFIX, - ARG_NO_PAGER, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "suffix", required_argument, NULL, ARG_SUFFIX }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - {} - }; - - int c; - +static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + OptionParser state = { argc, argv }; + const char *arg; + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) switch (c) { - case 'h': + OPTION_COMMON_HELP: return help(); - case ARG_VERSION: + OPTION_COMMON_VERSION: return version(); - case ARG_SUFFIX: - arg_suffix = optarg; + OPTION_LONG("suffix", "SUFFIX", "Suffix to append to paths"): + arg_suffix = arg; break; - case ARG_NO_PAGER: + OPTION_COMMON_NO_PAGER: arg_pager_flags |= PAGER_DISABLE; break; - - case '?': - return -EINVAL; - - default: - assert_not_reached(); } + *ret_args = option_parser_get_args(&state); return 1; } @@ -246,15 +233,16 @@ static int run(int argc, char* argv[]) { log_setup(); - r = parse_argv(argc, argv); + char **args = NULL; + r = parse_argv(argc, argv, &args); if (r <= 0) return r; - if (optind >= argc) + if (strv_isempty(args)) return list_paths(); - for (int i = optind; i < argc; i++) - RET_GATHER(r, print_path(argv[i])); + STRV_FOREACH(i, args) + RET_GATHER(r, print_path(*i)); return r; } From 8d803844ae6af020ecdce8abf604cef6e0615e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 16 Apr 2026 18:47:33 +0200 Subject: [PATCH 4/6] pcrextend: convert to the new option parser --help is identical except for indentation and common option strings. Co-developed-by: Claude Opus 4.6 --- src/pcrextend/pcrextend.c | 164 ++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 97 deletions(-) diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c index e35f579e63..639331ba97 100644 --- a/src/pcrextend/pcrextend.c +++ b/src/pcrextend/pcrextend.c @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include - #include "sd-json.h" #include "sd-messages.h" #include "sd-varlink.h" @@ -10,8 +8,10 @@ #include "build.h" #include "efi-loader.h" #include "escape.h" +#include "format-table.h" #include "json-util.h" #include "main-func.h" +#include "options.h" #include "parse-argument.h" #include "pcrextend-util.h" #include "pretty-print.h" @@ -42,95 +42,63 @@ STATIC_DESTRUCTOR_REGISTER(arg_nvpcr_name, freep); #define EXTENSION_STRING_SAFE_LIMIT 1024 -static int help(int argc, char *argv[], void *userdata) { +static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL; int r; r = terminal_urlify_man("systemd-pcrextend", "8", &link); if (r < 0) return log_oom(); + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + printf("%1$s [OPTIONS...] WORD\n" "%1$s [OPTIONS...] --file-system=PATH\n" "%1$s [OPTIONS...] --machine-id\n" "%1$s [OPTIONS...] --product-id\n" - "\n%5$sExtend a TPM2 PCR with boot phase, machine ID, or file system ID.%6$s\n" - "\n%3$sOptions:%4$s\n" - " -h --help Show this help\n" - " --version Print version\n" - " --bank=DIGEST Select TPM PCR bank (SHA1, SHA256)\n" - " --pcr=INDEX Select TPM PCR index (0…23)\n" - " --nvpcr=NAME Select TPM PCR mode nvindex name\n" - " --tpm2-device=PATH Use specified TPM2 device\n" - " --graceful Exit gracefully if no TPM2 device is found\n" - " --file-system=PATH Measure UUID/labels of file system into PCR 15\n" - " --machine-id Measure machine ID into PCR 15\n" - " --product-id Measure SMBIOS product ID into NvPCR 'hardware'\n" - " --early Run in early boot mode, without access to /var/\n" - " --event-type=TYPE Event type to include in the event log\n" - "\nSee the %2$s for details.\n", + "\n%2$sExtend a TPM2 PCR with boot phase, machine ID, or file system ID.%3$s\n", program_invocation_short_name, - link, - ansi_underline(), - ansi_normal(), ansi_highlight(), ansi_normal()); + printf("\n%sOptions:%s\n", + ansi_underline(), + ansi_normal()); + + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee the %s for details.\n", link); return 0; } -static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - ARG_BANK, - ARG_PCR, - ARG_NVPCR, - ARG_TPM2_DEVICE, - ARG_GRACEFUL, - ARG_FILE_SYSTEM, - ARG_MACHINE_ID, - ARG_PRODUCT_ID, - ARG_EARLY, - ARG_EVENT_TYPE, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "bank", required_argument, NULL, ARG_BANK }, - { "pcr", required_argument, NULL, ARG_PCR }, - { "nvpcr", required_argument, NULL, ARG_NVPCR }, - { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE }, - { "graceful", no_argument, NULL, ARG_GRACEFUL }, - { "file-system", required_argument, NULL, ARG_FILE_SYSTEM }, - { "machine-id", no_argument, NULL, ARG_MACHINE_ID }, - { "product-id", no_argument, NULL, ARG_PRODUCT_ID }, - { "early", no_argument, NULL, ARG_EARLY }, - { "event-type", required_argument, NULL, ARG_EVENT_TYPE }, - {} - }; - - int c, r; - +static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + OptionParser state = { argc, argv }; + const char *arg; + int r; + + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) switch (c) { - case 'h': - help(0, NULL, NULL); - return 0; + OPTION_COMMON_HELP: + return help(); - case ARG_VERSION: + OPTION_COMMON_VERSION: return version(); - case ARG_BANK: { + OPTION_LONG("bank", "DIGEST", "Select TPM PCR bank (SHA1, SHA256)"): { const EVP_MD *implementation; - implementation = EVP_get_digestbyname(optarg); + implementation = EVP_get_digestbyname(arg); if (!implementation) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", optarg); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", arg); if (strv_extend(&arg_banks, EVP_MD_name(implementation)) < 0) return log_oom(); @@ -138,36 +106,36 @@ static int parse_argv(int argc, char *argv[]) { break; } - case ARG_PCR: - if (isempty(optarg)) { + OPTION_LONG("pcr", "INDEX", "Select TPM PCR index (0…23)"): + if (isempty(arg)) { arg_pcr_mask = 0; break; } - r = tpm2_pcr_index_from_string(optarg); + r = tpm2_pcr_index_from_string(arg); if (r < 0) - return log_error_errno(r, "Failed to parse PCR index: %s", optarg); + return log_error_errno(r, "Failed to parse PCR index: %s", arg); arg_pcr_mask |= INDEX_TO_MASK(uint32_t, r); break; - case ARG_NVPCR: - if (!tpm2_nvpcr_name_is_valid(optarg)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "NvPCR name is not valid: %s", optarg); + OPTION_LONG("nvpcr", "NAME", "Select TPM PCR mode nvindex name"): + if (!tpm2_nvpcr_name_is_valid(arg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "NvPCR name is not valid: %s", arg); - r = free_and_strdup_warn(&arg_nvpcr_name, optarg); + r = free_and_strdup_warn(&arg_nvpcr_name, arg); if (r < 0) return r; break; - case ARG_TPM2_DEVICE: { + OPTION_LONG("tpm2-device", "PATH", "Use specified TPM2 device"): { _cleanup_free_ char *device = NULL; - if (streq(optarg, "list")) + if (streq(arg, "list")) return tpm2_list_devices(/* legend= */ true, /* quiet= */ false); - if (!streq(optarg, "auto")) { - device = strdup(optarg); + if (!streq(arg, "auto")) { + device = strdup(arg); if (!device) return log_oom(); } @@ -176,43 +144,41 @@ static int parse_argv(int argc, char *argv[]) { break; } - case ARG_GRACEFUL: + OPTION_LONG("graceful", NULL, + "Exit gracefully if no TPM2 device is found"): arg_graceful = true; break; - case ARG_FILE_SYSTEM: - r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_file_system); + OPTION_LONG("file-system", "PATH", + "Measure UUID/labels of file system into PCR 15"): + r = parse_path_argument(arg, /* suppress_root= */ false, &arg_file_system); if (r < 0) return r; - break; - case ARG_MACHINE_ID: + OPTION_LONG("machine-id", NULL, "Measure machine ID into PCR 15"): arg_machine_id = true; break; - case ARG_PRODUCT_ID: + OPTION_LONG("product-id", NULL, + "Measure SMBIOS product ID into NvPCR 'hardware'"): arg_product_id = true; break; - case ARG_EARLY: + OPTION_LONG("early", NULL, + "Run in early boot mode, without access to /var/"): arg_early = true; break; - case ARG_EVENT_TYPE: - if (streq(optarg, "help")) + OPTION_LONG("event-type", "TYPE", + "Event type to include in the event log"): + if (streq(arg, "help")) return DUMP_STRING_TABLE(tpm2_userspace_event_type, Tpm2UserspaceEventType, _TPM2_USERSPACE_EVENT_TYPE_MAX); - arg_event_type = tpm2_userspace_event_type_from_string(optarg); + arg_event_type = tpm2_userspace_event_type_from_string(arg); if (arg_event_type < 0) - return log_error_errno(arg_event_type, "Failed to parse --event-type= argument: %s", optarg); + return log_error_errno(arg_event_type, "Failed to parse --event-type= argument: %s", arg); break; - - case '?': - return -EINVAL; - - default: - assert_not_reached(); } if (!!arg_file_system + arg_machine_id + arg_product_id > 1) @@ -237,6 +203,7 @@ static int parse_argv(int argc, char *argv[]) { return r; } + *ret_args = option_parser_get_args(&state); return 1; } @@ -482,15 +449,18 @@ static int run(int argc, char *argv[]) { log_setup(); - r = parse_argv(argc, argv); + char **args = NULL; + r = parse_argv(argc, argv, &args); if (r <= 0) return r; + size_t n_args = strv_length(args); + if (arg_varlink) return vl_server(); /* Invocation as Varlink service */ if (arg_file_system) { - if (optind != argc) + if (n_args != 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument."); r = pcrextend_file_system_word(arg_file_system, &word, NULL); @@ -501,7 +471,7 @@ static int run(int argc, char *argv[]) { } else if (arg_machine_id) { - if (optind != argc) + if (n_args != 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument."); r = pcrextend_machine_id_word(&word); @@ -512,7 +482,7 @@ static int run(int argc, char *argv[]) { } else if (arg_product_id) { - if (optind != argc) + if (n_args != 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument."); r = pcrextend_product_id_word(&word); @@ -521,10 +491,10 @@ static int run(int argc, char *argv[]) { event = TPM2_EVENT_PRODUCT_ID; } else { - if (optind+1 != argc) + if (n_args != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected a single argument."); - word = strdup(argv[optind]); + word = strdup(args[0]); if (!word) return log_oom(); From 07e0805f1abe42d5582ce357c01c477192bfc065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 16 Apr 2026 23:42:48 +0200 Subject: [PATCH 5/6] random-seed: convert to "verbs", use the new option+verb code --help output is the same except for indentation. Co-developed-by: Claude Opus 4.7 --- src/random-seed/random-seed-tool.c | 99 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/src/random-seed/random-seed-tool.c b/src/random-seed/random-seed-tool.c index b539c1f654..3e40fcddda 100644 --- a/src/random-seed/random-seed-tool.c +++ b/src/random-seed/random-seed-tool.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include -#include #include #include #include @@ -14,18 +13,20 @@ #include "build.h" #include "errno-util.h" #include "fd-util.h" +#include "format-table.h" #include "fs-util.h" #include "io-util.h" #include "log.h" #include "main-func.h" #include "mkdir.h" +#include "options.h" #include "parse-util.h" #include "pretty-print.h" #include "random-util.h" #include "sha256.h" -#include "string-table.h" #include "string-util.h" #include "sync-util.h" +#include "verbs.h" #include "xattr-util.h" typedef enum SeedAction { @@ -296,75 +297,75 @@ static int save_seed_file( return 0; } -static int help(int argc, char *argv[], void *userdata) { +static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL; int r; r = terminal_urlify_man("systemd-random-seed", "8", &link); if (r < 0) return log_oom(); - printf("%1$s [OPTIONS...] COMMAND\n" - "\n%5$sLoad and save the system random seed at boot and shutdown.%6$s\n" - "\n%3$sCommands:%4$s\n" - " load Load a random seed saved on disk into the kernel entropy pool\n" - " save Save a new random seed on disk\n" - "\n%3$sOptions:%4$s\n" - " -h --help Show this help\n" - " --version Show package version\n" - "\nSee the %2$s for details.\n", + r = verbs_get_help_table(&verbs); + if (r < 0) + return r; + + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + + (void) table_sync_column_widths(0, verbs, options); + + printf("%s [OPTIONS...] COMMAND\n" + "\n%sLoad and save the system random seed at boot and shutdown.%s\n" + "\nCommands:\n", program_invocation_short_name, - link, - ansi_underline(), - ansi_normal(), ansi_highlight(), ansi_normal()); + r = table_print_or_warn(verbs); + if (r < 0) + return r; + + printf("\nOptions:\n"); + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee the %s for details.\n", link); return 0; } -static const char* const seed_action_table[_ACTION_MAX] = { - [ACTION_LOAD] = "load", - [ACTION_SAVE] = "save", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(seed_action, SeedAction); +VERB_FULL(verb_set_action, "load", NULL, VERB_ANY, 1, 0, ACTION_LOAD, + "Load a random seed saved on disk into the kernel entropy pool"); +VERB_FULL(verb_set_action, "save", NULL, VERB_ANY, 1, 0, ACTION_SAVE, + "Save a new random seed on disk"); +static int verb_set_action(int argc, char *argv[], uintptr_t data, void *userdata) { + arg_action = data; + return 0; +} static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - {} - }; - - int c; - assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) - switch (c) { - case 'h': - return help(0, NULL, NULL); - case ARG_VERSION: - return version(); - case '?': - return -EINVAL; + OptionParser state = { argc, argv }; + const char *arg; + int r; - default: - assert_not_reached(); + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) + switch (c) { + + OPTION_COMMON_HELP: + return help(); + + OPTION_COMMON_VERSION: + return version(); } - if (optind + 1 != argc) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires one argument."); - - arg_action = seed_action_from_string(argv[optind]); - if (arg_action < 0) - return log_error_errno(arg_action, "Unknown action '%s'", argv[optind]); + r = dispatch_verb_with_args(option_parser_get_args(&state), NULL); + if (r < 0) + return r; return 1; } From 5961237fde7eaa30dcde99e07147e0bbb7246fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 17 Apr 2026 08:00:58 +0200 Subject: [PATCH 6/6] socket-proxyd: convert to the new option parser --help output is identical in content. --help/--version as now first in the list, as is usual. Co-developed-by: Claude Opus 4.7 --- src/socket-proxy/socket-proxyd.c | 98 +++++++++++++------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index e1eec1dd41..82250a0b06 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include #include @@ -15,8 +14,10 @@ #include "errno-util.h" #include "event-util.h" #include "fd-util.h" +#include "format-table.h" #include "log.h" #include "main-func.h" +#include "options.h" #include "parse-util.h" #include "pretty-print.h" #include "resolve-private.h" @@ -24,6 +25,7 @@ #include "socket-forward.h" #include "socket-util.h" #include "string-util.h" +#include "strv.h" #include "time-util.h" static unsigned arg_connections_max = 256; @@ -382,8 +384,8 @@ static int add_listen_socket(Context *context, int fd) { } static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_free_ char *time_link = NULL; + _cleanup_free_ char *link = NULL, *time_link = NULL; + _cleanup_(table_unrefp) Table *options = NULL; int r; r = terminal_urlify_man("systemd-socket-proxyd", "8", &link); @@ -393,61 +395,49 @@ static int help(void) { if (r < 0) return log_oom(); + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + printf("%1$s [HOST:PORT]\n" - "%1$s [SOCKET]\n\n" - "%2$sBidirectionally proxy local sockets to another (possibly remote) socket.%3$s\n\n" - " -c --connections-max= Set the maximum number of connections to be accepted\n" - " --exit-idle-time= Exit when without a connection for this duration. See\n" - " the %4$s for time span format\n" - " -h --help Show this help\n" - " --version Show package version\n" - "\nSee the %5$s for details.\n", + "%1$s [SOCKET]\n" + "\n%2$sBidirectionally proxy local sockets to another (possibly remote) socket.%3$s\n\n", program_invocation_short_name, ansi_highlight(), - ansi_normal(), - time_link, - link); + ansi_normal()); + r = table_print_or_warn(options); + if (r < 0) + return r; + + printf("\nSee %s for --exit-idle-time= time span format.\n" + "See the %s for details.\n", + time_link, link); return 0; } static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_VERSION = 0x100, - ARG_EXIT_IDLE, - ARG_IGNORE_ENV - }; - - static const struct option options[] = { - { "connections-max", required_argument, NULL, 'c' }, - { "exit-idle-time", required_argument, NULL, ARG_EXIT_IDLE }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - {} - }; - - int c, r; - assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "c:h", options, NULL)) >= 0) + OptionParser state = { argc, argv }; + const char *arg; + int r; + FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c) switch (c) { - case 'h': + OPTION_COMMON_HELP: return help(); - case ARG_VERSION: + OPTION_COMMON_VERSION: return version(); - case 'c': - r = safe_atou(optarg, &arg_connections_max); - if (r < 0) { - log_error("Failed to parse --connections-max= argument: %s", optarg); - return r; - } + OPTION('c', "connections-max", "NUMBER", + "Set the maximum number of connections to be accepted"): + r = safe_atou(arg, &arg_connections_max); + if (r < 0) + return log_error_errno(r, "Failed to parse --connections-max= argument: %s", arg); if (arg_connections_max < 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -455,28 +445,22 @@ static int parse_argv(int argc, char *argv[]) { break; - case ARG_EXIT_IDLE: - r = parse_sec(optarg, &arg_exit_idle_time); + OPTION_LONG("exit-idle-time", "TIME", + "Exit when without a connection for this duration"): + r = parse_sec(arg, &arg_exit_idle_time); if (r < 0) - return log_error_errno(r, "Failed to parse --exit-idle-time= argument: %s", optarg); + return log_error_errno(r, "Failed to parse --exit-idle-time= argument: %s", arg); break; - - case '?': - return -EINVAL; - - default: - assert_not_reached(); } - if (optind >= argc) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Not enough parameters."); + char **args = option_parser_get_args(&state); + size_t n = strv_length(args); + if (n < 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not enough parameters."); + if (n > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters."); - if (argc != optind+1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Too many parameters."); - - arg_remote_host = argv[optind]; + arg_remote_host = args[0]; return 1; }