Old virsh command parsing mashes all the args back into a string and miss the quotes, this patches fix it. It is also needed for introducing qemu-monitor-command which is very useful. This patches uses the new vrshCommandParser abstraction and adds vshCommandArgvParse() for arguments vector, so we don't need to mash arguments vector into a command sting. And the usage was changed: old: virsh [options] [commands] new: virsh [options]... [<command_string>] virsh [options]... <command> [args...] So we still support commands like: # virsh "define D.xml; dumpxml D" "define D.xml; dumpxml D" was parsed as a commands-string. and support commands like: # virsh qemu-monitor-command f13guest "info cpus" we will not mash them into a string, we use new argv parser for it. But we don't support the command like: # virsh "define D.xml; dumpxml" D "define D.xml; dumpxml" was parsed as a command-name, but we have no such command-name. Signed-off-by: Lai Jiangshan <laijs@xxxxxxxxxxxxxx> --- virsh.c | 63 +++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 27321a5..9fd0602 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -10165,12 +10165,47 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd) typedef struct __vshCommandParser { int (*getNextArg)(vshControl *, struct __vshCommandParser *, char **); + /* vshCommandStringGetArg() */ char *pos; + /* vshCommandArgvGetArg() */ + char **arg_pos; + char **arg_end; } vshCommandParser; static int vshCommandParse(vshControl *ctl, vshCommandParser *parser); /* --------------- + * Command argv parsing + * --------------- + */ + +static int +vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res) +{ + if (parser->arg_pos == parser->arg_end) { + *res = NULL; + return VSH_TK_END; + } + + *res = vshStrdup(ctl, *parser->arg_pos); + parser->arg_pos++; + return VSH_TK_ARG; +} + +static int vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) +{ + vshCommandParser parser; + + if (nargs <= 0) + return FALSE; + + parser.arg_pos = argv; + parser.arg_end = argv + nargs; + parser.getNextArg = vshCommandArgvGetArg; + return vshCommandParse(ctl, &parser); +} + +/* --------------- * Command string parsing * --------------- */ @@ -10939,7 +10974,8 @@ static void vshUsage(void) { const vshCmdDef *cmd; - fprintf(stdout, _("\n%s [options] [commands]\n\n" + fprintf(stdout, _("\n%s [options]... [<command_string>]" + "\n%s [options]... <command> [args...]\n\n" " options:\n" " -c | --connect <uri> hypervisor connection URI\n" " -r | --readonly connect readonly\n" @@ -10949,7 +10985,7 @@ vshUsage(void) " -t | --timing print timing information\n" " -l | --log <file> output logging to file\n" " -v | --version program version\n\n" - " commands (non interactive mode):\n"), progname); + " commands (non interactive mode):\n"), progname, progname); for (cmd = commands; cmd->name; cmd++) fprintf(stdout, @@ -11069,26 +11105,13 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) if (argc > end) { /* parse command */ - char *cmdstr; - int sz = 0, ret; - ctl->imode = FALSE; - - for (i = end; i < argc; i++) - sz += strlen(argv[i]) + 1; /* +1 is for blank space between items */ - - cmdstr = vshCalloc(ctl, sz + 1, 1); - - for (i = end; i < argc; i++) { - strncat(cmdstr, argv[i], sz); - sz -= strlen(argv[i]); - strncat(cmdstr, " ", sz--); + if (argc - end == 1) { + vshDebug(ctl, 2, "commands: \"%s\"\n", argv[end]); + return vshCommandStringParse(ctl, argv[end]); + } else { + return vshCommandArgvParse(ctl, argc - end, argv + end); } - vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr); - ret = vshCommandStringParse(ctl, cmdstr); - - VIR_FREE(cmdstr); - return ret; } return TRUE; } -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list