]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal-remote: convert to the new option parser
authorDaan De Meyer <daan@amutable.com>
Wed, 8 Apr 2026 14:31:00 +0000 (14:31 +0000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 22 Apr 2026 18:05:38 +0000 (20:05 +0200)
Replace the getopt_long()-based parser with the FOREACH_OPTION /
OPTION_* macros from src/shared/options.h, mirroring the recent
conversions of nspawn and vmspawn. Each option's metadata (long
name, short name, metavar and help text) now lives next to its
parsing logic, and the --help text is generated from those
definitions via option_parser_get_help_table() instead of being
hard-coded.

Positional file arguments are collected via
option_parser_get_args() rather than strv_skip(argv, optind).

src/journal-remote/journal-remote-main.c

index 9cb84bbe1e64b2b2825c340f6dec261b197f8366..d5277ad7ef1b3a7cec1cbc005ca7b1481081ce37 100644 (file)
@@ -1,6 +1,5 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <getopt.h>
 #include <unistd.h>
 
 #include "sd-daemon.h"
@@ -12,6 +11,7 @@
 #include "daemon-util.h"
 #include "extract-word.h"
 #include "fd-util.h"
+#include "format-table.h"
 #include "format-util.h"
 #include "fileio.h"
 #include "hashmap.h"
@@ -21,6 +21,7 @@
 #include "logs-show.h"
 #include "main-func.h"
 #include "microhttpd-util.h"
+#include "options.h"
 #include "parse-argument.h"
 #include "parse-helpers.h"
 #include "parse-util.h"
@@ -838,155 +839,120 @@ static int parse_config(void) {
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
+        _cleanup_(table_unrefp) Table *options = NULL;
         int r;
 
         r = terminal_urlify_man("systemd-journal-remote.service", "8", &link);
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...] {FILE|-}...\n\n"
-               "Write external journal events to journal file(s).\n\n"
-               "  -h --help                 Show this help\n"
-               "     --version              Show package version\n"
-               "     --url=URL              Read events from systemd-journal-gatewayd at URL\n"
-               "     --getter=COMMAND       Read events from the output of COMMAND\n"
-               "     --listen-raw=ADDR      Listen for connections at ADDR\n"
-               "     --listen-http=ADDR     Listen for HTTP connections at ADDR\n"
-               "     --listen-https=ADDR    Listen for HTTPS connections at ADDR\n"
-               "  -o --output=FILE|DIR      Write output to FILE or DIR/external-*.journal\n"
-               "     --compress[=BOOL]      Use compression in the output journal (default: yes)\n"
-               "     --seal[=BOOL]          Use event sealing (default: no)\n"
-               "     --key=FILENAME         SSL key in PEM format (default:\n"
-               "                            \"" PRIV_KEY_FILE "\")\n"
-               "     --cert=FILENAME        SSL certificate in PEM format (default:\n"
-               "                            \"" CERT_FILE "\")\n"
-               "     --trust=FILENAME|all   SSL CA certificate or disable checking (default:\n"
-               "                            \"" TRUST_FILE "\")\n"
-               "     --gnutls-log=CATEGORY...\n"
-               "                            Specify a list of gnutls logging categories\n"
-               "     --split-mode=none|host How many output files to create\n"
-               "\nNote: file descriptors from sd_listen_fds() will be consumed, too.\n"
-               "\nSee the %s for details.\n",
+        r = option_parser_get_help_table(&options);
+        if (r < 0)
+                return r;
+
+        printf("%s [OPTIONS...] {FILE|-}...\n"
+               "\n%sWrite external journal events to journal file(s).%s\n"
+               "\n%sOptions:%s\n",
                program_invocation_short_name,
+               ansi_highlight(),
+               ansi_normal(),
+               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 consumed, too.\n"
+               "\nSee the %s for details.\n",
                link);
 
         return 0;
 }
 
 static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_URL,
