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