Merge pull request #4459 from keszybz/commandline-parsing

Commandline parsing simplification and udev fix
This commit is contained in:
Lennart Poettering
2016-10-24 17:20:37 +02:00
committed by GitHub
16 changed files with 136 additions and 162 deletions
+15 -16
View File
@@ -301,22 +301,21 @@
<term><varname>ForwardToConsole=</varname></term>
<term><varname>ForwardToWall=</varname></term>
<listitem><para>Control whether log messages received by the
journal daemon shall be forwarded to a traditional syslog
daemon, to the kernel log buffer (kmsg), to the system
console, or sent as wall messages to all logged-in users.
These options take boolean arguments. If forwarding to syslog
is enabled but nothing reads messages from the socket,
forwarding to syslog has no effect. By default, only
forwarding to wall is enabled. These settings may be
overridden at boot time with the kernel command line options
<literal>systemd.journald.forward_to_syslog=</literal>,
<literal>systemd.journald.forward_to_kmsg=</literal>,
<literal>systemd.journald.forward_to_console=</literal>, and
<literal>systemd.journald.forward_to_wall=</literal>. When
forwarding to the console, the TTY to log to can be changed
with <varname>TTYPath=</varname>, described
below.</para></listitem>
<listitem><para>Control whether log messages received by the journal daemon shall
be forwarded to a traditional syslog daemon, to the kernel log buffer (kmsg), to
the system console, or sent as wall messages to all logged-in users. These
options take boolean arguments. If forwarding to syslog is enabled but nothing
reads messages from the socket, forwarding to syslog has no effect. By default,
only forwarding to wall is enabled. These settings may be overridden at boot time
with the kernel command line options
<literal>systemd.journald.forward_to_syslog</literal>,
<literal>systemd.journald.forward_to_kmsg</literal>,
<literal>systemd.journald.forward_to_console</literal>, and
<literal>systemd.journald.forward_to_wall</literal>. If the option name is
specified without <literal>=</literal> and the following argument, true is
assumed. Otherwise, the argument is parsed as a boolean. When forwarding to the
console, the TTY to log to can be changed with <varname>TTYPath=</varname>,
described below.</para></listitem>
</varlistentry>
<varlistentry>
+2 -2
View File
@@ -967,7 +967,7 @@ int log_set_max_level_from_string(const char *e) {
return 0;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
/*
* The systemd.log_xyz= settings are parsed by all tools, and
@@ -1012,7 +1012,7 @@ void log_parse_environment(void) {
/* Only try to read the command line in daemons.
We assume that anything that has a controlling
tty is user stuff. */
(void) parse_proc_cmdline(parse_proc_cmdline_item);
(void) parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
e = secure_getenv("SYSTEMD_LOG_TARGET");
if (e && log_set_target_from_string(e) < 0)
+7 -4
View File
@@ -42,7 +42,9 @@ int proc_cmdline(char **ret) {
return read_one_line_file("/proc/cmdline", ret);
}
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data),
void *data,
bool strip_prefix) {
_cleanup_free_ char *line = NULL;
const char *p;
int r;
@@ -56,7 +58,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
char *value = NULL;
char *value = NULL, *unprefixed;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
if (r < 0)
@@ -66,14 +68,15 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
/* Filter out arguments that are intended only for the
* initrd */
if (!in_initrd() && startswith(word, "rd."))
unprefixed = startswith(word, "rd.");
if (unprefixed && !in_initrd())
continue;
value = strchr(word, '=');
if (value)
*(value++) = 0;
r = parse_item(word, value);
r = parse_item(strip_prefix && unprefixed ? unprefixed : word, value, data);
if (r < 0)
return r;
}
+3 -1
View File
@@ -20,7 +20,9 @@
***/
int proc_cmdline(char **ret);
int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value));
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data),
void *data,
bool strip_prefix);
int get_proc_cmdline_key(const char *parameter, char **value);
int shall_restore_state(void);
+2 -2
View File
@@ -308,7 +308,7 @@ static int set_machine_id(const char *m) {
return 0;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
@@ -1569,7 +1569,7 @@ int main(int argc, char *argv[]) {
}
if (arg_system) {
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
}
+8 -8
View File
@@ -277,12 +277,12 @@ static crypto_device *get_crypto_device(const char *uuid) {
return d;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
crypto_device *d;
_cleanup_free_ char *uuid = NULL, *uuid_value = NULL;
if (STR_IN_SET(key, "luks", "rd.luks") && value) {
if (streq(key, "luks") && value) {
r = parse_boolean(value);
if (r < 0)
@@ -290,7 +290,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
else
arg_enabled = r;
} else if (STR_IN_SET(key, "luks.crypttab", "rd.luks.crypttab") && value) {
} else if (streq(key, "luks.crypttab") && value) {
r = parse_boolean(value);
if (r < 0)
@@ -298,7 +298,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
else
arg_read_crypttab = r;
} else if (STR_IN_SET(key, "luks.uuid", "rd.luks.uuid") && value) {
} else if (streq(key, "luks.uuid") && value) {
d = get_crypto_device(startswith(value, "luks-") ? value+5 : value);
if (!d)
@@ -306,7 +306,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
d->create = arg_whitelist = true;
} else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) {
} else if (streq(key, "luks.options") && value) {
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
if (r == 2) {
@@ -320,7 +320,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
} else if (free_and_strdup(&arg_default_options, value) < 0)
return log_oom();
} else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) {
} else if (streq(key, "luks.key") && value) {
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
if (r == 2) {
@@ -334,7 +334,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
} else if (free_and_strdup(&arg_default_keyfile, value) < 0)
return log_oom();
} else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) {
} else if (streq(key, "luks.name") && value) {
r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
if (r == 2) {
@@ -478,7 +478,7 @@ int main(int argc, char *argv[]) {
if (!arg_disks)
goto cleanup;
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
if (r < 0) {
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
r = EXIT_FAILURE;
+2 -2
View File
@@ -33,7 +33,7 @@ static char **arg_mask = NULL;
static char **arg_wants = NULL;
static bool arg_debug_shell = false;
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
assert(key);
@@ -178,7 +178,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+2 -2
View File
@@ -94,7 +94,7 @@ static void start_target(const char *target, const char *mode) {
log_error("Failed to start unit: %s", bus_error_message(&error, r));
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
assert(key);
@@ -293,7 +293,7 @@ int main(int argc, char *argv[]) {
umask(0022);
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+2 -2
View File
@@ -590,7 +590,7 @@ static int add_sysroot_usr_mount(void) {
"/proc/cmdline");
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
/* root=, usr=, usrfstype= and roofstype= may occur more than once, the last
@@ -674,7 +674,7 @@ int main(int argc, char *argv[]) {
umask(0022);
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+2 -2
View File
@@ -907,7 +907,7 @@ fallback:
return 1;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
assert(key);
@@ -1018,7 +1018,7 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
@@ -33,7 +33,7 @@
static const char *arg_dest = "/tmp";
static char *arg_resume_dev = NULL;
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
if (streq(key, "resume") && value) {
free(arg_resume_dev);
@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
if (!in_initrd())
return EXIT_SUCCESS;
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+59 -76
View File
@@ -1526,85 +1526,68 @@ static int setup_signals(Server *s) {
return 0;
}
static int server_parse_proc_cmdline(Server *s) {
_cleanup_free_ char *line = NULL;
const char *p;
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
Server *s = data;
int r;
r = proc_cmdline(&line);
if (r < 0) {
log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
return 0;
}
assert(s);
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (streq(key, "systemd.journald.forward_to_syslog")) {
r = value ? parse_boolean(value) : true;
if (r < 0)
return log_error_errno(r, "Failed to parse journald syntax \"%s\": %m", line);
if (r == 0)
break;
if (startswith(word, "systemd.journald.forward_to_syslog=")) {
r = parse_boolean(word + 35);
if (r < 0)
log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
else
s->forward_to_syslog = r;
} else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
else
s->forward_to_kmsg = r;
} else if (startswith(word, "systemd.journald.forward_to_console=")) {
r = parse_boolean(word + 36);
if (r < 0)
log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
else
s->forward_to_console = r;
} else if (startswith(word, "systemd.journald.forward_to_wall=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33);
else
s->forward_to_wall = r;
} else if (startswith(word, "systemd.journald.max_level_console=")) {
r = log_level_from_string(word + 35);
if (r < 0)
log_warning("Failed to parse max level console value %s. Ignoring.", word + 35);
else
s->max_level_console = r;
} else if (startswith(word, "systemd.journald.max_level_store=")) {
r = log_level_from_string(word + 33);
if (r < 0)
log_warning("Failed to parse max level store value %s. Ignoring.", word + 33);
else
s->max_level_store = r;
} else if (startswith(word, "systemd.journald.max_level_syslog=")) {
r = log_level_from_string(word + 34);
if (r < 0)
log_warning("Failed to parse max level syslog value %s. Ignoring.", word + 34);
else
s->max_level_syslog = r;
} else if (startswith(word, "systemd.journald.max_level_kmsg=")) {
r = log_level_from_string(word + 32);
if (r < 0)
log_warning("Failed to parse max level kmsg value %s. Ignoring.", word + 32);
else
s->max_level_kmsg = r;
} else if (startswith(word, "systemd.journald.max_level_wall=")) {
r = log_level_from_string(word + 32);
if (r < 0)
log_warning("Failed to parse max level wall value %s. Ignoring.", word + 32);
else
s->max_level_wall = r;
} else if (startswith(word, "systemd.journald"))
log_warning("Invalid systemd.journald parameter. Ignoring.");
}
log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value);
else
s->forward_to_syslog = r;
} else if (streq(key, "systemd.journald.forward_to_kmsg")) {
r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value);
else
s->forward_to_kmsg = r;
} else if (streq(key, "systemd.journald.forward_to_console")) {
r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value);
else
s->forward_to_console = r;
} else if (streq(key, "systemd.journald.forward_to_wall")) {
r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value);
else
s->forward_to_wall = r;
} else if (streq(key, "systemd.journald.max_level_console") && value) {
r = log_level_from_string(value);
if (r < 0)
log_warning("Failed to parse max level console value \"%s\". Ignoring.", value);
else
s->max_level_console = r;
} else if (streq(key, "systemd.journald.max_level_store") && value) {
r = log_level_from_string(value);
if (r < 0)
log_warning("Failed to parse max level store value \"%s\". Ignoring.", value);
else
s->max_level_store = r;
} else if (streq(key, "systemd.journald.max_level_syslog") && value) {
r = log_level_from_string(value);
if (r < 0)
log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value);
else
s->max_level_syslog = r;
} else if (streq(key, "systemd.journald.max_level_kmsg") && value) {
r = log_level_from_string(value);
if (r < 0)
log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value);
else
s->max_level_kmsg = r;
} else if (streq(key, "systemd.journald.max_level_wall") && value) {
r = log_level_from_string(value);
if (r < 0)
log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value);
else
s->max_level_wall = r;
} else if (startswith(key, "systemd.journald"))
log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key);
/* do not warn about state here, since probably systemd already did */
return 0;
@@ -1915,7 +1898,7 @@ int server_init(Server *s) {
journal_reset_metrics(&s->runtime_storage.metrics);
server_parse_config_file(s);
server_parse_proc_cmdline(s);
parse_proc_cmdline(parse_proc_cmdline_item, s, true);
if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) {
log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0",
+3 -3
View File
@@ -59,10 +59,10 @@ static int add_modules(const char *p) {
return 0;
}
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) {
if (streq(key, "modules-load") && value) {
r = add_modules(value);
if (r < 0)
return r;
@@ -226,7 +226,7 @@ int main(int argc, char *argv[]) {
umask(0022);
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+2 -2
View File
@@ -32,7 +32,7 @@
static bool arg_skip = false;
static bool arg_force = false;
static int parse_proc_cmdline_item(const char *key, const char *value) {
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
if (streq(key, "quotacheck.mode") && value) {
@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
umask(0022);
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+5 -2
View File
@@ -25,15 +25,18 @@
#include "string-util.h"
#include "util.h"
static int parse_item(const char *key, const char *value) {
static int obj;
static int parse_item(const char *key, const char *value, void *data) {
assert_se(key);
assert_se(data == &obj);
log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
return 0;
}
static void test_parse_proc_cmdline(void) {
assert_se(parse_proc_cmdline(parse_item) >= 0);
assert_se(parse_proc_cmdline(parse_item, &obj, true) >= 0);
}
static void test_runlevel_to_target(void) {
+20 -36
View File
@@ -1362,49 +1362,33 @@ static int listen_fds(int *rctrl, int *rnetlink) {
* udev.exec-delay=<number of seconds> delay execution of every executed program
* udev.event-timeout=<number of seconds> seconds to wait before terminating an event
*/
static int parse_proc_cmdline_item(const char *key, const char *value) {
const char *full_key = key;
int r;
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r = 0;
assert(key);
if (!value)
return 0;
if (startswith(key, "rd."))
key += strlen("rd.");
if (startswith(key, "udev."))
key += strlen("udev.");
else
return 0;
if (streq(key, "log-priority")) {
int prio;
prio = util_log_priority(value);
if (prio < 0)
goto invalid;
log_set_max_level(prio);
} else if (streq(key, "children-max")) {
r = safe_atou(value, &arg_children_max);
if (r < 0)
goto invalid;
} else if (streq(key, "exec-delay")) {
r = safe_atoi(value, &arg_exec_delay);
if (r < 0)
goto invalid;
} else if (streq(key, "event-timeout")) {
if (streq(key, "udev.log-priority") && value) {
r = util_log_priority(value);
if (r >= 0)
log_set_max_level(r);
} else if (streq(key, "udev.event-timeout") && value) {
r = safe_atou64(value, &arg_event_timeout_usec);
if (r < 0)
goto invalid;
arg_event_timeout_usec *= USEC_PER_SEC;
arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
}
if (r >= 0) {
arg_event_timeout_usec *= USEC_PER_SEC;
arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
}
} else if (streq(key, "udev.children-max") && value)
r = safe_atou(value, &arg_children_max);
else if (streq(key, "udev.exec-delay") && value)
r = safe_atoi(value, &arg_exec_delay);
else if (startswith(key, "udev."))
log_warning("Unknown udev kernel command line option \"%s\"", key);
return 0;
invalid:
log_warning("invalid %s ignored: %s", full_key, value);
if (r < 0)
log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value);
return 0;
}
@@ -1665,7 +1649,7 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto exit;
r = parse_proc_cmdline(parse_proc_cmdline_item);
r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
if (r < 0)
log_warning_errno(r, "failed to parse kernel command line, ignoring: %m");