In origin code, double quote is only allowed at the begin or end
"complicated argument"
--some_opt="complicated string" (we split this argument into 2 parts,
option and data, the data is "complicated string").
This patch makes it allow double quote at any position of
an argument:
complicated" argument"
complicated" "argument
--"some opt=complicated string"
This patch is also needed for the following patches,
the following patches will not split option argument into 2 parts,
so we have to allow double quote at any position of an argument.
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
diff --git a/tools/virsh.c b/tools/virsh.c
index 57ea618..7b6f2b6 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -10172,9 +10172,9 @@ static int
vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
{
int tk = VSH_TK_NONE;
- int quote = FALSE;
+ bool double_quote = false;
int sz = 0;
- char *p = str;
+ char *p = str, *q;
char *tkstr = NULL;
*end = NULL;
@@ -10188,9 +10188,13 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char
**res)
*end = ++p; /* = \0 or begin of next command */
return VSH_TK_END;
}
+
+ q = p;
+ *res = NULL;
+copy:
while (*p) {
/* end of token is blank space or ';' */
- if ((quote == FALSE && (*p == ' ' || *p == '\t')) || *p
== ';')
+ if (!double_quote && (*p == ' ' || *p == '\t' || *p ==
';'))
break;
/* end of option name could be '=' */
@@ -10206,23 +10210,22 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char
**res)
p += 2;
} else {
tk = VSH_TK_DATA;
- if (*p == '"') {
- quote = TRUE;
- p++;
- } else {
- quote = FALSE;
- }
}
tkstr = p; /* begin of token */
- } else if (quote && *p == '"') {
- quote = FALSE;
+ }
+
+ if (*p == '"') {
+ double_quote = !double_quote;
p++;
- break; /* end of "..." token */
+ continue;
}
+
+ if (*res)
+ (*res)[sz] = *p;
p++;
sz++;
}
- if (quote) {
+ if (double_quote) {
vshError(ctl, "%s", _("missing \""));
return VSH_TK_ERROR;
}
@@ -10231,8 +10234,12 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char
**res)
if (sz == 0)
return VSH_TK_END;
- *res = vshMalloc(ctl, sz + 1);
- memcpy(*res, tkstr, sz);
+ if (!*res) {
+ *res = vshMalloc(ctl, sz + 1);
+ sz = 0;
+ p = q;
+ goto copy;
+ }
*(*res + sz) = '\0';
*end = p;