00001
00005
00006
00007
00008
00009 #undef MYDEBUG
00010
00011 #include "system.h"
00012
00013 #if defined(__LCLINT__)
00014
00015 extern long long int strtoll(const char *nptr, char **endptr,
00016 int base)
00017 ;
00018
00019 #endif
00020
00021 #ifdef HAVE_FLOAT_H
00022 #include <float.h>
00023 #endif
00024 #include <math.h>
00025
00026 #include "poptint.h"
00027
00028 #ifdef MYDEBUG
00029
00030 int _popt_debug = 0;
00031 #endif
00032
00033
00034 unsigned int _poptArgMask = POPT_ARG_MASK;
00035
00036 unsigned int _poptGroupMask = POPT_GROUP_MASK;
00037
00038 #if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
00039 static char * strerror(int errno)
00040 {
00041 extern int sys_nerr;
00042 extern char * sys_errlist[];
00043
00044 if ((0 <= errno) && (errno < sys_nerr))
00045 return sys_errlist[errno];
00046 else
00047 return POPT_("unknown errno");
00048 }
00049 #endif
00050
00051 #ifdef MYDEBUG
00052
00053 static void prtcon(const char *msg, poptContext con)
00054 {
00055 if (msg) fprintf(stderr, "%s", msg);
00056 fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
00057 con, con->os,
00058 (con->os->nextCharArg ? con->os->nextCharArg : ""),
00059 (con->os->nextArg ? con->os->nextArg : ""),
00060 con->os->next,
00061 (con->os->argv && con->os->argv[con->os->next]
00062 ? con->os->argv[con->os->next] : ""));
00063 }
00064 #endif
00065
00066 void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
00067 {
00068 con->execPath = _free(con->execPath);
00069 con->execPath = xstrdup(path);
00070 con->execAbsolute = allowAbsolute;
00071 return;
00072 }
00073
00074 static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
00075
00076
00077 {
00078 if (opt != NULL)
00079 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00080 poptArg arg = { .ptr = opt->arg };
00081 if (arg.ptr)
00082 switch (poptArgType(opt)) {
00083 case POPT_ARG_INCLUDE_TABLE:
00084 poptSubstituteHelpI18N(arg.opt);
00085 invokeCallbacksPRE(con, arg.opt);
00086 break;
00087 case POPT_ARG_CALLBACK:
00088 if (!CBF_ISSET(opt, PRE))
00089 break;
00090
00091 arg.cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
00092
00093 break;
00094 }
00095 }
00096 }
00097
00098 static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
00099
00100
00101 {
00102 if (opt != NULL)
00103 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00104 poptArg arg = { .ptr = opt->arg };
00105 if (arg.ptr)
00106 switch (poptArgType(opt)) {
00107 case POPT_ARG_INCLUDE_TABLE:
00108 poptSubstituteHelpI18N(arg.opt);
00109 invokeCallbacksPOST(con, arg.opt);
00110 break;
00111 case POPT_ARG_CALLBACK:
00112 if (!CBF_ISSET(opt, POST))
00113 break;
00114
00115 arg.cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
00116
00117 break;
00118 }
00119 }
00120 }
00121
00122 static void invokeCallbacksOPTION(poptContext con,
00123 const struct poptOption * opt,
00124 const struct poptOption * myOpt,
00125 const void * myData, int shorty)
00126
00127
00128 {
00129 const struct poptOption * cbopt = NULL;
00130 poptArg cbarg = { .ptr = NULL };
00131
00132 if (opt != NULL)
00133 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00134 poptArg arg = { .ptr = opt->arg };
00135 switch (poptArgType(opt)) {
00136 case POPT_ARG_INCLUDE_TABLE:
00137 poptSubstituteHelpI18N(arg.opt);
00138 if (opt->arg != NULL)
00139 invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
00140 break;
00141 case POPT_ARG_CALLBACK:
00142 if (CBF_ISSET(opt, SKIPOPTION))
00143 break;
00144 cbopt = opt;
00145 cbarg.ptr = opt->arg;
00146 break;
00147 default:
00148 if (cbopt == NULL || cbarg.cb == NULL)
00149 break;
00150 if ((myOpt->shortName && opt->shortName && shorty &&
00151 myOpt->shortName == opt->shortName)
00152 || (myOpt->longName != NULL && opt->longName != NULL &&
00153 !strcmp(myOpt->longName, opt->longName)))
00154 { const void *cbData = (cbopt->descrip ? cbopt->descrip : myData);
00155
00156 cbarg.cb(con, POPT_CALLBACK_REASON_OPTION,
00157 myOpt, con->os->nextArg, cbData);
00158
00159
00160 if (!CBF_ISSET(cbopt, CONTINUE))
00161 return;
00162 }
00163 break;
00164 }
00165 }
00166 }
00167
00168 poptContext poptGetContext(const char * name, int argc, const char ** argv,
00169 const struct poptOption * options, unsigned int flags)
00170 {
00171 poptContext con = malloc(sizeof(*con));
00172
00173 if (con == NULL) return NULL;
00174 memset(con, 0, sizeof(*con));
00175
00176 con->os = con->optionStack;
00177 con->os->argc = argc;
00178
00179 con->os->argv = argv;
00180
00181 con->os->argb = NULL;
00182
00183 if (!(flags & POPT_CONTEXT_KEEP_FIRST))
00184 con->os->next = 1;
00185
00186 con->leftovers = calloc( (size_t)(argc + 1), sizeof(*con->leftovers) );
00187
00188 con->options = options;
00189
00190 con->aliases = NULL;
00191 con->numAliases = 0;
00192 con->flags = flags;
00193 con->execs = NULL;
00194 con->numExecs = 0;
00195 con->finalArgvAlloced = argc * 2;
00196 con->finalArgv = calloc( (size_t)con->finalArgvAlloced, sizeof(*con->finalArgv) );
00197 con->execAbsolute = 1;
00198 con->arg_strip = NULL;
00199
00200 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
00201 con->flags |= POPT_CONTEXT_POSIXMEHARDER;
00202
00203 if (name)
00204 con->appName = xstrdup(name);
00205
00206 invokeCallbacksPRE(con, con->options);
00207
00208 return con;
00209 }
00210
00211 static void cleanOSE( struct optionStackEntry *os)
00212
00213
00214
00215 {
00216 os->nextArg = _free(os->nextArg);
00217 os->argv = _free(os->argv);
00218 os->argb = PBM_FREE(os->argb);
00219 }
00220
00221 void poptResetContext(poptContext con)
00222 {
00223 int i;
00224
00225 if (con == NULL) return;
00226 while (con->os > con->optionStack) {
00227 cleanOSE(con->os--);
00228 }
00229 con->os->argb = PBM_FREE(con->os->argb);
00230 con->os->currAlias = NULL;
00231 con->os->nextCharArg = NULL;
00232 con->os->nextArg = NULL;
00233 con->os->next = 1;
00234
00235 con->numLeftovers = 0;
00236 con->nextLeftover = 0;
00237 con->restLeftover = 0;
00238 con->doExec = NULL;
00239
00240 if (con->finalArgv != NULL)
00241 for (i = 0; i < con->finalArgvCount; i++) {
00242
00243 con->finalArgv[i] = _free(con->finalArgv[i]);
00244
00245 }
00246
00247 con->finalArgvCount = 0;
00248 con->arg_strip = PBM_FREE(con->arg_strip);
00249
00250 return;
00251
00252 }
00253
00254
00255 static int handleExec( poptContext con,
00256 const char * longName, char shortName)
00257
00258
00259
00260 {
00261 poptItem item;
00262 int i;
00263
00264 if (con->execs == NULL || con->numExecs <= 0)
00265 return 0;
00266
00267 for (i = con->numExecs - 1; i >= 0; i--) {
00268 item = con->execs + i;
00269 if (longName && !(item->option.longName &&
00270 !strcmp(longName, item->option.longName)))
00271 continue;
00272 else if (shortName != item->option.shortName)
00273 continue;
00274 break;
00275 }
00276 if (i < 0) return 0;
00277
00278
00279 if (con->flags & POPT_CONTEXT_NO_EXEC)
00280 return 1;
00281
00282 if (con->doExec == NULL) {
00283 con->doExec = con->execs + i;
00284 return 1;
00285 }
00286
00287
00288
00289 if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
00290 con->finalArgvAlloced += 10;
00291 con->finalArgv = realloc(con->finalArgv,
00292 sizeof(*con->finalArgv) * con->finalArgvAlloced);
00293 }
00294
00295 i = con->finalArgvCount++;
00296 if (con->finalArgv != NULL)
00297 { char *s = malloc((longName ? strlen(longName) : 0) + sizeof("--"));
00298 if (s != NULL) {
00299 con->finalArgv[i] = s;
00300 *s++ = '-';
00301 if (longName)
00302 s = stpcpy( stpcpy(s, "-"), longName);
00303 else
00304 *s++ = shortName;
00305 *s = '\0';
00306 } else
00307 con->finalArgv[i] = NULL;
00308 }
00309
00310 return 1;
00311 }
00312
00320 static int
00321 longOptionStrcmp(const struct poptOption * opt,
00322 const char * longName, size_t longNameLen)
00323
00324 {
00325 const char * optLongName = opt->longName;
00326 int rc;
00327
00328 if (optLongName == NULL || longName == NULL)
00329 return 0;
00330
00331 if (F_ISSET(opt, TOGGLE)) {
00332 if (optLongName[0] == 'n' && optLongName[1] == 'o') {
00333 optLongName += sizeof("no") - 1;
00334 if (optLongName[0] == '-')
00335 optLongName++;
00336 }
00337 if (longName[0] == 'n' && longName[1] == 'o') {
00338 longName += sizeof("no") - 1;
00339 longNameLen -= sizeof("no") - 1;
00340 if (longName[0] == '-') {
00341 longName++;
00342 longNameLen--;
00343 }
00344 }
00345 }
00346 rc = (int)(strlen(optLongName) == longNameLen);
00347 if (rc)
00348 rc = (int)(strncmp(optLongName, longName, longNameLen) == 0);
00349 return rc;
00350 }
00351
00352
00353 static int handleAlias( poptContext con,
00354 const char * longName, size_t longNameLen,
00355 char shortName,
00356 const char * nextArg)
00357
00358
00359
00360 {
00361 poptItem item = con->os->currAlias;
00362 int rc;
00363 int i;
00364
00365 if (item) {
00366 if (longName && item->option.longName != NULL
00367 && longOptionStrcmp(&item->option, longName, longNameLen))
00368 return 0;
00369 else
00370 if (shortName && shortName == item->option.shortName)
00371 return 0;
00372 }
00373
00374 if (con->aliases == NULL || con->numAliases <= 0)
00375 return 0;
00376
00377 for (i = con->numAliases - 1; i >= 0; i--) {
00378 item = con->aliases + i;
00379 if (longName) {
00380 if (item->option.longName == NULL)
00381 continue;
00382 if (!longOptionStrcmp(&item->option, longName, longNameLen))
00383 continue;
00384 } else if (shortName != item->option.shortName)
00385 continue;
00386 break;
00387 }
00388 if (i < 0) return 0;
00389
00390 if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
00391 return POPT_ERROR_OPTSTOODEEP;
00392
00393 if (longName == NULL && nextArg != NULL && *nextArg != '\0')
00394 con->os->nextCharArg = nextArg;
00395
00396 con->os++;
00397 con->os->next = 0;
00398 con->os->stuffed = 0;
00399 con->os->nextArg = NULL;
00400 con->os->nextCharArg = NULL;
00401 con->os->currAlias = con->aliases + i;
00402 { const char ** av;
00403 int ac = con->os->currAlias->argc;
00404
00405 if (longName && nextArg != NULL && *nextArg != '\0') {
00406 av = malloc((ac + 1 + 1) * sizeof(*av));
00407 if (av != NULL) {
00408 for (i = 0; i < ac; i++) {
00409 av[i] = con->os->currAlias->argv[i];
00410 }
00411 av[ac++] = nextArg;
00412 av[ac] = NULL;
00413 } else
00414 av = con->os->currAlias->argv;
00415 } else
00416 av = con->os->currAlias->argv;
00417 rc = poptDupArgv(ac, av, &con->os->argc, &con->os->argv);
00418 if (av != NULL && av != con->os->currAlias->argv)
00419 free(av);
00420 }
00421 con->os->argb = NULL;
00422
00423 return (rc ? rc : 1);
00424 }
00425
00431 static
00432 const char * findProgramPath( const char * argv0)
00433
00434 {
00435 char *path = NULL, *s = NULL, *se;
00436 char *t = NULL;
00437
00438 if (argv0 == NULL) return NULL;
00439
00440
00441
00442 if (strchr(argv0, '/'))
00443 return xstrdup(argv0);
00444
00445 if ((path = getenv("PATH")) == NULL || (path = xstrdup(path)) == NULL)
00446 return NULL;
00447
00448
00449 if ((t = malloc(strlen(path) + strlen(argv0) + sizeof("/"))) != NULL)
00450 for (s = path; s && *s; s = se) {
00451
00452
00453 if ((se = strchr(s, ':')))
00454 *se++ = '\0';
00455
00456
00457 (void) stpcpy(stpcpy(stpcpy(t, s), "/"), argv0);
00458
00459
00460 if (!access(t, X_OK))
00461 break;
00462 }
00463
00464
00465
00466 if (!(s && *s) && t != NULL)
00467 t = _free(t);
00468
00469
00470 path = _free(path);
00471
00472
00473 return t;
00474 }
00475
00476 static int execCommand(poptContext con)
00477
00478
00479 {
00480 poptItem item = con->doExec;
00481 poptArgv argv = NULL;
00482 int argc = 0;
00483 int rc;
00484 int ec = POPT_ERROR_ERRNO;
00485
00486 if (item == NULL)
00487 return POPT_ERROR_NOARG;
00488
00489 if (item->argv == NULL || item->argc < 1 ||
00490 (!con->execAbsolute && strchr(item->argv[0], '/')))
00491 return POPT_ERROR_NOARG;
00492
00493 argv = malloc(sizeof(*argv) *
00494 (6 + item->argc + con->numLeftovers + con->finalArgvCount));
00495 if (argv == NULL) return POPT_ERROR_MALLOC;
00496
00497 if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
00498 char *s = malloc(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
00499 if (s)
00500 (void)stpcpy(stpcpy(stpcpy(s, con->execPath), "/"), item->argv[0]);
00501
00502 argv[argc] = s;
00503 } else
00504 argv[argc] = findProgramPath(item->argv[0]);
00505 if (argv[argc++] == NULL) {
00506 ec = POPT_ERROR_NOARG;
00507 goto exit;
00508 }
00509
00510 if (item->argc > 1) {
00511 memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
00512 argc += (item->argc - 1);
00513 }
00514
00515 if (con->finalArgv != NULL && con->finalArgvCount > 0) {
00516 memcpy(argv + argc, con->finalArgv,
00517 sizeof(*argv) * con->finalArgvCount);
00518 argc += con->finalArgvCount;
00519 }
00520
00521 if (con->leftovers != NULL && con->numLeftovers > 0) {
00522 memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
00523 argc += con->numLeftovers;
00524 }
00525
00526 argv[argc] = NULL;
00527
00528 #if defined(hpux) || defined(__hpux)
00529 rc = setresgid(getgid(), getgid(),-1);
00530 if (rc) goto exit;
00531 rc = setresuid(getuid(), getuid(),-1);
00532 if (rc) goto exit;
00533 #else
00534
00535
00536
00537
00538
00539 #if defined(HAVE_SETUID)
00540 rc = setgid(getgid());
00541 if (rc) goto exit;
00542 rc = setuid(getuid());
00543 if (rc) goto exit;
00544 #elif defined (HAVE_SETREUID)
00545 rc = setregid(getgid(), getgid());
00546 if (rc) goto exit;
00547 rc = setreuid(getuid(), getuid());
00548 if (rc) goto exit;
00549 #else
00550 ;
00551 #endif
00552 #endif
00553
00554 #ifdef MYDEBUG
00555 if (_popt_debug)
00556 { poptArgv avp;
00557 fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
00558 for (avp = argv; *avp; avp++)
00559 fprintf(stderr, " '%s'", *avp);
00560 fprintf(stderr, "\n");
00561 }
00562 #endif
00563
00564
00565 rc = execvp(argv[0], (char *const *)argv);
00566
00567
00568 exit:
00569 if (argv) {
00570 if (argv[0])
00571 free((void *)argv[0]);
00572 free(argv);
00573 }
00574 return ec;
00575 }
00576
00577
00578 static const struct poptOption *
00579 findOption(const struct poptOption * opt,
00580 const char * longName, size_t longNameLen,
00581 char shortName,
00582 poptCallbackType * callback,
00583 const void ** callbackData,
00584 unsigned int argInfo)
00585
00586 {
00587 const struct poptOption * cb = NULL;
00588 poptArg cbarg = { .ptr = NULL };
00589
00590
00591 if (LF_ISSET(ONEDASH) && !shortName && (longName && *longName == '\0'))
00592 shortName = '-';
00593
00594 for (; opt->longName || opt->shortName || opt->arg; opt++) {
00595 poptArg arg = { .ptr = opt->arg };
00596
00597 switch (poptArgType(opt)) {
00598 case POPT_ARG_INCLUDE_TABLE:
00599 { const struct poptOption * opt2;
00600
00601 poptSubstituteHelpI18N(arg.opt);
00602 if (arg.ptr == NULL) continue;
00603 opt2 = findOption(arg.opt, longName, longNameLen, shortName, callback,
00604 callbackData, argInfo);
00605 if (opt2 == NULL) continue;
00606
00607
00608 if (callback && *callback
00609 && callbackData && *callbackData == NULL)
00610 *callbackData = opt->descrip;
00611
00612 return opt2;
00613 } break;
00614 case POPT_ARG_CALLBACK:
00615 cb = opt;
00616 cbarg.ptr = opt->arg;
00617 continue;
00618 break;
00619 default:
00620 break;
00621 }
00622
00623 if (longName != NULL && opt->longName != NULL &&
00624 (!LF_ISSET(ONEDASH) || F_ISSET(opt, ONEDASH)) &&
00625 longOptionStrcmp(opt, longName, longNameLen))
00626 {
00627 break;
00628 } else if (shortName && shortName == opt->shortName) {
00629 break;
00630 }
00631 }
00632
00633 if (opt->longName == NULL && !opt->shortName)
00634 return NULL;
00635
00636
00637 if (callback)
00638 *callback = (cb ? cbarg.cb : NULL);
00639 if (callbackData)
00640
00641 *callbackData = (cb && !CBF_ISSET(cb, INC_DATA) ? cb->descrip : NULL);
00642
00643
00644
00645 return opt;
00646 }
00647
00648 static const char * findNextArg( poptContext con,
00649 unsigned argx, int delete_arg)
00650
00651
00652
00653 {
00654 struct optionStackEntry * os = con->os;
00655 const char * arg;
00656
00657 do {
00658 int i;
00659 arg = NULL;
00660 while (os->next == os->argc && os > con->optionStack) os--;
00661 if (os->next == os->argc && os == con->optionStack) break;
00662 if (os->argv != NULL)
00663 for (i = os->next; i < os->argc; i++) {
00664
00665 if (os->argb && PBM_ISSET(i, os->argb))
00666 continue;
00667 if (*os->argv[i] == '-')
00668 continue;
00669 if (--argx > 0)
00670 continue;
00671 arg = os->argv[i];
00672 if (delete_arg) {
00673 if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
00674 if (os->argb != NULL)
00675 PBM_SET(i, os->argb);
00676 }
00677 break;
00678
00679 }
00680 if (os > con->optionStack) os--;
00681 } while (arg == NULL);
00682 return arg;
00683 }
00684
00685 static const char *
00686 expandNextArg( poptContext con, const char * s)
00687
00688
00689
00690 {
00691 const char * a = NULL;
00692 char *t, *te;
00693 size_t tn = strlen(s) + 1;
00694 char c;
00695
00696 te = t = malloc(tn);
00697 if (t == NULL) return NULL;
00698 *t = '\0';
00699 while ((c = *s++) != '\0') {
00700 switch (c) {
00701 #if 0
00702 case '\\':
00703 c = *s++;
00704 break;
00705 #endif
00706 case '!':
00707 if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
00708 break;
00709
00710 if (a == NULL) {
00711 if ((a = findNextArg(con, 1U, 1)) == NULL)
00712 break;
00713 }
00714 s += sizeof("#:+") - 1;
00715
00716 tn += strlen(a);
00717 { size_t pos = (size_t) (te - t);
00718 if ((t = realloc(t, tn)) == NULL)
00719 return NULL;
00720 te = stpcpy(t + pos, a);
00721 }
00722 continue;
00723 break;
00724 default:
00725 break;
00726 }
00727 *te++ = c;
00728 }
00729 *te++ = '\0';
00730
00731 if ((t + tn) > te) {
00732
00733 if ((te = realloc(t, (size_t)(te - t))) == NULL)
00734 free(t);
00735 t = te;
00736
00737 }
00738 return t;
00739 }
00740
00741 static void poptStripArg( poptContext con, int which)
00742
00743
00744
00745 {
00746
00747 if (con->arg_strip == NULL)
00748 con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
00749 if (con->arg_strip != NULL)
00750 PBM_SET(which, con->arg_strip);
00751 return;
00752
00753 }
00754
00755
00756 unsigned int _poptBitsN = _POPT_BITS_N;
00757
00758 unsigned int _poptBitsM = _POPT_BITS_M;
00759
00760 unsigned int _poptBitsK = _POPT_BITS_K;
00761
00762
00763 static int _poptBitsNew( poptBits *bitsp)
00764
00765
00766 {
00767 if (bitsp == NULL)
00768 return POPT_ERROR_NULLARG;
00769
00770
00771 if (*bitsp == NULL) {
00772 if (_poptBitsN == 0) {
00773 _poptBitsN = _POPT_BITS_N;
00774 _poptBitsM = _POPT_BITS_M;
00775 }
00776 if (_poptBitsM == 0U) _poptBitsM = (3 * _poptBitsN) / 2;
00777 if (_poptBitsK == 0U || _poptBitsK > 32U) _poptBitsK = _POPT_BITS_K;
00778 *bitsp = PBM_ALLOC(_poptBitsM-1);
00779 }
00780
00781 return 0;
00782
00783 }
00784
00785 int poptBitsAdd(poptBits bits, const char * s)
00786 {
00787 size_t ns = (s ? strlen(s) : 0);
00788 uint32_t h0 = 0;
00789 uint32_t h1 = 0;
00790
00791 if (bits == NULL || ns == 0)
00792 return POPT_ERROR_NULLARG;
00793
00794 poptJlu32lpair(s, ns, &h0, &h1);
00795
00796 for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
00797 uint32_t h = h0 + ns * h1;
00798 uint32_t ix = (h % _poptBitsM);
00799 PBM_SET(ix, bits);
00800 }
00801 return 0;
00802 }
00803
00804 int poptBitsChk(poptBits bits, const char * s)
00805 {
00806 size_t ns = (s ? strlen(s) : 0);
00807 uint32_t h0 = 0;
00808 uint32_t h1 = 0;
00809 int rc = 1;
00810
00811 if (bits == NULL || ns == 0)
00812 return POPT_ERROR_NULLARG;
00813
00814 poptJlu32lpair(s, ns, &h0, &h1);
00815
00816 for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
00817 uint32_t h = h0 + ns * h1;
00818 uint32_t ix = (h % _poptBitsM);
00819 if (PBM_ISSET(ix, bits))
00820 continue;
00821 rc = 0;
00822 break;
00823 }
00824 return rc;
00825 }
00826
00827 int poptBitsClr(poptBits bits)
00828 {
00829 static size_t nbw = (__PBM_NBITS/8);
00830 size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
00831
00832 if (bits == NULL)
00833 return POPT_ERROR_NULLARG;
00834 memset(bits, 0, nw * nbw);
00835 return 0;
00836 }
00837
00838 int poptBitsDel(poptBits bits, const char * s)
00839 {
00840 size_t ns = (s ? strlen(s) : 0);
00841 uint32_t h0 = 0;
00842 uint32_t h1 = 0;
00843
00844 if (bits == NULL || ns == 0)
00845 return POPT_ERROR_NULLARG;
00846
00847 poptJlu32lpair(s, ns, &h0, &h1);
00848
00849 for (ns = 0; ns < (size_t)_poptBitsK; ns++) {
00850 uint32_t h = h0 + ns * h1;
00851 uint32_t ix = (h % _poptBitsM);
00852 PBM_CLR(ix, bits);
00853 }
00854 return 0;
00855 }
00856
00857 int poptBitsIntersect(poptBits *ap, const poptBits b)
00858 {
00859 __pbm_bits *abits;
00860 __pbm_bits *bbits;
00861 __pbm_bits rc = 0;
00862 size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
00863 size_t i;
00864
00865 if (ap == NULL || b == NULL || _poptBitsNew(ap))
00866 return POPT_ERROR_NULLARG;
00867 abits = __PBM_BITS(*ap);
00868 bbits = __PBM_BITS(b);
00869
00870 for (i = 0; i < nw; i++) {
00871 abits[i] &= bbits[i];
00872 rc |= abits[i];
00873 }
00874 return (rc ? 1 : 0);
00875 }
00876
00877 int poptBitsUnion(poptBits *ap, const poptBits b)
00878 {
00879 __pbm_bits *abits;
00880 __pbm_bits *bbits;
00881 __pbm_bits rc = 0;
00882 size_t nw = (__PBM_IX(_poptBitsM-1) + 1);
00883 size_t i;
00884
00885 if (ap == NULL || b == NULL || _poptBitsNew(ap))
00886 return POPT_ERROR_NULLARG;
00887 abits = __PBM_BITS(*ap);
00888 bbits = __PBM_BITS(b);
00889
00890 for (i = 0; i < nw; i++) {
00891 abits[i] |= bbits[i];
00892 rc |= abits[i];
00893 }
00894 return (rc ? 1 : 0);
00895 }
00896
00897 int poptBitsArgs(poptContext con, poptBits *ap)
00898 {
00899 const char ** av;
00900 int rc = 0;
00901
00902 if (con == NULL || ap == NULL || _poptBitsNew(ap) ||
00903 con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
00904 return POPT_ERROR_NULLARG;
00905
00906
00907 con->leftovers[con->numLeftovers] = NULL;
00908
00909 for (av = con->leftovers + con->nextLeftover; *av != NULL; av++) {
00910 if ((rc = poptBitsAdd(*ap, *av)) != 0)
00911 break;
00912 }
00913
00914 return rc;
00915
00916 }
00917
00918 int poptSaveBits(poptBits * bitsp,
00919 UNUSED(unsigned int argInfo), const char * s)
00920 {
00921 char *tbuf = NULL;
00922 char *t, *te;
00923 int rc = 0;
00924
00925 if (bitsp == NULL || s == NULL || *s == '\0' || _poptBitsNew(bitsp))
00926 return POPT_ERROR_NULLARG;
00927
00928
00929 te = tbuf = xstrdup(s);
00930 while ((t = te) != NULL && *t) {
00931 while (*te != '\0' && *te != ',')
00932 te++;
00933 if (*te != '\0')
00934 *te++ = '\0';
00935
00936 if (*t == '\0')
00937 continue;
00938
00939 if (*t == '!') {
00940 t++;
00941 if ((rc = poptBitsChk(*bitsp, t)) > 0)
00942 rc = poptBitsDel(*bitsp, t);
00943 } else
00944 rc = poptBitsAdd(*bitsp, t);
00945 if (rc)
00946 break;
00947 }
00948 tbuf = _free(tbuf);
00949 return rc;
00950 }
00951
00952
00953 int poptSaveString(const char *** argvp,
00954 UNUSED(unsigned int argInfo), const char * val)
00955 {
00956 int argc = 0;
00957
00958 if (argvp == NULL || val == NULL)
00959 return POPT_ERROR_NULLARG;
00960
00961
00962 if (*argvp != NULL)
00963 while ((*argvp)[argc] != NULL)
00964 argc++;
00965
00966
00967 if ((*argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp))) != NULL) {
00968 (*argvp)[argc++] = xstrdup(val);
00969 (*argvp)[argc ] = NULL;
00970 }
00971 return 0;
00972
00973 }
00974
00975
00976 static unsigned int seed = 0;
00977
00978 int poptSaveLongLong(long long * arg, unsigned int argInfo, long long aLongLong)
00979 {
00980 if (arg == NULL
00981 #ifdef NOTYET
00982
00983 || (((unsigned long long)arg) & (sizeof(*arg)-1))
00984 #endif
00985 )
00986 return POPT_ERROR_NULLARG;
00987
00988 if (aLongLong != 0 && LF_ISSET(RANDOM)) {
00989 #if defined(HAVE_SRANDOM)
00990 if (!seed) {
00991 srandom((unsigned)getpid());
00992 srandom((unsigned)random());
00993 }
00994 aLongLong = (long long)(random() % (aLongLong > 0 ? aLongLong : -aLongLong));
00995 aLongLong++;
00996 #else
00997
00998 return POPT_ERROR_BADOPERATION;
00999 #endif
01000 }
01001 if (LF_ISSET(NOT))
01002 aLongLong = ~aLongLong;
01003 switch (LF_ISSET(LOGICALOPS)) {
01004 case 0:
01005 *arg = aLongLong;
01006 break;
01007 case POPT_ARGFLAG_OR:
01008 *(unsigned long long *)arg |= (unsigned long long)aLongLong;
01009 break;
01010 case POPT_ARGFLAG_AND:
01011 *(unsigned long long *)arg &= (unsigned long long)aLongLong;
01012 break;
01013 case POPT_ARGFLAG_XOR:
01014 *(unsigned long long *)arg ^= (unsigned long long)aLongLong;
01015 break;
01016 default:
01017 return POPT_ERROR_BADOPERATION;
01018 break;
01019 }
01020 return 0;
01021 }
01022
01023 int poptSaveLong(long * arg, unsigned int argInfo, long aLong)
01024 {
01025
01026 if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
01027 return POPT_ERROR_NULLARG;
01028
01029 if (aLong != 0 && LF_ISSET(RANDOM)) {
01030 #if defined(HAVE_SRANDOM)
01031 if (!seed) {
01032 srandom((unsigned)getpid());
01033 srandom((unsigned)random());
01034 }
01035 aLong = random() % (aLong > 0 ? aLong : -aLong);
01036 aLong++;
01037 #else
01038
01039 return POPT_ERROR_BADOPERATION;
01040 #endif
01041 }
01042 if (LF_ISSET(NOT))
01043 aLong = ~aLong;
01044 switch (LF_ISSET(LOGICALOPS)) {
01045 case 0: *arg = aLong; break;
01046 case POPT_ARGFLAG_OR: *(unsigned long *)arg |= (unsigned long)aLong; break;
01047 case POPT_ARGFLAG_AND: *(unsigned long *)arg &= (unsigned long)aLong; break;
01048 case POPT_ARGFLAG_XOR: *(unsigned long *)arg ^= (unsigned long)aLong; break;
01049 default:
01050 return POPT_ERROR_BADOPERATION;
01051 break;
01052 }
01053 return 0;
01054 }
01055
01056 int poptSaveInt( int * arg, unsigned int argInfo, long aLong)
01057 {
01058
01059 if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
01060 return POPT_ERROR_NULLARG;
01061
01062 if (aLong != 0 && LF_ISSET(RANDOM)) {
01063 #if defined(HAVE_SRANDOM)
01064 if (!seed) {
01065 srandom((unsigned)getpid());
01066 srandom((unsigned)random());
01067 }
01068 aLong = random() % (aLong > 0 ? aLong : -aLong);
01069 aLong++;
01070 #else
01071
01072 return POPT_ERROR_BADOPERATION;
01073 #endif
01074 }
01075 if (LF_ISSET(NOT))
01076 aLong = ~aLong;
01077 switch (LF_ISSET(LOGICALOPS)) {
01078 case 0: *arg = (int) aLong; break;
01079 case POPT_ARGFLAG_OR: *(unsigned int *)arg |= (unsigned int) aLong; break;
01080 case POPT_ARGFLAG_AND: *(unsigned int *)arg &= (unsigned int) aLong; break;
01081 case POPT_ARGFLAG_XOR: *(unsigned int *)arg ^= (unsigned int) aLong; break;
01082 default:
01083 return POPT_ERROR_BADOPERATION;
01084 break;
01085 }
01086 return 0;
01087 }
01088
01089 int poptSaveShort( short * arg, unsigned int argInfo, long aLong)
01090 {
01091
01092 if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
01093 return POPT_ERROR_NULLARG;
01094
01095 if (aLong != 0 && LF_ISSET(RANDOM)) {
01096 #if defined(HAVE_SRANDOM)
01097 if (!seed) {
01098 srandom((unsigned)getpid());
01099 srandom((unsigned)random());
01100 }
01101 aLong = random() % (aLong > 0 ? aLong : -aLong);
01102 aLong++;
01103 #else
01104
01105 return POPT_ERROR_BADOPERATION;
01106 #endif
01107 }
01108 if (LF_ISSET(NOT))
01109 aLong = ~aLong;
01110 switch (LF_ISSET(LOGICALOPS)) {
01111 case 0: *arg = (short) aLong;
01112 break;
01113 case POPT_ARGFLAG_OR: *(unsigned short *)arg |= (unsigned short) aLong;
01114 break;
01115 case POPT_ARGFLAG_AND: *(unsigned short *)arg &= (unsigned short) aLong;
01116 break;
01117 case POPT_ARGFLAG_XOR: *(unsigned short *)arg ^= (unsigned short) aLong;
01118 break;
01119 default: return POPT_ERROR_BADOPERATION;
01120 break;
01121 }
01122 return 0;
01123 }
01124
01131 static unsigned int poptArgInfo(poptContext con, const struct poptOption * opt)
01132
01133 {
01134 unsigned int argInfo = opt->argInfo;
01135
01136 if (con->os->argv != NULL && con->os->next > 0 && opt->longName != NULL)
01137 if (LF_ISSET(TOGGLE)) {
01138 const char * longName = con->os->argv[con->os->next-1];
01139 while (*longName == '-') longName++;
01140
01141 if (longName[0] != opt->longName[0] || longName[1] != opt->longName[1])
01142 {
01143 if (!LF_ISSET(XOR)) {
01144
01145 if (LF_ISSET(LOGICALOPS))
01146 argInfo ^= (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND);
01147 argInfo ^= POPT_ARGFLAG_NOT;
01148 }
01149 }
01150 }
01151 return argInfo;
01152 }
01153
01161 static int poptParseInteger(long long * llp,
01162 UNUSED(unsigned int argInfo),
01163 const char * val)
01164
01165 {
01166 if (val) {
01167 char *end = NULL;
01168 *llp = strtoll(val, &end, 0);
01169
01170
01171
01172 if (!(end && *end == '\0'))
01173 return POPT_ERROR_BADNUMBER;
01174 } else
01175 *llp = 0;
01176 return 0;
01177 }
01178
01185 static int poptSaveArg(poptContext con, const struct poptOption * opt)
01186
01187
01188 {
01189 poptArg arg = { .ptr = opt->arg };
01190 int rc = 0;
01191
01192 switch (poptArgType(opt)) {
01193 case POPT_ARG_BITSET:
01194
01195 rc = poptSaveBits(arg.ptr, opt->argInfo, con->os->nextArg);
01196 break;
01197 case POPT_ARG_ARGV:
01198
01199 rc = poptSaveString(arg.ptr, opt->argInfo, con->os->nextArg);
01200 break;
01201 case POPT_ARG_STRING:
01202
01203 arg.argv[0] = (con->os->nextArg) ? xstrdup(con->os->nextArg) : NULL;
01204 break;
01205
01206 case POPT_ARG_INT:
01207 case POPT_ARG_SHORT:
01208 case POPT_ARG_LONG:
01209 case POPT_ARG_LONGLONG:
01210 { unsigned int argInfo = poptArgInfo(con, opt);
01211 long long aNUM = 0;
01212
01213 if ((rc = poptParseInteger(&aNUM, argInfo, con->os->nextArg)) != 0)
01214 break;
01215
01216 switch (poptArgType(opt)) {
01217 case POPT_ARG_LONGLONG:
01218
01219 #if !defined(LLONG_MAX)
01220 # define LLONG_MAX 9223372036854775807LL
01221 # define LLONG_MIN (-LLONG_MAX - 1LL)
01222 #endif
01223 rc = !(aNUM == LLONG_MIN || aNUM == LLONG_MAX)
01224 ? poptSaveLongLong(arg.longlongp, argInfo, aNUM)
01225 : POPT_ERROR_OVERFLOW;
01226 break;
01227 case POPT_ARG_LONG:
01228 rc = !(aNUM < (long long)LONG_MIN || aNUM > (long long)LONG_MAX)
01229 ? poptSaveLong(arg.longp, argInfo, (long)aNUM)
01230 : POPT_ERROR_OVERFLOW;
01231 break;
01232 case POPT_ARG_INT:
01233 rc = !(aNUM < (long long)INT_MIN || aNUM > (long long)INT_MAX)
01234 ? poptSaveInt(arg.intp, argInfo, (long)aNUM)
01235 : POPT_ERROR_OVERFLOW;
01236 break;
01237 case POPT_ARG_SHORT:
01238 rc = !(aNUM < (long long)SHRT_MIN || aNUM > (long long)SHRT_MAX)
01239 ? poptSaveShort(arg.shortp, argInfo, (long)aNUM)
01240 : POPT_ERROR_OVERFLOW;
01241 break;
01242 }
01243 } break;
01244
01245 case POPT_ARG_FLOAT:
01246 case POPT_ARG_DOUBLE:
01247 { char *end = NULL;
01248 double aDouble = 0.0;
01249
01250 if (con->os->nextArg) {
01251
01252 int saveerrno = errno;
01253 errno = 0;
01254 aDouble = strtod(con->os->nextArg, &end);
01255 if (errno == ERANGE) {
01256 rc = POPT_ERROR_OVERFLOW;
01257 break;
01258 }
01259 errno = saveerrno;
01260
01261 if (*end != '\0') {
01262 rc = POPT_ERROR_BADNUMBER;
01263 break;
01264 }
01265 }
01266
01267 switch (poptArgType(opt)) {
01268 case POPT_ARG_DOUBLE:
01269 arg.doublep[0] = aDouble;
01270 break;
01271 case POPT_ARG_FLOAT:
01272 #if !defined(DBL_EPSILON) && !defined(__LCLINT__)
01273 #define DBL_EPSILON 2.2204460492503131e-16
01274 #endif
01275 #define POPT_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
01276 if ((FLT_MIN - POPT_ABS(aDouble)) > DBL_EPSILON
01277 || (POPT_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
01278 rc = POPT_ERROR_OVERFLOW;
01279 else
01280 arg.floatp[0] = (float) aDouble;
01281 break;
01282 }
01283 } break;
01284 case POPT_ARG_MAINCALL:
01285
01286 con->maincall = opt->arg;
01287
01288 break;
01289 default:
01290 fprintf(stdout, POPT_("option type (%u) not implemented in popt\n"),
01291 poptArgType(opt));
01292 exit(EXIT_FAILURE);
01293 break;
01294 }
01295 return rc;
01296 }
01297
01298
01299 int poptGetNextOpt(poptContext con)
01300 {
01301 const struct poptOption * opt = NULL;
01302 int done = 0;
01303
01304 if (con == NULL)
01305 return -1;
01306 while (!done) {
01307 const char * origOptString = NULL;
01308 poptCallbackType cb = NULL;
01309 const void * cbData = NULL;
01310 const char * longArg = NULL;
01311 int canstrip = 0;
01312 int shorty = 0;
01313
01314 while (!con->os->nextCharArg && con->os->next == con->os->argc
01315 && con->os > con->optionStack) {
01316 cleanOSE(con->os--);
01317 }
01318 if (!con->os->nextCharArg && con->os->next == con->os->argc) {
01319 invokeCallbacksPOST(con, con->options);
01320
01321 if (con->maincall) {
01322
01323 (void) (*con->maincall) (con->finalArgvCount, con->finalArgv);
01324
01325 return -1;
01326 }
01327
01328 if (con->doExec) return execCommand(con);
01329 return -1;
01330 }
01331
01332
01333 if (!con->os->nextCharArg) {
01334 const char * optString;
01335 size_t optStringLen;
01336 int thisopt;
01337
01338
01339 if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
01340 con->os->next++;
01341 continue;
01342 }
01343
01344 thisopt = con->os->next;
01345 if (con->os->argv != NULL)
01346 origOptString = con->os->argv[con->os->next++];
01347
01348 if (origOptString == NULL)
01349 return POPT_ERROR_BADOPT;
01350
01351 if (con->restLeftover || *origOptString != '-' ||
01352 (*origOptString == '-' && origOptString[1] == '\0'))
01353 {
01354 if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
01355 con->restLeftover = 1;
01356 if (con->flags & POPT_CONTEXT_ARG_OPTS) {
01357 con->os->nextArg = xstrdup(origOptString);
01358 return 0;
01359 }
01360 if (con->leftovers != NULL)
01361 con->leftovers[con->numLeftovers++] = origOptString;
01362 continue;
01363 }
01364
01365
01366 optString = origOptString;
01367
01368 if (optString[0] == '\0')
01369 return POPT_ERROR_BADOPT;
01370
01371 if (optString[1] == '-' && !optString[2]) {
01372 con->restLeftover = 1;
01373 continue;
01374 } else {
01375 const char *oe;
01376 unsigned int argInfo = 0;
01377
01378 optString++;
01379 if (*optString == '-')
01380 optString++;
01381 else
01382 argInfo |= POPT_ARGFLAG_ONEDASH;
01383
01384
01385 for (oe = optString; *oe && *oe != '='; oe++)
01386 {};
01387 optStringLen = (size_t)(oe - optString);
01388 if (*oe == '=')
01389 longArg = oe + 1;
01390
01391
01392 if (handleAlias(con, optString, optStringLen, '\0', longArg)) {
01393 longArg = NULL;
01394 continue;
01395 }
01396
01397 if (handleExec(con, optString, '\0'))
01398 continue;
01399
01400 opt = findOption(con->options, optString, optStringLen, '\0', &cb, &cbData,
01401 argInfo);
01402 if (!opt && !LF_ISSET(ONEDASH))
01403 return POPT_ERROR_BADOPT;
01404 }
01405
01406 if (!opt) {
01407 con->os->nextCharArg = origOptString + 1;
01408 longArg = NULL;
01409 } else {
01410 if (con->os == con->optionStack && F_ISSET(opt, STRIP))
01411 {
01412 canstrip = 1;
01413 poptStripArg(con, thisopt);
01414 }
01415 shorty = 0;
01416 }
01417 }
01418
01419
01420 if (con->os->nextCharArg) {
01421 const char * nextCharArg = con->os->nextCharArg;
01422
01423 con->os->nextCharArg = NULL;
01424
01425 if (handleAlias(con, NULL, 0, *nextCharArg, nextCharArg + 1))
01426 continue;
01427
01428 if (handleExec(con, NULL, *nextCharArg)) {
01429
01430 nextCharArg++;
01431 if (*nextCharArg != '\0')
01432 con->os->nextCharArg = nextCharArg;
01433 continue;
01434 }
01435
01436 opt = findOption(con->options, NULL, 0, *nextCharArg, &cb,
01437 &cbData, 0);
01438 if (!opt)
01439 return POPT_ERROR_BADOPT;
01440 shorty = 1;
01441
01442 nextCharArg++;
01443 if (*nextCharArg != '\0')
01444 con->os->nextCharArg = nextCharArg + (int)(*nextCharArg == '=');
01445 }
01446
01447 if (opt == NULL) return POPT_ERROR_BADOPT;
01448 if (opt->arg && poptArgType(opt) == POPT_ARG_NONE) {
01449 unsigned int argInfo = poptArgInfo(con, opt);
01450 if (poptSaveInt((int *)opt->arg, argInfo, 1L))
01451 return POPT_ERROR_BADOPERATION;
01452 } else if (poptArgType(opt) == POPT_ARG_VAL) {
01453 if (opt->arg) {
01454 unsigned int argInfo = poptArgInfo(con, opt);
01455 if (poptSaveInt((int *)opt->arg, argInfo, (long)opt->val))
01456 return POPT_ERROR_BADOPERATION;
01457 }
01458 } else if (poptArgType(opt) != POPT_ARG_NONE) {
01459 int rc;
01460
01461 con->os->nextArg = _free(con->os->nextArg);
01462 if (longArg) {
01463 longArg = expandNextArg(con, longArg);
01464 con->os->nextArg = (char *) longArg;
01465 } else if (con->os->nextCharArg) {
01466 longArg = expandNextArg(con, con->os->nextCharArg);
01467 con->os->nextArg = (char *) longArg;
01468 con->os->nextCharArg = NULL;
01469 } else {
01470 while (con->os->next == con->os->argc &&
01471 con->os > con->optionStack)
01472 {
01473 cleanOSE(con->os--);
01474 }
01475 if (con->os->next == con->os->argc) {
01476 if (!F_ISSET(opt, OPTIONAL))
01477 return POPT_ERROR_NOARG;
01478 con->os->nextArg = NULL;
01479 } else {
01480
01481
01482
01483
01484
01485 if (con->os == con->optionStack
01486 && F_ISSET(opt, STRIP) && canstrip)
01487 {
01488 poptStripArg(con, con->os->next);
01489 }
01490
01491 if (con->os->argv != NULL) {
01492 if (F_ISSET(opt, OPTIONAL) &&
01493 con->os->argv[con->os->next][0] == '-') {
01494 con->os->nextArg = NULL;
01495 } else {
01496
01497 longArg = con->os->argv[con->os->next++];
01498 longArg = expandNextArg(con, longArg);
01499 con->os->nextArg = (char *) longArg;
01500 }
01501 }
01502 }
01503 }
01504 longArg = NULL;
01505
01506
01507 if (opt->arg != NULL && (rc = poptSaveArg(con, opt)) != 0)
01508 return rc;
01509 }
01510
01511 if (cb)
01512 invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
01513 else if (opt->val && (poptArgType(opt) != POPT_ARG_VAL))
01514 done = 1;
01515
01516 if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
01517 con->finalArgvAlloced += 10;
01518 con->finalArgv = realloc(con->finalArgv,
01519 sizeof(*con->finalArgv) * con->finalArgvAlloced);
01520 }
01521
01522 if (con->finalArgv != NULL)
01523 { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + sizeof("--"));
01524 if (s != NULL) {
01525 con->finalArgv[con->finalArgvCount++] = s;
01526 *s++ = '-';
01527 if (opt->longName) {
01528 if (!F_ISSET(opt, ONEDASH))
01529 *s++ = '-';
01530 s = stpcpy(s, opt->longName);
01531 } else {
01532 *s++ = opt->shortName;
01533 *s = '\0';
01534 }
01535 } else
01536 con->finalArgv[con->finalArgvCount++] = NULL;
01537 }
01538
01539 if (opt->arg && poptArgType(opt) == POPT_ARG_NONE)
01540 ;
01541 else if (poptArgType(opt) == POPT_ARG_VAL)
01542 ;
01543 else if (poptArgType(opt) != POPT_ARG_NONE) {
01544 if (con->finalArgv != NULL && con->os->nextArg != NULL)
01545 con->finalArgv[con->finalArgvCount++] =
01546 xstrdup(con->os->nextArg);
01547 }
01548 }
01549
01550 return (opt ? opt->val : -1);
01551 }
01552
01553 char * poptGetOptArg(poptContext con)
01554 {
01555 char * ret = NULL;
01556 if (con) {
01557 ret = con->os->nextArg;
01558 con->os->nextArg = NULL;
01559 }
01560 return ret;
01561 }
01562
01563 const char * poptGetArg(poptContext con)
01564 {
01565 const char * ret = NULL;
01566 if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
01567 ret = con->leftovers[con->nextLeftover++];
01568 return ret;
01569 }
01570
01571 const char * poptPeekArg(poptContext con)
01572 {
01573 const char * ret = NULL;
01574 if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
01575 ret = con->leftovers[con->nextLeftover];
01576 return ret;
01577 }
01578
01579 const char ** poptGetArgs(poptContext con)
01580 {
01581 if (con == NULL ||
01582 con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
01583 return NULL;
01584
01585
01586 con->leftovers[con->numLeftovers] = NULL;
01587
01588
01589 return (con->leftovers + con->nextLeftover);
01590
01591 }
01592
01593 static
01594 poptItem poptFreeItems( poptItem items, int nitems)
01595
01596 {
01597 if (items != NULL) {
01598 poptItem item = items;
01599 while (--nitems >= 0) {
01600
01601 item->option.longName = _free(item->option.longName);
01602 item->option.descrip = _free(item->option.descrip);
01603 item->option.argDescrip = _free(item->option.argDescrip);
01604
01605 item->argv = _free(item->argv);
01606 item++;
01607 }
01608 items = _free(items);
01609 }
01610 return NULL;
01611 }
01612
01613 poptContext poptFreeContext(poptContext con)
01614 {
01615 if (con == NULL) return con;
01616 poptResetContext(con);
01617 con->os->argb = _free(con->os->argb);
01618
01619 con->aliases = poptFreeItems(con->aliases, con->numAliases);
01620 con->numAliases = 0;
01621
01622 con->execs = poptFreeItems(con->execs, con->numExecs);
01623 con->numExecs = 0;
01624
01625 con->leftovers = _free(con->leftovers);
01626 con->finalArgv = _free(con->finalArgv);
01627 con->appName = _free(con->appName);
01628 con->otherHelp = _free(con->otherHelp);
01629 con->execPath = _free(con->execPath);
01630 con->arg_strip = PBM_FREE(con->arg_strip);
01631
01632 con = _free(con);
01633 return con;
01634 }
01635
01636 int poptAddAlias(poptContext con, struct poptAlias alias,
01637 UNUSED(int flags))
01638 {
01639 struct poptItem_s item_buf;
01640 poptItem item = &item_buf;
01641 memset(item, 0, sizeof(*item));
01642 item->option.longName = alias.longName;
01643 item->option.shortName = alias.shortName;
01644 item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
01645 item->option.arg = 0;
01646 item->option.val = 0;
01647 item->option.descrip = NULL;
01648 item->option.argDescrip = NULL;
01649 item->argc = alias.argc;
01650 item->argv = alias.argv;
01651 return poptAddItem(con, item, 0);
01652 }
01653
01654 int poptAddItem(poptContext con, poptItem newItem, int flags)
01655 {
01656 poptItem * items, item;
01657 int * nitems;
01658
01659 switch (flags) {
01660 case 1:
01661 items = &con->execs;
01662 nitems = &con->numExecs;
01663 break;
01664 case 0:
01665 items = &con->aliases;
01666 nitems = &con->numAliases;
01667 break;
01668 default:
01669 return 1;
01670 break;
01671 }
01672
01673 *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
01674 if ((*items) == NULL)
01675 return 1;
01676
01677 item = (*items) + (*nitems);
01678
01679 item->option.longName =
01680 (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
01681 item->option.shortName = newItem->option.shortName;
01682 item->option.argInfo = newItem->option.argInfo;
01683 item->option.arg = newItem->option.arg;
01684 item->option.val = newItem->option.val;
01685 item->option.descrip =
01686 (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
01687 item->option.argDescrip =
01688 (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
01689 item->argc = newItem->argc;
01690 item->argv = newItem->argv;
01691
01692 (*nitems)++;
01693
01694 return 0;
01695 }
01696
01697 const char * poptBadOption(poptContext con, unsigned int flags)
01698 {
01699 struct optionStackEntry * os = NULL;
01700
01701 if (con != NULL)
01702 os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
01703
01704 return (os != NULL && os->argv != NULL ? os->argv[os->next - 1] : NULL);
01705 }
01706
01707 const char * poptStrerror(const int error)
01708 {
01709 switch (error) {
01710 case POPT_ERROR_NOARG:
01711 return POPT_("missing argument");
01712 case POPT_ERROR_BADOPT:
01713 return POPT_("unknown option");
01714 case POPT_ERROR_BADOPERATION:
01715 return POPT_("mutually exclusive logical operations requested");
01716 case POPT_ERROR_NULLARG:
01717 return POPT_("opt->arg should not be NULL");
01718 case POPT_ERROR_OPTSTOODEEP:
01719 return POPT_("aliases nested too deeply");
01720 case POPT_ERROR_BADQUOTE:
01721 return POPT_("error in parameter quoting");
01722 case POPT_ERROR_BADNUMBER:
01723 return POPT_("invalid numeric value");
01724 case POPT_ERROR_OVERFLOW:
01725 return POPT_("number too large or too small");
01726 case POPT_ERROR_MALLOC:
01727 return POPT_("memory allocation failed");
01728 case POPT_ERROR_BADCONFIG:
01729 return POPT_("config file failed sanity test");
01730 case POPT_ERROR_ERRNO:
01731 return strerror(errno);
01732 default:
01733 return POPT_("unknown error");
01734 }
01735 }
01736
01737 int poptStuffArgs(poptContext con, const char ** argv)
01738 {
01739 int argc;
01740 int rc;
01741
01742 if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
01743 return POPT_ERROR_OPTSTOODEEP;
01744
01745 for (argc = 0; argv[argc]; argc++)
01746 {};
01747
01748 con->os++;
01749 con->os->next = 0;
01750 con->os->nextArg = NULL;
01751 con->os->nextCharArg = NULL;
01752 con->os->currAlias = NULL;
01753 rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
01754 con->os->argb = NULL;
01755 con->os->stuffed = 1;
01756
01757 return rc;
01758 }
01759
01760 const char * poptGetInvocationName(poptContext con)
01761 {
01762 return (con->os->argv ? con->os->argv[0] : "");
01763 }
01764
01765 int poptStrippedArgv(poptContext con, int argc, char ** argv)
01766 {
01767 int numargs = argc;
01768 int j = 1;
01769 int i;
01770
01771
01772 if (con->arg_strip)
01773 for (i = 1; i < argc; i++) {
01774 if (PBM_ISSET(i, con->arg_strip))
01775 numargs--;
01776 }
01777
01778 for (i = 1; i < argc; i++) {
01779 if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
01780 continue;
01781 argv[j] = (j < numargs) ? argv[i] : NULL;
01782 j++;
01783 }
01784
01785
01786 return numargs;
01787 }