Another batch of option/verb conversions (#41532)
Partially generated with Claude but then edited to fix conversions errors.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/socket.h> /* IWYU pragma: keep */
|
||||
|
||||
#include "sd-messages.h"
|
||||
@@ -9,9 +8,11 @@
|
||||
#include "battery-util.h"
|
||||
#include "build.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-table.h"
|
||||
#include "glyph-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
#include "plymouth-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "proc-cmdline.h"
|
||||
@@ -27,22 +28,28 @@ static bool arg_doit = true;
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-battery-check", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%s\n\n"
|
||||
"%sCheck battery level to see whether there's enough charge.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\nSee the %s for details.\n",
|
||||
"%sCheck battery level to see whether there's enough charge.%s\n\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -70,41 +77,23 @@ static int plymouth_send_message(const char *mode, const char *message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char * argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{}
|
||||
};
|
||||
|
||||
int c;
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
|
||||
FOREACH_OPTION(&state, c, /* ret_a= */ NULL, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
if (option_parser_get_n_args(&state) != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s takes no argument.",
|
||||
program_invocation_short_name);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
@@ -8,63 +7,53 @@
|
||||
#include "alloc-util.h"
|
||||
#include "build.h"
|
||||
#include "bus-error.h"
|
||||
#include "format-table.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
#include "pretty-print.h"
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-boot-check-no-failures.service", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%s [OPTIONS...]\n"
|
||||
"\n%sVerify system operational state.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Print version\n"
|
||||
"\nSee the %s for details.\n",
|
||||
"\n%sVerify system operational state.%s\n\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_PATH = 0x100,
|
||||
ARG_VERSION,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{}
|
||||
};
|
||||
|
||||
int c;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
|
||||
FOREACH_OPTION(&state, c, /* ret_a= */ NULL, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+51
-70
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -26,6 +25,7 @@
|
||||
#include "json-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
#include "parse-argument.h"
|
||||
#include "pcrextend-util.h"
|
||||
#include "pretty-print.h"
|
||||
@@ -51,148 +51,129 @@ STATIC_DESTRUCTOR_REGISTER(arg_key, freep);
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-imds", "1", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%s [OPTIONS...] [KEY]\n"
|
||||
"\n%sIMDS data acquisition.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" -K --well-known=[hostname|region|zone|ipv4-public|ipv6-public|ssh-key|\n"
|
||||
" userdata|userdata-base|userdata-base64]\n"
|
||||
" Select well-known key/base\n"
|
||||
" --refresh=SEC Set minimum freshness time for returned data\n"
|
||||
" --cache=no Disable cache use\n"
|
||||
" -u --userdata Dump user data\n"
|
||||
" --import Import system credentials from IMDS userdata\n"
|
||||
" and place them in /run/credstore/\n"
|
||||
"\nSee the %s for details.\n",
|
||||
"\n%sIMDS data acquisition.%s\n\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_REFRESH,
|
||||
ARG_CACHE,
|
||||
ARG_IMPORT,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "well-known", required_argument, NULL, 'K' },
|
||||
{ "refresh", required_argument, NULL, ARG_REFRESH },
|
||||
{ "cache", required_argument, NULL, ARG_CACHE },
|
||||
{ "userdata", no_argument, NULL, 'u' },
|
||||
{ "import", no_argument, NULL, ARG_IMPORT },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hK:u", options, NULL)) >= 0) {
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case 'K': {
|
||||
if (isempty(optarg)) {
|
||||
OPTION('K', "well-known", "KEY",
|
||||
"Select well-known key/base, one of:"
|
||||
" hostname, region, zone, ipv4-public, ipv6-public, ssh-key,"
|
||||
" userdata, userdata-base, userdata-base64"): {
|
||||
if (isempty(arg)) {
|
||||
arg_well_known = _IMDS_WELL_KNOWN_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (streq(optarg, "help"))
|
||||
if (streq(arg, "help"))
|
||||
return DUMP_STRING_TABLE(imds_well_known, ImdsWellKnown, _IMDS_WELL_KNOWN_MAX);
|
||||
|
||||
ImdsWellKnown wk = imds_well_known_from_string(optarg);
|
||||
ImdsWellKnown wk = imds_well_known_from_string(arg);
|
||||
if (wk < 0)
|
||||
return log_error_errno(wk, "Failed to parse --well-known= argument: %s", optarg);
|
||||
return log_error_errno(wk, "Failed to parse --well-known= argument: %s", arg);
|
||||
|
||||
arg_well_known = wk;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_CACHE:
|
||||
r = parse_tristate_argument_with_auto("--cache=", optarg, &arg_cache);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_REFRESH: {
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("refresh", "SEC", "Set minimum freshness time for returned data"): {
|
||||
if (isempty(arg)) {
|
||||
arg_refresh_usec_set = false;
|
||||
break;
|
||||
}
|
||||
|
||||
usec_t t;
|
||||
r = parse_sec(optarg, &t);
|
||||
r = parse_sec(arg, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse refresh timeout: %s", optarg);
|
||||
return log_error_errno(r, "Failed to parse refresh timeout: %s", arg);
|
||||
|
||||
arg_refresh_usec = t;
|
||||
arg_refresh_usec_set = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'u':
|
||||
OPTION_LONG("cache", "BOOL", "Control cache use"):
|
||||
r = parse_tristate_argument_with_auto("--cache=", arg, &arg_cache);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
OPTION('u', "userdata", NULL, "Dump user data"):
|
||||
arg_action = ACTION_USERDATA;
|
||||
break;
|
||||
|
||||
case ARG_IMPORT:
|
||||
OPTION_LONG("import", NULL,
|
||||
"Import system credentials from IMDS userdata"
|
||||
" and place them in /run/credstore/"):
|
||||
arg_action = ACTION_IMPORT;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
char **args = option_parser_get_args(&state);
|
||||
size_t n_args = option_parser_get_n_args(&state);
|
||||
|
||||
if (IN_SET(arg_action, ACTION_USERDATA, ACTION_IMPORT)) {
|
||||
if (argc != optind)
|
||||
if (n_args != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No parameters expected.");
|
||||
|
||||
} else {
|
||||
assert(arg_action < 0);
|
||||
|
||||
if (argc > optind + 1)
|
||||
if (n_args > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "None or one argument expected.");
|
||||
|
||||
if (argc == optind && arg_well_known < 0)
|
||||
if (n_args == 0 && arg_well_known < 0)
|
||||
arg_action = ACTION_SUMMARY;
|
||||
else {
|
||||
if (arg_well_known < 0)
|
||||
arg_well_known = IMDS_BASE;
|
||||
|
||||
if (argc > optind) {
|
||||
if (!imds_key_is_valid(argv[optind]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified IMDS key is not valid, refusing: %s", argv[optind]);
|
||||
if (n_args > 0) {
|
||||
if (!imds_key_is_valid(args[0]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified IMDS key is not valid, refusing: %s", args[0]);
|
||||
|
||||
if (!imds_well_known_can_suffix(arg_well_known))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Well known key '%s' does not take a key suffix, refusing.", imds_well_known_to_string(arg_well_known));
|
||||
|
||||
r = free_and_strdup_warn(&arg_key, argv[optind]);
|
||||
r = free_and_strdup_warn(&arg_key, args[0]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
+120
-177
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <unistd.h>
|
||||
@@ -26,6 +25,7 @@
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-ifname.h"
|
||||
#include "format-table.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "hashmap.h"
|
||||
#include "imds-util.h"
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "netlink-util.h"
|
||||
#include "options.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@@ -2203,50 +2204,45 @@ static int vl_server(void) {
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL, *endpoint_options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-imdsd@.service", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = option_parser_get_help_table_group("Manual Endpoint Configuration", &endpoint_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) table_sync_column_widths(0, options, endpoint_options);
|
||||
|
||||
printf("%1$s [OPTIONS...] KEY\n"
|
||||
"\n%5$sLow-level IMDS data acquisition.%6$s\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" -i --interface=INTERFACE\n"
|
||||
" Use the specified interface\n"
|
||||
" --refresh=SEC Set token refresh time\n"
|
||||
" --fwmark=INTEGER Choose firewall mark for HTTP traffic\n"
|
||||
" --cache=no Disable cache use\n"
|
||||
" -w --wait=yes Wait for connectivity\n"
|
||||
" -K --well-known= Select well-known key\n"
|
||||
" --setup-network Generate .network and .rr files\n"
|
||||
"\n%3$sManual Endpoint Configuration:%4$s\n"
|
||||
" --vendor=VENDOR Specify IMDS vendor literally\n"
|
||||
" --token-url=URL URL for acquiring token\n"
|
||||
" --refresh-header-name=NAME\n"
|
||||
" Header name for passing refresh time\n"
|
||||
" --data-url=URL Base URL for acquiring data\n"
|
||||
" --data-url-suffix=STRING\n"
|
||||
" Suffix to append to data URL\n"
|
||||
" --token-header-name=NAME\n"
|
||||
" Header name for passing token string\n"
|
||||
" --extra-header='NAME: VALUE'\n"
|
||||
" Additional header to pass to data transfer\n"
|
||||
" --address-ipv4=ADDRESS\n"
|
||||
" --address-ipv6=ADDRESS\n"
|
||||
" Configure the IPv4 and IPv6 address of the IMDS server\n"
|
||||
" --well-known-key=NAME:KEY\n"
|
||||
" Configure the location of well-known keys\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
"\n%2$sLow-level IMDS data acquisition.%3$s\n"
|
||||
"\n%4$sOptions:%5$s\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\n%sManual Endpoint Configuration:%s\n",
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(endpoint_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2259,91 +2255,48 @@ static bool http_header_valid(const char *a) {
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_REFRESH,
|
||||
ARG_FWMARK,
|
||||
ARG_CACHE,
|
||||
ARG_WAIT,
|
||||
ARG_VENDOR,
|
||||
ARG_TOKEN_URL,
|
||||
ARG_REFRESH_HEADER_NAME,
|
||||
ARG_DATA_URL,
|
||||
ARG_DATA_URL_SUFFIX,
|
||||
ARG_TOKEN_HEADER_NAME,
|
||||
ARG_EXTRA_HEADER,
|
||||
ARG_ADDRESS_IPV4,
|
||||
ARG_ADDRESS_IPV6,
|
||||
ARG_WELL_KNOWN_KEY,
|
||||
ARG_SETUP_NETWORK,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "refresh", required_argument, NULL, ARG_REFRESH },
|
||||
{ "fwmark", required_argument, NULL, ARG_FWMARK },
|
||||
{ "cache", required_argument, NULL, ARG_CACHE },
|
||||
{ "wait", required_argument, NULL, ARG_WAIT },
|
||||
{ "well-known", required_argument, NULL, 'K' },
|
||||
{ "setup-network", no_argument, NULL, ARG_SETUP_NETWORK },
|
||||
|
||||
/* The following all configure endpoint information explicitly */
|
||||
{ "vendor", required_argument, NULL, ARG_VENDOR },
|
||||
{ "token-url", required_argument, NULL, ARG_TOKEN_URL },
|
||||
{ "refresh-header-name", required_argument, NULL, ARG_REFRESH_HEADER_NAME },
|
||||
{ "data-url", required_argument, NULL, ARG_DATA_URL },
|
||||
{ "data-url-suffix", required_argument, NULL, ARG_DATA_URL_SUFFIX },
|
||||
{ "token-header-name", required_argument, NULL, ARG_TOKEN_HEADER_NAME },
|
||||
{ "extra-header", required_argument, NULL, ARG_EXTRA_HEADER },
|
||||
{ "address-ipv4", required_argument, NULL, ARG_ADDRESS_IPV4 },
|
||||
{ "address-ipv6", required_argument, NULL, ARG_ADDRESS_IPV6 },
|
||||
{ "well-known-key", required_argument, NULL, ARG_WELL_KNOWN_KEY },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hi:wK:", options, NULL)) >= 0) {
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case 'i':
|
||||
if (isempty(optarg)) {
|
||||
OPTION('i', "interface", "INTERFACE", "Use the specified interface"):
|
||||
if (isempty(arg)) {
|
||||
arg_ifname = mfree(arg_ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ifname_valid_full(optarg, IFNAME_VALID_ALTERNATIVE|IFNAME_VALID_NUMERIC))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface name '%s' is not valid.", optarg);
|
||||
if (!ifname_valid_full(arg, IFNAME_VALID_ALTERNATIVE|IFNAME_VALID_NUMERIC))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface name '%s' is not valid.", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_ifname, optarg);
|
||||
r = free_and_strdup_warn(&arg_ifname, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_REFRESH: {
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("refresh", "SEC", "Set token refresh time"): {
|
||||
if (isempty(arg)) {
|
||||
arg_refresh_usec = REFRESH_USEC_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
usec_t t;
|
||||
r = parse_sec(optarg, &t);
|
||||
r = parse_sec(arg, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse refresh timeout: %s", optarg);
|
||||
return log_error_errno(r, "Failed to parse refresh timeout: %s", arg);
|
||||
if (t < REFRESH_USEC_MIN) {
|
||||
log_warning("Increasing specified refresh time to %s, lower values are not supported.", FORMAT_TIMESPAN(REFRESH_USEC_MIN, 0));
|
||||
arg_refresh_usec = REFRESH_USEC_MIN;
|
||||
@@ -2352,50 +2305,48 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_FWMARK:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("fwmark", "INTEGER", "Choose firewall mark for HTTP traffic"):
|
||||
if (isempty(arg)) {
|
||||
arg_fwmark_set = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (streq(optarg, "default")) {
|
||||
if (streq(arg, "default")) {
|
||||
arg_fwmark = FWMARK_DEFAULT;
|
||||
arg_fwmark_set = true;
|
||||
break;
|
||||
}
|
||||
|
||||
r = safe_atou32(optarg, &arg_fwmark);
|
||||
r = safe_atou32(arg, &arg_fwmark);
|
||||
if (r < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse --fwmark= parameter: %s", optarg);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse --fwmark= parameter: %s", arg);
|
||||
|
||||
arg_fwmark_set = true;
|
||||
break;
|
||||
|
||||
case ARG_CACHE:
|
||||
r = parse_boolean_argument("--cache", optarg, &arg_cache);
|
||||
OPTION_LONG("cache", "BOOL", "Enable/disable cache use"):
|
||||
r = parse_boolean_argument("--cache", arg, &arg_cache);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_WAIT:
|
||||
r = parse_boolean_argument("--wait", optarg, &arg_wait);
|
||||
OPTION_LONG("wait", "BOOL", "Whether to wait for connectivity"):
|
||||
r = parse_boolean_argument("--wait", arg, &arg_wait);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
OPTION_SHORT('w', NULL, "Same as --wait=yes"):
|
||||
arg_wait = true;
|
||||
break;
|
||||
|
||||
case 'K': {
|
||||
if (isempty(optarg)) {
|
||||
OPTION('K', "well-known", "KEY", "Select well-known key"): {
|
||||
if (isempty(arg)) {
|
||||
arg_well_known = _IMDS_WELL_KNOWN_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
ImdsWellKnown wk = imds_well_known_from_string(optarg);
|
||||
ImdsWellKnown wk = imds_well_known_from_string(arg);
|
||||
if (wk < 0)
|
||||
return log_error_errno(wk, "Failed to parse --well-known= parameter: %m");
|
||||
|
||||
@@ -2403,146 +2354,148 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_VENDOR:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("setup-network", NULL, "Generate .network and .rr files"):
|
||||
arg_setup_network = true;
|
||||
break;
|
||||
|
||||
/* The following all configure endpoint information explicitly */
|
||||
OPTION_GROUP("Manual Endpoint Configuration"):
|
||||
break;
|
||||
|
||||
OPTION_LONG("vendor", "VENDOR", "Specify IMDS vendor literally"):
|
||||
if (isempty(arg)) {
|
||||
arg_vendor = mfree(arg_vendor);
|
||||
break;
|
||||
}
|
||||
|
||||
r = free_and_strdup_warn(&arg_vendor, optarg);
|
||||
r = free_and_strdup_warn(&arg_vendor, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_TOKEN_URL:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("token-url", "URL", "URL for acquiring token"):
|
||||
if (isempty(arg)) {
|
||||
arg_token_url = mfree(arg_token_url);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!http_url_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL: %s", optarg);
|
||||
if (!http_url_is_valid(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL: %s", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_token_url, optarg);
|
||||
r = free_and_strdup_warn(&arg_token_url, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_REFRESH_HEADER_NAME:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("refresh-header-name", "NAME", "Header name for passing refresh time"):
|
||||
if (isempty(arg)) {
|
||||
arg_refresh_header_name = mfree(arg_refresh_header_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!http_header_name_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header name: %s", optarg);
|
||||
if (!http_header_name_valid(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header name: %s", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_refresh_header_name, optarg);
|
||||
r = free_and_strdup_warn(&arg_refresh_header_name, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_DATA_URL:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("data-url", "URL", "Base URL for acquiring data"):
|
||||
if (isempty(arg)) {
|
||||
arg_data_url = mfree(arg_data_url);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!http_url_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL: %s", optarg);
|
||||
if (!http_url_is_valid(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL: %s", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_data_url, optarg);
|
||||
r = free_and_strdup_warn(&arg_data_url, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_DATA_URL_SUFFIX:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("data-url-suffix", "STRING", "Suffix to append to data URL"):
|
||||
if (isempty(arg)) {
|
||||
arg_data_url_suffix = mfree(arg_data_url_suffix);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ascii_is_valid(optarg) || string_has_cc(optarg, /* ok= */ NULL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL suffix: %s", optarg);
|
||||
if (!ascii_is_valid(arg) || string_has_cc(arg, /* ok= */ NULL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid URL suffix: %s", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_data_url_suffix, optarg);
|
||||
r = free_and_strdup_warn(&arg_data_url_suffix, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_TOKEN_HEADER_NAME:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("token-header-name", "NAME", "Header name for passing token string"):
|
||||
if (isempty(arg)) {
|
||||
arg_token_header_name = mfree(arg_token_header_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!http_header_name_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header name: %s", optarg);
|
||||
if (!http_header_name_valid(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header name: %s", arg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_token_header_name, optarg);
|
||||
r = free_and_strdup_warn(&arg_token_header_name, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_EXTRA_HEADER:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("extra-header", "NAME: VALUE", "Additional header to pass to data transfer"):
|
||||
if (isempty(arg)) {
|
||||
arg_extra_header = strv_free(arg_extra_header);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!http_header_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header: %s", optarg);
|
||||
if (!http_header_valid(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid HTTP header: %s", arg);
|
||||
|
||||
if (strv_extend(&arg_extra_header, optarg) < 0)
|
||||
if (strv_extend(&arg_extra_header, arg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_ADDRESS_IPV4: {
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("address-ipv4", "ADDRESS", "Configure IPv4 address of the IMDS server"): {
|
||||
if (isempty(arg)) {
|
||||
arg_address_ipv4 = (struct in_addr) {};
|
||||
break;
|
||||
}
|
||||
|
||||
union in_addr_union u;
|
||||
r = in_addr_from_string(AF_INET, optarg, &u);
|
||||
r = in_addr_from_string(AF_INET, arg, &u);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse IPv4 address: %s", optarg);
|
||||
return log_error_errno(r, "Failed to parse IPv4 address: %s", arg);
|
||||
arg_address_ipv4 = u.in;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_ADDRESS_IPV6: {
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("address-ipv6", "ADDRESS", "Configure IPv6 address of the IMDS server"): {
|
||||
if (isempty(arg)) {
|
||||
arg_address_ipv6 = (struct in6_addr) {};
|
||||
break;
|
||||
}
|
||||
|
||||
union in_addr_union u;
|
||||
r = in_addr_from_string(AF_INET6, optarg, &u);
|
||||
r = in_addr_from_string(AF_INET6, arg, &u);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse IPv6 address: %s", optarg);
|
||||
return log_error_errno(r, "Failed to parse IPv6 address: %s", arg);
|
||||
arg_address_ipv6 = u.in6;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_WELL_KNOWN_KEY: {
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("well-known-key", "NAME:KEY", "Configure the location of well-known keys"): {
|
||||
if (isempty(arg)) {
|
||||
for (ImdsWellKnown wk = 0; wk < _IMDS_WELL_KNOWN_MAX; wk++)
|
||||
arg_well_known_key[wk] = mfree(arg_well_known_key[wk]);
|
||||
break;
|
||||
}
|
||||
|
||||
const char *e = strchr(optarg, ':');
|
||||
const char *e = strchr(arg, ':');
|
||||
if (!e)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--well-known-key= expects colon separated name and key pairs.");
|
||||
|
||||
_cleanup_free_ char *name = strndup(optarg, e - optarg);
|
||||
_cleanup_free_ char *name = strndup(arg, e - arg);
|
||||
if (!name)
|
||||
return log_oom();
|
||||
|
||||
@@ -2557,21 +2510,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
r = free_and_strdup_warn(arg_well_known_key + wk, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_SETUP_NETWORK:
|
||||
arg_setup_network = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_vendor || arg_token_url || arg_refresh_header_name || arg_data_url || arg_data_url_suffix || arg_token_header_name || arg_extra_header)
|
||||
arg_endpoint_source = ENDPOINT_USER;
|
||||
@@ -2583,23 +2524,25 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_varlink = r;
|
||||
|
||||
if (!arg_varlink) {
|
||||
char **args = option_parser_get_args(&state);
|
||||
size_t n_args = option_parser_get_n_args(&state);
|
||||
|
||||
if (arg_setup_network) {
|
||||
if (optind != argc)
|
||||
if (n_args != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No argument expected.");
|
||||
} else {
|
||||
if (arg_well_known < 0) {
|
||||
/* if no --well-known= parameter was specified we require an argument */
|
||||
if (argc != optind+1)
|
||||
if (n_args != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A single argument expected.");
|
||||
} else if (argc > optind+1) /* if not, then the additional parameter is optional */
|
||||
} else if (n_args > 1) /* if not, then the additional parameter is optional */
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At most a single argument expected.");
|
||||
|
||||
if (argc > optind) {
|
||||
if (!imds_key_is_valid(argv[optind]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified IMDS key is not valid, refusing: %s", argv[optind]);
|
||||
if (n_args > 0) {
|
||||
if (!imds_key_is_valid(args[0]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified IMDS key is not valid, refusing: %s", args[0]);
|
||||
|
||||
r = free_and_strdup_warn(&arg_key, argv[optind]);
|
||||
r = free_and_strdup_warn(&arg_key, args[0]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -297,6 +297,7 @@ int _option_parser_get_help_table(
|
||||
* "=" is shown only when a long option is defined: -l --long=ARG, --long=ARG, -s ARG.
|
||||
*/
|
||||
bool need_eq = option_takes_arg(opt) && opt->long_code;
|
||||
bool need_quote = opt->metavar && strchr(opt->metavar, ' ');
|
||||
_cleanup_free_ char *s = strjoin(
|
||||
" ",
|
||||
sc,
|
||||
@@ -305,7 +306,9 @@ int _option_parser_get_help_table(
|
||||
strempty(opt->long_code),
|
||||
option_arg_optional(opt) ? "[" : "",
|
||||
need_eq ? "=" : "",
|
||||
need_quote ? "'" : "",
|
||||
strempty(opt->metavar),
|
||||
need_quote ? "'" : "",
|
||||
option_arg_optional(opt) ? "]" : "");
|
||||
if (!s)
|
||||
return log_oom();
|
||||
|
||||
+86
-91
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
@@ -19,6 +18,7 @@
|
||||
#include "hashmap.h"
|
||||
#include "json-util.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
#include "pager.h"
|
||||
#include "polkit-agent.h"
|
||||
#include "pretty-print.h"
|
||||
@@ -644,6 +644,8 @@ static int describe(sd_bus *bus, const char *target_path, const char *version) {
|
||||
return table_print_with_pager(table, SD_JSON_FORMAT_OFF, arg_pager_flags, arg_legend);
|
||||
}
|
||||
|
||||
VERB(verb_list, "list", "[TARGET[@VERSION]]", VERB_ANY, 2, VERB_DEFAULT|VERB_ONLINE_ONLY,
|
||||
"List available targets and versions");
|
||||
static int verb_list(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *target_path = NULL, *version = NULL;
|
||||
@@ -755,6 +757,8 @@ static int check_finished(sd_bus_message *reply, void *userdata, sd_bus_error *r
|
||||
return 0;
|
||||
}
|
||||
|
||||
VERB(verb_check, "check", "[TARGET...]", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY,
|
||||
"Check for updates");
|
||||
static int verb_check(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
@@ -1291,6 +1295,8 @@ static int do_update(sd_bus *bus, char **targets) {
|
||||
return did_anything ? 1 : 0;
|
||||
}
|
||||
|
||||
VERB(verb_update, "update", "[TARGET[@VERSION]...]", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY,
|
||||
"Install updates");
|
||||
static int verb_update(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
_cleanup_strv_free_ char **targets = NULL;
|
||||
@@ -1344,6 +1350,8 @@ static int do_vacuum(sd_bus *bus, const char *target, const char *path) {
|
||||
return count + disabled > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
VERB(verb_vacuum, "vacuum", "[TARGET...]", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY,
|
||||
"Clean up old updates");
|
||||
static int verb_vacuum(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
_cleanup_strv_free_ char **targets = NULL, **target_paths = NULL;
|
||||
@@ -1488,6 +1496,8 @@ static int list_features(sd_bus *bus) {
|
||||
return table_print_with_pager(table, SD_JSON_FORMAT_OFF, arg_pager_flags, arg_legend);
|
||||
}
|
||||
|
||||
VERB(verb_features, "features", "[FEATURE]", VERB_ANY, 2, VERB_ONLINE_ONLY,
|
||||
"List and inspect optional features on host OS");
|
||||
static int verb_features(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
@@ -1537,6 +1547,10 @@ static int verb_features(int argc, char *argv[], uintptr_t _data, void *userdata
|
||||
return table_print_with_pager(table, SD_JSON_FORMAT_OFF, arg_pager_flags, false);
|
||||
}
|
||||
|
||||
VERB(verb_enable, "enable", "FEATURE...", 2, VERB_ANY, VERB_ONLINE_ONLY,
|
||||
"Enable optional feature on host OS");
|
||||
VERB(verb_enable, "disable", "FEATURE...", 2, VERB_ANY, VERB_ONLINE_ONLY,
|
||||
"Disable optional feature on host OS");
|
||||
static int verb_enable(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
sd_bus *bus = ASSERT_PTR(userdata);
|
||||
bool did_anything = false, enable;
|
||||
@@ -1618,111 +1632,102 @@ static int verb_enable(int argc, char *argv[], uintptr_t _data, void *userdata)
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *verbs = NULL, *verbs2 = NULL, *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("updatectl", "1", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...] [VERSION]\n"
|
||||
"\n%5$sManage system updates.%6$s\n"
|
||||
"\n%3$sCommands:%4$s\n"
|
||||
" list [TARGET[@VERSION]] List available targets and versions\n"
|
||||
" check [TARGET...] Check for updates\n"
|
||||
" update [TARGET[@VERSION]...] Install updates\n"
|
||||
" vacuum [TARGET...] Clean up old updates\n"
|
||||
" features [FEATURE] List and inspect optional features on host OS\n"
|
||||
" enable FEATURE... Enable optional feature on host OS\n"
|
||||
" disable FEATURE... Disable optional feature on host OS\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" --reboot Reboot after updating to newer version\n"
|
||||
" --offline Do not fetch metadata from the network\n"
|
||||
" --now Download/delete resources immediately\n"
|
||||
" -H --host=[USER@]HOST Operate on remote host\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
"\nSee the %2$s for details.\n"
|
||||
, program_invocation_short_name
|
||||
, link
|
||||
, ansi_underline(), ansi_normal()
|
||||
, ansi_highlight(), ansi_normal()
|
||||
);
|
||||
r = verbs_get_help_table(&verbs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = option_parser_get_help_table_group("Verbs", &verbs2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) table_sync_column_widths(0, verbs, verbs2, options);
|
||||
|
||||
printf("%s [OPTIONS...] [VERSION]\n"
|
||||
"\n%sManage system updates.%s\n"
|
||||
"\n%sCommands:%s\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(verbs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = table_print_or_warn(verbs2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\n%sOptions:%s\n",
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_NO_PAGER,
|
||||
ARG_NO_LEGEND,
|
||||
ARG_REBOOT,
|
||||
ARG_OFFLINE,
|
||||
ARG_NOW,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||
{ "host", required_argument, NULL, 'H' },
|
||||
{ "reboot", no_argument, NULL, ARG_REBOOT },
|
||||
{ "offline", no_argument, NULL, ARG_OFFLINE },
|
||||
{ "now", no_argument, NULL, ARG_NOW },
|
||||
{}
|
||||
};
|
||||
|
||||
int c;
|
||||
VERB_COMMON_HELP_HIDDEN(help);
|
||||
|
||||
static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hH:", options, NULL)) >= 0) {
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_NO_LEGEND:
|
||||
arg_legend = false;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
arg_transport = BUS_TRANSPORT_REMOTE;
|
||||
arg_host = optarg;
|
||||
break;
|
||||
|
||||
case ARG_REBOOT:
|
||||
OPTION_LONG("reboot", NULL, "Reboot after updating to newer version"):
|
||||
arg_reboot = true;
|
||||
break;
|
||||
|
||||
case ARG_OFFLINE:
|
||||
OPTION_LONG("offline", NULL, "Do not fetch metadata from the network"):
|
||||
arg_offline = true;
|
||||
break;
|
||||
|
||||
case ARG_NOW:
|
||||
OPTION_LONG("now", NULL, "Download/delete resources immediately"):
|
||||
arg_now = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
OPTION_COMMON_HOST:
|
||||
arg_transport = BUS_TRANSPORT_REMOTE;
|
||||
arg_host = arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
OPTION_COMMON_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_NO_LEGEND:
|
||||
arg_legend = false;
|
||||
break;
|
||||
|
||||
OPTION_GROUP("Verbs"): {}
|
||||
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
}
|
||||
}
|
||||
|
||||
*ret_args = option_parser_get_args(&state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1730,23 +1735,13 @@ static int run(int argc, char *argv[]) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
static const Verb verbs[] = {
|
||||
{ "list", VERB_ANY, 2, VERB_DEFAULT|VERB_ONLINE_ONLY, verb_list },
|
||||
{ "check", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_check },
|
||||
{ "update", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_update },
|
||||
{ "vacuum", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_vacuum },
|
||||
{ "features", VERB_ANY, 2, VERB_ONLINE_ONLY, verb_features },
|
||||
{ "enable", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_enable },
|
||||
{ "disable", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_enable },
|
||||
{}
|
||||
};
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
log_setup();
|
||||
|
||||
(void) signal(SIGWINCH, columns_lines_cache_reset);
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
char **args = NULL;
|
||||
r = parse_argv(argc, argv, &args);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -1759,7 +1754,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
(void) sd_bus_set_allow_interactive_authorization(bus, true);
|
||||
|
||||
return dispatch_verb(argc, argv, verbs, bus);
|
||||
return dispatch_verb_with_args(args, bus);
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
|
||||
|
||||
+67
-84
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -16,6 +15,7 @@
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hashmap.h"
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
#include "mount-util.h"
|
||||
#include "options.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "path-util.h"
|
||||
@@ -2048,138 +2049,118 @@ static int cat_config(void) {
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *cmds = NULL, *opts = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-sysusers.service", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...] [CONFIGURATION FILE...]\n"
|
||||
"\n%2$sCreates system user and group accounts.%4$s\n"
|
||||
"\n%3$sCommands:%4$s\n"
|
||||
" --cat-config Show configuration files\n"
|
||||
" --tldr Show non-comment parts of configuration\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" --root=PATH Operate on an alternate filesystem root\n"
|
||||
" --image=PATH Operate on disk image as filesystem root\n"
|
||||
" --image-policy=POLICY Specify disk image dissection policy\n"
|
||||
" --replace=PATH Treat arguments as replacement for PATH\n"
|
||||
" --dry-run Just print what would be done\n"
|
||||
" --inline Treat arguments as configuration lines\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
"\nSee the %5$s for details.\n",
|
||||
r = option_parser_get_help_table(&cmds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = option_parser_get_help_table_group("Options", &opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) table_sync_column_widths(0, cmds, opts);
|
||||
|
||||
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n"
|
||||
"\n%sCreates system user and group accounts.%s\n"
|
||||
"\nCommands:\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(cmds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nOptions:\n");
|
||||
|
||||
r = table_print_or_warn(opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_CAT_CONFIG,
|
||||
ARG_TLDR,
|
||||
ARG_ROOT,
|
||||
ARG_IMAGE,
|
||||
ARG_IMAGE_POLICY,
|
||||
ARG_REPLACE,
|
||||
ARG_DRY_RUN,
|
||||
ARG_INLINE,
|
||||
ARG_NO_PAGER,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
|
||||
{ "tldr", no_argument, NULL, ARG_TLDR },
|
||||
{ "root", required_argument, NULL, ARG_ROOT },
|
||||
{ "image", required_argument, NULL, ARG_IMAGE },
|
||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||
{ "replace", required_argument, NULL, ARG_REPLACE },
|
||||
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
|
||||
{ "inline", no_argument, NULL, ARG_INLINE },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_CAT_CONFIG:
|
||||
OPTION_COMMON_CAT_CONFIG:
|
||||
arg_cat_flags = CAT_CONFIG_ON;
|
||||
break;
|
||||
|
||||
case ARG_TLDR:
|
||||
OPTION_COMMON_TLDR:
|
||||
arg_cat_flags = CAT_TLDR;
|
||||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
OPTION_GROUP("Options"):
|
||||
break;
|
||||
|
||||
OPTION_LONG("root", "PATH", "Operate on an alternate filesystem root"):
|
||||
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_IMAGE:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||
OPTION_LONG("image", "PATH", "Operate on disk image as filesystem root"):
|
||||
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_IMAGE_POLICY:
|
||||
r = parse_image_policy_argument(optarg, &arg_image_policy);
|
||||
OPTION_LONG("image-policy", "POLICY", "Specify disk image dissection policy"):
|
||||
r = parse_image_policy_argument(arg, &arg_image_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_REPLACE:
|
||||
if (!path_is_absolute(optarg))
|
||||
OPTION_LONG("replace", "PATH", "Treat arguments as replacement for PATH"):
|
||||
if (!path_is_absolute(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must be an absolute path.");
|
||||
if (!endswith(optarg, ".conf"))
|
||||
if (!endswith(arg, ".conf"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must have the extension '.conf'.");
|
||||
|
||||
arg_replace = optarg;
|
||||
arg_replace = arg;
|
||||
break;
|
||||
|
||||
case ARG_DRY_RUN:
|
||||
OPTION_LONG("dry-run", NULL, "Just print what would be done"):
|
||||
arg_dry_run = true;
|
||||
break;
|
||||
|
||||
case ARG_INLINE:
|
||||
OPTION_LONG("inline", NULL, "Treat arguments as configuration lines"):
|
||||
arg_inline = true;
|
||||
break;
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
OPTION_COMMON_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
char **args = option_parser_get_args(&state);
|
||||
size_t n_args = option_parser_get_n_args(&state);
|
||||
|
||||
if (arg_replace && arg_cat_flags != CAT_CONFIG_OFF)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --replace= is not supported with --cat-config/--tldr.");
|
||||
@@ -2188,7 +2169,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --inline is not supported with --cat-config/--tldr.");
|
||||
|
||||
if (arg_replace && optind >= argc)
|
||||
if (arg_replace && n_args == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"When --replace= is given, some configuration items must be specified.");
|
||||
|
||||
@@ -2196,6 +2177,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Use either --root= or --image=, the combination of both is not supported.");
|
||||
|
||||
*ret_args = args;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2281,7 +2263,8 @@ static int run(int argc, char *argv[]) {
|
||||
Item *i;
|
||||
int r;
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
char **args = NULL;
|
||||
r = parse_argv(argc, argv, &args);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -2331,10 +2314,10 @@ static int run(int argc, char *argv[]) {
|
||||
* insert the positional arguments at the specified place. Otherwise, if command line arguments are
|
||||
* specified, execute just them, and finally, without --replace= or any positional arguments, just
|
||||
* read configuration and execute it. */
|
||||
if (arg_replace || optind >= argc)
|
||||
r = read_config_files(&c, argv + optind);
|
||||
if (arg_replace || strv_isempty(args))
|
||||
r = read_config_files(&c, args);
|
||||
else
|
||||
r = parse_arguments(&c, argv + optind);
|
||||
r = parse_arguments(&c, args);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "format-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "offline-passwd.h"
|
||||
#include "options.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
|
||||
static char *arg_root = NULL;
|
||||
static const char *arg_root = NULL;
|
||||
|
||||
static void test_resolve_one(const char *name) {
|
||||
bool relaxed = name || arg_root;
|
||||
@@ -39,30 +39,22 @@ static void test_resolve_one(const char *name) {
|
||||
assert_se(relaxed || r == 0);
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "root", required_argument, NULL, 'r' },
|
||||
{}
|
||||
};
|
||||
|
||||
int c;
|
||||
|
||||
static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
assert_se(argc >= 0);
|
||||
assert_se(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "r:", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
case 'r':
|
||||
arg_root = optarg;
|
||||
|
||||
OPTION('r', "root", "PATH", "Operate on an alternate filesystem root"):
|
||||
arg_root = arg;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
*ret_args = option_parser_get_args(&state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -71,15 +63,16 @@ int main(int argc, char **argv) {
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
char **args = NULL;
|
||||
r = parse_argv(argc, argv, &args);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (optind >= argc)
|
||||
if (strv_isempty(args))
|
||||
test_resolve_one(NULL);
|
||||
else
|
||||
while (optind < argc)
|
||||
test_resolve_one(argv[optind++]);
|
||||
STRV_FOREACH(a, args)
|
||||
test_resolve_one(*a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+101
-142
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/file.h>
|
||||
#include <sysexits.h>
|
||||
#include <time.h>
|
||||
@@ -31,6 +30,7 @@
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "glob-util.h"
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "offline-passwd.h"
|
||||
#include "options.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
@@ -209,7 +210,7 @@ static char **arg_include_prefixes = NULL;
|
||||
static char **arg_exclude_prefixes = NULL;
|
||||
static char *arg_root = NULL;
|
||||
static char *arg_image = NULL;
|
||||
static char *arg_replace = NULL;
|
||||
static const char *arg_replace = NULL;
|
||||
static ImagePolicy *arg_image_policy = NULL;
|
||||
|
||||
#define MAX_DEPTH 256
|
||||
@@ -4129,218 +4130,174 @@ static int exclude_default_prefixes(void) {
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *cmds = NULL, *opts = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-tmpfiles", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s COMMAND [OPTIONS...] [CONFIGURATION FILE...]\n"
|
||||
"\n%2$sCreate, delete, and clean up files and directories.%4$s\n"
|
||||
"\n%3$sCommands:%4$s\n"
|
||||
" --create Create and adjust files and directories\n"
|
||||
" --clean Clean up files and directories\n"
|
||||
" --remove Remove files and directories marked for removal\n"
|
||||
" --purge Delete files and directories marked for creation in\n"
|
||||
" specified configuration files (careful!)\n"
|
||||
" --cat-config Show configuration files\n"
|
||||
" --tldr Show non-comment parts of configuration files\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" --user Execute user configuration\n"
|
||||
" --boot Execute actions only safe at boot\n"
|
||||
" --graceful Quietly ignore unknown users or groups\n"
|
||||
" --prefix=PATH Only apply rules with the specified prefix\n"
|
||||
" --exclude-prefix=PATH Ignore rules with the specified prefix\n"
|
||||
" -E Ignore rules prefixed with /dev, /proc, /run, /sys\n"
|
||||
" --root=PATH Operate on an alternate filesystem root\n"
|
||||
" --image=PATH Operate on disk image as filesystem root\n"
|
||||
" --image-policy=POLICY Specify disk image dissection policy\n"
|
||||
" --replace=PATH Treat arguments as replacement for PATH\n"
|
||||
" --dry-run Just print what would be done\n"
|
||||
" --inline Treat arguments as configuration lines\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
"\nSee the %5$s for details.\n",
|
||||
r = option_parser_get_help_table(&cmds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = option_parser_get_help_table_group("Options", &opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) table_sync_column_widths(0, cmds, opts);
|
||||
|
||||
printf("%s COMMAND [OPTIONS...] [CONFIGURATION FILE...]\n"
|
||||
"\n%sCreate, delete, and clean up files and directories.%s\n"
|
||||
"\nCommands:\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(cmds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nOptions:\n");
|
||||
|
||||
r = table_print_or_warn(opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_CAT_CONFIG,
|
||||
ARG_TLDR,
|
||||
ARG_USER,
|
||||
ARG_CREATE,
|
||||
ARG_CLEAN,
|
||||
ARG_REMOVE,
|
||||
ARG_PURGE,
|
||||
ARG_BOOT,
|
||||
ARG_GRACEFUL,
|
||||
ARG_PREFIX,
|
||||
ARG_EXCLUDE_PREFIX,
|
||||
ARG_ROOT,
|
||||
ARG_IMAGE,
|
||||
ARG_IMAGE_POLICY,
|
||||
ARG_REPLACE,
|
||||
ARG_DRY_RUN,
|
||||
ARG_INLINE,
|
||||
ARG_NO_PAGER,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
|
||||
{ "tldr", no_argument, NULL, ARG_TLDR },
|
||||
{ "create", no_argument, NULL, ARG_CREATE },
|
||||
{ "clean", no_argument, NULL, ARG_CLEAN },
|
||||
{ "remove", no_argument, NULL, ARG_REMOVE },
|
||||
{ "purge", no_argument, NULL, ARG_PURGE },
|
||||
{ "boot", no_argument, NULL, ARG_BOOT },
|
||||
{ "graceful", no_argument, NULL, ARG_GRACEFUL },
|
||||
{ "prefix", required_argument, NULL, ARG_PREFIX },
|
||||
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
|
||||
{ "root", required_argument, NULL, ARG_ROOT },
|
||||
{ "image", required_argument, NULL, ARG_IMAGE },
|
||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||
{ "replace", required_argument, NULL, ARG_REPLACE },
|
||||
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
|
||||
{ "inline", no_argument, NULL, ARG_INLINE },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hE", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_CAT_CONFIG:
|
||||
arg_cat_flags = CAT_CONFIG_ON;
|
||||
break;
|
||||
|
||||
case ARG_TLDR:
|
||||
arg_cat_flags = CAT_TLDR;
|
||||
break;
|
||||
|
||||
case ARG_USER:
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
case ARG_CREATE:
|
||||
OPTION_LONG("create", NULL, "Create and adjust files and directories"):
|
||||
arg_operation |= OPERATION_CREATE;
|
||||
break;
|
||||
|
||||
case ARG_CLEAN:
|
||||
OPTION_LONG("clean", NULL, "Clean up files and directories"):
|
||||
arg_operation |= OPERATION_CLEAN;
|
||||
break;
|
||||
|
||||
case ARG_REMOVE:
|
||||
OPTION_LONG("remove", NULL, "Remove files and directories marked for removal"):
|
||||
arg_operation |= OPERATION_REMOVE;
|
||||
break;
|
||||
|
||||
case ARG_BOOT:
|
||||
arg_boot = true;
|
||||
break;
|
||||
|
||||
case ARG_PURGE:
|
||||
OPTION_LONG("purge", NULL,
|
||||
"Delete files and directories marked for creation in"
|
||||
" specified configuration files (careful!)"):
|
||||
arg_operation |= OPERATION_PURGE;
|
||||
break;
|
||||
|
||||
case ARG_GRACEFUL:
|
||||
OPTION_COMMON_CAT_CONFIG:
|
||||
arg_cat_flags = CAT_CONFIG_ON;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_TLDR:
|
||||
arg_cat_flags = CAT_TLDR;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
OPTION_GROUP("Options"):
|
||||
break;
|
||||
|
||||
OPTION_LONG("user", NULL, "Execute user configuration"):
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
OPTION_LONG("boot", NULL, "Execute actions only safe at boot"):
|
||||
arg_boot = true;
|
||||
break;
|
||||
|
||||
OPTION_LONG("graceful", NULL, "Quietly ignore unknown users or groups"):
|
||||
arg_graceful = true;
|
||||
break;
|
||||
|
||||
case ARG_PREFIX:
|
||||
if (strv_extend(&arg_include_prefixes, optarg) < 0)
|
||||
OPTION_LONG("prefix", "PATH", "Only apply rules with the specified prefix"):
|
||||
if (strv_extend(&arg_include_prefixes, arg) < 0)
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
case ARG_EXCLUDE_PREFIX:
|
||||
if (strv_extend(&arg_exclude_prefixes, optarg) < 0)
|
||||
OPTION_LONG("exclude-prefix", "PATH", "Ignore rules with the specified prefix"):
|
||||
if (strv_extend(&arg_exclude_prefixes, arg) < 0)
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
|
||||
OPTION_SHORT('E', NULL, "Ignore rules prefixed with /dev, /proc, /run, /sys"):
|
||||
r = exclude_default_prefixes();
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_IMAGE:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||
OPTION_LONG("root", "PATH", "Operate on an alternate filesystem root"):
|
||||
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
OPTION_LONG("image", "PATH", "Operate on disk image as filesystem root"):
|
||||
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Imply -E here since it makes little sense to create files persistently in the /run mountpoint of a disk image */
|
||||
_fallthrough_;
|
||||
|
||||
case 'E':
|
||||
r = exclude_default_prefixes();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_IMAGE_POLICY:
|
||||
r = parse_image_policy_argument(optarg, &arg_image_policy);
|
||||
OPTION_LONG("image-policy", "POLICY", "Specify disk image dissection policy"):
|
||||
r = parse_image_policy_argument(arg, &arg_image_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_REPLACE:
|
||||
if (!path_is_absolute(optarg))
|
||||
OPTION_LONG("replace", "PATH", "Treat arguments as replacement for PATH"):
|
||||
if (!path_is_absolute(arg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must be an absolute path.");
|
||||
if (!endswith(optarg, ".conf"))
|
||||
if (!endswith(arg, ".conf"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The argument to --replace= must have the extension '.conf'.");
|
||||
|
||||
arg_replace = optarg;
|
||||
arg_replace = arg;
|
||||
break;
|
||||
|
||||
case ARG_DRY_RUN:
|
||||
OPTION_LONG("dry-run", NULL, "Just print what would be done"):
|
||||
arg_dry_run = true;
|
||||
break;
|
||||
|
||||
case ARG_INLINE:
|
||||
OPTION_LONG("inline", NULL, "Treat arguments as configuration lines"):
|
||||
arg_inline = true;
|
||||
break;
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
OPTION_COMMON_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
char **args = option_parser_get_args(&state);
|
||||
size_t n_args = option_parser_get_n_args(&state);
|
||||
|
||||
if (arg_operation == 0 && arg_cat_flags == CAT_CONFIG_OFF)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"You need to specify at least one of --clean, --create, --remove, or --purge.");
|
||||
|
||||
if (FLAGS_SET(arg_operation, OPERATION_PURGE) && optind >= argc)
|
||||
if (FLAGS_SET(arg_operation, OPERATION_PURGE) && n_args == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Refusing --purge without specification of a configuration file.");
|
||||
|
||||
@@ -4352,7 +4309,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --inline is not supported with --cat-config/--tldr.");
|
||||
|
||||
if (arg_replace && optind >= argc)
|
||||
if (arg_replace && n_args == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"When --replace= is given, some configuration items must be specified.");
|
||||
|
||||
@@ -4364,6 +4321,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Please specify either --root= or --image=, the combination of both is not supported.");
|
||||
|
||||
*ret_args = args;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4564,7 +4522,8 @@ static int run(int argc, char *argv[]) {
|
||||
} phase;
|
||||
int r;
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
char **args = NULL;
|
||||
r = parse_argv(argc, argv, &args);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -4619,7 +4578,7 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_cat_flags != CAT_CONFIG_OFF)
|
||||
return cat_config(config_dirs, argv + optind);
|
||||
return cat_config(config_dirs, args);
|
||||
|
||||
if (should_bypass("SYSTEMD_TMPFILES"))
|
||||
return 0;
|
||||
@@ -4663,10 +4622,10 @@ static int run(int argc, char *argv[]) {
|
||||
* insert the positional arguments at the specified place. Otherwise, if command line arguments are
|
||||
* specified, execute just them, and finally, without --replace= or any positional arguments, just
|
||||
* read configuration and execute it. */
|
||||
if (arg_replace || optind >= argc)
|
||||
r = read_config_files(&c, config_dirs, argv + optind, &invalid_config);
|
||||
if (arg_replace || strv_isempty(args))
|
||||
r = read_config_files(&c, config_dirs, args, &invalid_config);
|
||||
else
|
||||
r = parse_arguments(&c, config_dirs, argv + optind, &invalid_config);
|
||||
r = parse_arguments(&c, config_dirs, args, &invalid_config);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+24
-37
@@ -1,15 +1,15 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "build.h"
|
||||
#include "env-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
#include "pretty-print.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "tpm2-util.h"
|
||||
@@ -18,68 +18,55 @@ static bool arg_graceful = false;
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-tpm2-clear", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...]\n"
|
||||
"\n%5$sRequest clearing of the TPM2 from PC firmware.%6$s\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --graceful Exit gracefully if no TPM2 device is found\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%s [OPTIONS...]\n"
|
||||
"\n%sRequest clearing of the TPM2 from PC firmware.%s\n"
|
||||
"\n%sOptions:%s\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_GRACEFUL,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "graceful", no_argument, NULL, ARG_GRACEFUL },
|
||||
{}
|
||||
};
|
||||
|
||||
int c;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
|
||||
FOREACH_OPTION(&state, c, /* ret_a= */ NULL, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_GRACEFUL:
|
||||
OPTION_LONG("graceful", NULL, "Exit gracefully if no TPM2 device is found"):
|
||||
arg_graceful = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
if (option_parser_get_n_args(&state) != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects no arguments.");
|
||||
|
||||
return 1;
|
||||
|
||||
+34
-51
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
@@ -13,11 +12,13 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
#include "options.h"
|
||||
#include "parse-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "set.h"
|
||||
@@ -38,94 +39,76 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
#define TPM2_SRK_TPM2B_PUBLIC_PERSISTENT_PATH "/var/lib/systemd/tpm2-srk-public-key.tpm2b_public"
|
||||
#define TPM2_SRK_TPM2B_PUBLIC_RUNTIME_PATH "/run/systemd/tpm2-srk-public-key.tpm2b_public"
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-tpm2-setup", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...]\n"
|
||||
"\n%5$sSet up the TPM2 Storage Root Key (SRK), and initialize NvPCRs.%6$s\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --tpm2-device=PATH\n"
|
||||
" Pick TPM2 device\n"
|
||||
" --early=BOOL Store SRK public key in /run/ rather than /var/lib/\n"
|
||||
" --graceful Exit gracefully if no TPM2 device is found\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("%s [OPTIONS...]\n"
|
||||
"\n%sSet up the TPM2 Storage Root Key (SRK), and initialize NvPCRs.%s\n"
|
||||
"\n%sOptions:%s\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
ansi_underline(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_TPM2_DEVICE,
|
||||
ARG_EARLY,
|
||||
ARG_GRACEFUL,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
||||
{ "early", required_argument, NULL, ARG_EARLY },
|
||||
{ "graceful", no_argument, NULL, ARG_GRACEFUL },
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help(0, NULL, NULL);
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_TPM2_DEVICE:
|
||||
if (streq(optarg, "list"))
|
||||
OPTION_LONG("tpm2-device", "PATH", "Pick TPM2 device"):
|
||||
if (streq(arg, "list"))
|
||||
return tpm2_list_devices(/* legend= */ true, /* quiet= */ false);
|
||||
|
||||
if (free_and_strdup(&arg_tpm2_device, streq(optarg, "auto") ? NULL : optarg) < 0)
|
||||
if (free_and_strdup(&arg_tpm2_device, streq(arg, "auto") ? NULL : arg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_EARLY:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("early", "BOOL", "Store SRK public key in /run/ rather than /var/lib/"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --early= argument: %s", optarg);
|
||||
return log_error_errno(r, "Failed to parse --early= argument: %s", arg);
|
||||
|
||||
arg_early = r;
|
||||
break;
|
||||
|
||||
case ARG_GRACEFUL:
|
||||
OPTION_LONG("graceful", NULL, "Exit gracefully if no TPM2 device is found"):
|
||||
arg_graceful = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
if (option_parser_get_n_args(&state) != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects no argument.");
|
||||
|
||||
return 1;
|
||||
|
||||
+99
-161
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@@ -20,6 +19,7 @@
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "memfd-util.h"
|
||||
#include "options.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
@@ -72,206 +72,168 @@ STATIC_DESTRUCTOR_REGISTER(arg_push_fds, push_fds_done);
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("varlinkctl", "1", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
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);
|
||||
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
printf("%1$s [OPTIONS...] COMMAND ...\n\n"
|
||||
"%5$sIntrospect Varlink Services.%6$s\n"
|
||||
"\n%3$sCommands:%4$s\n"
|
||||
" info ADDRESS Show service information\n"
|
||||
" list-interfaces ADDRESS\n"
|
||||
" List interfaces implemented by service\n"
|
||||
" list-methods ADDRESS [INTERFACE…]\n"
|
||||
" List methods implemented by services or specific\n"
|
||||
" interfaces\n"
|
||||
" introspect ADDRESS [INTERFACE…]\n"
|
||||
" Show interface definition\n"
|
||||
" call ADDRESS METHOD [PARAMS]\n"
|
||||
" Invoke method\n"
|
||||
" --exec call ADDRESS METHOD PARAMS -- CMDLINE…\n"
|
||||
" Invoke method and pass response and fds to command\n"
|
||||
" list-registry Show list of services in the service registry\n"
|
||||
" validate-idl [FILE] Validate interface description\n"
|
||||
" help Show this help\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --no-ask-password Do not prompt for password\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --system Enumerate system registry\n"
|
||||
" --user Enumerate user registry\n"
|
||||
" --more Request multiple responses\n"
|
||||
" --collect Collect multiple responses in a JSON array\n"
|
||||
" --oneway Do not request response\n"
|
||||
" --json=MODE Output as JSON\n"
|
||||
" -j Same as --json=pretty on tty, --json=short otherwise\n"
|
||||
" -q --quiet Do not output method reply\n"
|
||||
" --graceful=ERROR Treat specified Varlink error as success\n"
|
||||
" --timeout=SECS Maximum time to wait for method call completion\n"
|
||||
" -E Short for --more --timeout=infinity\n"
|
||||
" --upgrade Request protocol upgrade (connection becomes raw\n"
|
||||
" bidirectional pipe on stdin/stdout after reply)\n"
|
||||
" --push-fd=FD Pass the specified fd along with method call\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
printf("%s [OPTIONS...] COMMAND ...\n\n"
|
||||
"%sIntrospect Varlink Services.%s\n"
|
||||
"\nCommands:\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
ansi_highlight(),
|
||||
ansi_normal());
|
||||
|
||||
r = table_print_or_warn(verbs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nOptions:\n");
|
||||
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
printf("\nWith --exec, specify the command to invoke:\n"
|
||||
" %s --exec call ADDRESS METHOD PARAMS -- CMDLINE…\n",
|
||||
program_invocation_short_name);
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
return help();
|
||||
}
|
||||
VERB_COMMON_HELP(help);
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_NO_PAGER,
|
||||
ARG_MORE,
|
||||
ARG_ONEWAY,
|
||||
ARG_JSON,
|
||||
ARG_COLLECT,
|
||||
ARG_GRACEFUL,
|
||||
ARG_TIMEOUT,
|
||||
ARG_EXEC,
|
||||
ARG_UPGRADE,
|
||||
ARG_PUSH_FD,
|
||||
ARG_NO_ASK_PASSWORD,
|
||||
ARG_USER,
|
||||
ARG_SYSTEM,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "more", no_argument, NULL, ARG_MORE },
|
||||
{ "oneway", no_argument, NULL, ARG_ONEWAY },
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "collect", no_argument, NULL, ARG_COLLECT },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "graceful", required_argument, NULL, ARG_GRACEFUL },
|
||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
||||
{ "exec", no_argument, NULL, ARG_EXEC },
|
||||
{ "upgrade", no_argument, NULL, ARG_UPGRADE },
|
||||
{ "push-fd", required_argument, NULL, ARG_PUSH_FD },
|
||||
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{},
|
||||
};
|
||||
|
||||
int c, r;
|
||||
static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hjqE", options, NULL)) >= 0)
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
OPTION_COMMON_HELP:
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
OPTION_COMMON_NO_ASK_PASSWORD:
|
||||
arg_ask_password = false;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
arg_timeout = USEC_INFINITY;
|
||||
_fallthrough_;
|
||||
OPTION_LONG("system", NULL, "Enumerate system registry"):
|
||||
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||
break;
|
||||
|
||||
case ARG_MORE:
|
||||
OPTION_LONG("user", NULL, "Enumerate user registry"):
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
OPTION_LONG("more", NULL, "Request multiple responses"):
|
||||
arg_method_flags = (arg_method_flags & ~SD_VARLINK_METHOD_ONEWAY) | SD_VARLINK_METHOD_MORE;
|
||||
break;
|
||||
|
||||
case ARG_ONEWAY:
|
||||
arg_method_flags = (arg_method_flags & ~SD_VARLINK_METHOD_MORE) | SD_VARLINK_METHOD_ONEWAY;
|
||||
break;
|
||||
|
||||
case ARG_COLLECT:
|
||||
OPTION_LONG("collect", NULL, "Collect multiple responses in a JSON array"):
|
||||
arg_collect = true;
|
||||
break;
|
||||
|
||||
case ARG_JSON:
|
||||
r = parse_json_argument(optarg, &arg_json_format_flags);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
OPTION_LONG("oneway", NULL, "Do not request response"):
|
||||
arg_method_flags = (arg_method_flags & ~SD_VARLINK_METHOD_MORE) | SD_VARLINK_METHOD_ONEWAY;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
OPTION_COMMON_JSON:
|
||||
r = parse_json_argument(arg, &arg_json_format_flags);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_LOWERCASE_J:
|
||||
arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
OPTION('q', "quiet", NULL, "Do not output method reply"):
|
||||
arg_quiet = true;
|
||||
break;
|
||||
|
||||
case ARG_GRACEFUL:
|
||||
r = varlink_idl_qualified_symbol_name_is_valid(optarg);
|
||||
OPTION_LONG("graceful", "ERROR", "Treat specified Varlink error as success"):
|
||||
r = varlink_idl_qualified_symbol_name_is_valid(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to validate Varlink error name '%s': %m", optarg);
|
||||
return log_error_errno(r, "Failed to validate Varlink error name '%s': %m", arg);
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid Varlink error name: %s", optarg);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid Varlink error name: %s", arg);
|
||||
|
||||
if (strv_extend(&arg_graceful, optarg) < 0)
|
||||
if (strv_extend(&arg_graceful, arg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_TIMEOUT:
|
||||
if (isempty(optarg)) {
|
||||
OPTION_LONG("timeout", "SECS", "Maximum time to wait for method call completion"):
|
||||
if (isempty(arg)) {
|
||||
arg_timeout = USEC_INFINITY;
|
||||
break;
|
||||
}
|
||||
|
||||
r = parse_sec(optarg, &arg_timeout);
|
||||
r = parse_sec(arg, &arg_timeout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --timeout= parameter '%s': %m", optarg);
|
||||
return log_error_errno(r, "Failed to parse --timeout= parameter '%s': %m", arg);
|
||||
|
||||
if (arg_timeout == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Timeout cannot be zero.");
|
||||
|
||||
break;
|
||||
|
||||
case ARG_EXEC:
|
||||
arg_exec = true;
|
||||
OPTION_SHORT('E', NULL, "Short for --more --timeout=infinity"):
|
||||
arg_timeout = USEC_INFINITY;
|
||||
arg_method_flags = (arg_method_flags & ~SD_VARLINK_METHOD_ONEWAY) | SD_VARLINK_METHOD_MORE;
|
||||
break;
|
||||
|
||||
case ARG_UPGRADE:
|
||||
OPTION_LONG("upgrade", NULL,
|
||||
"Request protocol upgrade (connection becomes raw"
|
||||
" bidirectional pipe on stdin/stdout after reply)"):
|
||||
arg_upgrade = true;
|
||||
break;
|
||||
|
||||
case ARG_PUSH_FD: {
|
||||
OPTION_LONG("exec", NULL, "Invoke method and pass response and fds to command"):
|
||||
arg_exec = true;
|
||||
break;
|
||||
|
||||
OPTION_LONG("push-fd", "FD", "Pass the specified fd along with method call"): {
|
||||
if (!GREEDY_REALLOC(arg_push_fds.fds, arg_push_fds.n_fds + 1))
|
||||
return log_oom();
|
||||
|
||||
_cleanup_close_ int add_fd = -EBADF;
|
||||
if (STARTSWITH_SET(optarg, "/", "./")) {
|
||||
if (STARTSWITH_SET(arg, "/", "./")) {
|
||||
/* We usually expect a numeric fd spec, but as an extension let's treat this
|
||||
* as a path to open in read-only mode in case this is clearly an absolute or
|
||||
* relative path */
|
||||
add_fd = open(optarg, O_CLOEXEC|O_RDONLY|O_NOCTTY);
|
||||
add_fd = open(arg, O_CLOEXEC|O_RDONLY|O_NOCTTY);
|
||||
if (add_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open '%s': %m", optarg);
|
||||
return log_error_errno(errno, "Failed to open '%s': %m", arg);
|
||||
} else {
|
||||
int parsed_fd = parse_fd(optarg);
|
||||
int parsed_fd = parse_fd(arg);
|
||||
if (parsed_fd < 0)
|
||||
return log_error_errno(parsed_fd, "Failed to parse --push-fd= parameter: %s", optarg);
|
||||
return log_error_errno(parsed_fd, "Failed to parse --push-fd= parameter: %s", arg);
|
||||
|
||||
/* Make a copy, so that the same fd could be used multiple times in a reasonable
|
||||
* way. This also validates the fd early */
|
||||
@@ -283,24 +245,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_push_fds.fds[arg_push_fds.n_fds++] = TAKE_FD(add_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_NO_ASK_PASSWORD:
|
||||
arg_ask_password = false;
|
||||
break;
|
||||
|
||||
case ARG_USER:
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
/* If more than one reply is expected, imply JSON-SEQ output, and set SD_JSON_FORMAT_FLUSH */
|
||||
@@ -309,6 +253,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
strv_sort_uniq(arg_graceful);
|
||||
|
||||
*ret_args = option_parser_get_args(&state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -377,6 +322,8 @@ static void get_info_data_done(GetInfoData *d) {
|
||||
d->interfaces = strv_free(d->interfaces);
|
||||
}
|
||||
|
||||
VERB(verb_info, "info", "ADDRESS", 2, 2, 0, "Show service information");
|
||||
VERB(verb_info, "list-interfaces", "ADDRESS", 2, 2, 0, "List interfaces implemented by service");
|
||||
static int verb_info(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
|
||||
const char *url;
|
||||
@@ -470,6 +417,9 @@ typedef struct GetInterfaceDescriptionData {
|
||||
const char *description;
|
||||
} GetInterfaceDescriptionData;
|
||||
|
||||
VERB(verb_introspect, "introspect", "ADDRESS [INTERFACE…]", 2, VERB_ANY, 0, "Show interface definition");
|
||||
VERB(verb_introspect, "list-methods", "ADDRESS [INTERFACE…]", 2, VERB_ANY, 0,
|
||||
"List methods implemented by services or specific interfaces");
|
||||
static int verb_introspect(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
|
||||
_cleanup_strv_free_ char **auto_interfaces = NULL;
|
||||
@@ -795,6 +745,7 @@ static int varlink_call_and_upgrade(const char *url, const char *method, sd_json
|
||||
return 0;
|
||||
}
|
||||
|
||||
VERB(verb_call, "call", "ADDRESS METHOD [PARAMS]", 3, VERB_ANY, 0, "Invoke method");
|
||||
static int verb_call(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *jp = NULL;
|
||||
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
|
||||
@@ -1068,6 +1019,7 @@ static int verb_call(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
VERB(verb_validate_idl, "validate-idl", "[FILE]", 1, 2, 0, "Validate interface description");
|
||||
static int verb_validate_idl(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *vi = NULL;
|
||||
_cleanup_free_ char *text = NULL;
|
||||
@@ -1117,6 +1069,7 @@ static int verb_validate_idl(int argc, char *argv[], uintptr_t _data, void *user
|
||||
return 0;
|
||||
}
|
||||
|
||||
VERB_NOARG(verb_list_registry, "list-registry", "Show list of services in the service registry");
|
||||
static int verb_list_registry(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
int r;
|
||||
|
||||
@@ -1216,32 +1169,17 @@ static int verb_list_registry(int argc, char *argv[], uintptr_t _data, void *use
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int varlinkctl_main(int argc, char *argv[]) {
|
||||
static const Verb verbs[] = {
|
||||
{ "info", 2, 2, 0, verb_info },
|
||||
{ "list-interfaces", 2, 2, 0, verb_info },
|
||||
{ "introspect", 2, VERB_ANY, 0, verb_introspect },
|
||||
{ "list-methods", 2, VERB_ANY, 0, verb_introspect },
|
||||
{ "call", 3, VERB_ANY, 0, verb_call },
|
||||
{ "list-registry", VERB_ANY, 1, 0, verb_list_registry },
|
||||
{ "validate-idl", 1, 2, 0, verb_validate_idl },
|
||||
{ "help", VERB_ANY, VERB_ANY, 0, verb_help },
|
||||
{}
|
||||
};
|
||||
|
||||
return dispatch_verb(argc, argv, verbs, NULL);
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
char **args = NULL; /* unnecessary initialization to appease gcc <= 13 */
|
||||
r = parse_argv(argc, argv, &args);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
return varlinkctl_main(argc, argv);
|
||||
return dispatch_verb_with_args(args, NULL);
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
||||
|
||||
Reference in New Issue
Block a user