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 @@
+
+
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"]'