LCOV - code coverage report
Current view: top level - third_party/popt - popt.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 359 976 36.8 %
Date: 2024-05-31 13:13:24 Functions: 21 47 44.7 %

          Line data    Source code
       1             : /** \ingroup popt
       2             :  * \file popt/popt.c
       3             :  */
       4             : 
       5             : /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
       6             :    file accompanying popt source distributions, available from
       7             :    ftp://ftp.rpm.org/pub/rpm/dist */
       8             : 
       9             : #undef  MYDEBUG
      10             : 
      11             : #include "system.h"
      12             : 
      13             : #if defined(__LCLINT__)
      14             : /*@-declundef -exportheader @*/
      15             : extern long long int strtoll(const char *nptr, /*@null@*/ char **endptr,
      16             :                 int base)
      17             :         /*@modifies *endptr@*/;
      18             : /*@=declundef =exportheader @*/
      19             : #endif
      20             : 
      21             : #ifdef HAVE_FLOAT_H
      22             : #include <float.h>
      23             : #endif
      24             : #include <math.h>
      25             : 
      26             : #include "poptint.h"
      27             : 
      28             : #ifdef  MYDEBUG
      29             : /*@unchecked@*/
      30             : int _popt_debug = 0;
      31             : #endif
      32             : 
      33             : /*@unchecked@*/
      34             : unsigned int _poptArgMask = POPT_ARG_MASK;
      35             : /*@unchecked@*/
      36             : unsigned int _poptGroupMask = POPT_GROUP_MASK;
      37             : 
      38             : #if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
      39             : static char * strerror(int errno)
      40             : {
      41             :     extern int sys_nerr;
      42             :     extern char * sys_errlist[];
      43             : 
      44             :     if ((0 <= errno) && (errno < sys_nerr))
      45             :         return sys_errlist[errno];
      46             :     else
      47             :         return POPT_("unknown errno");
      48             : }
      49             : #endif
      50             : 
      51             : #ifdef MYDEBUG
      52             : /*@unused@*/
      53             : static void prtcon(const char *msg, poptContext con)
      54             : {
      55             :     if (msg) fprintf(stderr, "%s", msg);
      56             :     fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
      57             :         con, con->os,
      58             :         (con->os->nextCharArg ? con->os->nextCharArg : ""),
      59             :         (con->os->nextArg ? con->os->nextArg : ""),
      60             :         con->os->next,
      61             :         (con->os->argv && con->os->argv[con->os->next]
      62             :                 ? con->os->argv[con->os->next] : ""));
      63             : }
      64             : #endif
      65             : 
      66           0 : void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
      67             : {
      68           0 :     con->execPath = _free(con->execPath);
      69           0 :     con->execPath = xstrdup(path);
      70           0 :     con->execAbsolute = allowAbsolute;
      71           0 :     return;
      72             : }
      73             : 
      74         178 : static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
      75             :         /*@globals internalState@*/
      76             :         /*@modifies internalState@*/
      77             : {
      78         178 :     if (opt != NULL)
      79        2000 :     for (; opt->longName || opt->shortName || opt->arg; opt++) {
      80        1822 :         poptArg arg = { .ptr = opt->arg };
      81        1822 :         if (arg.ptr)
      82         953 :         switch (poptArgType(opt)) {
      83         141 :         case POPT_ARG_INCLUDE_TABLE:    /* Recurse on included sub-tables. */
      84         141 :             poptSubstituteHelpI18N(arg.opt);    /* XXX side effects */
      85         141 :             invokeCallbacksPRE(con, arg.opt);
      86         141 :             /*@switchbreak@*/ break;
      87         141 :         case POPT_ARG_CALLBACK:         /* Perform callback. */
      88         141 :             if (!CBF_ISSET(opt, PRE))
      89          74 :                 /*@switchbreak@*/ break;
      90             : /*@-noeffectuncon @*/   /* XXX no known way to annotate (*vector) calls. */
      91          67 :             arg.cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
      92             : /*@=noeffectuncon @*/
      93          67 :             /*@switchbreak@*/ break;
      94             :         }
      95             :     }
      96         178 : }
      97             : 
      98         178 : static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
      99             :         /*@globals internalState@*/
     100             :         /*@modifies internalState@*/
     101             : {
     102         178 :     if (opt != NULL)
     103        2000 :     for (; opt->longName || opt->shortName || opt->arg; opt++) {
     104        1822 :         poptArg arg = { .ptr = opt->arg };
     105        1822 :         if (arg.ptr)
     106         953 :         switch (poptArgType(opt)) {
     107         141 :         case POPT_ARG_INCLUDE_TABLE:    /* Recurse on included sub-tables. */
     108         141 :             poptSubstituteHelpI18N(arg.opt);    /* XXX side effects */
     109         141 :             invokeCallbacksPOST(con, arg.opt);
     110         141 :             /*@switchbreak@*/ break;
     111         141 :         case POPT_ARG_CALLBACK:         /* Perform callback. */
     112         141 :             if (!CBF_ISSET(opt, POST))
     113          95 :                 /*@switchbreak@*/ break;
     114             : /*@-noeffectuncon @*/   /* XXX no known way to annotate (*vector) calls. */
     115          46 :             arg.cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
     116             : /*@=noeffectuncon @*/
     117          46 :             /*@switchbreak@*/ break;
     118             :         }
     119             :     }
     120         178 : }
     121             : 
     122         240 : static void invokeCallbacksOPTION(poptContext con,
     123             :                                 const struct poptOption * opt,
     124             :                                 const struct poptOption * myOpt,
     125             :                                 /*@null@*/ const void * myData, int shorty)
     126             :         /*@globals internalState@*/
     127             :         /*@modifies internalState@*/
     128             : {
     129         240 :     const struct poptOption * cbopt = NULL;
     130         240 :     poptArg cbarg = { .ptr = NULL };
     131             : 
     132         240 :     if (opt != NULL)
     133        1896 :     for (; opt->longName || opt->shortName || opt->arg; opt++) {
     134        1702 :         poptArg arg = { .ptr = opt->arg };
     135        1702 :         switch (poptArgType(opt)) {
     136         194 :         case POPT_ARG_INCLUDE_TABLE:    /* Recurse on included sub-tables. */
     137         194 :             poptSubstituteHelpI18N(arg.opt);    /* XXX side effects */
     138         194 :             if (opt->arg != NULL)
     139         194 :                 invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
     140         194 :             /*@switchbreak@*/ break;
     141         194 :         case POPT_ARG_CALLBACK:         /* Save callback info. */
     142         194 :             if (CBF_ISSET(opt, SKIPOPTION))
     143           0 :                 /*@switchbreak@*/ break;
     144         194 :             cbopt = opt;
     145         194 :             cbarg.ptr = opt->arg;
     146         194 :             /*@switchbreak@*/ break;
     147        1314 :         default:                /* Perform callback on matching option. */
     148        1314 :             if (cbopt == NULL || cbarg.cb == NULL)
     149             :                 /*@switchbreak@*/ break;
     150         685 :             if ((myOpt->shortName && opt->shortName && shorty &&
     151          72 :                         myOpt->shortName == opt->shortName)
     152         677 :              || (myOpt->longName != NULL && opt->longName != NULL &&
     153         677 :                         !strcmp(myOpt->longName, opt->longName)))
     154          46 :             {   const void *cbData = (cbopt->descrip ? cbopt->descrip : myData);
     155             : /*@-noeffectuncon @*/   /* XXX no known way to annotate (*vector) calls. */
     156          46 :                 cbarg.cb(con, POPT_CALLBACK_REASON_OPTION,
     157          46 :                         myOpt, con->os->nextArg, cbData);
     158             : /*@=noeffectuncon @*/
     159             :                 /* Terminate (unless explcitly continuing). */
     160          46 :                 if (!CBF_ISSET(cbopt, CONTINUE))
     161          46 :                     return;
     162             :             }
     163         639 :             /*@switchbreak@*/ break;
     164             :         }
     165             :     }
     166             : }
     167             : 
     168          37 : poptContext poptGetContext(const char * name, int argc, const char ** argv,
     169             :                         const struct poptOption * options, unsigned int flags)
     170             : {
     171          37 :     poptContext con = malloc(sizeof(*con));
     172             : 
     173          37 :     if (con == NULL) return NULL;       /* XXX can't happen */
     174          37 :     memset(con, 0, sizeof(*con));
     175             : 
     176          37 :     con->os = con->optionStack;
     177          37 :     con->os->argc = argc;
     178             : /*@-dependenttrans -assignexpose@*/     /* FIX: W2DO? */
     179          37 :     con->os->argv = argv;
     180             : /*@=dependenttrans =assignexpose@*/
     181          37 :     con->os->argb = NULL;
     182             : 
     183          37 :     if (!(flags & POPT_CONTEXT_KEEP_FIRST))
     184          17 :         con->os->next = 1;                /* skip argv[0] */
     185             : 
     186          37 :     con->leftovers = calloc( (size_t)(argc + 1), sizeof(*con->leftovers) );
     187             : /*@-dependenttrans -assignexpose@*/     /* FIX: W2DO? */
     188          37 :     con->options = options;
     189             : /*@=dependenttrans =assignexpose@*/
     190          37 :     con->aliases = NULL;
     191          37 :     con->numAliases = 0;
     192          37 :     con->flags = flags;
     193          37 :     con->execs = NULL;
     194          37 :     con->numExecs = 0;
     195          37 :     con->finalArgvAlloced = argc * 2;
     196          37 :     con->finalArgv = calloc( (size_t)con->finalArgvAlloced, sizeof(*con->finalArgv) );
     197          37 :     con->execAbsolute = 1;
     198          37 :     con->arg_strip = NULL;
     199             : 
     200          37 :     if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
     201           0 :         con->flags |= POPT_CONTEXT_POSIXMEHARDER;
     202             : 
     203          37 :     if (name)
     204          35 :         con->appName = xstrdup(name);
     205             : 
     206          37 :     invokeCallbacksPRE(con, con->options);
     207             : 
     208          37 :     return con;
     209             : }
     210             : 
     211           0 : static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
     212             :         /*@uses os @*/
     213             :         /*@releases os->nextArg, os->argv, os->argb @*/
     214             :         /*@modifies os @*/
     215             : {
     216           0 :     os->nextArg = _free(os->nextArg);
     217           0 :     os->argv = _free(os->argv);
     218           0 :     os->argb = PBM_FREE(os->argb);
     219           0 : }
     220             : 
     221          37 : void poptResetContext(poptContext con)
     222             : {
     223             :     int i;
     224             : 
     225          37 :     if (con == NULL) return;
     226          37 :     while (con->os > con->optionStack) {
     227           0 :         cleanOSE(con->os--);
     228             :     }
     229          37 :     con->os->argb = PBM_FREE(con->os->argb);
     230          37 :     con->os->currAlias = NULL;
     231          37 :     con->os->nextCharArg = NULL;
     232          37 :     con->os->nextArg = NULL;
     233          37 :     con->os->next = 1;                    /* skip argv[0] */
     234             : 
     235          37 :     con->numLeftovers = 0;
     236          37 :     con->nextLeftover = 0;
     237          37 :     con->restLeftover = 0;
     238          37 :     con->doExec = NULL;
     239             : 
     240          37 :     if (con->finalArgv != NULL)
     241         162 :     for (i = 0; i < con->finalArgvCount; i++) {
     242             : /*@-unqualifiedtrans@*/         /* FIX: typedef double indirection. */
     243         125 :         con->finalArgv[i] = _free(con->finalArgv[i]);
     244             : /*@=unqualifiedtrans@*/
     245             :     }
     246             : 
     247          37 :     con->finalArgvCount = 0;
     248          37 :     con->arg_strip = PBM_FREE(con->arg_strip);
     249             : /*@-nullstate@*/        /* FIX: con->finalArgv != NULL */
     250          37 :     return;
     251             : /*@=nullstate@*/
     252             : }
     253             : 
     254             : /* Only one of longName, shortName should be set, not both. */
     255          98 : static int handleExec(/*@special@*/ poptContext con,
     256             :                 /*@null@*/ const char * longName, char shortName)
     257             :         /*@uses con->execs, con->numExecs, con->flags, con->doExec,
     258             :                 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
     259             :         /*@modifies con @*/
     260             : {
     261             :     poptItem item;
     262             :     int i;
     263             : 
     264          98 :     if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */
     265          98 :         return 0;
     266             : 
     267           0 :     for (i = con->numExecs - 1; i >= 0; i--) {
     268           0 :         item = con->execs + i;
     269           0 :         if (longName && !(item->option.longName &&
     270           0 :                         !strcmp(longName, item->option.longName)))
     271           0 :             continue;
     272           0 :         else if (shortName != item->option.shortName)
     273           0 :             continue;
     274           0 :         break;
     275             :     }
     276           0 :     if (i < 0) return 0;
     277             : 
     278             : 
     279           0 :     if (con->flags & POPT_CONTEXT_NO_EXEC)
     280           0 :         return 1;
     281             : 
     282           0 :     if (con->doExec == NULL) {
     283           0 :         con->doExec = con->execs + i;
     284           0 :         return 1;
     285             :     }
     286             : 
     287             :     /* We already have an exec to do; remember this option for next
     288             :        time 'round */
     289           0 :     if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
     290           0 :         con->finalArgvAlloced += 10;
     291           0 :         con->finalArgv = realloc(con->finalArgv,
     292           0 :                         sizeof(*con->finalArgv) * con->finalArgvAlloced);
     293             :     }
     294             : 
     295           0 :     i = con->finalArgvCount++;
     296           0 :     if (con->finalArgv != NULL)      /* XXX can't happen */
     297           0 :     {   char *s  = malloc((longName ? strlen(longName) : 0) + sizeof("--"));
     298           0 :         if (s != NULL) {        /* XXX can't happen */
     299           0 :             con->finalArgv[i] = s;
     300           0 :             *s++ = '-';
     301           0 :             if (longName)
     302           0 :                 s = stpcpy( stpcpy(s, "-"), longName);
     303             :             else
     304           0 :                 *s++ = shortName;
     305           0 :             *s = '\0';
     306             :         } else
     307           0 :             con->finalArgv[i] = NULL;
     308             :     }
     309             : 
     310           0 :     return 1;
     311             : }
     312             : 
     313             : /**
     314             :  * Compare long option for equality, adjusting for POPT_ARGFLAG_TOGGLE.
     315             :  * @param opt           option
     316             :  * @param longName      arg option
     317             :  * @param longNameLen   arg option length
     318             :  * @return              does long option match?
     319             :  */
     320             : static int
     321        1041 : longOptionStrcmp(const struct poptOption * opt,
     322             :                 /*@null@*/ const char * longName, size_t longNameLen)
     323             :         /*@*/
     324             : {
     325        1041 :     const char * optLongName = opt->longName;
     326             :     int rc;
     327             : 
     328        1041 :     if (optLongName == NULL || longName == NULL)        /* XXX can't heppen */
     329           0 :         return 0;
     330             : 
     331        1041 :     if (F_ISSET(opt, TOGGLE)) {
     332           0 :         if (optLongName[0] == 'n' && optLongName[1] == 'o') {
     333           0 :             optLongName += sizeof("no") - 1;
     334           0 :             if (optLongName[0] == '-')
     335           0 :                 optLongName++;
     336             :         }
     337           0 :         if (longName[0] == 'n' && longName[1] == 'o') {
     338           0 :             longName += sizeof("no") - 1;
     339           0 :             longNameLen -= sizeof("no") - 1;
     340           0 :             if (longName[0] == '-') {
     341           0 :                 longName++;
     342           0 :                 longNameLen--;
     343             :             }
     344             :         }
     345             :     }
     346        1041 :     rc = (int)(strlen(optLongName) == longNameLen);
     347        1041 :     if (rc)
     348         121 :         rc = (int)(strncmp(optLongName, longName, longNameLen) == 0);
     349        1041 :     return rc;
     350             : }
     351             : 
     352             : /* Only one of longName, shortName may be set at a time */
     353          98 : static int handleAlias(/*@special@*/ poptContext con,
     354             :                 /*@null@*/ const char * longName, size_t longNameLen,
     355             :                 char shortName,
     356             :                 /*@exposed@*/ /*@null@*/ const char * nextArg)
     357             :         /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
     358             :                 con->os->currAlias, con->os->currAlias->option.longName @*/
     359             :         /*@modifies con @*/
     360             : {
     361          98 :     poptItem item = con->os->currAlias;
     362             :     int rc;
     363             :     int i;
     364             : 
     365          98 :     if (item) {
     366           0 :         if (longName && item->option.longName != NULL
     367           0 :          && longOptionStrcmp(&item->option, longName, longNameLen))
     368           0 :             return 0;
     369             :         else
     370           0 :         if (shortName && shortName == item->option.shortName)
     371           0 :             return 0;
     372             :     }
     373             : 
     374          98 :     if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */
     375          98 :         return 0;
     376             : 
     377           0 :     for (i = con->numAliases - 1; i >= 0; i--) {
     378           0 :         item = con->aliases + i;
     379           0 :         if (longName) {
     380           0 :             if (item->option.longName == NULL)
     381           0 :                 continue;
     382           0 :             if (!longOptionStrcmp(&item->option, longName, longNameLen))
     383           0 :                 continue;
     384           0 :         } else if (shortName != item->option.shortName)
     385           0 :             continue;
     386           0 :         break;
     387             :     }
     388           0 :     if (i < 0) return 0;
     389             : 
     390           0 :     if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
     391           0 :         return POPT_ERROR_OPTSTOODEEP;
     392             : 
     393           0 :     if (longName == NULL && nextArg != NULL && *nextArg != '\0')
     394           0 :         con->os->nextCharArg = nextArg;
     395             : 
     396           0 :     con->os++;
     397           0 :     con->os->next = 0;
     398           0 :     con->os->stuffed = 0;
     399           0 :     con->os->nextArg = NULL;
     400           0 :     con->os->nextCharArg = NULL;
     401           0 :     con->os->currAlias = con->aliases + i;
     402             :     {   const char ** av;
     403           0 :         int ac = con->os->currAlias->argc;
     404             :         /* Append --foo=bar arg to alias argv array (if present). */
     405           0 :         if (longName && nextArg != NULL && *nextArg != '\0') {
     406           0 :             av = malloc((ac + 1 + 1) * sizeof(*av));
     407           0 :             if (av != NULL) {   /* XXX won't happen. */
     408           0 :                 for (i = 0; i < ac; i++) {
     409           0 :                     av[i] = con->os->currAlias->argv[i];
     410             :                 }
     411           0 :                 av[ac++] = nextArg;
     412           0 :                 av[ac] = NULL;
     413             :             } else      /* XXX revert to old popt behavior if malloc fails. */
     414           0 :                 av = con->os->currAlias->argv;
     415             :         } else
     416           0 :             av = con->os->currAlias->argv;
     417           0 :         rc = poptDupArgv(ac, av, &con->os->argc, &con->os->argv);
     418           0 :         if (av != NULL && av != con->os->currAlias->argv)
     419           0 :             free(av);
     420             :     }
     421           0 :     con->os->argb = NULL;
     422             : 
     423           0 :     return (rc ? rc : 1);
     424             : }
     425             : 
     426             : /**
     427             :  * Return absolute path to executable by searching PATH.
     428             :  * @param argv0         name of executable
     429             :  * @return              (malloc'd) absolute path to executable (or NULL)
     430             :  */
     431             : static /*@null@*/
     432           0 : const char * findProgramPath(/*@null@*/ const char * argv0)
     433             :         /*@*/
     434             : {
     435           0 :     char *path = NULL, *s = NULL, *se;
     436           0 :     char *t = NULL;
     437             : 
     438           0 :     if (argv0 == NULL) return NULL;     /* XXX can't happen */
     439             : 
     440             :     /* If there is a / in argv[0], it has to be an absolute path. */
     441             :     /* XXX Hmmm, why not if (argv0[0] == '/') ... instead? */
     442           0 :     if (strchr(argv0, '/'))
     443           0 :         return xstrdup(argv0);
     444             : 
     445           0 :     if ((path = getenv("PATH")) == NULL || (path = xstrdup(path)) == NULL)
     446           0 :         return NULL;
     447             : 
     448             :     /* The return buffer in t is big enough for any path. */
     449           0 :     if ((t = malloc(strlen(path) + strlen(argv0) + sizeof("/"))) != NULL)
     450           0 :     for (s = path; s && *s; s = se) {
     451             : 
     452             :         /* Snip PATH element into [s,se). */
     453           0 :         if ((se = strchr(s, ':')))
     454           0 :             *se++ = '\0';
     455             : 
     456             :         /* Append argv0 to PATH element. */
     457           0 :         (void) stpcpy(stpcpy(stpcpy(t, s), "/"), argv0);
     458             : 
     459             :         /* If file is executable, bingo! */
     460           0 :         if (!access(t, X_OK))
     461           0 :             break;
     462             :     }
     463             : 
     464             :     /* If no executable was found in PATH, return NULL. */
     465             : /*@-compdef@*/
     466           0 :     if (!(s && *s) && t != NULL)
     467           0 :         t = _free(t);
     468             : /*@=compdef@*/
     469             : /*@-modobserver -observertrans -usedef @*/
     470           0 :     path = _free(path);
     471             : /*@=modobserver =observertrans =usedef @*/
     472             : 
     473           0 :     return t;
     474             : }
     475             : 
     476           0 : static int execCommand(poptContext con)
     477             :         /*@globals internalState @*/
     478             :         /*@modifies internalState @*/
     479             : {
     480           0 :     poptItem item = con->doExec;
     481           0 :     poptArgv argv = NULL;
     482           0 :     int argc = 0;
     483             :     int rc;
     484           0 :     int ec = POPT_ERROR_ERRNO;
     485             : 
     486           0 :     if (item == NULL) /*XXX can't happen*/
     487           0 :         return POPT_ERROR_NOARG;
     488             : 
     489           0 :     if (item->argv == NULL || item->argc < 1 ||
     490           0 :         (!con->execAbsolute && strchr(item->argv[0], '/')))
     491           0 :             return POPT_ERROR_NOARG;
     492             : 
     493           0 :     argv = malloc(sizeof(*argv) *
     494           0 :                         (6 + item->argc + con->numLeftovers + con->finalArgvCount));
     495           0 :     if (argv == NULL) return POPT_ERROR_MALLOC;
     496             : 
     497           0 :     if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
     498           0 :         char *s = malloc(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
     499           0 :         if (s)
     500           0 :             (void)stpcpy(stpcpy(stpcpy(s, con->execPath), "/"), item->argv[0]);
     501             : 
     502           0 :         argv[argc] = s;
     503             :     } else
     504           0 :         argv[argc] = findProgramPath(item->argv[0]);
     505           0 :     if (argv[argc++] == NULL) {
     506           0 :         ec = POPT_ERROR_NOARG;
     507           0 :         goto exit;
     508             :     }
     509             : 
     510           0 :     if (item->argc > 1) {
     511           0 :         memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
     512           0 :         argc += (item->argc - 1);
     513             :     }
     514             : 
     515           0 :     if (con->finalArgv != NULL && con->finalArgvCount > 0) {
     516           0 :         memcpy(argv + argc, con->finalArgv,
     517           0 :                 sizeof(*argv) * con->finalArgvCount);
     518           0 :         argc += con->finalArgvCount;
     519             :     }
     520             : 
     521           0 :     if (con->leftovers != NULL && con->numLeftovers > 0) {
     522           0 :         memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
     523           0 :         argc += con->numLeftovers;
     524             :     }
     525             : 
     526           0 :     argv[argc] = NULL;
     527             : 
     528             : #if defined(hpux) || defined(__hpux)
     529             :     rc = setresgid(getgid(), getgid(),-1);
     530             :     if (rc) goto exit;
     531             :     rc = setresuid(getuid(), getuid(),-1);
     532             :     if (rc) goto exit;
     533             : #else
     534             : /*
     535             :  * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
     536             :  * XXX  sez' Timur Bakeyev <mc@bat.ru>
     537             :  * XXX  from Norbert Warmuth <nwarmuth@privat.circular.de>
     538             :  */
     539             : #if defined(HAVE_SETUID)
     540           0 :     rc = setgid(getgid());
     541           0 :     if (rc) goto exit;
     542           0 :     rc = setuid(getuid());
     543           0 :     if (rc) goto exit;
     544             : #elif defined (HAVE_SETREUID)
     545             :     rc = setregid(getgid(), getgid());
     546             :     if (rc) goto exit;
     547             :     rc = setreuid(getuid(), getuid());
     548             :     if (rc) goto exit;
     549             : #else
     550             :     ; /* Can't drop privileges */
     551             : #endif
     552             : #endif
     553             : 
     554             : #ifdef  MYDEBUG
     555             : if (_popt_debug)
     556             :     {   poptArgv avp;
     557             :         fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
     558             :         for (avp = argv; *avp; avp++)
     559             :             fprintf(stderr, " '%s'", *avp);
     560             :         fprintf(stderr, "\n");
     561             :     }
     562             : #endif
     563             : 
     564             : /*@-nullstate@*/
     565           0 :     rc = execvp(argv[0], (char *const *)argv);
     566             : /*@=nullstate@*/
     567             : 
     568           0 : exit:
     569           0 :     if (argv) {
     570           0 :         if (argv[0])
     571           0 :             free((void *)argv[0]);
     572           0 :         free(argv);
     573             :     }
     574           0 :     return ec;
     575             : }
     576             : 
     577             : /*@observer@*/ /*@null@*/
     578             : static const struct poptOption *
     579         300 : findOption(const struct poptOption * opt,
     580             :                 /*@null@*/ const char * longName, size_t longNameLen,
     581             :                 char shortName,
     582             :                 /*@null@*/ /*@out@*/ poptCallbackType * callback,
     583             :                 /*@null@*/ /*@out@*/ const void ** callbackData,
     584             :                 unsigned int argInfo)
     585             :         /*@modifies *callback, *callbackData */
     586             : {
     587         300 :     const struct poptOption * cb = NULL;
     588         300 :     poptArg cbarg = { .ptr = NULL };
     589             : 
     590             :     /* This happens when a single - is given */
     591         300 :     if (LF_ISSET(ONEDASH) && !shortName && (longName && *longName == '\0'))
     592           0 :         shortName = '-';
     593             : 
     594        2387 :     for (; opt->longName || opt->shortName || opt->arg; opt++) {
     595        2207 :         poptArg arg = { .ptr = opt->arg };
     596             : 
     597        2207 :         switch (poptArgType(opt)) {
     598         202 :         case POPT_ARG_INCLUDE_TABLE:    /* Recurse on included sub-tables. */
     599             :         {   const struct poptOption * opt2;
     600             : 
     601         202 :             poptSubstituteHelpI18N(arg.opt);    /* XXX side effects */
     602         560 :             if (arg.ptr == NULL) continue;      /* XXX program error */
     603         202 :             opt2 = findOption(arg.opt, longName, longNameLen, shortName, callback,
     604             :                               callbackData, argInfo);
     605         202 :             if (opt2 == NULL) continue;
     606             :             /* Sub-table data will be inheirited if no data yet. */
     607             : /*@-observertrans -dependenttrans @*/
     608          46 :             if (callback && *callback
     609          46 :              && callbackData && *callbackData == NULL)
     610          46 :                 *callbackData = opt->descrip;
     611             : /*@=observertrans =dependenttrans @*/
     612          46 :             return opt2;
     613             :         }   /*@notreached@*/ /*@switchbreak@*/ break;
     614         202 :         case POPT_ARG_CALLBACK:
     615         202 :             cb = opt;
     616         202 :             cbarg.ptr = opt->arg;
     617         202 :             continue;
     618             :             /*@notreached@*/ /*@switchbreak@*/ break;
     619        1803 :         default:
     620        1803 :             /*@switchbreak@*/ break;
     621             :         }
     622             : 
     623        1803 :         if (longName != NULL && opt->longName != NULL &&
     624        2559 :                    (!LF_ISSET(ONEDASH) || F_ISSET(opt, ONEDASH)) &&
     625        1041 :                    longOptionStrcmp(opt, longName, longNameLen))
     626             :         {
     627             :             break;
     628        1745 :         } else if (shortName && shortName == opt->shortName) {
     629          16 :             break;
     630             :         }
     631             :     }
     632             : 
     633         254 :     if (opt->longName == NULL && !opt->shortName)
     634         180 :         return NULL;
     635             : 
     636             : /*@-modobserver -mods @*/
     637          74 :     if (callback)
     638          74 :         *callback = (cb ? cbarg.cb : NULL);
     639          74 :     if (callbackData)
     640             : /*@-observertrans -dependenttrans @*/
     641          74 :         *callbackData = (cb && !CBF_ISSET(cb, INC_DATA) ? cb->descrip : NULL);
     642             : /*@=observertrans =dependenttrans @*/
     643             : /*@=modobserver =mods @*/
     644             : 
     645          74 :     return opt;
     646             : }
     647             : 
     648           0 : static const char * findNextArg(/*@special@*/ poptContext con,
     649             :                 unsigned argx, int delete_arg)
     650             :         /*@uses con->optionStack, con->os,
     651             :                 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
     652             :         /*@modifies con @*/
     653             : {
     654           0 :     struct optionStackEntry * os = con->os;
     655             :     const char * arg;
     656             : 
     657             :     do {
     658             :         int i;
     659           0 :         arg = NULL;
     660           0 :         while (os->next == os->argc && os > con->optionStack) os--;
     661           0 :         if (os->next == os->argc && os == con->optionStack) break;
     662           0 :         if (os->argv != NULL)
     663           0 :         for (i = os->next; i < os->argc; i++) {
     664             : /*@-sizeoftype@*/
     665           0 :             if (os->argb && PBM_ISSET(i, os->argb))
     666           0 :                 /*@innercontinue@*/ continue;
     667           0 :             if (*os->argv[i] == '-')
     668           0 :                 /*@innercontinue@*/ continue;
     669           0 :             if (--argx > 0)
     670           0 :                 /*@innercontinue@*/ continue;
     671           0 :             arg = os->argv[i];
     672           0 :             if (delete_arg) {
     673           0 :                 if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
     674           0 :                 if (os->argb != NULL)        /* XXX can't happen */
     675           0 :                     PBM_SET(i, os->argb);
     676             :             }
     677           0 :             /*@innerbreak@*/ break;
     678             : /*@=sizeoftype@*/
     679             :         }
     680           0 :         if (os > con->optionStack) os--;
     681           0 :     } while (arg == NULL);
     682           0 :     return arg;
     683             : }
     684             : 
     685             : static /*@only@*/ /*@null@*/ const char *
     686          51 : expandNextArg(/*@special@*/ poptContext con, const char * s)
     687             :         /*@uses con->optionStack, con->os,
     688             :                 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
     689             :         /*@modifies con @*/
     690             : {
     691          51 :     const char * a = NULL;
     692             :     char *t, *te;
     693          51 :     size_t tn = strlen(s) + 1;
     694             :     char c;
     695             : 
     696          51 :     te = t = malloc(tn);
     697          51 :     if (t == NULL) return NULL;         /* XXX can't happen */
     698          51 :     *t = '\0';
     699        2500 :     while ((c = *s++) != '\0') {
     700        2449 :         switch (c) {
     701             : #if 0   /* XXX can't do this */
     702             :         case '\\':      /* escape */
     703             :             c = *s++;
     704             :             /*@switchbreak@*/ break;
     705             : #endif
     706           0 :         case '!':
     707           0 :             if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
     708             :                 /*@switchbreak@*/ break;
     709             :             /* XXX Make sure that findNextArg deletes only next arg. */
     710           0 :             if (a == NULL) {
     711           0 :                 if ((a = findNextArg(con, 1U, 1)) == NULL)
     712           0 :                     /*@switchbreak@*/ break;
     713             :             }
     714           0 :             s += sizeof("#:+") - 1;
     715             : 
     716           0 :             tn += strlen(a);
     717           0 :             {   size_t pos = (size_t) (te - t);
     718           0 :                 if ((t = realloc(t, tn)) == NULL)       /* XXX can't happen */
     719           0 :                     return NULL;
     720           0 :                 te = stpcpy(t + pos, a);
     721             :             }
     722           0 :             continue;
     723             :             /*@notreached@*/ /*@switchbreak@*/ break;
     724        2449 :         default:
     725        2449 :             /*@switchbreak@*/ break;
     726             :         }
     727        2449 :         *te++ = c;
     728             :     }
     729          51 :     *te++ = '\0';
     730             :     /* If the new string is longer than needed, shorten. */
     731          51 :     if ((t + tn) > te) {
     732             : /*@-usereleased@*/      /* XXX splint can't follow the pointers. */
     733           0 :         if ((te = realloc(t, (size_t)(te - t))) == NULL)
     734           0 :             free(t);
     735           0 :         t = te;
     736             : /*@=usereleased@*/
     737             :     }
     738          51 :     return t;
     739             : }
     740             : 
     741           0 : static void poptStripArg(/*@special@*/ poptContext con, int which)
     742             :         /*@uses con->optionStack @*/
     743             :         /*@defines con->arg_strip @*/
     744             :         /*@modifies con @*/
     745             : {
     746             : /*@-compdef -sizeoftype -usedef @*/
     747           0 :     if (con->arg_strip == NULL)
     748           0 :         con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
     749           0 :     if (con->arg_strip != NULL)              /* XXX can't happen */
     750           0 :     PBM_SET(which, con->arg_strip);
     751           0 :     return;
     752             : /*@=compdef =sizeoftype =usedef @*/
     753             : }
     754             : 
     755             : /*@unchecked@*/
     756             : unsigned int _poptBitsN = _POPT_BITS_N;
     757             : /*@unchecked@*/
     758             : unsigned int _poptBitsM = _POPT_BITS_M;
     759             : /*@unchecked@*/
     760             : unsigned int _poptBitsK = _POPT_BITS_K;
     761             : 
     762             : /*@-sizeoftype@*/
     763           0 : static int _poptBitsNew(/*@null@*/ poptBits *bitsp)
     764             :         /*@globals _poptBitsN, _poptBitsM, _poptBitsK @*/
     765             :         /*@modifies *bitsp, _poptBitsN, _poptBitsM, _poptBitsK @*/
     766             : {
     767           0 :     if (bitsp == NULL)
     768           0 :         return POPT_ERROR_NULLARG;
     769             : 
     770             :     /* XXX handle negated initialization. */
     771           0 :     if (*bitsp == NULL) {
     772           0 :         if (_poptBitsN == 0) {
     773           0 :             _poptBitsN = _POPT_BITS_N;
     774           0 :             _poptBitsM = _POPT_BITS_M;
     775             :         }
     776           0 :         if (_poptBitsM == 0U) _poptBitsM = (3 * _poptBitsN) / 2;
     777           0 :         if (_poptBitsK == 0U || _poptBitsK > 32U) _poptBitsK = _POPT_BITS_K;
     778           0 :         *bitsp = PBM_ALLOC(_poptBitsM-1);
     779             :     }
     780             : /*@-nullstate@*/
     781           0 :     return 0;
     782             : /*@=nullstate@*/
     783             : }
     784             : 
     785           0 : int poptBitsAdd(poptBits bits, const char * s)
     786             : {
     787           0 :     size_t ns = (s ? strlen(s) : 0);
     788           0 :     uint32_t h0 = 0;
     789           0 :     uint32_t h1 = 0;
     790             : 
     791           0 :     if (bits == NULL || ns == 0)
     792           0 :         return POPT_ERROR_NULLARG;
     793             : 
     794           0 :     poptJlu32lpair(s, ns, &h0, &h1);
     795             : 
     796           0 :     for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
     797           0 :         uint32_t h = h0 + ns * h1;
     798           0 :         uint32_t ix = (h % _poptBitsM);
     799           0 :         PBM_SET(ix, bits);
     800             :     }
     801           0 :     return 0;
     802             : }
     803             : 
     804           0 : int poptBitsChk(poptBits bits, const char * s)
     805             : {
     806           0 :     size_t ns = (s ? strlen(s) : 0);
     807           0 :     uint32_t h0 = 0;
     808           0 :     uint32_t h1 = 0;
     809           0 :     int rc = 1;
     810             : 
     811           0 :     if (bits == NULL || ns == 0)
     812           0 :         return POPT_ERROR_NULLARG;
     813             : 
     814           0 :     poptJlu32lpair(s, ns, &h0, &h1);
     815             : 
     816           0 :     for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
     817           0 :         uint32_t h = h0 + ns * h1;
     818           0 :         uint32_t ix = (h % _poptBitsM);
     819           0 :         if (PBM_ISSET(ix, bits))
     820           0 :             continue;
     821           0 :         rc = 0;
     822           0 :         break;
     823             :     }
     824           0 :     return rc;
     825             : }
     826             : 
     827           0 : int poptBitsClr(poptBits bits)
     828             : {
     829             :     static size_t nbw = (__PBM_NBITS/8);
     830           0 :     size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
     831             : 
     832           0 :     if (bits == NULL)
     833           0 :         return POPT_ERROR_NULLARG;
     834           0 :     memset(bits, 0, nw * nbw);
     835           0 :     return 0;
     836             : }
     837             : 
     838           0 : int poptBitsDel(poptBits bits, const char * s)
     839             : {
     840           0 :     size_t ns = (s ? strlen(s) : 0);
     841           0 :     uint32_t h0 = 0;
     842           0 :     uint32_t h1 = 0;
     843             : 
     844           0 :     if (bits == NULL || ns == 0)
     845           0 :         return POPT_ERROR_NULLARG;
     846             : 
     847           0 :     poptJlu32lpair(s, ns, &h0, &h1);
     848             : 
     849           0 :     for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
     850           0 :         uint32_t h = h0 + ns * h1;
     851           0 :         uint32_t ix = (h % _poptBitsM);
     852           0 :         PBM_CLR(ix, bits);
     853             :     }
     854           0 :     return 0;
     855             : }
     856             : 
     857           0 : int poptBitsIntersect(poptBits *ap, const poptBits b)
     858             : {
     859             :     __pbm_bits *abits;
     860             :     __pbm_bits *bbits;
     861           0 :     __pbm_bits rc = 0;
     862           0 :     size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
     863             :     size_t i;
     864             : 
     865           0 :     if (ap == NULL || b == NULL || _poptBitsNew(ap))
     866           0 :         return POPT_ERROR_NULLARG;
     867           0 :     abits = __PBM_BITS(*ap);
     868           0 :     bbits = __PBM_BITS(b);
     869             : 
     870           0 :     for (i = 0; i < nw; i++) {
     871           0 :         abits[i] &= bbits[i];
     872           0 :         rc |= abits[i];
     873             :     }
     874           0 :     return (rc ? 1 : 0);
     875             : }
     876             : 
     877           0 : int poptBitsUnion(poptBits *ap, const poptBits b)
     878             : {
     879             :     __pbm_bits *abits;
     880             :     __pbm_bits *bbits;
     881           0 :     __pbm_bits rc = 0;
     882           0 :     size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
     883             :     size_t i;
     884             : 
     885           0 :     if (ap == NULL || b == NULL || _poptBitsNew(ap))
     886           0 :         return POPT_ERROR_NULLARG;
     887           0 :     abits = __PBM_BITS(*ap);
     888           0 :     bbits = __PBM_BITS(b);
     889             : 
     890           0 :     for (i = 0; i < nw; i++) {
     891           0 :         abits[i] |= bbits[i];
     892           0 :         rc |= abits[i];
     893             :     }
     894           0 :     return (rc ? 1 : 0);
     895             : }
     896             : 
     897           0 : int poptBitsArgs(poptContext con, poptBits *ap)
     898             : {
     899             :     const char ** av;
     900           0 :     int rc = 0;
     901             : 
     902           0 :     if (con == NULL || ap == NULL || _poptBitsNew(ap) ||
     903           0 :         con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
     904           0 :         return POPT_ERROR_NULLARG;
     905             : 
     906             :     /* some apps like [like RPM ;-) ] need this NULL terminated */
     907           0 :     con->leftovers[con->numLeftovers] = NULL;
     908             : 
     909           0 :     for (av = con->leftovers + con->nextLeftover; *av != NULL; av++) {
     910           0 :         if ((rc = poptBitsAdd(*ap, *av)) != 0)
     911           0 :             break;
     912             :     }
     913             : /*@-nullstate@*/
     914           0 :     return rc;
     915             : /*@=nullstate@*/
     916             : }
     917             : 
     918           0 : int poptSaveBits(poptBits * bitsp,
     919             :                 /*@unused@*/ UNUSED(unsigned int argInfo), const char * s)
     920             : {
     921           0 :     char *tbuf = NULL;
     922             :     char *t, *te;
     923           0 :     int rc = 0;
     924             : 
     925           0 :     if (bitsp == NULL || s == NULL || *s == '\0' || _poptBitsNew(bitsp))
     926           0 :         return POPT_ERROR_NULLARG;
     927             : 
     928             :     /* Parse comma separated attributes. */
     929           0 :     te = tbuf = xstrdup(s);
     930           0 :     while ((t = te) != NULL && *t) {
     931           0 :         while (*te != '\0' && *te != ',')
     932           0 :             te++;
     933           0 :         if (*te != '\0')
     934           0 :             *te++ = '\0';
     935             :         /* XXX Ignore empty strings. */
     936           0 :         if (*t == '\0')
     937           0 :             continue;
     938             :         /* XXX Permit negated attributes. caveat emptor: false negatives. */
     939           0 :         if (*t == '!') {
     940           0 :             t++;
     941           0 :             if ((rc = poptBitsChk(*bitsp, t)) > 0)
     942           0 :                 rc = poptBitsDel(*bitsp, t);
     943             :         } else
     944           0 :             rc = poptBitsAdd(*bitsp, t);
     945           0 :         if (rc)
     946           0 :             break;
     947             :     }
     948           0 :     tbuf = _free(tbuf);
     949           0 :     return rc;
     950             : }
     951             : /*@=sizeoftype@*/
     952             : 
     953           0 : int poptSaveString(const char *** argvp,
     954             :                 /*@unused@*/ UNUSED(unsigned int argInfo), const char * val)
     955             : {
     956           0 :     int argc = 0;
     957             : 
     958           0 :     if (argvp == NULL || val == NULL)
     959           0 :         return POPT_ERROR_NULLARG;
     960             : 
     961             :     /* XXX likely needs an upper bound on argc. */
     962           0 :     if (*argvp != NULL)
     963           0 :     while ((*argvp)[argc] != NULL)
     964           0 :         argc++;
     965             : 
     966             : /*@-unqualifiedtrans -nullstate@*/      /* XXX no annotation for (*argvp) */
     967           0 :     if ((*argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp))) != NULL) {
     968           0 :         (*argvp)[argc++] = xstrdup(val);
     969           0 :         (*argvp)[argc  ] = NULL;
     970             :     }
     971           0 :     return 0;
     972             : /*@=unqualifiedtrans =nullstate@*/
     973             : }
     974             : 
     975             : /*@unchecked@*/
     976             : static unsigned int seed = 0;
     977             : 
     978           0 : int poptSaveLongLong(long long * arg, unsigned int argInfo, long long aLongLong)
     979             : {
     980           0 :     if (arg == NULL
     981             : #ifdef  NOTYET
     982             :     /* XXX Check alignment, may fail on funky platforms. */
     983             :      || (((unsigned long long)arg) & (sizeof(*arg)-1))
     984             : #endif
     985             :     )
     986           0 :         return POPT_ERROR_NULLARG;
     987             : 
     988           0 :     if (aLongLong != 0 && LF_ISSET(RANDOM)) {
     989             : #if defined(HAVE_SRANDOM)
     990           0 :         if (!seed) {
     991           0 :             srandom((unsigned)getpid());
     992           0 :             srandom((unsigned)random());
     993             :         }
     994           0 :         aLongLong = (long long)(random() % (aLongLong > 0 ? aLongLong : -aLongLong));
     995           0 :         aLongLong++;
     996             : #else
     997             :         /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
     998             :         return POPT_ERROR_BADOPERATION;
     999             : #endif
    1000             :     }
    1001           0 :     if (LF_ISSET(NOT))
    1002           0 :         aLongLong = ~aLongLong;
    1003           0 :     switch (LF_ISSET(LOGICALOPS)) {
    1004           0 :     case 0:
    1005           0 :         *arg = aLongLong;
    1006           0 :         break;
    1007           0 :     case POPT_ARGFLAG_OR:
    1008           0 :         *(unsigned long long *)arg |= (unsigned long long)aLongLong;
    1009           0 :         break;
    1010           0 :     case POPT_ARGFLAG_AND:
    1011           0 :         *(unsigned long long *)arg &= (unsigned long long)aLongLong;
    1012           0 :         break;
    1013           0 :     case POPT_ARGFLAG_XOR:
    1014           0 :         *(unsigned long long *)arg ^= (unsigned long long)aLongLong;
    1015           0 :         break;
    1016           0 :     default:
    1017           0 :         return POPT_ERROR_BADOPERATION;
    1018             :         /*@notreached@*/ break;
    1019             :     }
    1020           0 :     return 0;
    1021             : }
    1022             : 
    1023           0 : int poptSaveLong(long * arg, unsigned int argInfo, long aLong)
    1024             : {
    1025             :     /* XXX Check alignment, may fail on funky platforms. */
    1026           0 :     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
    1027           0 :         return POPT_ERROR_NULLARG;
    1028             : 
    1029           0 :     if (aLong != 0 && LF_ISSET(RANDOM)) {
    1030             : #if defined(HAVE_SRANDOM)
    1031           0 :         if (!seed) {
    1032           0 :             srandom((unsigned)getpid());
    1033           0 :             srandom((unsigned)random());
    1034             :         }
    1035           0 :         aLong = random() % (aLong > 0 ? aLong : -aLong);
    1036           0 :         aLong++;
    1037             : #else
    1038             :         /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
    1039             :         return POPT_ERROR_BADOPERATION;
    1040             : #endif
    1041             :     }
    1042           0 :     if (LF_ISSET(NOT))
    1043           0 :         aLong = ~aLong;
    1044           0 :     switch (LF_ISSET(LOGICALOPS)) {
    1045           0 :     case 0:                *arg = aLong; break;
    1046           0 :     case POPT_ARGFLAG_OR:  *(unsigned long *)arg |= (unsigned long)aLong; break;
    1047           0 :     case POPT_ARGFLAG_AND: *(unsigned long *)arg &= (unsigned long)aLong; break;
    1048           0 :     case POPT_ARGFLAG_XOR: *(unsigned long *)arg ^= (unsigned long)aLong; break;
    1049           0 :     default:
    1050           0 :         return POPT_ERROR_BADOPERATION;
    1051             :         /*@notreached@*/ break;
    1052             :     }
    1053           0 :     return 0;
    1054             : }
    1055             : 
    1056          14 : int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong)
    1057             : {
    1058             :     /* XXX Check alignment, may fail on funky platforms. */
    1059          14 :     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
    1060           0 :         return POPT_ERROR_NULLARG;
    1061             : 
    1062          14 :     if (aLong != 0 && LF_ISSET(RANDOM)) {
    1063             : #if defined(HAVE_SRANDOM)
    1064           0 :         if (!seed) {
    1065           0 :             srandom((unsigned)getpid());
    1066           0 :             srandom((unsigned)random());
    1067             :         }
    1068           0 :         aLong = random() % (aLong > 0 ? aLong : -aLong);
    1069           0 :         aLong++;
    1070             : #else
    1071             :         /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
    1072             :         return POPT_ERROR_BADOPERATION;
    1073             : #endif
    1074             :     }
    1075          14 :     if (LF_ISSET(NOT))
    1076           0 :         aLong = ~aLong;
    1077          14 :     switch (LF_ISSET(LOGICALOPS)) {
    1078          14 :     case 0:                *arg = (int) aLong;                          break;
    1079           0 :     case POPT_ARGFLAG_OR:  *(unsigned int *)arg |= (unsigned int) aLong; break;
    1080           0 :     case POPT_ARGFLAG_AND: *(unsigned int *)arg &= (unsigned int) aLong; break;
    1081           0 :     case POPT_ARGFLAG_XOR: *(unsigned int *)arg ^= (unsigned int) aLong; break;
    1082           0 :     default:
    1083           0 :         return POPT_ERROR_BADOPERATION;
    1084             :         /*@notreached@*/ break;
    1085             :     }
    1086          14 :     return 0;
    1087             : }
    1088             : 
    1089           0 : int poptSaveShort(/*@null@*/ short * arg, unsigned int argInfo, long aLong)
    1090             : {
    1091             :     /* XXX Check alignment, may fail on funky platforms. */
    1092           0 :     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
    1093           0 :         return POPT_ERROR_NULLARG;
    1094             : 
    1095           0 :     if (aLong != 0 && LF_ISSET(RANDOM)) {
    1096             : #if defined(HAVE_SRANDOM)
    1097           0 :         if (!seed) {
    1098           0 :             srandom((unsigned)getpid());
    1099           0 :             srandom((unsigned)random());
    1100             :         }
    1101           0 :         aLong = random() % (aLong > 0 ? aLong : -aLong);
    1102           0 :         aLong++;
    1103             : #else
    1104             :         /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
    1105             :         return POPT_ERROR_BADOPERATION;
    1106             : #endif
    1107             :     }
    1108           0 :     if (LF_ISSET(NOT))
    1109           0 :         aLong = ~aLong;
    1110           0 :     switch (LF_ISSET(LOGICALOPS)) {
    1111           0 :     case 0:                *arg = (short) aLong;
    1112           0 :         break;
    1113           0 :     case POPT_ARGFLAG_OR:  *(unsigned short *)arg |= (unsigned short) aLong;
    1114           0 :         break;
    1115           0 :     case POPT_ARGFLAG_AND: *(unsigned short *)arg &= (unsigned short) aLong;
    1116           0 :         break;
    1117           0 :     case POPT_ARGFLAG_XOR: *(unsigned short *)arg ^= (unsigned short) aLong;
    1118           0 :         break;
    1119           0 :     default: return POPT_ERROR_BADOPERATION;
    1120             :         /*@notreached@*/ break;
    1121             :     }
    1122           0 :     return 0;
    1123             : }
    1124             : 
    1125             : /**
    1126             :  * Return argInfo field, handling POPT_ARGFLAG_TOGGLE overrides.
    1127             :  * @param con           context
    1128             :  * @param opt           option
    1129             :  * @return              argInfo
    1130             :  */
    1131          14 : static unsigned int poptArgInfo(poptContext con, const struct poptOption * opt)
    1132             :         /*@*/
    1133             : {
    1134          14 :     unsigned int argInfo = opt->argInfo;
    1135             : 
    1136          14 :     if (con->os->argv != NULL && con->os->next > 0 && opt->longName != NULL)
    1137          14 :     if (LF_ISSET(TOGGLE)) {
    1138           0 :         const char * longName = con->os->argv[con->os->next-1];
    1139           0 :         while (*longName == '-') longName++;
    1140             :         /* XXX almost good enough but consider --[no]nofoo corner cases. */
    1141           0 :         if (longName[0] != opt->longName[0] || longName[1] != opt->longName[1])
    1142             :         {
    1143           0 :             if (!LF_ISSET(XOR)) {       /* XXX dont toggle with XOR */
    1144             :                 /* Toggle POPT_BIT_SET <=> POPT_BIT_CLR. */
    1145           0 :                 if (LF_ISSET(LOGICALOPS))
    1146           0 :                     argInfo ^= (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND);
    1147           0 :                 argInfo ^= POPT_ARGFLAG_NOT;
    1148             :             }
    1149             :         }
    1150             :     }
    1151          14 :     return argInfo;
    1152             : }
    1153             : 
    1154             : /**
    1155             :  * Parse an integer expression.
    1156             :  * @retval *llp         integer expression value
    1157             :  * @param argInfo       integer expression type
    1158             :  * @param val           integer expression string
    1159             :  * @return              0 on success, otherwise POPT_* error.
    1160             :  */
    1161           2 : static int poptParseInteger(long long * llp,
    1162             :                 /*@unused@*/ UNUSED(unsigned int argInfo),
    1163             :                 /*@null@*/ const char * val)
    1164             :         /*@modifies *llp @*/
    1165             : {
    1166           2 :     if (val) {
    1167           2 :         char *end = NULL;
    1168           2 :         *llp = strtoll(val, &end, 0);
    1169             : 
    1170             :         /* XXX parse scaling suffixes here. */
    1171             : 
    1172           2 :         if (!(end && *end == '\0'))
    1173           0 :             return POPT_ERROR_BADNUMBER;
    1174             :     } else
    1175           0 :         *llp = 0;
    1176           2 :     return 0;
    1177             : }
    1178             : 
    1179             : /**
    1180             :  * Save the option argument through the (*opt->arg) pointer.
    1181             :  * @param con           context
    1182             :  * @param opt           option
    1183             :  * @return              0 on success, otherwise POPT_* error.
    1184             :  */
    1185           9 : static int poptSaveArg(poptContext con, const struct poptOption * opt)
    1186             :         /*@globals fileSystem, internalState @*/
    1187             :         /*@modifies con, fileSystem, internalState @*/
    1188             : {
    1189           9 :     poptArg arg = { .ptr = opt->arg };
    1190           9 :     int rc = 0;         /* assume success */
    1191             : 
    1192           9 :     switch (poptArgType(opt)) {
    1193           0 :     case POPT_ARG_BITSET:
    1194             :         /* XXX memory leak, application is responsible for free. */
    1195           0 :         rc = poptSaveBits(arg.ptr, opt->argInfo, con->os->nextArg);
    1196           0 :         /*@switchbreak@*/ break;
    1197           0 :     case POPT_ARG_ARGV:
    1198             :         /* XXX memory leak, application is responsible for free. */
    1199           0 :         rc = poptSaveString(arg.ptr, opt->argInfo, con->os->nextArg);
    1200           0 :         /*@switchbreak@*/ break;
    1201           7 :     case POPT_ARG_STRING:
    1202             :         /* XXX memory leak, application is responsible for free. */
    1203           7 :         arg.argv[0] = (con->os->nextArg) ? xstrdup(con->os->nextArg) : NULL;
    1204           7 :         /*@switchbreak@*/ break;
    1205             : 
    1206           2 :     case POPT_ARG_INT:
    1207             :     case POPT_ARG_SHORT:
    1208             :     case POPT_ARG_LONG:
    1209             :     case POPT_ARG_LONGLONG:
    1210           2 :     {   unsigned int argInfo = poptArgInfo(con, opt);
    1211           2 :         long long aNUM = 0;
    1212             : 
    1213           2 :         if ((rc = poptParseInteger(&aNUM, argInfo, con->os->nextArg)) != 0)
    1214           0 :             break;
    1215             : 
    1216           2 :         switch (poptArgType(opt)) {
    1217           0 :         case POPT_ARG_LONGLONG:
    1218             : /* XXX let's not demand C99 compiler flags for <limits.h> quite yet. */
    1219             : #if !defined(LLONG_MAX)
    1220             : #   define LLONG_MAX    9223372036854775807LL
    1221             : #   define LLONG_MIN    (-LLONG_MAX - 1LL)
    1222             : #endif
    1223           0 :             rc = !(aNUM == LLONG_MIN || aNUM == LLONG_MAX)
    1224           0 :                 ? poptSaveLongLong(arg.longlongp, argInfo, aNUM)
    1225           0 :                 : POPT_ERROR_OVERFLOW;
    1226           0 :             /*@innerbreak@*/ break;
    1227           0 :         case POPT_ARG_LONG:
    1228             :             rc = !(aNUM < (long long)LONG_MIN || aNUM > (long long)LONG_MAX)
    1229             :                 ? poptSaveLong(arg.longp, argInfo, (long)aNUM)
    1230           0 :                 : POPT_ERROR_OVERFLOW;
    1231           0 :             /*@innerbreak@*/ break;
    1232           2 :         case POPT_ARG_INT:
    1233           2 :             rc = !(aNUM < (long long)INT_MIN || aNUM > (long long)INT_MAX)
    1234           2 :                 ? poptSaveInt(arg.intp, argInfo, (long)aNUM)
    1235           2 :                 : POPT_ERROR_OVERFLOW;
    1236           2 :             /*@innerbreak@*/ break;
    1237           0 :         case POPT_ARG_SHORT:
    1238           0 :             rc = !(aNUM < (long long)SHRT_MIN || aNUM > (long long)SHRT_MAX)
    1239           0 :                 ? poptSaveShort(arg.shortp, argInfo, (long)aNUM)
    1240           0 :                 : POPT_ERROR_OVERFLOW;
    1241           0 :             /*@innerbreak@*/ break;
    1242             :         }
    1243           2 :     }   /*@switchbreak@*/ break;
    1244             : 
    1245           0 :     case POPT_ARG_FLOAT:
    1246             :     case POPT_ARG_DOUBLE:
    1247           0 :     {   char *end = NULL;
    1248           0 :         double aDouble = 0.0;
    1249             : 
    1250           0 :         if (con->os->nextArg) {
    1251             : /*@-mods@*/
    1252           0 :             int saveerrno = errno;
    1253           0 :             errno = 0;
    1254           0 :             aDouble = strtod(con->os->nextArg, &end);
    1255           0 :             if (errno == ERANGE) {
    1256           0 :                 rc = POPT_ERROR_OVERFLOW;
    1257           0 :                 break;
    1258             :             }
    1259           0 :             errno = saveerrno;
    1260             : /*@=mods@*/
    1261           0 :             if (*end != '\0') {
    1262           0 :                 rc = POPT_ERROR_BADNUMBER;
    1263           0 :                 break;
    1264             :             }
    1265             :         }
    1266             : 
    1267           0 :         switch (poptArgType(opt)) {
    1268           0 :         case POPT_ARG_DOUBLE:
    1269           0 :             arg.doublep[0] = aDouble;
    1270           0 :             /*@innerbreak@*/ break;
    1271           0 :         case POPT_ARG_FLOAT:
    1272             : #if !defined(DBL_EPSILON) && !defined(__LCLINT__)
    1273             : #define DBL_EPSILON 2.2204460492503131e-16
    1274             : #endif
    1275             : #define POPT_ABS(a)     ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
    1276           0 :             if ((FLT_MIN - POPT_ABS(aDouble)) > DBL_EPSILON
    1277           0 :              || (POPT_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
    1278           0 :                 rc = POPT_ERROR_OVERFLOW;
    1279             :             else
    1280           0 :                 arg.floatp[0] = (float) aDouble;
    1281           0 :             /*@innerbreak@*/ break;
    1282             :         }
    1283           0 :     }   /*@switchbreak@*/ break;
    1284           0 :     case POPT_ARG_MAINCALL:
    1285             : /*@-assignexpose -type@*/
    1286           0 :         con->maincall = opt->arg;
    1287             : /*@=assignexpose =type@*/
    1288           0 :         /*@switchbreak@*/ break;
    1289           0 :     default:
    1290           0 :         fprintf(stdout, POPT_("option type (%u) not implemented in popt\n"),
    1291           0 :                 poptArgType(opt));
    1292           0 :         exit(EXIT_FAILURE);
    1293             :         /*@notreached@*/ /*@switchbreak@*/ break;
    1294             :     }
    1295           9 :     return rc;
    1296             : }
    1297             : 
    1298             : /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
    1299          55 : int poptGetNextOpt(poptContext con)
    1300             : {
    1301          55 :     const struct poptOption * opt = NULL;
    1302          55 :     int done = 0;
    1303             : 
    1304          55 :     if (con == NULL)
    1305           0 :         return -1;
    1306         187 :     while (!done) {
    1307         175 :         const char * origOptString = NULL;
    1308         175 :         poptCallbackType cb = NULL;
    1309         175 :         const void * cbData = NULL;
    1310         175 :         const char * longArg = NULL;
    1311         175 :         int canstrip = 0;
    1312         175 :         int shorty = 0;
    1313             : 
    1314         350 :         while (!con->os->nextCharArg && con->os->next == con->os->argc
    1315         212 :                 && con->os > con->optionStack) {
    1316           0 :             cleanOSE(con->os--);
    1317             :         }
    1318         175 :         if (!con->os->nextCharArg && con->os->next == con->os->argc) {
    1319          37 :             invokeCallbacksPOST(con, con->options);
    1320             : 
    1321          37 :             if (con->maincall) {
    1322             :                 /*@-noeffectuncon @*/
    1323           0 :                 (void) (*con->maincall) (con->finalArgvCount, con->finalArgv);
    1324             :                 /*@=noeffectuncon @*/
    1325          43 :                 return -1;
    1326             :             }
    1327             : 
    1328          37 :             if (con->doExec) return execCommand(con);
    1329          37 :             return -1;
    1330             :         }
    1331             : 
    1332             :         /* Process next long option */
    1333         138 :         if (!con->os->nextCharArg) {
    1334             :             const char * optString;
    1335             :             size_t optStringLen;
    1336             :             int thisopt;
    1337             : 
    1338             : /*@-sizeoftype@*/
    1339         138 :             if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
    1340           0 :                 con->os->next++;
    1341          58 :                 continue;
    1342             :             }
    1343             : /*@=sizeoftype@*/
    1344         138 :             thisopt = con->os->next;
    1345         138 :             if (con->os->argv != NULL)    /* XXX can't happen */
    1346         138 :             origOptString = con->os->argv[con->os->next++];
    1347             : 
    1348         138 :             if (origOptString == NULL)  /* XXX can't happen */
    1349           0 :                 return POPT_ERROR_BADOPT;
    1350             : 
    1351         138 :             if (con->restLeftover || *origOptString != '-' ||
    1352          80 :                 (*origOptString == '-' && origOptString[1] == '\0'))
    1353             :             {
    1354          58 :                 if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
    1355           0 :                     con->restLeftover = 1;
    1356          58 :                 if (con->flags & POPT_CONTEXT_ARG_OPTS) {
    1357           0 :                     con->os->nextArg = xstrdup(origOptString);
    1358           0 :                     return 0;
    1359             :                 }
    1360          58 :                 if (con->leftovers != NULL)  /* XXX can't happen */
    1361          58 :                     con->leftovers[con->numLeftovers++] = origOptString;
    1362          58 :                 continue;
    1363             :             }
    1364             : 
    1365             :             /* Make a copy we can hack at */
    1366          80 :             optString = origOptString;
    1367             : 
    1368          80 :             if (optString[0] == '\0')
    1369           0 :                 return POPT_ERROR_BADOPT;
    1370             : 
    1371          80 :             if (optString[1] == '-' && !optString[2]) {
    1372           0 :                 con->restLeftover = 1;
    1373           0 :                 continue;
    1374             :             } else {
    1375             :                 const char *oe;
    1376          80 :                 unsigned int argInfo = 0;
    1377             : 
    1378          80 :                 optString++;
    1379          80 :                 if (*optString == '-')
    1380          62 :                     optString++;
    1381             :                 else
    1382          18 :                     argInfo |= POPT_ARGFLAG_ONEDASH;
    1383             : 
    1384             :                 /* Check for "--long=arg" option. */
    1385         792 :                 for (oe = optString; *oe && *oe != '='; oe++)
    1386             :                     {};
    1387          80 :                 optStringLen = (size_t)(oe - optString);
    1388          80 :                 if (*oe == '=')
    1389          39 :                     longArg = oe + 1;
    1390             : 
    1391             :                 /* XXX aliases with arg substitution need "--alias=arg" */
    1392          80 :                 if (handleAlias(con, optString, optStringLen, '\0', longArg)) {
    1393           0 :                     longArg = NULL;
    1394           0 :                     continue;
    1395             :                 }
    1396             : 
    1397          80 :                 if (handleExec(con, optString, '\0'))
    1398           0 :                     continue;
    1399             : 
    1400          80 :                 opt = findOption(con->options, optString, optStringLen, '\0', &cb, &cbData,
    1401             :                                  argInfo);
    1402          80 :                 if (!opt && !LF_ISSET(ONEDASH))
    1403           4 :                     return POPT_ERROR_BADOPT;
    1404             :             }
    1405             : 
    1406          76 :             if (!opt) {
    1407          18 :                 con->os->nextCharArg = origOptString + 1;
    1408          18 :                 longArg = NULL;
    1409             :             } else {
    1410          58 :                 if (con->os == con->optionStack && F_ISSET(opt, STRIP))
    1411             :                 {
    1412           0 :                     canstrip = 1;
    1413           0 :                     poptStripArg(con, thisopt);
    1414             :                 }
    1415          58 :                 shorty = 0;
    1416             :             }
    1417             :         }
    1418             : 
    1419             :         /* Process next short option */
    1420          76 :         if (con->os->nextCharArg) {
    1421          18 :             const char * nextCharArg = con->os->nextCharArg;
    1422             : 
    1423          18 :             con->os->nextCharArg = NULL;
    1424             : 
    1425          18 :             if (handleAlias(con, NULL, 0, *nextCharArg, nextCharArg + 1))
    1426           0 :                 continue;
    1427             : 
    1428          18 :             if (handleExec(con, NULL, *nextCharArg)) {
    1429             :                 /* Restore rest of short options for further processing */
    1430           0 :                 nextCharArg++;
    1431           0 :                 if (*nextCharArg != '\0')
    1432           0 :                     con->os->nextCharArg = nextCharArg;
    1433           0 :                 continue;
    1434             :             }
    1435             : 
    1436          18 :             opt = findOption(con->options, NULL, 0, *nextCharArg, &cb,
    1437             :                              &cbData, 0);
    1438          18 :             if (!opt)
    1439           2 :                 return POPT_ERROR_BADOPT;
    1440          16 :             shorty = 1;
    1441             : 
    1442          16 :             nextCharArg++;
    1443          16 :             if (*nextCharArg != '\0')
    1444           2 :                 con->os->nextCharArg = nextCharArg + (int)(*nextCharArg == '=');
    1445             :         }
    1446             : 
    1447          74 :         if (opt == NULL) return POPT_ERROR_BADOPT;      /* XXX can't happen */
    1448          86 :         if (opt->arg && poptArgType(opt) == POPT_ARG_NONE) {
    1449          12 :             unsigned int argInfo = poptArgInfo(con, opt);
    1450          12 :             if (poptSaveInt((int *)opt->arg, argInfo, 1L))
    1451           0 :                 return POPT_ERROR_BADOPERATION;
    1452          62 :         } else if (poptArgType(opt) == POPT_ARG_VAL) {
    1453           0 :             if (opt->arg) {
    1454           0 :                 unsigned int argInfo = poptArgInfo(con, opt);
    1455           0 :                 if (poptSaveInt((int *)opt->arg, argInfo, (long)opt->val))
    1456           0 :                     return POPT_ERROR_BADOPERATION;
    1457             :             }
    1458          62 :         } else if (poptArgType(opt) != POPT_ARG_NONE) {
    1459             :             int rc;
    1460             : 
    1461          51 :             con->os->nextArg = _free(con->os->nextArg);
    1462          51 :             if (longArg) {
    1463          38 :                 longArg = expandNextArg(con, longArg);
    1464          38 :                 con->os->nextArg = (char *) longArg;
    1465          13 :             } else if (con->os->nextCharArg) {
    1466           2 :                 longArg = expandNextArg(con, con->os->nextCharArg);
    1467           2 :                 con->os->nextArg = (char *) longArg;
    1468           2 :                 con->os->nextCharArg = NULL;
    1469             :             } else {
    1470          11 :                 while (con->os->next == con->os->argc &&
    1471           0 :                         con->os > con->optionStack)
    1472             :                 {
    1473           0 :                     cleanOSE(con->os--);
    1474             :                 }
    1475          11 :                 if (con->os->next == con->os->argc) {
    1476           0 :                     if (!F_ISSET(opt, OPTIONAL))
    1477           0 :                         return POPT_ERROR_NOARG;
    1478           0 :                     con->os->nextArg = NULL;
    1479             :                 } else {
    1480             : 
    1481             :                     /*
    1482             :                      * Make sure this isn't part of a short arg or the
    1483             :                      * result of an alias expansion.
    1484             :                      */
    1485          11 :                     if (con->os == con->optionStack
    1486          11 :                      && F_ISSET(opt, STRIP) && canstrip)
    1487             :                     {
    1488           0 :                         poptStripArg(con, con->os->next);
    1489             :                     }
    1490             :                 
    1491          11 :                     if (con->os->argv != NULL) {  /* XXX can't happen */
    1492          11 :                         if (F_ISSET(opt, OPTIONAL) &&
    1493           0 :                             con->os->argv[con->os->next][0] == '-') {
    1494           0 :                             con->os->nextArg = NULL;
    1495             :                         } else {
    1496             :                             /* XXX watchout: subtle side-effects live here. */
    1497          11 :                             longArg = con->os->argv[con->os->next++];
    1498          11 :                             longArg = expandNextArg(con, longArg);
    1499          11 :                             con->os->nextArg = (char *) longArg;
    1500             :                         }
    1501             :                     }
    1502             :                 }
    1503             :             }
    1504          51 :             longArg = NULL;
    1505             : 
    1506             :            /* Save the option argument through a (*opt->arg) pointer. */
    1507          51 :             if (opt->arg != NULL && (rc = poptSaveArg(con, opt)) != 0)
    1508           0 :                 return rc;
    1509             :         }
    1510             : 
    1511          74 :         if (cb)
    1512          46 :             invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
    1513          28 :         else if (opt->val && (poptArgType(opt) != POPT_ARG_VAL))
    1514          12 :             done = 1;
    1515             : 
    1516          74 :         if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
    1517           0 :             con->finalArgvAlloced += 10;
    1518           0 :             con->finalArgv = realloc(con->finalArgv,
    1519           0 :                             sizeof(*con->finalArgv) * con->finalArgvAlloced);
    1520             :         }
    1521             : 
    1522          74 :         if (con->finalArgv != NULL)
    1523          74 :         {   char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + sizeof("--"));
    1524          74 :             if (s != NULL) {    /* XXX can't happen */
    1525          74 :                 con->finalArgv[con->finalArgvCount++] = s;
    1526          74 :                 *s++ = '-';
    1527          74 :                 if (opt->longName) {
    1528          74 :                     if (!F_ISSET(opt, ONEDASH))
    1529          74 :                         *s++ = '-';
    1530          74 :                     s = stpcpy(s, opt->longName);
    1531             :                 } else {
    1532           0 :                     *s++ = opt->shortName;
    1533           0 :                     *s = '\0';
    1534             :                 }
    1535             :             } else
    1536           0 :                 con->finalArgv[con->finalArgvCount++] = NULL;
    1537             :         }
    1538             : 
    1539          74 :         if (opt->arg && poptArgType(opt) == POPT_ARG_NONE)
    1540             :             /*@-ifempty@*/ ; /*@=ifempty@*/
    1541          62 :         else if (poptArgType(opt) == POPT_ARG_VAL)
    1542             :             /*@-ifempty@*/ ; /*@=ifempty@*/
    1543          62 :         else if (poptArgType(opt) != POPT_ARG_NONE) {
    1544          51 :             if (con->finalArgv != NULL && con->os->nextArg != NULL)
    1545          51 :                 con->finalArgv[con->finalArgvCount++] =
    1546          51 :                         xstrdup(con->os->nextArg);
    1547             :         }
    1548             :     }
    1549             : 
    1550          12 :     return (opt ? opt->val : -1);    /* XXX can't happen */
    1551             : }
    1552             : 
    1553           5 : char * poptGetOptArg(poptContext con)
    1554             : {
    1555           5 :     char * ret = NULL;
    1556           5 :     if (con) {
    1557           5 :         ret = con->os->nextArg;
    1558           5 :         con->os->nextArg = NULL;
    1559             :     }
    1560           5 :     return ret;
    1561             : }
    1562             : 
    1563          19 : const char * poptGetArg(poptContext con)
    1564             : {
    1565          19 :     const char * ret = NULL;
    1566          19 :     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
    1567          16 :         ret = con->leftovers[con->nextLeftover++];
    1568          19 :     return ret;
    1569             : }
    1570             : 
    1571          25 : const char * poptPeekArg(poptContext con)
    1572             : {
    1573          25 :     const char * ret = NULL;
    1574          25 :     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
    1575          14 :         ret = con->leftovers[con->nextLeftover];
    1576          25 :     return ret;
    1577             : }
    1578             : 
    1579           8 : const char ** poptGetArgs(poptContext con)
    1580             : {
    1581           8 :     if (con == NULL ||
    1582           8 :         con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
    1583           0 :         return NULL;
    1584             : 
    1585             :     /* some apps like [like RPM ;-) ] need this NULL terminated */
    1586           8 :     con->leftovers[con->numLeftovers] = NULL;
    1587             : 
    1588             : /*@-nullret -nullstate @*/      /* FIX: typedef double indirection. */
    1589           8 :     return (con->leftovers + con->nextLeftover);
    1590             : /*@=nullret =nullstate @*/
    1591             : }
    1592             : 
    1593             : static /*@null@*/
    1594          74 : poptItem poptFreeItems(/*@only@*/ /*@null@*/ poptItem items, int nitems)
    1595             :         /*@modifies items @*/
    1596             : {
    1597          74 :     if (items != NULL) {
    1598           0 :         poptItem item = items;
    1599           0 :         while (--nitems >= 0) {
    1600             : /*@-modobserver -observertrans -dependenttrans@*/
    1601           0 :             item->option.longName = _free(item->option.longName);
    1602           0 :             item->option.descrip = _free(item->option.descrip);
    1603           0 :             item->option.argDescrip = _free(item->option.argDescrip);
    1604             : /*@=modobserver =observertrans =dependenttrans@*/
    1605           0 :             item->argv = _free(item->argv);
    1606           0 :             item++;
    1607             :         }
    1608           0 :         items = _free(items);
    1609             :     }
    1610          74 :     return NULL;
    1611             : }
    1612             : 
    1613          37 : poptContext poptFreeContext(poptContext con)
    1614             : {
    1615          37 :     if (con == NULL) return con;
    1616          37 :     poptResetContext(con);
    1617          37 :     con->os->argb = _free(con->os->argb);
    1618             : 
    1619          37 :     con->aliases = poptFreeItems(con->aliases, con->numAliases);
    1620          37 :     con->numAliases = 0;
    1621             : 
    1622          37 :     con->execs = poptFreeItems(con->execs, con->numExecs);
    1623          37 :     con->numExecs = 0;
    1624             : 
    1625          37 :     con->leftovers = _free(con->leftovers);
    1626          37 :     con->finalArgv = _free(con->finalArgv);
    1627          37 :     con->appName = _free(con->appName);
    1628          37 :     con->otherHelp = _free(con->otherHelp);
    1629          37 :     con->execPath = _free(con->execPath);
    1630          37 :     con->arg_strip = PBM_FREE(con->arg_strip);
    1631             :     
    1632          37 :     con = _free(con);
    1633          37 :     return con;
    1634             : }
    1635             : 
    1636           0 : int poptAddAlias(poptContext con, struct poptAlias alias,
    1637             :                 /*@unused@*/ UNUSED(int flags))
    1638             : {
    1639             :     struct poptItem_s item_buf;
    1640           0 :     poptItem item = &item_buf;
    1641           0 :     memset(item, 0, sizeof(*item));
    1642           0 :     item->option.longName = alias.longName;
    1643           0 :     item->option.shortName = alias.shortName;
    1644           0 :     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
    1645           0 :     item->option.arg = 0;
    1646           0 :     item->option.val = 0;
    1647           0 :     item->option.descrip = NULL;
    1648           0 :     item->option.argDescrip = NULL;
    1649           0 :     item->argc = alias.argc;
    1650           0 :     item->argv = alias.argv;
    1651           0 :     return poptAddItem(con, item, 0);
    1652             : }
    1653             : 
    1654           0 : int poptAddItem(poptContext con, poptItem newItem, int flags)
    1655             : {
    1656             :     poptItem * items, item;
    1657             :     int * nitems;
    1658             : 
    1659           0 :     switch (flags) {
    1660           0 :     case 1:
    1661           0 :         items = &con->execs;
    1662           0 :         nitems = &con->numExecs;
    1663           0 :         break;
    1664           0 :     case 0:
    1665           0 :         items = &con->aliases;
    1666           0 :         nitems = &con->numAliases;
    1667           0 :         break;
    1668           0 :     default:
    1669           0 :         return 1;
    1670             :         /*@notreached@*/ break;
    1671             :     }
    1672             : 
    1673           0 :     *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
    1674           0 :     if ((*items) == NULL)
    1675           0 :         return 1;
    1676             : 
    1677           0 :     item = (*items) + (*nitems);
    1678             : 
    1679           0 :     item->option.longName =
    1680           0 :         (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
    1681           0 :     item->option.shortName = newItem->option.shortName;
    1682           0 :     item->option.argInfo = newItem->option.argInfo;
    1683           0 :     item->option.arg = newItem->option.arg;
    1684           0 :     item->option.val = newItem->option.val;
    1685           0 :     item->option.descrip =
    1686           0 :         (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
    1687           0 :     item->option.argDescrip =
    1688           0 :        (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
    1689           0 :     item->argc = newItem->argc;
    1690           0 :     item->argv = newItem->argv;
    1691             : 
    1692           0 :     (*nitems)++;
    1693             : 
    1694           0 :     return 0;
    1695             : }
    1696             : 
    1697           0 : const char * poptBadOption(poptContext con, unsigned int flags)
    1698             : {
    1699           0 :     struct optionStackEntry * os = NULL;
    1700             : 
    1701           0 :     if (con != NULL)
    1702           0 :         os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
    1703             : 
    1704           0 :     return (os != NULL && os->argv != NULL ? os->argv[os->next - 1] : NULL);
    1705             : }
    1706             : 
    1707           0 : const char * poptStrerror(const int error)
    1708             : {
    1709           0 :     switch (error) {
    1710           0 :       case POPT_ERROR_NOARG:
    1711           0 :         return POPT_("missing argument");
    1712           0 :       case POPT_ERROR_BADOPT:
    1713           0 :         return POPT_("unknown option");
    1714           0 :       case POPT_ERROR_BADOPERATION:
    1715           0 :         return POPT_("mutually exclusive logical operations requested");
    1716           0 :       case POPT_ERROR_NULLARG:
    1717           0 :         return POPT_("opt->arg should not be NULL");
    1718           0 :       case POPT_ERROR_OPTSTOODEEP:
    1719           0 :         return POPT_("aliases nested too deeply");
    1720           0 :       case POPT_ERROR_BADQUOTE:
    1721           0 :         return POPT_("error in parameter quoting");
    1722           0 :       case POPT_ERROR_BADNUMBER:
    1723           0 :         return POPT_("invalid numeric value");
    1724           0 :       case POPT_ERROR_OVERFLOW:
    1725           0 :         return POPT_("number too large or too small");
    1726           0 :       case POPT_ERROR_MALLOC:
    1727           0 :         return POPT_("memory allocation failed");
    1728           0 :       case POPT_ERROR_BADCONFIG:
    1729           0 :         return POPT_("config file failed sanity test");
    1730           0 :       case POPT_ERROR_ERRNO:
    1731           0 :         return strerror(errno);
    1732           0 :       default:
    1733           0 :         return POPT_("unknown error");
    1734             :     }
    1735             : }
    1736             : 
    1737           0 : int poptStuffArgs(poptContext con, const char ** argv)
    1738             : {
    1739             :     int argc;
    1740             :     int rc;
    1741             : 
    1742           0 :     if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
    1743           0 :         return POPT_ERROR_OPTSTOODEEP;
    1744             : 
    1745           0 :     for (argc = 0; argv[argc]; argc++)
    1746             :         {};
    1747             : 
    1748           0 :     con->os++;
    1749           0 :     con->os->next = 0;
    1750           0 :     con->os->nextArg = NULL;
    1751           0 :     con->os->nextCharArg = NULL;
    1752           0 :     con->os->currAlias = NULL;
    1753           0 :     rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
    1754           0 :     con->os->argb = NULL;
    1755           0 :     con->os->stuffed = 1;
    1756             : 
    1757           0 :     return rc;
    1758             : }
    1759             : 
    1760           0 : const char * poptGetInvocationName(poptContext con)
    1761             : {
    1762           0 :     return (con->os->argv ? con->os->argv[0] : "");
    1763             : }
    1764             : 
    1765           0 : int poptStrippedArgv(poptContext con, int argc, char ** argv)
    1766             : {
    1767           0 :     int numargs = argc;
    1768           0 :     int j = 1;
    1769             :     int i;
    1770             :     
    1771             : /*@-sizeoftype@*/
    1772           0 :     if (con->arg_strip)
    1773           0 :     for (i = 1; i < argc; i++) {
    1774           0 :         if (PBM_ISSET(i, con->arg_strip))
    1775           0 :             numargs--;
    1776             :     }
    1777             :     
    1778           0 :     for (i = 1; i < argc; i++) {
    1779           0 :         if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
    1780           0 :             continue;
    1781           0 :         argv[j] = (j < numargs) ? argv[i] : NULL;
    1782           0 :         j++;
    1783             :     }
    1784             : /*@=sizeoftype@*/
    1785             :     
    1786           0 :     return numargs;
    1787             : }

Generated by: LCOV version 1.14