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