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;
        bool type_a, type_b;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
                switch(c) {

                case 'h':
                        return help();

                case ARG_VERSION:
                        return version();

                case ARG_URL:
                        if (arg_url)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "cannot currently set more than one --url");

                        arg_url = optarg;
                        break;

                case ARG_GETTER:
                        if (arg_getter)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "cannot currently use --getter more than once");

                        arg_getter = optarg;
                        break;

                case ARG_LISTEN_RAW:
                        if (arg_listen_raw)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "cannot currently use --listen-raw more than once");

                        arg_listen_raw = optarg;
                        break;

                case ARG_LISTEN_HTTP:
                        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);
                        if (r >= 0)
                                http_socket = r;
                        else
                                arg_listen_http = optarg;
                        break;

                case ARG_LISTEN_HTTPS:
                        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);
                        if (r >= 0)
                                https_socket = r;
                        else
                                arg_listen_https = optarg;

                        break;

                case ARG_KEY:
                        if (arg_key)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Key file specified twice");

                        arg_key = strdup(optarg);
                        if (!arg_key)
                                return log_oom();

                        break;

                case ARG_CERT:
                        if (arg_cert)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Certificate file specified twice");

                        arg_cert = strdup(optarg);
                        if (!arg_cert)
                                return log_oom();

                        break;

                case ARG_TRUST:
                        if (arg_trust || arg_trust_all)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Confusing trusted CA configuration");

                        if (streq(optarg, "all"))
                                arg_trust_all = true;
                        else {
#if HAVE_GNUTLS
                                arg_trust = strdup(optarg);
                                if (!arg_trust)
                                        return log_oom();
#else
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Option --trust is not available.");
#endif
                        }

                        break;

                case 'o':
                        if (arg_output)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "cannot use --output/-o more than once");

                        arg_output = optarg;
                        break;

                case ARG_SPLIT_MODE:
                        arg_split_mode = journal_write_split_mode_from_string(optarg);
                        if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Invalid split mode: %s", optarg);
                        break;

                case ARG_COMPRESS:
                        if (optarg) {
                                r = parse_boolean(optarg);
                                if (r < 0)
                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                               "Failed to parse --compress= parameter.");

                                arg_compress = !!r;
                        } else
                                arg_compress = true;

                        break;

                case ARG_SEAL:
                        if (optarg) {
                                r = parse_boolean(optarg);
                                if (r < 0)
                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                               "Failed to parse --seal= parameter.");

                                arg_seal = !!r;
                        } else
                                arg_seal = true;

                        break;

                case ARG_GNUTLS_LOG: {
#if HAVE_GNUTLS
                        const char* p = optarg;
                        for (;;) {
                                _cleanup_free_ char *word = NULL;

                                r = extract_first_word(&p, &word, ",", 0);
                                if (r < 0)
                                        return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m");
                                if (r == 0)
                                        break;

                                if (strv_push(&arg_gnutls_log, word) < 0)
                                        return log_oom();

                                word = NULL;
                        }
                        break;
#else
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                               "Option --gnutls-log is not available.");
#endif
                }

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unknown option code.");
                }

        if (optind < argc)
                arg_files = argv + optind;

        type_a = arg_getter || !strv_isempty(arg_files);
        type_b = arg_url
                || arg_listen_raw
                || arg_listen_http || arg_listen_https
                || sd_listen_fds(false) > 0;
        if (type_a && type_b)
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                       "Cannot use file input or --getter with "
                                       "--arg-listen-... or socket activation.");
        if (type_a) {
                if (!arg_output)
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                               "Option --output must be specified with file input or --getter.");

                if (!IN_SET(arg_split_mode, JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID))
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                               "For active sources, only --split-mode=none is allowed.");

                arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
        }

        if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
                arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;

        if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output) {
                if (is_dir(arg_output, true) > 0)
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                               "For SplitMode=none, output must be a file.");
                if (!endswith(arg_output, ".journal"))
                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                               "For SplitMode=none, output file name must end with .journal.");
        }

        if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
            && arg_output && is_dir(arg_output, true) <= 0)
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                       "For SplitMode=host, output must be a directory.");

        log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
                  journal_write_split_mode_to_string(arg_split_mode),
                  strna(arg_key),
                  strna(arg_cert),
                  strna(arg_trust));

        return 1 /* work to do */;
}