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