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