]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/proc-cmdline: allow parsing of cmdline from a string
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 26 Sep 2018 07:29:09 +0000 (09:29 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 8 Oct 2018 15:05:19 +0000 (17:05 +0200)
Comes with tests.

Also add direct test for $SYSTEMD_PROC_CMDLINE.

In test-proc-cmdline, "true" was masquerading as PROC_CMDLINE_STRIP_RD_PREFIX,
fix that. Also, reorder functions to match call order.

src/basic/proc-cmdline.c
src/basic/proc-cmdline.h
src/test/test-proc-cmdline.c

index c7c4018df1fb9e7bb1ca94a32700484068c3fe81..b386c705e118e4ed34612c603c5db9a422c14e83 100644 (file)
@@ -39,17 +39,12 @@ 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) {
-        _cleanup_free_ char *line = NULL;
+int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags) {
         const char *p;
         int r;
 
         assert(parse_item);
 
-        r = proc_cmdline(&line);
-        if (r < 0)
-                return r;
-
         p = line;
         for (;;) {
                 _cleanup_free_ char *word = NULL;
@@ -85,6 +80,19 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned fla
         return 0;
 }
 
+int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, unsigned 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 == '-') ||
index 4a9e6e0f6201173729a2411de00c22e92d3a2c0a..ffc45fddb964113e33a020f68f5f9d9f6d5a5313 100644 (file)
@@ -14,6 +14,7 @@ typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *da
 
 int proc_cmdline(char **ret);
 
+int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, unsigned flags);
 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);
index 8f77e084b6cba3b2d2f335865828e9380d752937..5db103bd22a7212e1c52954359b8abf6174033c3 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "alloc-util.h"
+#include "env-util.h"
 #include "log.h"
 #include "macro.h"
 #include "proc-cmdline.h"
@@ -19,28 +20,68 @@ static int parse_item(const char *key, const char *value, void *data) {
 }
 
 static void test_proc_cmdline_parse(void) {
-        assert_se(proc_cmdline_parse(parse_item, &obj, true) >= 0);
+        log_info("/* %s */", __func__);
+
+        assert_se(proc_cmdline_parse(parse_item, &obj, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0);
 }
 
-static void test_runlevel_to_target(void) {
-        in_initrd_force(false);
-        assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
-        assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
-        assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
-        assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
-        assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL));
+static void test_proc_cmdline_override(void) {
+        log_info("/* %s */", __func__);
 
-        in_initrd_force(true);
-        assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
-        assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
-        assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
-        assert_se(streq_ptr(runlevel_to_target("3"), NULL));
-        assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET));
+        assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm") == 0);
+
+        /* Test if the override works */
+        _cleanup_free_ char *line = NULL, *value = NULL;
+        assert_se(proc_cmdline(&line) >= 0);
+
+        /* Test if parsing makes uses of the override */
+        assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm"));
+        assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux"));
+}
+
+static int parse_item_given(const char *key, const char *value, void *data) {
+        assert_se(key);
+        assert_se(data);
+
+        bool *strip = data;
+
+        log_info("%s: option <%s> = <%s>", __func__, key, strna(value));
+        if (streq(key, "foo_bar"))
+                assert_se(streq(value, "quux"));
+        else if (streq(key, "wuff-piep"))
+                assert_se(streq(value, "tuet "));
+        else if (in_initrd() && *strip && streq(key, "zumm"))
+                assert_se(!value);
+        else if (in_initrd() && !*strip && streq(key, "rd.zumm"))
+                assert_se(!value);
+        else
+                assert_not_reached("Bad key!");
+
+        return 0;
+}
+
+static void test_proc_cmdline_given(bool flip_initrd) {
+        log_info("/* %s (flip: %s) */", __func__, yes_no(flip_initrd));
+
+        if (flip_initrd)
+                in_initrd_force(!in_initrd());
+
+        bool t = true, f = false;
+        assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm",
+                                           parse_item_given, &t, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0);
+
+        assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm",
+                                           parse_item_given, &f, 0) >= 0);
+
+
+        if (flip_initrd)
+                in_initrd_force(!in_initrd());
 }
 
 static void test_proc_cmdline_get_key(void) {
         _cleanup_free_ char *value = NULL;
 
+        log_info("/* %s */", __func__);
         putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm");
 
         assert_se(proc_cmdline_get_key("", 0, &value) == -EINVAL);
@@ -78,6 +119,7 @@ static void test_proc_cmdline_get_key(void) {
 static void test_proc_cmdline_get_bool(void) {
         bool value = false;
 
+        log_info("/* %s */", __func__);
         putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep");
 
         assert_se(proc_cmdline_get_bool("", &value) == -EINVAL);
@@ -94,6 +136,7 @@ static void test_proc_cmdline_get_bool(void) {
 }
 
 static void test_proc_cmdline_key_streq(void) {
+        log_info("/* %s */", __func__);
 
         assert_se(proc_cmdline_key_streq("", ""));
         assert_se(proc_cmdline_key_streq("a", "a"));
@@ -110,6 +153,7 @@ static void test_proc_cmdline_key_streq(void) {
 }
 
 static void test_proc_cmdline_key_startswith(void) {
+        log_info("/* %s */", __func__);
 
         assert_se(proc_cmdline_key_startswith("", ""));
         assert_se(proc_cmdline_key_startswith("x", ""));
@@ -124,11 +168,33 @@ static void test_proc_cmdline_key_startswith(void) {
         assert_se(!proc_cmdline_key_startswith("foo-bar", "foo_xx"));
 }
 
+static void test_runlevel_to_target(void) {
+        log_info("/* %s */", __func__);
+
+        in_initrd_force(false);
+        assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+        assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+        assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
+        assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
+        assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL));
+
+        in_initrd_force(true);
+        assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+        assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+        assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL));
+        assert_se(streq_ptr(runlevel_to_target("3"), NULL));
+        assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET));
+}
+
 int main(void) {
         log_parse_environment();
         log_open();
 
         test_proc_cmdline_parse();
+        test_proc_cmdline_override();
+        test_proc_cmdline_given(false);
+        /* Repeat the same thing, but now flip our ininitrdness */
+        test_proc_cmdline_given(true);
         test_proc_cmdline_key_streq();
         test_proc_cmdline_key_startswith();
         test_proc_cmdline_get_key();