[libvirt] [PATCH 5/8] virsh: rework command parsing

2010-10-12 Thread Lai Jiangshan
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 la...@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 urihypervisor 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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 5/8] virsh: rework command parsing

2010-10-12 Thread Eric Blake

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]
+Bvirsh [IOPTION]... [ICOMMAND_STRING]
+
+Bvirsh [IOPTION]... ICOMMAND [IARG]...

 =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 Icommand is one of the commands listed below, Idomain-id
 is the numeric domain id, or the domain name (which will be internally
-translated to domain id), and IOPTIONS are command specific
+translated to domain id), and IARGS 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 Bvirsh 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 Bquit command will then 
exit

+The Bvirsh program can be used either to run one ICOMMAND by giving the
+command and its arguments on the shell command line, or a ICOMMAND_STRING
+which is a single shell argument consisting of multiple ICOMMAND actions
+and their arguments joined with whitespace, and separated by semicolons
+between commands.  Within ICOMMAND_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, Bvirsh will then start a 
minimal
+interpreter waiting for your commands, and the Bquit command will 
then exit

 the program.

 =head1 NOTES

--
Eric Blake   ebl...@redhat.com+1-801-349-2682
Libvirt virtualization library http://libvirt.org

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list