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