diff --git a/src/core/main.c b/src/core/main.c index 25ddafee47..18d0927b7a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -259,7 +259,7 @@ static int set_default_unit(const char *u) { return 0; } -static int parse_proc_cmdline_word(const char *word) { +static int parse_proc_cmdline_item(const char *key, const char *value) { static const char * const rlmap[] = { "emergency", SPECIAL_EMERGENCY_TARGET, @@ -274,125 +274,119 @@ static int parse_proc_cmdline_word(const char *word) { "4", SPECIAL_RUNLEVEL4_TARGET, "5", SPECIAL_RUNLEVEL5_TARGET, }; + int r; - assert(word); + assert(key); - if (startswith(word, "systemd.unit=")) { + if (streq(key, "systemd.unit") && value) { if (!in_initrd()) - return set_default_unit(word + 13); + return set_default_unit(value); - } else if (startswith(word, "rd.systemd.unit=")) { + } else if (streq(key, "rd.systemd.unit") && value) { - if (in_initrd()) - return set_default_unit(word + 16); + return set_default_unit(value); - } else if (startswith(word, "systemd.log_target=")) { + } else if (streq(key, "systemd.log_target") && value) { - if (log_set_target_from_string(word + 19) < 0) - log_warning("Failed to parse log target %s. Ignoring.", word + 19); + if (log_set_target_from_string(value) < 0) + log_warning("Failed to parse log target %s. Ignoring.", value); - } else if (startswith(word, "systemd.log_level=")) { + } else if (streq(key, "systemd.log_level") && value) { - if (log_set_max_level_from_string(word + 18) < 0) - log_warning("Failed to parse log level %s. Ignoring.", word + 18); + if (log_set_max_level_from_string(value) < 0) + log_warning("Failed to parse log level %s. Ignoring.", value); - } else if (startswith(word, "systemd.log_color=")) { + } else if (streq(key, "systemd.log_color") && value) { - if (log_show_color_from_string(word + 18) < 0) - log_warning("Failed to parse log color setting %s. Ignoring.", word + 18); + if (log_show_color_from_string(value) < 0) + log_warning("Failed to parse log color setting %s. Ignoring.", value); - } else if (startswith(word, "systemd.log_location=")) { + } else if (streq(key, "systemd.log_location") && value) { - if (log_show_location_from_string(word + 21) < 0) - log_warning("Failed to parse log location setting %s. Ignoring.", word + 21); + if (log_show_location_from_string(value) < 0) + log_warning("Failed to parse log location setting %s. Ignoring.", value); - } else if (startswith(word, "systemd.dump_core=")) { - int r; + } else if (streq(key, "systemd.dump_core") && value) { - r = parse_boolean(word + 18); + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18); + log_warning("Failed to parse dump core switch %s. Ignoring.", value); else arg_dump_core = r; - } else if (startswith(word, "systemd.crash_shell=")) { - int r; + } else if (streq(key, "systemd.crash_shell") && value) { - r = parse_boolean(word + 20); + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20); + log_warning("Failed to parse crash shell switch %s. Ignoring.", value); else arg_crash_shell = r; - } else if (startswith(word, "systemd.confirm_spawn=")) { - int r; + } else if (streq(key, "systemd.crash_chvt") && value) { - r = parse_boolean(word + 22); + if (safe_atoi(value, &r) < 0) + log_warning("Failed to parse crash chvt switch %s. Ignoring.", value); + else + arg_crash_chvt = r; + + } else if (streq(key, "systemd.confirm_spawn") && value) { + + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22); + log_warning("Failed to parse confirm spawn switch %s. Ignoring.", value); else arg_confirm_spawn = r; - } else if (startswith(word, "systemd.crash_chvt=")) { - int k; + } else if (streq(key, "systemd.show_status") && value) { - if (safe_atoi(word + 19, &k) < 0) - log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19); - else - arg_crash_chvt = k; - - } else if (startswith(word, "systemd.show_status=")) { - int r; - - r = parse_show_status(word + 20, &arg_show_status); + r = parse_show_status(value, &arg_show_status); if (r < 0) - log_warning("Failed to parse show status switch %s. Ignoring.", word + 20); - } else if (startswith(word, "systemd.default_standard_output=")) { - int r; + log_warning("Failed to parse show status switch %s. Ignoring.", value); - r = exec_output_from_string(word + 32); + } else if (streq(key, "systemd.default_standard_output") && value) { + + r = exec_output_from_string(value); if (r < 0) - log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32); + log_warning("Failed to parse default standard output switch %s. Ignoring.", value); else arg_default_std_output = r; - } else if (startswith(word, "systemd.default_standard_error=")) { - int r; - r = exec_output_from_string(word + 31); + } else if (streq(key, "systemd.default_standard_error") && value) { + + r = exec_output_from_string(value); if (r < 0) - log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31); + log_warning("Failed to parse default standard error switch %s. Ignoring.", value); else arg_default_std_error = r; - } else if (startswith(word, "systemd.setenv=")) { - const char *cenv = word + 15; - if (env_assignment_is_valid(cenv)) { + } else if (streq(key, "systemd.setenv") && value) { + + if (env_assignment_is_valid(value)) { char **env; - env = strv_env_set(arg_default_environment, cenv); + env = strv_env_set(arg_default_environment, value); if (env) arg_default_environment = env; else - log_warning("Setting environment variable '%s' failed, ignoring: %s", - cenv, strerror(ENOMEM)); + log_warning("Setting environment variable '%s' failed, ignoring: %s", value, strerror(ENOMEM)); } else - log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv); + log_warning("Environment variable name '%s' is not valid. Ignoring.", value); - } else if (startswith(word, "systemd.") || - (in_initrd() && startswith(word, "rd.systemd."))) { + } else if (!streq(key, "systemd.restore_state") && + (startswith(key, "systemd.") || startswith(key, "rd.systemd."))) { const char *c; /* Ignore systemd.journald.xyz and friends */ - c = word; + c = key; if (startswith(c, "rd.")) c += 3; if (startswith(c, "systemd.")) c += 8; if (c[strcspn(c, ".=")] != '.') { - log_warning("Unknown kernel switch %s. Ignoring.", word); + log_warning("Unknown kernel switch %s. Ignoring.", key); log_info("Supported kernel switches:\n" "systemd.unit=UNIT Default unit to start\n" @@ -411,25 +405,30 @@ static int parse_proc_cmdline_word(const char *word) { " Set default log output for services\n" "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n" " Set default log error output for services\n" - "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n"); + "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n" + "systemd.restore_state=0|1 Restore backlight/rfkill state at boot\n"); } - } else if (streq(word, "quiet")) { + } else if (streq(key, "quiet") && !value) { + if (arg_show_status == _SHOW_STATUS_UNSET) arg_show_status = SHOW_STATUS_AUTO; - } else if (streq(word, "debug")) { + + } else if (streq(key, "debug") && !value) { + /* Log to kmsg, the journal socket will fill up before the * journal is started and tools running during that time * will block with every log message for for 60 seconds, * before they give up. */ log_set_max_level(LOG_DEBUG); log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_CONSOLE : LOG_TARGET_KMSG); - } else if (!in_initrd()) { + + } else if (!in_initrd() && !value) { unsigned i; /* SysV compatibility */ for (i = 0; i < ELEMENTSOF(rlmap); i += 2) - if (streq(word, rlmap[i])) + if (streq(key, rlmap[i])) return set_default_unit(rlmap[i+1]); } @@ -1000,7 +999,18 @@ static int parse_argv(int argc, char *argv[]) { * instead. */ for (a = argv; a < argv + argc; a++) { - r = parse_proc_cmdline_word(*a); + _cleanup_free_ char *w; + char *value; + + w = strdup(*a); + if (!w) + return log_oom(); + + value = strchr(w, '='); + if (value) + *(value++) = 0; + + r = parse_proc_cmdline_item(w, value); if (r < 0) { log_error("Failed on cmdline argument %s: %s", *a, strerror(-r)); return r; @@ -1449,7 +1459,7 @@ int main(int argc, char *argv[]) { goto finish; if (arg_running_as == SYSTEMD_SYSTEM) - if (parse_proc_cmdline(parse_proc_cmdline_word) < 0) + if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) goto finish; log_parse_environment(); diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index d2e055431e..9460e83fd1 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -255,85 +255,44 @@ static int create_disk( return 0; } -static int parse_proc_cmdline_word(const char *word) { +static int parse_proc_cmdline_item(const char *key, const char *value) { int r; - if (startswith(word, "luks=")) { - r = parse_boolean(word + 5); + if (STR_IN_SET(key, "luks", "rd.luks") && value) { + + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse luks switch %s. Ignoring.", word + 5); + log_warning("Failed to parse luks switch %s. Ignoring.", value); else arg_enabled = r; - } else if (startswith(word, "rd.luks=")) { + } else if (STR_IN_SET(key, "luks.crypttab", "rd.luks.crypttab") && value) { - if (in_initrd()) { - r = parse_boolean(word + 8); - if (r < 0) - log_warning("Failed to parse luks switch %s. Ignoring.", word + 8); - else - arg_enabled = r; - } - - } else if (startswith(word, "luks.crypttab=")) { - r = parse_boolean(word + 14); + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 14); + log_warning("Failed to parse luks crypttab switch %s. Ignoring.", value); else arg_read_crypttab = r; - } else if (startswith(word, "rd.luks.crypttab=")) { + } else if (STR_IN_SET(key, "luks.uuid", "rd.luks.uuid") && value) { - if (in_initrd()) { - r = parse_boolean(word + 17); - if (r < 0) - log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 17); - else - arg_read_crypttab = r; - } - - } else if (startswith(word, "luks.uuid=")) { - if (strv_extend(&arg_disks, word + 10) < 0) + if (strv_extend(&arg_disks, value) < 0) return log_oom(); - } else if (startswith(word, "rd.luks.uuid=")) { + } else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) { - if (in_initrd()) { - if (strv_extend(&arg_disks, word + 13) < 0) - return log_oom(); - } - - } else if (startswith(word, "luks.options=")) { - if (strv_extend(&arg_options, word + 13) < 0) + if (strv_extend(&arg_options, value) < 0) return log_oom(); - } else if (startswith(word, "rd.luks.options=")) { + } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) { - if (in_initrd()) { - if (strv_extend(&arg_options, word + 16) < 0) - return log_oom(); - } - - } else if (startswith(word, "luks.key=")) { free(arg_keyfile); - arg_keyfile = strdup(word + 9); + arg_keyfile = strdup(key); if (!arg_keyfile) return log_oom(); - } else if (startswith(word, "rd.luks.key=")) { - - if (in_initrd()) { - free(arg_keyfile); - arg_keyfile = strdup(word + 12); - if (!arg_keyfile) - return log_oom(); - } - - } else if (startswith(word, "luks.") || - (in_initrd() && startswith(word, "rd.luks."))) { - - log_warning("Unknown kernel switch %s. Ignoring.", word); - } + } else if (startswith(key, "luks.") || startswith(key, "rd.luks.")) + log_warning("Unknown kernel switch %s. Ignoring.", key); return 0; } @@ -359,7 +318,7 @@ int main(int argc, char *argv[]) { umask(0022); - if (parse_proc_cmdline(parse_proc_cmdline_word) < 0) + if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) goto cleanup; if (!arg_enabled) { diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 4a5f6b17c1..b6691c96ff 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -72,21 +72,26 @@ static void start_target(const char *target) { log_error("Failed to start unit: %s", bus_error_message(&error, -r)); } -static int parse_proc_cmdline_word(const char *w) { - if (streq(w, "fsck.mode=auto")) - arg_force = arg_skip = false; - else if (streq(w, "fsck.mode=force")) - arg_force = true; - else if (streq(w, "fsck.mode=skip")) - arg_skip = true; - else if (startswith(w, "fsck")) +static int parse_proc_cmdline_item(const char *key, const char *value) { + + if (streq(key, "fsck.mode") && value) { + + if (streq(value, "auto")) + arg_force = arg_skip = false; + else if (streq(value, "force")) + arg_force = true; + else if (streq(value, "skip")) + arg_skip = true; + else + log_warning("Invalid fsck.mode= parameter. Ignoring."); + } else if (startswith(key, "fsck.")) log_warning("Invalid fsck parameter. Ignoring."); #ifdef HAVE_SYSV_COMPAT - else if (streq(w, "fastboot")) { - log_error("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line."); + else if (streq(key, "fastboot") && !value) { + log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line."); arg_skip = true; - } else if (streq(w, "forcefsck")) { - log_error("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line."); + } else if (streq(key, "forcefsck") && !value) { + log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line."); arg_force = true; } #endif @@ -215,7 +220,7 @@ int main(int argc, char *argv[]) { umask(0022); - parse_proc_cmdline(parse_proc_cmdline_word); + parse_proc_cmdline(parse_proc_cmdline_item); test_files(); if (!arg_force && arg_skip) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index aac1a436ec..c50586b793 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -34,6 +34,7 @@ #include "mkdir.h" #include "fileio.h" #include "generator.h" +#include "strv.h" static const char *arg_dest = "/tmp"; static bool arg_fstab_enabled = true; @@ -461,32 +462,19 @@ static int parse_new_root_from_proc_cmdline(void) { return (r < 0) ? r : 0; } -static int parse_proc_cmdline_word(const char *word) { +static int parse_proc_cmdline_item(const char *key, const char *value) { int r; - if (startswith(word, "fstab=")) { + if (STR_IN_SET(key, "fstab", "rd.fstab") && value) { - r = parse_boolean(word + 6); + r = parse_boolean(value); if (r < 0) - log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6); + log_warning("Failed to parse fstab switch %s. Ignoring.", value); else arg_fstab_enabled = r; - } else if (startswith(word, "rd.fstab=")) { - - if (in_initrd()) { - r = parse_boolean(word + 9); - if (r < 0) - log_warning("Failed to parse fstab switch %s. Ignoring.", word + 9); - else - arg_fstab_enabled = r; - } - - } else if (startswith(word, "fstab.") || - (in_initrd() && startswith(word, "rd.fstab."))) { - - log_warning("Unknown kernel switch %s. Ignoring.", word); - } + } else if (startswith(key, "fstab.") || startswith(key, "rd.fstab.")) + log_warning("Unknown kernel switch %s. Ignoring.", key); return 0; } @@ -508,7 +496,7 @@ int main(int argc, char *argv[]) { umask(0022); - if (parse_proc_cmdline(parse_proc_cmdline_word) < 0) + if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) return EXIT_FAILURE; /* Always honour root= in the kernel command line if we are in an initrd */ diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 37d7a77068..49b153d411 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -69,20 +69,13 @@ static int add_modules(const char *p) { return 0; } -static int parse_proc_cmdline_word(const char *word) { +static int parse_proc_cmdline_item(const char *key, const char *value) { int r; - if (startswith(word, "modules-load=")) { - r = add_modules(word + 13); + if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) { + r = add_modules(value); if (r < 0) return r; - - } else if (startswith(word, "rd.modules-load=")) { - if (in_initrd()) { - r = add_modules(word + 16); - if (r < 0) - return r; - } } return 0; @@ -253,7 +246,7 @@ int main(int argc, char *argv[]) { umask(0022); - if (parse_proc_cmdline(parse_proc_cmdline_word) < 0) + if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) return EXIT_FAILURE; ctx = kmod_new(NULL, NULL); diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index 8ff0f7f0c3..efd6e18308 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -31,18 +31,24 @@ static bool arg_skip = false; static bool arg_force = false; -static int parse_proc_cmdline_word(const char *w) { - if (streq(w, "quotacheck.mode=auto")) - arg_force = arg_skip = false; - else if (streq(w, "quotacheck.mode=force")) - arg_force = true; - else if (streq(w, "quotacheck.mode=skip")) - arg_skip = true; - else if (startswith(w, "quotacheck")) +static int parse_proc_cmdline_item(const char *key, const char *value) { + + if (streq(key, "quotacheck.mode") && value) { + + if (streq(value, "auto")) + arg_force = arg_skip = false; + else if (streq(value, "force")) + arg_force = true; + else if (streq(value, "skip")) + arg_skip = true; + else + log_warning("Invalid quotacheck.mode= parameter. Ignoring."); + + } else if (startswith(key, "quotacheck.")) log_warning("Invalid quotacheck parameter. Ignoring."); #ifdef HAVE_SYSV_COMPAT - else if (streq(w, "forcequotacheck")) { - log_error("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line."); + else if (streq(key, "forcequotacheck") && !value) { + log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line."); arg_force = true; } #endif @@ -80,7 +86,7 @@ int main(int argc, char *argv[]) { umask(0022); - parse_proc_cmdline(parse_proc_cmdline_word); + parse_proc_cmdline(parse_proc_cmdline_item); test_files(); if (!arg_force) { diff --git a/src/shared/util.c b/src/shared/util.c index 588b1f5691..cffa1abb30 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5944,7 +5944,7 @@ int split_pair(const char *s, const char *sep, char **l, char **r) { } int shall_restore_state(void) { - _cleanup_free_ char *line; + _cleanup_free_ char *line = NULL; char *w, *state; size_t l; int r; @@ -5955,11 +5955,26 @@ int shall_restore_state(void) { if (r == 0) /* Container ... */ return 1; - FOREACH_WORD_QUOTED(w, l, line, state) - if (l == 23 && strneq(w, "systemd.restore_state=0", 23)) - return 0; + r = 1; - return 1; + FOREACH_WORD_QUOTED(w, l, line, state) { + const char *e; + char n[l+1]; + int k; + + memcpy(n, w, l); + n[l] = 0; + + e = startswith(n, "systemd.restore_state="); + if (!e) + continue; + + k = parse_boolean(e); + if (k >= 0) + r = k; + } + + return r; } int proc_cmdline(char **ret) { @@ -5977,7 +5992,7 @@ int proc_cmdline(char **ret) { if (*p == 0) *p = ' '; - *p = 0; + *p = 0; *ret = buf; return 1; } @@ -5989,12 +6004,14 @@ int proc_cmdline(char **ret) { return 1; } -int parse_proc_cmdline(int (*parse_word)(const char *word)) { +int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { _cleanup_free_ char *line = NULL; char *w, *state; size_t l; int r; + assert(parse_item); + r = proc_cmdline(&line); if (r < 0) log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); @@ -6002,17 +6019,23 @@ int parse_proc_cmdline(int (*parse_word)(const char *word)) { return 0; FOREACH_WORD_QUOTED(w, l, line, state) { - _cleanup_free_ char *word; + char word[l+1], *value; - word = strndup(w, l); - if (!word) - return log_oom(); + memcpy(word, w, l); + word[l] = 0; - r = parse_word(word); - if (r < 0) { - log_error("Failed on cmdline argument %s: %s", word, strerror(-r)); + /* Filter out arguments that are intended only for the + * initrd */ + if (!in_initrd() && startswith(word, "rd.")) + continue; + + value = strchr(word, '='); + if (value) + *(value++) = 0; + + r = parse_item(word, value); + if (r < 0) return r; - } } return 0; diff --git a/src/shared/util.h b/src/shared/util.h index 51b1caf946..cd166f6637 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -869,7 +869,7 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, } int proc_cmdline(char **ret); -int parse_proc_cmdline(int (*parse_word)(const char *word)); +int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); int container_get_leader(const char *machine, pid_t *pid);