From: Zbigniew Jędrzejewski-Szmek Date: Thu, 23 Apr 2026 20:27:59 +0000 (+0200) Subject: socket-activate: convert to the new option parser X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90a068ab5d1fa671a4d4e75e3890a33a5bd00136;p=thirdparty%2Fsystemd.git socket-activate: convert to the new option parser --help is identical except for whitespace and common option strings. Co-developed-by: Claude Opus 4.7 --- diff --git a/src/socket-activate/socket-activate.c b/src/socket-activate/socket-activate.c index e7102b62a1a..2f0c81a1111 100644 --- a/src/socket-activate/socket-activate.c +++ b/src/socket-activate/socket-activate.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include #include @@ -14,9 +13,11 @@ #include "errno-util.h" #include "escape.h" #include "fd-util.h" +#include "format-table.h" #include "format-util.h" #include "log.h" #include "main-func.h" +#include "options.h" #include "pidfd-util.h" #include "pidref.h" #include "pretty-print.h" @@ -320,83 +321,63 @@ static int install_chld_handler(void) { static int help(void) { _cleanup_free_ char *link = NULL; + _cleanup_(table_unrefp) Table *options = NULL; int r; r = terminal_urlify_man("systemd-socket-activate", "1", &link); if (r < 0) return log_oom(); + r = option_parser_get_help_table(&options); + if (r < 0) + return r; + printf("%s [OPTIONS...] COMMAND ...\n" "\n%sListen on sockets and launch child on connection.%s\n" - "\nOptions:\n" - " -h --help Show this help and exit\n" - " --version Print version string and exit\n" - " -l --listen=ADDR Listen for raw connections at ADDR\n" - " -d --datagram Listen on datagram instead of stream socket\n" - " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n" - " -a --accept Spawn separate child for each connection\n" - " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n" - " --fdname=NAME[:NAME...] Specify names for file descriptors\n" - " --inetd Enable inetd file descriptor passing protocol\n" - " --now Start instantly instead of waiting for connection\n" - "\nNote: file descriptors from sd_listen_fds() will be passed through.\n" - "\nSee the %s for details.\n", + "\n%sOptions:%s\n", program_invocation_short_name, ansi_highlight(), ansi_normal(), - link); + ansi_underline(), + ansi_normal()); + + r = table_print_or_warn(options); + if (r < 0) + return r; + printf("\nNote: file descriptors from sd_listen_fds() will be passed through.\n" + "\nSee the %s for details.\n", link); return 0; } -static int parse_argv(int argc, char *argv[]) { - enum { - ARG_VERSION = 0x100, - ARG_FDNAME, - ARG_SEQPACKET, - ARG_INETD, - ARG_NOW, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "datagram", no_argument, NULL, 'd' }, - { "seqpacket", no_argument, NULL, ARG_SEQPACKET }, - { "listen", required_argument, NULL, 'l' }, - { "accept", no_argument, NULL, 'a' }, - { "setenv", required_argument, NULL, 'E' }, - { "environment", required_argument, NULL, 'E' }, /* legacy alias */ - { "fdname", required_argument, NULL, ARG_FDNAME }, - { "inetd", no_argument, NULL, ARG_INETD }, - { "now", no_argument, NULL, ARG_NOW }, - {} - }; - - int c, r; - +static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argc >= 0); assert(argv); + assert(remaining_args); + + OptionParser state = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION }; + const char *arg; + int r; - /* 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, "+hl:aE:d", options, NULL)) >= 0) + 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 'l': - r = strv_extend(&arg_listen, optarg); + OPTION('l', "listen", "ADDR", + "Listen for raw connections at ADDR"): + r = strv_extend(&arg_listen, arg); if (r < 0) return log_oom(); break; - case 'd': + OPTION('d', "datagram", NULL, + "Listen on datagram instead of stream socket"): if (arg_socket_type == SOCK_SEQPACKET) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--datagram may not be combined with --seqpacket."); @@ -404,7 +385,8 @@ static int parse_argv(int argc, char *argv[]) { arg_socket_type = SOCK_DGRAM; break; - case ARG_SEQPACKET: + OPTION_LONG("seqpacket", NULL, + "Listen on SOCK_SEQPACKET instead of stream socket"): if (arg_socket_type == SOCK_DGRAM) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--seqpacket may not be combined with --datagram."); @@ -412,20 +394,24 @@ static int parse_argv(int argc, char *argv[]) { arg_socket_type = SOCK_SEQPACKET; break; - case 'a': + OPTION('a', "accept", NULL, + "Spawn separate child for each connection"): arg_accept = true; break; - case 'E': - r = strv_env_replace_strdup_passthrough(&arg_setenv, optarg); + OPTION('E', "setenv", "NAME[=VALUE]", + "Pass an environment variable to children"): {} + OPTION_LONG("environment", "NAME[=VALUE]", /* help= */ NULL): /* legacy alias */ + r = strv_env_replace_strdup_passthrough(&arg_setenv, arg); if (r < 0) - return log_error_errno(r, "Cannot assign environment variable %s: %m", optarg); + return log_error_errno(r, "Cannot assign environment variable %s: %m", arg); break; - case ARG_FDNAME: { + OPTION_LONG("fdname", "NAME[:NAME...]", + "Specify names for file descriptors"): { _cleanup_strv_free_ char **names = NULL; - names = strv_split(optarg, ":"); + names = strv_split(arg, ":"); if (!names) return log_oom(); @@ -446,22 +432,19 @@ static int parse_argv(int argc, char *argv[]) { break; } - case ARG_INETD: + OPTION_LONG("inetd", NULL, + "Enable inetd file descriptor passing protocol"): arg_inetd = true; break; - case ARG_NOW: + OPTION_LONG("now", NULL, + "Start instantly instead of waiting for connection"): arg_now = true; break; - - case '?': - return -EINVAL; - - default: - assert_not_reached(); } - if (optind == argc) + *remaining_args = option_parser_get_args(&state); + if (strv_isempty(*remaining_args)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "%s: command to execute is missing.", program_invocation_short_name); @@ -488,11 +471,12 @@ static int run(int argc, char **argv) { log_setup(); - r = parse_argv(argc, argv); + char **args = NULL; + r = parse_argv(argc, argv, &args); if (r <= 0) return r; - exec_argv = strv_copy(argv + optind); + exec_argv = strv_copy(args); if (!exec_argv) return log_oom();