Final batch of conversions to COMMAND and additions of --introspect-cli (#43558)

This commit is contained in:
Yu Watanabe
2026-08-29 04:26:12 +09:00
committed by GitHub
19 changed files with 125 additions and 395 deletions
+1 -1
View File
@@ -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];
+10 -28
View File
@@ -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);
+20 -26
View File
@@ -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
View File
@@ -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;
+10 -17
View File
@@ -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)
+13 -24
View File
@@ -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)
+1 -33
View File
@@ -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;
-4
View File
@@ -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);
-74
View File
@@ -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);
}
-10
View File
@@ -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);
-1
View File
@@ -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
View File
@@ -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;
-19
View File
@@ -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[],
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+12 -20
View File
@@ -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);
-1
View File
@@ -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