]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal-upload: convert to OPTION macros
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Wed, 29 Apr 2026 22:05:02 +0000 (00:05 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Tue, 5 May 2026 11:49:51 +0000 (13:49 +0200)
The help strings are adjusted a tiny bit.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
src/journal-remote/journal-upload.c

index 23bb48f6876204a3bf1ee26747c3ff7b3f48a2fa..f4b698ae415d61e14ee68c24221fe19df00cf8a8 100644 (file)
@@ -1,7 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <fcntl.h>
-#include <getopt.h>
 #include <stdio.h>
 #include <unistd.h>
 
 #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"
 #include "hashmap.h"
+#include "help-util.h"
 #include "journal-header-util.h"
 #include "journal-upload.h"
 #include "journal-util.h"
@@ -28,9 +29,9 @@
 #include "logs-show.h"
 #include "main-func.h"
 #include "mkdir.h"
+#include "options.h"
 #include "parse-argument.h"
 #include "parse-helpers.h"
-#include "pretty-print.h"
 #include "process-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -683,194 +684,145 @@ 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-upload.service", "8", &link);
+        r = option_parser_get_help_table(&options);
         if (r < 0)
-                return log_oom();
+                return r;
 
-        printf("%s -u URL {FILE|-}...\n\n"
-               "Upload journal events to a remote server.\n\n"
-               "  -h --help                 Show this help\n"
-               "     --version              Show package version\n"
-               "  -u --url=URL              Upload to this address (default port "
-                                            STRINGIFY(DEFAULT_PORT) ")\n"
-               "     --key=FILENAME         Specify key in PEM format (default:\n"
-               "                            \"" PRIV_KEY_FILE "\")\n"
-               "     --cert=FILENAME        Specify certificate in PEM format (default:\n"
-               "                            \"" CERT_FILE "\")\n"
-               "     --trust=FILENAME|all   Specify CA certificate or disable checking (default:\n"
-               "                            \"" TRUST_FILE "\")\n"
-               "     --system               Use the system journal\n"
-               "     --user                 Use the user journal for the current user\n"
-               "  -m --merge                Use  all available journals\n"
-               "  -M --machine=CONTAINER    Operate on local container\n"
-               "     --namespace=NAMESPACE  Use journal files from namespace\n"
-               "  -D --directory=PATH       Use journal files from directory\n"
-               "     --file=PATH            Use this journal file\n"
-               "     --cursor=CURSOR        Start at the specified cursor\n"
-               "     --after-cursor=CURSOR  Start after the specified cursor\n"
-               "     --follow[=BOOL]        Do [not] wait for input\n"
-               "     --save-state[=FILE]    Save uploaded cursors (default \n"
-               "                            " STATE_FILE ")\n"
-               "\nSee the %s for details.\n",
-               program_invocation_short_name,
-               link);
+        help_cmdline("-u URL {FILE|-}...");
+        help_abstract("Upload journal events to a remote server.");
+
+        help_section("Options");
+        r = table_print_or_warn(options);
+        if (r < 0)
+                return r;
 
+        help_man_page_reference("systemd-journal-upload.service", "8");
         return 0;
 }
 
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_KEY,
-                ARG_CERT,
-                ARG_TRUST,
-                ARG_USER,
-                ARG_SYSTEM,
-                ARG_FILE,
-                ARG_CURSOR,
-                ARG_AFTER_CURSOR,
-                ARG_FOLLOW,
-                ARG_SAVE_STATE,
-                ARG_NAMESPACE,
-        };
-
-        static const struct option options[] = {
-                { "help",         no_argument,       NULL, 'h'                },
-                { "version",      no_argument,       NULL, ARG_VERSION        },
-                { "url",          required_argument, NULL, 'u'                },
-                { "key",          required_argument, NULL, ARG_KEY            },
-                { "cert",         required_argument, NULL, ARG_CERT           },
-                { "trust",        required_argument, NULL, ARG_TRUST          },
-                { "system",       no_argument,       NULL, ARG_SYSTEM         },
-                { "user",         no_argument,       NULL, ARG_USER           },
-                { "merge",        no_argument,       NULL, 'm'                },
-                { "machine",      required_argument, NULL, 'M'                },
-                { "namespace",    required_argument, NULL, ARG_NAMESPACE      },
-                { "directory",    required_argument, NULL, 'D'                },
-                { "file",         required_argument, NULL, ARG_FILE           },
-                { "cursor",       required_argument, NULL, ARG_CURSOR         },
-                { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR   },
-                { "follow",       optional_argument, NULL, ARG_FOLLOW         },
-                { "save-state",   optional_argument, NULL, ARG_SAVE_STATE     },
-                {}
-        };
-
-        int c, r;
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
+        int r;
 
         assert(argc >= 0);
         assert(argv);
