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