>From 36d93d40b535ce7f1253d7740f214dc65b2975b9 Mon Sep 17 00:00:00 2001 From: Daniel Mierswa Date: Tue, 7 Jul 2009 00:54:38 +0200 Subject: [PATCH] Attempt to handle quotes in kernel parameters 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 --- kernel/params.c | 111 ++++++++++++++++++++++++++++++++---------------------- 1 files changed, 66 insertions(+), 45 deletions(-) diff --git a/kernel/params.c b/kernel/params.c index 7f6912c..5908623 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -72,58 +72,83 @@ 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" ] + */ +int printf(char const *,...); +static size_t pull_token(char *args, char const *delim) { - unsigned int i, equals = 0; - int in_quote = 0, quoted = 0; - char *next; - - if (*args == '"') { - args++; - in_quote = 1; - quoted = 1; - } + size_t i; + char *last_quote = NULL; for (i = 0; args[i]; i++) { - if (args[i] == ' ' && !in_quote) + if (args[i] == '"') { + if (last_quote) { + size_t remain_len = strlen(args + i + 1); + + /* remove both quotes by moving strings */ + memmove(last_quote, last_quote + 1, args + i - 1 - last_quote); + memmove(args + i - 1, args + i + 1, remain_len + 1); + + /* fill the blank we've left */ + args[i + remain_len] = '\0'; + + /* removed 2 quotes, decrease the iterator */ + i -= 2; + last_quote = NULL; + } else { + last_quote = args + i; + } + + continue; + } + + if (last_quote) { + /* escaped quote */ + if (args[i] == '\\' && args[i + 1] == '"') { + /* move all characters back */ + memmove(args + i, args + i + 1, strlen(args + i + 1) + 1); + } + + continue; + } + + if (strchr(delim, args[i])) { break; - if (equals == 0) { - if (args[i] == '=') - equals = i; } - if (args[i] == '"') - in_quote = !in_quote; } + return i; +} + +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 +162,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