From: Daniel Mierswa <impulze@impulze.org>
To: Rusty Russell <rusty@rustcorp.com.au>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [RFC] Re: Parsing kernel parameters and escaping "
Date: Sun, 12 Jul 2009 19:59:39 +0200 [thread overview]
Message-ID: <4A5A248B.1070606@impulze.org> (raw)
In-Reply-To: <200907121911.58333.rusty@rustcorp.com.au>
[-- Attachment #1: Type: text/plain, Size: 1918 bytes --]
Rusty Russell wrote:
> Yes, we've never had the ability to escape quotes (and you're the first to
> ask), so when I wrote this code I kept it simple. You can have spaced out
> values, but you need to quote the whole thing "param=some value with spaces".
True, but that would leave quotes where they are instead of removing them.
> We have to be careful not to break existing cmdlines tho: I don't know
> if anyone uses \ currently, but simply interpreting \" is probably safe.
Yes, the only way that compatibility seems to break is that now \" in a quoted
string is replaced by a single ".
> add_token is a weird name for this. It actually mangles the argument, and it
> really should return the char *.
Fixed.
> How about something like:
> static unsigned int pull_token(char *args, const char *delim)
Fixed.
> Which unescapes and returns the length of the token, or zero if it simply
> swallowed delimeters? Assuming it always nul terminates, then the caller can
> simply do:
> [...]
Fixed.
> Important cases to test are:
> x param = "x", val = NULL
> x= param = "x", val = ""
> x=y=1 param = "x", val = "y=1"
>
> Plus all variations where x and y contain quotes.
Tested:
|param| => [param[(none)]]
|param=| => [param[]]
|param=value| => [param[value]]
|param=value=withequal | => [param[value=withequal]]
|param="value with spaces" | => [param[value with spaces]]
|param="value with spaces and quotes \"" | => [param[value with spaces and quotes "]]
|param=\"foo\" | => [param[\"foo" ]]
|"param = value" | => [param = value[(none)]]
> Cheers,
> Rusty.
Thanks for your kind feedback, I'm willing to put more effort into this when needed. I really
first wanted to check if patches for this are welcomed.
--
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
[-- Attachment #2: kernel2.patch --]
[-- Type: text/plain, Size: 4158 bytes --]
>From 21402346a295eb539a111b777ee54f3dd5263b6f Mon Sep 17 00:00:00 2001
From: Daniel Mierswa <impulze@impulze.org>
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 <impulze@impulze.org>
---
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
next prev parent reply other threads:[~2009-07-12 17:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-05 13:54 Parsing kernel parameters and escaping " Daniel Mierswa
2009-07-06 23:03 ` [RFC] " Daniel Mierswa
2009-07-06 23:05 ` Daniel Mierswa
2009-07-07 0:54 ` Daniel Mierswa
2009-07-12 9:41 ` Rusty Russell
2009-07-12 17:59 ` Daniel Mierswa [this message]
2009-07-12 23:57 ` Rusty Russell
2009-07-13 2:49 ` Daniel Mierswa
2009-07-14 2:49 ` Rusty Russell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A5A248B.1070606@impulze.org \
--to=impulze@impulze.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rusty@rustcorp.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox