summaryrefslogtreecommitdiff
path: root/src/basic/proc-cmdline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/proc-cmdline.c')
-rw-r--r--src/basic/proc-cmdline.c176
1 files changed, 133 insertions, 43 deletions
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index add481c2ae..1670001364 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -39,46 +39,71 @@ int proc_cmdline(char **ret) {
return read_one_line_file("/proc/cmdline", ret);
}
-int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned flags) {
+static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdlineFlags flags) {
+ const char *q = *p;
+ int r;
- _cleanup_free_ char *line = NULL;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ const char *c;
+
+ r = extract_first_word(&q, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ /* Filter out arguments that are intended only for the initrd */
+ c = startswith(word, "rd.");
+ if (c) {
+ if (!in_initrd())
+ continue;
+
+ if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) {
+ r = free_and_strdup(&word, c);
+ if (r < 0)
+ return r;
+ }
+
+ } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
+ continue; /* And optionally filter out arguments that are intended only for the host */
+
+ *p = q;
+ *ret_word = TAKE_PTR(word);
+ return 1;
+ }
+
+ *p = q;
+ *ret_word = NULL;
+ return 0;
+}
+
+int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
const char *p;
int r;
assert(parse_item);
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
+ /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_parse(), let's make this
+ * clear. */
+ assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL));
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
- char *value, *key, *q;
+ char *value;
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ r = proc_cmdline_extract_first(&p, &word, flags);
if (r < 0)
return r;
if (r == 0)
break;
- 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(key, '=');
+ value = strchr(word, '=');
if (value)
*(value++) = 0;
- r = parse_item(key, value, data);
+ r = parse_item(word, value, data);
if (r < 0)
return r;
}
@@ -86,15 +111,26 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned fla
return 0;
}
-static bool relaxed_equal_char(char a, char b) {
+int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
+ _cleanup_free_ char *line = NULL;
+ int r;
+
+ assert(parse_item);
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+
+ return proc_cmdline_parse_given(line, parse_item, data, flags);
+}
+
+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);
@@ -120,29 +156,29 @@ bool proc_cmdline_key_streq(const char *x, const char *y) {
return true;
}
-int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
+int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) {
_cleanup_free_ char *line = NULL, *ret = NULL;
bool found = false;
const char *p;
int r;
- /* Looks for a specific key on the kernel command line. Supports two modes:
+ /* Looks for a specific key on the kernel command line. Supports three 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".
+ * a) The "ret_value" parameter is used. In this case a parameter beginning with the "key" string followed by
+ * "=" is searched for, and the value following it is returned in "ret_value".
*
- * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if 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.
+ * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if 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.
+ * c) The "ret_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)
+ if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !ret_value)
return -EINVAL;
r = proc_cmdline(&line);
@@ -152,20 +188,16 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
p = line;
for (;;) {
_cleanup_free_ char *word = NULL;
- const char *e;
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ r = proc_cmdline_extract_first(&p, &word, flags);
if (r < 0)
return r;
if (r == 0)
break;
- /* 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 (ret_value) {
+ const char *e;
- if (value) {
e = proc_cmdline_key_startswith(word, key);
if (!e)
continue;
@@ -177,17 +209,19 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
found = true;
- } else if (*e == 0 && (flags & PROC_CMDLINE_VALUE_OPTIONAL))
+ } else if (*e == 0 && FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL))
found = true;
} else {
- if (streq(word, key))
+ if (streq(word, key)) {
found = true;
+ break; /* we found what we were looking for */
+ }
}
}
- if (value)
- *value = TAKE_PTR(ret);
+ if (ret_value)
+ *ret_value = TAKE_PTR(ret);
return found;
}
@@ -217,6 +251,62 @@ int proc_cmdline_get_bool(const char *key, bool *ret) {
return 1;
}
+int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) {
+ _cleanup_free_ char *line = NULL;
+ const char *p;
+ va_list ap;
+ int r, ret = 0;
+
+ /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_get_key_many(), let's make
+ * this clear. */
+ assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL));
+
+ /* This call may clobber arguments on failure! */
+
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+
+ p = line;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = proc_cmdline_extract_first(&p, &word, flags);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ va_start(ap, flags);
+
+ for (;;) {
+ char **v;
+ const char *k, *e;
+
+ k = va_arg(ap, const char*);
+ if (!k)
+ break;
+
+ assert_se(v = va_arg(ap, char**));
+
+ e = proc_cmdline_key_startswith(word, k);
+ if (e && *e == '=') {
+ r = free_and_strdup(v, e + 1);
+ if (r < 0) {
+ va_end(ap);
+ return r;
+ }
+
+ ret++;
+ }
+ }
+
+ va_end(ap);
+ }
+
+ return ret;
+}
+
int shall_restore_state(void) {
bool ret;
int r;