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