5 /* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
6 file accompanying popt source distributions, available from
7 ftp://ftp.rpm.org/pub/rpm/dist */
22 static char * strerror(int errno
) {
24 extern char * sys_errlist
[];
26 if ((0 <= errno
) && (errno
< sys_nerr
))
27 return sys_errlist
[errno
];
29 return POPT_("unknown errno");
34 /*@unused@*/ static void prtcon(const char *msg
, poptContext con
)
36 if (msg
) fprintf(stderr
, "%s", msg
);
37 fprintf(stderr
, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
39 (con
->os
->nextCharArg
? con
->os
->nextCharArg
: ""),
40 (con
->os
->nextArg
? con
->os
->nextArg
: ""),
42 (con
->os
->argv
&& con
->os
->argv
[con
->os
->next
]
43 ? con
->os
->argv
[con
->os
->next
] : ""));
47 void poptSetExecPath(poptContext con
, const char * path
, int allowAbsolute
)
49 con
->execPath
= _free(con
->execPath
);
50 con
->execPath
= xstrdup(path
);
51 con
->execAbsolute
= allowAbsolute
;
52 /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
57 static void invokeCallbacksPRE(poptContext con
, const struct poptOption
* opt
)
58 /*@globals internalState@*/
59 /*@modifies internalState@*/
62 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
63 if (opt
->arg
== NULL
) continue; /* XXX program error. */
64 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
65 /* Recurse on included sub-tables. */
66 invokeCallbacksPRE(con
, opt
->arg
);
67 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
68 (opt
->argInfo
& POPT_CBFLAG_PRE
))
70 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
72 /* Perform callback. */
73 /*@-moduncon -noeffectuncon @*/
74 cb(con
, POPT_CALLBACK_REASON_PRE
, NULL
, NULL
, opt
->descrip
);
75 /*@=moduncon =noeffectuncon @*/
80 static void invokeCallbacksPOST(poptContext con
, const struct poptOption
* opt
)
81 /*@globals internalState@*/
82 /*@modifies internalState@*/
85 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
86 if (opt
->arg
== NULL
) continue; /* XXX program error. */
87 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
88 /* Recurse on included sub-tables. */
89 invokeCallbacksPOST(con
, opt
->arg
);
90 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
91 (opt
->argInfo
& POPT_CBFLAG_POST
))
93 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
95 /* Perform callback. */
96 /*@-moduncon -noeffectuncon @*/
97 cb(con
, POPT_CALLBACK_REASON_POST
, NULL
, NULL
, opt
->descrip
);
98 /*@=moduncon =noeffectuncon @*/
103 static void invokeCallbacksOPTION(poptContext con
,
104 const struct poptOption
* opt
,
105 const struct poptOption
* myOpt
,
106 /*@null@*/ const void * myData
, int shorty
)
107 /*@globals internalState@*/
108 /*@modifies internalState@*/
110 const struct poptOption
* cbopt
= NULL
;
113 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
114 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
115 /* Recurse on included sub-tables. */
116 if (opt
->arg
!= NULL
) /* XXX program error */
117 invokeCallbacksOPTION(con
, opt
->arg
, myOpt
, myData
, shorty
);
118 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
119 !(opt
->argInfo
& POPT_CBFLAG_SKIPOPTION
)) {
120 /* Save callback info. */
122 } else if (cbopt
!= NULL
&&
123 ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
124 myOpt
->shortName
== opt
->shortName
) ||
125 (myOpt
->longName
&& opt
->longName
&&
126 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
127 !strcmp(myOpt
->longName
, opt
->longName
)))
131 poptCallbackType cb
= (poptCallbackType
)cbopt
->arg
;
133 const void * cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
134 /* Perform callback. */
135 if (cb
!= NULL
) { /* XXX program error */
136 /*@-moduncon -noeffectuncon @*/
137 cb(con
, POPT_CALLBACK_REASON_OPTION
, myOpt
,
138 con
->os
->nextArg
, cbData
);
139 /*@=moduncon =noeffectuncon @*/
141 /* Terminate (unless explcitly continuing). */
142 if (!(cbopt
->argInfo
& POPT_CBFLAG_CONTINUE
))
148 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
149 const struct poptOption
* options
, int flags
)
151 poptContext con
= malloc(sizeof(*con
));
153 if (con
== NULL
) return NULL
; /* XXX can't happen */
154 memset(con
, 0, sizeof(*con
));
156 con
->os
= con
->optionStack
;
157 con
->os
->argc
= argc
;
158 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
159 con
->os
->argv
= argv
;
160 /*@=dependenttrans =assignexpose@*/
161 con
->os
->argb
= NULL
;
163 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
164 con
->os
->next
= 1; /* skip argv[0] */
166 con
->leftovers
= calloc( (argc
+ 1), sizeof(*con
->leftovers
) );
167 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
168 con
->options
= options
;
169 /*@=dependenttrans =assignexpose@*/
175 con
->finalArgvAlloced
= argc
* 2;
176 con
->finalArgv
= calloc( con
->finalArgvAlloced
, sizeof(*con
->finalArgv
) );
177 con
->execAbsolute
= 1;
178 con
->arg_strip
= NULL
;
180 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
181 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
184 char * t
= malloc(strlen(name
) + 1);
185 if (t
) con
->appName
= strcpy(t
, name
);
189 invokeCallbacksPRE(con
, con
->options
);
195 static void cleanOSE(/*@special@*/ struct optionStackEntry
*os
)
197 /*@releases os->nextArg, os->argv, os->argb @*/
200 os
->nextArg
= _free(os
->nextArg
);
201 os
->argv
= _free(os
->argv
);
202 os
->argb
= PBM_FREE(os
->argb
);
205 void poptResetContext(poptContext con
)
209 if (con
== NULL
) return;
210 while (con
->os
> con
->optionStack
) {
213 con
->os
->argb
= PBM_FREE(con
->os
->argb
);
214 con
->os
->currAlias
= NULL
;
215 con
->os
->nextCharArg
= NULL
;
216 con
->os
->nextArg
= NULL
;
217 con
->os
->next
= 1; /* skip argv[0] */
219 con
->numLeftovers
= 0;
220 con
->nextLeftover
= 0;
221 con
->restLeftover
= 0;
224 if (con
->finalArgv
!= NULL
)
225 for (i
= 0; i
< con
->finalArgvCount
; i
++)
226 /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
227 con
->finalArgv
[i
] = _free(con
->finalArgv
[i
]);
228 /*@=unqualifiedtrans@*/
230 con
->finalArgvCount
= 0;
231 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
232 /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
237 /* Only one of longName, shortName should be set, not both. */
238 static int handleExec(/*@special@*/ poptContext con
,
239 /*@null@*/ const char * longName
, char shortName
)
240 /*@uses con->execs, con->numExecs, con->flags, con->doExec,
241 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
247 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
250 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
251 item
= con
->execs
+ i
;
252 if (longName
&& !(item
->option
.longName
&&
253 !strcmp(longName
, item
->option
.longName
)))
255 else if (shortName
!= item
->option
.shortName
)
262 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
265 if (con
->doExec
== NULL
) {
266 con
->doExec
= con
->execs
+ i
;
270 /* We already have an exec to do; remember this option for next
272 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
273 con
->finalArgvAlloced
+= 10;
274 con
->finalArgv
= realloc(con
->finalArgv
,
275 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
278 i
= con
->finalArgvCount
++;
279 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
280 { char *s
= malloc((longName
? strlen(longName
) : 0) + 3);
281 if (s
!= NULL
) { /* XXX can't happen */
283 sprintf(s
, "--%s", longName
);
285 sprintf(s
, "-%c", shortName
);
286 con
->finalArgv
[i
] = s
;
288 con
->finalArgv
[i
] = NULL
;
291 /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
296 /* Only one of longName, shortName may be set at a time */
297 static int handleAlias(/*@special@*/ poptContext con
,
298 /*@null@*/ const char * longName
, char shortName
,
299 /*@keep@*/ /*@null@*/ const char * nextCharArg
)
300 /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
301 con->os->currAlias, con->os->currAlias->option.longName @*/
304 poptItem item
= con
->os
->currAlias
;
309 if (longName
&& (item
->option
.longName
&&
310 !strcmp(longName
, item
->option
.longName
)))
312 if (shortName
&& shortName
== item
->option
.shortName
)
316 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
319 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
320 item
= con
->aliases
+ i
;
321 if (longName
&& !(item
->option
.longName
&&
322 !strcmp(longName
, item
->option
.longName
)))
324 else if (shortName
!= item
->option
.shortName
)
330 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
331 return POPT_ERROR_OPTSTOODEEP
;
333 if (nextCharArg
&& *nextCharArg
)
334 con
->os
->nextCharArg
= nextCharArg
;
338 con
->os
->stuffed
= 0;
339 con
->os
->nextArg
= NULL
;
340 con
->os
->nextCharArg
= NULL
;
341 con
->os
->currAlias
= con
->aliases
+ i
;
342 rc
= poptDupArgv(con
->os
->currAlias
->argc
, con
->os
->currAlias
->argv
,
343 &con
->os
->argc
, &con
->os
->argv
);
344 con
->os
->argb
= NULL
;
346 return (rc
? rc
: 1);
349 static int execCommand(poptContext con
)
352 poptItem item
= con
->doExec
;
357 if (item
== NULL
) /*XXX can't happen*/
358 return POPT_ERROR_NOARG
;
360 if (item
->argv
== NULL
|| item
->argc
< 1 ||
361 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
362 return POPT_ERROR_NOARG
;
364 argv
= malloc(sizeof(*argv
) *
365 (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
366 if (argv
== NULL
) return POPT_ERROR_MALLOC
; /* XXX can't happen */
368 if (!strchr(item
->argv
[0], '/') && con
->execPath
) {
369 char *s
= alloca(strlen(con
->execPath
) + strlen(item
->argv
[0]) + sizeof("/"));
370 sprintf(s
, "%s/%s", con
->execPath
, item
->argv
[0]);
373 argv
[argc
] = findProgramPath(item
->argv
[0]);
375 if (argv
[argc
++] == NULL
) return POPT_ERROR_NOARG
;
377 if (item
->argc
> 1) {
378 memcpy(argv
+ argc
, item
->argv
+ 1, sizeof(*argv
) * (item
->argc
- 1));
379 argc
+= (item
->argc
- 1);
382 if (con
->finalArgv
!= NULL
&& con
->finalArgvCount
> 0) {
383 memcpy(argv
+ argc
, con
->finalArgv
,
384 sizeof(*argv
) * con
->finalArgvCount
);
385 argc
+= con
->finalArgvCount
;
388 if (con
->leftovers
!= NULL
&& con
->numLeftovers
> 0) {
392 memcpy(argv
+ argc
, con
->leftovers
, sizeof(*argv
) * con
->numLeftovers
);
393 argc
+= con
->numLeftovers
;
399 rc
= setresuid(getuid(), getuid(),-1);
400 if (rc
) return POPT_ERROR_ERRNO
;
403 * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
404 * XXX sez' Timur Bakeyev <mc@bat.ru>
405 * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
407 #if defined(HAVE_SETUID)
408 rc
= setuid(getuid());
409 if (rc
) return POPT_ERROR_ERRNO
;
410 #elif defined (HAVE_SETREUID)
411 rc
= setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
412 if (rc
) return POPT_ERROR_ERRNO
;
414 ; /* Can't drop privileges */
419 return POPT_ERROR_NOARG
;
422 fprintf(stderr
, "==> execvp(%s) argv[%d]:", argv
[0], argc
);
423 for (avp
= argv
; *avp
; avp
++)
424 fprintf(stderr
, " '%s'", *avp
);
425 fprintf(stderr
, "\n");
429 rc
= execvp(argv
[0], (char *const *)argv
);
430 return POPT_ERROR_ERRNO
;
433 /*@observer@*/ /*@null@*/ static const struct poptOption
*
434 findOption(const struct poptOption
* opt
, /*@null@*/ const char * longName
,
436 /*@null@*/ /*@out@*/ poptCallbackType
* callback
,
437 /*@null@*/ /*@out@*/ const void ** callbackData
,
439 /*@modifies *callback, *callbackData */
441 const struct poptOption
* cb
= NULL
;
443 /* This happens when a single - is given */
444 if (singleDash
&& !shortName
&& (longName
&& *longName
== '\0'))
447 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
449 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
450 const struct poptOption
* opt2
;
452 /* Recurse on included sub-tables. */
453 if (opt
->arg
== NULL
) continue; /* XXX program error */
454 opt2
= findOption(opt
->arg
, longName
, shortName
, callback
,
455 callbackData
, singleDash
);
456 if (opt2
== NULL
) continue;
457 /* Sub-table data will be inheirited if no data yet. */
458 if (!(callback
&& *callback
)) return opt2
;
459 if (!(callbackData
&& *callbackData
== NULL
)) return opt2
;
460 /*@-observertrans -dependenttrans @*/
461 *callbackData
= opt
->descrip
;
462 /*@=observertrans =dependenttrans @*/
464 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
) {
466 } else if (longName
&& opt
->longName
&&
467 (!singleDash
|| (opt
->argInfo
& POPT_ARGFLAG_ONEDASH
)) &&
468 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
469 !strcmp(longName
, opt
->longName
))
473 } else if (shortName
&& shortName
== opt
->shortName
) {
478 if (!opt
->longName
&& !opt
->shortName
)
480 /*@-modobserver -mods @*/
481 if (callback
) *callback
= NULL
;
482 if (callbackData
) *callbackData
= NULL
;
486 *callback
= (poptCallbackType
)cb
->arg
;
488 if (!(cb
->argInfo
& POPT_CBFLAG_INC_DATA
)) {
490 /*@-observertrans@*/ /* FIX: typedef double indirection. */
491 *callbackData
= cb
->descrip
;
495 /*@=modobserver =mods @*/
500 static const char * findNextArg(/*@special@*/ poptContext con
,
501 unsigned argx
, int delete_arg
)
502 /*@uses con->optionStack, con->os,
503 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
506 struct optionStackEntry
* os
= con
->os
;
512 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
513 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
514 if (os
->argv
!= NULL
)
515 for (i
= os
->next
; i
< os
->argc
; i
++) {
517 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
518 /*@innercontinue@*/ continue;
519 if (*os
->argv
[i
] == '-')
520 /*@innercontinue@*/ continue;
522 /*@innercontinue@*/ continue;
525 if (os
->argb
== NULL
) os
->argb
= PBM_ALLOC(os
->argc
);
526 if (os
->argb
!= NULL
) /* XXX can't happen */
527 PBM_SET(i
, os
->argb
);
529 /*@innerbreak@*/ break;
532 if (os
> con
->optionStack
) os
--;
533 } while (arg
== NULL
);
537 static /*@only@*/ /*@null@*/ const char *
538 expandNextArg(/*@special@*/ poptContext con
, const char * s
)
539 /*@uses con->optionStack, con->os,
540 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
543 const char * a
= NULL
;
546 size_t tn
= strlen(s
) + 1;
549 te
= t
= malloc(tn
);;
550 if (t
== NULL
) return NULL
; /* XXX can't happen */
551 while ((c
= *s
++) != '\0') {
553 #if 0 /* XXX can't do this */
554 case '\\': /* escape */
556 /*@switchbreak@*/ break;
559 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
560 /*@switchbreak@*/ break;
561 /* XXX Make sure that findNextArg deletes only next arg. */
563 if ((a
= findNextArg(con
, 1, 1)) == NULL
)
564 /*@switchbreak@*/ break;
573 strncpy(te
, a
, alen
); te
+= alen
;
575 /*@notreached@*/ /*@switchbreak@*/ break;
577 /*@switchbreak@*/ break;
582 t
= realloc(t
, strlen(t
) + 1); /* XXX memory leak, hard to plug */
586 static void poptStripArg(/*@special@*/ poptContext con
, int which
)
587 /*@uses con->arg_strip, con->optionStack @*/
588 /*@defines con->arg_strip @*/
592 if (con
->arg_strip
== NULL
)
593 con
->arg_strip
= PBM_ALLOC(con
->optionStack
[0].argc
);
594 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
595 PBM_SET(which
, con
->arg_strip
);
597 /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
602 static int poptSaveLong(const struct poptOption
* opt
, long aLong
)
603 /*@modifies opt->arg @*/
605 if (opt
->arg
== NULL
)
606 return POPT_ERROR_NULLARG
;
608 if (opt
->argInfo
& POPT_ARGFLAG_NOT
)
610 switch (opt
->argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
612 *((long *) opt
->arg
) = aLong
;
614 case POPT_ARGFLAG_OR
:
615 *((long *) opt
->arg
) |= aLong
;
617 case POPT_ARGFLAG_AND
:
618 *((long *) opt
->arg
) &= aLong
;
620 case POPT_ARGFLAG_XOR
:
621 *((long *) opt
->arg
) ^= aLong
;
624 return POPT_ERROR_BADOPERATION
;
625 /*@notreached@*/ break;
630 static int poptSaveInt(const struct poptOption
* opt
, long aLong
)
631 /*@modifies opt->arg @*/
633 if (opt
->arg
== NULL
)
634 return POPT_ERROR_NULLARG
;
636 if (opt
->argInfo
& POPT_ARGFLAG_NOT
)
638 switch (opt
->argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
640 *((int *) opt
->arg
) = aLong
;
642 case POPT_ARGFLAG_OR
:
643 *((int *) opt
->arg
) |= aLong
;
645 case POPT_ARGFLAG_AND
:
646 *((int *) opt
->arg
) &= aLong
;
648 case POPT_ARGFLAG_XOR
:
649 *((int *) opt
->arg
) ^= aLong
;
652 return POPT_ERROR_BADOPERATION
;
653 /*@notreached@*/ break;
658 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
659 int poptGetNextOpt(poptContext con
)
661 const struct poptOption
* opt
= NULL
;
667 const char * origOptString
= NULL
;
668 poptCallbackType cb
= NULL
;
669 const void * cbData
= NULL
;
670 const char * longArg
= NULL
;
674 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
675 && con
->os
> con
->optionStack
) {
678 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
680 invokeCallbacksPOST(con
, con
->options
);
682 if (con
->doExec
) return execCommand(con
);
686 /* Process next long option */
687 if (!con
->os
->nextCharArg
) {
688 char * localOptString
, * optString
;
692 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
697 thisopt
= con
->os
->next
;
698 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
699 origOptString
= con
->os
->argv
[con
->os
->next
++];
701 if (origOptString
== NULL
) /* XXX can't happen */
702 return POPT_ERROR_BADOPT
;
704 if (con
->restLeftover
|| *origOptString
!= '-') {
705 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
706 con
->restLeftover
= 1;
707 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
708 con
->os
->nextArg
= xstrdup(origOptString
);
711 if (con
->leftovers
!= NULL
) /* XXX can't happen */
712 con
->leftovers
[con
->numLeftovers
++] = origOptString
;
716 /* Make a copy we can hack at */
717 localOptString
= optString
=
718 strcpy(alloca(strlen(origOptString
) + 1), origOptString
);
720 if (optString
[0] == '\0')
721 return POPT_ERROR_BADOPT
;
723 if (optString
[1] == '-' && !optString
[2]) {
724 con
->restLeftover
= 1;
731 if (*optString
== '-')
732 singleDash
= 0, optString
++;
736 /* XXX aliases with arg substitution need "--alias=arg" */
737 if (handleAlias(con
, optString
, '\0', NULL
))
740 if (handleExec(con
, optString
, '\0'))
743 /* Check for "--long=arg" option. */
744 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
748 /* XXX longArg is mapped back to persistent storage. */
749 longArg
= origOptString
+ (oe
- localOptString
);
752 opt
= findOption(con
->options
, optString
, '\0', &cb
, &cbData
,
754 if (!opt
&& !singleDash
)
755 return POPT_ERROR_BADOPT
;
759 con
->os
->nextCharArg
= origOptString
+ 1;
761 if (con
->os
== con
->optionStack
&&
762 opt
->argInfo
& POPT_ARGFLAG_STRIP
)
765 poptStripArg(con
, thisopt
);
771 /* Process next short option */
772 /*@-branchstate@*/ /* FIX: W2DO? */
773 if (con
->os
->nextCharArg
) {
774 origOptString
= con
->os
->nextCharArg
;
776 con
->os
->nextCharArg
= NULL
;
778 if (handleAlias(con
, NULL
, *origOptString
, origOptString
+ 1))
781 if (handleExec(con
, NULL
, *origOptString
)) {
782 /* Restore rest of short options for further processing */
784 if (*origOptString
!= '\0')
785 con
->os
->nextCharArg
= origOptString
;
789 opt
= findOption(con
->options
, NULL
, *origOptString
, &cb
,
792 return POPT_ERROR_BADOPT
;
796 if (*origOptString
!= '\0')
797 con
->os
->nextCharArg
= origOptString
;
801 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
802 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
) {
803 if (poptSaveInt(opt
, 1L))
804 return POPT_ERROR_BADOPERATION
;
805 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
) {
807 if (poptSaveInt(opt
, (long)opt
->val
))
808 return POPT_ERROR_BADOPERATION
;
810 } else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
811 con
->os
->nextArg
= _free(con
->os
->nextArg
);
812 /*@-usedef@*/ /* FIX: W2DO? */
815 longArg
= expandNextArg(con
, longArg
);
816 con
->os
->nextArg
= longArg
;
817 } else if (con
->os
->nextCharArg
) {
818 longArg
= expandNextArg(con
, con
->os
->nextCharArg
);
819 con
->os
->nextArg
= longArg
;
820 con
->os
->nextCharArg
= NULL
;
822 while (con
->os
->next
== con
->os
->argc
&&
823 con
->os
> con
->optionStack
) {
826 if (con
->os
->next
== con
->os
->argc
) {
827 if (!(opt
->argInfo
& POPT_ARGFLAG_OPTIONAL
))
828 /*@-compdef@*/ /* FIX: con->os->argv not defined */
829 return POPT_ERROR_NOARG
;
831 con
->os
->nextArg
= NULL
;
835 * Make sure this isn't part of a short arg or the
836 * result of an alias expansion.
838 if (con
->os
== con
->optionStack
&&
839 (opt
->argInfo
& POPT_ARGFLAG_STRIP
) &&
841 poptStripArg(con
, con
->os
->next
);
844 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
845 /* XXX watchout: subtle side-effects live here. */
846 longArg
= con
->os
->argv
[con
->os
->next
++];
847 longArg
= expandNextArg(con
, longArg
);
848 con
->os
->nextArg
= longArg
;
855 switch (opt
->argInfo
& POPT_ARG_MASK
) {
856 case POPT_ARG_STRING
:
857 /* XXX memory leak, hard to plug */
858 *((const char **) opt
->arg
) = (con
->os
->nextArg
)
859 ? xstrdup(con
->os
->nextArg
) : NULL
;
860 /*@switchbreak@*/ break;
867 if (con
->os
->nextArg
) {
868 aLong
= strtol(con
->os
->nextArg
, &end
, 0);
869 if (!(end
&& *end
== '\0'))
870 return POPT_ERROR_BADNUMBER
;
873 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_LONG
) {
874 if (aLong
== LONG_MIN
|| aLong
== LONG_MAX
)
875 return POPT_ERROR_OVERFLOW
;
876 if (poptSaveLong(opt
, aLong
))
877 return POPT_ERROR_BADOPERATION
;
879 if (aLong
> INT_MAX
|| aLong
< INT_MIN
)
880 return POPT_ERROR_OVERFLOW
;
881 if (poptSaveInt(opt
, aLong
))
882 return POPT_ERROR_BADOPERATION
;
884 } /*@switchbreak@*/ break;
887 case POPT_ARG_DOUBLE
:
888 { double aDouble
= 0.0;
891 if (con
->os
->nextArg
) {
893 int saveerrno
= errno
;
895 aDouble
= strtod(con
->os
->nextArg
, &end
);
897 return POPT_ERROR_OVERFLOW
;
901 return POPT_ERROR_BADNUMBER
;
904 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_DOUBLE
) {
905 *((double *) opt
->arg
) = aDouble
;
908 #define DBL_EPSILON 2.2204460492503131e-16
910 #define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
911 if ((MY_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
912 return POPT_ERROR_OVERFLOW
;
913 if ((FLT_MIN
- MY_ABS(aDouble
)) > DBL_EPSILON
)
914 return POPT_ERROR_OVERFLOW
;
915 *((float *) opt
->arg
) = aDouble
;
917 } /*@switchbreak@*/ break;
920 POPT_("option type (%d) not implemented in popt\n"),
921 (opt
->argInfo
& POPT_ARG_MASK
));
923 /*@notreached@*/ /*@switchbreak@*/ break;
930 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
932 } else if (opt
->val
&& ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_VAL
))
935 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
936 con
->finalArgvAlloced
+= 10;
937 con
->finalArgv
= realloc(con
->finalArgv
,
938 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
941 if (con
->finalArgv
!= NULL
)
942 { char *s
= malloc((opt
->longName
? strlen(opt
->longName
) : 0) + 3);
943 if (s
!= NULL
) { /* XXX can't happen */
946 ((opt
->argInfo
& POPT_ARGFLAG_ONEDASH
) ? "-" : "--"),
949 sprintf(s
, "-%c", opt
->shortName
);
950 con
->finalArgv
[con
->finalArgvCount
++] = s
;
952 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
955 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
)
956 /*@-ifempty@*/ ; /*@=ifempty@*/
957 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
)
958 /*@-ifempty@*/ ; /*@=ifempty@*/
959 else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
960 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
)
961 con
->finalArgv
[con
->finalArgvCount
++] =
962 /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
963 xstrdup(con
->os
->nextArg
);
968 return (opt
? opt
->val
: -1); /* XXX can't happen */
971 const char * poptGetOptArg(poptContext con
)
973 const char * ret
= NULL
;
976 ret
= con
->os
->nextArg
;
977 con
->os
->nextArg
= NULL
;
983 const char * poptGetArg(poptContext con
)
985 const char * ret
= NULL
;
986 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
987 ret
= con
->leftovers
[con
->nextLeftover
++];
991 const char * poptPeekArg(poptContext con
)
993 const char * ret
= NULL
;
994 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
995 ret
= con
->leftovers
[con
->nextLeftover
];
999 const char ** poptGetArgs(poptContext con
)
1002 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1005 /* some apps like [like RPM ;-) ] need this NULL terminated */
1006 con
->leftovers
[con
->numLeftovers
] = NULL
;
1008 /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
1009 return (con
->leftovers
+ con
->nextLeftover
);
1010 /*@=nullret =nullstate @*/
1013 poptContext
poptFreeContext(poptContext con
)
1018 if (con
== NULL
) return con
;
1019 poptResetContext(con
);
1020 con
->os
->argb
= _free(con
->os
->argb
);
1022 if (con
->aliases
!= NULL
)
1023 for (i
= 0; i
< con
->numAliases
; i
++) {
1024 item
= con
->aliases
+ i
;
1025 /*@-modobserver -observertrans -dependenttrans@*/
1026 item
->option
.longName
= _free(item
->option
.longName
);
1027 item
->option
.descrip
= _free(item
->option
.descrip
);
1028 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1029 /*@=modobserver =observertrans =dependenttrans@*/
1030 item
->argv
= _free(item
->argv
);
1032 con
->aliases
= _free(con
->aliases
);
1034 if (con
->execs
!= NULL
)
1035 for (i
= 0; i
< con
->numExecs
; i
++) {
1036 item
= con
->execs
+ i
;
1037 /*@-modobserver -observertrans -dependenttrans@*/
1038 item
->option
.longName
= _free(item
->option
.longName
);
1039 item
->option
.descrip
= _free(item
->option
.descrip
);
1040 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1041 /*@=modobserver =observertrans =dependenttrans@*/
1042 item
->argv
= _free(item
->argv
);
1044 con
->execs
= _free(con
->execs
);
1046 con
->leftovers
= _free(con
->leftovers
);
1047 con
->finalArgv
= _free(con
->finalArgv
);
1048 con
->appName
= _free(con
->appName
);
1049 con
->otherHelp
= _free(con
->otherHelp
);
1050 con
->execPath
= _free(con
->execPath
);
1051 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
1057 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1058 /*@unused@*/ UNUSED(int flags
))
1060 poptItem item
= (poptItem
) alloca(sizeof(*item
));
1061 memset(item
, 0, sizeof(*item
));
1062 item
->option
.longName
= alias
.longName
;
1063 item
->option
.shortName
= alias
.shortName
;
1064 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1065 item
->option
.arg
= 0;
1066 item
->option
.val
= 0;
1067 item
->option
.descrip
= NULL
;
1068 item
->option
.argDescrip
= NULL
;
1069 item
->argc
= alias
.argc
;
1070 item
->argv
= alias
.argv
;
1071 return poptAddItem(con
, item
, 0);
1074 /*@-mustmod@*/ /* LCL: con not modified? */
1075 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1077 poptItem
* items
, item
;
1082 items
= &con
->execs
;
1083 nitems
= &con
->numExecs
;
1086 items
= &con
->aliases
;
1087 nitems
= &con
->numAliases
;
1091 /*@notreached@*/ break;
1094 *items
= realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1095 if ((*items
) == NULL
)
1098 item
= (*items
) + (*nitems
);
1100 item
->option
.longName
=
1101 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1102 item
->option
.shortName
= newItem
->option
.shortName
;
1103 item
->option
.argInfo
= newItem
->option
.argInfo
;
1104 item
->option
.arg
= newItem
->option
.arg
;
1105 item
->option
.val
= newItem
->option
.val
;
1106 item
->option
.descrip
=
1107 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1108 item
->option
.argDescrip
=
1109 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1110 item
->argc
= newItem
->argc
;
1111 item
->argv
= newItem
->argv
;
1119 const char * poptBadOption(poptContext con
, int flags
)
1121 struct optionStackEntry
* os
= NULL
;
1124 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1126 /*@-nullderef@*/ /* LCL: os->argv != NULL */
1127 return (os
&& os
->argv
? os
->argv
[os
->next
- 1] : NULL
);
1131 const char * poptStrerror(const int error
)
1134 case POPT_ERROR_NOARG
:
1135 return POPT_("missing argument");
1136 case POPT_ERROR_BADOPT
:
1137 return POPT_("unknown option");
1138 case POPT_ERROR_BADOPERATION
:
1139 return POPT_("mutually exclusive logical operations requested");
1140 case POPT_ERROR_NULLARG
:
1141 return POPT_("opt->arg should not be NULL");
1142 case POPT_ERROR_OPTSTOODEEP
:
1143 return POPT_("aliases nested too deeply");
1144 case POPT_ERROR_BADQUOTE
:
1145 return POPT_("error in parameter quoting");
1146 case POPT_ERROR_BADNUMBER
:
1147 return POPT_("invalid numeric value");
1148 case POPT_ERROR_OVERFLOW
:
1149 return POPT_("number too large or too small");
1150 case POPT_ERROR_MALLOC
:
1151 return POPT_("memory allocation failed");
1152 case POPT_ERROR_ERRNO
:
1153 return strerror(errno
);
1155 return POPT_("unknown error");
1159 int poptStuffArgs(poptContext con
, const char ** argv
)
1164 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1165 return POPT_ERROR_OPTSTOODEEP
;
1167 for (argc
= 0; argv
[argc
]; argc
++)
1172 con
->os
->nextArg
= NULL
;
1173 con
->os
->nextCharArg
= NULL
;
1174 con
->os
->currAlias
= NULL
;
1175 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1176 con
->os
->argb
= NULL
;
1177 con
->os
->stuffed
= 1;
1182 const char * poptGetInvocationName(poptContext con
)
1184 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1187 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1195 for (i
= 1; i
< argc
; i
++) {
1196 if (PBM_ISSET(i
, con
->arg_strip
))
1200 for (i
= 1; i
< argc
; i
++) {
1201 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1203 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;