summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-11-12 12:41:23 +0100
committerLennart Poettering <lennart@poettering.net>2018-11-14 17:01:54 +0100
commit78b30ee056796e7fbb2eb5e8ed9363511da9fa5d (patch)
tree6cbec11c62c974d55dfd837111f64d783c32e0a6 /src
parentproc-cmdline: split out rd. prefix handling in proc_cmdline_parse_given() and... (diff)
downloadsystemd-78b30ee056796e7fbb2eb5e8ed9363511da9fa5d.tar.xz
systemd-78b30ee056796e7fbb2eb5e8ed9363511da9fa5d.zip
proc-cmdline: introduce new proc_cmdline_get_key_many() helper
This is like parse_env_file(), but from the kernel command line
Diffstat (limited to 'src')
-rw-r--r--src/basic/proc-cmdline.c56
-rw-r--r--src/basic/proc-cmdline.h3
-rw-r--r--src/test/test-proc-cmdline.c19
3 files changed, 78 insertions, 0 deletions
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index 112f3b7aa2..1670001364 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -251,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;
diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h
index cf04cb46c2..ff04379fbd 100644
--- a/src/basic/proc-cmdline.h
+++ b/src/basic/proc-cmdline.h
@@ -21,6 +21,9 @@ int proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, ProcCmd
int proc_cmdline_get_key(const char *parameter, ProcCmdlineFlags flags, char **value);
int proc_cmdline_get_bool(const char *key, bool *ret);
+int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...);
+#define proc_cmdline_get_key_many(flags, ...) proc_cmdline_get_key_many_internal(flags, __VA_ARGS__, NULL)
+
char *proc_cmdline_key_startswith(const char *s, const char *prefix);
bool proc_cmdline_key_streq(const char *x, const char *y);
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
index 1b6724755f..3edc75f554 100644
--- a/src/test/test-proc-cmdline.c
+++ b/src/test/test-proc-cmdline.c
@@ -135,6 +135,24 @@ static void test_proc_cmdline_get_bool(void) {
assert_se(proc_cmdline_get_bool("quux", &value) == -EINVAL && value == false);
}
+static void test_proc_cmdline_get_key_many(void) {
+ _cleanup_free_ char *value1 = NULL, *value2 = NULL, *value3 = NULL, *value4 = NULL;
+
+ log_info("/* %s */", __func__);
+ assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm") == 0);
+
+ assert_se(proc_cmdline_get_key_many(0,
+ "wuff-piep", &value3,
+ "foo_bar", &value1,
+ "idontexist", &value2,
+ "zumm", &value4) == 2);
+
+ assert_se(streq_ptr(value1, "quux"));
+ assert_se(!value2);
+ assert_se(streq_ptr(value3, "tuet"));
+ assert_se(!value4);
+}
+
static void test_proc_cmdline_key_streq(void) {
log_info("/* %s */", __func__);
@@ -199,6 +217,7 @@ int main(void) {
test_proc_cmdline_key_startswith();
test_proc_cmdline_get_key();
test_proc_cmdline_get_bool();
+ test_proc_cmdline_get_key_many();
test_runlevel_to_target();
return 0;