Convert PID1 to option macros (#42099)
This commit is contained in:
@@ -3031,6 +3031,9 @@ SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
- whenever we receive fds via SCM_RIGHTS make sure none got dropped due to the
|
||||
reception limit the kernel silently enforces.
|
||||
|
||||
- after option+verb introspection is added, add a test to verify that the
|
||||
list in proc-cmdline.c matches the actual option list in systemd and shutdown.
|
||||
|
||||
- write a document explaining how to write correct udev rules. Mention things
|
||||
such as:
|
||||
1. do not do lists of vid/pid matches, use hwdb for that
|
||||
|
||||
@@ -39,27 +39,32 @@ bool invoked_as(char *argv[], const char *token) {
|
||||
}
|
||||
|
||||
bool invoked_by_systemd(void) {
|
||||
static int cached = -1;
|
||||
int r;
|
||||
|
||||
if (cached >= 0)
|
||||
return cached;
|
||||
|
||||
/* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
|
||||
* or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
|
||||
const char *e = getenv("SYSTEMD_EXEC_PID");
|
||||
if (!e)
|
||||
return false;
|
||||
return (cached = false);
|
||||
|
||||
if (streq(e, "*"))
|
||||
/* For testing. */
|
||||
return true;
|
||||
return (cached = true);
|
||||
|
||||
pid_t p;
|
||||
r = parse_pid(e, &p);
|
||||
if (r < 0) {
|
||||
/* We know that systemd sets the variable correctly. Something else must have set it. */
|
||||
log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
|
||||
return false;
|
||||
return (cached = false);
|
||||
}
|
||||
|
||||
return getpid_cached() == p;
|
||||
cached = getpid_cached() == p;
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool argv_looks_like_help(int argc, char **argv) {
|
||||
|
||||
@@ -9,7 +9,7 @@ extern char **saved_argv;
|
||||
void save_argc_argv(int argc, char **argv);
|
||||
|
||||
bool invoked_as(char *argv[], const char *token);
|
||||
bool invoked_by_systemd(void);
|
||||
bool invoked_by_systemd(void) _const_;
|
||||
bool argv_looks_like_help(int argc, char **argv);
|
||||
|
||||
int rename_process_full(const char *comm, const char *invocation);
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#define SYSTEMD_GETOPT_SHORT_OPTIONS "hDbsz:"
|
||||
|
||||
#define COMMON_GETOPT_ARGS \
|
||||
ARG_LOG_LEVEL = 0x100, \
|
||||
ARG_LOG_TARGET, \
|
||||
ARG_LOG_COLOR, \
|
||||
ARG_LOG_LOCATION, \
|
||||
ARG_LOG_TIME
|
||||
|
||||
#define SYSTEMD_GETOPT_ARGS \
|
||||
ARG_UNIT, \
|
||||
ARG_SYSTEM, \
|
||||
ARG_USER, \
|
||||
ARG_TEST, \
|
||||
ARG_NO_PAGER, \
|
||||
ARG_VERSION, \
|
||||
ARG_DUMP_CONFIGURATION_ITEMS, \
|
||||
ARG_DUMP_BUS_PROPERTIES, \
|
||||
ARG_BUS_INTROSPECT, \
|
||||
ARG_DUMP_CORE, \
|
||||
ARG_CRASH_CHVT, \
|
||||
ARG_CRASH_SHELL, \
|
||||
ARG_CRASH_REBOOT, \
|
||||
ARG_CRASH_ACTION, \
|
||||
ARG_CONFIRM_SPAWN, \
|
||||
ARG_SHOW_STATUS, \
|
||||
ARG_DESERIALIZE, \
|
||||
ARG_SWITCHED_ROOT, \
|
||||
ARG_DEFAULT_STD_OUTPUT, \
|
||||
ARG_DEFAULT_STD_ERROR, \
|
||||
ARG_MACHINE_ID, \
|
||||
ARG_SERVICE_WATCHDOGS
|
||||
|
||||
#define SHUTDOWN_GETOPT_ARGS \
|
||||
ARG_EXIT_CODE, \
|
||||
ARG_TIMEOUT
|
||||
|
||||
#define COMMON_GETOPT_OPTIONS \
|
||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL }, \
|
||||
{ "log-target", required_argument, NULL, ARG_LOG_TARGET }, \
|
||||
{ "log-color", optional_argument, NULL, ARG_LOG_COLOR }, \
|
||||
{ "log-location", optional_argument, NULL, ARG_LOG_LOCATION }, \
|
||||
{ "log-time", optional_argument, NULL, ARG_LOG_TIME }
|
||||
|
||||
#define SYSTEMD_GETOPT_OPTIONS \
|
||||
{ "unit", required_argument, NULL, ARG_UNIT }, \
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM }, \
|
||||
{ "user", no_argument, NULL, ARG_USER }, \
|
||||
{ "test", no_argument, NULL, ARG_TEST }, \
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER }, \
|
||||
{ "help", no_argument, NULL, 'h' }, \
|
||||
{ "version", no_argument, NULL, ARG_VERSION }, \
|
||||
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, \
|
||||
{ "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES }, \
|
||||
{ "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT }, \
|
||||
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE }, \
|
||||
{ "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT }, \
|
||||
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, \
|
||||
{ "crash-reboot", optional_argument, NULL, ARG_CRASH_REBOOT }, \
|
||||
{ "crash-action", required_argument, NULL, ARG_CRASH_ACTION }, \
|
||||
{ "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN }, \
|
||||
{ "show-status", optional_argument, NULL, ARG_SHOW_STATUS }, \
|
||||
{ "deserialize", required_argument, NULL, ARG_DESERIALIZE }, \
|
||||
{ "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT }, \
|
||||
{ "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, }, \
|
||||
{ "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, }, \
|
||||
{ "machine-id", required_argument, NULL, ARG_MACHINE_ID }, \
|
||||
{ "service-watchdogs", required_argument, NULL, ARG_SERVICE_WATCHDOGS }
|
||||
|
||||
#define SHUTDOWN_GETOPT_OPTIONS \
|
||||
{ "exit-code", required_argument, NULL, ARG_EXIT_CODE }, \
|
||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT }
|
||||
+44
-16
@@ -5,7 +5,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fileio.h"
|
||||
#include "getopt-defs.h"
|
||||
#include "initrd-util.h"
|
||||
#include "log.h"
|
||||
#include "parse-util.h"
|
||||
@@ -15,18 +14,50 @@
|
||||
#include "strv.h"
|
||||
#include "virt.h"
|
||||
|
||||
typedef enum ArgType {
|
||||
no_argument,
|
||||
required_argument,
|
||||
optional_argument,
|
||||
} ArgType;
|
||||
|
||||
int proc_cmdline_filter_pid1_args(char **argv, char ***ret) {
|
||||
enum {
|
||||
COMMON_GETOPT_ARGS,
|
||||
SYSTEMD_GETOPT_ARGS,
|
||||
SHUTDOWN_GETOPT_ARGS,
|
||||
const struct {
|
||||
const char *name;
|
||||
ArgType has_arg;
|
||||
} options[] = {
|
||||
{ "log-level", required_argument },
|
||||
{ "log-target", required_argument },
|
||||
{ "log-color", optional_argument },
|
||||
{ "log-location", optional_argument },
|
||||
{ "log-time", optional_argument },
|
||||
{ "unit", required_argument },
|
||||
{ "system", no_argument, },
|
||||
{ "user", no_argument, },
|
||||
{ "test", no_argument, },
|
||||
{ "no-pager", no_argument, },
|
||||
{ "help", no_argument, },
|
||||
{ "version", no_argument, },
|
||||
{ "dump-configuration-items", no_argument, },
|
||||
{ "dump-bus-properties", no_argument, },
|
||||
{ "bus-introspect", required_argument },
|
||||
{ "dump-core", optional_argument },
|
||||
{ "crash-chvt", required_argument },
|
||||
{ "crash-vt", required_argument },
|
||||
{ "crash-shell", optional_argument },
|
||||
{ "crash-reboot", optional_argument },
|
||||
{ "crash-action", required_argument },
|
||||
{ "confirm-spawn", optional_argument },
|
||||
{ "show-status", optional_argument },
|
||||
{ "deserialize", required_argument },
|
||||
{ "switched-root", no_argument, },
|
||||
{ "default-standard-output", required_argument },
|
||||
{ "default-standard-error", required_argument },
|
||||
{ "machine-id", required_argument },
|
||||
{ "service-watchdogs", required_argument },
|
||||
{ "exit-code", required_argument },
|
||||
{ "timeout", required_argument },
|
||||
};
|
||||
static const struct option options[] = {
|
||||
COMMON_GETOPT_OPTIONS,
|
||||
SYSTEMD_GETOPT_OPTIONS,
|
||||
SHUTDOWN_GETOPT_OPTIONS,
|
||||
};
|
||||
static const char *short_options = SYSTEMD_GETOPT_SHORT_OPTIONS;
|
||||
const char *short_options = "hDbsz:";
|
||||
|
||||
_cleanup_strv_free_ char **filtered = NULL;
|
||||
int state, r;
|
||||
@@ -108,12 +139,10 @@ int proc_cmdline_filter_pid1_args(char **argv, char ***ret) {
|
||||
}
|
||||
|
||||
int proc_cmdline(char **ret) {
|
||||
const char *e;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */
|
||||
e = secure_getenv("SYSTEMD_PROC_CMDLINE");
|
||||
const char *e = secure_getenv("SYSTEMD_PROC_CMDLINE");
|
||||
if (e)
|
||||
return strdup_to(ret, e);
|
||||
|
||||
@@ -124,13 +153,12 @@ int proc_cmdline(char **ret) {
|
||||
}
|
||||
|
||||
static int proc_cmdline_strv_internal(char ***ret, bool filter_pid1_args) {
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */
|
||||
e = secure_getenv("SYSTEMD_PROC_CMDLINE");
|
||||
const char *e = secure_getenv("SYSTEMD_PROC_CMDLINE");
|
||||
if (e)
|
||||
return strv_split_full(ret, e, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
|
||||
|
||||
|
||||
+184
-215
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/vt.h>
|
||||
#include <stdlib.h>
|
||||
@@ -19,6 +18,7 @@
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ansi-color.h"
|
||||
#include "apparmor-setup.h"
|
||||
#include "architecture.h"
|
||||
#include "argv-util.h"
|
||||
@@ -47,8 +47,10 @@
|
||||
#include "fd-util.h"
|
||||
#include "fdset.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
#include "format-util.h"
|
||||
#include "getopt-defs.h"
|
||||
#include "glyph-util.h"
|
||||
#include "help-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "id128-util.h"
|
||||
@@ -73,13 +75,13 @@
|
||||
#include "mkdir-label.h"
|
||||
#include "mount-setup.h"
|
||||
#include "mount-util.h"
|
||||
#include "options.h"
|
||||
#include "os-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
@@ -994,249 +996,236 @@ static void set_manager_settings(Manager *m) {
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
COMMON_GETOPT_ARGS,
|
||||
SYSTEMD_GETOPT_ARGS,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
COMMON_GETOPT_OPTIONS,
|
||||
SYSTEMD_GETOPT_OPTIONS,
|
||||
{}
|
||||
};
|
||||
|
||||
int c, r;
|
||||
bool user_arg_seen = false;
|
||||
int r;
|
||||
|
||||
assert(argc >= 1);
|
||||
assert(argv);
|
||||
|
||||
if (getpid_cached() == 1)
|
||||
opterr = 0;
|
||||
int log_level_shift = getpid_cached() == 1 ? LOG_DEBUG - LOG_ERR : 0;
|
||||
OptionParser opts = { argc, argv, .log_level_shift = log_level_shift };
|
||||
|
||||
while ((c = getopt_long(argc, argv, SYSTEMD_GETOPT_SHORT_OPTIONS, options, NULL)) >= 0)
|
||||
/* Note: when new options are added here, also add them to the exclusion list in proc-cmdline.c! */
|
||||
|
||||
FOREACH_OPTION(c, &opts)
|
||||
switch (c) {
|
||||
|
||||
case ARG_LOG_LEVEL:
|
||||
r = log_set_max_level_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log level \"%s\": %m", optarg);
|
||||
|
||||
OPTION_COMMON_HELP:
|
||||
arg_action = ACTION_HELP;
|
||||
break;
|
||||
|
||||
case ARG_LOG_TARGET:
|
||||
r = log_set_target_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log target \"%s\": %m", optarg);
|
||||
|
||||
OPTION_COMMON_VERSION:
|
||||
arg_action = ACTION_VERSION;
|
||||
break;
|
||||
|
||||
case ARG_LOG_COLOR:
|
||||
|
||||
if (optarg) {
|
||||
r = log_show_color_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log color setting \"%s\": %m",
|
||||
optarg);
|
||||
} else
|
||||
log_show_color(true);
|
||||
|
||||
OPTION_LONG("test", NULL, "Determine initial transaction, dump it and exit"):
|
||||
arg_action = ACTION_TEST;
|
||||
break;
|
||||
|
||||
case ARG_LOG_LOCATION:
|
||||
if (optarg) {
|
||||
r = log_show_location_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log location setting \"%s\": %m",
|
||||
optarg);
|
||||
} else
|
||||
log_show_location(true);
|
||||
|
||||
break;
|
||||
|
||||
case ARG_LOG_TIME:
|
||||
|
||||
if (optarg) {
|
||||
r = log_show_time_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log time setting \"%s\": %m",
|
||||
optarg);
|
||||
} else
|
||||
log_show_time(true);
|
||||
|
||||
break;
|
||||
|
||||
case ARG_DEFAULT_STD_OUTPUT:
|
||||
r = exec_output_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse default standard output setting \"%s\": %m",
|
||||
optarg);
|
||||
arg_defaults.std_output = r;
|
||||
break;
|
||||
|
||||
case ARG_DEFAULT_STD_ERROR:
|
||||
r = exec_output_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse default standard error output setting \"%s\": %m",
|
||||
optarg);
|
||||
arg_defaults.std_error = r;
|
||||
break;
|
||||
|
||||
case ARG_UNIT:
|
||||
r = free_and_strdup(&arg_default_unit, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set default unit \"%s\": %m", optarg);
|
||||
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
OPTION_LONG("system", NULL, "Combined with --test: operate in system mode"):
|
||||
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||
break;
|
||||
|
||||
case ARG_USER:
|
||||
OPTION_LONG("user", NULL, "Combined with --test: operate in user mode"):
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
user_arg_seen = true;
|
||||
break;
|
||||
|
||||
case ARG_TEST:
|
||||
arg_action = ACTION_TEST;
|
||||
break;
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_VERSION:
|
||||
arg_action = ACTION_VERSION;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_CONFIGURATION_ITEMS:
|
||||
OPTION_LONG("dump-configuration-items", NULL, "Dump understood unit configuration items"):
|
||||
arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_BUS_PROPERTIES:
|
||||
OPTION_LONG("dump-bus-properties", NULL, "Dump exposed bus properties"):
|
||||
arg_action = ACTION_DUMP_BUS_PROPERTIES;
|
||||
break;
|
||||
|
||||
case ARG_BUS_INTROSPECT:
|
||||
arg_bus_introspect = optarg;
|
||||
OPTION_LONG("bus-introspect", "PATH", "Write XML introspection data"):
|
||||
arg_bus_introspect = opts.arg;
|
||||
arg_action = ACTION_BUS_INTROSPECT;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_CORE:
|
||||
r = parse_boolean_argument("--dump-core", optarg, &arg_dump_core);
|
||||
OPTION_LONG("unit", "UNIT", "Set default unit"):
|
||||
r = free_and_strdup(&arg_default_unit, opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set default unit \"%s\": %m", opts.arg);
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "dump-core", "BOOL", "Dump core on crash"):
|
||||
r = parse_boolean_argument("--dump-core", opts.arg, &arg_dump_core);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_CRASH_CHVT:
|
||||
r = parse_crash_chvt(optarg, &arg_crash_chvt);
|
||||
OPTION_LONG("crash-chvt", "NR", "Change to specified VT on crash"): {}
|
||||
OPTION_LONG("crash-vt", "NR", /* help= */ NULL): /* compat option that was previously documented in --help */
|
||||
r = parse_crash_chvt(opts.arg, &arg_crash_chvt);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse crash virtual terminal index: \"%s\": %m",
|
||||
optarg);
|
||||
return log_error_errno(r, "Failed to parse crash virtual terminal index '%s': %m",
|
||||
opts.arg);
|
||||
break;
|
||||
|
||||
case ARG_CRASH_SHELL:
|
||||
r = parse_boolean_argument("--crash-shell", optarg, &arg_crash_shell);
|
||||
OPTION_LONG("crash-action", "ACTION", "Specify what to do on crash"):
|
||||
r = crash_action_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse crash action \"%s\": %m", opts.arg);
|
||||
arg_crash_action = r;
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "crash-shell", "BOOL", "Run shell on crash"):
|
||||
r = parse_boolean_argument("--crash-shell", opts.arg, &arg_crash_shell);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_CRASH_REBOOT:
|
||||
r = parse_boolean_argument("--crash-reboot", optarg, NULL);
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "confirm-spawn", "BOOL",
|
||||
"Ask for confirmation when spawning processes"):
|
||||
arg_confirm_spawn = mfree(arg_confirm_spawn);
|
||||
|
||||
r = parse_confirm_spawn(opts.arg, &arg_confirm_spawn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse confirm spawn option: \"%s\": %m",
|
||||
opts.arg);
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "show-status", "BOOL",
|
||||
"Show status updates on the console during boot"):
|
||||
if (opts.arg) {
|
||||
r = parse_show_status(opts.arg, &arg_show_status);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse show status boolean: \"%s\": %m",
|
||||
opts.arg);
|
||||
} else
|
||||
arg_show_status = SHOW_STATUS_YES;
|
||||
break;
|
||||
|
||||
OPTION_LONG("log-target", "TARGET",
|
||||
"Set log target (console, journal, kmsg, journal-or-kmsg, null)"):
|
||||
r = log_set_target_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log target \"%s\": %m", opts.arg);
|
||||
break;
|
||||
|
||||
OPTION_LONG("log-level", "LEVEL",
|
||||
"Set log level (debug, info, notice, warning, err, crit, alert, emerg)"):
|
||||
r = log_set_max_level_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log level \"%s\": %m", opts.arg);
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "log-color", "BOOL", "Highlight important log messages"):
|
||||
if (opts.arg) {
|
||||
r = log_show_color_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log color setting \"%s\": %m",
|
||||
opts.arg);
|
||||
} else
|
||||
log_show_color(true);
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "log-location", "BOOL",
|
||||
"Include code location in log messages"):
|
||||
if (opts.arg) {
|
||||
r = log_show_location_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log location setting \"%s\": %m",
|
||||
opts.arg);
|
||||
} else
|
||||
log_show_location(true);
|
||||
break;
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "log-time", "BOOL", "Prefix log messages with current time"):
|
||||
if (opts.arg) {
|
||||
r = log_show_time_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse log time setting \"%s\": %m",
|
||||
opts.arg);
|
||||
} else
|
||||
log_show_time(true);
|
||||
break;
|
||||
|
||||
OPTION_LONG("default-standard-output", "…", "Set default standard output for services"):
|
||||
r = exec_output_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse default standard output setting \"%s\": %m",
|
||||
opts.arg);
|
||||
arg_defaults.std_output = r;
|
||||
break;
|
||||
|
||||
OPTION_LONG("default-standard-error", "…", "Set default standard error output for services"):
|
||||
r = exec_output_from_string(opts.arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse default standard error output setting \"%s\": %m",
|
||||
opts.arg);
|
||||
arg_defaults.std_error = r;
|
||||
break;
|
||||
|
||||
OPTION_COMMON_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
/* Options not shown in --help. */
|
||||
|
||||
OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "crash-reboot", "BOOL", /* help= */ NULL):
|
||||
r = parse_boolean_argument("--crash-reboot", opts.arg, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
arg_crash_action = r > 0 ? CRASH_REBOOT : CRASH_FREEZE;
|
||||
break;
|
||||
|
||||
case ARG_CRASH_ACTION:
|
||||
r = crash_action_from_string(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse crash action \"%s\": %m", optarg);
|
||||
arg_crash_action = r;
|
||||
break;
|
||||
|
||||
case ARG_CONFIRM_SPAWN:
|
||||
arg_confirm_spawn = mfree(arg_confirm_spawn);
|
||||
|
||||
r = parse_confirm_spawn(optarg, &arg_confirm_spawn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse confirm spawn option: \"%s\": %m",
|
||||
optarg);
|
||||
break;
|
||||
|
||||
case ARG_SERVICE_WATCHDOGS:
|
||||
r = parse_boolean_argument("--service-watchdogs=", optarg, &arg_service_watchdogs);
|
||||
OPTION_LONG("service-watchdogs", "BOOL", /* help= */ NULL):
|
||||
r = parse_boolean_argument("--service-watchdogs=", opts.arg, &arg_service_watchdogs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_SHOW_STATUS:
|
||||
if (optarg) {
|
||||
r = parse_show_status(optarg, &arg_show_status);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse show status boolean: \"%s\": %m",
|
||||
optarg);
|
||||
} else
|
||||
arg_show_status = SHOW_STATUS_YES;
|
||||
break;
|
||||
|
||||
case ARG_DESERIALIZE: {
|
||||
int fd;
|
||||
FILE *f;
|
||||
|
||||
fd = parse_fd(optarg);
|
||||
OPTION_LONG("deserialize", "FD", /* help= */ NULL): {
|
||||
int fd = parse_fd(opts.arg);
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to parse serialization fd \"%s\": %m", optarg);
|
||||
return log_error_errno(fd, "Failed to parse serialization fd \"%s\": %m", opts.arg);
|
||||
|
||||
(void) fd_cloexec(fd, true);
|
||||
|
||||
f = fdopen(fd, "r");
|
||||
FILE *f = fdopen(fd, "r");
|
||||
if (!f)
|
||||
return log_error_errno(errno, "Failed to open serialization fd %d: %m", fd);
|
||||
|
||||
safe_fclose(arg_serialization);
|
||||
arg_serialization = f;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_SWITCHED_ROOT:
|
||||
OPTION_LONG("switched-root", NULL, /* help= */ NULL):
|
||||
arg_switched_root = true;
|
||||
break;
|
||||
|
||||
case ARG_MACHINE_ID:
|
||||
r = id128_from_string_nonzero(optarg, &arg_machine_id);
|
||||
OPTION_LONG("machine-id", "ID", /* help= */ NULL):
|
||||
r = id128_from_string_nonzero(opts.arg, &arg_machine_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "MachineID '%s' is not valid: %m", optarg);
|
||||
return log_error_errno(r, "MachineID '%s' is not valid: %m", opts.arg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
arg_action = ACTION_HELP;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
OPTION_SHORT('D', NULL, /* help= */ NULL):
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 's':
|
||||
case 'z':
|
||||
/* Just to eat away the sysvinit kernel cmdline args that we'll parse in
|
||||
* parse_proc_cmdline_item() or ignore, without any getopt() error messages.
|
||||
*/
|
||||
case '?':
|
||||
/* Eat the sysvinit kernel cmdline args that we'll parse in
|
||||
* parse_proc_cmdline_item() or ignore. */
|
||||
OPTION_SHORT('b', NULL, /* help= */ NULL): {}
|
||||
OPTION_SHORT('s', NULL, /* help= */ NULL): {}
|
||||
OPTION_SHORT('z', "ARG", /* help= */ NULL):
|
||||
if (getpid_cached() != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Switch -%c is only supported when running as PID 1.", opts.opt->short_code);
|
||||
/* In PID1, do nothing and continue with option parsing. */
|
||||
break;
|
||||
OPTION_ERROR:
|
||||
if (getpid_cached() != 1)
|
||||
return -EINVAL;
|
||||
else
|
||||
return 0;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
/* In PID1, silently terminate option parsing. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (optind < argc && getpid_cached() != 1)
|
||||
if (option_parser_get_n_args(&opts) > 0 && getpid_cached() != 1)
|
||||
/* Hmm, when we aren't run as init system let's complain about excess arguments */
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Excess arguments.");
|
||||
|
||||
@@ -1248,50 +1237,24 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
_cleanup_(table_unrefp) Table *options = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd", "1", &link);
|
||||
r = option_parser_get_help_table(&options);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
return r;
|
||||
|
||||
printf("%s [OPTIONS...]\n\n"
|
||||
"%sStarts and monitors system and user services.%s\n\n"
|
||||
"This program takes no positional arguments.\n\n"
|
||||
"%sOptions%s:\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show version\n"
|
||||
" --test Determine initial transaction, dump it and exit\n"
|
||||
" --system Combined with --test: operate in system mode\n"
|
||||
" --user Combined with --test: operate in user mode\n"
|
||||
" --dump-configuration-items Dump understood unit configuration items\n"
|
||||
" --dump-bus-properties Dump exposed bus properties\n"
|
||||
" --bus-introspect=PATH Write XML introspection data\n"
|
||||
" --unit=UNIT Set default unit\n"
|
||||
" --dump-core[=BOOL] Dump core on crash\n"
|
||||
" --crash-vt=NR Change to specified VT on crash\n"
|
||||
" --crash-action=ACTION Specify what to do on crash\n"
|
||||
" --crash-shell[=BOOL] Run shell on crash\n"
|
||||
" --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n"
|
||||
" --show-status[=BOOL] Show status updates on the console during boot\n"
|
||||
" --log-target=TARGET Set log target (console, journal, kmsg,\n"
|
||||
" journal-or-kmsg, null)\n"
|
||||
" --log-level=LEVEL Set log level (debug, info, notice, warning,\n"
|
||||
" err, crit, alert, emerg)\n"
|
||||
" --log-color[=BOOL] Highlight important log messages\n"
|
||||
" --log-location[=BOOL] Include code location in log messages\n"
|
||||
" --log-time[=BOOL] Prefix log messages with current time\n"
|
||||
" --default-standard-output= Set default standard output for services\n"
|
||||
" --default-standard-error= Set default standard error output for services\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
help_cmdline("[OPTIONS...]");
|
||||
help_abstract("Starts and monitors system and user services.");
|
||||
|
||||
printf("\nThis program takes no positional arguments.\n");
|
||||
|
||||
help_section("Options");
|
||||
r = table_print_or_warn(options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
help_man_page_reference("systemd", "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2228,8 +2191,8 @@ static int do_reexecute(
|
||||
}
|
||||
|
||||
/* Try the fallback, if there is any, without any serialization. We pass the original argv[] and
|
||||
* envp[]. (Well, modulo the ordering changes due to getopt() in argv[], and some cleanups in envp[],
|
||||
* but let's hope that doesn't matter.) */
|
||||
* envp[]. (Well, modulo the ordering changes due to option parsing in argv[], and some cleanups in
|
||||
* envp[], but let's hope that doesn't matter.) */
|
||||
|
||||
arg_serialization = safe_fclose(arg_serialization);
|
||||
fds = fdset_free(fds);
|
||||
@@ -3341,15 +3304,19 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
/* The efivarfs is now mounted, let's lock down the system token. */
|
||||
lock_down_efi_variables();
|
||||
|
||||
} else {
|
||||
/* Running as user instance */
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
log_set_always_reopen_console(true);
|
||||
log_set_target_and_open(LOG_TARGET_AUTO);
|
||||
|
||||
/* clear the kernel timestamp, because we are not PID 1 */
|
||||
kernel_timestamp = DUAL_TIMESTAMP_NULL;
|
||||
|
||||
if (invoked_by_systemd()) {
|
||||
log_set_always_reopen_console(true);
|
||||
log_set_target_and_open(LOG_TARGET_AUTO);
|
||||
}
|
||||
|
||||
r = mac_init();
|
||||
if (r < 0) {
|
||||
error_message = "Failed to initialize MAC support";
|
||||
@@ -3361,9 +3328,11 @@ int main(int argc, char *argv[]) {
|
||||
* transitioning from the initrd to the main systemd or suchlike. */
|
||||
save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock);
|
||||
|
||||
/* Reset all signal handlers. */
|
||||
/* Reset all signal handlers to clean up after reexec. */
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) ignore_signals(SIGNALS_IGNORE);
|
||||
|
||||
if (getpid_cached() == 1 || invoked_by_systemd())
|
||||
(void) ignore_signals(SIGNALS_IGNORE);
|
||||
|
||||
(void) parse_configuration(&saved_rlimit_nofile, &saved_rlimit_memlock);
|
||||
|
||||
|
||||
@@ -80,6 +80,10 @@ typedef struct Option {
|
||||
#define OPTION_POSITIONAL OPTION_FULL(OPTION_POSITIONAL_ENTRY, /* sc= */ 0, "(positional)", /* mv= */ NULL, /* h= */ NULL)
|
||||
#define OPTION_HELP_VERBATIM(lc, h) OPTION_FULL(OPTION_HELP_ENTRY_VERBATIM, /* sc= */ 0, lc, /* mv= */ NULL, h)
|
||||
|
||||
/* This can be used when custom error handling is needed. */
|
||||
#define OPTION_ERROR \
|
||||
case INT_MIN ... -1
|
||||
|
||||
#define OPTION_COMMON_HELP \
|
||||
OPTION('h', "help", NULL, "Show this help")
|
||||
|
||||
|
||||
@@ -61,7 +61,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argv);
|
||||
|
||||
/* The interface is: the verb must stay in argv[1]. Any extra positional arguments
|
||||
* are warned about and ignored. See 4b5d8d0f22ae61ceb45a25391354ba53b43ee992. */
|
||||
* are warned about and ignored. See 4b5d8d0f22ae61ceb45a25391354ba53b43ee992.
|
||||
*
|
||||
* Note: when new options are added here, also add them to the exclusion list in proc-cmdline.c! */
|
||||
|
||||
OptionParser opts = { argc, argv, OPTION_PARSER_RETURN_POSITIONAL_ARGS };
|
||||
int r;
|
||||
|
||||
Reference in New Issue
Block a user