Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

popt/popt.c

Go to the documentation of this file.
00001 
00005 /* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
00006    file accompanying popt source distributions, available from
00007    ftp://ftp.rpm.org/pub/rpm/dist */
00008 
00009 #undef  MYDEBUG
00010 
00011 #include "system.h"
00012 
00013 #if HAVE_FLOAT_H
00014 #include <float.h>
00015 #endif
00016 #include <math.h>
00017 
00018 #include "findme.h"
00019 #include "poptint.h"
00020 
00021 #ifndef HAVE_STRERROR
00022 static char * strerror(int errno) {
00023     extern int sys_nerr;
00024     extern char * sys_errlist[];
00025 
00026     if ((0 <= errno) && (errno < sys_nerr))
00027         return sys_errlist[errno];
00028     else
00029         return POPT_("unknown errno");
00030 }
00031 #endif
00032 
00033 void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) {
00034     if (con->execPath) free((void *)con->execPath);
00035     con->execPath = xstrdup(path);
00036     con->execAbsolute = allowAbsolute;
00037 }
00038 
00039 static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
00040 {
00041     for (; opt->longName || opt->shortName || opt->arg; opt++) {
00042         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00043             /* Recurse on included sub-tables. */
00044             invokeCallbacksPRE(con, opt->arg);
00045         } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00046                    (opt->argInfo & POPT_CBFLAG_PRE))
00047         {   poptCallbackType cb = (poptCallbackType)opt->arg;
00048             /* Perform callback. */
00049             cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
00050         }
00051     }
00052 }
00053 
00054 static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
00055 {
00056     for (; opt->longName || opt->shortName || opt->arg; opt++) {
00057         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00058             /* Recurse on included sub-tables. */
00059             invokeCallbacksPOST(con, opt->arg);
00060         } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00061                    (opt->argInfo & POPT_CBFLAG_POST))
00062         {   poptCallbackType cb = (poptCallbackType)opt->arg;
00063             /* Perform callback. */
00064             cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
00065         }
00066     }
00067 }
00068 
00069 static void invokeCallbacksOPTION(poptContext con,
00070                                   const struct poptOption * opt,
00071                                   const struct poptOption * myOpt,
00072                                   const void * myData, int shorty)
00073 {
00074     const struct poptOption * cbopt = NULL;
00075 
00076     for (; opt->longName || opt->shortName || opt->arg; opt++) {
00077         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00078             /* Recurse on included sub-tables. */
00079             invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
00080         } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00081                   !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
00082             /* Save callback info. */
00083             cbopt = opt;
00084         } else if (cbopt != NULL &&
00085                    ((myOpt->shortName && opt->shortName && shorty &&
00086                         myOpt->shortName == opt->shortName) ||
00087                     (myOpt->longName && opt->longName &&
00088                         !strcmp(myOpt->longName, opt->longName)))
00089                    )
00090         {   poptCallbackType cb = (poptCallbackType)cbopt->arg;
00091             const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
00092             /* Perform callback. */
00093             cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
00094                         con->os->nextArg, cbData);
00095             /* Terminate (unless explcitly continuing). */
00096             if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
00097                 return;
00098         }
00099     }
00100 }
00101 
00102 poptContext poptGetContext(const char * name, int argc, const char ** argv,
00103                            const struct poptOption * options, int flags)
00104 {
00105     poptContext con = malloc(sizeof(*con));
00106 
00107     memset(con, 0, sizeof(*con));
00108 
00109     con->os = con->optionStack;
00110     con->os->argc = argc;
00111     con->os->argv = argv;
00112     con->os->argb = NULL;
00113 
00114     if (!(flags & POPT_CONTEXT_KEEP_FIRST))
00115         con->os->next = 1;                      /* skip argv[0] */
00116 
00117     con->leftovers = calloc( (argc + 1), sizeof(char *) );
00118     con->options = options;
00119     con->aliases = NULL;
00120     con->numAliases = 0;
00121     con->flags = flags;
00122     con->execs = NULL;
00123     con->numExecs = 0;
00124     con->finalArgvAlloced = argc * 2;
00125     con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
00126     con->execAbsolute = 1;
00127     con->arg_strip = NULL;
00128 
00129     if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
00130         con->flags |= POPT_CONTEXT_POSIXMEHARDER;
00131 
00132     if (name)
00133         con->appName = strcpy(malloc(strlen(name) + 1), name);
00134 
00135     invokeCallbacksPRE(con, con->options);
00136 
00137     return con;
00138 }
00139 
00140 static void cleanOSE(struct optionStackEntry *os)
00141 {
00142     if (os->nextArg) {
00143         free((void *)os->nextArg);
00144         os->nextArg = NULL;
00145     }
00146     if (os->argv) {
00147         free((void *)os->argv);
00148         os->argv = NULL;
00149     }
00150     if (os->argb) {
00151         PBM_FREE(os->argb);
00152         os->argb = NULL;
00153     }
00154 }
00155 
00156 void poptResetContext(poptContext con) {
00157     int i;
00158 
00159     while (con->os > con->optionStack) {
00160         cleanOSE(con->os--);
00161     }
00162     if (con->os->argb) {
00163         PBM_FREE(con->os->argb);
00164         con->os->argb = NULL;
00165     }
00166     con->os->currAlias = NULL;
00167     con->os->nextCharArg = NULL;
00168     con->os->nextArg = NULL;
00169     con->os->next = 1;                  /* skip argv[0] */
00170 
00171     con->numLeftovers = 0;
00172     con->nextLeftover = 0;
00173     con->restLeftover = 0;
00174     con->doExec = NULL;
00175 
00176     for (i = 0; i < con->finalArgvCount; i++) {
00177         if (con->finalArgv[i]) {
00178             free((void *)con->finalArgv[i]);
00179             con->finalArgv[i] = NULL;
00180         }
00181     }
00182 
00183     con->finalArgvCount = 0;
00184 
00185     if (con->arg_strip) {
00186         PBM_FREE(con->arg_strip);
00187         con->arg_strip = NULL;
00188     }
00189 }
00190 
00191 /* Only one of longName, shortName may be set at a time */
00192 static int handleExec(poptContext con, char * longName, char shortName) {
00193     int i;
00194 
00195     i = con->numExecs - 1;
00196     if (longName) {
00197         while (i >= 0 && (!con->execs[i].longName ||
00198             strcmp(con->execs[i].longName, longName))) i--;
00199     } else {
00200         while (i >= 0 &&
00201             con->execs[i].shortName != shortName) i--;
00202     }
00203 
00204     if (i < 0) return 0;
00205 
00206     if (con->flags & POPT_CONTEXT_NO_EXEC)
00207         return 1;
00208 
00209     if (con->doExec == NULL) {
00210         con->doExec = con->execs + i;
00211         return 1;
00212     }
00213 
00214     /* We already have an exec to do; remember this option for next
00215        time 'round */
00216     if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
00217         con->finalArgvAlloced += 10;
00218         con->finalArgv = realloc(con->finalArgv,
00219                         sizeof(*con->finalArgv) * con->finalArgvAlloced);
00220     }
00221 
00222     i = con->finalArgvCount++;
00223     {   char *s  = malloc((longName ? strlen(longName) : 0) + 3);
00224         if (longName)
00225             sprintf(s, "--%s", longName);
00226         else
00227             sprintf(s, "-%c", shortName);
00228         con->finalArgv[i] = s;
00229     }
00230 
00231     return 1;
00232 }
00233 
00234 /* Only one of longName, shortName may be set at a time */
00235 static int handleAlias(poptContext con, const char * longName, char shortName,
00236                        /*@keep@*/ const char * nextCharArg) {
00237     int i;
00238 
00239     if (con->os->currAlias && con->os->currAlias->longName && longName &&
00240         !strcmp(con->os->currAlias->longName, longName))
00241         return 0;
00242     if (con->os->currAlias && shortName &&
00243             shortName == con->os->currAlias->shortName)
00244         return 0;
00245 
00246     i = con->numAliases - 1;
00247     if (longName) {
00248         while (i >= 0 && (!con->aliases[i].longName ||
00249             strcmp(con->aliases[i].longName, longName))) i--;
00250     } else {
00251         while (i >= 0 &&
00252             con->aliases[i].shortName != shortName) i--;
00253     }
00254 
00255     if (i < 0) return 0;
00256 
00257     if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
00258         return POPT_ERROR_OPTSTOODEEP;
00259 
00260     if (nextCharArg && *nextCharArg)
00261         con->os->nextCharArg = nextCharArg;
00262 
00263     con->os++;
00264     con->os->next = 0;
00265     con->os->stuffed = 0;
00266     con->os->nextArg = NULL;
00267     con->os->nextCharArg = NULL;
00268     con->os->currAlias = con->aliases + i;
00269     poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
00270                 &con->os->argc, &con->os->argv);
00271     con->os->argb = NULL;
00272 
00273     return 1;
00274 }
00275 
00276 static void execCommand(poptContext con) {
00277     const char ** argv;
00278     int argc = 0;
00279     const char ** sargv;
00280     int sargc = 0;
00281 
00282     poptParseArgvString(con->doExec->script, &sargc, &sargv);
00283 
00284     if (sargv == NULL || sargc < 1 ||
00285         (!con->execAbsolute && strchr(sargv[0], '/')))
00286             return;
00287 
00288     argv = malloc(sizeof(*argv) *
00289                         (6 + sargc + con->numLeftovers + con->finalArgvCount));
00290 
00291     if (!strchr(sargv[0], '/') && con->execPath) {
00292         char *s = alloca(strlen(con->execPath) + strlen(sargv[0]) + sizeof("/"));
00293         sprintf(s, "%s/%s", con->execPath, sargv[0]);
00294         argv[argc] = s;
00295     } else {
00296         argv[argc] = findProgramPath(sargv[0]);
00297     }
00298     if (argv[argc++] == NULL) return;
00299 
00300     if (sargc > 1) {
00301         memcpy(argv + argc, sargv + 1, sizeof(*argv) * (sargc - 1));
00302         argc += (sargc - 1);
00303     }
00304 
00305     memcpy(argv + argc, con->finalArgv, sizeof(*argv) * con->finalArgvCount);
00306     argc += con->finalArgvCount;
00307 
00308     if (con->numLeftovers) {
00309         argv[argc++] = "--";
00310         memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
00311         argc += con->numLeftovers;
00312     }
00313 
00314     argv[argc++] = NULL;
00315 
00316 #ifdef __hpux
00317     setresuid(getuid(), getuid(),-1);
00318 #else
00319 /*
00320  * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
00321  * XXX  sez' Timur Bakeyev <mc@bat.ru>
00322  * XXX  from Norbert Warmuth <nwarmuth@privat.circular.de>
00323  */
00324 #if defined(HAVE_SETUID)
00325     setuid(getuid());
00326 #elif defined (HAVE_SETREUID)
00327     setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
00328 #else
00329     ; /* Can't drop privileges */
00330 #endif
00331 #endif
00332 
00333     if (argv[0] == NULL)
00334         return;
00335 #ifdef MYDEBUG
00336     {   const char ** arg;
00337         fprintf(stderr, "==> execvp(%s):", argv[0]);
00338         for (arg = argv; *arg; arg++)
00339             fprintf(stderr, " %s", *arg);
00340         fprintf(stderr, "\n");
00341     }
00342 #endif
00343 
00344     execvp(argv[0], (char *const *)argv);
00345 }
00346 
00347 /*@observer@*/ static const struct poptOption *
00348 findOption(const struct poptOption * opt, const char * longName,
00349     char shortName,
00350     /*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData,
00351     int singleDash)
00352 {
00353     const struct poptOption * cb = NULL;
00354 
00355     /* This happens when a single - is given */
00356     if (singleDash && !shortName && !*longName)
00357         shortName = '-';
00358 
00359     for (; opt->longName || opt->shortName || opt->arg; opt++) {
00360 
00361         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00362             const struct poptOption * opt2;
00363             /* Recurse on included sub-tables. */
00364             opt2 = findOption(opt->arg, longName, shortName, callback,
00365                               callbackData, singleDash);
00366             if (opt2) {
00367                 /* Sub-table data will be inheirited if no data yet. */
00368                 if (*callback && *callbackData == NULL)
00369                     *callbackData = opt->descrip;
00370                 return opt2;
00371             }
00372         } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
00373             cb = opt;
00374         } else if (longName && opt->longName &&
00375                    (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
00376                    !strcmp(longName, opt->longName)) {
00377             break;
00378         } else if (shortName && shortName == opt->shortName) {
00379             break;
00380         }
00381     }
00382 
00383     if (!opt->longName && !opt->shortName)
00384         return NULL;
00385     *callbackData = NULL;
00386     *callback = NULL;
00387     if (cb) {
00388         *callback = (poptCallbackType)cb->arg;
00389         if (!(cb->argInfo & POPT_CBFLAG_INC_DATA))
00390             *callbackData = cb->descrip;
00391     }
00392 
00393     return opt;
00394 }
00395 
00396 static const char *findNextArg(poptContext con, unsigned argx, int delete)
00397 {
00398     struct optionStackEntry * os = con->os;
00399     const char * arg;
00400 
00401     do {
00402         int i;
00403         arg = NULL;
00404         while (os->next == os->argc && os > con->optionStack) os--;
00405         if (os->next == os->argc && os == con->optionStack) break;
00406         for (i = os->next; i < os->argc; i++) {
00407             if (os->argb && PBM_ISSET(i, os->argb)) continue;
00408             if (*os->argv[i] == '-') continue;
00409             if (--argx > 0) continue;
00410             arg = os->argv[i];
00411             if (delete) {
00412                 if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
00413                 PBM_SET(i, os->argb);
00414             }
00415             break;
00416         }
00417         if (os > con->optionStack) os--;
00418     } while (arg == NULL);
00419     return arg;
00420 }
00421 
00422 static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
00423 {
00424     const char *a;
00425     size_t alen;
00426     char *t, *te;
00427     size_t tn = strlen(s) + 1;
00428     char c;
00429 
00430     te = t = malloc(tn);;
00431     while ((c = *s++) != '\0') {
00432         switch (c) {
00433 #if 0   /* XXX can't do this */
00434         case '\\':      /* escape */
00435             c = *s++;
00436             break;
00437 #endif
00438         case '!':
00439             if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
00440                 break;
00441             if ((a = findNextArg(con, 1, 1)) == NULL)
00442                 break;
00443             s += 3;
00444 
00445             alen = strlen(a);
00446             tn += alen;
00447             *te = '\0';
00448             t = realloc(t, tn);
00449             te = t + strlen(t);
00450             strncpy(te, a, alen); te += alen;
00451             continue;
00452             /*@notreached@*/ break;
00453         default:
00454             break;
00455         }
00456         *te++ = c;
00457     }
00458     *te = '\0';
00459     t = realloc(t, strlen(t)+1);        /* XXX memory leak, hard to plug */
00460     return t;
00461 }
00462 
00463 static void poptStripArg(poptContext con, int which)
00464 {
00465     if (con->arg_strip == NULL)
00466         con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
00467     PBM_SET(which, con->arg_strip);
00468 }
00469 
00470 static int poptSaveLong(const struct poptOption * opt, long aLong) {
00471     if (opt->argInfo & POPT_ARGFLAG_NOT)
00472         aLong = ~aLong;
00473     switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00474     case 0:
00475         *((long *) opt->arg) = aLong;
00476         break;
00477     case POPT_ARGFLAG_OR:
00478         *((long *) opt->arg) |= aLong;
00479         break;
00480     case POPT_ARGFLAG_AND:
00481         *((long *) opt->arg) &= aLong;
00482         break;
00483     case POPT_ARGFLAG_XOR:
00484         *((long *) opt->arg) ^= aLong;
00485         break;
00486     default:
00487         return POPT_ERROR_BADOPERATION;
00488         break;
00489     }
00490     return 0;
00491 }
00492 
00493 static int poptSaveInt(const struct poptOption * opt, long aLong) {
00494     if (opt->argInfo & POPT_ARGFLAG_NOT)
00495         aLong = ~aLong;
00496     switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00497     case 0:
00498         *((int *) opt->arg) = aLong;
00499         break;
00500     case POPT_ARGFLAG_OR:
00501         *((int *) opt->arg) |= aLong;
00502         break;
00503     case POPT_ARGFLAG_AND:
00504         *((int *) opt->arg) &= aLong;
00505         break;
00506     case POPT_ARGFLAG_XOR:
00507         *((int *) opt->arg) ^= aLong;
00508         break;
00509     default:
00510         return POPT_ERROR_BADOPERATION;
00511         break;
00512     }
00513     return 0;
00514 }
00515 
00516 #ifdef MYDEBUG
00517 static void prtcon(const char *msg, poptContext con)
00518 {
00519     if (msg) fprintf(stderr, "%s", msg);
00520     fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
00521         con, con->os,
00522         (con->os->nextCharArg ? con->os->nextCharArg : ""),
00523         (con->os->nextArg ? con->os->nextArg : ""),
00524         con->os->next,
00525         (con->os->argv && con->os->argv[con->os->next]
00526                 ? con->os->argv[con->os->next] : ""));
00527 }
00528 #endif
00529 
00530 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
00531 int poptGetNextOpt(poptContext con)
00532 {
00533     const struct poptOption * opt = NULL;
00534     int done = 0;
00535 
00536     while (!done) {
00537         const char * origOptString = NULL;
00538         poptCallbackType cb = NULL;
00539         const void * cbData = NULL;
00540         const char * longArg = NULL;
00541         int canstrip = 0;
00542         int shorty = 0;
00543 
00544         while (!con->os->nextCharArg && con->os->next == con->os->argc
00545                 && con->os > con->optionStack) {
00546             cleanOSE(con->os--);
00547         }
00548         if (!con->os->nextCharArg && con->os->next == con->os->argc) {
00549             invokeCallbacksPOST(con, con->options);
00550             if (con->doExec) execCommand(con);
00551             return -1;
00552         }
00553 
00554         /* Process next long option */
00555         if (!con->os->nextCharArg) {
00556             char * localOptString, * optString;
00557             int thisopt;
00558 
00559             if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
00560                 con->os->next++;
00561                 continue;
00562             }
00563             thisopt = con->os->next;
00564             origOptString = con->os->argv[con->os->next++];
00565 
00566             if (con->restLeftover || *origOptString != '-') {
00567                 con->leftovers[con->numLeftovers++] = origOptString;
00568                 if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
00569                     con->restLeftover = 1;
00570                 continue;
00571             }
00572 
00573             /* Make a copy we can hack at */
00574             localOptString = optString =
00575                         strcpy(alloca(strlen(origOptString) + 1),
00576                         origOptString);
00577 
00578             if (!optString[0])
00579                 return POPT_ERROR_BADOPT;
00580 
00581             if (optString[1] == '-' && !optString[2]) {
00582                 con->restLeftover = 1;
00583                 continue;
00584             } else {
00585                 char *oe;
00586                 int singleDash;
00587 
00588                 optString++;
00589                 if (*optString == '-')
00590                     singleDash = 0, optString++;
00591                 else
00592                     singleDash = 1;
00593 
00594                 /* XXX aliases with arg substitution need "--alias=arg" */
00595                 if (handleAlias(con, optString, '\0', NULL))
00596                     continue;
00597                 if (handleExec(con, optString, '\0'))
00598                     continue;
00599 
00600                 /* Check for "--long=arg" option. */
00601                 for (oe = optString; *oe && *oe != '='; oe++)
00602                     ;
00603                 if (*oe == '=') {
00604                     *oe++ = '\0';
00605                     /* XXX longArg is mapped back to persistent storage. */
00606                     longArg = origOptString + (oe - localOptString);
00607                 }
00608 
00609                 opt = findOption(con->options, optString, '\0', &cb, &cbData,
00610                                  singleDash);
00611                 if (!opt && !singleDash)
00612                     return POPT_ERROR_BADOPT;
00613             }
00614 
00615             if (!opt) {
00616                 con->os->nextCharArg = origOptString + 1;
00617             } else {
00618                 if (con->os == con->optionStack &&
00619                    opt->argInfo & POPT_ARGFLAG_STRIP) {
00620                     canstrip = 1;
00621                     poptStripArg(con, thisopt);
00622                 }
00623                 shorty = 0;
00624             }
00625         }
00626 
00627         /* Process next short option */
00628         if (con->os->nextCharArg) {
00629             origOptString = con->os->nextCharArg;
00630 
00631             con->os->nextCharArg = NULL;
00632 
00633             if (handleAlias(con, NULL, *origOptString,
00634                             origOptString + 1)) {
00635                 continue;
00636             }
00637             if (handleExec(con, NULL, *origOptString)) {
00638                 /* Restore rest of short options for further processing */
00639                 origOptString++;
00640                 if (*origOptString) con->os->nextCharArg = origOptString;
00641                 continue;
00642             }
00643 
00644             opt = findOption(con->options, NULL, *origOptString, &cb,
00645                              &cbData, 0);
00646             if (!opt)
00647                 return POPT_ERROR_BADOPT;
00648             shorty = 1;
00649 
00650             origOptString++;
00651             if (*origOptString) con->os->nextCharArg = origOptString;
00652         }
00653 
00654         if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
00655             if (poptSaveInt(opt, 1L))
00656                 return POPT_ERROR_BADOPERATION;
00657         } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
00658             if (opt->arg) {
00659                 if (poptSaveInt(opt, (long)opt->val))
00660                     return POPT_ERROR_BADOPERATION;
00661             }
00662         } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
00663             if (con->os->nextArg) {
00664                 free((void *)con->os->nextArg);
00665                 con->os->nextArg = NULL;
00666             }
00667             if (longArg) {
00668                 con->os->nextArg = expandNextArg(con, longArg);
00669             } else if (con->os->nextCharArg) {
00670                 con->os->nextArg = expandNextArg(con, con->os->nextCharArg);
00671                 con->os->nextCharArg = NULL;
00672             } else {
00673                 while (con->os->next == con->os->argc &&
00674                        con->os > con->optionStack) {
00675                     cleanOSE(con->os--);
00676                 }
00677                 if (con->os->next == con->os->argc) {
00678                     if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
00679                         con->os->nextArg = NULL;
00680                     else
00681                         return POPT_ERROR_NOARG;
00682                 } else {
00683 
00684                     /* make sure this isn't part of a short arg or the
00685                         result of an alias expansion */
00686                     if (con->os == con->optionStack &&
00687                         opt->argInfo & POPT_ARGFLAG_STRIP &&
00688                         canstrip) {
00689                         poptStripArg(con, con->os->next);
00690                     }
00691                 
00692                     con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]);
00693                 }
00694             }
00695 
00696             if (opt->arg) {
00697                 switch (opt->argInfo & POPT_ARG_MASK) {
00698                 case POPT_ARG_STRING:
00699                     /* XXX memory leak, hard to plug */
00700                     *((const char **) opt->arg) = (con->os->nextArg)
00701                         ? xstrdup(con->os->nextArg) : NULL;
00702                     break;
00703 
00704                 case POPT_ARG_INT:
00705                 case POPT_ARG_LONG:
00706                 {   long aLong = 0;
00707                     char *end;
00708 
00709                     if (con->os->nextArg) {
00710                         aLong = strtol(con->os->nextArg, &end, 0);
00711                         if (!(end && *end == '\0'))
00712                             return POPT_ERROR_BADNUMBER;
00713                     }
00714 
00715                     if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00716                         if (aLong == LONG_MIN || aLong == LONG_MAX)
00717                             return POPT_ERROR_OVERFLOW;
00718                         if (poptSaveLong(opt, aLong))
00719                             return POPT_ERROR_BADOPERATION;
00720                     } else {
00721                         if (aLong > INT_MAX || aLong < INT_MIN)
00722                             return POPT_ERROR_OVERFLOW;
00723                         if (poptSaveInt(opt, aLong))
00724                             return POPT_ERROR_BADOPERATION;
00725                     }
00726                 }   break;
00727 
00728                 case POPT_ARG_FLOAT:
00729                 case POPT_ARG_DOUBLE:
00730                 {   double aDouble = 0.0;
00731                     char *end;
00732 
00733                     if (con->os->nextArg) {
00734                         aDouble = strtod(con->os->nextArg, &end);
00735                         if (*end)
00736                             return POPT_ERROR_BADNUMBER;
00737                     }
00738 
00739                     if (aDouble == +HUGE_VAL || aDouble == -HUGE_VAL)
00740                         return POPT_ERROR_OVERFLOW;
00741                     if (aDouble == 0.0 && errno == ERANGE)
00742                         return POPT_ERROR_OVERFLOW;
00743                     if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
00744                         *((double *) opt->arg) = aDouble;
00745                     } else {
00746 #ifdef ABS
00747 #undef ABS
00748 #endif
00749 #define ABS(a) (((a) < 0) ? -(a) : (a))
00750                         if (ABS(aDouble) > FLT_MAX)
00751                             return POPT_ERROR_OVERFLOW;
00752                         if (ABS(aDouble) < FLT_MIN)
00753                             return POPT_ERROR_OVERFLOW;
00754                         *((float *) opt->arg) = aDouble;
00755                     }
00756                 }   break;
00757                 default:
00758                     fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"),
00759                       opt->argInfo & POPT_ARG_MASK);
00760                     exit(EXIT_FAILURE);
00761                 }
00762             }
00763         }
00764 
00765         if (cb)
00766             invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
00767         else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
00768             done = 1;
00769 
00770         if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
00771             con->finalArgvAlloced += 10;
00772             con->finalArgv = realloc(con->finalArgv,
00773                             sizeof(*con->finalArgv) * con->finalArgvAlloced);
00774         }
00775 
00776         {   char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
00777             if (opt->longName)
00778                 sprintf(s, "%s%s",
00779                     ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
00780                     opt->longName);
00781             else
00782                 sprintf(s, "-%c", opt->shortName);
00783             con->finalArgv[con->finalArgvCount++] = s;
00784         }
00785 
00786         if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
00787             /*@-ifempty@*/ ;
00788         else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
00789             /*@-ifempty@*/ ;
00790         else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
00791             if (con->os->nextArg)
00792                 con->finalArgv[con->finalArgvCount++] =
00793                         xstrdup(con->os->nextArg);
00794         }
00795     }
00796 
00797     return opt->val;
00798 }
00799 
00800 const char * poptGetOptArg(poptContext con) {
00801     const char * ret = con->os->nextArg;
00802     con->os->nextArg = NULL;
00803     return ret;
00804 }
00805 
00806 const char * poptGetArg(poptContext con) {
00807     const char * ret = (con->nextLeftover < con->numLeftovers)
00808         ? con->leftovers[con->nextLeftover++] : NULL;
00809     return ret;
00810 }
00811 
00812 const char * poptPeekArg(poptContext con) {
00813     const char * ret = (con->nextLeftover < con->numLeftovers)
00814         ? con->leftovers[con->nextLeftover] : NULL;
00815     return ret;
00816 }
00817 
00818 const char ** poptGetArgs(poptContext con) {
00819     if (con->numLeftovers == con->nextLeftover) return NULL;
00820 
00821     /* some apps like [like RPM ;-) ] need this NULL terminated */
00822     con->leftovers[con->numLeftovers] = NULL;
00823 
00824     return (con->leftovers + con->nextLeftover);
00825 }
00826 
00827 void poptFreeContext(poptContext con) {
00828     int i;
00829 
00830     poptResetContext(con);
00831     if (con->os->argb) free(con->os->argb);
00832 
00833     for (i = 0; i < con->numAliases; i++) {
00834         if (con->aliases[i].longName) free((void *)con->aliases[i].longName);
00835         free(con->aliases[i].argv);
00836     }
00837 
00838     for (i = 0; i < con->numExecs; i++) {
00839         if (con->execs[i].longName) free((void *)con->execs[i].longName);
00840         free((void *)con->execs[i].script);
00841     }
00842     if (con->execs) free((void *)con->execs);
00843 
00844     free(con->leftovers);
00845     free(con->finalArgv);
00846     if (con->appName) free((void *)con->appName);
00847     if (con->aliases) free(con->aliases);
00848     if (con->otherHelp) free((void *)con->otherHelp);
00849     if (con->execPath) free((void *)con->execPath);
00850     if (con->arg_strip) PBM_FREE(con->arg_strip);
00851     
00852     free(con);
00853 }
00854 
00855 int poptAddAlias(poptContext con, struct poptAlias newAlias,
00856                 /*@unused@*/ int flags)
00857 {
00858     int aliasNum = con->numAliases++;
00859     struct poptAlias * alias;
00860 
00861     /* SunOS won't realloc(NULL, ...) */
00862     if (!con->aliases)
00863         con->aliases = malloc(sizeof(newAlias) * con->numAliases);
00864     else
00865         con->aliases = realloc(con->aliases,
00866                                sizeof(newAlias) * con->numAliases);
00867     alias = con->aliases + aliasNum;
00868 
00869     alias->longName = (newAlias.longName)
00870         ? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName)
00871         : NULL;
00872     alias->shortName = newAlias.shortName;
00873     alias->argc = newAlias.argc;
00874     alias->argv = newAlias.argv;
00875 
00876     return 0;
00877 }
00878 
00879 const char * poptBadOption(poptContext con, int flags) {
00880     struct optionStackEntry * os;
00881 
00882     if (flags & POPT_BADOPTION_NOALIAS)
00883         os = con->optionStack;
00884     else
00885         os = con->os;
00886 
00887     return os->argv[os->next - 1];
00888 }
00889 
00890 const char *const poptStrerror(const int error) {
00891     switch (error) {
00892       case POPT_ERROR_NOARG:
00893         return POPT_("missing argument");
00894       case POPT_ERROR_BADOPT:
00895         return POPT_("unknown option");
00896       case POPT_ERROR_BADOPERATION:
00897         return POPT_("mutually exclusive logical operations requested");
00898       case POPT_ERROR_OPTSTOODEEP:
00899         return POPT_("aliases nested too deeply");
00900       case POPT_ERROR_BADQUOTE:
00901         return POPT_("error in parameter quoting");
00902       case POPT_ERROR_BADNUMBER:
00903         return POPT_("invalid numeric value");
00904       case POPT_ERROR_OVERFLOW:
00905         return POPT_("number too large or too small");
00906       case POPT_ERROR_ERRNO:
00907         return strerror(errno);
00908       default:
00909         return POPT_("unknown error");
00910     }
00911 }
00912 
00913 int poptStuffArgs(poptContext con, const char ** argv) {
00914     int argc;
00915 
00916     if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
00917         return POPT_ERROR_OPTSTOODEEP;
00918 
00919     for (argc = 0; argv[argc]; argc++)
00920         ;
00921 
00922     con->os++;
00923     con->os->next = 0;
00924     con->os->nextArg = NULL;
00925     con->os->nextCharArg = NULL;
00926     con->os->currAlias = NULL;
00927     poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
00928     con->os->argb = NULL;
00929     con->os->stuffed = 1;
00930 
00931     return 0;
00932 }
00933 
00934 const char * poptGetInvocationName(poptContext con) {
00935     return con->os->argv[0];
00936 }
00937 
00938 int poptStrippedArgv(poptContext con, int argc, char **argv)
00939 {
00940     int i,j=1, numargs=argc;
00941     
00942     for (i = 1; i < argc; i++) {
00943         if (PBM_ISSET(i, con->arg_strip))
00944             numargs--;
00945     }
00946     
00947     for (i = 1; i < argc; i++) {
00948         if (PBM_ISSET(i, con->arg_strip))
00949             continue;
00950         argv[j] = (j < numargs) ? argv[i] : '\0';
00951         j++;
00952     }
00953     
00954     return numargs;
00955 }

Generated at Sun Apr 8 18:43:01 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000