Annotation of embedaddon/rsync/popt/popt.c, revision 1.1.1.2

1.1       misho       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 HAVE_FLOAT_H
                     14: #include <float.h>
                     15: #endif
                     16: #include <math.h>
                     17: 
                     18: #include "findme.h"
                     19: #include "poptint.h"
                     20: 
                     21: #ifndef DBL_EPSILON
                     22: #define DBL_EPSILON 2.2204460492503131e-16
                     23: #endif
                     24: 
                     25: #ifdef MYDEBUG
                     26: /*@unchecked@*/
                     27: int _popt_debug = 0;
                     28: #endif
                     29: 
                     30: #if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
                     31: static char * strerror(int errno)
                     32: {
                     33:     extern int sys_nerr;
                     34:     extern char * sys_errlist[];
                     35: 
                     36:     if ((0 <= errno) && (errno < sys_nerr))
                     37:        return sys_errlist[errno];
                     38:     else
                     39:        return POPT_("unknown errno");
                     40: }
                     41: #endif
                     42: 
                     43: #ifdef MYDEBUG
                     44: /*@unused@*/
                     45: static void prtcon(const char *msg, poptContext con)
                     46: {
                     47:     if (msg) fprintf(stderr, "%s", msg);
                     48:     fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
                     49:        con, con->os,
                     50:        (con->os->nextCharArg ? con->os->nextCharArg : ""),
                     51:        (con->os->nextArg ? con->os->nextArg : ""),
                     52:        con->os->next,
                     53:        (con->os->argv && con->os->argv[con->os->next]
                     54:                ? con->os->argv[con->os->next] : ""));
                     55: }
                     56: #endif
                     57: 
                     58: void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
                     59: {
                     60:     con->execPath = _free(con->execPath);
                     61:     con->execPath = xstrdup(path);
                     62:     con->execAbsolute = allowAbsolute;
                     63:     /*@-nullstate@*/ /* LCL: con->execPath not NULL */
                     64:     return;
                     65:     /*@=nullstate@*/
                     66: }
                     67: 
                     68: static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
                     69:        /*@globals internalState@*/
                     70:        /*@modifies internalState@*/
                     71: {
                     72:     if (opt != NULL)
                     73:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
                     74:        if (opt->arg == NULL) continue;         /* XXX program error. */
                     75:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
                     76:            void * arg = opt->arg;
                     77: /*@-branchstate@*/
                     78:            /* XXX sick hack to preserve pretense of ABI. */
                     79:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
                     80: /*@=branchstate@*/
                     81:            /* Recurse on included sub-tables. */
                     82:            invokeCallbacksPRE(con, arg);
                     83:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
                     84:                   (opt->argInfo & POPT_CBFLAG_PRE))
                     85:        {   /*@-castfcnptr@*/
                     86:            poptCallbackType cb = (poptCallbackType)opt->arg;
                     87:            /*@=castfcnptr@*/
                     88:            /* Perform callback. */
                     89:            /*@-noeffectuncon @*/
                     90:            cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
                     91:            /*@=noeffectuncon @*/
                     92:        }
                     93:     }
                     94: }
                     95: 
                     96: static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
                     97:        /*@globals internalState@*/
                     98:        /*@modifies internalState@*/
                     99: {
                    100:     if (opt != NULL)
                    101:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
                    102:        if (opt->arg == NULL) continue;         /* XXX program error. */
                    103:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
                    104:            void * arg = opt->arg;
                    105: /*@-branchstate@*/
                    106:            /* XXX sick hack to preserve pretense of ABI. */
                    107:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
                    108: /*@=branchstate@*/
                    109:            /* Recurse on included sub-tables. */
                    110:            invokeCallbacksPOST(con, arg);
                    111:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
                    112:                   (opt->argInfo & POPT_CBFLAG_POST))
                    113:        {   /*@-castfcnptr@*/
                    114:            poptCallbackType cb = (poptCallbackType)opt->arg;
                    115:            /*@=castfcnptr@*/
                    116:            /* Perform callback. */
                    117:            /*@-noeffectuncon @*/
                    118:            cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
                    119:            /*@=noeffectuncon @*/
                    120:        }
                    121:     }
                    122: }
                    123: 
                    124: static void invokeCallbacksOPTION(poptContext con,
                    125:                                  const struct poptOption * opt,
                    126:                                  const struct poptOption * myOpt,
                    127:                                  /*@null@*/ const void * myData, int shorty)
                    128:        /*@globals internalState@*/
                    129:        /*@modifies internalState@*/
                    130: {
                    131:     const struct poptOption * cbopt = NULL;
                    132: 
                    133:     if (opt != NULL)
                    134:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
                    135:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
                    136:            void * arg = opt->arg;
                    137: /*@-branchstate@*/
                    138:            /* XXX sick hack to preserve pretense of ABI. */
                    139:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
                    140: /*@=branchstate@*/
                    141:            /* Recurse on included sub-tables. */
                    142:            if (opt->arg != NULL)       /* XXX program error */
                    143:                invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
                    144:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
                    145:                  !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
                    146:            /* Save callback info. */
                    147:            cbopt = opt;
                    148:        } else if (cbopt != NULL &&
                    149:                   ((myOpt->shortName && opt->shortName && shorty &&
                    150:                        myOpt->shortName == opt->shortName) ||
                    151:                    (myOpt->longName && opt->longName &&
                    152:                /*@-nullpass@*/         /* LCL: opt->longName != NULL */
                    153:                        !strcmp(myOpt->longName, opt->longName)))
                    154:                /*@=nullpass@*/
                    155:                   )
                    156:        {   /*@-castfcnptr@*/
                    157:            poptCallbackType cb = (poptCallbackType)cbopt->arg;
                    158:            /*@=castfcnptr@*/
                    159:            const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
                    160:            /* Perform callback. */
                    161:            if (cb != NULL) {   /* XXX program error */
                    162:                /*@-noeffectuncon @*/
                    163:                cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
                    164:                        con->os->nextArg, cbData);
                    165:                /*@=noeffectuncon @*/
                    166:            }
                    167:            /* Terminate (unless explcitly continuing). */
                    168:            if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
                    169:                return;
                    170:        }
                    171:     }
                    172: }
                    173: 
                    174: poptContext poptGetContext(const char * name, int argc, const char ** argv,
                    175:                           const struct poptOption * options, int flags)
                    176: {
                    177:     poptContext con = malloc(sizeof(*con));
                    178: 
                    179:     if (con == NULL) return NULL;      /* XXX can't happen */
                    180:     memset(con, 0, sizeof(*con));
                    181: 
                    182:     con->os = con->optionStack;
                    183:     con->os->argc = argc;
                    184:     /*@-dependenttrans -assignexpose@*/        /* FIX: W2DO? */
                    185:     con->os->argv = argv;
                    186:     /*@=dependenttrans =assignexpose@*/
                    187:     con->os->argb = NULL;
                    188: 
                    189:     if (!(flags & POPT_CONTEXT_KEEP_FIRST))
                    190:        con->os->next = 1;                      /* skip argv[0] */
                    191: 
                    192:     con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
                    193:     /*@-dependenttrans -assignexpose@*/        /* FIX: W2DO? */
                    194:     con->options = options;
                    195:     /*@=dependenttrans =assignexpose@*/
                    196:     con->aliases = NULL;
                    197:     con->numAliases = 0;
                    198:     con->flags = flags;
                    199:     con->execs = NULL;
                    200:     con->numExecs = 0;
                    201:     con->finalArgvAlloced = argc * 2;
                    202:     con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
                    203:     con->execAbsolute = 1;
                    204:     con->arg_strip = NULL;
                    205: 
                    206:     if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
                    207:        con->flags |= POPT_CONTEXT_POSIXMEHARDER;
                    208: 
                    209:     if (name) {
                    210:        size_t bufsize = strlen(name) + 1;
                    211:        char * t = malloc(bufsize);
                    212:        if (t) {
                    213:            strlcpy(t, name, bufsize);
                    214:            con->appName = t;
                    215:        }
                    216:     }
                    217: 
                    218:     /*@-internalglobs@*/
                    219:     invokeCallbacksPRE(con, con->options);
                    220:     /*@=internalglobs@*/
                    221: 
                    222:     return con;
                    223: }
                    224: 
                    225: static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
                    226:        /*@uses os @*/
                    227:        /*@releases os->nextArg, os->argv, os->argb @*/
                    228:        /*@modifies os @*/
                    229: {
                    230:     os->nextArg = _free(os->nextArg);
                    231:     os->argv = _free(os->argv);
                    232:     os->argb = PBM_FREE(os->argb);
                    233: }
                    234: 
                    235: /*@-boundswrite@*/
                    236: void poptResetContext(poptContext con)
                    237: {
                    238:     int i;
                    239: 
                    240:     if (con == NULL) return;
                    241:     while (con->os > con->optionStack) {
                    242:        cleanOSE(con->os--);
                    243:     }
                    244:     con->os->argb = PBM_FREE(con->os->argb);
                    245:     con->os->currAlias = NULL;
                    246:     con->os->nextCharArg = NULL;
                    247:     con->os->nextArg = NULL;
                    248:     con->os->next = 1;                 /* skip argv[0] */
                    249: 
                    250:     con->numLeftovers = 0;
                    251:     con->nextLeftover = 0;
                    252:     con->restLeftover = 0;
                    253:     con->doExec = NULL;
                    254: 
                    255:     if (con->finalArgv != NULL)
                    256:     for (i = 0; i < con->finalArgvCount; i++) {
                    257:        /*@-unqualifiedtrans@*/         /* FIX: typedef double indirection. */
                    258:        con->finalArgv[i] = _free(con->finalArgv[i]);
                    259:        /*@=unqualifiedtrans@*/
                    260:     }
                    261: 
                    262:     con->finalArgvCount = 0;
                    263:     con->arg_strip = PBM_FREE(con->arg_strip);
                    264:     /*@-nullstate@*/   /* FIX: con->finalArgv != NULL */
                    265:     return;
                    266:     /*@=nullstate@*/
                    267: }
                    268: /*@=boundswrite@*/
                    269: 
                    270: /* Only one of longName, shortName should be set, not both. */
                    271: /*@-boundswrite@*/
                    272: static int handleExec(/*@special@*/ poptContext con,
                    273:                /*@null@*/ const char * longName, char shortName)
                    274:        /*@uses con->execs, con->numExecs, con->flags, con->doExec,
                    275:                con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
                    276:        /*@modifies con @*/
                    277: {
                    278:     poptItem item;
                    279:     int i;
                    280: 
                    281:     if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */
                    282:        return 0;
                    283: 
                    284:     for (i = con->numExecs - 1; i >= 0; i--) {
                    285:        item = con->execs + i;
                    286:        if (longName && !(item->option.longName &&
                    287:                        !strcmp(longName, item->option.longName)))
                    288:            continue;
                    289:        else if (shortName != item->option.shortName)
                    290:            continue;
                    291:        break;
                    292:     }
                    293:     if (i < 0) return 0;
                    294: 
                    295: 
                    296:     if (con->flags & POPT_CONTEXT_NO_EXEC)
                    297:        return 1;
                    298: 
                    299:     if (con->doExec == NULL) {
                    300:        con->doExec = con->execs + i;
                    301:        return 1;
                    302:     }
                    303: 
                    304:     /* We already have an exec to do; remember this option for next
                    305:        time 'round */
                    306:     if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
                    307:        con->finalArgvAlloced += 10;
                    308:        con->finalArgv = realloc(con->finalArgv,
                    309:                        sizeof(*con->finalArgv) * con->finalArgvAlloced);
                    310:     }
                    311: 
                    312:     i = con->finalArgvCount++;
                    313:     if (con->finalArgv != NULL)        /* XXX can't happen */
                    314:     {  size_t bufsize = (longName ? strlen(longName) : 0) + 3;
                    315:        char *s  = malloc(bufsize);
                    316:        if (s != NULL) {        /* XXX can't happen */
                    317:            if (longName)
                    318:                snprintf(s, bufsize, "--%s", longName);
                    319:            else
                    320:                snprintf(s, bufsize, "-%c", shortName);
                    321:            con->finalArgv[i] = s;
                    322:        } else
                    323:            con->finalArgv[i] = NULL;
                    324:     }
                    325: 
                    326:     /*@-nullstate@*/   /* FIX: con->finalArgv[] == NULL */
                    327:     return 1;
                    328:     /*@=nullstate@*/
                    329: }
                    330: /*@=boundswrite@*/
                    331: 
                    332: /* Only one of longName, shortName may be set at a time */
                    333: static int handleAlias(/*@special@*/ poptContext con,
                    334:                /*@null@*/ const char * longName, char shortName,
                    335:                /*@exposed@*/ /*@null@*/ const char * nextCharArg)
                    336:        /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
                    337:                con->os->currAlias, con->os->currAlias->option.longName @*/
                    338:        /*@modifies con @*/
                    339: {
                    340:     poptItem item = con->os->currAlias;
                    341:     int rc;
                    342:     int i;
                    343: 
                    344:     if (item) {
                    345:        if (longName && (item->option.longName &&
                    346:                !strcmp(longName, item->option.longName)))
                    347:            return 0;
                    348:        if (shortName && shortName == item->option.shortName)
                    349:            return 0;
                    350:     }
                    351: 
                    352:     if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */
                    353:        return 0;
                    354: 
                    355:     for (i = con->numAliases - 1; i >= 0; i--) {
                    356:        item = con->aliases + i;
                    357:        if (longName && !(item->option.longName &&
                    358:                        !strcmp(longName, item->option.longName)))
                    359:            continue;
                    360:        else if (shortName != item->option.shortName)
                    361:            continue;
                    362:        break;
                    363:     }
                    364:     if (i < 0) return 0;
                    365: 
                    366:     if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
                    367:        return POPT_ERROR_OPTSTOODEEP;
                    368: 
                    369: /*@-boundsread@*/
                    370:     if (nextCharArg && *nextCharArg)
                    371:        con->os->nextCharArg = nextCharArg;
                    372: /*@=boundsread@*/
                    373: 
                    374:     con->os++;
                    375:     con->os->next = 0;
                    376:     con->os->stuffed = 0;
                    377:     con->os->nextArg = NULL;
                    378:     con->os->nextCharArg = NULL;
                    379:     con->os->currAlias = con->aliases + i;
                    380:     rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
                    381:                &con->os->argc, &con->os->argv);
                    382:     con->os->argb = NULL;
                    383: 
                    384:     return (rc ? rc : 1);
                    385: }
                    386: 
                    387: /*@-bounds -boundswrite @*/
                    388: static int execCommand(poptContext con)
                    389:        /*@globals internalState @*/
                    390:        /*@modifies internalState @*/
                    391: {
                    392:     poptItem item = con->doExec;
                    393:     const char ** argv;
                    394:     int argc = 0;
                    395: 
                    396:     if (item == NULL) /*XXX can't happen*/
                    397:        return POPT_ERROR_NOARG;
                    398: 
                    399:     if (item->argv == NULL || item->argc < 1 ||
                    400:        (!con->execAbsolute && strchr(item->argv[0], '/')))
                    401:            return POPT_ERROR_NOARG;
                    402: 
                    403:     argv = malloc(sizeof(*argv) *
                    404:                        (6 + item->argc + con->numLeftovers + con->finalArgvCount));
                    405:     if (argv == NULL) return POPT_ERROR_MALLOC;
                    406: 
                    407:     if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
                    408:        size_t bufsize = strlen(con->execPath) + strlen(item->argv[0]) + sizeof "/";
                    409:        char *s = alloca(bufsize);
                    410:        snprintf(s, bufsize, "%s/%s", con->execPath, item->argv[0]);
                    411:        argv[argc] = s;
                    412:     } else
                    413:        argv[argc] = findProgramPath(item->argv[0]);
                    414:     if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
                    415: 
                    416:     if (item->argc > 1) {
                    417:        memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
                    418:        argc += (item->argc - 1);
                    419:     }
                    420: 
                    421:     if (con->finalArgv != NULL && con->finalArgvCount > 0) {
                    422:        memcpy(argv + argc, con->finalArgv,
                    423:                sizeof(*argv) * con->finalArgvCount);
                    424:        argc += con->finalArgvCount;
                    425:     }
                    426: 
                    427:     if (con->leftovers != NULL && con->numLeftovers > 0) {
                    428:        memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
                    429:        argc += con->numLeftovers;
                    430:     }
                    431: 
                    432:     argv[argc] = NULL;
                    433: 
                    434:   {
                    435: #ifdef __hpux
                    436:     int rc = setresgid(getgid(), getgid(),-1);
                    437:     if (rc) return POPT_ERROR_ERRNO;
                    438:     rc = setresuid(getuid(), getuid(),-1);
                    439:     if (rc) return POPT_ERROR_ERRNO;
                    440: #else
                    441: /*
                    442:  * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
                    443:  * XXX         sez' Timur Bakeyev <mc@bat.ru>
                    444:  * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
                    445:  */
                    446: #if defined(HAVE_SETUID)
                    447:     int rc = setgid(getgid());
                    448:     if (rc) return POPT_ERROR_ERRNO;
                    449:     rc = setuid(getuid());
                    450:     if (rc) return POPT_ERROR_ERRNO;
                    451: #elif defined (HAVE_SETREUID)
                    452:     int rc = setregid(getgid(), getgid());
                    453:     if (rc) return POPT_ERROR_ERRNO;
                    454:     rc = setreuid(getuid(), getuid());
                    455:     if (rc) return POPT_ERROR_ERRNO;
                    456: #else
                    457:     ; /* Can't drop privileges */
                    458: #endif
                    459: #endif
                    460:   }
                    461: 
                    462:     if (argv[0] == NULL)
                    463:        return POPT_ERROR_NOARG;
                    464: 
                    465: #ifdef MYDEBUG
                    466: if (_popt_debug)
                    467:     {  const char ** avp;
                    468:        fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
                    469:        for (avp = argv; *avp; avp++)
                    470:            fprintf(stderr, " '%s'", *avp);
                    471:        fprintf(stderr, "\n");
                    472:     }
                    473: #endif
                    474: 
                    475:     execvp(argv[0], (char *const *)argv);
                    476: 
                    477:     return POPT_ERROR_ERRNO;
                    478: }
                    479: /*@=bounds =boundswrite @*/
                    480: 
                    481: /*@-boundswrite@*/
                    482: /*@observer@*/ /*@null@*/ static const struct poptOption *
                    483: findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
                    484:                char shortName,
                    485:                /*@null@*/ /*@out@*/ poptCallbackType * callback,
                    486:                /*@null@*/ /*@out@*/ const void ** callbackData,
                    487:                int singleDash)
                    488:        /*@modifies *callback, *callbackData */
                    489: {
                    490:     const struct poptOption * cb = NULL;
                    491: 
                    492:     /* This happens when a single - is given */
                    493:     if (singleDash && !shortName && (longName && *longName == '\0'))
                    494:        shortName = '-';
                    495: 
                    496:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
                    497: 
                    498:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
                    499:            const struct poptOption * opt2;
                    500:            void * arg = opt->arg;
                    501: 
                    502: /*@-branchstate@*/
                    503:            /* XXX sick hack to preserve pretense of ABI. */
                    504:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
                    505: /*@=branchstate@*/
                    506:            /* Recurse on included sub-tables. */
                    507:            if (arg == NULL) continue;  /* XXX program error */
                    508:            opt2 = findOption(arg, longName, shortName, callback,
                    509:                              callbackData, singleDash);
                    510:            if (opt2 == NULL) continue;
                    511:            /* Sub-table data will be inheirited if no data yet. */
                    512:            if (!(callback && *callback)) return opt2;
                    513:            if (!(callbackData && *callbackData == NULL)) return opt2;
                    514:            /*@-observertrans -dependenttrans @*/
                    515:            *callbackData = opt->descrip;
                    516:            /*@=observertrans =dependenttrans @*/
                    517:            return opt2;
                    518:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
                    519:            cb = opt;
                    520:        } else if (longName && opt->longName &&
                    521:                   (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
                    522:                /*@-nullpass@*/         /* LCL: opt->longName != NULL */
                    523:                   !strcmp(longName, opt->longName))
                    524:                /*@=nullpass@*/
                    525:        {
                    526:            break;
                    527:        } else if (shortName && shortName == opt->shortName) {
                    528:            break;
                    529:        }
                    530:     }
                    531: 
                    532:     if (!opt->longName && !opt->shortName)
                    533:        return NULL;
                    534:     /*@-modobserver -mods @*/
                    535:     if (callback) *callback = NULL;
                    536:     if (callbackData) *callbackData = NULL;
                    537:     if (cb) {
                    538:        if (callback)
                    539:        /*@-castfcnptr@*/
                    540:            *callback = (poptCallbackType)cb->arg;
                    541:        /*@=castfcnptr@*/
                    542:        if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) {
                    543:            if (callbackData)
                    544:                /*@-observertrans@*/    /* FIX: typedef double indirection. */
                    545:                *callbackData = cb->descrip;
                    546:                /*@=observertrans@*/
                    547:        }
                    548:     }
                    549:     /*@=modobserver =mods @*/
                    550: 
                    551:     return opt;
                    552: }
                    553: /*@=boundswrite@*/
                    554: 
                    555: static const char * findNextArg(/*@special@*/ poptContext con,
                    556:                unsigned argx, int delete_arg)
                    557:        /*@uses con->optionStack, con->os,
                    558:                con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
                    559:        /*@modifies con @*/
                    560: {
                    561:     struct optionStackEntry * os = con->os;
                    562:     const char * arg;
                    563: 
                    564:     do {
                    565:        int i;
                    566:        arg = NULL;
                    567:        while (os->next == os->argc && os > con->optionStack) os--;
                    568:        if (os->next == os->argc && os == con->optionStack) break;
                    569:        if (os->argv != NULL)
                    570:        for (i = os->next; i < os->argc; i++) {
                    571:            /*@-sizeoftype@*/
                    572:            if (os->argb && PBM_ISSET(i, os->argb))
                    573:                /*@innercontinue@*/ continue;
                    574:            if (*os->argv[i] == '-')
                    575:                /*@innercontinue@*/ continue;
                    576:            if (--argx > 0)
                    577:                /*@innercontinue@*/ continue;
                    578:            arg = os->argv[i];
                    579:            if (delete_arg) {
                    580:                if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
                    581:                if (os->argb != NULL)   /* XXX can't happen */
                    582:                PBM_SET(i, os->argb);
                    583:            }
                    584:            /*@innerbreak@*/ break;
                    585:            /*@=sizeoftype@*/
                    586:        }
                    587:        if (os > con->optionStack) os--;
                    588:     } while (arg == NULL);
                    589:     return arg;
                    590: }
                    591: 
                    592: /*@-boundswrite@*/
                    593: static /*@only@*/ /*@null@*/ const char *
                    594: expandNextArg(/*@special@*/ poptContext con, const char * s)
                    595:        /*@uses con->optionStack, con->os,
                    596:                con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
                    597:        /*@modifies con @*/
                    598: {
                    599:     const char * a = NULL;
                    600:     size_t alen, pos;
                    601:     char *t, *te;
                    602:     size_t tn = strlen(s) + 1;
                    603:     char c;
                    604: 
                    605:     te = t = malloc(tn);;
                    606:     if (t == NULL) return NULL;                /* XXX can't happen */
                    607:     while ((c = *s++) != '\0') {
                    608:        switch (c) {
                    609: #if 0  /* XXX can't do this */
                    610:        case '\\':      /* escape */
                    611:            c = *s++;
                    612:            /*@switchbreak@*/ break;
                    613: #endif
                    614:        case '!':
                    615:            if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
                    616:                /*@switchbreak@*/ break;
                    617:            /* XXX Make sure that findNextArg deletes only next arg. */
                    618:            if (a == NULL) {
                    619:                if ((a = findNextArg(con, 1, 1)) == NULL)
                    620:                    /*@switchbreak@*/ break;
                    621:            }
                    622:            s += 3;
                    623: 
                    624:            alen = strlen(a);
                    625:            tn += alen;
                    626:            pos = te - t;
                    627:            t = realloc(t, tn);
                    628:            te = t + pos;
1.1.1.2 ! misho     629:            memcpy(te, a, alen+1); te += alen;
1.1       misho     630:            continue;
                    631:            /*@notreached@*/ /*@switchbreak@*/ break;
                    632:        default:
                    633:            /*@switchbreak@*/ break;
                    634:        }
                    635:        *te++ = c;
                    636:     }
                    637:     *te = '\0';
                    638:     t = realloc(t, strlen(t) + 1);     /* XXX memory leak, hard to plug */
                    639:     return t;
                    640: }
                    641: /*@=boundswrite@*/
                    642: 
                    643: static void poptStripArg(/*@special@*/ poptContext con, int which)
                    644:        /*@uses con->arg_strip, con->optionStack @*/
                    645:        /*@defines con->arg_strip @*/
                    646:        /*@modifies con @*/
                    647: {
                    648:     /*@-sizeoftype@*/
                    649:     if (con->arg_strip == NULL)
                    650:        con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
                    651:     if (con->arg_strip != NULL)                /* XXX can't happen */
                    652:     PBM_SET(which, con->arg_strip);
                    653:     /*@=sizeoftype@*/
                    654:     /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
                    655:     return;
                    656:     /*@=compdef@*/
                    657: }
                    658: 
                    659: int poptSaveLong(long * arg, int argInfo, long aLong)
                    660: {
                    661:     /* XXX Check alignment, may fail on funky platforms. */
                    662:     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
                    663:        return POPT_ERROR_NULLARG;
                    664: 
                    665:     if (argInfo & POPT_ARGFLAG_NOT)
                    666:        aLong = ~aLong;
                    667:     switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
                    668:     case 0:
                    669:        *arg = aLong;
                    670:        break;
                    671:     case POPT_ARGFLAG_OR:
                    672:        *arg |= aLong;
                    673:        break;
                    674:     case POPT_ARGFLAG_AND:
                    675:        *arg &= aLong;
                    676:        break;
                    677:     case POPT_ARGFLAG_XOR:
                    678:        *arg ^= aLong;
                    679:        break;
                    680:     default:
                    681:        return POPT_ERROR_BADOPERATION;
                    682:        /*@notreached@*/ break;
                    683:     }
                    684:     return 0;
                    685: }
                    686: 
                    687: int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
                    688: {
                    689:     /* XXX Check alignment, may fail on funky platforms. */
                    690:     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
                    691:        return POPT_ERROR_NULLARG;
                    692: 
                    693:     if (argInfo & POPT_ARGFLAG_NOT)
                    694:        aLong = ~aLong;
                    695:     switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
                    696:     case 0:
                    697:        *arg = aLong;
                    698:        break;
                    699:     case POPT_ARGFLAG_OR:
                    700:        *arg |= aLong;
                    701:        break;
                    702:     case POPT_ARGFLAG_AND:
                    703:        *arg &= aLong;
                    704:        break;
                    705:     case POPT_ARGFLAG_XOR:
                    706:        *arg ^= aLong;
                    707:        break;
                    708:     default:
                    709:        return POPT_ERROR_BADOPERATION;
                    710:        /*@notreached@*/ break;
                    711:     }
                    712:     return 0;
                    713: }
                    714: 
                    715: /*@-boundswrite@*/
                    716: /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
                    717: int poptGetNextOpt(poptContext con)
                    718: {
                    719:     const struct poptOption * opt = NULL;
                    720:     int done = 0;
                    721: 
                    722:     if (con == NULL)
                    723:        return -1;
                    724:     while (!done) {
                    725:        const char * origOptString = NULL;
                    726:        poptCallbackType cb = NULL;
                    727:        const void * cbData = NULL;
                    728:        const char * longArg = NULL;
                    729:        int canstrip = 0;
                    730:        int shorty = 0;
                    731: 
                    732:        while (!con->os->nextCharArg && con->os->next == con->os->argc
                    733:                && con->os > con->optionStack) {
                    734:            cleanOSE(con->os--);
                    735:        }
                    736:        if (!con->os->nextCharArg && con->os->next == con->os->argc) {
                    737:            /*@-internalglobs@*/
                    738:            invokeCallbacksPOST(con, con->options);
                    739:            /*@=internalglobs@*/
                    740:            if (con->doExec) return execCommand(con);
                    741:            return -1;
                    742:        }
                    743: 
                    744:        /* Process next long option */
                    745:        if (!con->os->nextCharArg) {
                    746:            char * localOptString, * optString;
                    747:            int thisopt;
                    748: 
                    749:            /*@-sizeoftype@*/
                    750:            if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
                    751:                con->os->next++;
                    752:                continue;
                    753:            }
                    754:            /*@=sizeoftype@*/
                    755:            thisopt = con->os->next;
                    756:            if (con->os->argv != NULL)  /* XXX can't happen */
                    757:            origOptString = con->os->argv[con->os->next++];
                    758: 
                    759:            if (origOptString == NULL)  /* XXX can't happen */
                    760:                return POPT_ERROR_BADOPT;
                    761: 
                    762:            if (con->restLeftover || *origOptString != '-') {
                    763:                if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
                    764:                    con->restLeftover = 1;
                    765:                if (con->flags & POPT_CONTEXT_ARG_OPTS) {
                    766:                    con->os->nextArg = xstrdup(origOptString);
                    767:                    return 0;
                    768:                }
                    769:                if (con->leftovers != NULL)     /* XXX can't happen */
                    770:                    con->leftovers[con->numLeftovers++] = origOptString;
                    771:                continue;
                    772:            }
                    773: 
                    774:            /* Make a copy we can hack at */
                    775:            {   size_t bufsize = strlen(origOptString) + 1;
                    776:                localOptString = optString = alloca(bufsize);
                    777:                if (optString == NULL) /* XXX can't happen */
                    778:                    return POPT_ERROR_BADOPT;
                    779:                strlcpy(optString, origOptString, bufsize);
                    780:            }
                    781: 
                    782:            if (optString[0] == '\0')
                    783:                return POPT_ERROR_BADOPT;
                    784: 
                    785:            if (optString[1] == '-' && !optString[2]) {
                    786:                con->restLeftover = 1;
                    787:                continue;
                    788:            } else {
                    789:                char *oe;
                    790:                int singleDash;
                    791: 
                    792:                optString++;
                    793:                if (*optString == '-')
                    794:                    singleDash = 0, optString++;
                    795:                else
                    796:                    singleDash = 1;
                    797: 
                    798:                /* XXX aliases with arg substitution need "--alias=arg" */
                    799:                if (handleAlias(con, optString, '\0', NULL))
                    800:                    continue;
                    801: 
                    802:                if (handleExec(con, optString, '\0'))
                    803:                    continue;
                    804: 
                    805:                /* Check for "--long=arg" option. */
                    806:                for (oe = optString; *oe && *oe != '='; oe++)
                    807:                    {};
                    808:                if (*oe == '=') {
                    809:                    *oe++ = '\0';
                    810:                    /* XXX longArg is mapped back to persistent storage. */
                    811:                    longArg = origOptString + (oe - localOptString);
                    812:                } else
                    813:                    oe = NULL;
                    814: 
                    815:                opt = findOption(con->options, optString, '\0', &cb, &cbData,
                    816:                                 singleDash);
                    817:                if (!opt && !singleDash)
                    818:                    return POPT_ERROR_BADOPT;
                    819:                if (!opt && oe)
                    820:                    oe[-1] = '='; /* restore overwritten '=' */
                    821:            }
                    822: 
                    823:            if (!opt) {
                    824:                con->os->nextCharArg = origOptString + 1;
                    825:                longArg = NULL;
                    826:            } else {
                    827:                if (con->os == con->optionStack &&
                    828:                   opt->argInfo & POPT_ARGFLAG_STRIP)
                    829:                {
                    830:                    canstrip = 1;
                    831:                    poptStripArg(con, thisopt);
                    832:                }
                    833:                shorty = 0;
                    834:            }
                    835:        }
                    836: 
                    837:        /* Process next short option */
                    838:        /*@-branchstate@*/              /* FIX: W2DO? */
                    839:        if (con->os->nextCharArg) {
                    840:            origOptString = con->os->nextCharArg;
                    841: 
                    842:            con->os->nextCharArg = NULL;
                    843: 
                    844:            if (handleAlias(con, NULL, *origOptString, origOptString + 1))
                    845:                continue;
                    846: 
                    847:            if (handleExec(con, NULL, *origOptString)) {
                    848:                /* Restore rest of short options for further processing */
                    849:                origOptString++;
                    850:                if (*origOptString != '\0')
                    851:                    con->os->nextCharArg = origOptString;
                    852:                continue;
                    853:            }
                    854: 
                    855:            opt = findOption(con->options, NULL, *origOptString, &cb,
                    856:                             &cbData, 0);
                    857:            if (!opt)
                    858:                return POPT_ERROR_BADOPT;
                    859:            shorty = 1;
                    860: 
                    861:            origOptString++;
                    862:            if (*origOptString != '\0')
                    863:                con->os->nextCharArg = origOptString;
                    864:        }
                    865:        /*@=branchstate@*/
                    866: 
                    867:        if (opt == NULL) return POPT_ERROR_BADOPT;      /* XXX can't happen */
                    868:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
                    869:         || (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
                    870:            if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
                    871:                return POPT_ERROR_UNWANTEDARG;
                    872:            if (opt->arg) {
                    873:                long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
                    874:                if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
                    875:                    return POPT_ERROR_BADOPERATION;
                    876:            }
                    877:        } else {
                    878:            con->os->nextArg = _free(con->os->nextArg);
                    879:            /*@-usedef@*/       /* FIX: W2DO? */
                    880:            if (longArg) {
                    881:            /*@=usedef@*/
                    882:                longArg = expandNextArg(con, longArg);
                    883:                con->os->nextArg = longArg;
                    884:            } else if (con->os->nextCharArg) {
                    885:                longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
                    886:                con->os->nextArg = longArg;
                    887:                con->os->nextCharArg = NULL;
                    888:            } else {
                    889:                while (con->os->next == con->os->argc &&
                    890:                       con->os > con->optionStack) {
                    891:                    cleanOSE(con->os--);
                    892:                }
                    893:                if (con->os->next == con->os->argc) {
                    894:                    if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL))
                    895:                        /*@-compdef@*/  /* FIX: con->os->argv not defined */
                    896:                        return POPT_ERROR_NOARG;
                    897:                        /*@=compdef@*/
                    898:                    con->os->nextArg = NULL;
                    899:                } else {
                    900: 
                    901:                    /*
                    902:                     * Make sure this isn't part of a short arg or the
                    903:                     * result of an alias expansion.
                    904:                     */
                    905:                    if (con->os == con->optionStack &&
                    906:                        (opt->argInfo & POPT_ARGFLAG_STRIP) &&
                    907:                        canstrip) {
                    908:                        poptStripArg(con, con->os->next);
                    909:                    }
                    910:                
                    911:                    if (con->os->argv != NULL) {        /* XXX can't happen */
                    912:                        /* XXX watchout: subtle side-effects live here. */
                    913:                        longArg = con->os->argv[con->os->next++];
                    914:                        longArg = expandNextArg(con, longArg);
                    915:                        con->os->nextArg = longArg;
                    916:                    }
                    917:                }
                    918:            }
                    919:            longArg = NULL;
                    920: 
                    921:            if (opt->arg) {
                    922:                switch (opt->argInfo & POPT_ARG_MASK) {
                    923:                case POPT_ARG_STRING:
                    924:                    /* XXX memory leak, hard to plug */
                    925:                    *((const char **) opt->arg) = (con->os->nextArg)
                    926:                        ? xstrdup(con->os->nextArg) : NULL;
                    927:                    /*@switchbreak@*/ break;
                    928: 
                    929:                case POPT_ARG_INT:
                    930:                case POPT_ARG_LONG:
                    931:                {   long aLong = 0;
                    932:                    char *end;
                    933: 
                    934:                    if (con->os->nextArg) {
                    935:                        aLong = strtol(con->os->nextArg, &end, 0);
                    936:                        if (!(end && *end == '\0'))
                    937:                            return POPT_ERROR_BADNUMBER;
                    938:                    }
                    939: 
                    940:                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
                    941:                        if (aLong == LONG_MIN || aLong == LONG_MAX)
                    942:                            return POPT_ERROR_OVERFLOW;
                    943:                        if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
                    944:                            return POPT_ERROR_BADOPERATION;
                    945:                    } else {
                    946:                        if (aLong > INT_MAX || aLong < INT_MIN)
                    947:                            return POPT_ERROR_OVERFLOW;
                    948:                        if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
                    949:                            return POPT_ERROR_BADOPERATION;
                    950:                    }
                    951:                }   /*@switchbreak@*/ break;
                    952: 
                    953:                case POPT_ARG_FLOAT:
                    954:                case POPT_ARG_DOUBLE:
                    955:                {   double aDouble = 0.0;
                    956:                    char *end;
                    957: 
                    958:                    if (con->os->nextArg) {
                    959:                        /*@-mods@*/
                    960:                        int saveerrno = errno;
                    961:                        errno = 0;
                    962:                        aDouble = strtod(con->os->nextArg, &end);
                    963:                        if (errno == ERANGE)
                    964:                            return POPT_ERROR_OVERFLOW;
                    965:                        errno = saveerrno;
                    966:                        /*@=mods@*/
                    967:                        if (*end != '\0')
                    968:                            return POPT_ERROR_BADNUMBER;
                    969:                    }
                    970: 
                    971:                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
                    972:                        *((double *) opt->arg) = aDouble;
                    973:                    } else {
                    974: #define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
                    975:                        if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
                    976:                            return POPT_ERROR_OVERFLOW;
                    977:                        if ((FLT_MIN - MY_ABS(aDouble)) > DBL_EPSILON)
                    978:                            return POPT_ERROR_OVERFLOW;
                    979:                        *((float *) opt->arg) = aDouble;
                    980:                    }
                    981:                }   /*@switchbreak@*/ break;
                    982:                default:
                    983:                    fprintf(stdout,
                    984:                        POPT_("option type (%d) not implemented in popt\n"),
                    985:                        (opt->argInfo & POPT_ARG_MASK));
                    986:                    exit(EXIT_FAILURE);
                    987:                    /*@notreached@*/ /*@switchbreak@*/ break;
                    988:                }
                    989:            }
                    990:        }
                    991: 
                    992:        if (cb) {
                    993:            /*@-internalglobs@*/
                    994:            invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
                    995:            /*@=internalglobs@*/
                    996:        } else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
                    997:            done = 1;
                    998: 
                    999:        if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
                   1000:            con->finalArgvAlloced += 10;
                   1001:            con->finalArgv = realloc(con->finalArgv,
                   1002:                            sizeof(*con->finalArgv) * con->finalArgvAlloced);
                   1003:        }
                   1004: 
                   1005:        if (con->finalArgv != NULL)
                   1006:        {   ssize_t bufsize = (opt->longName ? strlen(opt->longName) : 0) + 3;
                   1007:            char *s = malloc(bufsize);
                   1008:            if (s != NULL) {    /* XXX can't happen */
                   1009:                if (opt->longName)
                   1010:                    snprintf(s, bufsize, "%s%s",
                   1011:                        ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
                   1012:                        opt->longName);
                   1013:                else
                   1014:                    snprintf(s, bufsize, "-%c", opt->shortName);
                   1015:                con->finalArgv[con->finalArgvCount++] = s;
                   1016:            } else
                   1017:                con->finalArgv[con->finalArgvCount++] = NULL;
                   1018:        }
                   1019: 
                   1020:        if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
                   1021:            /*@-ifempty@*/ ; /*@=ifempty@*/
                   1022:        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
                   1023:            /*@-ifempty@*/ ; /*@=ifempty@*/
                   1024:        else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
                   1025:            if (con->finalArgv != NULL && con->os->nextArg)
                   1026:                con->finalArgv[con->finalArgvCount++] =
                   1027:                        /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
                   1028:                        xstrdup(con->os->nextArg);
                   1029:                        /*@=nullpass@*/
                   1030:        }
                   1031:     }
                   1032: 
                   1033:     return (opt ? opt->val : -1);      /* XXX can't happen */
                   1034: }
                   1035: /*@=boundswrite@*/
                   1036: 
                   1037: const char * poptGetOptArg(poptContext con)
                   1038: {
                   1039:     const char * ret = NULL;
                   1040:     /*@-branchstate@*/
                   1041:     if (con) {
                   1042:        ret = con->os->nextArg;
                   1043:        con->os->nextArg = NULL;
                   1044:     }
                   1045:     /*@=branchstate@*/
                   1046:     return ret;
                   1047: }
                   1048: 
                   1049: const char * poptGetArg(poptContext con)
                   1050: {
                   1051:     const char * ret = NULL;
                   1052:     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
                   1053:        ret = con->leftovers[con->nextLeftover++];
                   1054:     return ret;
                   1055: }
                   1056: 
                   1057: const char * poptPeekArg(poptContext con)
                   1058: {
                   1059:     const char * ret = NULL;
                   1060:     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
                   1061:        ret = con->leftovers[con->nextLeftover];
                   1062:     return ret;
                   1063: }
                   1064: 
                   1065: /*@-boundswrite@*/
                   1066: const char ** poptGetArgs(poptContext con)
                   1067: {
                   1068:     if (con == NULL ||
                   1069:        con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
                   1070:        return NULL;
                   1071: 
                   1072:     /* some apps like [like RPM ;-) ] need this NULL terminated */
                   1073:     con->leftovers[con->numLeftovers] = NULL;
                   1074: 
                   1075:     /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
                   1076:     return (con->leftovers + con->nextLeftover);
                   1077:     /*@=nullret =nullstate @*/
                   1078: }
                   1079: /*@=boundswrite@*/
                   1080: 
                   1081: poptContext poptFreeContext(poptContext con)
                   1082: {
                   1083:     poptItem item;
                   1084:     int i;
                   1085: 
                   1086:     if (con == NULL) return con;
                   1087:     poptResetContext(con);
                   1088:     con->os->argb = _free(con->os->argb);
                   1089: 
                   1090:     if (con->aliases != NULL)
                   1091:     for (i = 0; i < con->numAliases; i++) {
                   1092:        item = con->aliases + i;
                   1093:        /*@-modobserver -observertrans -dependenttrans@*/
                   1094:        item->option.longName = _free(item->option.longName);
                   1095:        item->option.descrip = _free(item->option.descrip);
                   1096:        item->option.argDescrip = _free(item->option.argDescrip);
                   1097:        /*@=modobserver =observertrans =dependenttrans@*/
                   1098:        item->argv = _free(item->argv);
                   1099:     }
                   1100:     con->aliases = _free(con->aliases);
                   1101: 
                   1102:     if (con->execs != NULL)
                   1103:     for (i = 0; i < con->numExecs; i++) {
                   1104:        item = con->execs + i;
                   1105:        /*@-modobserver -observertrans -dependenttrans@*/
                   1106:        item->option.longName = _free(item->option.longName);
                   1107:        item->option.descrip = _free(item->option.descrip);
                   1108:        item->option.argDescrip = _free(item->option.argDescrip);
                   1109:        /*@=modobserver =observertrans =dependenttrans@*/
                   1110:        item->argv = _free(item->argv);
                   1111:     }
                   1112:     con->execs = _free(con->execs);
                   1113: 
                   1114:     con->leftovers = _free(con->leftovers);
                   1115:     con->finalArgv = _free(con->finalArgv);
                   1116:     con->appName = _free(con->appName);
                   1117:     con->otherHelp = _free(con->otherHelp);
                   1118:     con->execPath = _free(con->execPath);
                   1119:     con->arg_strip = PBM_FREE(con->arg_strip);
                   1120:     
                   1121:     con = _free(con);
                   1122:     return con;
                   1123: }
                   1124: 
                   1125: int poptAddAlias(poptContext con, struct poptAlias alias,
                   1126:                /*@unused@*/ UNUSED(int flags))
                   1127: {
                   1128:     poptItem item = (poptItem) alloca(sizeof(*item));
                   1129:     memset(item, 0, sizeof(*item));
                   1130:     item->option.longName = alias.longName;
                   1131:     item->option.shortName = alias.shortName;
                   1132:     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
                   1133:     item->option.arg = 0;
                   1134:     item->option.val = 0;
                   1135:     item->option.descrip = NULL;
                   1136:     item->option.argDescrip = NULL;
                   1137:     item->argc = alias.argc;
                   1138:     item->argv = alias.argv;
                   1139:     return poptAddItem(con, item, 0);
                   1140: }
                   1141: 
                   1142: /*@-boundswrite@*/
                   1143: /*@-mustmod@*/ /* LCL: con not modified? */
                   1144: int poptAddItem(poptContext con, poptItem newItem, int flags)
                   1145: {
                   1146:     poptItem * items, item;
                   1147:     int * nitems;
                   1148: 
                   1149:     switch (flags) {
                   1150:     case 1:
                   1151:        items = &con->execs;
                   1152:        nitems = &con->numExecs;
                   1153:        break;
                   1154:     case 0:
                   1155:        items = &con->aliases;
                   1156:        nitems = &con->numAliases;
                   1157:        break;
                   1158:     default:
                   1159:        return 1;
                   1160:        /*@notreached@*/ break;
                   1161:     }
                   1162: 
                   1163:     *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
                   1164:     if ((*items) == NULL)
                   1165:        return 1;
                   1166: 
                   1167:     item = (*items) + (*nitems);
                   1168: 
                   1169:     item->option.longName =
                   1170:        (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
                   1171:     item->option.shortName = newItem->option.shortName;
                   1172:     item->option.argInfo = newItem->option.argInfo;
                   1173:     item->option.arg = newItem->option.arg;
                   1174:     item->option.val = newItem->option.val;
                   1175:     item->option.descrip =
                   1176:        (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
                   1177:     item->option.argDescrip =
                   1178:        (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
                   1179:     item->argc = newItem->argc;
                   1180:     item->argv = newItem->argv;
                   1181: 
                   1182:     (*nitems)++;
                   1183: 
                   1184:     return 0;
                   1185: }
                   1186: /*@=mustmod@*/
                   1187: /*@=boundswrite@*/
                   1188: 
                   1189: const char * poptBadOption(poptContext con, int flags)
                   1190: {
                   1191:     struct optionStackEntry * os = NULL;
                   1192: 
                   1193:     if (con != NULL)
                   1194:        os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
                   1195: 
                   1196:     /*@-nullderef@*/   /* LCL: os->argv != NULL */
                   1197:     return (os && os->argv ? os->argv[os->next - 1] : NULL);
                   1198:     /*@=nullderef@*/
                   1199: }
                   1200: 
                   1201: const char * poptStrerror(const int error)
                   1202: {
                   1203:     switch (error) {
                   1204:       case POPT_ERROR_NOARG:
                   1205:        return POPT_("missing argument");
                   1206:       case POPT_ERROR_UNWANTEDARG:
                   1207:        return POPT_("option does not take an argument");
                   1208:       case POPT_ERROR_BADOPT:
                   1209:        return POPT_("unknown option");
                   1210:       case POPT_ERROR_BADOPERATION:
                   1211:        return POPT_("mutually exclusive logical operations requested");
                   1212:       case POPT_ERROR_NULLARG:
                   1213:        return POPT_("opt->arg should not be NULL");
                   1214:       case POPT_ERROR_OPTSTOODEEP:
                   1215:        return POPT_("aliases nested too deeply");
                   1216:       case POPT_ERROR_BADQUOTE:
                   1217:        return POPT_("error in parameter quoting");
                   1218:       case POPT_ERROR_BADNUMBER:
                   1219:        return POPT_("invalid numeric value");
                   1220:       case POPT_ERROR_OVERFLOW:
                   1221:        return POPT_("number too large or too small");
                   1222:       case POPT_ERROR_MALLOC:
                   1223:        return POPT_("memory allocation failed");
                   1224:       case POPT_ERROR_ERRNO:
                   1225:        return strerror(errno);
                   1226:       default:
                   1227:        return POPT_("unknown error");
                   1228:     }
                   1229: }
                   1230: 
                   1231: int poptStuffArgs(poptContext con, const char ** argv)
                   1232: {
                   1233:     int argc;
                   1234:     int rc;
                   1235: 
                   1236:     if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
                   1237:        return POPT_ERROR_OPTSTOODEEP;
                   1238: 
                   1239:     for (argc = 0; argv[argc]; argc++)
                   1240:        {};
                   1241: 
                   1242:     con->os++;
                   1243:     con->os->next = 0;
                   1244:     con->os->nextArg = NULL;
                   1245:     con->os->nextCharArg = NULL;
                   1246:     con->os->currAlias = NULL;
                   1247:     rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
                   1248:     con->os->argb = NULL;
                   1249:     con->os->stuffed = 1;
                   1250: 
                   1251:     return rc;
                   1252: }
                   1253: 
                   1254: const char * poptGetInvocationName(poptContext con)
                   1255: {
                   1256:     return (con->os->argv ? con->os->argv[0] : "");
                   1257: }
                   1258: 
                   1259: /*@-boundswrite@*/
                   1260: int poptStrippedArgv(poptContext con, int argc, char ** argv)
                   1261: {
                   1262:     int numargs = argc;
                   1263:     int j = 1;
                   1264:     int i;
                   1265:     
                   1266:     /*@-sizeoftype@*/
                   1267:     if (con->arg_strip)
                   1268:     for (i = 1; i < argc; i++) {
                   1269:        if (PBM_ISSET(i, con->arg_strip))
                   1270:            numargs--;
                   1271:     }
                   1272:     
                   1273:     for (i = 1; i < argc; i++) {
                   1274:        if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
                   1275:            continue;
                   1276:        argv[j] = (j < numargs) ? argv[i] : NULL;
                   1277:        j++;
                   1278:     }
                   1279:     /*@=sizeoftype@*/
                   1280:     
                   1281:     return numargs;
                   1282: }
                   1283: /*@=boundswrite@*/

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>