-                ARG_LISTEN_RAW,
-                ARG_LISTEN_HTTP,
-                ARG_LISTEN_HTTPS,
-                ARG_GETTER,
-                ARG_SPLIT_MODE,
-                ARG_COMPRESS,
-                ARG_SEAL,
-                ARG_KEY,
-                ARG_CERT,
-                ARG_TRUST,
-                ARG_GNUTLS_LOG,
-        };
-
-        static const struct option options[] = {
-                { "help",         no_argument,       NULL, 'h'              },
-                { "version",      no_argument,       NULL, ARG_VERSION      },
-                { "url",          required_argument, NULL, ARG_URL          },
-                { "getter",       required_argument, NULL, ARG_GETTER       },
-                { "listen-raw",   required_argument, NULL, ARG_LISTEN_RAW   },
-                { "listen-http",  required_argument, NULL, ARG_LISTEN_HTTP  },
-                { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
-                { "output",       required_argument, NULL, 'o'              },
-                { "split-mode",   required_argument, NULL, ARG_SPLIT_MODE   },
-                { "compress",     optional_argument, NULL, ARG_COMPRESS     },
-                { "seal",         optional_argument, NULL, ARG_SEAL         },
-                { "key",          required_argument, NULL, ARG_KEY          },
-                { "cert",         required_argument, NULL, ARG_CERT         },
-                { "trust",        required_argument, NULL, ARG_TRUST        },
-                { "gnutls-log",   required_argument, NULL, ARG_GNUTLS_LOG   },
-                {}
-        };
-
-        int c, r;
+        int r;
         bool type_a, type_b;
 
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "ho:", 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_URL:
-                        r = free_and_strdup_warn(&arg_url, optarg);
+                OPTION_LONG("url", "URL", "Read events from systemd-journal-gatewayd at URL"):
+                        r = free_and_strdup_warn(&arg_url, arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_GETTER:
-                        r = free_and_strdup_warn(&arg_getter, optarg);
+                OPTION_LONG("getter", "COMMAND", "Read events from the output of COMMAND"):
+                        r = free_and_strdup_warn(&arg_getter, arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_LISTEN_RAW:
-                        r = free_and_strdup_warn(&arg_listen_raw, optarg);
+                OPTION_LONG("listen-raw", "ADDR", "Listen for connections at ADDR"):
+                        r = free_and_strdup_warn(&arg_listen_raw, arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_LISTEN_HTTP:
+                OPTION_LONG("listen-http", "ADDR", "Listen for HTTP connections at ADDR"):
                         if (arg_listen_http || http_socket >= 0)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Cannot currently use --listen-http= more than once");
 
-                        r = negative_fd(optarg);
+                        r = negative_fd(arg);
                         if (r >= 0)
                                 http_socket = r;
                         else {
-                                r = free_and_strdup_warn(&arg_listen_http, optarg);
+                                r = free_and_strdup_warn(&arg_listen_http, arg);
                                 if (r < 0)
                                         return r;
                         }
                         break;
 
-                case ARG_LISTEN_HTTPS:
+                OPTION_LONG("listen-https", "ADDR", "Listen for HTTPS connections at ADDR"):
                         if (arg_listen_https || https_socket >= 0)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Cannot currently use --listen-https= more than once");
 
-                        r = negative_fd(optarg);
+                        r = negative_fd(arg);
                         if (r >= 0)
                                 https_socket = r;
                         else {
-                                r = free_and_strdup_warn(&arg_listen_https, optarg);
+                                r = free_and_strdup_warn(&arg_listen_https, arg);
                                 if (r < 0)
                                         return r;
                         }
                         break;
 
-                case ARG_KEY:
-                        r = free_and_strdup_warn(&arg_key, optarg);
+                OPTION_LONG("key", "FILENAME", "SSL key in PEM format (default: \"" PRIV_KEY_FILE "\")"):
+                        r = free_and_strdup_warn(&arg_key, arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_CERT:
-                        r = free_and_strdup_warn(&arg_cert, optarg);
+                OPTION_LONG("cert", "FILENAME", "SSL certificate in PEM format (default: \"" CERT_FILE "\")"):
+                        r = free_and_strdup_warn(&arg_cert, arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_TRUST:
+                OPTION_LONG("trust", "FILENAME|all",
+                            "SSL CA certificate or disable checking (default: \"" TRUST_FILE "\")"):
 #if HAVE_GNUTLS
-                        r = free_and_strdup_warn(&arg_trust, optarg);
+                        r = free_and_strdup_warn(&arg_trust, arg);
                         if (r < 0)
                                 return r;
 #else
@@ -994,33 +960,35 @@ static int parse_argv(int argc, char *argv[]) {
 #endif
                         break;
 
-                case 'o':
-                        r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_output);
+                OPTION('o', "output", "FILE|DIR", "Write output to FILE or DIR/external-*.journal"):
+                        r = parse_path_argument(arg, /* suppress_root= */ false, &arg_output);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_SPLIT_MODE:
-                        arg_split_mode = journal_write_split_mode_from_string(optarg);
+                OPTION_LONG("split-mode", "none|host", "How many output files to create"):
+                        arg_split_mode = journal_write_split_mode_from_string(arg);
                         if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
-                                return log_error_errno(arg_split_mode, "Invalid split mode: %s", optarg);
+                                return log_error_errno(arg_split_mode, "Invalid split mode: %s", arg);
                         break;
 
-                case ARG_COMPRESS:
-                        r = parse_boolean_argument("--compress", optarg, &arg_compress);
+                OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "compress", "BOOL",
+                                  "Use compression in the output journal (default: yes)"):
+                        r = parse_boolean_argument("--compress", arg, &arg_compress);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_SEAL:
-                        r = parse_boolean_argument("--seal", optarg, &arg_seal);
+                OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "seal", "BOOL",
+                                  "Use event sealing (default: no)"):
+                        r = parse_boolean_argument("--seal", arg, &arg_seal);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_GNUTLS_LOG:
+                OPTION_LONG("gnutls-log", "CATEGORY,...", "Specify a list of gnutls logging categories"):
 #if HAVE_GNUTLS
-                        for (const char *p = optarg;;) {
+                        for (const char *p = arg;;) {
                                 _cleanup_free_ char *word = NULL;
 
                                 r = extract_first_word(&p, &word, ",", 0);
@@ -1036,15 +1004,9 @@ static int parse_argv(int argc, char *argv[]) {
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --gnutls-log= is not available.");
 #endif
                         break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached();
                 }
 
-        arg_files = strv_copy(strv_skip(argv, optind));
+        arg_files = strv_copy(option_parser_get_args(&state));
         if (!arg_files)
                 return log_oom();