Re: [RFC] Re: Parsing kernel parameters and escaping "
From: Daniel Mierswa
Date: Mon Jul 06 2009 - 19:05:37 EST
Daniel Mierswa wrote:
> As stated in my last E-Mail in this thread there are currently some
> limitations when passing quotes to kernel parameters, I tried to remove
> some of those limitations. A git fp is attached.
>
> (from the commit message):
>> 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]
>
> Any suggestions welcome. Please be kind, as I'm not too familar with
> writing parsers, kernel development and what I may have broke. :-)
>
Great I forgot the patch, here it is now.
--
Mierswa, Daniel
If you still don't like it, that's ok: that's why I'm boss. I simply
know better than you do.
--- Linus Torvalds, comp.os.linux.advocacy, 1996/07/22
From 2dbc124b6c1674592ec5faaae5ca87fc7b16cc12 Mon Sep 17 00:00:00 2001
From: Daniel Mierswa <impulze@xxxxxxxxxxx>
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 | 135 ++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 93 insertions(+), 42 deletions(-)
diff --git a/kernel/params.c b/kernel/params.c
index de273ec..0a9fc14 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -75,58 +75,109 @@ 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;
+
+ 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;
+ int in_quotes, is_escaped;
+
+ *param = *val = NULL;
+ in_quotes = is_escaped = 0;
+
+ /* tokenizer */
+ for (token = args; *token; token++) {
+ /* parameter or value is finished */
+ if (!in_quotes && *token == ' ') {
+ *token = '\0';
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 (!is_escaped && *token == '\\') {
+ is_escaped = 1;
+ continue;
}
- if (quoted && args[i-1] == '"')
- args[i-1] = '\0';
+
+ 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);
+ }
+
+ /* remove trailing spaces */
+ while (*token == ' ') {
+ token++;
+ }
- /* Chew up trailing spaces. */
- while (*next == ' ')
- next++;
- return next;
+ return token + 1;
}
/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
--
1.6.3.3
Attachment:
signature.asc
Description: OpenPGP digital signature