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