summaryrefslogtreecommitdiffstats
path: root/src/basic/proc-cmdline.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-03-22 19:15:43 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-03-29 03:33:01 +0200
commit70806d455483329ba69917832268800bff411382 (patch)
treea29dbf15995dad3f2f612ed087b1f8d0f4919a10 /src/basic/proc-cmdline.c
parentman: correct/tweak text about unit name syntax (diff)
downloadsystemd-70806d455483329ba69917832268800bff411382.tar.xz
systemd-70806d455483329ba69917832268800bff411382.zip
proc-cmdline: split commandline earlier in proc_cmdline_parse() and friend
No functional change, just preparation for later commits.
Diffstat (limited to 'src/basic/proc-cmdline.c')
-rw-r--r--src/basic/proc-cmdline.c230
1 files changed, 116 insertions, 114 deletions
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index de1f66635a..06822ddb49 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -12,8 +12,8 @@
#include "parse-util.h"
#include "proc-cmdline.h"
#include "process-util.h"
-#include "special.h"
#include "string-util.h"
+#include "strv.h"
#include "virt.h"
int proc_cmdline(char **ret) {
@@ -40,71 +40,47 @@ int proc_cmdline(char **ret) {
return read_one_line_file("/proc/cmdline", ret);
}
-static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdlineFlags flags) {
- const char *q = *p;
- int r;
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
- const char *c;
-
- r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
- if (r < 0)
- return r;
- if (r == 0)
- break;
+static char *mangle_word(const char *word, ProcCmdlineFlags flags) {
+ char *c;
+ c = startswith(word, "rd.");
+ if (c) {
/* 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;
- }
+ if (!in_initrd())
+ return NULL;
- } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
- continue; /* And optionally filter out arguments that are intended only for the host */
+ if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX))
+ return c;
- *p = q;
- *ret_word = TAKE_PTR(word);
- return 1;
- }
+ } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd())
+ /* And optionally filter out arguments that are intended only for the host */
+ return NULL;
- *p = q;
- *ret_word = NULL;
- return 0;
+ return (char*) word;
}
-static int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
- const char *p;
+static int proc_cmdline_parse_strv(char **args, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
int r;
assert(parse_item);
- /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_parse(), let's make this
- * clear. */
+ /* 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;
+ STRV_FOREACH(word, args) {
+ char *key, *value;
- r = proc_cmdline_extract_first(&p, &word, flags);
- if (r < 0)
- return r;
- if (r == 0)
- break;
+ key = mangle_word(*word, flags);
+ if (!key)
+ continue;
- value = strchr(word, '=');
+ value = strchr(key, '=');
if (value)
- *(value++) = 0;
+ *(value++) = '\0';
- r = parse_item(word, value, data);
+ r = parse_item(key, value, data);
if (r < 0)
return r;
}
@@ -113,6 +89,7 @@ static int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse
}
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;
@@ -126,10 +103,15 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineF
if (r != -ENODATA)
log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
} else {
- r = proc_cmdline_parse_given(line, parse_item, data, flags);
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
+
+ r = proc_cmdline_parse_strv(args, parse_item, data, flags);
if (r < 0)
return r;
+ args = strv_free(args);
line = mfree(line);
}
}
@@ -138,7 +120,11 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineF
if (r < 0)
return r;
- return proc_cmdline_parse_given(line, parse_item, data, flags);
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
+
+ return proc_cmdline_parse_strv(args, parse_item, data, flags);
}
static bool relaxed_equal_char(char a, char b) {
@@ -173,24 +159,19 @@ bool proc_cmdline_key_streq(const char *x, const char *y) {
return true;
}
-static int cmdline_get_key(const char *line, const char *key, ProcCmdlineFlags flags, char **ret_value) {
+static int cmdline_get_key(char **args, const char *key, ProcCmdlineFlags flags, char **ret_value) {
_cleanup_free_ char *v = NULL;
bool found = false;
- const char *p;
int r;
- assert(line);
assert(key);
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
+ STRV_FOREACH(p, args) {
+ const char *word;
- r = proc_cmdline_extract_first(&p, &word, flags);
- if (r < 0)
- return r;
- if (r == 0)
- break;
+ word = mangle_word(*p, flags);
+ if (!word)
+ continue;
if (ret_value) {
const char *e;
@@ -224,6 +205,7 @@ static int cmdline_get_key(const char *line, const char *key, ProcCmdlineFlags f
}
int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) {
+ _cleanup_strv_free_ char **args = NULL;
_cleanup_free_ char *line = NULL, *v = NULL;
int r;
@@ -251,10 +233,14 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_val
if (r < 0)
return r;
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
+
if (FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) /* Shortcut */
- return cmdline_get_key(line, key, flags, ret_value);
+ return cmdline_get_key(args, key, flags, ret_value);
- r = cmdline_get_key(line, key, flags, ret_value ? &v : NULL);
+ r = cmdline_get_key(args, key, flags, ret_value ? &v : NULL);
if (r < 0)
return r;
if (r > 0) {
@@ -275,7 +261,12 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_val
if (r < 0)
return r;
- return cmdline_get_key(line, key, flags, ret_value);
+ args = strv_free(args);
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
+
+ return cmdline_get_key(args, key, flags, ret_value);
}
int proc_cmdline_get_bool(const char *key, bool *ret) {
@@ -303,75 +294,86 @@ 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;
- bool processing_efi = true;
- const char *p;
- va_list ap;
+static int cmdline_get_key_ap(ProcCmdlineFlags flags, char* const* args, 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));
+ for (;;) {
+ char **v;
+ const char *k, *e;
- /* This call may clobber arguments on failure! */
+ k = va_arg(ap, const char*);
+ if (!k)
+ break;
- if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
- r = systemd_efi_options_variable(&line);
- if (r < 0 && r != -ENODATA)
- log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
- }
+ assert_se(v = va_arg(ap, char**));
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
+ STRV_FOREACH(p, args) {
+ const char *word;
- r = proc_cmdline_extract_first(&p, &word, flags);
- if (r < 0)
- return r;
- if (r == 0) {
- /* We finished with this command line. If this was the EFI one, then let's proceed with the regular one */
- if (processing_efi) {
- processing_efi = false;
+ word = mangle_word(*p, flags);
+ if (!word)
+ continue;
- line = mfree(line);
- r = proc_cmdline(&line);
+ e = proc_cmdline_key_startswith(word, k);
+ if (e && *e == '=') {
+ r = free_and_strdup(v, e + 1);
if (r < 0)
return r;
- p = line;
- continue;
+ ret++;
}
-
- break;
}
+ }
- va_start(ap, flags);
+ return ret;
+}
- for (;;) {
- char **v;
- const char *k, *e;
+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;
- k = va_arg(ap, const char*);
- if (!k)
- break;
+ /* 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));
- assert_se(v = va_arg(ap, char**));
+ /* This call may clobber arguments on failure! */
- 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;
- }
+ if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
+ r = systemd_efi_options_variable(&line);
+ if (r < 0 && r != -ENODATA)
+ log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
+ if (r >= 0) {
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
- ret++;
- }
- }
+ va_start(ap, flags);
+ r = cmdline_get_key_ap(flags, args, ap);
+ va_end(ap);
+ if (r < 0)
+ return r;
- va_end(ap);
+ ret = r;
+ args = strv_free(args);
+ line = mfree(line);
+ }
}
- return ret;
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+
+ r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return r;
+
+ va_start(ap, flags);
+ r = cmdline_get_key_ap(flags, args, ap);
+ va_end(ap);
+ if (r < 0)
+ return r;
+
+ return ret + r;
}