]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virsh: simplify top-level option parsing
authorEric Blake <eblake@redhat.com>
Tue, 12 Oct 2010 21:49:13 +0000 (15:49 -0600)
committerEric Blake <eblake@redhat.com>
Wed, 13 Oct 2010 13:52:33 +0000 (07:52 -0600)
This makes 'virsh --conn test:///default help help' work right;
previously, the abbreviation confused our hand-rolled option parsing.

* tools/virsh.c (vshParseArgv): Use getopt_long feature, rather
than (incorrectly) reparsing options ourselves.

tools/virsh.c

index bae647000a50c441c037c2e5bd4548532bde73a4..01694939042ba2b41797ac24e4fa5eb756c7a451 100644 (file)
@@ -11138,9 +11138,8 @@ vshUsage(void)
 static int
 vshParseArgv(vshControl *ctl, int argc, char **argv)
 {
-    char *last = NULL;
-    int i, end = 0, help = 0;
-    int arg, idx = 0;
+    bool help = false;
+    int arg;
     struct option opt[] = {
         {"debug", 1, 0, 'd'},
         {"help", 0, 0, 'h'},
@@ -11153,46 +11152,10 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
         {0, 0, 0, 0}
     };
 
-
-    if (argc < 2)
-        return TRUE;
-
-    /* look for begin of the command, for example:
-     *   ./virsh --debug 5 -q command --cmdoption
-     *                  <--- ^ --->
-     *        getopt() stuff | command suff
-     */
-    for (i = 1; i < argc; i++) {
-        if (*argv[i] != '-') {
-            int valid = FALSE;
-
-            /* non "--option" argv, is it command? */
-            if (last) {
-                struct option *o;
-                int sz = strlen(last);
-
-                for (o = opt; o->name; o++) {
-                    if (o->has_arg == 1){
-                        if (sz == 2 && *(last + 1) == o->val)
-                            /* valid virsh short option */
-                            valid = TRUE;
-                        else if (sz > 2 && STREQ(o->name, last + 2))
-                            /* valid virsh long option */
-                            valid = TRUE;
-                    }
-                }
-            }
-            if (!valid) {
-                end = i;
-                break;
-            }
-        }
-        last = argv[i];
-    }
-    end = end ? end : argc;
-
-    /* standard (non-command) options */
-    while ((arg = getopt_long(end, argv, "d:hqtc:vrl:", opt, &idx)) != -1) {
+    /* Standard (non-command) options. The leading + ensures that no
+     * argument reordering takes place, so that command options are
+     * not confused with top-level virsh options. */
+    while ((arg = getopt_long(argc, argv, "+d:hqtc:vrl:", opt, NULL)) != -1) {
         switch (arg) {
         case 'd':
             if (virStrToLong_i(optarg, NULL, 10, &ctl->debug) < 0) {
@@ -11201,7 +11164,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
             }
             break;
         case 'h':
-            help = 1;
+            help = true;
             break;
         case 'q':
             ctl->quiet = TRUE;
@@ -11213,7 +11176,8 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
             ctl->name = vshStrdup(ctl, optarg);
             break;
         case 'v':
-            fprintf(stdout, "%s\n", VERSION);
+            /* FIXME - list a copyright blurb, as in GNU programs?  */
+            puts(VERSION);
             exit(EXIT_SUCCESS);
         case 'r':
             ctl->readonly = TRUE;
@@ -11228,8 +11192,8 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
     }
 
     if (help) {
-        if (end < argc) {
-            vshError(ctl, _("extra argument '%s'. See --help."), argv[end]);
+        if (optind < argc) {
+            vshError(ctl, _("extra argument '%s'. See --help."), argv[optind]);
             exit(EXIT_FAILURE);
         }
 
@@ -11238,14 +11202,14 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
         exit(EXIT_SUCCESS);
     }
 
-    if (argc > end) {
+    if (argc > optind) {
         /* parse command */
         ctl->imode = FALSE;
-        if (argc - end == 1) {
-            vshDebug(ctl, 2, "commands: \"%s\"\n", argv[end]);
-            return vshCommandStringParse(ctl, argv[end]);
+        if (argc - optind == 1) {
+            vshDebug(ctl, 2, "commands: \"%s\"\n", argv[optind]);
+            return vshCommandStringParse(ctl, argv[optind]);
         } else {
-            return vshCommandArgvParse(ctl, argc - end, argv + end);
+            return vshCommandArgvParse(ctl, argc - optind, argv + optind);
         }
     }
     return TRUE;