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 #ifdef MYDEBUG
00034 static void prtcon(const char *msg, poptContext con)
00035 {
00036 if (msg) fprintf(stderr, "%s", msg);
00037 fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
00038 con, con->os,
00039 (con->os->nextCharArg ? con->os->nextCharArg : ""),
00040 (con->os->nextArg ? con->os->nextArg : ""),
00041 con->os->next,
00042 (con->os->argv && con->os->argv[con->os->next]
00043 ? con->os->argv[con->os->next] : ""));
00044 }
00045 #endif
00046
00047 void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
00048 {
00049 con->execPath = _free(con->execPath);
00050 con->execPath = xstrdup(path);
00051 con->execAbsolute = allowAbsolute;
00052 }
00053
00054 static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
00055
00056 {
00057 if (opt != NULL)
00058 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00059 if (opt->arg == NULL) continue;
00060 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00061
00062 invokeCallbacksPRE(con, opt->arg);
00063 } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00064 (opt->argInfo & POPT_CBFLAG_PRE))
00065 {
00066 poptCallbackType cb = (poptCallbackType)opt->arg;
00067
00068
00069
00070 cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
00071
00072 }
00073 }
00074 }
00075
00076 static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
00077
00078 {
00079 if (opt != NULL)
00080 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00081 if (opt->arg == NULL) continue;
00082 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00083
00084 invokeCallbacksPOST(con, opt->arg);
00085 } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00086 (opt->argInfo & POPT_CBFLAG_POST))
00087 {
00088 poptCallbackType cb = (poptCallbackType)opt->arg;
00089
00090
00091
00092 cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
00093
00094 }
00095 }
00096 }
00097
00098 static void invokeCallbacksOPTION(poptContext con,
00099 const struct poptOption * opt,
00100 const struct poptOption * myOpt,
00101 const void * myData, int shorty)
00102
00103 {
00104 const struct poptOption * cbopt = NULL;
00105
00106 if (opt != NULL)
00107 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00108 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00109
00110 if (opt->arg != NULL)
00111 invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
00112 } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
00113 !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
00114
00115 cbopt = opt;
00116 } else if (cbopt != NULL &&
00117 ((myOpt->shortName && opt->shortName && shorty &&
00118 myOpt->shortName == opt->shortName) ||
00119 (myOpt->longName && opt->longName &&
00120
00121 !strcmp(myOpt->longName, opt->longName)))
00122
00123 )
00124 {
00125 poptCallbackType cb = (poptCallbackType)cbopt->arg;
00126
00127 const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
00128
00129 if (cb != NULL) {
00130
00131 cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
00132 con->os->nextArg, cbData);
00133
00134 }
00135
00136 if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
00137 return;
00138 }
00139 }
00140 }
00141
00142 poptContext poptGetContext(const char * name, int argc, const char ** argv,
00143 const struct poptOption * options, int flags)
00144 {
00145 poptContext con = malloc(sizeof(*con));
00146
00147 if (con == NULL) return NULL;
00148 memset(con, 0, sizeof(*con));
00149
00150 con->os = con->optionStack;
00151 con->os->argc = argc;
00152
00153 con->os->argv = argv;
00154
00155 con->os->argb = NULL;
00156
00157 if (!(flags & POPT_CONTEXT_KEEP_FIRST))
00158 con->os->next = 1;
00159
00160 con->leftovers = calloc( (argc + 1), sizeof(char *) );
00161
00162 con->options = options;
00163
00164 con->aliases = NULL;
00165 con->numAliases = 0;
00166 con->flags = flags;
00167 con->execs = NULL;
00168 con->numExecs = 0;
00169 con->finalArgvAlloced = argc * 2;
00170 con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
00171 con->execAbsolute = 1;
00172 con->arg_strip = NULL;
00173
00174 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
00175 con->flags |= POPT_CONTEXT_POSIXMEHARDER;
00176
00177 if (name) {
00178 char * t = malloc(strlen(name) + 1);
00179 if (t) con->appName = strcpy(t, name);
00180 }
00181
00182 invokeCallbacksPRE(con, con->options);
00183
00184 return con;
00185 }
00186
00187 static void cleanOSE( struct optionStackEntry *os)
00188
00189
00190
00191 {
00192 os->nextArg = _free(os->nextArg);
00193 os->argv = _free(os->argv);
00194 os->argb = PBM_FREE(os->argb);
00195 }
00196
00197 void poptResetContext(poptContext con)
00198 {
00199 int i;
00200
00201 if (con == NULL) return;
00202 while (con->os > con->optionStack) {
00203 cleanOSE(con->os--);
00204 }
00205 con->os->argb = PBM_FREE(con->os->argb);
00206 con->os->currAlias = NULL;
00207 con->os->nextCharArg = NULL;
00208 con->os->nextArg = NULL;
00209 con->os->next = 1;
00210
00211 con->numLeftovers = 0;
00212 con->nextLeftover = 0;
00213 con->restLeftover = 0;
00214 con->doExec = NULL;
00215
00216 if (con->finalArgv != NULL)
00217 for (i = 0; i < con->finalArgvCount; i++)
00218
00219 con->finalArgv[i] = _free(con->finalArgv[i]);
00220
00221
00222 con->finalArgvCount = 0;
00223 con->arg_strip = PBM_FREE(con->arg_strip);
00224
00225 return;
00226
00227 }
00228
00229
00230 static int handleExec( poptContext con,
00231 const char * longName, char shortName)
00232
00233
00234
00235 {
00236 poptItem item;
00237 int i;
00238
00239 if (con->execs == NULL || con->numExecs <= 0)
00240 return 0;
00241
00242 for (i = con->numExecs - 1; i >= 0; i--) {
00243 item = con->execs + i;
00244 if (longName && !(item->option.longName &&
00245 !strcmp(longName, item->option.longName)))
00246 continue;
00247 else if (shortName != item->option.shortName)
00248 continue;
00249 break;
00250 }
00251 if (i < 0) return 0;
00252
00253
00254 if (con->flags & POPT_CONTEXT_NO_EXEC)
00255 return 1;
00256
00257 if (con->doExec == NULL) {
00258 con->doExec = con->execs + i;
00259 return 1;
00260 }
00261
00262
00263
00264 if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
00265 con->finalArgvAlloced += 10;
00266 con->finalArgv = realloc(con->finalArgv,
00267 sizeof(*con->finalArgv) * con->finalArgvAlloced);
00268 }
00269
00270 i = con->finalArgvCount++;
00271 if (con->finalArgv != NULL)
00272 { char *s = malloc((longName ? strlen(longName) : 0) + 3);
00273 if (s != NULL) {
00274 if (longName)
00275 sprintf(s, "--%s", longName);
00276 else
00277 sprintf(s, "-%c", shortName);
00278 con->finalArgv[i] = s;
00279 } else
00280 con->finalArgv[i] = NULL;
00281 }
00282
00283
00284 return 1;
00285
00286 }
00287
00288
00289 static int handleAlias( poptContext con,
00290 const char * longName, char shortName,
00291 const char * nextCharArg)
00292
00293
00294
00295 {
00296 poptItem item = con->os->currAlias;
00297 int rc;
00298 int i;
00299
00300 if (item) {
00301 if (longName && (item->option.longName &&
00302 !strcmp(longName, item->option.longName)))
00303 return 0;
00304 if (shortName && shortName == item->option.shortName)
00305 return 0;
00306 }
00307
00308 if (con->aliases == NULL || con->numAliases <= 0)
00309 return 0;
00310
00311 for (i = con->numAliases - 1; i >= 0; i--) {
00312 item = con->aliases + i;
00313 if (longName && !(item->option.longName &&
00314 !strcmp(longName, item->option.longName)))
00315 continue;
00316 else if (shortName != item->option.shortName)
00317 continue;
00318 break;
00319 }
00320 if (i < 0) return 0;
00321
00322 if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
00323 return POPT_ERROR_OPTSTOODEEP;
00324
00325 if (nextCharArg && *nextCharArg)
00326 con->os->nextCharArg = nextCharArg;
00327
00328 con->os++;
00329 con->os->next = 0;
00330 con->os->stuffed = 0;
00331 con->os->nextArg = NULL;
00332 con->os->nextCharArg = NULL;
00333 con->os->currAlias = con->aliases + i;
00334 rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
00335 &con->os->argc, &con->os->argv);
00336 con->os->argb = NULL;
00337
00338 return (rc ? rc : 1);
00339 }
00340
00341 static int execCommand(poptContext con)
00342
00343 {
00344 poptItem item = con->doExec;
00345 const char ** argv;
00346 int argc = 0;
00347 int rc;
00348
00349 if (item == NULL)
00350 return POPT_ERROR_NOARG;
00351
00352 if (item->argv == NULL || item->argc < 1 ||
00353 (!con->execAbsolute && strchr(item->argv[0], '/')))
00354 return POPT_ERROR_NOARG;
00355
00356 argv = malloc(sizeof(*argv) *
00357 (6 + item->argc + con->numLeftovers + con->finalArgvCount));
00358 if (argv == NULL) return POPT_ERROR_MALLOC;
00359
00360 if (!strchr(item->argv[0], '/') && con->execPath) {
00361 char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
00362 sprintf(s, "%s/%s", con->execPath, item->argv[0]);
00363 argv[argc] = s;
00364 } else {
00365 argv[argc] = findProgramPath(item->argv[0]);
00366 }
00367 if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
00368
00369 if (item->argc > 1) {
00370 memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
00371 argc += (item->argc - 1);
00372 }
00373
00374 if (con->finalArgv != NULL && con->finalArgvCount > 0) {
00375 memcpy(argv + argc, con->finalArgv,
00376 sizeof(*argv) * con->finalArgvCount);
00377 argc += con->finalArgvCount;
00378 }
00379
00380 if (con->leftovers != NULL && con->numLeftovers > 0) {
00381 #if 0
00382 argv[argc++] = "--";
00383 #endif
00384 memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
00385 argc += con->numLeftovers;
00386 }
00387
00388 argv[argc] = NULL;
00389
00390 #ifdef __hpux
00391 rc = setresuid(getuid(), getuid(),-1);
00392 if (rc) return POPT_ERROR_ERRNO;
00393 #else
00394
00395
00396
00397
00398
00399 #if defined(HAVE_SETUID)
00400 rc = setuid(getuid());
00401 if (rc) return POPT_ERROR_ERRNO;
00402 #elif defined (HAVE_SETREUID)
00403 rc = setreuid(getuid(), getuid());
00404 if (rc) return POPT_ERROR_ERRNO;
00405 #else
00406 ;
00407 #endif
00408 #endif
00409
00410 if (argv[0] == NULL)
00411 return POPT_ERROR_NOARG;
00412 #ifdef MYDEBUG
00413 { const char ** avp;
00414 fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
00415 for (avp = argv; *avp; avp++)
00416 fprintf(stderr, " '%s'", *avp);
00417 fprintf(stderr, "\n");
00418 }
00419 #endif
00420
00421 rc = execvp(argv[0], (char *const *)argv);
00422
00423 fprintf(stderr, "%s: %s\n",
00424 argv[0], poptStrerror(POPT_ERROR_ERRNO));
00425
00426 exit(EXIT_FAILURE);
00427 }
00428
00429 static const struct poptOption *
00430 findOption(const struct poptOption * opt, const char * longName,
00431 char shortName,
00432 poptCallbackType * callback,
00433 const void ** callbackData,
00434 int singleDash)
00435
00436 {
00437 const struct poptOption * cb = NULL;
00438
00439
00440 if (singleDash && !shortName && (longName && *longName == '\0'))
00441 shortName = '-';
00442
00443 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00444
00445 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00446 const struct poptOption * opt2;
00447
00448
00449 if (opt->arg == NULL) continue;
00450 opt2 = findOption(opt->arg, longName, shortName, callback,
00451 callbackData, singleDash);
00452 if (opt2 == NULL) continue;
00453
00454 if (!(callback && *callback)) return opt2;
00455 if (!(callbackData && *callbackData == NULL)) return opt2;
00456
00457 *callbackData = opt->descrip;
00458
00459 return opt2;
00460 } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
00461 cb = opt;
00462 } else if (longName && opt->longName &&
00463 (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
00464
00465 !strcmp(longName, opt->longName))
00466
00467 {
00468 break;
00469 } else if (shortName && shortName == opt->shortName) {
00470 break;
00471 }
00472 }
00473
00474 if (!opt->longName && !opt->shortName)
00475 return NULL;
00476
00477 if (callback) *callback = NULL;
00478 if (callbackData) *callbackData = NULL;
00479 if (cb) {
00480 if (callback)
00481
00482 *callback = (poptCallbackType)cb->arg;
00483
00484 if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) {
00485 if (callbackData)
00486
00487 *callbackData = cb->descrip;
00488
00489 }
00490 }
00491
00492
00493 return opt;
00494 }
00495
00496 static const char * findNextArg( poptContext con,
00497 unsigned argx, int delete_arg)
00498
00499
00500
00501 {
00502 struct optionStackEntry * os = con->os;
00503 const char * arg;
00504
00505 do {
00506 int i;
00507 arg = NULL;
00508 while (os->next == os->argc && os > con->optionStack) os--;
00509 if (os->next == os->argc && os == con->optionStack) break;
00510 if (os->argv != NULL)
00511 for (i = os->next; i < os->argc; i++) {
00512 if (os->argb && PBM_ISSET(i, os->argb)) continue;
00513 if (*os->argv[i] == '-') continue;
00514 if (--argx > 0) continue;
00515 arg = os->argv[i];
00516 if (delete_arg) {
00517 if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
00518 if (os->argb != NULL)
00519 PBM_SET(i, os->argb);
00520 }
00521 break;
00522 }
00523 if (os > con->optionStack) os--;
00524 } while (arg == NULL);
00525 return arg;
00526 }
00527
00528 static const char *
00529 expandNextArg( poptContext con, const char * s)
00530
00531
00532
00533 {
00534 const char * a = NULL;
00535 size_t alen;
00536 char *t, *te;
00537 size_t tn = strlen(s) + 1;
00538 char c;
00539
00540 te = t = malloc(tn);;
00541 if (t == NULL) return NULL;
00542 while ((c = *s++) != '\0') {
00543 switch (c) {
00544 #if 0
00545 case '\\':
00546 c = *s++;
00547 break;
00548 #endif
00549 case '!':
00550 if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
00551 break;
00552
00553 if (a == NULL) {
00554 if ((a = findNextArg(con, 1, 1)) == NULL) break;
00555 }
00556 s += 3;
00557
00558 alen = strlen(a);
00559 tn += alen;
00560 *te = '\0';
00561 t = realloc(t, tn);
00562 te = t + strlen(t);
00563 strncpy(te, a, alen); te += alen;
00564 continue;
00565 break;
00566 default:
00567 break;
00568 }
00569 *te++ = c;
00570 }
00571 *te = '\0';
00572 t = realloc(t, strlen(t) + 1);
00573 return t;
00574 }
00575
00576 static void poptStripArg( poptContext con, int which)
00577
00578
00579
00580 {
00581 if (con->arg_strip == NULL)
00582 con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
00583 if (con->arg_strip != NULL)
00584 PBM_SET(which, con->arg_strip);
00585 }
00586
00587 static int poptSaveLong(const struct poptOption * opt, long aLong)
00588
00589 {
00590 if (opt->arg == NULL)
00591 return POPT_ERROR_NULLARG;
00592
00593 if (opt->argInfo & POPT_ARGFLAG_NOT)
00594 aLong = ~aLong;
00595 switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00596 case 0:
00597 *((long *) opt->arg) = aLong;
00598 break;
00599 case POPT_ARGFLAG_OR:
00600 *((long *) opt->arg) |= aLong;
00601 break;
00602 case POPT_ARGFLAG_AND:
00603 *((long *) opt->arg) &= aLong;
00604 break;
00605 case POPT_ARGFLAG_XOR:
00606 *((long *) opt->arg) ^= aLong;
00607 break;
00608 default:
00609 return POPT_ERROR_BADOPERATION;
00610 break;
00611 }
00612 return 0;
00613 }
00614
00615 static int poptSaveInt(const struct poptOption * opt, long aLong)
00616
00617 {
00618 if (opt->arg == NULL)
00619 return POPT_ERROR_NULLARG;
00620
00621 if (opt->argInfo & POPT_ARGFLAG_NOT)
00622 aLong = ~aLong;
00623 switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00624 case 0:
00625 *((int *) opt->arg) = aLong;
00626 break;
00627 case POPT_ARGFLAG_OR:
00628 *((int *) opt->arg) |= aLong;
00629 break;
00630 case POPT_ARGFLAG_AND:
00631 *((int *) opt->arg) &= aLong;
00632 break;
00633 case POPT_ARGFLAG_XOR:
00634 *((int *) opt->arg) ^= aLong;
00635 break;
00636 default:
00637 return POPT_ERROR_BADOPERATION;
00638 break;
00639 }
00640 return 0;
00641 }
00642
00643
00644 int poptGetNextOpt(poptContext con)
00645 {
00646 const struct poptOption * opt = NULL;
00647 int done = 0;
00648
00649 if (con == NULL)
00650 return -1;
00651 while (!done) {
00652 const char * origOptString = NULL;
00653 poptCallbackType cb = NULL;
00654 const void * cbData = NULL;
00655 const char * longArg = NULL;
00656 int canstrip = 0;
00657 int shorty = 0;
00658
00659 while (!con->os->nextCharArg && con->os->next == con->os->argc
00660 && con->os > con->optionStack) {
00661 cleanOSE(con->os--);
00662 }
00663 if (!con->os->nextCharArg && con->os->next == con->os->argc) {
00664 invokeCallbacksPOST(con, con->options);
00665 if (con->doExec) return execCommand(con);
00666 return -1;
00667 }
00668
00669
00670 if (!con->os->nextCharArg) {
00671 char * localOptString, * optString;
00672 int thisopt;
00673
00674 if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
00675 con->os->next++;
00676 continue;
00677 }
00678 thisopt = con->os->next;
00679 if (con->os->argv != NULL)
00680 origOptString = con->os->argv[con->os->next++];
00681
00682 if (origOptString == NULL)
00683 return POPT_ERROR_BADOPT;
00684
00685 if (con->restLeftover || *origOptString != '-') {
00686 if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
00687 con->restLeftover = 1;
00688 if (con->flags & POPT_CONTEXT_ARG_OPTS) {
00689 con->os->nextArg = xstrdup(origOptString);
00690 return 0;
00691 }
00692 if (con->leftovers != NULL)
00693 con->leftovers[con->numLeftovers++] = origOptString;
00694 continue;
00695 }
00696
00697
00698 localOptString = optString =
00699 strcpy(alloca(strlen(origOptString) + 1), origOptString);
00700
00701 if (optString[0] == '\0')
00702 return POPT_ERROR_BADOPT;
00703
00704 if (optString[1] == '-' && !optString[2]) {
00705 con->restLeftover = 1;
00706 continue;
00707 } else {
00708 char *oe;
00709 int singleDash;
00710
00711 optString++;
00712 if (*optString == '-')
00713 singleDash = 0, optString++;
00714 else
00715 singleDash = 1;
00716
00717
00718 if (handleAlias(con, optString, '\0', NULL))
00719 continue;
00720
00721 if (handleExec(con, optString, '\0'))
00722 continue;
00723
00724
00725 for (oe = optString; *oe && *oe != '='; oe++)
00726 {};
00727 if (*oe == '=') {
00728 *oe++ = '\0';
00729
00730 longArg = origOptString + (oe - localOptString);
00731 }
00732
00733 opt = findOption(con->options, optString, '\0', &cb, &cbData,
00734 singleDash);
00735 if (!opt && !singleDash)
00736 return POPT_ERROR_BADOPT;
00737 }
00738
00739 if (!opt) {
00740 con->os->nextCharArg = origOptString + 1;
00741 } else {
00742 if (con->os == con->optionStack &&
00743 opt->argInfo & POPT_ARGFLAG_STRIP)
00744 {
00745 canstrip = 1;
00746 poptStripArg(con, thisopt);
00747 }
00748 shorty = 0;
00749 }
00750 }
00751
00752
00753 if (con->os->nextCharArg) {
00754 origOptString = con->os->nextCharArg;
00755
00756 con->os->nextCharArg = NULL;
00757
00758 if (handleAlias(con, NULL, *origOptString, origOptString + 1))
00759 continue;
00760
00761 if (handleExec(con, NULL, *origOptString)) {
00762
00763 origOptString++;
00764 if (*origOptString != '\0')
00765 con->os->nextCharArg = origOptString;
00766 continue;
00767 }
00768
00769 opt = findOption(con->options, NULL, *origOptString, &cb,
00770 &cbData, 0);
00771 if (!opt)
00772 return POPT_ERROR_BADOPT;
00773 shorty = 1;
00774
00775 origOptString++;
00776
00777 if (*origOptString != '\0')
00778 con->os->nextCharArg = origOptString;
00779
00780 }
00781
00782 if (opt == NULL) return POPT_ERROR_BADOPT;
00783 if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
00784 if (poptSaveInt(opt, 1L))
00785 return POPT_ERROR_BADOPERATION;
00786 } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
00787 if (opt->arg) {
00788 if (poptSaveInt(opt, (long)opt->val))
00789 return POPT_ERROR_BADOPERATION;
00790 }
00791 } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
00792 con->os->nextArg = _free(con->os->nextArg);
00793
00794 if (longArg) {
00795
00796 longArg = expandNextArg(con, longArg);
00797 con->os->nextArg = longArg;
00798 } else if (con->os->nextCharArg) {
00799 longArg = expandNextArg(con, con->os->nextCharArg);
00800 con->os->nextArg = longArg;
00801 con->os->nextCharArg = NULL;
00802 } else {
00803 while (con->os->next == con->os->argc &&
00804 con->os > con->optionStack) {
00805 cleanOSE(con->os--);
00806 }
00807 if (con->os->next == con->os->argc) {
00808 if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL))
00809
00810 return POPT_ERROR_NOARG;
00811
00812 con->os->nextArg = NULL;
00813 } else {
00814
00815
00816
00817
00818
00819 if (con->os == con->optionStack &&
00820 (opt->argInfo & POPT_ARGFLAG_STRIP) &&
00821 canstrip) {
00822 poptStripArg(con, con->os->next);
00823 }
00824
00825 if (con->os->argv != NULL) {
00826
00827 longArg = con->os->argv[con->os->next++];
00828 longArg = expandNextArg(con, longArg);
00829 con->os->nextArg = longArg;
00830 }
00831 }
00832 }
00833 longArg = NULL;
00834
00835 if (opt->arg) {
00836 switch (opt->argInfo & POPT_ARG_MASK) {
00837 case POPT_ARG_STRING:
00838
00839 *((const char **) opt->arg) = (con->os->nextArg)
00840 ? xstrdup(con->os->nextArg) : NULL;
00841 break;
00842
00843 case POPT_ARG_INT:
00844 case POPT_ARG_LONG:
00845 { long aLong = 0;
00846 char *end;
00847
00848 if (con->os->nextArg) {
00849 aLong = strtol(con->os->nextArg, &end, 0);
00850 if (!(end && *end == '\0'))
00851 return POPT_ERROR_BADNUMBER;
00852 }
00853
00854 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00855 if (aLong == LONG_MIN || aLong == LONG_MAX)
00856 return POPT_ERROR_OVERFLOW;
00857 if (poptSaveLong(opt, aLong))
00858 return POPT_ERROR_BADOPERATION;
00859 } else {
00860 if (aLong > INT_MAX || aLong < INT_MIN)
00861 return POPT_ERROR_OVERFLOW;
00862 if (poptSaveInt(opt, aLong))
00863 return POPT_ERROR_BADOPERATION;
00864 }
00865 } break;
00866
00867 case POPT_ARG_FLOAT:
00868 case POPT_ARG_DOUBLE:
00869 { double aDouble = 0.0;
00870 char *end;
00871
00872 if (con->os->nextArg) {
00873 int saveerrno = errno;
00874 errno = 0;
00875 aDouble = strtod(con->os->nextArg, &end);
00876 if (errno == ERANGE)
00877 return POPT_ERROR_OVERFLOW;
00878 errno = saveerrno;
00879 if (*end != '\0')
00880 return POPT_ERROR_BADNUMBER;
00881 }
00882
00883 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
00884 *((double *) opt->arg) = aDouble;
00885 } else {
00886 #define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
00887 if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
00888 return POPT_ERROR_OVERFLOW;
00889 if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON)
00890 return POPT_ERROR_OVERFLOW;
00891 *((float *) opt->arg) = aDouble;
00892 }
00893 } break;
00894 default:
00895 fprintf(stdout,
00896 POPT_("option type (%d) not implemented in popt\n"),
00897 (opt->argInfo & POPT_ARG_MASK));
00898 exit(EXIT_FAILURE);
00899 }
00900 }
00901 }
00902
00903 if (cb)
00904 invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
00905 else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
00906 done = 1;
00907
00908 if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
00909 con->finalArgvAlloced += 10;
00910 con->finalArgv = realloc(con->finalArgv,
00911 sizeof(*con->finalArgv) * con->finalArgvAlloced);
00912 }
00913
00914 if (con->finalArgv != NULL)
00915 { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
00916 if (s != NULL) {
00917 if (opt->longName)
00918 sprintf(s, "%s%s",
00919 ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
00920 opt->longName);
00921 else
00922 sprintf(s, "-%c", opt->shortName);
00923 con->finalArgv[con->finalArgvCount++] = s;
00924 } else
00925 con->finalArgv[con->finalArgvCount++] = NULL;
00926 }
00927
00928 if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
00929 ;
00930 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
00931 ;
00932 else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
00933 if (con->finalArgv != NULL && con->os->nextArg)
00934 con->finalArgv[con->finalArgvCount++] =
00935
00936 xstrdup(con->os->nextArg);
00937
00938 }
00939 }
00940
00941 return (opt ? opt->val : -1);
00942 }
00943
00944 const char * poptGetOptArg(poptContext con)
00945 {
00946 const char * ret = NULL;
00947 if (con) {
00948 ret = con->os->nextArg;
00949 con->os->nextArg = NULL;
00950 }
00951 return ret;
00952 }
00953
00954 const char * poptGetArg(poptContext con)
00955 {
00956 const char * ret = NULL;
00957 if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
00958 ret = con->leftovers[con->nextLeftover++];
00959 return ret;
00960 }
00961
00962 const char * poptPeekArg(poptContext con)
00963 {
00964 const char * ret = NULL;
00965 if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
00966 ret = con->leftovers[con->nextLeftover];
00967 return ret;
00968 }
00969
00970 const char ** poptGetArgs(poptContext con)
00971 {
00972 if (con == NULL ||
00973 con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
00974 return NULL;
00975
00976
00977 con->leftovers[con->numLeftovers] = NULL;
00978
00979
00980 return (con->leftovers + con->nextLeftover);
00981
00982 }
00983
00984 poptContext poptFreeContext(poptContext con)
00985 {
00986 poptItem item;
00987 int i;
00988
00989 if (con == NULL) return con;
00990 poptResetContext(con);
00991 con->os->argb = _free(con->os->argb);
00992
00993 if (con->aliases != NULL)
00994 for (i = 0; i < con->numAliases; i++) {
00995 item = con->aliases + i;
00996
00997 item->option.longName = _free(item->option.longName);
00998 item->option.descrip = _free(item->option.descrip);
00999 item->option.argDescrip = _free(item->option.argDescrip);
01000
01001 item->argv = _free(item->argv);
01002 }
01003 con->aliases = _free(con->aliases);
01004
01005 if (con->execs != NULL)
01006 for (i = 0; i < con->numExecs; i++) {
01007 item = con->execs + i;
01008
01009 item->option.longName = _free(item->option.longName);
01010 item->option.descrip = _free(item->option.descrip);
01011 item->option.argDescrip = _free(item->option.argDescrip);
01012
01013 item->argv = _free(item->argv);
01014 }
01015 con->execs = _free(con->execs);
01016
01017 con->leftovers = _free(con->leftovers);
01018 con->finalArgv = _free(con->finalArgv);
01019 con->appName = _free(con->appName);
01020 con->otherHelp = _free(con->otherHelp);
01021 con->execPath = _free(con->execPath);
01022 con->arg_strip = PBM_FREE(con->arg_strip);
01023
01024 con = _free(con);
01025 return con;
01026 }
01027
01028 int poptAddAlias(poptContext con, struct poptAlias newAlias,
01029 int flags)
01030 {
01031 poptItem item = alloca(sizeof(*item));
01032 memset(item, 0, sizeof(*item));
01033 item->option.longName = newAlias.longName;
01034 item->option.shortName = newAlias.shortName;
01035 item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
01036 item->option.arg = 0;
01037 item->option.val = 0;
01038 item->option.descrip = NULL;
01039 item->option.argDescrip = NULL;
01040 item->argc = newAlias.argc;
01041 item->argv = newAlias.argv;
01042 return poptAddItem(con, item, 0);
01043 }
01044
01045 int poptAddItem(poptContext con, poptItem newItem, int flags)
01046 {
01047 poptItem * items, item;
01048 int * nitems;
01049
01050 switch (flags) {
01051 case 1:
01052 items = &con->execs;
01053 nitems = &con->numExecs;
01054 break;
01055 case 0:
01056 items = &con->aliases;
01057 nitems = &con->numAliases;
01058 break;
01059 default:
01060 return 1;
01061 break;
01062 }
01063
01064 *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
01065 if ((*items) == NULL)
01066 return 1;
01067
01068 item = (*items) + (*nitems);
01069
01070 item->option.longName =
01071 (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
01072 item->option.shortName = newItem->option.shortName;
01073 item->option.argInfo = newItem->option.argInfo;
01074 item->option.arg = newItem->option.arg;
01075 item->option.val = newItem->option.val;
01076 item->option.descrip =
01077 (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
01078 item->option.argDescrip =
01079 (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
01080 item->argc = newItem->argc;
01081 item->argv = newItem->argv;
01082
01083 (*nitems)++;
01084
01085 return 0;
01086 }
01087
01088 const char * poptBadOption(poptContext con, int flags)
01089 {
01090 struct optionStackEntry * os = NULL;
01091
01092 if (con != NULL)
01093 os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
01094
01095
01096 return (os && os->argv ? os->argv[os->next - 1] : NULL);
01097
01098 }
01099
01100 const char *const poptStrerror(const int error)
01101 {
01102 switch (error) {
01103 case POPT_ERROR_NOARG:
01104 return POPT_("missing argument");
01105 case POPT_ERROR_BADOPT:
01106 return POPT_("unknown option");
01107 case POPT_ERROR_BADOPERATION:
01108 return POPT_("mutually exclusive logical operations requested");
01109 case POPT_ERROR_NULLARG:
01110 return POPT_("opt->arg should not be NULL");
01111 case POPT_ERROR_OPTSTOODEEP:
01112 return POPT_("aliases nested too deeply");
01113 case POPT_ERROR_BADQUOTE:
01114 return POPT_("error in parameter quoting");
01115 case POPT_ERROR_BADNUMBER:
01116 return POPT_("invalid numeric value");
01117 case POPT_ERROR_OVERFLOW:
01118 return POPT_("number too large or too small");
01119 case POPT_ERROR_MALLOC:
01120 return POPT_("memory allocation failed");
01121 case POPT_ERROR_ERRNO:
01122 return strerror(errno);
01123 default:
01124 return POPT_("unknown error");
01125 }
01126 }
01127
01128 int poptStuffArgs(poptContext con, const char ** argv)
01129 {
01130 int argc;
01131 int rc;
01132
01133 if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
01134 return POPT_ERROR_OPTSTOODEEP;
01135
01136 for (argc = 0; argv[argc]; argc++)
01137 {};
01138
01139 con->os++;
01140 con->os->next = 0;
01141 con->os->nextArg = NULL;
01142 con->os->nextCharArg = NULL;
01143 con->os->currAlias = NULL;
01144 rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
01145 con->os->argb = NULL;
01146 con->os->stuffed = 1;
01147
01148 return rc;
01149 }
01150
01151 const char * poptGetInvocationName(poptContext con)
01152 {
01153 return (con->os->argv ? con->os->argv[0] : "");
01154 }
01155
01156 int poptStrippedArgv(poptContext con, int argc, char ** argv)
01157 {
01158 int numargs = argc;
01159 int j = 1;
01160 int i;
01161
01162 if (con->arg_strip)
01163 for (i = 1; i < argc; i++) {
01164 if (PBM_ISSET(i, con->arg_strip))
01165 numargs--;
01166 }
01167
01168 for (i = 1; i < argc; i++) {
01169 if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
01170 continue;
01171 argv[j] = (j < numargs) ? argv[i] : NULL;
01172 j++;
01173 }
01174
01175 return numargs;
01176 }