From fe3bf00a0fc2db941fef41c44fc6d9eefad4d037 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] --- kernel/params.c | 146 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 104 insertions(+), 42 deletions(-) diff --git a/kernel/params.c b/kernel/params.c index de273ec..73de8f5 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -75,58 +75,120 @@ 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) +/* handle quotes in tokens (parameter and values) + * '" foo bar "' => ' foo bar ' + * '" foo \" "' => ' foo " ' + */ +static void add_token(char ** token, char * args) { - unsigned int i, equals = 0; - int in_quote = 0, quoted = 0; - char *next; + char * iterator, * last_quote; + int in_quotes; - if (*args == '"') { - args++; - in_quote = 1; - quoted = 1; + in_quotes = 0; + last_quote = NULL; + + for (iterator = args; *iterator; iterator++) { + if (*iterator == '\\' && *(iterator + 1) == '"') { + char * mover; + + /* move all characters back */ + for (mover = iterator; *mover; mover++) { + *mover = *(mover + 1); + } + + continue; + } + + if (*iterator != '"') { + continue; + } + + if (in_quotes) { + char * mover; + + /* move whole string back until current " is reached */ + for (mover = last_quote; mover != iterator - 1; mover++) { + *mover = *(mover + 1); + } + + /* ignore the current " and move the rest of the string back */ + while (*mover) { + *mover = *(mover + 2); + mover++; + } + + /* ignored 2 quotes, decrease the iterator */ + iterator -= 2; + last_quote = NULL; + } else { + last_quote = iterator; + } + + in_quotes = !in_quotes; } - for (i = 0; args[i]; i++) { - if (args[i] == ' ' && !in_quote) + *token = args; +} + +static char * next_arg(char * args, char ** param, char ** val) +{ + char * token, * next; + int in_quotes, is_escaped; + + *param = *val = next = NULL; + in_quotes = is_escaped = 0; + + /* tokenizer */ + for (token = args; *token; token++) { + /* parameter or value is finished */ + if (!in_quotes && *token == ' ') { + *token = '\0'; + + /* there're still characters in the parameter line */ + next = token + 1; + + /* remove trailing whitespace */ + while (*next == ' ') { + next++; + } + break; - if (equals == 0) { - if (args[i] == '=') - equals = i; } - if (args[i] == '"') - in_quote = !in_quote; - } - *param = args; - if (!equals) - *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'; + /* parameter/value split */ + if (!in_quotes && *token == '=' && !*param) { + *token = '\0'; + add_token(param, args); + args = token + 1; + continue; } - if (quoted && args[i-1] == '"') - args[i-1] = '\0'; + + if (!is_escaped && *token == '\\') { + is_escaped = 1; + continue; + } + + if (*token == '"' && !is_escaped) { + in_quotes = !in_quotes; + } + + /* always reset escape value, only " needs it */ + is_escaped = 0; } - if (args[i]) { - args[i] = '\0'; - next = args + i + 1; - } else - next = args + i; + if (!*param) { + add_token(param, args); + } else { + add_token(val, args); + } + + /* there're parameters left in the command line */ + if (next) { + return next; + } - /* Chew up trailing spaces. */ - while (*next == ' ') - next++; - return next; + /* end of the line */ + return token; } /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ -- 1.6.3.3