return read_one_line_file("/proc/cmdline", ret);
}
+int proc_cmdline_strv(char ***ret) {
+ const char *e;
+ int r;
+
+ assert(ret);
+
+ /* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */
+ e = secure_getenv("SYSTEMD_PROC_CMDLINE");
+ if (e)
+ return strv_split_full(ret, e, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+
+ if (detect_container() > 0)
+ return get_process_cmdline_strv(1, /* flags = */ 0, ret);
+ else {
+ _cleanup_free_ char *s = NULL;
+
+ r = read_one_line_file("/proc/cmdline", &s);
+ if (r < 0)
+ return r;
+
+ return strv_split_full(ret, s, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ }
+}
+
static char *mangle_word(const char *word, ProcCmdlineFlags flags) {
char *c;
int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
_cleanup_strv_free_ char **args = NULL;
- _cleanup_free_ char *line = NULL;
int r;
assert(parse_item);
/* We parse the EFI variable first, because later settings have higher priority. */
if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
+ _cleanup_free_ char *line = NULL;
+
r = systemd_efi_options_variable(&line);
if (r < 0) {
if (r != -ENODATA)
return r;
args = strv_free(args);
- line = mfree(line);
}
}
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ r = proc_cmdline_strv(&args);
if (r < 0)
return r;
if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !ret_value)
return -EINVAL;
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ r = proc_cmdline_strv(&args);
if (r < 0)
return r;
return r;
}
- line = mfree(line);
r = systemd_efi_options_variable(&line);
if (r == -ENODATA) {
if (ret_value)
int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) {
_cleanup_strv_free_ char **args = NULL;
- _cleanup_free_ char *line = NULL;
int r, ret = 0;
va_list ap;
/* This call may clobber arguments on failure! */
if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
+ _cleanup_free_ char *line = NULL;
+
r = systemd_efi_options_variable(&line);
if (r < 0 && r != -ENODATA)
log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
ret = r;
args = strv_free(args);
- line = mfree(line);
}
}
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ r = proc_cmdline_strv(&args);
if (r < 0)
return r;
#include "proc-cmdline.h"
#include "special.h"
#include "string-util.h"
+#include "strv.h"
#include "tests.h"
static int obj;
TEST(proc_cmdline_override) {
_cleanup_free_ char *line = NULL, *value = NULL;
+ _cleanup_strv_free_ char **args = NULL;
assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"") == 0);
assert_se(putenv((char*) "SYSTEMD_EFI_OPTIONS=different") == 0);
assert_se(proc_cmdline(&line) >= 0);
assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\""));
line = mfree(line);
+ assert_se(proc_cmdline_strv(&args) >= 0);
+ assert_se(strv_equal(args, STRV_MAKE("foo_bar=quux", "wuff-piep=tuet", "zumm", "some_arg_with_space=foo bar", "and_one_more=zzz aaa")));
+ args = strv_free(args);
/* Test if parsing makes uses of the override */
assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux"));
assert_se(proc_cmdline(&line) >= 0);
assert_se(streq(line, "hoge"));
line = mfree(line);
+ assert_se(proc_cmdline_strv(&args) >= 0);
+ assert_se(strv_equal(args, STRV_MAKE("hoge")));
+ args = strv_free(args);
assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux"));
value = mfree(value);