Reject passing an arg to an option that doesn't take one (bug 6915).
[rsync.git] / popt / popt.c
index 00a60270f3b13c509096a58b7d842cd45d58391e..ec6f3bd8be7420575eb713eeaf83b63ec7e26793 100644 (file)
@@ -392,7 +392,6 @@ static int execCommand(poptContext con)
     poptItem item = con->doExec;
     const char ** argv;
     int argc = 0;
-    int rc;
 
     if (item == NULL) /*XXX can't happen*/
        return POPT_ERROR_NOARG;
@@ -432,8 +431,9 @@ static int execCommand(poptContext con)
 
     argv[argc] = NULL;
 
+  {
 #ifdef __hpux
-    rc = setresgid(getgid(), getgid(),-1);
+    int rc = setresgid(getgid(), getgid(),-1);
     if (rc) return POPT_ERROR_ERRNO;
     rc = setresuid(getuid(), getuid(),-1);
     if (rc) return POPT_ERROR_ERRNO;
@@ -444,12 +444,12 @@ static int execCommand(poptContext con)
  * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
  */
 #if defined(HAVE_SETUID)
-    rc = setgid(getgid());
+    int rc = setgid(getgid());
     if (rc) return POPT_ERROR_ERRNO;
     rc = setuid(getuid());
     if (rc) return POPT_ERROR_ERRNO;
 #elif defined (HAVE_SETREUID)
-    rc = setregid(getgid(), getgid());
+    int rc = setregid(getgid(), getgid());
     if (rc) return POPT_ERROR_ERRNO;
     rc = setreuid(getuid(), getuid());
     if (rc) return POPT_ERROR_ERRNO;
@@ -457,6 +457,7 @@ static int execCommand(poptContext con)
     ; /* Can't drop privileges */
 #endif
 #endif
+  }
 
     if (argv[0] == NULL)
        return POPT_ERROR_NOARG;
@@ -471,7 +472,7 @@ if (_popt_debug)
     }
 #endif
 
-    rc = execvp(argv[0], (char *const *)argv);
+    execvp(argv[0], (char *const *)argv);
 
     return POPT_ERROR_ERRNO;
 }
@@ -808,16 +809,20 @@ int poptGetNextOpt(poptContext con)
                    *oe++ = '\0';
                    /* XXX longArg is mapped back to persistent storage. */
                    longArg = origOptString + (oe - localOptString);
-               }
+               } else
+                   oe = NULL;
 
                opt = findOption(con->options, optString, '\0', &cb, &cbData,
                                 singleDash);
                if (!opt && !singleDash)
                    return POPT_ERROR_BADOPT;
+               if (!opt && oe)
+                   oe[-1] = '='; /* restore overwritten '=' */
            }
 
            if (!opt) {
                con->os->nextCharArg = origOptString + 1;
+               longArg = NULL;
            } else {
                if (con->os == con->optionStack &&
                   opt->argInfo & POPT_ARGFLAG_STRIP)
@@ -860,15 +865,16 @@ int poptGetNextOpt(poptContext con)
        /*@=branchstate@*/
 
        if (opt == NULL) return POPT_ERROR_BADOPT;      /* XXX can't happen */
-       if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
-           if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
-               return POPT_ERROR_BADOPERATION;
-       } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
+       if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
+        || (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
+           if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
+               return POPT_ERROR_UNWANTEDARG;
            if (opt->arg) {
-               if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
+               long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
+               if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
                    return POPT_ERROR_BADOPERATION;
            }
-       } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
+       } else {
            con->os->nextArg = _free(con->os->nextArg);
            /*@-usedef@*/       /* FIX: W2DO? */
            if (longArg) {
@@ -876,7 +882,7 @@ int poptGetNextOpt(poptContext con)
                longArg = expandNextArg(con, longArg);
                con->os->nextArg = longArg;
            } else if (con->os->nextCharArg) {
-               longArg = expandNextArg(con, con->os->nextCharArg);
+               longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
                con->os->nextArg = longArg;
                con->os->nextCharArg = NULL;
            } else {
@@ -1197,6 +1203,8 @@ const char * poptStrerror(const int error)
     switch (error) {
       case POPT_ERROR_NOARG:
        return POPT_("missing argument");
+      case POPT_ERROR_UNWANTEDARG:
+       return POPT_("option does not take an argument");
       case POPT_ERROR_BADOPT:
        return POPT_("unknown option");
       case POPT_ERROR_BADOPERATION: