diff --git a/src/basic/argv-util.c b/src/basic/argv-util.c index b0381a6096..2796d5c0b6 100644 --- a/src/basic/argv-util.c +++ b/src/basic/argv-util.c @@ -28,7 +28,7 @@ void save_argc_argv(int argc, char **argv) { } bool invoked_as(char *argv[], const char *token) { - const char *progname = secure_getenv("SYSTEMD_INVOKED_AS"); + const char *progname = empty_to_null(secure_getenv("SYSTEMD_INVOKED_AS")); if (!progname && argv) progname = argv[0]; diff --git a/src/home/test-homectl-prompts.c b/src/home/test-homectl-prompts.c index 5429eaaa5e..8e65c864e0 100644 --- a/src/home/test-homectl-prompts.c +++ b/src/home/test-homectl-prompts.c @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-json.h" + #include "alloc-util.h" -#include "format-table.h" -#include "help-util.h" #include "homectl-prompts.h" #include "main-func.h" #include "options.h" @@ -11,31 +11,10 @@ #include "tests.h" #include "verbs.h" -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options, verbs); - - help_cmdline("[OPTIONS...] VERB [USERNAME]"); - help_abstract("Exercise homectl prompt functions in isolation."); - - help_section("Verbs"); - r = table_print_or_warn(verbs); - if (r < 0) - return r; - - help_section("Options"); - return table_print_or_warn(options); -} +COMMAND( + "test-homectl-prompts\0", + "Exercise homectl prompt functions in isolation.", +); VERB(verb_groups, "groups", "[USER]\0", VERB_ANY, 2, 0, "Select groups"); static int verb_groups(int argc, char *argv[], uintptr_t _data, void *userdata) { @@ -83,7 +62,10 @@ static int parse_argv(int argc, char **argv, char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help(); + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } *remaining_args = option_parser_get_args(&opts); diff --git a/src/libsystemd/sd-journal/test-journal-append.c b/src/libsystemd/sd-journal/test-journal-append.c index c71240660d..abdb06b9ef 100644 --- a/src/libsystemd/sd-journal/test-journal-append.c +++ b/src/libsystemd/sd-journal/test-journal-append.c @@ -4,11 +4,13 @@ #include #include +#include "sd-json.h" + #include "chattr-util.h" -#include "format-table.h" #include "iovec-util.h" #include "journal-file-util.h" #include "log.h" +#include "main-func.h" #include "mmap-cache.h" #include "options.h" #include "parse-util.h" @@ -17,6 +19,12 @@ #include "tests.h" #include "time-util.h" #include "tmpfile-util.h" +#include "verbs.h" + +COMMAND( + "test-journal-append\0", + "Append entries to journal files and check corruption handling.", +); static int journal_append_message(JournalFile *mj, const char *message) { struct iovec iovec; @@ -141,7 +149,7 @@ static int journal_corrupt_and_append(uint64_t start_offset, uint64_t step) { return 0; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { uint64_t start_offset = UINT64_MAX; uint64_t iterations = 100; uint64_t iteration_step = 1; @@ -156,24 +164,8 @@ int main(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { - OPTION_COMMON_HELP: { - _cleanup_(table_unrefp) Table *options = NULL; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - printf("Syntax:\n" - " %s [OPTION...]\n" - "\nOptions:\n", - program_invocation_short_name); - - r = table_print_or_warn(options); - if (r < 0) - return r; - - return 0; - } + OPTION_COMMON_HELP: + return command_print_help(); OPTION_LONG("start-offset", "OFFSET", "Offset at which to start corrupting the journal " @@ -220,6 +212,9 @@ int main(int argc, char *argv[]) { run_one = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (run_one) @@ -235,12 +230,11 @@ int main(int argc, char *argv[]) { offset = (start_offset == UINT64_MAX ? 0 : start_offset) + i * iteration_step; r = journal_corrupt_and_append(offset, corrupt_step); - if (r < 0) - return EXIT_FAILURE; - if (r > 0) - /* Reached the end of the journal file */ - break; + if (r != 0) /* Either error or EXIT_TEST_SKIP */ + return r; } - return EXIT_SUCCESS; + return 0; } + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/libudev/test-libudev.c b/src/libudev/test-libudev.c index 06feb1ffbc..2c09e59d62 100644 --- a/src/libudev/test-libudev.c +++ b/src/libudev/test-libudev.c @@ -3,9 +3,10 @@ #include #include +#include "sd-json.h" + #include "devnum-util.h" #include "fd-util.h" -#include "format-table.h" #include "libudev-list-internal.h" #include "log.h" #include "main-func.h" @@ -13,6 +14,7 @@ #include "options.h" #include "string-util.h" #include "tests.h" +#include "verbs.h" #include "version.h" static bool arg_monitor = false; @@ -405,22 +407,10 @@ static void test_list(void) { assert_se(!udev_list_entry_get_by_name(e, "ccc")); } -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - printf("%s [OPTIONS...]\n\n", program_invocation_short_name); - - r = table_print_or_warn(options); - if (r < 0) - return r; - - return 0; -} +COMMAND( + "test-libudev\0", + "Test libudev functions.", +); static int parse_args(int argc, char *argv[], const char **syspath, const char **subsystem) { assert(argc >= 0); @@ -434,7 +424,7 @@ static int parse_args(int argc, char *argv[], const char **syspath, const char * switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help(); OPTION('V', "version", NULL, "Show package version"): printf("%s\n", GIT_VERSION); @@ -455,6 +445,9 @@ static int parse_args(int argc, char *argv[], const char **syspath, const char * OPTION('m', "monitor", NULL, "Run monitor test"): arg_monitor = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } return 1; diff --git a/src/network/test-modem-manager-mock.c b/src/network/test-modem-manager-mock.c index c38a7a43cc..820e22c640 100644 --- a/src/network/test-modem-manager-mock.c +++ b/src/network/test-modem-manager-mock.c @@ -13,16 +13,16 @@ #include "sd-bus.h" #include "sd-daemon.h" #include "sd-event.h" +#include "sd-json.h" #include "alloc-util.h" #include "build.h" -#include "format-table.h" -#include "help-util.h" #include "log.h" #include "main-func.h" #include "options.h" #include "parse-util.h" #include "string-util.h" +#include "verbs.h" static char *arg_ifname = NULL; static char *arg_ipv4_address = NULL; @@ -364,20 +364,10 @@ static int filter_handler(sd_bus_message *m, void *userdata, sd_bus_error *error return 0; } -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - help_cmdline("[OPTIONS...]"); - help_abstract("Mock ModemManager D-Bus service for testing."); - - help_section("Options"); - return table_print_or_warn(options); -} +COMMAND( + "test-modem-manager-mock\0", + "Mock ModemManager D-Bus service for testing.", +); static int parse_argv(int argc, char *argv[]) { int r; @@ -391,7 +381,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help(); OPTION_COMMON_VERSION: return version(); @@ -432,6 +422,9 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to parse IPv6 prefix length: %m"); break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (!arg_ifname) diff --git a/src/report/report-sign-tpm2.c b/src/report/report-sign-tpm2.c index a742639336..10fa62f31b 100644 --- a/src/report/report-sign-tpm2.c +++ b/src/report/report-sign-tpm2.c @@ -9,9 +9,7 @@ #include "dlopen-note.h" #include "fd-util.h" #include "fileio.h" -#include "format-table.h" #include "fs-util.h" -#include "help-util.h" #include "iovec-util.h" #include "json-util.h" #include "log.h" @@ -25,6 +23,14 @@ #include "tpm2-util.h" #include "varlink-io.systemd.Report.Signer.h" #include "varlink-util.h" +#include "verbs.h" + +COMMAND( + "systemd-report-sign-tpm2\0", + "Get an attestation report from a Trusted Platform Module (TPM) " + "that includes the hash of the system report.", + .man_pages = "systemd-report-sign-tpm2@.service(8)\0", +); #define REPORT_SIGN_TPM2_PERSISTENT_DIR "/var/lib/systemd/report.sign.tpm2" #define REPORT_SIGN_TPM2_RUNTIME_DIR "/run/systemd/report.sign.tpm2" @@ -715,27 +721,6 @@ static int vl_server(void) { return 0; } -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - help_cmdline("[OPTIONS...]"); - help_abstract("Get an attestation report from a Trusted Platform Module (TPM) " - "that includes the hash of the system report."); - help_section("Options"); - - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference("systemd-report-sign-tpm2@.service", "8"); - return 0; -} - static int parse_argv(int argc, char *argv[]) { int r; @@ -747,9 +732,13 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help(); + OPTION_COMMON_VERSION: return version(); + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (option_parser_get_n_args(&opts) > 0) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index b0c15ca806..88d76b67f0 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -2172,7 +2172,7 @@ static const char* table_data_rgap_underline(const TableData *d) { return NULL; } -int table_data_requested_width(Table *table, size_t column, size_t *ret) { +static int table_data_requested_width(Table *table, size_t column, size_t *ret) { size_t width = 0; int r; @@ -2218,38 +2218,6 @@ int table_set_column_width(Table *t, size_t column, size_t width) { return r; } -int _table_sync_column_widths(size_t column, Table *a, ...) { - size_t max = 0; - va_list ap; - int r = 0; - - assert(a); - - /* Make the specified column have the same width in the tables. */ - - va_start(ap, a); - for (Table *t = a; t; t = va_arg(ap, Table*)) { - size_t w; - - r = table_data_requested_width(t, column, &w); - if (r < 0) - break; - - max = MAX(max, w); - } - va_end(ap); - if (r < 0) - return log_error_errno(r, "Failed to query table column width: %m"); - - r = 0; - va_start(ap, a); - for (Table *t = a; t; t = va_arg(ap, Table*)) - RET_GATHER(r, table_set_column_width(t, column, max)); - va_end(ap); - - return r; -} - int table_sync_all_column_widths(size_t column, Table **a) { size_t max = 0; int r; diff --git a/src/shared/format-table.h b/src/shared/format-table.h index 8087abfb9e..0907eeb698 100644 --- a/src/shared/format-table.h +++ b/src/shared/format-table.h @@ -144,11 +144,7 @@ int table_set_reverse(Table *t, size_t column, bool b); int table_hide_column_from_display_internal(Table *t, ...); #define table_hide_column_from_display(t, ...) table_hide_column_from_display_internal(t, __VA_ARGS__, SIZE_MAX) -int table_data_requested_width(Table *table, size_t column, size_t *ret); - int table_set_column_width(Table *t, size_t column, size_t width); -int _table_sync_column_widths(size_t column, Table *a, ...); -#define table_sync_column_widths(column, a, ...) _table_sync_column_widths(column, a, __VA_ARGS__, NULL) int table_sync_all_column_widths(size_t column, Table **a); int table_print_full(Table *t, FILE *f, bool flush); diff --git a/src/shared/help-util.c b/src/shared/help-util.c deleted file mode 100644 index 8968ba1377..0000000000 --- a/src/shared/help-util.c +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include - -#include "alloc-util.h" -#include "ansi-color.h" -#include "help-util.h" -#include "path-util.h" -#include "pretty-print.h" - -/* These are helpers for putting together --help texts in a uniform way with a common output style. Each - * function generates a separate part of the --help text: - * - * 1. help_cmdline() outputs a brief summary of the command line syntax. This shall be used at least once, - * in some cases multiple times. This generally comes first in the output. - * - * 2. help_abstract() outputs a brief prose abstract of the command, should carry a single line of text - * that gives the user a hint what this tool does. Use only once, right after the last help_cmdline(). - * - * 3. help_section() can be used to format multiple sections of the --help text. It should be used at least - * once for an "Options:" section, but can be used more than once, for programs with many - * options/verbs. The first invocation should come right after help_abstract(). - * - * 4. Finally, help_man_page_reference() adds a final line linking the man page of the tool. This should be - * used only once, and terminates the --help text. - * - * Switches and verbs documentation should be inserted after each help_section(). For that ideally use - * options.[ch] APIs. */ - -void help_cmdline(const char *arguments) { - const char *progname = - last_path_component(secure_getenv("SYSTEMD_INVOKED_AS")) - ?: program_invocation_short_name; - - assert(arguments); - - printf("%s>%s %s %s\n", - ansi_grey(), - ansi_normal(), - progname, - arguments); -} - -void help_abstract(const char *text) { - assert(text); - - printf("\n%s%s%s%s\n", - ansi_highlight(), - ansi_add_italics(), - text, - ansi_normal()); -} - -void help_section(const char *title) { - assert(title); - - printf("\n%s%s:%s\n", - ansi_underline(), - title, - ansi_normal()); -} - -void help_man_page_reference(const char *page, const char *section) { - assert(page); - assert(section); - - /* Displaying --help texts generally should not fail, hence let's fall back to a simple string in - * case of OOM. */ - _cleanup_free_ char *link = NULL; - if (terminal_urlify_man(page, section, &link) < 0) - printf("\nSee the %s(%s) man page for details.\n", page, section); - else - printf("\nSee the %s for details.\n", link); -} diff --git a/src/shared/help-util.h b/src/shared/help-util.h deleted file mode 100644 index 380487213f..0000000000 --- a/src/shared/help-util.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -void help_cmdline(const char *arguments); - -void help_abstract(const char *text); - -void help_section(const char *title); - -void help_man_page_reference(const char *page, const char *section); diff --git a/src/shared/meson.build b/src/shared/meson.build index ee395ffbe1..a8cea5b931 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -95,7 +95,6 @@ shared_sources = files( 'gnutls-util.c', 'gpt.c', 'group-record.c', - 'help-util.c', 'hibernate-util.c', 'hostname-setup.c', 'hwdb-util.c', diff --git a/src/shared/options.c b/src/shared/options.c index 72fc93245f..f92eabc1e6 100644 --- a/src/shared/options.c +++ b/src/shared/options.c @@ -516,86 +516,6 @@ const Option* options_find_namespace( return NULL; /* not found :/ */ } -int _option_parser_get_help_table_full( - const Option options[], - const Option options_end[], - const char *namespace, - const char *group, - Table **ret) { - int r; - - // TODO: drop this function and all its wrappers - - assert(ret); - - _cleanup_(table_unrefp) Table *table = table_new("names", "help"); - if (!table) - return log_oom(); - - bool in_ns = namespace == NULL; /* Are we currently in the section of the array that forms namespace - * ? The first part is the default unnamed namespace, so - * if the namespace was not specified, we are in it. */ - - bool in_group = group == NULL; /* Are we currently in the section of the array that forms group - * ? The first part is the default group, so if the group was - * not specified, we are in it. */ - - const Option *opt; - for (opt = options; opt < options_end; opt++) { - bool ns_marker = FLAGS_SET(opt->flags, OPTION_NAMESPACE_MARKER); - if (!in_ns) { - in_ns = ns_marker && streq(namespace, opt->long_code); - continue; - } - if (ns_marker) - break; /* End of namespace */ - - bool group_marker = FLAGS_SET(opt->flags, OPTION_GROUP_MARKER); - if (!in_group) { - in_group = group_marker && streq(group, opt->long_code); - continue; - } - if (group_marker) - break; /* End of group */ - - if (!opt->help) - /* No help string — we do not show the option */ - continue; - - _cleanup_free_ char *s = option_get_synopsis(opt, " ", /* show_metavar= */ true); - if (!s) - return log_oom(); - - /* We indent the option string by two spaces. We could set the minimum cell width and - * right-align for a similar result, but that'd be more work. This is only used for - * display. */ - bool shift_left = opt->short_code != 0 || FLAGS_SET(opt->flags, OPTION_HELP_ENTRY_VERBATIM); - const char *prefix = shift_left ? " " : " "; - _cleanup_free_ char *t = strjoin(prefix, s); - if (!t) - return log_oom(); - - r = table_add_many(table, TABLE_STRING, t); - if (r < 0) - return table_log_add_error(r); - - _cleanup_strv_free_ char **split = strv_split(opt->help, /* separators= */ NULL); - if (!split) - return log_oom(); - - r = table_add_many(table, TABLE_STRV_WRAPPED, split); - if (r < 0) - return table_log_add_error(r); - } - - assert(!table_isempty(table)); /* The namespace or group were not found. Something is off. */ - - table_set_header(table, false); - *ret = TAKE_PTR(table); - assert(opt - options < INT_MAX); - return opt - options; -} - int options_get_help_table_group( const Option options[], const Option options_end[], @@ -605,7 +525,6 @@ int options_get_help_table_group( int r; assert(ret); - assert(ret_group); _cleanup_(table_unrefp) Table *table = NULL; @@ -674,7 +593,8 @@ int options_get_help_table_group( } *ret = TAKE_PTR(table); - *ret_group = group; + if (ret_group) + *ret_group = group; assert(opt - options < INT_MAX); return opt - options; diff --git a/src/shared/options.h b/src/shared/options.h index 5b971879c8..83e72188b4 100644 --- a/src/shared/options.h +++ b/src/shared/options.h @@ -99,10 +99,6 @@ assert_cc(sizeof(Option) % sizeof(void*) == 0); /* This option is internal-only for now and not shown in --help */ \ OPTION_LONG("introspect-cli", NULL, /* help= */ NULL) -/* For programs which do not do option parsing, but check the argv array directly. */ -#define OPTION_COMMON_INTROSPECT_CLI_ENTRY \ - _OPTION_ENTRY(__COUNTER__, /* fl= */ 0, /* sc= */ 0, "introspect-cli", /* mv= */ NULL, /* d= */ 0u, /* h= */ NULL) - #define OPTION_COMMON_NO_PAGER \ OPTION_LONG("no-pager", NULL, "Do not start a pager") @@ -281,21 +277,6 @@ const Option* options_find_namespace( const Option options_end[], const char *namespace); -int _option_parser_get_help_table_full( - const Option options[], - const Option options_end[], - const char *namespace, - const char *group, - Table **ret); -#define option_parser_get_help_table_full(namespace, group, ret) \ - _option_parser_get_help_table_full(__start_SYSTEMD_OPTIONS, __stop_SYSTEMD_OPTIONS, namespace, group, ret) -#define option_parser_get_help_table_ns(ns, ret) \ - option_parser_get_help_table_full(ns, /* group= */ NULL, ret) -#define option_parser_get_help_table_group(group, ret) \ - option_parser_get_help_table_full(/* namespace= */ NULL, group, ret) -#define option_parser_get_help_table(ret) \ - option_parser_get_help_table_group(/* group= */ NULL, ret) - int options_get_help_table_group( const Option options[], const Option options_end[], diff --git a/src/shared/service-util.h b/src/shared/service-util.h index e63f8fe9b0..e35b7838b5 100644 --- a/src/shared/service-util.h +++ b/src/shared/service-util.h @@ -13,9 +13,9 @@ int _service_parse_argv( /* The service is expected to define a COMMAND() with .option_namespace = "service" and the option * groups matching the features it supports: "Options" always, "Bus introspection" iff bus_objects - * is passed, "Runtime scope" iff runtime_scope is passed. The macro captures the calling binary's - * verb section, where that COMMAND is found, while the options are defined in - * service_parse_argv_full() itself. */ + * is passed, "Runtime scope" iff runtime_scope is passed. The macro inserts the calling binary's + * verb section, where that COMMAND is found, while the options are defined in _service_parse_argv(). + */ #define service_parse_argv(bus_objects, runtime_scope, argc, argv) \ _service_parse_argv( \ __start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, \ diff --git a/src/shared/verbs.c b/src/shared/verbs.c index 920b4e0458..c79659467b 100644 --- a/src/shared/verbs.c +++ b/src/shared/verbs.c @@ -6,11 +6,11 @@ #include "env-util.h" #include "extract-word.h" #include "format-table.h" -#include "help-util.h" #include "log.h" #include "nulstr-util.h" #include "options.h" #include "pager.h" +#include "path-util.h" #include "pretty-print.h" #include "string-util.h" #include "strv.h" @@ -270,7 +270,7 @@ const Verb* _verbs_find_command( return NULL; } -int _verbs_get_help_table( +static int verbs_get_help_table( const Verb verbs[], const Verb verbs_end[], const char *group, @@ -292,13 +292,8 @@ int _verbs_get_help_table( const Verb *verb; for (verb = verbs; verb < verbs_end; verb++) { - /* Binaries with one or more VERB_COMMAND entries call this function - * through print_verb_option_help() which provides a verbs slice that - * starts after the VERB_COMMAND entry. - * - * In unconverted binaries, this function is called directly. */ - // TODO: make this function static after everything has been converted. - + /* This function is called through print_verb_option_help(), which provides a verbs + * slice that starts after the VERB_COMMAND entry. */ if (FLAGS_SET(verb->flags, VERB_COMMAND_MARKER)) break; @@ -364,7 +359,7 @@ static int print_verb_option_help( const char *group = FLAGS_SET(verb->flags, VERB_GROUP_MARKER) ? verb->verb : NULL; _cleanup_(table_unrefp) Table *table = NULL; - r = _verbs_get_help_table(verb, verbs_end, group, &table); + r = verbs_get_help_table(verb, verbs_end, group, &table); if (r < 0) return r; @@ -518,6 +513,29 @@ static const Verb* verbs_find_cmd_verbs(const Verb *cmdverb, const Verb verbs_en return actual; } +static void help_cmdline(const char *arguments) { + assert(arguments); + + const char *progname = + empty_to_null(last_path_component(secure_getenv("SYSTEMD_INVOKED_AS"))) + ?: program_invocation_short_name; + + printf("%s>%s %s %s\n", + ansi_grey(), + ansi_normal(), + progname, + arguments); +} + +void help_section(const char *title) { + assert(title); + + printf("\n%s%s:%s\n", + ansi_underline(), + title, + ansi_normal()); +} + int _command_print_help_full( const Verb verbs[], const Verb verbs_end[], @@ -617,12 +635,22 @@ int _command_print_verb_help( } if (verb->option_namespace) { + const Option *optns = options_find_namespace(options, options_end, verb->option_namespace); + if (!optns) + return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Option namespace %s not found.", verb->option_namespace); + _cleanup_(table_unrefp) Table *table = NULL; - r = _option_parser_get_help_table_full(options, options_end, verb->option_namespace, - /* group= */ NULL, &table); + r = options_get_help_table_group( + optns, options_end, + /* option_groups= */ NULL, + &table, + /* ret_group= */ NULL); if (r < 0) return r; + /* Note: we assume that only one option group is used for a verb. If this ever + * stops being true, the code here would need to be adjusted to loop over groups. */ help_section("Options"); r = table_print_or_warn(table); if (r < 0) diff --git a/src/shared/verbs.h b/src/shared/verbs.h index 3453c5e72a..a1eb671490 100644 --- a/src/shared/verbs.h +++ b/src/shared/verbs.h @@ -140,28 +140,7 @@ int _dispatch_verb(char **args, const Verb verbs[], const Verb verbs_end[], void #define dispatch_verb(args, userdata) \ _dispatch_verb(args, __start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, userdata) -int _verbs_get_help_table( - const Verb verbs[], - const Verb verbs_end[], - const char *group, - Table **ret); -#define verbs_get_help_table_group(group, ret) \ - _verbs_get_help_table(__start_SYSTEMD_VERBS, __stop_SYSTEMD_VERBS, group, ret) -#define verbs_get_help_table(ret) \ - verbs_get_help_table_group(/* group= */ NULL, ret) - -#define _VERB_COMMON_HELP_IMPL(impl) \ - static int verb_help(int argc, char **argv, uintptr_t data, void *userdata) { \ - return impl(); \ - } - -#define VERB_COMMON_HELP(impl) \ - VERB(verb_help, "help", NULL, VERB_ANY, VERB_ANY, 0, "Show this help"); \ - _VERB_COMMON_HELP_IMPL(impl) - -#define VERB_COMMON_HELP_HIDDEN(impl) \ - VERB(verb_help, "help", NULL, VERB_ANY, VERB_ANY, 0, NULL); \ - _VERB_COMMON_HELP_IMPL(impl) +void help_section(const char *title); #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) diff --git a/src/test/test-chase-manual.c b/src/test/test-chase-manual.c index 410522ceb1..e3d83a6026 100644 --- a/src/test/test-chase-manual.c +++ b/src/test/test-chase-manual.c @@ -1,36 +1,25 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-json.h" + #include "chase.h" #include "fd-util.h" -#include "format-table.h" #include "log.h" #include "main-func.h" #include "options.h" #include "strv.h" #include "tests.h" +#include "verbs.h" static const char *arg_root = NULL; static int arg_flags = 0; static bool arg_open = false; -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - printf("%s [OPTIONS...] path...\n" - "\nExercise chase() function on specified paths.\n\n", - program_invocation_short_name); - - r = table_print_or_warn(options); - if (r < 0) - return r; - - return 0; -} +COMMAND( + "test-chase-manual\0", + "Exercise chase() function on specified paths.", + .argspec = "PATH…\0", +); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -43,7 +32,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help(); OPTION_LONG("root", "PATH", "Operate below specified root directory"): arg_root = opts.arg; @@ -64,6 +53,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_LONG_DATA("warn", NULL, CHASE_WARN, "Emit a warning on error"): arg_flags |= opts.opt->data; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } *ret_args = option_parser_get_args(&opts); diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index cd8985cae7..384c53a8b7 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -4,7 +4,6 @@ #include "device-private.h" #include "device-util.h" -#include "help-util.h" #include "log.h" #include "options.h" #include "udev-builtin.h" diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 8c6e0e0ad3..00bde6b6b7 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -111,6 +111,7 @@ INTROSPECTABLE=( systemd-report-cgroup systemd-report-files systemd-report-sign-plain + systemd-report-sign-tpm2 systemd-report-sign-tsm systemd-resolved systemd-run