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