diff options
-rw-r--r-- | man/kernel-command-line.xml | 22 | ||||
-rw-r--r-- | man/systemd-debug-generator.xml | 2 | ||||
-rw-r--r-- | man/systemd-modules-load.service.xml | 4 | ||||
-rw-r--r-- | man/systemd-udevd.service.xml | 16 | ||||
-rw-r--r-- | src/basic/cgroup-util.c | 39 | ||||
-rw-r--r-- | src/basic/log.c | 25 | ||||
-rw-r--r-- | src/basic/proc-cmdline.c | 133 | ||||
-rw-r--r-- | src/basic/proc-cmdline.h | 33 | ||||
-rw-r--r-- | src/core/main.c | 116 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-generator.c | 46 | ||||
-rw-r--r-- | src/debug-generator/debug-generator.c | 61 | ||||
-rw-r--r-- | src/firstboot/firstboot.c | 19 | ||||
-rw-r--r-- | src/fsck/fsck.c | 12 | ||||
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 36 | ||||
-rw-r--r-- | src/gpt-auto-generator/gpt-auto-generator.c | 11 | ||||
-rw-r--r-- | src/hibernate-resume/hibernate-resume-generator.c | 25 | ||||
-rw-r--r-- | src/journal/journald-server.c | 56 | ||||
-rw-r--r-- | src/modules-load/modules-load.c | 8 | ||||
-rw-r--r-- | src/quotacheck/quotacheck.c | 7 | ||||
-rw-r--r-- | src/test/test-proc-cmdline.c | 96 | ||||
-rw-r--r-- | src/udev/net/link-config.c | 9 | ||||
-rw-r--r-- | src/udev/udevd.c | 41 |
22 files changed, 561 insertions, 256 deletions
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index c86e45265f..78e45e66a9 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -102,7 +102,7 @@ <varlistentry> <term><varname>systemd.mask=</varname></term> <term><varname>systemd.wants=</varname></term> - <term><varname>systemd.debug-shell</varname></term> + <term><varname>systemd.debug_shell</varname></term> <listitem> <para>Additional parameters understood by <citerefentry><refentrytitle>systemd-debug-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, @@ -236,14 +236,14 @@ </varlistentry> <varlistentry> - <term><varname>udev.log-priority=</varname></term> - <term><varname>rd.udev.log-priority=</varname></term> - <term><varname>udev.children-max=</varname></term> - <term><varname>rd.udev.children-max=</varname></term> - <term><varname>udev.exec-delay=</varname></term> - <term><varname>rd.udev.exec-delay=</varname></term> - <term><varname>udev.event-timeout=</varname></term> - <term><varname>rd.udev.event-timeout=</varname></term> + <term><varname>udev.log_priority=</varname></term> + <term><varname>rd.udev.log_priority=</varname></term> + <term><varname>udev.children_max=</varname></term> + <term><varname>rd.udev.children_max=</varname></term> + <term><varname>udev.exec_delay=</varname></term> + <term><varname>rd.udev.exec_delay=</varname></term> + <term><varname>udev.event_timeout=</varname></term> + <term><varname>rd.udev.event_timeout=</varname></term> <term><varname>net.ifnames=</varname></term> <listitem> @@ -332,8 +332,8 @@ </varlistentry> <varlistentry> - <term><varname>modules-load=</varname></term> - <term><varname>rd.modules-load=</varname></term> + <term><varname>modules_load=</varname></term> + <term><varname>rd.modules_load=</varname></term> <listitem> <para>Load a specific kernel module early at boot. For diff --git a/man/systemd-debug-generator.xml b/man/systemd-debug-generator.xml index 5c5e9fc4a1..0a66b9bbf9 100644 --- a/man/systemd-debug-generator.xml +++ b/man/systemd-debug-generator.xml @@ -70,7 +70,7 @@ the initial transaction. This is useful to start one or more additional units at boot. May be specified more than once.</para> - <para>If the <option>systemd.debug-shell</option> option is + <para>If the <option>systemd.debug_shell</option> option is specified, the debug shell service <literal>debug-shell.service</literal> is pulled into the boot transaction. It will spawn a debug shell on tty9 during early diff --git a/man/systemd-modules-load.service.xml b/man/systemd-modules-load.service.xml index b25929b2e4..ee097d7f5c 100644 --- a/man/systemd-modules-load.service.xml +++ b/man/systemd-modules-load.service.xml @@ -73,8 +73,8 @@ <variablelist class='kernel-commandline-options'> <varlistentry> - <term><varname>modules-load=</varname></term> - <term><varname>rd.modules-load=</varname></term> + <term><varname>modules_load=</varname></term> + <term><varname>rd.modules_load=</varname></term> <listitem><para>Takes a comma-separated list of kernel modules to statically load during early boot. The option prefixed with diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml index 243fd06471..81b957b0c8 100644 --- a/man/systemd-udevd.service.xml +++ b/man/systemd-udevd.service.xml @@ -133,22 +133,22 @@ <para>Parameters starting with "rd." will be read when <command>systemd-udevd</command> is used in an initrd.</para> <varlistentry> - <term><varname>udev.log-priority=</varname></term> - <term><varname>rd.udev.log-priority=</varname></term> + <term><varname>udev.log_priority=</varname></term> + <term><varname>rd.udev.log_priority=</varname></term> <listitem> <para>Set the log level.</para> </listitem> </varlistentry> <varlistentry> - <term><varname>udev.children-max=</varname></term> - <term><varname>rd.udev.children-max=</varname></term> + <term><varname>udev.children_max=</varname></term> + <term><varname>rd.udev.children_max=</varname></term> <listitem> <para>Limit the number of events executed in parallel.</para> </listitem> </varlistentry> <varlistentry> - <term><varname>udev.exec-delay=</varname></term> - <term><varname>rd.udev.exec-delay=</varname></term> + <term><varname>udev.exec_delay=</varname></term> + <term><varname>rd.udev.exec_delay=</varname></term> <listitem> <para>Delay the execution of <varname>RUN</varname> instructions by the given number of seconds. This option might be useful when @@ -157,8 +157,8 @@ </listitem> </varlistentry> <varlistentry> - <term><varname>udev.event-timeout=</varname></term> - <term><varname>rd.udev.event-timeout=</varname></term> + <term><varname>udev.event_timeout=</varname></term> + <term><varname>rd.udev.event_timeout=</varname></term> <listitem> <para>Wait for events to finish up to the given number of seconds. This option might be useful if events are diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index dc13025115..d2d18f13f0 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2361,6 +2361,7 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { bool cg_is_unified_wanted(void) { static thread_local int wanted = -1; int r, unified; + bool b; /* If the hierarchy is already mounted, then follow whatever * was chosen for it. */ @@ -2374,20 +2375,11 @@ bool cg_is_unified_wanted(void) { if (wanted >= 0) return wanted; - r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy", NULL); - if (r > 0) - return (wanted = true); - else { - _cleanup_free_ char *value = NULL; - - r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy=", &value); - if (r < 0) - return false; - if (r == 0) - return (wanted = false); + r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", &b); + if (r < 0) + return false; - return (wanted = parse_boolean(value) > 0); - } + return (wanted = r > 0 ? b : false); } bool cg_is_legacy_wanted(void) { @@ -2397,6 +2389,7 @@ bool cg_is_legacy_wanted(void) { bool cg_is_unified_systemd_controller_wanted(void) { static thread_local int wanted = -1; int r, unified; + bool b; /* If the unified hierarchy is requested in full, no need to * bother with this. */ @@ -2415,23 +2408,11 @@ bool cg_is_unified_systemd_controller_wanted(void) { if (wanted >= 0) return wanted; - r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller", NULL); - if (r > 0) - wanted = false; - else { - _cleanup_free_ char *value = NULL; - - r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller=", &value); - if (r < 0) - return false; - - if (r == 0) - wanted = false; - else - wanted = parse_boolean(value) <= 0; - } + r = proc_cmdline_get_bool("systemd.legacy_systemd_cgroup_controller", &b); + if (r < 0) + return false; - return wanted; + return (wanted = r > 0 ? b : false); } bool cg_is_legacy_systemd_controller_wanted(void) { diff --git a/src/basic/log.c b/src/basic/log.c index 557212c022..1362b1c086 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -981,24 +981,30 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (streq(key, "debug") && !value) log_set_max_level(LOG_DEBUG); - else if (streq(key, "systemd.log_target") && value) { + else if (proc_cmdline_key_streq(key, "systemd.log_target")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (log_set_target_from_string(value) < 0) log_warning("Failed to parse log target '%s'. Ignoring.", value); - } else if (streq(key, "systemd.log_level") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.log_level")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (log_set_max_level_from_string(value) < 0) log_warning("Failed to parse log level '%s'. Ignoring.", value); - } else if (streq(key, "systemd.log_color") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.log_color")) { - if (log_show_color_from_string(value) < 0) + if (log_show_color_from_string(value ?: "1") < 0) log_warning("Failed to parse log color setting '%s'. Ignoring.", value); - } else if (streq(key, "systemd.log_location") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.log_location")) { - if (log_show_location_from_string(value) < 0) + if (log_show_location_from_string(value ?: "1") < 0) log_warning("Failed to parse log location setting '%s'. Ignoring.", value); } @@ -1009,10 +1015,9 @@ void log_parse_environment(void) { const char *e; if (get_ctty_devnr(0, NULL) < 0) - /* 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, NULL, true); + /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is + user stuff. */ + (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); e = secure_getenv("SYSTEMD_LOG_TARGET"); if (e && log_set_target_from_string(e) < 0) diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 98c94ed5e2..6ecb6c3f0d 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -56,9 +56,8 @@ 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, void *data), - void *data, - bool strip_prefix) { +int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned flags) { + _cleanup_free_ char *line = NULL; const char *p; int r; @@ -72,7 +71,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, voi p = line; for (;;) { _cleanup_free_ char *word = NULL; - char *value = NULL, *unprefixed; + char *value, *key, *q; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) @@ -80,17 +79,23 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, voi if (r == 0) break; - /* Filter out arguments that are intended only for the - * initrd */ - unprefixed = startswith(word, "rd."); - if (unprefixed && !in_initrd()) - continue; + key = word; + + /* Filter out arguments that are intended only for the initrd */ + q = startswith(word, "rd."); + if (q) { + if (!in_initrd()) + continue; + + if (flags & PROC_CMDLINE_STRIP_RD_PREFIX) + key = q; + } - value = strchr(word, '='); + value = strchr(key, '='); if (value) *(value++) = 0; - r = parse_item(strip_prefix && unprefixed ? unprefixed : word, value, data); + r = parse_item(key, value, data); if (r < 0) return r; } @@ -98,13 +103,64 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, voi return 0; } -int get_proc_cmdline_key(const char *key, char **value) { +static bool relaxed_equal_char(char a, char b) { + + return a == b || + (a == '_' && b == '-') || + (a == '-' && b == '_'); +} + +char *proc_cmdline_key_startswith(const char *s, const char *prefix) { + + assert(s); + assert(prefix); + + /* Much like startswith(), but considers "-" and "_" the same */ + + for (; *prefix != 0; s++, prefix++) + if (!relaxed_equal_char(*s, *prefix)) + return NULL; + + return (char*) s; +} + +bool proc_cmdline_key_streq(const char *x, const char *y) { + assert(x); + assert(y); + + /* Much like streq(), but considers "-" and "_" the same */ + + for (; *x != 0 || *y != 0; x++, y++) + if (!relaxed_equal_char(*x, *y)) + return false; + + return true; +} + +int proc_cmdline_get_key(const char *key, unsigned flags, char **value) { _cleanup_free_ char *line = NULL, *ret = NULL; bool found = false; const char *p; int r; - assert(key); + /* Looks for a specific key on the kernel command line. Supports two modes: + * + * a) The "value" parameter is used. In this case a parameter beginning with the "key" string followed by "=" + * is searched, and the value following this is returned in "value". + * + * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the the key is found as a + * separate word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then + * this is also accepted, and "value" is returned as NULL. + * + * c) The "value" parameter is NULL. In this case a search for the exact "key" parameter is performed. + * + * In all three cases, > 0 is returned if the key is found, 0 if not.*/ + + if (isempty(key)) + return -EINVAL; + + if ((flags & PROC_CMDLINE_VALUE_OPTIONAL) && !value) + return -EINVAL; r = proc_cmdline(&line); if (r < 0) @@ -121,21 +177,26 @@ int get_proc_cmdline_key(const char *key, char **value) { if (r == 0) break; - /* Filter out arguments that are intended only for the - * initrd */ + /* Automatically filter out arguments that are intended only for the initrd, if we are not in the + * initrd. */ if (!in_initrd() && startswith(word, "rd.")) continue; if (value) { - e = startswith(word, key); + e = proc_cmdline_key_startswith(word, key); if (!e) continue; - r = free_and_strdup(&ret, e); - if (r < 0) - return r; + if (*e == '=') { + r = free_and_strdup(&ret, e+1); + if (r < 0) + return r; + + found = true; + + } else if (*e == 0 && (flags & PROC_CMDLINE_VALUE_OPTIONAL)) + found = true; - found = true; } else { if (streq(word, key)) found = true; @@ -148,20 +209,42 @@ int get_proc_cmdline_key(const char *key, char **value) { } return found; +} + +int proc_cmdline_get_bool(const char *key, bool *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(ret); + + r = proc_cmdline_get_key(key, PROC_CMDLINE_VALUE_OPTIONAL, &v); + if (r < 0) + return r; + if (r == 0) { + *ret = false; + return 0; + } + + if (v) { /* parameter passed */ + r = parse_boolean(v); + if (r < 0) + return r; + *ret = r; + } else /* no parameter passed */ + *ret = true; + return 1; } int shall_restore_state(void) { - _cleanup_free_ char *value = NULL; + bool ret; int r; - r = get_proc_cmdline_key("systemd.restore_state=", &value); + r = proc_cmdline_get_bool("systemd.restore_state", &ret); if (r < 0) return r; - if (r == 0) - return true; - return parse_boolean(value); + return r > 0 ? ret : true; } static const char * const rlmap[] = { diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index 6d6ee95c11..ebfed355e9 100644 --- a/src/basic/proc-cmdline.h +++ b/src/basic/proc-cmdline.h @@ -19,11 +19,36 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <stdbool.h> + +#include "log.h" + +enum { + PROC_CMDLINE_STRIP_RD_PREFIX = 1, + PROC_CMDLINE_VALUE_OPTIONAL = 2, +}; + +typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data); + int proc_cmdline(char **ret); -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 proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, unsigned flags); + +int proc_cmdline_get_key(const char *parameter, unsigned flags, char **value); +int proc_cmdline_get_bool(const char *key, bool *ret); + +char *proc_cmdline_key_startswith(const char *s, const char *prefix); +bool proc_cmdline_key_streq(const char *x, const char *y); int shall_restore_state(void); const char* runlevel_to_target(const char *rl); + +/* A little helper call, to be used in proc_cmdline_parse_t callbacks */ +static inline bool proc_cmdline_value_missing(const char *key, const char *value) { + if (!value) { + log_warning("Missing argument for %s= kernel command line switch, ignoring.", key); + return true; + } + + return false; +} diff --git a/src/core/main.c b/src/core/main.c index 6ec996577c..56a81ab94a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -337,60 +337,73 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat assert(key); - if (streq(key, "systemd.unit") && value) { + if (STR_IN_SET(key, "systemd.unit", "rd.systemd.unit")) { - if (!in_initrd()) - return free_and_strdup(&arg_default_unit, value); + if (proc_cmdline_value_missing(key, value)) + return 0; - } else if (streq(key, "rd.systemd.unit") && value) { - - if (in_initrd()) - return free_and_strdup(&arg_default_unit, value); + if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) + log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); + else if (in_initrd() == !!startswith(key, "rd.")) { + if (free_and_strdup(&arg_default_unit, value) < 0) + return log_oom(); + } - } else if (streq(key, "systemd.dump_core") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.dump_core")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : true; if (r < 0) log_warning("Failed to parse dump core switch %s. Ignoring.", value); else arg_dump_core = r; - } else if (streq(key, "systemd.crash_chvt") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.crash_chvt")) { - if (parse_crash_chvt(value) < 0) + if (!value) + arg_crash_chvt = 0; /* turn on */ + else if (parse_crash_chvt(value) < 0) log_warning("Failed to parse crash chvt switch %s. Ignoring.", value); - } else if (streq(key, "systemd.crash_shell") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.crash_shell")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : true; if (r < 0) log_warning("Failed to parse crash shell switch %s. Ignoring.", value); else arg_crash_shell = r; - } else if (streq(key, "systemd.crash_reboot") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.crash_reboot")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : true; if (r < 0) log_warning("Failed to parse crash reboot switch %s. Ignoring.", value); else arg_crash_reboot = r; - } else if (streq(key, "systemd.confirm_spawn") && value) { - - arg_confirm_spawn = mfree(arg_confirm_spawn); + } else if (proc_cmdline_key_streq(key, "systemd.confirm_spawn")) { + char *s; - r = parse_confirm_spawn(value, &arg_confirm_spawn); + r = parse_confirm_spawn(value, &s); if (r < 0) log_warning_errno(r, "Failed to parse confirm_spawn switch %s. Ignoring.", value); + else { + free(arg_confirm_spawn); + arg_confirm_spawn = s; + } - } else if (streq(key, "systemd.show_status") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.show_status")) { - r = parse_show_status(value, &arg_show_status); - if (r < 0) - log_warning("Failed to parse show status switch %s. Ignoring.", value); + if (value) { + r = parse_show_status(value, &arg_show_status); + if (r < 0) + log_warning("Failed to parse show status switch %s. Ignoring.", value); + } else + arg_show_status = SHOW_STATUS_YES; - } else if (streq(key, "systemd.default_standard_output") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.default_standard_output")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; r = exec_output_from_string(value); if (r < 0) @@ -398,7 +411,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat else arg_default_std_output = r; - } else if (streq(key, "systemd.default_standard_error") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.default_standard_error")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; r = exec_output_from_string(value); if (r < 0) @@ -406,24 +422,42 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat else arg_default_std_error = r; - } else if (streq(key, "systemd.setenv") && value) { + } else if (streq(key, "systemd.setenv")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (env_assignment_is_valid(value)) { char **env; env = strv_env_set(arg_default_environment, value); - if (env) - arg_default_environment = env; - else - log_warning_errno(ENOMEM, "Setting environment variable '%s' failed, ignoring: %m", value); + if (!env) + return log_oom(); + + arg_default_environment = env; } else log_warning("Environment variable name '%s' is not valid. Ignoring.", value); - } else if (streq(key, "systemd.machine_id") && value) { + } else if (proc_cmdline_key_streq(key, "systemd.machine_id")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = set_machine_id(value); + if (r < 0) + log_warning("MachineID '%s' is not valid. Ignoring.", value); - r = set_machine_id(value); - if (r < 0) - log_warning("MachineID '%s' is not valid. Ignoring.", value); + } else if (proc_cmdline_key_streq(key, "systemd.default_timeout_start_sec")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = parse_sec(value, &arg_default_timeout_start_usec); + if (r < 0) + log_warning_errno(r, "Failed to parse default start timeout: %s, ignoring.", value); + + if (arg_default_timeout_start_usec <= 0) + arg_default_timeout_start_usec = USEC_INFINITY; } else if (streq(key, "quiet") && !value) { @@ -445,15 +479,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat target = runlevel_to_target(key); if (target) return free_and_strdup(&arg_default_unit, target); - - } else if (streq(key, "systemd.default_timeout_start_sec") && value) { - - r = parse_sec(value, &arg_default_timeout_start_usec); - if (r < 0) - log_warning_errno(r, "Failed to parse default start timeout: %s, ignoring.", value); - - if (arg_default_timeout_start_usec <= 0) - arg_default_timeout_start_usec = USEC_INFINITY; } return 0; @@ -1341,10 +1366,9 @@ static int fixup_environment(void) { * However if TERM was configured through the kernel * command line then leave it alone. */ - r = get_proc_cmdline_key("TERM=", &term); + r = proc_cmdline_get_key("TERM", 0, &term); if (r < 0) return r; - if (r == 0) { term = strdup(default_term_for_tty("/dev/console")); if (!term) @@ -1591,7 +1615,7 @@ int main(int argc, char *argv[]) { } if (arg_system) { - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); } diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 68029865a0..e2a43f7195 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -278,27 +278,30 @@ static crypto_device *get_crypto_device(const char *uuid) { } 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; + crypto_device *d; + int r; - if (streq(key, "luks") && value) { + if (streq(key, "luks")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : 1; if (r < 0) - log_warning("Failed to parse luks switch %s. Ignoring.", value); + log_warning("Failed to parse luks= kernel command line switch %s. Ignoring.", value); else arg_enabled = r; - } else if (streq(key, "luks.crypttab") && value) { + } else if (streq(key, "luks.crypttab")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : 1; if (r < 0) - log_warning("Failed to parse luks crypttab switch %s. Ignoring.", value); + log_warning("Failed to parse luks.crypttab= kernel command line switch %s. Ignoring.", value); else arg_read_crypttab = r; - } else if (streq(key, "luks.uuid") && value) { + } else if (streq(key, "luks.uuid")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; d = get_crypto_device(startswith(value, "luks-") ? value+5 : value); if (!d) @@ -306,7 +309,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat d->create = arg_whitelist = true; - } else if (streq(key, "luks.options") && value) { + } else if (streq(key, "luks.options")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -314,13 +320,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!d) return log_oom(); - free(d->options); - d->options = uuid_value; - uuid_value = NULL; + free_and_replace(d->options, uuid_value); } else if (free_and_strdup(&arg_default_options, value) < 0) return log_oom(); - } else if (streq(key, "luks.key") && value) { + } else if (streq(key, "luks.key")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -328,13 +335,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!d) return log_oom(); - free(d->keyfile); - d->keyfile = uuid_value; - uuid_value = NULL; + free_and_replace(d->keyfile, uuid_value); } else if (free_and_strdup(&arg_default_keyfile, value) < 0) return log_oom(); - } else if (streq(key, "luks.name") && value) { + } else if (streq(key, "luks.name")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -478,7 +486,7 @@ int main(int argc, char *argv[]) { if (!arg_disks) goto cleanup; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); if (r < 0) { log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = EXIT_FAILURE; diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c index 28ebe36b38..1d8bc71e57 100644 --- a/src/debug-generator/debug-generator.c +++ b/src/debug-generator/debug-generator.c @@ -39,56 +39,53 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat assert(key); if (streq(key, "systemd.mask")) { + char *n; - if (!value) - log_error("Missing argument for systemd.mask= kernel command line parameter."); - else { - char *n; + if (proc_cmdline_value_missing(key, value)) + return 0; - r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); - if (r < 0) - return log_error_errno(r, "Failed to glob unit name: %m"); + r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); + if (r < 0) + return log_error_errno(r, "Failed to glob unit name: %m"); - r = strv_consume(&arg_mask, n); - if (r < 0) - return log_oom(); - } + r = strv_consume(&arg_mask, n); + if (r < 0) + return log_oom(); } else if (streq(key, "systemd.wants")) { + char *n; - if (!value) - log_error("Missing argument for systemd.want= kernel command line parameter."); - else { - char *n; + if (proc_cmdline_value_missing(key, value)) + return 0; - r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); - if (r < 0) - return log_error_errno(r, "Failed to glob unit name: %m"); + r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); + if (r < 0) + return log_error_errno(r, "Failed to glob unit name: %m"); - r = strv_consume(&arg_wants, n); - if (r < 0) - return log_oom(); - } + r = strv_consume(&arg_wants, n); + if (r < 0) + return log_oom(); - } else if (streq(key, "systemd.debug-shell")) { + } else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) { if (value) { r = parse_boolean(value); if (r < 0) - log_error("Failed to parse systemd.debug-shell= argument '%s', ignoring.", value); + log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value); else arg_debug_shell = r; } else arg_debug_shell = true; + } else if (streq(key, "systemd.unit")) { - if (!value) - log_error("Missing argument for systemd.unit= kernel command line parameter."); - else { - r = free_and_strdup(&arg_default_unit, value); - if (r < 0) - return log_error_errno(r, "Failed to set default unit %s: %m", value); - } + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_default_unit, value); + if (r < 0) + return log_error_errno(r, "Failed to set default unit %s: %m", value); + } else if (!value) { const char *target; @@ -173,7 +170,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 7c615abbc5..fd7051f21e 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -826,7 +826,7 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - _cleanup_free_ char *enabled = NULL; + bool enabled; int r; r = parse_argv(argc, argv); @@ -839,15 +839,14 @@ int main(int argc, char *argv[]) { umask(0022); - r = get_proc_cmdline_key("systemd.firstboot=", &enabled); - if (r < 0) - return r; - if (r > 0) { - r = parse_boolean(enabled); - if (r == 0) - goto finish; - if (r < 0) - log_warning_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %s", enabled); + r = proc_cmdline_get_bool("systemd.firstboot", &enabled); + if (r < 0) { + log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring."); + goto finish; + } + if (r > 0 && !enabled) { + r = 0; /* disabled */ + goto finish; } r = process_locale(); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index be25c6a2b2..2100681e17 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -99,7 +99,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat assert(key); - if (streq(key, "fsck.mode") && value) { + if (streq(key, "fsck.mode")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (streq(value, "auto")) arg_force = arg_skip = false; @@ -110,7 +113,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat else log_warning("Invalid fsck.mode= parameter '%s'. Ignoring.", value); - } else if (streq(key, "fsck.repair") && value) { + } else if (streq(key, "fsck.repair")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (streq(value, "preen")) arg_repair = "-a"; @@ -293,7 +299,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index f6a912ae06..84163abbc5 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -612,27 +612,36 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat * instance should take precedence. In the case of multiple rootflags= * or usrflags= the arguments should be concatenated */ - if (STR_IN_SET(key, "fstab", "rd.fstab") && value) { + if (STR_IN_SET(key, "fstab", "rd.fstab")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : 1; if (r < 0) log_warning("Failed to parse fstab switch %s. Ignoring.", value); else arg_fstab_enabled = r; - } else if (streq(key, "root") && value) { + } else if (streq(key, "root")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (free_and_strdup(&arg_root_what, value) < 0) return log_oom(); - } else if (streq(key, "rootfstype") && value) { + } else if (streq(key, "rootfstype")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (free_and_strdup(&arg_root_fstype, value) < 0) return log_oom(); - } else if (streq(key, "rootflags") && value) { + } else if (streq(key, "rootflags")) { char *o; + if (proc_cmdline_value_missing(key, value)) + return 0; + o = arg_root_options ? strjoin(arg_root_options, ",", value) : strdup(value); @@ -642,19 +651,28 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat free(arg_root_options); arg_root_options = o; - } else if (streq(key, "mount.usr") && value) { + } else if (streq(key, "mount.usr")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (free_and_strdup(&arg_usr_what, value) < 0) return log_oom(); - } else if (streq(key, "mount.usrfstype") && value) { + } else if (streq(key, "mount.usrfstype")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (free_and_strdup(&arg_usr_fstype, value) < 0) return log_oom(); - } else if (streq(key, "mount.usrflags") && value) { + } else if (streq(key, "mount.usrflags")) { char *o; + if (proc_cmdline_value_missing(key, value)) + return 0; + o = arg_usr_options ? strjoin(arg_usr_options, ",", value) : strdup(value); @@ -689,7 +707,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index a60905de94..f94f9f7827 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -912,15 +912,18 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat assert(key); - if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) { + if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto")) { - r = parse_boolean(value); + r = value ? parse_boolean(value) : 1; if (r < 0) log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value); else arg_enabled = r; - } else if (streq(key, "root") && value) { + } else if (streq(key, "root")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; /* Disable root disk logic if there's a root= value * specified (unless it happens to be "gpt-auto") */ @@ -1018,7 +1021,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index 9f59c04b26..a97fe668d5 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -31,15 +31,22 @@ #include "util.h" static const char *arg_dest = "/tmp"; -static char *arg_resume_dev = NULL; +static char *arg_resume_device = NULL; static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { - if (streq(key, "resume") && value) { - free(arg_resume_dev); - arg_resume_dev = fstab_node_to_udev_node(value); - if (!arg_resume_dev) + if (streq(key, "resume")) { + char *s; + + if (proc_cmdline_value_missing(key, value)) + return 0; + + s = fstab_node_to_udev_node(value); + if (!s) return log_oom(); + + free(arg_resume_device); + arg_resume_device = s; } return 0; @@ -49,10 +56,10 @@ static int process_resume(void) { _cleanup_free_ char *name = NULL, *lnk = NULL; int r; - if (!arg_resume_dev) + if (!arg_resume_device) return 0; - r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_dev, ".service", &name); + r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); @@ -88,12 +95,12 @@ int main(int argc, char *argv[]) { if (!in_initrd()) return EXIT_SUCCESS; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = process_resume(); - free(arg_resume_dev); + free(arg_resume_device); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 5c6941ebd6..6bdb375fb7 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1532,60 +1532,93 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat assert(s); - if (streq(key, "systemd.journald.forward_to_syslog")) { + if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_syslog")) { + r = value ? parse_boolean(value) : true; if (r < 0) 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")) { + + } else if (proc_cmdline_key_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")) { + + } else if (proc_cmdline_key_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")) { + + } else if (proc_cmdline_key_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) { + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + 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) { + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + 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) { + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + 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) { + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + 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) { + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + 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); @@ -1898,7 +1931,10 @@ int server_init(Server *s) { journal_reset_metrics(&s->runtime_storage.metrics); server_parse_config_file(s); - parse_proc_cmdline(parse_proc_cmdline_item, s, true); + + r = proc_cmdline_parse(parse_proc_cmdline_item, s, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); 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", diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 0901fea8dc..615998a6f6 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -62,7 +62,11 @@ static int add_modules(const char *p) { static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; - if (streq(key, "modules-load") && value) { + if (proc_cmdline_key_streq(key, "modules_load")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + r = add_modules(value); if (r < 0) return r; @@ -226,7 +230,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index 2714cde5c7..2495bcbefd 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -34,7 +34,10 @@ static bool arg_force = false; static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { - if (streq(key, "quotacheck.mode") && value) { + if (streq(key, "quotacheck.mode")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; if (streq(value, "auto")) arg_force = arg_skip = false; @@ -88,7 +91,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c index 4101678f19..12dac8585b 100644 --- a/src/test/test-proc-cmdline.c +++ b/src/test/test-proc-cmdline.c @@ -35,8 +35,8 @@ static int parse_item(const char *key, const char *value, void *data) { return 0; } -static void test_parse_proc_cmdline(void) { - assert_se(parse_proc_cmdline(parse_item, &obj, true) >= 0); +static void test_proc_cmdline_parse(void) { + assert_se(proc_cmdline_parse(parse_item, &obj, true) >= 0); } static void test_runlevel_to_target(void) { @@ -55,11 +55,101 @@ static void test_runlevel_to_target(void) { assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET)); } +static void test_proc_cmdline_get_key(void) { + _cleanup_free_ char *value = NULL; + + putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm"); + + assert_se(proc_cmdline_get_key("", 0, &value) == -EINVAL); + assert_se(proc_cmdline_get_key("abc", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("abc", 0, &value) == 0 && value == NULL); + assert_se(proc_cmdline_get_key("abc", PROC_CMDLINE_VALUE_OPTIONAL, &value) == 0 && value == NULL); + + assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo_bar", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("foo-bar", PROC_CMDLINE_VALUE_OPTIONAL, NULL) == -EINVAL); + + assert_se(proc_cmdline_get_key("wuff-piep", 0, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff-piep", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", 0, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("wuff_piep", PROC_CMDLINE_VALUE_OPTIONAL, NULL) == -EINVAL); + + assert_se(proc_cmdline_get_key("zumm", 0, &value) == 0 && value == NULL); + assert_se(proc_cmdline_get_key("zumm", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && value == NULL); + assert_se(proc_cmdline_get_key("zumm", 0, NULL) > 0); +} + +static void test_proc_cmdline_get_bool(void) { + bool value = false; + + putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep"); + + assert_se(proc_cmdline_get_bool("", &value) == -EINVAL); + assert_se(proc_cmdline_get_bool("abc", &value) == 0 && value == false); + assert_se(proc_cmdline_get_bool("foo_bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("foo-bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar-waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar_waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("x_y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x_y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("quux", &value) == -EINVAL && value == false); +} + +static void test_proc_cmdline_key_streq(void) { + + assert_se(proc_cmdline_key_streq("", "")); + assert_se(proc_cmdline_key_streq("a", "a")); + assert_se(!proc_cmdline_key_streq("", "a")); + assert_se(!proc_cmdline_key_streq("a", "")); + assert_se(proc_cmdline_key_streq("a", "a")); + assert_se(!proc_cmdline_key_streq("a", "b")); + assert_se(proc_cmdline_key_streq("x-y-z", "x-y-z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x_y_z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x-y_z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x_y-z")); + assert_se(proc_cmdline_key_streq("x_y-z", "x-y_z")); + assert_se(!proc_cmdline_key_streq("x_y-z", "x-z_z")); +} + +static void test_proc_cmdline_key_startswith(void) { + + assert_se(proc_cmdline_key_startswith("", "")); + assert_se(proc_cmdline_key_startswith("x", "")); + assert_se(!proc_cmdline_key_startswith("", "x")); + assert_se(proc_cmdline_key_startswith("x", "x")); + assert_se(!proc_cmdline_key_startswith("x", "y")); + assert_se(!proc_cmdline_key_startswith("foo-bar", "quux")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo-bar")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo_bar")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo_")); + assert_se(!proc_cmdline_key_startswith("foo-bar", "foo_xx")); +} + int main(void) { log_parse_environment(); log_open(); - test_parse_proc_cmdline(); + test_proc_cmdline_parse(); + test_proc_cmdline_key_streq(); + test_proc_cmdline_key_startswith(); + test_proc_cmdline_get_key(); + test_proc_cmdline_get_bool(); test_runlevel_to_target(); return 0; diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 1dca375279..3af87f1388 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -192,14 +192,9 @@ static int load_link(link_config_ctx *ctx, const char *filename) { } static bool enable_name_policy(void) { - _cleanup_free_ char *value = NULL; - int r; - - r = get_proc_cmdline_key("net.ifnames=", &value); - if (r > 0 && streq(value, "0")) - return false; + bool b; - return true; + return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b; } int link_config_load(link_config_ctx *ctx) { diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 895c6f271b..dd23054b0d 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1357,10 +1357,10 @@ static int listen_fds(int *rctrl, int *rnetlink) { /* * read the kernel command line, in case we need to get into debug mode - * udev.log-priority=<level> syslog priority - * udev.children-max=<number of workers> events are fully serialized if set to 1 - * 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 + * udev.log_priority=<level> syslog priority + * udev.children_max=<number of workers> events are fully serialized if set to 1 + * 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, void *data) { int r = 0; @@ -1370,25 +1370,46 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!value) return 0; - if (streq(key, "udev.log-priority") && value) { + if (proc_cmdline_key_streq(key, "udev.log_priority")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + r = util_log_priority(value); if (r >= 0) log_set_max_level(r); - } else if (streq(key, "udev.event-timeout") && value) { + + } else if (proc_cmdline_key_streq(key, "udev.event_timeout")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + r = safe_atou64(value, &arg_event_timeout_usec); 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) + + } else if (proc_cmdline_key_streq(key, "udev.children_max")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + r = safe_atou(value, &arg_children_max); - else if (streq(key, "udev.exec-delay") && value) + + } else if (proc_cmdline_key_streq(key, "udev.exec_delay")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + r = safe_atoi(value, &arg_exec_delay); - else if (startswith(key, "udev.")) + + } else if (startswith(key, "udev.")) log_warning("Unknown udev kernel command line option \"%s\"", key); if (r < 0) log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value); + return 0; } @@ -1649,7 +1670,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto exit; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); |