[libvirt] [PATCH 5/8] virsh: rework command parsing
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@cn.fujitsu.com> --- 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; }
On 10/12/2010 01:14 AM, Lai Jiangshan wrote:
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
s/vrsh/vsh/
+++ 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;
If I was worried about memory, I'd consider making this a discriminated union; but we don't instantiate too many vshCommandParser objects to be worth worrying about the extra word of storage.
+/* --------------- * 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"
Hmm; we need a corresponding patch to virsh.pod. ACK. Here's what I'm squashing as part of rebasing (yes, I documented features that aren't in until later patches; oh well). And I'm posting a followup patch that documents virsh's options, like -c. diff --git i/tools/virsh.c w/tools/virsh.c index 901b953..688705d 100644 --- i/tools/virsh.c +++ w/tools/virsh.c @@ -10203,7 +10203,7 @@ static int vshCommandParse(vshControl *ctl, vshCommandParser *parser); * --------------- */ -static int +static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res) { if (parser->arg_pos == parser->arg_end) { diff --git i/tools/virsh.pod w/tools/virsh.pod index e0471b1..209aa54 100644 --- i/tools/virsh.pod +++ w/tools/virsh.pod @@ -4,7 +4,9 @@ virsh - management user interface =head1 SYNOPSIS -virsh <subcommand> [args] +B<virsh> [I<OPTION>]... [I<COMMAND_STRING>] + +B<virsh> [I<OPTION>]... I<COMMAND> [I<ARG>]... =head1 DESCRIPTION @@ -22,20 +24,25 @@ KVM, LXC, OpenVZ, VirtualBox, OpenNebula, and VMware ESX. The basic structure of most virsh usage is: - virsh <command> <domain-id> [OPTIONS] + virsh <command> <domain-id> [ARG]... Where I<command> is one of the commands listed below, I<domain-id> is the numeric domain id, or the domain name (which will be internally -translated to domain id), and I<OPTIONS> are command specific +translated to domain id), and I<ARGS> are command specific options. There are a few exceptions to this rule in the cases where the command in question acts on all domains, the entire machine, or directly on the xen hypervisor. Those exceptions will be clear for each of those commands. -The B<virsh> program can be used either to run one command at a time -by giving the command as an argument on the command line, or as a shell -if no command is given in the command line, it will then start a minimal -interpreter waiting for your commands and the B<quit> command will then exit +The B<virsh> program can be used either to run one I<COMMAND> by giving the +command and its arguments on the shell command line, or a I<COMMAND_STRING> +which is a single shell argument consisting of multiple I<COMMAND> actions +and their arguments joined with whitespace, and separated by semicolons +between commands. Within I<COMMAND_STRING>, virsh understands the +same single, double, and backslash escapes as the shell, although you must +add another layer of shell escaping in creating the single shell argument. +If no command is given in the command line, B<virsh> will then start a minimal +interpreter waiting for your commands, and the B<quit> command will then exit the program. =head1 NOTES -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
* tools/virsh.pod: Document top-level options. ---
And I'm posting a followup patch that documents virsh's options, like -c.
Can't believe we didn't have this in the man page! tools/virsh.pod | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 44 insertions(+), 1 deletions(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index 209aa54..f65f6d4 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -24,7 +24,7 @@ KVM, LXC, OpenVZ, VirtualBox, OpenNebula, and VMware ESX. The basic structure of most virsh usage is: - virsh <command> <domain-id> [ARG]... + virsh [OPTION]... <command> <domain-id> [ARG]... Where I<command> is one of the commands listed below, I<domain-id> is the numeric domain id, or the domain name (which will be internally @@ -45,6 +45,49 @@ If no command is given in the command line, B<virsh> will then start a minimal interpreter waiting for your commands, and the B<quit> command will then exit the program. +The B<virsh> program understands the following I<OPTIONS>. + +=over 4 + +=item B<-h>, B<--help> + +Ignore all other arguments, and behave as if the B<help> command were +given instead. + +=item B<-v>, B<--version> + +Ignore all other arguments, and behave as if the B<version> command were +given instead. + +=item B<-c>, B<--connect> I<URI> + +Connect to the specified I<URI>, as if by the B<connect> command, +instead of the default connection. + +=item B<-d>, B<--debug> I<LEVEL> + +Enable debug messages at integer I<LEVEL> and above. I<LEVEL> can +range from 0 (default) to 5. + +=item B<-l>, B<--log> I<FILE> + +Output logging details to I<FILE>. + +=item B<-q>, B<--quiet> + +Avoid extra informational messages. + +=item B<-r>, B<--readonly> + +Make the initial connection read-only, as if by the I<--readonly> +option of the B<connect> command. + +=item B<-t>, B<--timing> + +Output elapsed time information for each command. + +=back + =head1 NOTES Most B<virsh> operations rely upon the libvirt library being able to -- 1.7.2.3
On Tue, Oct 12, 2010 at 02:50:56PM -0600, Eric Blake wrote:
* tools/virsh.pod: Document top-level options. ---
And I'm posting a followup patch that documents virsh's options, like -c.
Can't believe we didn't have this in the man page!
tools/virsh.pod | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 44 insertions(+), 1 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod index 209aa54..f65f6d4 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -24,7 +24,7 @@ KVM, LXC, OpenVZ, VirtualBox, OpenNebula, and VMware ESX.
The basic structure of most virsh usage is:
- virsh <command> <domain-id> [ARG]... + virsh [OPTION]... <command> <domain-id> [ARG]...
Argh ! ACK :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (3)
-
Daniel Veillard -
Eric Blake -
Lai Jiangshan