[PATCH] Attempt to handle quotes in kernel parameters

From: Daniel Mierswa
Date: Mon Jul 06 2009 - 18:54:38 EST


There was a limitation for kernel parameters with regards to quoting. It
wasn't possible to escape quotes or use quotes to form space-filled
values _inside_ parameters. This patch attempts to make that possible,
kernel parameters are now parsed as follows:
'"param= value"' [param= value][]
'param=" value "" combination "' [param][ value combination ]
'param=" \" test"' [param][ " test]
'"param"=another' [param][another]

Signed-off-by: Daniel Mierswa <impulze@xxxxxxxxxxx>
---
kernel/params.c | 128 +++++++++++++++++++++++++++++++++++--------------------
1 files changed, 82 insertions(+), 46 deletions(-)

diff --git a/kernel/params.c b/kernel/params.c
index 7f6912c..5f9709d 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -72,58 +72,98 @@ static int parse_one(char *param,
return -ENOENT;
}

-/* You can use " around spaces, but can't escape ". */
-/* Hyphens and underscores equivalent in parameter names. */
-static char *next_arg(char *args, char **param, char **val)
+/* modifies args with handled quotes
+ * [" foo bar "] => [ foo bar ]
+ * [" foo \" "] => [ foo " ]
+ * [\"foo] => [\"foo]
+ * [\"foo\" ] => [\"foo" ]
+ */
+static size_t pull_token(char *args, char const *delim)
{
- unsigned int i, equals = 0;
- int in_quote = 0, quoted = 0;
- char *next;
+ size_t length = 0;
+ char *iterator = NULL, *last_quote = NULL;
+
+ for (iterator = args; *iterator; iterator++, length++) {
+ if (*iterator == '"') {
+ if (last_quote) {
+ char *mover = last_quote;
+
+ /* move whole string back until current " is reached */
+ while (mover != iterator - 1) {
+ *mover = *(mover + 1);
+ mover++;
+ }
+
+ /* ignore the current " and move the rest of the string back */
+ while (*mover) {
+ *mover = *(mover + 2);
+ mover++;
+ }
+
+ /* ignored 2 quotes, decrease the iterator and length */
+ length -= 2;
+ iterator -= 2;
+ last_quote = NULL;
+ } else {
+ last_quote = iterator;
+ }

- if (*args == '"') {
- args++;
- in_quote = 1;
- quoted = 1;
- }
+ continue;
+ }

- for (i = 0; args[i]; i++) {
- if (args[i] == ' ' && !in_quote)
- break;
- if (equals == 0) {
- if (args[i] == '=')
- equals = i;
+ if (last_quote) {
+ /* escaped quote */
+ if (*iterator == '\\' && *(iterator + 1) == '"') {
+ char *mover = NULL;
+
+ /* move all characters back */
+ for (mover = iterator; *mover; mover++) {
+ *mover = *(mover + 1);
+ }
+ }
+
+ continue;
+ }
+
+ {
+ /* check for delimiter */
+ char const *delim_iterator = NULL;
+ for (delim_iterator = delim; *delim_iterator; delim_iterator++) {
+ if (*iterator == *delim_iterator) {
+ return length;
+ }
+ }
}
- if (args[i] == '"')
- in_quote = !in_quote;
}

+ return length;
+}
+
+static char *next_arg(char *args, char **param, char **val)
+{
+ size_t len;
+
+ /* Chew leading spaces */
+ while (*args == ' ')
+ args++;
+
+ len = pull_token(args, " \t\n=");
*param = args;
- if (!equals)
+ args += len;
+
+ if (*args == '=') {
+ (*param)[len] = '\0';
+ args++;
+ len = pull_token(args, " \t\n");
+ *val = args;
+ args += len;
+ (*val)[len] = '\0';
+ } else {
+ (*param)[len] = '\0';
*val = NULL;
- else {
- args[equals] = '\0';
- *val = args + equals + 1;
-
- /* Don't include quotes in value. */
- if (**val == '"') {
- (*val)++;
- if (args[i-1] == '"')
- args[i-1] = '\0';
- }
- if (quoted && args[i-1] == '"')
- args[i-1] = '\0';
}

- if (args[i]) {
- args[i] = '\0';
- next = args + i + 1;
- } else
- next = args + i;
-
- /* Chew up trailing spaces. */
- while (*next == ' ')
- next++;
- return next;
+ return args + 1;
}

/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
@@ -137,10 +177,6 @@ int parse_args(const char *name,

DEBUGP("Parsing ARGS: %s\n", args);

- /* Chew leading spaces */
- while (*args == ' ')
- args++;
-
while (*args) {
int ret;
int irq_was_disabled;
--
1.6.3.3


--------------050008090408070104050009--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/