00001
00005
00006
00007
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
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
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
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
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
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
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
00093 cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
00094 con->os->nextArg, cbData);
00095
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;
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;
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
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
00215
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
00235 static int handleAlias(poptContext con, const char * longName, char shortName,
00236 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
00321
00322
00323
00324 #if defined(HAVE_SETUID)
00325 setuid(getuid());
00326 #elif defined (HAVE_SETREUID)
00327 setreuid(getuid(), getuid());
00328 #else
00329 ;
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 static const struct poptOption *
00348 findOption(const struct poptOption * opt, const char * longName,
00349 char shortName,
00350 poptCallbackType * callback, const void ** callbackData,
00351 int singleDash)
00352 {
00353 const struct poptOption * cb = NULL;
00354
00355
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
00364 opt2 = findOption(opt->arg, longName, shortName, callback,
00365 callbackData, singleDash);
00366 if (opt2) {
00367
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 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
00434 case '\\':
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 break;
00453 default:
00454 break;
00455 }
00456 *te++ = c;
00457 }
00458 *te = '\0';
00459 t = realloc(t, strlen(t)+1);
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
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
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
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
00595 if (handleAlias(con, optString, '\0', NULL))
00596 continue;
00597 if (handleExec(con, optString, '\0'))
00598 continue;
00599
00600
00601 for (oe = optString; *oe && *oe != '='; oe++)
00602 ;
00603 if (*oe == '=') {
00604 *oe++ = '\0';
00605
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
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
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
00685
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
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 ;
00788 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
00789 ;
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
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 int flags)
00857 {
00858 int aliasNum = con->numAliases++;
00859 struct poptAlias * alias;
00860
00861
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 }