Convert remaining udev progs to option macros (#41856)

This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-04-29 17:23:18 +02:00
committed by GitHub
24 changed files with 840 additions and 1045 deletions
+5 -8
View File
@@ -31,7 +31,6 @@
#include "process-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "tpm2-pcr.h"
#include "tpm2-util.h"
@@ -579,14 +578,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
char **args = option_parser_get_args(&opts);
if (option_parser_get_n_args(&opts) > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many arguments, refusing.");
if (strv_length(args) > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many arguments, refusing.");
if (args[0])
r = parse_path_argument(args[0], false, &arg_node);
const char *arg = option_parser_get_arg(&opts, 0);
if (arg)
r = parse_path_argument(arg, false, &arg_node);
else if (!wipe_requested())
r = determine_default_node();
else
+1 -2
View File
@@ -181,8 +181,7 @@ static int parse_argv(int argc, char *argv[]) {
"%s expects exactly one argument (the mount point).",
program_invocation_short_name);
arg_target = option_parser_get_args(&opts)[0];
arg_target = option_parser_get_arg(&opts, 0);
return 1;
}
+1 -1
View File
@@ -1420,7 +1420,7 @@ static int parse_argv(int argc, char *argv[]) {
* the old container user functionality. To maintain backwards compatibility
* with the space-separated form (--user NAME), if the next opts.arg does not look
* like an option, interpret it as a user name. */
const char *t = option_parser_next_arg(&opts);
const char *t = option_parser_peek_next_arg(&opts);
if (t && t[0] != '-') {
opts.arg = option_parser_consume_next_arg(&opts);
log_warning("--user NAME is deprecated, use --uid=NAME instead.");
+1 -1
View File
@@ -188,7 +188,7 @@ static int help_sudo_mode(void) {
* 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_full("run0", /* group= */ NULL, &opts_table);
r = option_parser_get_help_table_ns("run0", &opts_table);
if (r < 0)
return r;
+10 -2
View File
@@ -344,7 +344,7 @@ int option_parse(
return r;
}
char* option_parser_next_arg(const OptionParser *state) {
char* option_parser_peek_next_arg(const OptionParser *state) {
/* Peek at the next argument, whatever it is (option or position arg).
* May return NULL. */
@@ -360,7 +360,7 @@ char* option_parser_consume_next_arg(OptionParser *state) {
* so we won't try to interpret it as an option.
* May return NULL. */
char *t = option_parser_next_arg(state);
char *t = option_parser_peek_next_arg(state);
if (t)
shift_arg(state->argv, state->positional_offset++, state->optind++);
return t;
@@ -388,6 +388,14 @@ size_t option_parser_get_n_args(const OptionParser *state) {
return state->argc - state->positional_offset;
}
char* option_parser_get_arg(const OptionParser *state, size_t i) {
assert(state->optind > 0);
assert(state->state == OPTION_PARSER_DONE);
assert(state->positional_offset <= state->argc);
return (size_t) (state->argc - state->positional_offset) > i ? state->argv[state->positional_offset + i] : NULL;
}
char* option_get_synopsis(const Option *opt, const char *joiner, bool show_metavar) {
assert(opt);
assert(!(opt->flags & (OPTION_NAMESPACE_MARKER |
+14 -3
View File
@@ -150,10 +150,13 @@ typedef struct Option {
"(file, provider:PROVIDER)")
/* A form used in udev code for compatibility. -V is accepted but not documented. */
#define OPTION_COMMON_VERSION_WITH_HIDDEN_V \
OPTION_COMMON_VERSION: {} \
#define OPTION_COMMON_VERSION_WITH_HIDDEN_V \
OPTION_COMMON_VERSION: {} \
OPTION_SHORT('V', NULL, /* help= */ NULL)
#define OPTION_COMMON_RESOLVE_NAMES \
OPTION('N', "resolve-names", "MODE", \
"When to resolve users and groups (early, late, or never)")
/* This is magically mapped to the beginning and end of the section */
extern const Option __start_SYSTEMD_OPTIONS[];
@@ -221,11 +224,17 @@ int option_parse(
break; \
} else
char* option_parser_next_arg(const OptionParser *state);
/* Those helpers are used *during* option parsing and allow looking at or taking the next item in
* the argv array, either an option or a positional parameter. */
char* option_parser_peek_next_arg(const OptionParser *state);
char* option_parser_consume_next_arg(OptionParser *state);
/* Those helpers are used *after* option parsing and return the positional arguments (and unparsed
* options in case option parsing was stopped early, e.g. via "--"). */
char** option_parser_get_args(const OptionParser *state);
size_t option_parser_get_n_args(const OptionParser *state);
char* option_parser_get_arg(const OptionParser *state, size_t i);
char* option_get_synopsis(const Option *opt, const char *joiner, bool show_metavar);
int _option_parser_get_help_table_full(
@@ -236,6 +245,8 @@ int _option_parser_get_help_table_full(
Table **ret);
#define option_parser_get_help_table_full(namespace, group, ret) \
_option_parser_get_help_table_full(ALIGN_PTR(__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) \
+12 -7
View File
@@ -58,7 +58,12 @@ static void test_option_parse_one(
ASSERT_TRUE(strv_equal(args, remaining));
ASSERT_STREQ(argv[0], saved_argv0);
ASSERT_EQ(option_parser_get_n_args(&opts), strv_length(remaining));
size_t l = strv_length(remaining);
ASSERT_EQ(option_parser_get_n_args(&opts), l);
ASSERT_STREQ(option_parser_get_arg(&opts, 0), l > 0 ? remaining[0] : NULL);
ASSERT_STREQ(option_parser_get_arg(&opts, 1), l > 1 ? remaining[1] : NULL);
ASSERT_STREQ(option_parser_get_arg(&opts, 2), l > 2 ? remaining[2] : NULL);
ASSERT_STREQ(option_parser_get_arg(&opts, 3), l > 3 ? remaining[3] : NULL);
}
static void test_option_invalid_one(
@@ -1331,7 +1336,7 @@ TEST(option_optional_arg_consume) {
/* --user without arg: next arg is positional (doesn't start with -).
* The option parser returns NULL for the arg. The caller would then
* use option_parser_next_arg/consume_next_arg to grab it. */
* use option_parser_peek_next_arg/consume_next_arg to grab it. */
{
char **argv = STRV_MAKE("arg0", "--user", "someuser", "pos1");
int argc = strv_length(argv);
@@ -1341,7 +1346,7 @@ TEST(option_optional_arg_consume) {
ASSERT_OK_POSITIVE(option_parse(options, options + 3, &opts));
ASSERT_STREQ(opts.opt->long_code, "user");
ASSERT_NULL(opts.arg);
ASSERT_STREQ(option_parser_next_arg(&opts), "someuser");
ASSERT_STREQ(option_parser_peek_next_arg(&opts), "someuser");
ASSERT_STREQ(option_parser_consume_next_arg(&opts), "someuser");
ASSERT_EQ(option_parse(options, options + 3, &opts), 0);
@@ -1361,7 +1366,7 @@ TEST(option_optional_arg_consume) {
ASSERT_OK_POSITIVE(option_parse(options, options + 3, &opts));
ASSERT_STREQ(opts.opt->long_code, "user");
ASSERT_NULL(opts.arg);
ASSERT_NULL(option_parser_next_arg(&opts));
ASSERT_NULL(option_parser_peek_next_arg(&opts));
ASSERT_NULL(option_parser_consume_next_arg(&opts));
ASSERT_EQ(option_parse(options, options + 3, &opts), 0);
@@ -1381,12 +1386,12 @@ TEST(option_optional_arg_consume) {
ASSERT_OK_POSITIVE(option_parse(options, options + 3, &opts));
ASSERT_STREQ(opts.opt->long_code, "user");
ASSERT_NULL(opts.arg);
ASSERT_STREQ(option_parser_next_arg(&opts), "-u");
ASSERT_STREQ(option_parser_peek_next_arg(&opts), "-u");
ASSERT_OK_POSITIVE(option_parse(options, options + 3, &opts));
ASSERT_STREQ(opts.opt->long_code, "uid");
ASSERT_STREQ(opts.arg, "nobody");
ASSERT_NULL(option_parser_next_arg(&opts));
ASSERT_NULL(option_parser_peek_next_arg(&opts));
ASSERT_NULL(option_parser_consume_next_arg(&opts));
ASSERT_EQ(option_parse(options, options + 3, &opts), 0);
@@ -1413,7 +1418,7 @@ TEST(option_optional_arg_consume) {
const char *arg = opts.arg;
if (!arg) {
const char *t = option_parser_next_arg(&opts);
const char *t = option_parser_peek_next_arg(&opts);
if (t && t[0] != '-')
arg = option_parser_consume_next_arg(&opts);
}
+15 -22
View File
@@ -10,7 +10,6 @@
#endif
#include <fcntl.h>
#include <getopt.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -26,6 +25,7 @@
#include "fd-util.h"
#include "initrd-util.h"
#include "gpt.h"
#include "options.h"
#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
@@ -506,13 +506,6 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
int64_t offset = 0;
int r;
static const struct option options[] = {
{ "offset", required_argument, NULL, 'o' },
{ "hint", required_argument, NULL, 'H' },
{ "noraid", no_argument, NULL, 'R' },
{}
};
r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return log_device_debug_errno(dev, r, "blkid not available: %m");
@@ -522,32 +515,32 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
if (!pr)
return log_device_debug_errno(dev, errno_or_else(ENOMEM), "Failed to create blkid prober: %m");
for (;;) {
int option;
OptionParser opts = { argc, argv, .namespace = "udev-builtin-blkid" };
option = getopt_long(argc, argv, "o:H:R", options, NULL);
if (option == -1)
break;
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
switch (option) {
case 'H':
OPTION_NAMESPACE("udev-builtin-blkid"): {}
OPTION('H', "hint", "HINT", NULL):
errno = 0;
r = sym_blkid_probe_set_hint(pr, optarg, 0);
r = sym_blkid_probe_set_hint(pr, opts.arg, 0);
if (r < 0)
return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", optarg);
return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", opts.arg);
break;
case 'o':
r = safe_atoi64(optarg, &offset);
OPTION('o', "offset", "OFFSET", NULL):
r = safe_atoi64(opts.arg, &offset);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", optarg);
return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", opts.arg);
if (offset < 0)
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid offset %"PRIi64".", offset);
break;
case 'R':
OPTION('R', "noraid", NULL, NULL):
noraid = true;
break;
}
}
r = sd_device_get_devname(dev, &devnode);
if (r < 0)
+18 -26
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fnmatch.h>
#include <getopt.h>
#include <stdio.h>
#include "sd-hwdb.h"
@@ -9,6 +8,7 @@
#include "alloc-util.h"
#include "device-util.h"
#include "hwdb-util.h"
#include "options.h"
#include "parse-util.h"
#include "string-util.h"
#include "udev-builtin.h"
@@ -128,13 +128,6 @@ next:
}
static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
static const struct option options[] = {
{ "filter", required_argument, NULL, 'f' },
{ "device", required_argument, NULL, 'd' },
{ "subsystem", required_argument, NULL, 's' },
{ "lookup-prefix", required_argument, NULL, 'p' },
{}
};
const char *filter = NULL, *device = NULL, *subsystem = NULL, *prefix = NULL;
_cleanup_(sd_device_unrefp) sd_device *srcdev = NULL;
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
@@ -143,35 +136,34 @@ static int builtin_hwdb(UdevEvent *event, int argc, char *argv[]) {
if (!hwdb)
return -EINVAL;
for (;;) {
int option;
OptionParser opts = { argc, argv, .namespace = "udev-builtin-hwdb" };
option = getopt_long(argc, argv, "f:d:s:p:", options, NULL);
if (option == -1)
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
OPTION_NAMESPACE("udev-builtin-hwdb"): {}
OPTION('f', "filter", "FILTER", NULL):
filter = opts.arg;
break;
switch (option) {
case 'f':
filter = optarg;
OPTION('d', "device", "DEVICE", NULL):
device = opts.arg;
break;
case 'd':
device = optarg;
OPTION('s', "subsystem", "SUBSYSTEM", NULL):
subsystem = opts.arg;
break;
case 's':
subsystem = optarg;
break;
case 'p':
prefix = optarg;
OPTION('p', "lookup-prefix", "PREFIX", NULL):
prefix = opts.arg;
break;
}
}
/* query a specific key given as argument */
if (argv[optind]) {
r = udev_builtin_hwdb_lookup(event, prefix, argv[optind], filter);
char *modalias = option_parser_get_arg(&opts, 0);
if (modalias) {
r = udev_builtin_hwdb_lookup(event, prefix, modalias, filter);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
if (r == 0)
+58 -76
View File
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdlib.h>
#include "conf-parser.h"
@@ -8,10 +7,12 @@
#include "daemon-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-table.h"
#include "hashmap.h"
#include "help-util.h"
#include "limits-util.h"
#include "options.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "serialize.h"
#include "signal-util.h"
@@ -149,110 +150,91 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("systemd-udevd.service", "8", &link);
r = option_parser_get_help_table_ns("udevd", &options);
if (r < 0)
return log_oom();
return r;
printf("%s [OPTIONS...]\n\n"
"Rule-based manager for device events and files.\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -d --daemon Detach and run in the background\n"
" -D --debug Enable debug output\n"
" -c --children-max=INT Set maximum number of workers\n"
" -e --exec-delay=SECONDS Seconds to wait before executing RUN=\n"
" -t --event-timeout=SECONDS Seconds to wait before terminating an event\n"
" -N --resolve-names=early|late|never\n"
" When to resolve users and groups\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
link);
help_cmdline("[OPTIONS...]");
help_abstract("Rule-based manager for device events and files.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("systemd-udevd.service", "8");
return 0;
}
static int parse_argv(int argc, char *argv[], UdevConfig *config) {
enum {
ARG_TIMEOUT_SIGNAL,
};
static const struct option options[] = {
{ "daemon", no_argument, NULL, 'd' },
{ "debug", no_argument, NULL, 'D' },
{ "children-max", required_argument, NULL, 'c' },
{ "exec-delay", required_argument, NULL, 'e' },
{ "event-timeout", required_argument, NULL, 't' },
{ "resolve-names", required_argument, NULL, 'N' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "timeout-signal", required_argument, NULL, ARG_TIMEOUT_SIGNAL },
{}
};
int c, r;
int r;
assert(argc >= 0);
assert(argv);
assert(config);
while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) {
OptionParser opts = { argc, argv, OPTION_PARSER_NORMAL, "udevd" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'd':
OPTION_NAMESPACE("udevd"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
printf("%s\n", GIT_VERSION);
return 0;
OPTION('d', "daemon", NULL, "Detach and run in the background"):
arg_daemonize = true;
break;
case 'c':
r = safe_atou(optarg, &config->children_max);
if (r < 0)
log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", optarg);
break;
case 'e':
r = parse_sec(optarg, &config->exec_delay_usec);
if (r < 0)
log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", optarg);
break;
case ARG_TIMEOUT_SIGNAL:
r = signal_from_string(optarg);
if (r <= 0)
log_warning_errno(r, "Failed to parse --timeout-signal= value '%s', ignoring: %m", optarg);
else
config->timeout_signal = r;
break;
case 't':
r = parse_sec(optarg, &config->timeout_usec);
if (r < 0)
log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", optarg);
break;
case 'D':
OPTION('D', "debug", NULL, "Enable debug output"):
arg_debug = true;
config->log_level = LOG_DEBUG;
break;
case 'N': {
ResolveNameTiming t;
t = resolve_name_timing_from_string(optarg);
OPTION('c', "children-max", "INT", "Set maximum number of workers"):
r = safe_atou(opts.arg, &config->children_max);
if (r < 0)
log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", opts.arg);
break;
OPTION('e', "exec-delay", "SECONDS", "Seconds to wait before executing RUN="):
r = parse_sec(opts.arg, &config->exec_delay_usec);
if (r < 0)
log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", opts.arg);
break;
OPTION('t', "event-timeout", "SECONDS", "Seconds to wait before terminating an event"):
r = parse_sec(opts.arg, &config->timeout_usec);
if (r < 0)
log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", opts.arg);
break;
OPTION_COMMON_RESOLVE_NAMES: {
ResolveNameTiming t = resolve_name_timing_from_string(opts.arg);
if (t < 0)
log_warning("Invalid --resolve-names= value '%s', ignoring.", optarg);
log_warning("Invalid --resolve-names= value '%s', ignoring.", opts.arg);
else
config->resolve_name_timing = t;
break;
}
case 'h':
return help();
case 'V':
printf("%s\n", GIT_VERSION);
return 0;
case '?':
return -EINVAL;
default:
assert_not_reached();
OPTION_LONG("timeout-signal", "SIGNAL", "Signal used when terminating an event"):
r = signal_from_string(opts.arg);
if (r <= 0)
log_warning_errno(r, "Failed to parse --timeout-signal= value '%s', ignoring: %m", opts.arg);
else
config->timeout_signal = r;
break;
}
}
return 1;
}
+40 -48
View File
@@ -1,14 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include "alloc-util.h"
#include "conf-files.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "parse-argument.h"
#include "pretty-print.h"
#include "static-destruct.h"
#include "strv.h"
#include "udevadm.h"
#include "udevadm-util.h"
@@ -19,83 +19,75 @@ static bool arg_config = false;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("udevadm", "8", &link);
r = option_parser_get_help_table_ns("udevadm-cat", &options);
if (r < 0)
return log_oom();
return r;
printf("%s cat [OPTIONS] [FILE...]\n"
"\n%sShow udev rules files.%s\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --tldr Skip comments and empty lines\n"
" --config Show udev.conf rather than udev rules files\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
help_cmdline("cat [OPTIONS...] [FILE...]");
help_abstract("Show udev rules files.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_ROOT = 0x100,
ARG_TLDR,
ARG_CONFIG,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "root", required_argument, NULL, ARG_ROOT },
{ "tldr", no_argument, NULL, ARG_TLDR },
{ "config", no_argument, NULL, ARG_CONFIG },
{}
};
int r, c;
static int parse_argv(int argc, char *argv[], char ***remaining_args) {
int r;
assert(argc >= 0);
assert(argv);
assert(remaining_args);
while ((c = getopt_long(argc, argv, "hVN:", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-cat" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'h':
OPTION_NAMESPACE("udevadm-cat"): {}
OPTION_COMMON_HELP:
return help();
case 'V':
OPTION_COMMON_VERSION_WITH_HIDDEN_V:
return print_version();
case ARG_ROOT:
r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
OPTION_LONG("root", "PATH",
"Operate on an alternate filesystem root"):
r = parse_path_argument(opts.arg, /* suppress_root= */ true, &arg_root);
if (r < 0)
return r;
break;
case ARG_TLDR:
OPTION_LONG("tldr", NULL,
"Skip comments and empty lines"):
arg_cat_flags = CAT_TLDR;
break;
case ARG_CONFIG:
OPTION_LONG("config", NULL,
"Show udev.conf rather than udev rules files"):
arg_config = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (arg_config && optind < argc)
if (arg_config && option_parser_get_n_args(&opts) > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Combination of --config and FILEs is not supported.");
*remaining_args = option_parser_get_args(&opts);
return 1;
}
int verb_cat_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
char **args = NULL;
int r;
r = parse_argv(argc, argv);
r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -107,7 +99,7 @@ int verb_cat_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
CLEANUP_ARRAY(files, n_files, conf_file_free_array);
r = search_rules_files(strv_skip(argv, optind), arg_root, &files, &n_files);
r = search_rules_files(args, arg_root, &files, &n_files);
if (r < 0)
return r;
+56 -85
View File
@@ -1,12 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include "creds-util.h"
#include "errno-util.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "static-destruct.h"
@@ -47,151 +48,121 @@ static bool arg_has_control_commands(void) {
}
static int help(void) {
printf("%s control OPTION\n\n"
"Control the udev daemon.\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -e --exit Instruct the daemon to cleanup and exit\n"
" -l --log-level=LEVEL Set the udev log level for the daemon\n"
" -s --stop-exec-queue Do not execute events, queue only\n"
" -S --start-exec-queue Execute events, flush queue\n"
" -R --reload Reload rules and databases\n"
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
" --ping Wait for udev to respond to a ping message\n"
" --trace=BOOL Enable/disable trace logging\n"
" --revert Revert previously set configurations\n"
" -t --timeout=SECONDS Maximum time to block for a reply\n"
" --load-credentials Load udev rules from credentials\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-control", &options);
if (r < 0)
return r;
help_cmdline("control OPTION");
help_abstract("Control the udev daemon.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_PING = 0x100,
ARG_TRACE,
ARG_REVERT,
ARG_LOAD_CREDENTIALS,
};
static const struct option options[] = {
{ "exit", no_argument, NULL, 'e' },
{ "log-level", required_argument, NULL, 'l' },
{ "log-priority", required_argument, NULL, 'l' }, /* for backward compatibility */
{ "stop-exec-queue", no_argument, NULL, 's' },
{ "start-exec-queue", no_argument, NULL, 'S' },
{ "reload", no_argument, NULL, 'R' },
{ "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
{ "property", required_argument, NULL, 'p' },
{ "env", required_argument, NULL, 'p' }, /* alias for -p */
{ "children-max", required_argument, NULL, 'm' },
{ "ping", no_argument, NULL, ARG_PING },
{ "trace", required_argument, NULL, ARG_TRACE },
{ "revert", no_argument, NULL, ARG_REVERT },
{ "timeout", required_argument, NULL, 't' },
{ "load-credentials", no_argument, NULL, ARG_LOAD_CREDENTIALS },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
};
int c, r;
int r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-control" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'e':
OPTION_NAMESPACE("udevadm-control"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('e', "exit", NULL, "Instruct the daemon to cleanup and exit"):
arg_exit = true;
break;
case 'l':
arg_log_level = log_level_from_string(optarg);
OPTION_LONG("log-priority", "LEVEL", NULL): {} /* backward compat alias for --log-level */
OPTION('l', "log-level", "LEVEL", "Set the udev log level for the daemon"):
arg_log_level = log_level_from_string(opts.arg);
if (arg_log_level < 0)
return log_error_errno(arg_log_level, "Failed to parse log level '%s': %m", optarg);
return log_error_errno(arg_log_level, "Failed to parse log level '%s': %m", opts.arg);
break;
case 's':
OPTION('s', "stop-exec-queue", NULL, "Do not execute events, queue only"):
arg_start_exec_queue = false;
break;
case 'S':
OPTION('S', "start-exec-queue", NULL, "Execute events, flush queue"):
arg_start_exec_queue = true;
break;
case 'R':
OPTION_LONG("reload-rules", NULL, NULL): {} /* hidden alias for -R */
OPTION('R', "reload", NULL, "Reload rules and databases"):
arg_reload = true;
break;
case 'p':
if (!strchr(optarg, '='))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", optarg);
OPTION_LONG("env", "KEY=VALUE", NULL): {} /* hidden alias for -p */
OPTION('p', "property", "KEY=VALUE", "Set a global property for all events"):
if (!strchr(opts.arg, '='))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", opts.arg);
r = strv_extend(&arg_env, optarg);
r = strv_extend(&arg_env, opts.arg);
if (r < 0)
return log_error_errno(r, "Failed to extend environment: %m");
break;
case 'm': {
OPTION('m', "children-max", "N", "Maximum number of children"): {
unsigned i;
r = safe_atou(optarg, &i);
r = safe_atou(opts.arg, &i);
if (r < 0)
return log_error_errno(r, "Failed to parse maximum number of children '%s': %m", optarg);
return log_error_errno(r, "Failed to parse maximum number of children '%s': %m", opts.arg);
arg_max_children = i;
break;
}
case ARG_PING:
OPTION_LONG("ping", NULL, "Wait for udev to respond to a ping message"):
arg_ping = true;
break;
case ARG_TRACE:
r = parse_boolean_argument("--trace=", optarg, NULL);
OPTION_LONG("trace", "BOOL", "Enable/disable trace logging"):
r = parse_boolean_argument("--trace=", opts.arg, NULL);
if (r < 0)
return r;
arg_trace = r;
break;
case ARG_REVERT:
OPTION_LONG("revert", NULL, "Revert previously set configurations"):
arg_revert = true;
break;
case 't':
r = parse_sec(optarg, &arg_timeout);
OPTION('t', "timeout", "SECONDS", "Maximum time to block for a reply"):
r = parse_sec(opts.arg, &arg_timeout);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
return log_error_errno(r, "Failed to parse timeout value '%s': %m", opts.arg);
break;
case ARG_LOAD_CREDENTIALS:
OPTION_LONG("load-credentials", NULL, "Load udev rules from credentials"):
arg_load_credentials = true;
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (!arg_has_control_commands() && !arg_load_credentials)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No control command option is specified.");
if (optind < argc)
if (option_parser_get_n_args(&opts) > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Extraneous argument: %s", argv[optind]);
"This subprogram takes no positional arguments.");
return 1;
}
+47 -46
View File
@@ -1,10 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <getopt.h>
#include <stdio.h>
#include "format-table.h"
#include "help-util.h"
#include "hwdb-util.h"
#include "log.h"
#include "options.h"
#include "udevadm.h"
static const char *arg_test = NULL;
@@ -14,65 +16,64 @@ static bool arg_update = false;
static bool arg_strict = false;
static int help(void) {
printf("%s hwdb [OPTIONS]\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -u --update Update the hardware database\n"
" -s --strict When updating, return non-zero exit value on any parsing error\n"
" --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
" -t --test=MODALIAS Query database and print result\n"
" -r --root=PATH Alternative root path in the filesystem\n\n"
"NOTE:\n"
"The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n"
"Please use systemd-hwdb instead.\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-hwdb", &options);
if (r < 0)
return r;
help_cmdline("hwdb [OPTIONS]");
help_abstract("Update or query the hardware database.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
printf("\nNOTE:\n"
"The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n"
"Please use systemd-hwdb instead.\n");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_USR = 0x100,
};
assert(argc >= 0);
assert(argv);
static const struct option options[] = {
{ "update", no_argument, NULL, 'u' },
{ "usr", no_argument, NULL, ARG_USR },
{ "strict", no_argument, NULL, 's' },
{ "test", required_argument, NULL, 't' },
{ "root", required_argument, NULL, 'r' },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
};
OptionParser opts = { argc, argv, .namespace = "udevadm-hwdb" };
int c;
while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0)
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'u':
OPTION_NAMESPACE("udevadm-hwdb"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('u', "update", NULL, "Update the hardware database"):
arg_update = true;
break;
case ARG_USR:
arg_hwdb_bin_dir = UDEVLIBEXECDIR;
break;
case 's':
OPTION('s', "strict", NULL,
"When updating, return non-zero exit value on any parsing error"):
arg_strict = true;
break;
case 't':
arg_test = optarg;
OPTION_LONG("usr", NULL,
"Generate in " UDEVLIBEXECDIR " instead of /etc/udev"):
arg_hwdb_bin_dir = UDEVLIBEXECDIR;
break;
case 'r':
arg_root = optarg;
OPTION('t', "test", "MODALIAS", "Query database and print result"):
arg_test = opts.arg;
break;
OPTION('r', "root", "PATH", "Alternative root path in the filesystem"):
arg_root = opts.arg;
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
return 1;
+114 -180
View File
@@ -2,7 +2,6 @@
#include <ctype.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@@ -20,7 +19,10 @@
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-table.h"
#include "glyph-util.h"
#include "help-util.h"
#include "options.h"
#include "pager.h"
#include "parse-argument.h"
#include "sort-util.h"
@@ -800,51 +802,21 @@ static int query_device(QueryType query, sd_device* device) {
}
static int help(void) {
printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n"
"Query sysfs or the udev database.\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -q --query=TYPE Query device information:\n"
" name Name of device node\n"
" symlink Pointing to node\n"
" path sysfs device path\n"
" property The device properties\n"
" all All values\n"
" --property=NAME Show only properties by this name\n"
" --value When showing properties, print only their values\n"
" -p --path=SYSPATH sysfs device path used for query or attribute walk\n"
" -n --name=NAME Node or symlink name used for query or attribute walk\n"
" -r --root Prepend dev directory to path names\n"
" -a --attribute-walk Print all key matches walking along the chain\n"
" of parent devices\n"
" -t --tree Show tree of devices\n"
" -d --device-id-of-file=FILE Print major:minor of device containing this file\n"
" -x --export Export key/value pairs\n"
" -P --export-prefix Export the key name with a prefix\n"
" -e --export-db Export the content of the udev database\n"
" -c --cleanup-db Clean up the udev database\n"
" -w --wait-for-initialization[=SECONDS]\n"
" Wait for device to be initialized\n"
" --no-pager Do not pipe output into a pager\n"
" --json=pretty|short|off Generate JSON output\n"
" --subsystem-match=SUBSYSTEM\n"
" Query devices matching a subsystem\n"
" --subsystem-nomatch=SUBSYSTEM\n"
" Query devices not matching a subsystem\n"
" --attr-match=FILE[=VALUE]\n"
" Query devices that match an attribute\n"
" --attr-nomatch=FILE[=VALUE]\n"
" Query devices that do not match an attribute\n"
" --property-match=KEY=VALUE\n"
" Query devices with matching properties\n"
" --tag-match=TAG Query devices with a matching tag\n"
" --sysname-match=NAME Query devices with this /sys path\n"
" --name-match=NAME Query devices with this /dev name\n"
" --parent-match=NAME Query devices with this parent device\n"
" --initialized-match Query devices that are already initialized\n"
" --initialized-nomatch Query devices that are not initialized yet\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-info", &options);
if (r < 0)
return r;
help_cmdline("info [OPTIONS] [DEVPATH|FILE]");
help_abstract("Query sysfs or the udev database.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
@@ -1006,90 +978,64 @@ static int print_tree(sd_device* below) {
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_PROPERTY = 0x100,
ARG_VALUE,
ARG_NO_PAGER,
ARG_JSON,
ARG_SUBSYSTEM_MATCH,
ARG_SUBSYSTEM_NOMATCH,
ARG_ATTR_MATCH,
ARG_ATTR_NOMATCH,
ARG_PROPERTY_MATCH,
ARG_TAG_MATCH,
ARG_SYSNAME_MATCH,
ARG_NAME_MATCH,
ARG_PARENT_MATCH,
ARG_INITIALIZED_MATCH,
ARG_INITIALIZED_NOMATCH,
};
static const struct option options[] = {
{ "attribute-walk", no_argument, NULL, 'a' },
{ "tree", no_argument, NULL, 't' },
{ "cleanup-db", no_argument, NULL, 'c' },
{ "device-id-of-file", required_argument, NULL, 'd' },
{ "export", no_argument, NULL, 'x' },
{ "export-db", no_argument, NULL, 'e' },
{ "export-prefix", required_argument, NULL, 'P' },
{ "help", no_argument, NULL, 'h' },
{ "name", required_argument, NULL, 'n' },
{ "path", required_argument, NULL, 'p' },
{ "property", required_argument, NULL, ARG_PROPERTY },
{ "query", required_argument, NULL, 'q' },
{ "root", no_argument, NULL, 'r' },
{ "value", no_argument, NULL, ARG_VALUE },
{ "version", no_argument, NULL, 'V' },
{ "wait-for-initialization", optional_argument, NULL, 'w' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "json", required_argument, NULL, ARG_JSON },
{ "subsystem-match", required_argument, NULL, ARG_SUBSYSTEM_MATCH },
{ "subsystem-nomatch", required_argument, NULL, ARG_SUBSYSTEM_NOMATCH },
{ "attr-match", required_argument, NULL, ARG_ATTR_MATCH },
{ "attr-nomatch", required_argument, NULL, ARG_ATTR_NOMATCH },
{ "property-match", required_argument, NULL, ARG_PROPERTY_MATCH },
{ "tag-match", required_argument, NULL, ARG_TAG_MATCH },
{ "sysname-match", required_argument, NULL, ARG_SYSNAME_MATCH },
{ "name-match", required_argument, NULL, ARG_NAME_MATCH },
{ "parent-match", required_argument, NULL, ARG_PARENT_MATCH },
{ "initialized-match", no_argument, NULL, ARG_INITIALIZED_MATCH },
{ "initialized-nomatch", no_argument, NULL, ARG_INITIALIZED_NOMATCH },
{}
};
int c, r;
int r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "atced:n:p:q:rxP:w::Vh", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-info" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case ARG_PROPERTY:
OPTION_NAMESPACE("udevadm-info"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('q', "query", "TYPE", "Query device information:"): {}
OPTION_HELP_VERBATIM(" name", "- name of device node"): {}
OPTION_HELP_VERBATIM(" symlink", "- pointing to node"): {}
OPTION_HELP_VERBATIM(" path", "- sysfs device path"): {}
OPTION_HELP_VERBATIM(" property", "- the device properties"): {}
OPTION_HELP_VERBATIM(" all", "- all values"):
arg_query = query_type_from_string(opts.arg);
if (arg_query < 0) {
if (streq(opts.arg, "env")) /* deprecated */
arg_query = QUERY_PROPERTY;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown query type '%s'", opts.arg);
}
break;
OPTION_LONG("property", "NAME", "Show only properties by this name"):
/* Make sure that if the empty property list was specified, we won't show any
properties. */
if (isempty(optarg) && !arg_properties) {
if (isempty(opts.arg) && !arg_properties) {
arg_properties = new0(char*, 1);
if (!arg_properties)
return log_oom();
} else {
r = strv_split_and_extend(&arg_properties, optarg, ",", true);
r = strv_split_and_extend(&arg_properties, opts.arg, ",", true);
if (r < 0)
return log_oom();
}
break;
case ARG_VALUE:
OPTION_LONG("value", NULL,
"When showing properties, print only their values"):
arg_value = true;
break;
case 'n':
case 'p': {
const char *prefix = c == 'n' ? "/dev/" : "/sys/";
OPTION('p', "path", "SYSPATH", "sysfs device path used for query or attribute walk"): {} /* fall through */
OPTION('n', "name", "NAME", "Node or symlink name used for query or attribute walk"): {
const char *prefix = opts.opt->short_code == 'n' ? "/dev/" : "/sys/";
char *path;
path = path_join(path_startswith(optarg, prefix) ? NULL : prefix, optarg);
path = path_join(path_startswith(opts.arg, prefix) ? NULL : prefix, opts.arg);
if (!path)
return log_oom();
@@ -1099,159 +1045,147 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case 'q':
arg_query = query_type_from_string(optarg);
if (arg_query < 0) {
if (streq(optarg, "env")) /* deprecated */
arg_query = QUERY_PROPERTY;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown query type '%s'", optarg);
}
break;
case 'r':
OPTION('r', "root", NULL, "Prepend dev directory to path names"):
arg_root = true;
break;
case 'd':
OPTION('a', "attribute-walk", NULL,
"Print all key matches walking along the chain of parent devices"):
arg_action_type = ACTION_ATTRIBUTE_WALK;
break;
OPTION('t', "tree", NULL, "Show tree of devices"):
arg_action_type = ACTION_TREE;
break;
OPTION('d', "device-id-of-file", "FILE",
"Print major:minor of device containing this file"):
arg_action_type = ACTION_DEVICE_ID_FILE;
r = free_and_strdup(&arg_name, optarg);
r = free_and_strdup(&arg_name, opts.arg);
if (r < 0)
return log_oom();
break;
case 'a':
arg_action_type = ACTION_ATTRIBUTE_WALK;
OPTION('x', "export", NULL, "Export key/value pairs"):
arg_export = true;
break;
case 't':
arg_action_type = ACTION_TREE;
OPTION('P', "export-prefix", "NAME", "Export the key name with a prefix"):
arg_export = true;
arg_export_prefix = opts.arg;
break;
case 'e':
OPTION('e', "export-db", NULL, "Export the content of the udev database"):
arg_action_type = ACTION_EXPORT;
break;
case 'c':
OPTION('c', "cleanup-db", NULL, "Clean up the udev database"):
arg_action_type = ACTION_CLEANUP_DB;
break;
case 'x':
arg_export = true;
break;
case 'P':
arg_export = true;
arg_export_prefix = optarg;
break;
case 'w':
if (optarg) {
r = parse_sec(optarg, &arg_wait_for_initialization_timeout);
OPTION_FULL(OPTION_OPTIONAL_ARG, 'w', "wait-for-initialization", "SECS",
"Wait for device to be initialized"):
if (opts.arg) {
r = parse_sec(opts.arg, &arg_wait_for_initialization_timeout);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout value: %m");
} else
arg_wait_for_initialization_timeout = USEC_INFINITY;
break;
case 'V':
return print_version();
case 'h':
return help();
case ARG_NO_PAGER:
OPTION_COMMON_NO_PAGER:
arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
OPTION_COMMON_JSON:
r = parse_json_argument(opts.arg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case ARG_SUBSYSTEM_MATCH:
r = strv_extend(&arg_subsystem_match, optarg);
OPTION_LONG("subsystem-match", "SUBSYSTEM",
"Query devices matching a subsystem"):
r = strv_extend(&arg_subsystem_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_SUBSYSTEM_NOMATCH:
r = strv_extend(&arg_subsystem_nomatch, optarg);
OPTION_LONG("subsystem-nomatch", "SUBSYSTEM",
"Query devices not matching a subsystem"):
r = strv_extend(&arg_subsystem_nomatch, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_ATTR_MATCH:
if (!strchr(optarg, '='))
OPTION_LONG("attr-match", "FILE[=VALUE]",
"Query devices that match an attribute"):
if (!strchr(opts.arg, '='))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Expected <ATTR>=<value> instead of '%s'", optarg);
"Expected <ATTR>=<value> instead of '%s'", opts.arg);
r = strv_extend(&arg_attr_match, optarg);
r = strv_extend(&arg_attr_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_ATTR_NOMATCH:
if (!strchr(optarg, '='))
OPTION_LONG("attr-nomatch", "FILE[=VALUE]",
"Query devices that do not match an attribute"):
if (!strchr(opts.arg, '='))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Expected <ATTR>=<value> instead of '%s'", optarg);
"Expected <ATTR>=<value> instead of '%s'", opts.arg);
r = strv_extend(&arg_attr_nomatch, optarg);
r = strv_extend(&arg_attr_nomatch, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_PROPERTY_MATCH:
if (!strchr(optarg, '='))
OPTION_LONG("property-match", "KEY=VALUE",
"Query devices with matching properties"):
if (!strchr(opts.arg, '='))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Expected <PROPERTY>=<value> instead of '%s'", optarg);
"Expected <PROPERTY>=<value> instead of '%s'", opts.arg);
r = strv_extend(&arg_property_match, optarg);
r = strv_extend(&arg_property_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_TAG_MATCH:
r = strv_extend(&arg_tag_match, optarg);
OPTION_LONG("tag-match", "TAG", "Query devices with a matching tag"):
r = strv_extend(&arg_tag_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_SYSNAME_MATCH:
r = strv_extend(&arg_sysname_match, optarg);
OPTION_LONG("sysname-match", "NAME", "Query devices with this /sys path"):
r = strv_extend(&arg_sysname_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_NAME_MATCH:
r = strv_extend(&arg_name_match, optarg);
OPTION_LONG("name-match", "NAME", "Query devices with this /dev name"):
r = strv_extend(&arg_name_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_PARENT_MATCH:
r = strv_extend(&arg_parent_match, optarg);
OPTION_LONG("parent-match", "NAME", "Query devices with this parent device"):
r = strv_extend(&arg_parent_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_INITIALIZED_MATCH:
OPTION_LONG("initialized-match", NULL,
"Query devices that are already initialized"):
arg_initialized_match = MATCH_INITIALIZED_YES;
break;
case ARG_INITIALIZED_NOMATCH:
OPTION_LONG("initialized-nomatch", NULL,
"Query devices that are not initialized yet"):
arg_initialized_match = MATCH_INITIALIZED_NO;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
r = strv_extend_strv(&arg_devices, argv + optind, /* filter_duplicates= */ false);
r = strv_extend_strv(&arg_devices, option_parser_get_args(&opts), /* filter_duplicates= */ false);
if (r < 0)
return log_error_errno(r, "Failed to build argument list: %m");
+35 -56
View File
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -9,11 +8,14 @@
#include "device-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "format-table.h"
#include "glyph-util.h"
#include "hash-funcs.h"
#include "help-util.h"
#include "lock-util.h"
#include "options.h"
#include "path-util.h"
#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "signal-util.h"
#include "sort-util.h"
@@ -33,70 +35,52 @@ STATIC_DESTRUCTOR_REGISTER(arg_backing, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("udevadm", "8", &link);
r = option_parser_get_help_table_ns("udevadm-lock", &options);
if (r < 0)
return log_oom();
return r;
printf("%s [OPTIONS...] COMMAND\n"
"%s [OPTIONS...] --print\n"
"\n%sLock a block device and run a command.%s\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -d --device=DEVICE Block device to lock\n"
" -b --backing=FILE File whose backing block device to lock\n"
" -t --timeout=SECS Block at most the specified time waiting for lock\n"
" -p --print Only show which block device the lock would be taken on\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
help_cmdline("lock [OPTIONS...] COMMAND");
help_cmdline("lock [OPTIONS...] --print");
help_abstract("Lock a block device and run a command.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "device", required_argument, NULL, 'd' },
{ "backing", required_argument, NULL, 'b' },
{ "timeout", required_argument, NULL, 't' },
{ "print", no_argument, NULL, 'p' },
{}
};
int c, r;
int r;
assert(argc >= 0);
assert(argv);
/* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long()
* that checks for GNU extensions in optstring ('-' or '+' at the beginning). */
optind = 0;
while ((c = getopt_long(argc, argv, arg_print ? "hVd:b:t:p" : "+hVd:b:t:p", options, NULL)) >= 0)
OptionParser opts = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION, "udevadm-lock" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'h':
OPTION_NAMESPACE("udevadm-lock"): {}
OPTION_COMMON_HELP:
return help();
case 'V':
OPTION('V', "version", NULL, "Show package version"):
return print_version();
case 'd':
case 'b': {
OPTION('d', "device", "DEVICE", "Block device to lock"): {} /* fall through */
OPTION('b', "backing", "FILE", "File whose backing block device to lock"): {
_cleanup_free_ char *s = NULL;
char ***l = c == 'd' ? &arg_devices : &arg_backing;
char ***l = opts.opt->short_code == 'd' ? &arg_devices : &arg_backing;
r = path_make_absolute_cwd(optarg, &s);
r = path_make_absolute_cwd(opts.arg, &s);
if (r < 0)
return log_error_errno(r, "Failed to make path '%s' absolute: %m", optarg);
return log_error_errno(r, "Failed to make path '%s' absolute: %m", opts.arg);
path_simplify(s);
@@ -107,31 +91,26 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case 't':
r = parse_sec(optarg, &arg_timeout_usec);
OPTION('t', "timeout", "SECS", "Block at most the specified time waiting for lock"):
r = parse_sec(opts.arg, &arg_timeout_usec);
if (r < 0)
return log_error_errno(r, "Failed to parse --timeout= parameter: %s", optarg);
return log_error_errno(r, "Failed to parse --timeout= parameter: %s", opts.arg);
break;
case 'p':
OPTION('p', "print", NULL, "Only show which block device the lock would be taken on"):
arg_print = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
char **args = option_parser_get_args(&opts);
if (arg_print) {
if (optind != argc)
if (!strv_isempty(args))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No arguments expected.");
} else {
if (optind + 1 > argc)
if (strv_isempty(args))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too few arguments, command to execute.");
arg_cmdline = strv_copy(argv + optind);
arg_cmdline = strv_copy(args);
if (!arg_cmdline)
return log_oom();
}
+47 -44
View File
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include "sd-device.h"
#include "sd-event.h"
@@ -9,8 +7,11 @@
#include "device-monitor-private.h"
#include "device-private.h"
#include "device-util.h"
#include "format-table.h"
#include "format-util.h"
#include "hashmap.h"
#include "help-util.h"
#include "options.h"
#include "set.h"
#include "static-destruct.h"
#include "string-util.h"
@@ -99,60 +100,70 @@ static int setup_monitor(MonitorNetlinkGroup sender, sd_event *event, sd_device_
}
static int help(void) {
printf("%s monitor [OPTIONS]\n\n"
"Listen to kernel and udev events.\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -p --property Print the event properties\n"
" -k --kernel Print kernel uevents\n"
" -u --udev Print udev events\n"
" -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
" -t --tag-match=TAG Filter events by tag\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-monitor", &options);
if (r < 0)
return r;
help_cmdline("monitor [OPTIONS]");
help_abstract("Listen to kernel and udev events.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "property", no_argument, NULL, 'p' },
{ "environment", no_argument, NULL, 'e' }, /* alias for -p */
{ "kernel", no_argument, NULL, 'k' },
{ "udev", no_argument, NULL, 'u' },
{ "subsystem-match", required_argument, NULL, 's' },
{ "tag-match", required_argument, NULL, 't' },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
};
int r;
int r, c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-monitor" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'p':
case 'e':
OPTION_NAMESPACE("udevadm-monitor"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('e', "environment", NULL, /* help= */ NULL): {} /* hidden alias for -p */
OPTION('p', "property", NULL, "Print the event properties"):
arg_show_property = true;
break;
case 'k':
OPTION('k', "kernel", NULL, "Print kernel uevents"):
arg_print_kernel = true;
break;
case 'u':
OPTION('u', "udev", NULL, "Print udev events"):
arg_print_udev = true;
break;
case 's': {
OPTION('s', "subsystem-match", "SUBSYSTEM[/DEVTYPE]",
"Filter events by subsystem"): {
_cleanup_free_ char *subsystem = NULL, *devtype = NULL;
const char *slash;
slash = strchr(optarg, '/');
slash = strchr(opts.arg, '/');
if (slash) {
devtype = strdup(slash + 1);
if (!devtype)
return log_oom();
subsystem = strndup(optarg, slash - optarg);
subsystem = strndup(opts.arg, slash - opts.arg);
} else
subsystem = strdup(optarg);
subsystem = strdup(opts.arg);
if (!subsystem)
return log_oom();
@@ -165,20 +176,12 @@ static int parse_argv(int argc, char *argv[]) {
TAKE_PTR(devtype);
break;
}
case 't':
r = set_put_strdup(&arg_tag_filter, optarg);
OPTION('t', "tag-match", "TAG", "Filter events by tag"):
r = set_put_strdup(&arg_tag_filter, opts.arg);
if (r < 0)
return log_oom();
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (!arg_print_kernel && !arg_print_udev) {
+47 -42
View File
@@ -4,7 +4,6 @@
* Copyright © 2009 Scott James Remnant <scott@netsplit.com>
*/
#include <getopt.h>
#include <unistd.h>
#include "sd-bus.h"
@@ -14,6 +13,9 @@
#include "alloc-util.h"
#include "bus-util.h"
#include "format-table.h"
#include "help-util.h"
#include "options.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
@@ -28,60 +30,63 @@ static usec_t arg_timeout_usec = 120 * USEC_PER_SEC;
static const char *arg_exists = NULL;
static int help(void) {
printf("%s settle [OPTIONS]\n\n"
"Wait for pending udev events.\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -t --timeout=SEC Maximum time to wait for events\n"
" -E --exit-if-exists=FILE Stop waiting if file exists\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-settle", &options);
if (r < 0)
return r;
help_cmdline("settle [OPTIONS]");
help_abstract("Wait for pending udev events.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "timeout", required_argument, NULL, 't' },
{ "exit-if-exists", required_argument, NULL, 'E' },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{ "seq-start", required_argument, NULL, 's' }, /* removed */
{ "seq-end", required_argument, NULL, 'e' }, /* removed */
{ "quiet", no_argument, NULL, 'q' }, /* removed */
{}
};
int r;
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) {
OptionParser opts = { argc, argv, .namespace = "udevadm-settle" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 't':
r = parse_sec(optarg, &arg_timeout_usec);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
break;
case 'E':
if (!path_is_valid(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid path: %s", optarg);
arg_exists = optarg;
break;
case 'V':
return print_version();
case 'h':
OPTION_NAMESPACE("udevadm-settle"): {}
OPTION_COMMON_HELP:
return help();
case 's':
case 'e':
case 'q':
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('t', "timeout", "SEC", "Maximum time to wait for events"):
r = parse_sec(opts.arg, &arg_timeout_usec);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout value '%s': %m", opts.arg);
break;
OPTION('E', "exit-if-exists", "FILE", "Stop waiting if file exists"):
if (!path_is_valid(opts.arg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid path: %s", opts.arg);
arg_exists = opts.arg;
break;
OPTION('s', "seq-start", "ARG", NULL): {} /* removed */
OPTION('e', "seq-end", "ARG", NULL): {} /* removed */
OPTION('q', "quiet", NULL, NULL): /* removed */
return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
"Option -%c no longer supported.",
c);
case '?':
return -EINVAL;
default:
assert_not_reached();
opts.opt->short_code);
}
}
return 1;
}
+38 -32
View File
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include "device-private.h"
#include "device-util.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "udev-builtin.h"
#include "udevadm.h"
#include "udevadm-util.h"
@@ -15,51 +15,57 @@ static const char *arg_command = NULL;
static const char *arg_syspath = NULL;
static int help(void) {
printf("%s test-builtin [OPTIONS] COMMAND DEVPATH\n\n"
"Test a built-in command.\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -a --action=ACTION|help Set action string\n"
"\nCommands:\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-test-builtin", &options);
if (r < 0)
return r;
help_cmdline("test-builtin [OPTIONS] COMMAND DEVPATH");
help_abstract("Test a built-in command.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_section("Commands:");
udev_builtin_list();
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "action", required_argument, NULL, 'a' },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
};
int r;
int r, c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "a:Vh", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-test-builtin" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'a':
r = parse_device_action(optarg, &arg_action);
OPTION_NAMESPACE("udevadm-test-builtin"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('a', "action", "ACTION|help", "Set action string"):
r = parse_device_action(opts.arg, &arg_action);
if (r <= 0)
return r;
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (argc != optind + 2)
if (option_parser_get_n_args(&opts) != 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected two arguments: command string and device path.");
arg_command = ASSERT_PTR(argv[optind]);
arg_syspath = ASSERT_PTR(argv[optind+1]);
char **args = option_parser_get_args(&opts);
arg_command = ASSERT_PTR(args[0]);
arg_syspath = ASSERT_PTR(args[1]);
return 1;
}
+45 -44
View File
@@ -3,7 +3,6 @@
* Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
*/
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
@@ -12,7 +11,10 @@
#include "alloc-util.h"
#include "device-private.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "parse-argument.h"
#include "static-destruct.h"
#include "strv.h"
@@ -33,55 +35,59 @@ static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
STATIC_DESTRUCTOR_REGISTER(arg_extra_rules_dir, strv_freep);
static int help(void) {
_cleanup_(table_unrefp) Table *options = NULL;
int r;
printf("%s test [OPTIONS] DEVPATH\n\n"
"Test an event run.\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -a --action=ACTION|help Set action string\n"
" -N --resolve-names=early|late|never When to resolve names\n"
" -D --extra-rules-dir=DIR Also load rules from the directory\n"
" -v --verbose Show verbose logs\n"
" --json=pretty|short|off Generate JSON output\n",
program_invocation_short_name);
r = option_parser_get_help_table_ns("udevadm-test", &options);
if (r < 0)
return r;
help_cmdline("test [OPTIONS] DEVPATH");
help_abstract("Test an event run.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_JSON = 0x100,
};
int r;
static const struct option options[] = {
{ "action", required_argument, NULL, 'a' },
{ "resolve-names", required_argument, NULL, 'N' },
{ "extra-rules-dir", required_argument, NULL, 'D' },
{ "verbose", no_argument, NULL, 'v' },
{ "json", required_argument, NULL, ARG_JSON },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{}
};
assert(argc >= 0);
assert(argv);
int r, c;
OptionParser opts = { argc, argv, .namespace = "udevadm-test" };
while ((c = getopt_long(argc, argv, "a:N:D:vVh", options, NULL)) >= 0)
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'a':
r = parse_device_action(optarg, &arg_action);
OPTION_NAMESPACE("udevadm-test"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('a', "action", "ACTION|help", "Set action string"):
r = parse_device_action(opts.arg, &arg_action);
if (r <= 0)
return r;
break;
case 'N':
r = parse_resolve_name_timing(optarg, &arg_resolve_name_timing);
OPTION_COMMON_RESOLVE_NAMES:
r = parse_resolve_name_timing(opts.arg, &arg_resolve_name_timing);
if (r <= 0)
return r;
break;
case 'D': {
OPTION('D', "extra-rules-dir", "DIR", "Also load rules from the directory"): {
_cleanup_free_ char *p = NULL;
r = parse_path_argument(optarg, /* suppress_root= */ false, &p);
r = parse_path_argument(opts.arg, /* suppress_root= */ false, &p);
if (r < 0)
return r;
@@ -90,25 +96,20 @@ static int parse_argv(int argc, char *argv[]) {
return log_oom();
break;
}
case 'v':
OPTION('v', "verbose", NULL, "Show verbose logs"):
arg_verbose = true;
break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
OPTION_COMMON_JSON:
r = parse_json_argument(opts.arg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
arg_syspath = argv[optind];
char **args = option_parser_get_args(&opts);
arg_syspath = args[0];
if (!arg_syspath)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "syspath parameter missing.");
+95 -137
View File
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include "sd-device.h"
@@ -10,7 +9,10 @@
#include "device-enumerator-private.h"
#include "device-private.h"
#include "device-util.h"
#include "format-table.h"
#include "help-util.h"
#include "id128-util.h"
#include "options.h"
#include "set.h"
#include "static-destruct.h"
#include "string-table.h"
@@ -320,214 +322,170 @@ static int setup_matches(sd_device_enumerator *e) {
}
static int help(void) {
printf("%s trigger [OPTIONS] DEVPATH\n\n"
"Request events from the kernel.\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -v --verbose Print the list of devices while running\n"
" -n --dry-run Do not actually trigger the events\n"
" -q --quiet Suppress error logging in triggering events\n"
" -t --type= Type of events to trigger\n"
" devices sysfs devices (default)\n"
" subsystems sysfs subsystems and drivers\n"
" all sysfs devices, subsystems, and drivers\n"
" -c --action=ACTION|help Event action value, default is \"change\"\n"
" -s --subsystem-match=SUBSYSTEM Trigger devices from a matching subsystem\n"
" -S --subsystem-nomatch=SUBSYSTEM Exclude devices from a matching subsystem\n"
" -a --attr-match=FILE[=VALUE] Trigger devices with a matching attribute\n"
" -A --attr-nomatch=FILE[=VALUE] Exclude devices with a matching attribute\n"
" -p --property-match=KEY=VALUE Trigger devices with a matching property\n"
" -g --tag-match=TAG Trigger devices with a matching tag\n"
" -y --sysname-match=NAME Trigger devices with this /sys path\n"
" --name-match=NAME Trigger devices with this /dev name\n"
" -b --parent-match=NAME Trigger devices with that parent device\n"
" --include-parents Trigger parent devices of found devices\n"
" --initialized-match Trigger devices that are already initialized\n"
" --initialized-nomatch Trigger devices that are not initialized yet\n"
" -w --settle Wait for the triggered events to complete\n"
" --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
" before triggering uevents\n"
" --uuid Print synthetic uevent UUID\n"
" --prioritized-subsystem=SUBSYSTEM[,SUBSYSTEM…]\n"
" Trigger devices from a matching subsystem first\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-trigger", &options);
if (r < 0)
return r;
help_cmdline("trigger [OPTIONS] DEVPATH");
help_abstract("Request events from the kernel.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_NAME = 0x100,
ARG_PING,
ARG_UUID,
ARG_PRIORITIZED_SUBSYSTEM,
ARG_INITIALIZED_MATCH,
ARG_INITIALIZED_NOMATCH,
ARG_INCLUDE_PARENTS,
};
static const struct option options[] = {
{ "verbose", no_argument, NULL, 'v' },
{ "dry-run", no_argument, NULL, 'n' },
{ "quiet", no_argument, NULL, 'q' },
{ "type", required_argument, NULL, 't' },
{ "action", required_argument, NULL, 'c' },
{ "subsystem-match", required_argument, NULL, 's' },
{ "subsystem-nomatch", required_argument, NULL, 'S' },
{ "attr-match", required_argument, NULL, 'a' },
{ "attr-nomatch", required_argument, NULL, 'A' },
{ "property-match", required_argument, NULL, 'p' },
{ "tag-match", required_argument, NULL, 'g' },
{ "sysname-match", required_argument, NULL, 'y' },
{ "name-match", required_argument, NULL, ARG_NAME },
{ "parent-match", required_argument, NULL, 'b' },
{ "include-parents", no_argument, NULL, ARG_INCLUDE_PARENTS },
{ "initialized-match", no_argument, NULL, ARG_INITIALIZED_MATCH },
{ "initialized-nomatch", no_argument, NULL, ARG_INITIALIZED_NOMATCH },
{ "settle", no_argument, NULL, 'w' },
{ "wait-daemon", optional_argument, NULL, ARG_PING },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{ "uuid", no_argument, NULL, ARG_UUID },
{ "prioritized-subsystem", required_argument, NULL, ARG_PRIORITIZED_SUBSYSTEM },
{}
};
int c, r;
int r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "vnqt:c:s:S:a:A:p:g:y:b:wVh", options, NULL)) >= 0) {
OptionParser opts = { argc, argv, .namespace = "udevadm-trigger" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'v':
OPTION_NAMESPACE("udevadm-trigger"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('v', "verbose", NULL, "Print the list of devices while running"):
arg_verbose = true;
break;
case 'n':
OPTION('n', "dry-run", NULL, "Do not actually trigger the events"):
arg_dry_run = true;
break;
case 'q':
OPTION('q', "quiet", NULL, "Suppress error logging in triggering events"):
arg_quiet = true;
break;
case 't':
arg_scan_type = scan_type_from_string(optarg);
OPTION('t', "type", "TYPE", "Type of sysfs events to trigger:"): {}
OPTION_HELP_VERBATIM(" devices", "- devices (default)"): {}
OPTION_HELP_VERBATIM(" subsystems", "- subsystems and drivers"): {}
OPTION_HELP_VERBATIM(" all", "- devices, subsystems, and drivers"):
arg_scan_type = scan_type_from_string(opts.arg);
if (arg_scan_type < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", opts.arg);
break;
case 'c':
r = parse_device_action(optarg, &arg_action);
OPTION('c', "action", "ACTION|help", "Event action value, default is \"change\""):
r = parse_device_action(opts.arg, &arg_action);
if (r <= 0)
return r;
break;
case 's':
r = strv_extend(&arg_subsystem_match, optarg);
OPTION('s', "subsystem-match", "SUBSYSTEM",
"Trigger devices from a matching subsystem"):
r = strv_extend(&arg_subsystem_match, opts.arg);
if (r < 0)
return log_oom();
break;
case 'S':
r = strv_extend(&arg_subsystem_nomatch, optarg);
OPTION('S', "subsystem-nomatch", "SUBSYSTEM",
"Exclude devices from a matching subsystem"):
r = strv_extend(&arg_subsystem_nomatch, opts.arg);
if (r < 0)
return log_oom();
break;
case 'a':
r = strv_extend(&arg_attr_match, optarg);
OPTION('a', "attr-match", "FILE[=VALUE]",
"Trigger devices with a matching attribute"):
r = strv_extend(&arg_attr_match, opts.arg);
if (r < 0)
return log_oom();
break;
case 'A':
r = strv_extend(&arg_attr_nomatch, optarg);
OPTION('A', "attr-nomatch", "FILE[=VALUE]",
"Exclude devices with a matching attribute"):
r = strv_extend(&arg_attr_nomatch, opts.arg);
if (r < 0)
return log_oom();
break;
case 'p':
r = strv_extend(&arg_property_match, optarg);
OPTION('p', "property-match", "KEY=VALUE",
"Trigger devices with a matching property"):
r = strv_extend(&arg_property_match, opts.arg);
if (r < 0)
return log_oom();
break;
case 'g':
r = strv_extend(&arg_tag_match, optarg);
OPTION('g', "tag-match", "TAG", "Trigger devices with a matching tag"):
r = strv_extend(&arg_tag_match, opts.arg);
if (r < 0)
return log_oom();
break;
case 'y':
r = strv_extend(&arg_sysname_match, optarg);
OPTION('y', "sysname-match", "NAME", "Trigger devices with this /sys path"):
r = strv_extend(&arg_sysname_match, opts.arg);
if (r < 0)
return log_oom();
break;
case 'b':
r = strv_extend(&arg_parent_match, optarg);
OPTION_LONG("name-match", "NAME", "Trigger devices with this /dev name"):
r = strv_extend(&arg_name_match, opts.arg);
if (r < 0)
return log_oom();
break;
case ARG_INCLUDE_PARENTS:
OPTION('b', "parent-match", "NAME", "Trigger devices with that parent device"):
r = strv_extend(&arg_parent_match, opts.arg);
if (r < 0)
return log_oom();
break;
OPTION_LONG("include-parents", NULL, "Trigger parent devices of found devices"):
arg_include_parents = true;
break;
case 'w':
arg_settle = true;
break;
case ARG_NAME:
r = strv_extend(&arg_name_match, optarg);
if (r < 0)
return log_oom();
break;
case ARG_PING:
arg_ping = true;
if (optarg) {
r = parse_sec(optarg, &arg_ping_timeout_usec);
if (r < 0)
log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
}
break;
case ARG_UUID:
arg_uuid = true;
break;
case ARG_PRIORITIZED_SUBSYSTEM:
r = strv_split_and_extend(&arg_prioritized_subsystems, optarg, ",", /* filter_duplicates= */ false);
if (r < 0)
return log_oom();
break;
case ARG_INITIALIZED_MATCH:
OPTION_LONG("initialized-match", NULL,
"Trigger devices that are already initialized"):
arg_initialized_match = MATCH_INITIALIZED_YES;
break;
case ARG_INITIALIZED_NOMATCH:
OPTION_LONG("initialized-nomatch", NULL,
"Trigger devices that are not initialized yet"):
arg_initialized_match = MATCH_INITIALIZED_NO;
break;
case 'V':
return print_version();
OPTION('w', "settle", NULL, "Wait for the triggered events to complete"):
arg_settle = true;
break;
case 'h':
return help();
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "wait-daemon", "SECONDS",
"Wait for udevd daemon to be initialized before triggering uevents"):
arg_ping = true;
if (opts.arg) {
r = parse_sec(opts.arg, &arg_ping_timeout_usec);
if (r < 0)
log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", opts.arg);
}
break;
case '?':
return -EINVAL;
OPTION_LONG("uuid", NULL, "Print synthetic uevent UUID"):
arg_uuid = true;
break;
default:
assert_not_reached();
OPTION_LONG("prioritized-subsystem", "SUBSYSTEM[,SUBSYSTEM…]",
"Trigger devices from a matching subsystem first"):
r = strv_split_and_extend(&arg_prioritized_subsystems, opts.arg, ",", /* filter_duplicates= */ false);
if (r < 0)
return log_oom();
break;
}
}
r = strv_extend_strv(&arg_devices, argv + optind, /* filter_duplicates= */ false);
r = strv_extend_strv(&arg_devices, option_parser_get_args(&opts), /* filter_duplicates= */ false);
if (r < 0)
return log_error_errno(r, "Failed to build argument list: %m");
+1 -1
View File
@@ -144,7 +144,7 @@ int parse_resolve_name_timing(const char *str, ResolveNameTiming *ret) {
if (streq(str, "help"))
return DUMP_STRING_TABLE(resolve_name_timing, ResolveNameTiming, _RESOLVE_NAME_TIMING_MAX);
ResolveNameTiming v = resolve_name_timing_from_string(optarg);
ResolveNameTiming v = resolve_name_timing_from_string(str);
if (v < 0)
return log_error_errno(v, "--resolve-names= must be 'early', 'late', or 'never'.");
+39 -52
View File
@@ -1,16 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "conf-files.h"
#include "errno-util.h"
#include "format-table.h"
#include "help-util.h"
#include "log.h"
#include "options.h"
#include "parse-argument.h"
#include "pretty-print.h"
#include "static-destruct.h"
#include "strv.h"
#include "udev-rules.h"
#include "udevadm.h"
#include "udevadm-util.h"
@@ -23,81 +24,66 @@ static bool arg_style = true;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("udevadm", "8", &link);
r = option_parser_get_help_table_ns("udevadm-verify", &options);
if (r < 0)
return log_oom();
return r;
printf("%s verify [OPTIONS] [FILE...]\n"
"\n%sVerify udev rules files.%s\n\n"
" -h --help Show this help\n"
" -V --version Show package version\n"
" -N --resolve-names=early|late|never When to resolve names\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --no-summary Do not show summary\n"
" --no-style Ignore style issues\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
help_cmdline("verify [OPTIONS] [FILE...]");
help_abstract("Verify udev rules files.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_ROOT = 0x100,
ARG_NO_SUMMARY,
ARG_NO_STYLE,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "resolve-names", required_argument, NULL, 'N' },
{ "root", required_argument, NULL, ARG_ROOT },
{ "no-summary", no_argument, NULL, ARG_NO_SUMMARY },
{ "no-style", no_argument, NULL, ARG_NO_STYLE },
{}
};
int r, c;
static int parse_argv(int argc, char *argv[], char ***remaining_args) {
int r;
assert(argc >= 0);
assert(argv);
assert(remaining_args);
while ((c = getopt_long(argc, argv, "hVN:", options, NULL)) >= 0)
OptionParser opts = { argc, argv, .namespace = "udevadm-verify" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'h':
OPTION_NAMESPACE("udevadm-verify"): {}
OPTION_COMMON_HELP:
return help();
case 'V':
OPTION('V', "version", NULL, "Show package version"):
return print_version();
case 'N':
r = parse_resolve_name_timing(optarg, &arg_resolve_name_timing);
OPTION_COMMON_RESOLVE_NAMES:
r = parse_resolve_name_timing(opts.arg, &arg_resolve_name_timing);
if (r <= 0)
return r;
break;
case ARG_ROOT:
r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
OPTION_LONG("root", "PATH", "Operate on an alternate filesystem root"):
r = parse_path_argument(opts.arg, /* suppress_root= */ true, &arg_root);
if (r < 0)
return r;
break;
case ARG_NO_SUMMARY:
OPTION_LONG("no-summary", NULL, "Do not show summary"):
arg_summary = false;
break;
case ARG_NO_STYLE:
OPTION_LONG("no-style", NULL, "Ignore style issues"):
arg_style = false;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
*remaining_args = option_parser_get_args(&opts);
return 1;
}
@@ -158,9 +144,10 @@ static int verify_rules(UdevRules *rules, ConfFile * const *files, size_t n_file
int verb_verify_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(udev_rules_freep) UdevRules *rules = NULL;
char **args = NULL;
int r;
r = parse_argv(argc, argv);
r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -173,7 +160,7 @@ int verb_verify_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
CLEANUP_ARRAY(files, n_files, conf_file_free_array);
r = search_rules_files(strv_skip(argv, optind), arg_root, &files, &n_files);
r = search_rules_files(args, arg_root, &files, &n_files);
if (r < 0)
return r;
+43 -49
View File
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
@@ -10,7 +8,10 @@
#include "device-monitor-private.h"
#include "device-util.h"
#include "event-util.h"
#include "format-table.h"
#include "fs-util.h"
#include "help-util.h"
#include "options.h"
#include "parse-util.h"
#include "path-util.h"
#include "static-destruct.h"
@@ -297,79 +298,72 @@ static int setup_periodic_timer(sd_event *event) {
}
static int help(void) {
printf("%s wait [OPTIONS] DEVICE [DEVICE…]\n\n"
"Wait for devices or device symlinks being created.\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -t --timeout=SEC Maximum time to wait for the device\n"
" --initialized=BOOL Wait for devices being initialized by systemd-udevd\n"
" --removed Wait for devices being removed\n"
" --settle Also wait for all queued events being processed\n",
program_invocation_short_name);
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevadm-wait", &options);
if (r < 0)
return r;
help_cmdline("wait [OPTIONS] DEVICE [DEVICE…]");
help_abstract("Wait for devices or device symlinks being created.");
help_section("Options:");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_INITIALIZED = 0x100,
ARG_REMOVED,
ARG_SETTLE,
};
int r;
static const struct option options[] = {
{ "timeout", required_argument, NULL, 't' },
{ "initialized", required_argument, NULL, ARG_INITIALIZED },
{ "removed", no_argument, NULL, ARG_REMOVED },
{ "settle", no_argument, NULL, ARG_SETTLE },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{}
};
assert(argc >= 0);
assert(argv);
int c, r;
OptionParser opts = { argc, argv, .namespace = "udevadm-wait" };
while ((c = getopt_long(argc, argv, "t:hV", options, NULL)) >= 0)
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 't':
r = parse_sec(optarg, &arg_timeout_usec);
OPTION_NAMESPACE("udevadm-wait"): {}
OPTION_COMMON_HELP:
return help();
OPTION('V', "version", NULL, "Show package version"):
return print_version();
OPTION('t', "timeout", "SEC", "Maximum time to wait for the device"):
r = parse_sec(opts.arg, &arg_timeout_usec);
if (r < 0)
return log_error_errno(r, "Failed to parse -t/--timeout= parameter: %s", optarg);
return log_error_errno(r, "Failed to parse -t/--timeout= parameter: %s", opts.arg);
break;
case ARG_INITIALIZED:
r = parse_boolean(optarg);
OPTION_LONG("initialized", "BOOL",
"Wait for devices being initialized by systemd-udevd"):
r = parse_boolean(opts.arg);
if (r < 0)
return log_error_errno(r, "Failed to parse --initialized= parameter: %s", optarg);
return log_error_errno(r, "Failed to parse --initialized= parameter: %s", opts.arg);
arg_wait_until = r ? WAIT_UNTIL_INITIALIZED : WAIT_UNTIL_ADDED;
break;
case ARG_REMOVED:
OPTION_LONG("removed", NULL, "Wait for devices being removed"):
arg_wait_until = WAIT_UNTIL_REMOVED;
break;
case ARG_SETTLE:
OPTION_LONG("settle", NULL, "Also wait for all queued events being processed"):
arg_settle = true;
break;
case 'V':
return print_version();
case 'h':
return help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (optind >= argc)
char **args = option_parser_get_args(&opts);
if (strv_isempty(args))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too few arguments, expected at least one device path or device symlink.");
arg_devices = strv_copy(argv + optind);
arg_devices = strv_copy(args);
if (!arg_devices)
return log_oom();
+58 -81
View File
@@ -1,87 +1,93 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdio.h>
#include "alloc-util.h"
#include "argv-util.h"
#include "format-table.h"
#include "help-util.h"
#include "label-util.h"
#include "main-func.h"
#include "pretty-print.h"
#include "options.h"
#include "udev-util.h"
#include "udevadm.h"
#include "udevd.h"
#include "verbs.h"
static int help(void) {
static const char *const short_descriptions[][2] = {
{ "info", "Query sysfs or the udev database" },
{ "trigger", "Request events from the kernel" },
{ "settle", "Wait for pending udev events" },
{ "control", "Control the udev daemon" },
{ "monitor", "Listen to kernel and udev events" },
{ "test", "Test an event run" },
{ "test-builtin", "Test a built-in command" },
{ "verify", "Verify udev rules files" },
{ "cat", "Show udev rules files" },
{ "wait", "Wait for device or device symlink" },
{ "lock", "Lock a block device" },
};
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *verbs = NULL, *options = NULL;
int r;
r = terminal_urlify_man("udevadm", "8", &link);
r = verbs_get_help_table(&verbs);
if (r < 0)
return log_oom();
return r;
printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n"
"Send control commands or test the device manager.\n\n"
"Commands:\n",
program_invocation_short_name);
r = option_parser_get_help_table_ns("udevadm", &options);
if (r < 0)
return r;
FOREACH_ELEMENT(desc, short_descriptions)
printf(" %-12s %s\n", (*desc)[0], (*desc)[1]);
(void) table_sync_column_widths(0, verbs, options);
printf("\nSee the %s for details.\n", link);
help_cmdline("[OPTIONS…] COMMAND [COMMAND OPTIONS…]");
help_abstract("Send control commands or test the device manager.");
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("udevadm", "8");
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{}
};
int c;
VERB_COMMON_HELP(help);
VERB_SCOPE(, verb_info_main, "info", "[DEVPATH|FILE]", VERB_ANY, VERB_ANY, 0, "Query sysfs or the udev database");
VERB_SCOPE(, verb_trigger_main, "trigger", "DEVPATH", VERB_ANY, VERB_ANY, 0, "Request events from the kernel");
VERB_SCOPE(, verb_settle_main, "settle", NULL, VERB_ANY, VERB_ANY, 0, "Wait for pending udev events");
VERB_SCOPE(, verb_control_main, "control", "OPTION", VERB_ANY, VERB_ANY, 0, "Control the udev daemon");
VERB_SCOPE(, verb_monitor_main, "monitor", NULL, VERB_ANY, VERB_ANY, 0, "Listen to kernel and udev events");
VERB_SCOPE(, verb_test_main, "test", "DEVPATH", VERB_ANY, VERB_ANY, 0, "Test an event run");
VERB_SCOPE(, verb_builtin_main, "test-builtin", "COMMAND DEVPATH", VERB_ANY, VERB_ANY, 0, "Test a built-in command");
VERB_SCOPE(, verb_verify_main, "verify", "[FILE…]", VERB_ANY, VERB_ANY, 0, "Verify udev rules files");
VERB_SCOPE(, verb_cat_main, "cat", "[FILE…]", VERB_ANY, VERB_ANY, 0, "Show udev rules files");
VERB_SCOPE(, verb_wait_main, "wait", "DEVICE [DEVICE…]", VERB_ANY, VERB_ANY, 0, "Wait for device or device symlink");
VERB_SCOPE(, verb_lock_main, "lock", "[OPTIONS…] COMMAND", VERB_ANY, VERB_ANY, 0, "Lock a block device");
VERB_SCOPE(, verb_hwdb_main, "hwdb", NULL, VERB_ANY, VERB_ANY, 0, /* help= */ NULL); /* deprecated */
VERB_NOARG(verb_version_main, "version", /* help= */ NULL);
static int verb_version_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
return print_version();
}
static int parse_argv(int argc, char *argv[], char ***remaining_args) {
assert(argc >= 0);
assert(argv);
assert(remaining_args);
/* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long()
* that checks for GNU extensions in optstring ('-' or '+' at the beginning). */
optind = 0;
while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
OptionParser opts = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION, "udevadm" };
FOREACH_OPTION(c, &opts, /* on_error= */ return c)
switch (c) {
case 'd':
log_set_max_level(LOG_DEBUG);
break;
OPTION_NAMESPACE("udevadm"): {}
case 'h':
OPTION_COMMON_HELP:
return help();
case 'V':
OPTION_COMMON_VERSION_WITH_HIDDEN_V:
return print_version();
case '?':
return -EINVAL;
default:
assert_not_reached();
OPTION('d', "debug", NULL, "Enable debug logging"):
log_set_max_level(LOG_DEBUG);
break;
}
*remaining_args = option_parser_get_args(&opts);
return 1; /* work to do */
}
@@ -91,37 +97,8 @@ int print_version(void) {
return 0;
}
static int verb_version_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
return print_version();
}
static int verb_help_main(int argc, char *argv[], uintptr_t _data, void *userdata) {
return help();
}
static int udevadm_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "cat", VERB_ANY, VERB_ANY, 0, verb_cat_main },
{ "info", VERB_ANY, VERB_ANY, 0, verb_info_main },
{ "trigger", VERB_ANY, VERB_ANY, 0, verb_trigger_main },
{ "settle", VERB_ANY, VERB_ANY, 0, verb_settle_main },
{ "control", VERB_ANY, VERB_ANY, 0, verb_control_main },
{ "monitor", VERB_ANY, VERB_ANY, 0, verb_monitor_main },
{ "hwdb", VERB_ANY, VERB_ANY, 0, verb_hwdb_main },
{ "test", VERB_ANY, VERB_ANY, 0, verb_test_main },
{ "test-builtin", VERB_ANY, VERB_ANY, 0, verb_builtin_main },
{ "wait", VERB_ANY, VERB_ANY, 0, verb_wait_main },
{ "lock", VERB_ANY, VERB_ANY, 0, verb_lock_main },
{ "verify", VERB_ANY, VERB_ANY, 0, verb_verify_main },
{ "version", VERB_ANY, VERB_ANY, 0, verb_version_main },
{ "help", VERB_ANY, VERB_ANY, 0, verb_help_main },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
static int run(int argc, char *argv[]) {
char **args = NULL;
int r;
if (invoked_as(argv, "udevd"))
@@ -130,7 +107,7 @@ static int run(int argc, char *argv[]) {
(void) udev_parse_config();
log_setup();
r = parse_argv(argc, argv);
r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -138,7 +115,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
return udevadm_main(argc, argv);
return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);