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

Lai Jiangshan laijs at cn.fujitsu.com
Tue Oct 12 07:14:01 UTC 2010


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 at 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;
 }




More information about the libvir-list mailing list