+        assert(ret_args);
+
+        OptionParser opts = { argc, argv };
 
-        while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0)
+        FOREACH_OPTION_OR_RETURN(c, &opts)
                 switch (c) {
-                case 'h':
+
+                OPTION_COMMON_HELP:
                         return help();
 
-                case ARG_VERSION:
+                OPTION_COMMON_VERSION:
                         return version();
 
-                case 'u':
-                        r = free_and_strdup_warn(&arg_url, optarg);
+                OPTION('u', "url", "URL",
+                       "Upload to this address (default port " STRINGIFY(DEFAULT_PORT) ")"):
+                        r = free_and_strdup_warn(&arg_url, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_KEY:
-                        r = free_and_strdup_warn(&arg_key, optarg);
+                OPTION_LONG("key", "FILENAME",
+                            "Specify key in PEM format (default: \"" PRIV_KEY_FILE "\")"):
+                        r = free_and_strdup_warn(&arg_key, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_CERT:
-                        r = free_and_strdup_warn(&arg_cert, optarg);
+                OPTION_LONG("cert", "FILENAME",
+                            "Specify certificate in PEM format (default: \"" CERT_FILE "\")"):
+                        r = free_and_strdup_warn(&arg_cert, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_TRUST:
-                        r = free_and_strdup_warn(&arg_trust, optarg);
+                OPTION_LONG("trust", "FILENAME|all",
+                            "Specify CA certificate or disable checking (default: \"" TRUST_FILE "\")"):
+                        r = free_and_strdup_warn(&arg_trust, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_SYSTEM:
+                OPTION_LONG("system", NULL, "Use the system journal"):
                         arg_journal_type |= SD_JOURNAL_SYSTEM;
                         break;
 
-                case ARG_USER:
+                OPTION_LONG("user", NULL, "Use the user journal for the current user"):
                         arg_journal_type |= SD_JOURNAL_CURRENT_USER;
                         break;
 
-                case 'm':
+                OPTION('m', "merge", NULL, "Use all available journals"):
                         arg_merge = true;
                         break;
 
-                case 'M':
-                        r = free_and_strdup_warn(&arg_machine, optarg);
+                OPTION_COMMON_MACHINE:
+                        r = free_and_strdup_warn(&arg_machine, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_NAMESPACE:
-                        if (streq(optarg, "*")) {
+                OPTION_LONG("namespace", "NAMESPACE", "Use journal files from namespace"):
+                        if (streq(opts.arg, "*")) {
                                 arg_namespace_flags = SD_JOURNAL_ALL_NAMESPACES;
                                 arg_namespace = mfree(arg_namespace);
                                 r = 0;
-                        } else if (startswith(optarg, "+")) {
+                        } else if (startswith(opts.arg, "+")) {
                                 arg_namespace_flags = SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE;
-                                r = free_and_strdup_warn(&arg_namespace, optarg + 1);
-                        } else if (isempty(optarg)) {
+                                r = free_and_strdup_warn(&arg_namespace, opts.arg + 1);
+                        } else if (isempty(opts.arg)) {
                                 arg_namespace_flags = 0;
                                 arg_namespace = mfree(arg_namespace);
                                 r = 0;
                         } else {
                                 arg_namespace_flags = 0;
-                                r = free_and_strdup_warn(&arg_namespace, optarg);
+                                r = free_and_strdup_warn(&arg_namespace, opts.arg);
                         }
                         if (r < 0)
                                 return r;
                         break;
 
-                case 'D':
-                        r = free_and_strdup_warn(&arg_directory, optarg);
+                OPTION('D', "directory", "PATH", "Use journal files from this directory"):
+                        r = free_and_strdup_warn(&arg_directory, opts.arg);
                         if (r < 0)
                                 return r;
                         break;
 
-                case ARG_FILE:
-                        r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
+                OPTION_LONG("file", "PATH", "Use this journal file"):
+                        r = glob_extend(&arg_file, opts.arg, GLOB_NOCHECK);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to add paths: %m");
                         break;
 
-                case ARG_CURSOR:
-                case ARG_AFTER_CURSOR:
-                        r = free_and_strdup_warn(&arg_cursor, optarg);
+                OPTION_LONG_DATA("after-cursor", "CURSOR", /* data= */ true,
+                                 "Start after the specified cursor"): {}
+                OPTION_LONG_DATA("cursor", "CURSOR", /* data= */ false,
+                                 "Start at the specified cursor"):
+                        r = free_and_strdup_warn(&arg_cursor, opts.arg);
                         if (r < 0)
                                 return r;
-                        arg_after_cursor = c == ARG_AFTER_CURSOR;
+                        arg_after_cursor = opts.opt->data;
                         break;
 
-                case ARG_FOLLOW:
-                        r = parse_boolean_argument("--follow", optarg, NULL);
+                OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "follow", "BOOL",
+                                  "Whether to wait for input"):
+                        r = parse_boolean_argument("--follow", opts.arg, NULL);
                         if (r < 0)
                                 return r;
                         arg_follow = r;
                         break;
 
-                case ARG_SAVE_STATE:
-                        r = free_and_strdup_warn(&arg_save_state, optarg ?: STATE_FILE);
+                OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "save-state", "FILE",
+                                  "Save uploaded cursors (default " STATE_FILE ")"):
+                        r = free_and_strdup_warn(&arg_save_state, opts.arg ?: STATE_FILE);
                         if (r < 0)
                                 return r;
                         break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached();
                 }
 
         if (!arg_url)
@@ -881,10 +833,12 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Options --key= and --cert= must be used together.");
 
-        if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type))
+        char **args = option_parser_get_args(&opts);
+        if (!strv_isempty(args) && (arg_directory || arg_file || arg_machine || arg_journal_type))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Input arguments make no sense with journal input.");
 
+        *ret_args = args;
         return 1;
 }
 
@@ -911,6 +865,7 @@ static int open_journal(sd_journal **j) {
 static int run(int argc, char **argv) {
         _cleanup_(destroy_uploader) Uploader u = {};
         _unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+        char **args = NULL;
         bool use_journal;
         int r;
 
@@ -920,7 +875,7 @@ static int run(int argc, char **argv) {
         if (r < 0)
                 return r;
 
-        r = parse_argv(argc, argv);
+        r = parse_argv(argc, argv, &args);
         if (r <= 0)
                 return r;
 
@@ -947,7 +902,7 @@ static int run(int argc, char **argv) {
         log_debug("%s running as pid "PID_FMT,
                   program_invocation_short_name, getpid_cached());
 
-        use_journal = optind >= argc;
+        use_journal = strv_isempty(args);
         if (use_journal) {
                 sd_journal *j;
                 r = open_journal(&j);
@@ -965,7 +920,7 @@ static int run(int argc, char **argv) {
                                       "STATUS=Processing input...",
                                       NOTIFY_STOPPING_MESSAGE);
 
-        for (;;) {
+        for (size_t i = 0;;) {
                 r = sd_event_get_state(u.event);
                 if (r < 0)
                         return r;
@@ -978,11 +933,11 @@ static int run(int argc, char **argv) {
 
                         r = check_journal_input(&u);
                 } else if (u.input < 0 && !use_journal) {
-                        if (optind >= argc)
+                        if (!args[i])
                                 return 0;
 
-                        log_debug("Using %s as input.", argv[optind]);
-                        r = open_file_for_upload(&u, argv[optind++]);
+                        log_debug("Using %s as input.", args[i]);
+                        r = open_file_for_upload(&u, args[i++]);
                 }
                 if (r < 0)
                         return r;