diff --git a/man/run0.xml b/man/run0.xml index c2e891149f..1eb9905b57 100644 --- a/man/run0.xml +++ b/man/run0.xml @@ -373,6 +373,16 @@ + + + + + Do not pipe output into a pager. This currently only applies to + . (The pager is not started during normal operation.) + + + + All command line arguments after the first non-option argument become part of the command line of diff --git a/src/bootctl/bootctl.c b/src/bootctl/bootctl.c index d28b0f3f3e..e397b2aab1 100644 --- a/src/bootctl/bootctl.c +++ b/src/bootctl/bootctl.c @@ -2,6 +2,7 @@ #include +#include "sd-json.h" #include "sd-varlink.h" #include "blockdev-util.h" @@ -28,18 +29,15 @@ #include "escape.h" #include "fd-util.h" #include "find-esp.h" -#include "format-table.h" #include "image-policy.h" #include "log.h" #include "loop-util.h" #include "main-func.h" #include "mount-util.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" #include "path-util.h" -#include "pretty-print.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -109,6 +107,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_entry_title, freep); STATIC_DESTRUCTOR_REGISTER(arg_entry_version, freep); STATIC_DESTRUCTOR_REGISTER(arg_extras, strv_freep); +COMMAND( + "bootctl\0", + "Control EFI firmware boot settings and manage boot loader.", + .man_pages = "bootctl.1\0", + .pager_flags = &arg_pager_flags, +); + static const char* const install_source_table[_INSTALL_SOURCE_MAX] = { [INSTALL_SOURCE_IMAGE] = "image", [INSTALL_SOURCE_HOST] = "host", @@ -290,78 +295,7 @@ GracefulMode arg_graceful(void) { return _arg_graceful; } -static int help(void) { - _cleanup_free_ char *link = NULL; - int r; - - pager_open(arg_pager_flags); - - r = terminal_urlify_man("bootctl", "1", &link); - if (r < 0) - return log_oom(); - - static const char *const verb_groups[] = { - "Generic EFI Firmware/Boot Loader Commands", - "Boot Loader Specification Commands", - "Boot Loader Interface Commands", - "systemd-boot Commands", - "Kernel Image Commands", - }; - - static const char *const option_groups[] = { - "Block Device Discovery Commands", - "Options", - }; - - Table *verb_tables[ELEMENTSOF(verb_groups)] = {}; - CLEANUP_ELEMENTS(verb_tables, table_unref_array_clear); - Table *option_tables[ELEMENTSOF(option_groups)] = {}; - CLEANUP_ELEMENTS(option_tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(verb_groups); i++) { - r = verbs_get_help_table_group(verb_groups[i], &verb_tables[i]); - if (r < 0) - return r; - } - - for (size_t i = 0; i < ELEMENTSOF(option_groups); i++) { - r = option_parser_get_help_table_group(option_groups[i], &option_tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths(0, - verb_tables[0], verb_tables[1], verb_tables[2], - verb_tables[3], verb_tables[4], - option_tables[0], option_tables[1]); - - printf("%s [OPTIONS...] COMMAND ...\n" - "\n%sControl EFI firmware boot settings and manage boot loader.%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - for (size_t i = 0; i < ELEMENTSOF(verb_groups); i++) { - printf("\n%s%s:%s\n", ansi_underline(), verb_groups[i], ansi_normal()); - - r = table_print_or_warn(verb_tables[i]); - if (r < 0) - return r; - } - - for (size_t i = 0; i < ELEMENTSOF(option_groups); i++) { - printf("\n%s%s:%s\n", ansi_underline(), option_groups[i], ansi_normal()); - - r = table_print_or_warn(option_tables[i]); - if (r < 0) - return r; - } - - printf("\nSee the %s for details.\n", link); - return 0; -} - -VERB_COMMON_HELP(help); +VERB_COMMON_HELP_AUTO_HIDDEN("bootctl"); VERB_GROUP("Generic EFI Firmware/Boot Loader Commands"); @@ -479,7 +413,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_GROUP("Options"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("bootctl"); OPTION_COMMON_VERSION: return version(); @@ -765,7 +699,11 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { arg_tries_left = u; break; - }} + } + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); + } char **args = option_parser_get_args(&opts); diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 32d79077c3..1d087a9b74 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -3,6 +3,7 @@ #include #include "sd-device.h" +#include "sd-json.h" #include "sd-varlink.h" #include "alloc-util.h" @@ -24,15 +25,12 @@ #include "cryptsetup-util.h" #include "dlopen-note.h" #include "extract-word.h" -#include "format-table.h" -#include "help-util.h" #include "initrd-util.h" #include "libfido2-util.h" #include "limits-util.h" #include "log.h" #include "main-func.h" #include "memory-util.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -45,6 +43,7 @@ #include "time-util.h" #include "tpm2-pcr.h" #include "tpm2-util.h" +#include "verbs.h" #define ARGON2ID_BENCHMARK_DEFAULT_TARGET_MS 2000U #define ARGON2ID_BENCHMARK_MAX_ATTEMPTS 8U @@ -119,6 +118,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep); STATIC_DESTRUCTOR_REGISTER(arg_node, freep); STATIC_DESTRUCTOR_REGISTER(arg_wipe_slots, freep); +COMMAND( + "systemd-cryptenroll\0", + "Enroll a security token or authentication credential to a LUKS volume.", + .argspec = "[BLOCK-DEVICE]\0", + .man_pages = "systemd-cryptenroll.1\0", + .pager_flags = &arg_pager_flags, +); + static bool wipe_requested(void) { return arg_n_wipe_slots > 0 || arg_wipe_slots_scope != WIPE_EXPLICIT || @@ -345,46 +352,6 @@ static int parse_prompt_suppress(const char *arg) { } } -static int help(void) { - int r; - - static const char* const groups[] = { - NULL, - "Unlocking", - "Simple Enrollment", - "PKCS#11 Enrollment", - "FIDO2 Enrollment", - "TPM2 Enrollment", - }; - - Table *tables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = option_parser_get_help_table_group(groups[i], &tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths(0, tables[0], tables[1], tables[2], tables[3], tables[4], tables[5]); - - pager_open(arg_pager_flags); - - help_cmdline("[OPTIONS...] [BLOCK-DEVICE]"); - help_abstract("Enroll a security token or authentication credential to a LUKS volume."); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - help_section(groups[i] ?: "Options"); - - r = table_print_or_warn(tables[i]); - if (r < 0) - return r; - } - - help_man_page_reference("systemd-cryptenroll", "1"); - return 0; -} - static int parse_argv(int argc, char *argv[]) { bool auto_public_key_pcr_mask = true, auto_pcrlock = true; @@ -398,7 +365,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-cryptenroll"); OPTION_COMMON_VERSION: return version(); @@ -786,6 +753,9 @@ static int parse_argv(int argc, char *argv[]) { if (arg_tpm2_argon2id_iter_time == 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Target time must be non-zero."); break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (option_parser_get_n_args(&opts) > 1) diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index ed0182950d..55f36b1d86 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -712,6 +712,13 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +COMMAND( + "mount.ddi\0", + "External helper for mount.8 to mount Discoverable Disk Images (DDIs).", + .man_pages = "systemd-dissect.1\0", + .option_namespace = "mount.ddi", +); + static int parse_argv_as_mount_helper(int argc, char *argv[]) { const char *options = NULL; bool fake = false; diff --git a/src/imds/imdsd.c b/src/imds/imdsd.c index aecc2feac7..4324864aa5 100644 --- a/src/imds/imdsd.c +++ b/src/imds/imdsd.c @@ -29,10 +29,8 @@ #include "fd-util.h" #include "fileio.h" #include "format-ifname.h" -#include "format-table.h" #include "hash-funcs.h" #include "hashmap.h" -#include "help-util.h" #include "imds-util.h" #include "in-addr-util.h" #include "io-util.h" @@ -41,7 +39,6 @@ #include "log.h" #include "main-func.h" #include "netlink-util.h" -#include "options.h" #include "parse-argument.h" #include "parse-util.h" #include "path-util.h" @@ -54,6 +51,7 @@ #include "utf8.h" #include "varlink-io.systemd.InstanceMetadata.h" #include "varlink-util.h" +#include "verbs.h" #include "web-util.h" #include "xattr-util.h" @@ -141,6 +139,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_token_header_name, freep); STATIC_DESTRUCTOR_REGISTER(arg_extra_header, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_well_known_key, imds_well_known_key_free); +COMMAND( + "systemd-imdsd\0", + "Low-level IMDS data acquisition.", + .argspec = "KEY\0", + .man_pages = "systemd-imdsd@.service.8\0", +); + typedef struct Context Context; typedef struct ChildData { @@ -2192,37 +2197,6 @@ static int vl_server(void) { return 0; } -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL, *endpoint_options = NULL; - int r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Manual Endpoint Configuration", &endpoint_options); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options, endpoint_options); - - help_cmdline("[OPTIONS...] KEY"); - help_abstract("Low-level IMDS data acquisition."); - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_section("Manual Endpoint Configuration"); - r = table_print_or_warn(endpoint_options); - if (r < 0) - return r; - - help_man_page_reference("systemd-imdsd@.service", "8"); - return 0; -} - static bool http_header_name_valid(const char *a) { return a && ascii_is_valid(a) && !string_has_cc(a, /* ok= */ NULL) && !strchr(a, ':'); } @@ -2239,7 +2213,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-imdsd"); OPTION_COMMON_VERSION: return version(); @@ -2484,6 +2458,9 @@ static int parse_argv(int argc, char *argv[]) { return r; break; } + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (arg_vendor || arg_token_url || arg_refresh_header_name || arg_data_url || arg_data_url_suffix || arg_token_header_name || arg_extra_header) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ce9470cf76..e37ee113fd 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -3,15 +3,14 @@ #include #include "sd-journal.h" +#include "sd-json.h" #include "sd-varlink.h" #include "build.h" #include "dissect-image.h" #include "dlopen-note.h" #include "extract-word.h" -#include "format-table.h" #include "glob-util.h" -#include "help-util.h" #include "id128-print.h" #include "image-policy.h" #include "journalctl.h" @@ -28,7 +27,6 @@ #include "main-func.h" #include "mount-util.h" #include "mountpoint-util.h" -#include "options.h" #include "output-mode.h" #include "pager.h" #include "parse-argument.h" @@ -45,6 +43,7 @@ #include "varlink-io.systemd.JournalAccess.h" #include "varlink-io.systemd.Metrics.h" #include "varlink-util.h" +#include "verbs.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -143,6 +142,17 @@ STATIC_DESTRUCTOR_REGISTER(arg_pattern, freep); STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern, pcre2_code_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); +COMMAND( + "journalctl\0", + "Query the journal.", + .argspec = "[MATCH…]\0", + .man_pages = "journalctl.1\0", + .option_namespace = "journalctl", + .pager_flags = &arg_pager_flags, +); + +// TODO: also expose journalctl-varlink interface through COMMAND + static int parse_id_descriptor(const char *x, sd_id128_t *ret_id, int *ret_offset) { sd_id128_t id = SD_ID128_NULL; int off = 0, r; @@ -271,46 +281,6 @@ static int help_facilities(void) { return 0; } -static int help(void) { - static const char *const groups[] = { - "Source Options", - "Filtering Options", - "Output Control Options", - "Pager Control Options", - "Forward Secure Sealing (FSS) Options", - "Commands", - }; - - Table *tables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(tables, table_unref_array_clear); - int r; - - pager_open(arg_pager_flags); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = option_parser_get_help_table_full("journalctl", groups[i], &tables[i]); - if (r < 0) - return r; - } - - assert_cc(ELEMENTSOF(tables) == 6); - (void) table_sync_column_widths(0, tables[0], tables[1], tables[2], - tables[3], tables[4], tables[5]); - - help_cmdline("[OPTIONS…] [MATCHES…]"); - help_abstract("Query the journal."); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - help_section(groups[i]); - r = table_print_or_warn(tables[i]); - if (r < 0) - return r; - } - - help_man_page_reference("journalctl", "1"); - return 0; -} - static int vl_server(void) { _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL; int r; @@ -823,7 +793,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_GROUP("Commands"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("journalctl"); OPTION_COMMON_VERSION: return version(); @@ -932,6 +902,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_LONG("new-id128", NULL, /* help= */ NULL): arg_action = ACTION_NEW_ID128; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } char **args = option_parser_get_args(&opts); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 7d63e6b03b..f7e1b88e10 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -5,6 +5,7 @@ #include "sd-bus.h" #include "sd-journal.h" +#include "sd-json.h" #include "alloc-util.h" #include "ansi-color.h" @@ -20,11 +21,9 @@ #include "dlopen-note.h" #include "format-table.h" #include "format-util.h" -#include "help-util.h" #include "log.h" #include "logs-show.h" #include "main-func.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -56,6 +55,13 @@ static OutputMode arg_output = OUTPUT_SHORT; STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); +COMMAND( + "loginctl\0", + "Send control commands to or query the login manager.", + .man_pages = "loginctl.1\0", + .pager_flags = &arg_pager_flags, +); + typedef struct SessionStatusInfo { const char *id; uid_t uid; @@ -1493,53 +1499,7 @@ static int verb_terminate_seat(int argc, char *argv[], uintptr_t _data, void *us return 0; } -static int help(void) { - static const char *const groups[] = { - "Session Commands", - "User Commands", - "Seat Commands", - }; - - Table *vtables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(vtables, table_unref_array_clear); - _cleanup_(table_unrefp) Table *options = NULL; - int r; - - pager_open(arg_pager_flags); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = verbs_get_help_table_group(groups[i], &vtables[i]); - if (r < 0) - return r; - } - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - assert_cc(ELEMENTSOF(vtables) == 3); - (void) table_sync_column_widths(0, vtables[0], vtables[1], vtables[2], options); - - help_cmdline("[OPTIONS…] COMMAND …"); - help_abstract("Send control commands to or query the login manager."); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - help_section(groups[i]); - r = table_print_or_warn(vtables[i]); - if (r < 0) - return r; - } - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference("loginctl", "1"); - return 0; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("loginctl"); static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -1554,7 +1514,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("loginctl"); OPTION_COMMON_VERSION: return version(); @@ -1652,6 +1612,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_COMMON_NO_ASK_PASSWORD: arg_ask_password = false; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } *remaining_args = option_parser_get_args(&opts); diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c index 1eb372be64..d932d00b0d 100644 --- a/src/machine-id-setup/machine-id-setup-main.c +++ b/src/machine-id-setup/machine-id-setup-main.c @@ -2,11 +2,12 @@ #include +#include "sd-json.h" + #include "alloc-util.h" #include "build.h" #include "dissect-image.h" #include "dlopen-note.h" -#include "format-table.h" #include "id128-util.h" #include "image-policy.h" #include "log.h" @@ -14,9 +15,8 @@ #include "machine-id-setup.h" #include "main-func.h" #include "mount-util.h" -#include "options.h" #include "parse-argument.h" -#include "pretty-print.h" +#include "verbs.h" static char *arg_root = NULL; static char *arg_image = NULL; @@ -28,49 +28,11 @@ STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *commands = NULL, *options = NULL; - int r; - - r = terminal_urlify_man("systemd-machine-id-setup", "1", &link); - if (r < 0) - return log_oom(); - - 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, commands, options); - - printf("%s [OPTIONS...]\n\n" - "%sInitialize /etc/machine-id from a random source.%s\n" - "\n%sCommands:%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal(), - ansi_underline(), - ansi_normal()); - - r = table_print_or_warn(commands); - 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; -} +COMMAND( + "systemd-machine-id-setup\0", + "Initialize /etc/machine-id from a random source.", + .man_pages = "systemd-machine-id-setup.1\0", +); static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); @@ -82,8 +44,10 @@ static int parse_argv(int argc, char *argv[]) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Commands"): {} + OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-machine-id-setup"); OPTION_COMMON_VERSION: return version(); @@ -115,6 +79,9 @@ static int parse_argv(int argc, char *argv[]) { OPTION_LONG("print", NULL, "Print used machine ID"): arg_print = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (option_parser_get_n_args(&opts) > 0) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 19ad385733..8275eb6a03 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -8,6 +8,7 @@ #include "sd-bus.h" #include "sd-event.h" #include "sd-journal.h" +#include "sd-json.h" #include "sd-varlink.h" #include "alloc-util.h" @@ -33,7 +34,6 @@ #include "format-ifname.h" #include "format-table.h" #include "format-util.h" -#include "help-util.h" #include "hostname-util.h" #include "import-util.h" #include "in-addr-util.h" @@ -45,7 +45,6 @@ #include "machine-util.h" #include "main-func.h" #include "nulstr-util.h" -#include "options.h" #include "osc-context.h" #include "output-mode.h" #include "pager.h" @@ -117,6 +116,13 @@ static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep); +COMMAND( + "machinectl\0", + "Send control commands to or query the virtual machine and container registration manager.", + .man_pages = "machinectl.1\0", + .pager_flags = &arg_pager_flags, +); + static OutputFlags get_output_flags(void) { return FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL | @@ -2370,58 +2376,7 @@ static int chainload_importctl(char **args) { return log_error_errno(r, "Failed to invoke 'importctl': %m"); } -static int help(void) { - static const char* const vgroups[] = { - "Machine Commands", - "Image Commands", - }; - - Table *vtables[ELEMENTSOF(vgroups)] = {}; - CLEANUP_ELEMENTS(vtables, table_unref_array_clear); - _cleanup_(table_unrefp) Table *options = 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(&options); - if (r < 0) - return r; - - assert_cc(ELEMENTSOF(vtables) == 2); - (void) table_sync_column_widths(0, options, vtables[0], vtables[1]); - - pager_open(arg_pager_flags); - - help_cmdline("[OPTIONS…] COMMAND …"); - - printf("\n%1$s%2$sSend control commands to or query the virtual machine and container%3$s\n" - "%1$s%2$sregistration manager.%3$s\n", - ansi_highlight(), - ansi_add_italics(), - ansi_normal()); - - 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); - if (r < 0) - return r; - - help_man_page_reference("machinectl", "1"); - - return 0; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("machinectl"); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -2454,7 +2409,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return help(); + return command_print_help("machinectl"); OPTION_COMMON_VERSION: return version(); @@ -2620,6 +2575,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION('q', "quiet", NULL, "Suppress output"): arg_quiet = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } /* We gathered some positional args in 'args' ourselves. Append the remaining ones. */ diff --git a/src/measure/measure-tool.c b/src/measure/measure-tool.c index bcd20743ed..02bba3866c 100644 --- a/src/measure/measure-tool.c +++ b/src/measure/measure-tool.c @@ -5,6 +5,7 @@ #include "sd-json.h" #include "alloc-util.h" +#include "ansi-color.h" #include "ask-password-api.h" #include "build.h" #include "crypto-util.h" @@ -13,15 +14,12 @@ #include "efivars.h" #include "fd-util.h" #include "fileio.h" -#include "format-table.h" #include "hexdecoct.h" #include "log.h" #include "main-func.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" -#include "pretty-print.h" #include "string-util.h" #include "strv.h" #include "tpm2-pcr.h" @@ -67,57 +65,14 @@ static void free_sections(char*(*sections)[_UNIFIED_SECTION_MAX]) { STATIC_DESTRUCTOR_REGISTER(arg_sections, free_sections); -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *verbs = NULL, *options = NULL, *options2 = NULL; - int r; +COMMAND( + "systemd-measure\0", + "Pre-calculate and sign PCR hash for a unified kernel image (UKI).", + .man_pages = "systemd-measure.1\0", + .pager_flags = &arg_pager_flags, +); - r = terminal_urlify_man("systemd-measure", "1", &link); - if (r < 0) - return log_oom(); - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("UKI PE Section Options", &options2); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, verbs, options, options2); - - printf("%s [OPTIONS...] COMMAND ...\n" - "\n%sPre-calculate and sign PCR hash for a unified kernel image (UKI).%s\n" - "\n%sCommands:%s\n", - program_invocation_short_name, - ansi_highlight(), ansi_normal(), - ansi_underline(), 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("\n%sUKI PE Section Options:%s\n", ansi_underline(), ansi_normal()); - - r = table_print_or_warn(options2); - if (r < 0) - return r; - - printf("\nSee the %s for details.\n", link); - return 0; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("systemd-measure"); static char *normalize_phase(const char *s) { _cleanup_strv_free_ char **l = NULL; @@ -146,7 +101,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-measure"); OPTION_COMMON_VERSION: return version(); @@ -315,6 +270,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); } if (arg_public_key && arg_certificate) diff --git a/src/mstack/mstack-tool.c b/src/mstack/mstack-tool.c index 45c699d574..ea2aa404c3 100644 --- a/src/mstack/mstack-tool.c +++ b/src/mstack/mstack-tool.c @@ -3,6 +3,8 @@ #include #include +#include "sd-json.h" + #include "argv-util.h" #include "build.h" #include "chase.h" @@ -11,15 +13,14 @@ #include "extract-word.h" #include "fd-util.h" #include "format-table.h" -#include "help-util.h" #include "image-policy.h" #include "main-func.h" #include "mount-util.h" #include "mountpoint-util.h" #include "mstack.h" -#include "options.h" #include "parse-argument.h" #include "string-util.h" +#include "verbs.h" static enum { ACTION_INSPECT, @@ -41,38 +42,17 @@ STATIC_DESTRUCTOR_REGISTER(arg_where, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_filter, image_filter_freep); -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL, *commands = NULL; - int r; - - r = option_parser_get_help_table_ns("systemd-mstack", &options); - if (r < 0) - return r; - - r = option_parser_get_help_table_full("systemd-mstack", "Commands", &commands); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options, commands); - - help_cmdline("[OPTIONS...] WHAT"); - help_cmdline("[OPTIONS...] --mount WHAT WHERE"); - help_cmdline("[OPTIONS...] --umount WHERE"); - help_abstract("Inspect or apply mount stack."); - - help_section("Commands"); - 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("systemd-mstack", "1"); - return 0; -} +COMMAND( + "systemd-mstack\0", + "Inspect or apply mount stack.", + .argspec = + "WHAT\0" + "--mount WHAT WHERE\0" + "--umount WHERE\0", + .man_pages = "systemd-mstack.1\0", + .option_namespace = "systemd-mstack", + .pager_flags = &arg_pager_flags, +); static int parse_argv(int argc, char *argv[]) { int r; @@ -87,6 +67,34 @@ static int parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("systemd-mstack"): {} + OPTION_GROUP("Commands"): {} + + OPTION_COMMON_HELP: + return command_print_help("systemd-mstack"); + + OPTION_COMMON_VERSION: + return version(); + + OPTION('m', "mount", NULL, "Mount the mstack to the specified directory"): + arg_action = ACTION_MOUNT; + break; + + OPTION_SHORT('M', NULL, "Shortcut for --mount --mkdir"): + arg_action = ACTION_MOUNT; + arg_mstack_flags |= MSTACK_MKDIR; + break; + + OPTION('u', "umount", NULL, "Unmount the image from the specified directory"): + arg_action = ACTION_UMOUNT; + break; + + OPTION_SHORT('U', NULL, "Shortcut for --umount --rmdir"): + arg_action = ACTION_UMOUNT; + arg_rmdir = true; + break; + + OPTION_GROUP("Options"): {} + OPTION('r', "read-only", NULL, "Mount read-only"): arg_mstack_flags |= MSTACK_RDONLY; break; @@ -130,31 +138,8 @@ static int parse_argv(int argc, char *argv[]) { return r; break; - OPTION_GROUP("Commands"): {} - - OPTION_COMMON_HELP: - return help(); - - OPTION_COMMON_VERSION: - return version(); - - OPTION('m', "mount", NULL, "Mount the mstack to the specified directory"): - arg_action = ACTION_MOUNT; - break; - - OPTION_SHORT('M', NULL, "Shortcut for --mount --mkdir"): - arg_action = ACTION_MOUNT; - arg_mstack_flags |= MSTACK_MKDIR; - break; - - OPTION('u', "umount", NULL, "Unmount the image from the specified directory"): - arg_action = ACTION_UMOUNT; - break; - - OPTION_SHORT('U', NULL, "Shortcut for --umount --rmdir"): - arg_action = ACTION_UMOUNT; - arg_rmdir = true; - break; + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } char **args = option_parser_get_args(&opts); @@ -203,6 +188,13 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +COMMAND( + "mount.mstack\0", + "External helper for mount.8 to mount mount stacks.", + .man_pages = "systemd-mstack.1\0", + .option_namespace = "mount.mstack", +); + static int parse_argv_as_mount_helper(int argc, char *argv[]) { const char *mount_options = NULL; bool fake = false; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ee612a76d6..82b366eb43 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -16,6 +16,7 @@ #include "sd-daemon.h" #include "sd-event.h" #include "sd-id128.h" +#include "sd-json.h" #include "sd-netlink.h" #include "sd-path.h" #include "sd-varlink.h" @@ -54,7 +55,6 @@ #include "fdset.h" #include "fileio.h" #include "fork-notify.h" -#include "format-table.h" #include "format-util.h" #include "fs-util.h" #include "gpt.h" @@ -93,7 +93,6 @@ #include "nspawn-setuid.h" #include "nspawn-stub-pid1.h" #include "nsresource.h" -#include "options.h" #include "os-util.h" #include "osc-context.h" #include "pager.h" @@ -135,6 +134,7 @@ #include "unit-name.h" #include "user-record.h" #include "user-util.h" +#include "verbs.h" #include "vpick.h" /* The notify socket inside the container it can use to talk to nspawn using the sd_notify(3) protocol */ @@ -318,6 +318,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_background, freep); STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep); +COMMAND( + "systemd-nspawn\0", + "Spawn a command or OS in a lightweight container.", + .argspec = "[PATH] [ARGUMENTS…]\0", + .man_pages = "systemd-nspawn.1\0", + .pager_flags = &arg_pager_flags, +); + static int parse_private_users( const char *s, UserNamespaceMode *ret_userns_mode, @@ -383,69 +391,6 @@ static int parse_private_users( return 0; } -static int help(void) { - _cleanup_free_ char *link = NULL; - int r; - - pager_open(arg_pager_flags); - - r = terminal_urlify_man("systemd-nspawn", "1", &link); - if (r < 0) - return log_oom(); - - static const char* const groups[] = { - NULL, - "Image", - "Execution", - "System Identity", - "Properties", - "User Namespacing", - "Networking", - "Security", - "Resources", - "Integration", - "Mounts", - "Input/Output", - "Credentials", - "Other", - }; - - Table* tables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = option_parser_get_help_table_group(groups[i], &tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths(0, tables[0], tables[1], tables[2], tables[3], - tables[4], tables[5], tables[6], tables[7], - tables[8], tables[9], tables[10], tables[11], - tables[12], tables[13]); - - printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" - "%sSpawn a command or OS in a lightweight container.%s\n\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - r = table_print_or_warn(tables[0]); - if (r < 0) - return r; - - for (size_t i = 1; i < ELEMENTSOF(groups); i++) { - printf("\n%s%s:%s\n", ansi_underline(), groups[i], ansi_normal()); - - r = table_print_or_warn(tables[i]); - if (r < 0) - return r; - } - - printf("\nSee the %s for details.\n", link); - return 0; -} - static int custom_mount_check_all(void) { FOREACH_ARRAY(m, arg_custom_mounts, arg_n_custom_mounts) if (path_equal(m->destination, "/") && arg_userns_mode != USER_NAMESPACE_NO) { @@ -614,7 +559,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-nspawn"); OPTION_COMMON_VERSION: return version(); @@ -1445,6 +1390,9 @@ static int parse_argv(int argc, char *argv[]) { OPTION_LONG("system", NULL, "Run in the system service manager scope"): arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } } diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index d290538aad..f0c92ba197 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -35,7 +35,6 @@ #include "fs-util.h" #include "glyph-util.h" #include "gpt.h" -#include "help-util.h" #include "hexdecoct.h" #include "initrd-util.h" #include "json-util.h" @@ -43,7 +42,6 @@ #include "list.h" #include "main-func.h" #include "mkdir.h" -#include "options.h" #include "ordered-set.h" #include "parse-argument.h" #include "parse-util.h" @@ -105,6 +103,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_location_end, freep); STATIC_DESTRUCTOR_REGISTER(arg_policy_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep); +COMMAND( + "systemd-pcrlock\0", + "Manage a TPM2 PCR lock.", + .man_pages = "systemd-pcrlock.8\0", + .pager_flags = &arg_pager_flags, +); + #define PCRLOCK_SECUREBOOT_POLICY_PATH "/var/lib/pcrlock.d/240-secureboot-policy.pcrlock.d/generated.pcrlock" #define PCRLOCK_FIRMWARE_CODE_EARLY_PATH "/var/lib/pcrlock.d/250-firmware-code-early.pcrlock.d/generated.pcrlock" #define PCRLOCK_FIRMWARE_CONFIG_EARLY_PATH "/var/lib/pcrlock.d/250-firmware-config-early.pcrlock.d/generated.pcrlock" @@ -5317,50 +5322,10 @@ static int verb_lock_raw(int argc, char *argv[], uintptr_t _data, void *userdata return write_pcrlock(records, NULL); } -static int help(void) { - _cleanup_(table_unrefp) Table *commands = NULL, *protections = NULL, *options = NULL; - int r; - - r = verbs_get_help_table(&commands); - if (r < 0) - return r; - - r = verbs_get_help_table_group("Protections", &protections); - if (r < 0) - return r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, commands, protections, options); - - help_cmdline("[OPTIONS...] COMMAND ..."); - help_abstract("Manage a TPM2 PCR lock."); - - help_section("Commands"); - r = table_print_or_warn(commands); - if (r < 0) - return r; - - help_section("Protections"); - r = table_print_or_warn(protections); - if (r < 0) - return r; - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference("systemd-pcrlock", "8"); - return 0; -} - VERB_NOARG(verb_unlock_simple, "unlock-raw", "Remove .pcrlock file for raw data"); -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("systemd-pcrlock"); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -5375,7 +5340,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-pcrlock"); OPTION_COMMON_VERSION: return version(); @@ -5538,6 +5503,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION('q', "quiet", NULL, "Suppress unnecessary output"): arg_quiet = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } if (auto_location) { diff --git a/src/repart/repart.c b/src/repart/repart.c index 2c454a54c7..cb48e457dd 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -61,7 +61,6 @@ #include "mount-util.h" #include "mountpoint-util.h" #include "nulstr-util.h" -#include "options.h" #include "parse-argument.h" #include "parse-helpers.h" #include "parse-util.h" @@ -88,6 +87,7 @@ #include "utf8.h" #include "varlink-io.systemd.Repart.h" #include "varlink-util.h" +#include "verbs.h" #include "xattr-util.h" /* If not configured otherwise use a minimal partition size of 10M */ @@ -248,6 +248,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_eltorito_system, freep); STATIC_DESTRUCTOR_REGISTER(arg_eltorito_volume, freep); STATIC_DESTRUCTOR_REGISTER(arg_eltorito_publisher, freep); +COMMAND( + "systemd-repart\0", + "Grow and add partitions to a partition table, and generate disk images (DDIs).", + .argspec = "[DEVICE]\0", + .man_pages = "systemd-repart.8\0", + .pager_flags = &arg_pager_flags, +); + typedef enum ProgressPhase { PROGRESS_LOADING_DEFINITIONS, PROGRESS_LOADING_TABLE, @@ -10167,62 +10175,6 @@ static int parse_join_signature(const char *p, Set **verity_settings_map) { return 0; } -static int help(void) { - _cleanup_free_ char *link = NULL; - int r; - - r = terminal_urlify_man("systemd-repart", "8", &link); - if (r < 0) - return log_oom(); - - static const char *const option_groups[] = { - "Options", - "Operation", - "Output", - "Factory Reset", - "Configuration & Image Control", - "Verity", - "Encryption", - "Partition Control", - "Copying", - "DDI Profile", - "Auxiliary Resource Generation", - "El Torito boot catalog", - }; - - Table *option_tables[ELEMENTSOF(option_groups)] = {}; - CLEANUP_ELEMENTS(option_tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(option_groups); i++) { - r = option_parser_get_help_table_group(option_groups[i], &option_tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths(0, - option_tables[0], option_tables[1], option_tables[2], - option_tables[3], option_tables[4], option_tables[5], - option_tables[6], option_tables[7], option_tables[8], - option_tables[9], option_tables[10], option_tables[11]); - - printf("%s [OPTIONS...] [DEVICE]\n" - "\n%sGrow and add partitions to a partition table, and generate disk images (DDIs).%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - for (size_t i = 0; i < ELEMENTSOF(option_groups); i++) { - printf("\n%s%s:%s\n", ansi_underline(), option_groups[i], ansi_normal()); - - r = table_print_or_warn(option_tables[i]); - if (r < 0) - return r; - } - - printf("\nSee the %s for details.\n", link); - return 0; -} - static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); @@ -10237,7 +10189,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_GROUP("Options"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-repart"); OPTION_COMMON_VERSION: return version(); @@ -10765,6 +10717,9 @@ static int parse_argv(int argc, char *argv[]) { return r; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } if (option_parser_get_n_args(&opts) > 1) diff --git a/src/run/run.c b/src/run/run.c index 1288dc0d1f..63994775a8 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -41,11 +41,9 @@ #include "format-table.h" #include "format-util.h" #include "fs-util.h" -#include "help-util.h" #include "hostname-util.h" #include "log.h" #include "main-func.h" -#include "options.h" #include "osc-context.h" #include "pager.h" #include "parse-argument.h" @@ -68,6 +66,7 @@ #include "unit-def.h" #include "unit-name.h" #include "user-util.h" +#include "verbs.h" #include "virt.h" static bool arg_ask_password = true; @@ -145,68 +144,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_background, freep); STATIC_DESTRUCTOR_REGISTER(arg_shell_prompt_prefix, freep); STATIC_DESTRUCTOR_REGISTER(arg_area, freep); -static int help(void) { - int r; - - pager_open(arg_pager_flags); - - static const char* const groups[] = { - NULL, - "Path options", - "Socket options", - "Timer options", - }; - - Table *tables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = option_parser_get_help_table_full("systemd-run", groups[i], &tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths(0, tables[0], tables[1], tables[2], tables[3]); - - help_cmdline("[OPTIONS...] COMMAND [ARGUMENTS...]"); - help_abstract("Run the specified command in a transient scope or service."); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - help_section(groups[i] ?: "Options"); - - r = table_print_or_warn(tables[i]); - if (r < 0) - return r; - } - - help_man_page_reference("systemd-run", "1"); - return 0; -} - -static int help_sudo_mode(void) { - _cleanup_(table_unrefp) Table *opts_table = NULL; - int r; - - /* NB: Let's not go overboard with short options: we try to keep a modicum of compatibility with - * sudo's short switches, hence please do not introduce new short switches unless they have a roughly - * equivalent purpose on sudo. Use long options for everything private to run0. */ - - r = option_parser_get_help_table_ns("run0", &opts_table); - if (r < 0) - return r; - - help_cmdline("[OPTIONS...] COMMAND [ARGUMENTS...]"); - help_abstract("Elevate privileges interactively."); - - help_section("Options"); - - r = table_print_or_warn(opts_table); - if (r < 0) - return r; - - help_man_page_reference("run0", "1"); - return 0; -} +COMMAND( + "systemd-run\0", + "Run the specified command in a transient scope or service.", + .argspec = "COMMAND [ARGUMENTS…]\0", + .man_pages = "systemd-run.1\0", + .option_namespace = "systemd-run", + .pager_flags = &arg_pager_flags, +); static bool become_root(void) { if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM) @@ -263,7 +208,7 @@ static int parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("systemd-run"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-run"); OPTION_COMMON_VERSION: return version(); @@ -592,6 +537,9 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } /* If we are talking to the per-user instance PolicyKit isn't going to help */ @@ -806,11 +754,24 @@ static Glyph pty_window_glyph(void) { return GLYPH_YELLOW_CIRCLE; } +COMMAND( + "run0\0", + "Elevate privileges interactively.", + .argspec = "COMMAND [ARGUMENTS…]\0", + .man_pages = "run0.1\0", + .option_namespace = "run0", + .pager_flags = &arg_pager_flags, +); + static int parse_argv_sudo_mode(int argc, char *argv[]) { int r; /* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions - * though (but limit the extension to long options). */ + * though (but limit the extension to long options). + * + * NB: Let's not go overboard with short options: we try to keep a modicum of compatibility with + * sudo's short switches, hence please do not introduce new short switches unless they have a roughly + * equivalent purpose on sudo. Use long options for everything private to run0. */ assert(argc >= 0); assert(argv); @@ -823,7 +784,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { OPTION_NAMESPACE("run0"): {} OPTION_COMMON_HELP: - return help_sudo_mode(); + return command_print_help("run0"); OPTION('V', "version", NULL, "Show package version"): return version(); @@ -836,6 +797,10 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { arg_ask_password = false; break; + OPTION_COMMON_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + OPTION_LONG("machine", "CONTAINER", "Operate on local container"): r = parse_machine_argument(opts.arg, &arg_host, &arg_transport); if (r < 0) @@ -975,6 +940,9 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { if (r < 0) return r; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } if (!arg_working_directory) { diff --git a/src/storage/storagectl.c b/src/storage/storagectl.c index b899513616..51292fc66a 100644 --- a/src/storage/storagectl.c +++ b/src/storage/storagectl.c @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "sd-varlink.h" - #include #include #include +#include "sd-json.h" +#include "sd-varlink.h" + #include "alloc-util.h" #include "ansi-color.h" #include "argv-util.h" @@ -17,12 +18,10 @@ #include "fd-util.h" #include "format-table.h" #include "format-util.h" -#include "help-util.h" #include "machine-util.h" #include "main-func.h" #include "mount-util.h" #include "namespace-util.h" -#include "options.h" #include "parse-argument.h" #include "parse-util.h" #include "path-lookup.h" @@ -46,41 +45,15 @@ static bool arg_legend = true; static bool arg_ask_password = true; static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM; -static int help(void) { - int r; +COMMAND( + "storagectl\0", + "Enumerate storage volumes and providers.", + .man_pages = "storagectl.1\0", + .option_namespace = "storagectl", + .pager_flags = &arg_pager_flags, +); - help_cmdline("[OPTIONS...] COMMAND"); - help_abstract("Enumerate storage volumes and providers."); - - _cleanup_(table_unrefp) Table *verbs = NULL; - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - _cleanup_(table_unrefp) Table *options = NULL; - r = option_parser_get_help_table_ns("storagectl", &options); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, verbs, options); - - 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; - - help_man_page_reference("storagectl", "1"); - return 0; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("storagectl"); static const char *ro_color(int ro) { if (ro > 0) @@ -395,6 +368,15 @@ static int verb_providers(int argc, char *argv[], uintptr_t data, void *userdata return 0; } +/* This COMMAND must be below all the VERBs of the main command */ +COMMAND( + "mount.storage\0", + "External helper for mount.8 to expose storage volumes.", + .man_pages = "storagectl.1\0", + .option_namespace = "mount.storage", + .pager_flags = &arg_pager_flags, +); + static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -409,7 +391,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_NAMESPACE("storagectl"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("storagectl"); OPTION_COMMON_VERSION: return version(); @@ -439,6 +421,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_COMMON_USER: arg_runtime_scope = RUNTIME_SCOPE_USER; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } *remaining_args = option_parser_get_args(&opts); @@ -448,7 +433,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { static int run_as_mount_helper(int argc, char *argv[]) { int r; - /* Implements util-linux "external helper" command line interface, as per mount(8) man page. + /* Implements util-linux "external helper" command line interface, as per mount.8 man page. * * Usage: * diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 8149e755f5..fa95932985 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -1,26 +1,26 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include +#include "sd-json.h" + #include "alloc-util.h" #include "build.h" #include "conf-files.h" #include "constants.h" #include "creds-util.h" #include "errno-util.h" -#include "format-table.h" #include "glob-util.h" #include "hashmap.h" #include "log.h" #include "main-func.h" -#include "options.h" #include "pager.h" #include "path-util.h" #include "pretty-print.h" #include "string-util.h" #include "strv.h" #include "sysctl-util.h" +#include "verbs.h" static char **arg_prefixes = NULL; static CatFlags arg_cat_flags = CAT_CONFIG_OFF; @@ -31,6 +31,14 @@ static PagerFlags arg_pager_flags = 0; STATIC_DESTRUCTOR_REGISTER(arg_prefixes, strv_freep); +COMMAND( + "systemd-sysctl\0", + "Apply kernel sysctl settings.", + .argspec = "[CONFIGURATION FILE…]\0", + .man_pages = "systemd-sysctl.service.8\0", + .pager_flags = &arg_pager_flags, +); + typedef struct SysctlOption { char *key; char *value; @@ -317,48 +325,6 @@ static int cat_config(char **files) { return cat_files(NULL, files, arg_cat_flags); } -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *commands = NULL, *options = NULL; - int r; - - r = terminal_urlify_man("systemd-sysctl.service", "8", &link); - if (r < 0) - return log_oom(); - - 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, commands, options); - - printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n" - "\n%sApplies kernel sysctl settings.%s\n" - "\n%sCommands:%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal(), - ansi_underline(), - ansi_normal()); - - r = table_print_or_warn(commands); - 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 parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); assert(argv); @@ -369,8 +335,10 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Commands"): {} + OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-sysctl"); OPTION_COMMON_VERSION: return version(); @@ -422,6 +390,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { "Treat arguments as configuration lines"): arg_inline = true; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } *remaining_args = option_parser_get_args(&opts); diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c index 0e1338140f..49a0f1b37a 100644 --- a/src/sysupdate/sysupdate.c +++ b/src/sysupdate/sysupdate.c @@ -23,14 +23,12 @@ #include "format-table.h" #include "glyph-util.h" #include "hashmap.h" -#include "help-util.h" #include "hexdecoct.h" #include "image-policy.h" #include "json-util.h" #include "loop-util.h" #include "main-func.h" #include "mount-util.h" -#include "options.h" #include "os-util.h" #include "pager.h" #include "parse-argument.h" @@ -83,6 +81,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_component, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep); +COMMAND( + "systemd-sysupdate\0", + "Update OS images.", + .man_pages = "systemd-sysupdate.8\0", + .pager_flags = &arg_pager_flags, +); + #define CONTEXT_NULL \ (Context) { \ .component_enabled = true, \ @@ -3301,46 +3306,7 @@ static int verb_enable_component(int argc, char *argv[], uintptr_t _data, void * return 0; } -static int help(void) { - _cleanup_(table_unrefp) Table *common_options = NULL, *options = NULL, *verbs = NULL; - int r; - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - r = option_parser_get_help_table(&common_options); - 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, common_options, options); - - help_cmdline("[OPTIONS…] [VERSION]"); - help_abstract("Update OS images."); - - help_section("Commands"); - r = table_print_or_warn(verbs); - if (r < 0) - return r; - - r = table_print_or_warn(common_options); - if (r < 0) - return r; - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference("systemd-sysupdate", "8"); - return 0; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("systemd-sysupdate"); static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); @@ -3354,14 +3320,11 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-sysupdate"); OPTION_COMMON_VERSION: return version(); - OPTION_GROUP("Options"): - break; - OPTION('C', "component", "NAME", "Select component to update"): if (isempty(opts.arg)) { @@ -3496,6 +3459,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); } if (arg_image && arg_root) diff --git a/src/sysupdate/updatectl.c b/src/sysupdate/updatectl.c index cd41aeb900..70902697cf 100644 --- a/src/sysupdate/updatectl.c +++ b/src/sysupdate/updatectl.c @@ -18,7 +18,6 @@ #include "hashmap.h" #include "json-util.h" #include "main-func.h" -#include "options.h" #include "pager.h" #include "polkit-agent.h" #include "pretty-print.h" @@ -39,6 +38,13 @@ static bool arg_ask_password = true; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; +COMMAND( + "updatectl\0", + "Manage system updates.", + .man_pages = "updatectl.1\0", + .pager_flags = &arg_pager_flags, +); + #define SYSUPDATE_HOST_PATH "/org/freedesktop/sysupdate1/target/host" #define SYSUPDATE_TARGET_INTERFACE "org.freedesktop.sysupdate1.Target" @@ -1635,58 +1641,7 @@ static int verb_enable(int argc, char *argv[], uintptr_t _data, void *userdata) return 0; } -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *verbs = NULL, *verbs2 = NULL, *options = NULL; - int r; - - r = terminal_urlify_man("updatectl", "1", &link); - if (r < 0) - return log_oom(); - - r = verbs_get_help_table(&verbs); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Verbs", &verbs2); - if (r < 0) - return r; - - r = option_parser_get_help_table(&options); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, verbs, verbs2, options); - - printf("%s [OPTIONS...] [VERSION]\n" - "\n%sManage system updates.%s\n" - "\n%sCommands:%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal(), - ansi_underline(), - ansi_normal()); - - r = table_print_or_warn(verbs); - if (r < 0) - return r; - r = table_print_or_warn(verbs2); - 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; -} - -VERB_COMMON_HELP_HIDDEN(help); +VERB_COMMON_HELP_AUTO_HIDDEN("updatectl"); static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); @@ -1697,6 +1652,12 @@ 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("updatectl"); + + OPTION_COMMON_VERSION: + return version(); + OPTION_LONG("reboot", NULL, "Reboot after updating to newer version"): arg_reboot = true; break; @@ -1722,17 +1683,12 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { arg_legend = false; break; - OPTION_GROUP("Verbs"): {} - OPTION_COMMON_NO_ASK_PASSWORD: arg_ask_password = false; break; - OPTION_COMMON_HELP: - return help(); - - OPTION_COMMON_VERSION: - return version(); + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } *ret_args = option_parser_get_args(&opts); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 5cf4c01964..489a2697e9 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -3,6 +3,8 @@ #include #include +#include "sd-json.h" + #include "alloc-util.h" #include "build.h" #include "chase.h" @@ -16,7 +18,6 @@ #include "extract-word.h" #include "fd-util.h" #include "fileio.h" -#include "format-table.h" #include "format-util.h" #include "fs-util.h" #include "hashmap.h" @@ -29,7 +30,6 @@ #include "loop-util.h" #include "main-func.h" #include "mount-util.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "path-util.h" @@ -114,6 +114,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); +COMMAND( + "systemd-sysusers\0", + "Create system user and group accounts.", + .argspec = "[CONFIGURATION FILE…]\0", + .man_pages = "systemd-sysusers.service.8\0", + .pager_flags = &arg_pager_flags, +); + typedef struct Context { int audit_fd; @@ -2094,46 +2102,6 @@ static int cat_config(void) { return cat_files(NULL, files, arg_cat_flags); } -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *cmds = NULL, *opts = NULL; - int r; - - r = terminal_urlify_man("systemd-sysusers.service", "8", &link); - if (r < 0) - return log_oom(); - - r = option_parser_get_help_table(&cmds); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Options", &opts); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, cmds, opts); - - printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n" - "\n%sCreates system user and group accounts.%s\n" - "\nCommands:\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - r = table_print_or_warn(cmds); - if (r < 0) - return r; - - printf("\nOptions:\n"); - - r = table_print_or_warn(opts); - if (r < 0) - return r; - - printf("\nSee the %s for details.\n", link); - return 0; -} - static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -2145,6 +2113,8 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Commands"): {} + OPTION_COMMON_CAT_CONFIG: arg_cat_flags = CAT_CONFIG_ON; break; @@ -2154,7 +2124,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-sysusers"); OPTION_COMMON_VERSION: return version(); @@ -2201,6 +2171,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_COMMON_NO_PAGER: arg_pager_flags |= PAGER_DISABLE; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } char **args = option_parser_get_args(&opts); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 2d362cb9ad..e567bd63f2 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -7,6 +7,7 @@ #include #include +#include "sd-json.h" #include "sd-path.h" #include "acl-util.h" @@ -32,7 +33,6 @@ #include "extract-word.h" #include "fd-util.h" #include "fileio.h" -#include "format-table.h" #include "format-util.h" #include "fs-util.h" #include "glob-util.h" @@ -47,7 +47,6 @@ #include "mount-util.h" #include "mountpoint-util.h" #include "offline-passwd.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -251,6 +250,14 @@ STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_label_context, mac_label_context_freep); +COMMAND( + "systemd-tmpfiles\0", + "Create, delete, and clean up files and directories.", + .argspec = "[CONFIGURATION FILE…]\0", + .man_pages = "systemd-tmpfiles.8\0", + .pager_flags = &arg_pager_flags, +); + static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = { [CREATION_NORMAL] = "Created", [CREATION_EXISTING] = "Found existing", @@ -4916,46 +4923,6 @@ static int exclude_default_prefixes(void) { return 0; } -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *cmds = NULL, *opts = NULL; - int r; - - r = terminal_urlify_man("systemd-tmpfiles", "8", &link); - if (r < 0) - return log_oom(); - - r = option_parser_get_help_table(&cmds); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Options", &opts); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, cmds, opts); - - printf("%s COMMAND [OPTIONS...] [CONFIGURATION FILE...]\n" - "\n%sCreate, delete, and clean up files and directories.%s\n" - "\nCommands:\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - r = table_print_or_warn(cmds); - if (r < 0) - return r; - - printf("\nOptions:\n"); - - r = table_print_or_warn(opts); - if (r < 0) - return r; - - printf("\nSee the %s for details.\n", link); - return 0; -} - static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -4967,6 +4934,8 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Commands"): {} + OPTION_LONG("create", NULL, "Create and adjust files and directories"): arg_operation |= OPERATION_CREATE; break; @@ -4994,7 +4963,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { break; OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-tmpfiles"); OPTION_COMMON_VERSION: return version(); @@ -5074,6 +5043,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_COMMON_NO_PAGER: arg_pager_flags |= PAGER_DISABLE; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } char **args = option_parser_get_args(&opts); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 725e90dbec..4708b976ab 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -13,6 +13,7 @@ #include "sd-daemon.h" #include "sd-event.h" #include "sd-id128.h" +#include "sd-json.h" #include "sd-varlink.h" #include "alloc-util.h" @@ -37,12 +38,10 @@ #include "fd-util.h" #include "fileio.h" #include "fork-notify.h" -#include "format-table.h" #include "format-util.h" #include "fs-util.h" #include "gpt.h" #include "group-record.h" -#include "help-util.h" #include "hexdecoct.h" #include "hostname-setup.h" #include "hostname-util.h" @@ -59,7 +58,6 @@ #include "namespace-util.h" #include "netif-util.h" #include "nsresource.h" -#include "options.h" #include "osc-context.h" #include "pager.h" #include "parse-argument.h" @@ -92,6 +90,7 @@ #include "user-record.h" #include "user-util.h" #include "utf8.h" +#include "verbs.h" #include "vmspawn-bind-volume.h" #include "vmspawn-mount.h" #include "vmspawn-qemu-config.h" @@ -233,55 +232,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_bind_user_shell, freep); STATIC_DESTRUCTOR_REGISTER(arg_bind_user_groups, strv_freep); -static int help(void) { - int r; - - pager_open(arg_pager_flags); - - static const char* const groups[] = { - NULL, - "Image", - "Host Configuration", - "Networking", - "Execution", - "System Identity", - "Properties", - "User Namespacing", - "Mounts", - "Logging", - "SSH", - "Input/Output", - "Credentials", - }; - - Table* tables[ELEMENTSOF(groups)] = {}; - CLEANUP_ELEMENTS(tables, table_unref_array_clear); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - r = option_parser_get_help_table_group(groups[i], &tables[i]); - if (r < 0) - return r; - } - - (void) table_sync_column_widths( - 0, tables[0], tables[1], tables[2], tables[3], tables[4], - tables[5], tables[6], tables[7], tables[8], tables[9], tables[10], - tables[11], tables[12]); - - help_cmdline("[OPTIONS...] [ARGUMENTS...]"); - help_abstract("Spawn a command or OS in a virtual machine."); - - for (size_t i = 0; i < ELEMENTSOF(groups); i++) { - help_section(groups[i] ?: "Options"); - - r = table_print_or_warn(tables[i]); - if (r < 0) - return r; - } - - help_man_page_reference("systemd-vmspawn", "1"); - return 0; -} +COMMAND( + "systemd-vmspawn\0", + "Spawn a command or OS in a virtual machine.", + .argspec = "[ARGUMENTS…]\0", + .man_pages = "systemd-vmspawn.1\0", + .pager_flags = &arg_pager_flags, +); static int parse_environment(void) { const char *e; @@ -354,7 +311,7 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-vmspawn"); OPTION_COMMON_VERSION: return version(); @@ -957,6 +914,9 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } /* Drop duplicate --bind-user= and --bind-user-group= entries */ diff --git a/src/vpick/vpick-tool.c b/src/vpick/vpick-tool.c index 6ce3ef944e..fb1c4d0329 100644 --- a/src/vpick/vpick-tool.c +++ b/src/vpick/vpick-tool.c @@ -2,20 +2,21 @@ #include +#include "sd-json.h" + #include "alloc-util.h" #include "architecture.h" #include "build.h" #include "format-table.h" #include "log.h" #include "main-func.h" -#include "options.h" #include "parse-util.h" #include "path-util.h" -#include "pretty-print.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "verbs.h" #include "vpick.h" typedef enum { @@ -42,6 +43,13 @@ STATIC_DESTRUCTOR_REGISTER(arg_filter_basename, freep); STATIC_DESTRUCTOR_REGISTER(arg_filter_version, freep); STATIC_DESTRUCTOR_REGISTER(arg_filter_suffix, freep); +COMMAND( + "systemd-vpick\0", + "Pick entry from versioned directory.", + .argspec = "PATH…\0", + .man_pages = "systemd-vpick.1\0", +); + static const char *print_table[_PRINT_MAX] = { [PRINT_PATH] = "path", [PRINT_FILENAME] = "filename", @@ -54,45 +62,6 @@ static const char *print_table[_PRINT_MAX] = { DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(print, Print); -static int help(void) { - _cleanup_free_ char *link = NULL; - _cleanup_(table_unrefp) Table *lookup_keys = NULL, *output = NULL; - int r; - - r = terminal_urlify_man("systemd-vpick", "1", &link); - if (r < 0) - return log_oom(); - - r = option_parser_get_help_table(&lookup_keys); - if (r < 0) - return r; - - r = option_parser_get_help_table_group("Output", &output); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, lookup_keys, output); - - printf("%s [OPTIONS...] PATH...\n" - "\n%sPick entry from versioned directory.%s\n", - program_invocation_short_name, - ansi_highlight(), - ansi_normal()); - - printf("\n%sLookup Keys:%s\n", ansi_underline(), ansi_normal()); - r = table_print_or_warn(lookup_keys); - if (r < 0) - return r; - - printf("\n%sOutput:%s\n", ansi_underline(), ansi_normal()); - r = table_print_or_warn(output); - if (r < 0) - return r; - - printf("\nSee the %s for details.\n", link); - return 0; -} - static int parse_argv(int argc, char *argv[], char ***ret_args) { int r; @@ -104,6 +73,8 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Lookup Keys"): {} + OPTION('B', "basename", "BASENAME", "Look for specified basename"): if (!filename_part_is_valid(opts.arg)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid basename string: %s", opts.arg); @@ -172,7 +143,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_GROUP("Output"): {} OPTION_COMMON_HELP: - return help(); + return command_print_help("systemd-vpick"); OPTION_COMMON_VERSION: return version(); @@ -208,6 +179,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { SET_FLAG(arg_flags, PICK_RESOLVE, r); break; + + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(SD_JSON_FORMAT_OFF); } if (arg_print < 0) diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index b53741aa25..8da538ef12 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -11,16 +11,22 @@ export SYSTEMD_PAGER=cat # A smoke test for the introspection code INTROSPECTABLE=( + bootctl busctl coredumpctl homectl hostnamectl importctl + journalctl localectl + loginctl + machinectl networkctl oomctl portablectl resolvectl + run0 + storagectl systemd-ac-power systemd-analyze systemd-ask-password @@ -35,6 +41,7 @@ INTROSPECTABLE=( systemd-cgtop systemd-clonesetup systemd-creds + systemd-cryptenroll systemd-cryptsetup systemd-delta systemd-detect-virt @@ -47,22 +54,30 @@ INTROSPECTABLE=( systemd-hwdb systemd-id128 systemd-imds + systemd-imdsd systemd-inhibit systemd-journal-gatewayd systemd-journal-remote systemd-journal-upload systemd-keyutil + systemd-machine-id-setup + systemd-measure systemd-modules-load + systemd-mstack systemd-mute-console systemd-network-generator systemd-networkd-wait-online systemd-notify + systemd-nspawn systemd-oomd systemd-path systemd-pcrextend + systemd-pcrlock systemd-pty-forward systemd-random-seed + systemd-repart systemd-report + systemd-run systemd-sbsign systemd-sleep systemd-socket-activate @@ -72,14 +87,21 @@ INTROSPECTABLE=( systemd-storage-block systemd-storage-fs systemd-storagetm + systemd-sysctl systemd-sysinstall + systemd-sysupdate + systemd-sysusers + systemd-tmpfiles systemd-tpm2-clear systemd-tpm2-setup systemd-tty-ask-password-agent systemd-update-done systemd-validatefs systemd-veritysetup + systemd-vmspawn + systemd-vpick timedatectl + updatectl userdbctl varlinkctl ) @@ -103,20 +125,29 @@ for i in "${INTROSPECTABLE[@]}"; do fi done -# systemd-hwdb defines verbs, check that they are described +# check verbs and multicall binaries if command -v systemd-hwdb >/dev/null; then systemd-hwdb --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | sort == ["help", "query", "update"]' fi -# systemd-id128 defines many verbs, check that some are described -systemd-id128 --introspect-cli | jq -e \ - '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' +resolvectl --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["resolvconf", "resolvectl", "systemd-resolve"]' + +storagectl --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["mount.storage", "storagectl"]' -# systemd-clonesetup defines verbs, check that they are described systemd-clonesetup --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | sort == ["add", "remove"]' -# resolvectl is a multicall binary, check that both commands are described -resolvectl --introspect-cli | jq -e \ - '[.commands[].names[0]] | sort == ["resolvconf", "resolvectl", "systemd-resolve"]' +systemd-dissect --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["mount.ddi", "systemd-dissect"]' + +systemd-id128 --introspect-cli | jq -e \ + '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' + +systemd-mstack --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["mount.mstack", "systemd-mstack"]' + +systemd-run --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["run0", "systemd-run"]'