5 /* (C) 1998-2002 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 */
27 static char * strerror(int errno
) {
29 extern char * sys_errlist
[];
31 if ((0 <= errno
) && (errno
< sys_nerr
))
32 return sys_errlist
[errno
];
34 return POPT_("unknown errno");
39 /*@unused@*/ static void prtcon(const char *msg
, poptContext con
)
41 if (msg
) fprintf(stderr
, "%s", msg
);
42 fprintf(stderr
, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
44 (con
->os
->nextCharArg
? con
->os
->nextCharArg
: ""),
45 (con
->os
->nextArg
? con
->os
->nextArg
: ""),
47 (con
->os
->argv
&& con
->os
->argv
[con
->os
->next
]
48 ? con
->os
->argv
[con
->os
->next
] : ""));
52 void poptSetExecPath(poptContext con
, const char * path
, int allowAbsolute
)
54 con
->execPath
= _free(con
->execPath
);
55 con
->execPath
= xstrdup(path
);
56 con
->execAbsolute
= allowAbsolute
;
57 /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
62 static void invokeCallbacksPRE(poptContext con
, const struct poptOption
* opt
)
63 /*@globals internalState@*/
64 /*@modifies internalState@*/
67 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
68 if (opt
->arg
== NULL
) continue; /* XXX program error. */
69 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
70 /* Recurse on included sub-tables. */
71 invokeCallbacksPRE(con
, opt
->arg
);
72 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
73 (opt
->argInfo
& POPT_CBFLAG_PRE
))
75 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
77 /* Perform callback. */
78 /*@-moduncon -noeffectuncon @*/
79 cb(con
, POPT_CALLBACK_REASON_PRE
, NULL
, NULL
, opt
->descrip
);
80 /*@=moduncon =noeffectuncon @*/
85 static void invokeCallbacksPOST(poptContext con
, const struct poptOption
* opt
)
86 /*@globals internalState@*/
87 /*@modifies internalState@*/
90 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
91 if (opt
->arg
== NULL
) continue; /* XXX program error. */
92 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
93 /* Recurse on included sub-tables. */
94 invokeCallbacksPOST(con
, opt
->arg
);
95 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
96 (opt
->argInfo
& POPT_CBFLAG_POST
))
98 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
100 /* Perform callback. */
101 /*@-moduncon -noeffectuncon @*/
102 cb(con
, POPT_CALLBACK_REASON_POST
, NULL
, NULL
, opt
->descrip
);
103 /*@=moduncon =noeffectuncon @*/
108 static void invokeCallbacksOPTION(poptContext con
,
109 const struct poptOption
* opt
,
110 const struct poptOption
* myOpt
,
111 /*@null@*/ const void * myData
, int shorty
)
112 /*@globals internalState@*/
113 /*@modifies internalState@*/
115 const struct poptOption
* cbopt
= NULL
;
118 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
119 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
120 /* Recurse on included sub-tables. */
121 if (opt
->arg
!= NULL
) /* XXX program error */
122 invokeCallbacksOPTION(con
, opt
->arg
, myOpt
, myData
, shorty
);
123 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
124 !(opt
->argInfo
& POPT_CBFLAG_SKIPOPTION
)) {
125 /* Save callback info. */
127 } else if (cbopt
!= NULL
&&
128 ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
129 myOpt
->shortName
== opt
->shortName
) ||
130 (myOpt
->longName
&& opt
->longName
&&
131 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
132 !strcmp(myOpt
->longName
, opt
->longName
)))
136 poptCallbackType cb
= (poptCallbackType
)cbopt
->arg
;
138 const void * cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
139 /* Perform callback. */
140 if (cb
!= NULL
) { /* XXX program error */
141 /*@-moduncon -noeffectuncon @*/
142 cb(con
, POPT_CALLBACK_REASON_OPTION
, myOpt
,
143 con
->os
->nextArg
, cbData
);
144 /*@=moduncon =noeffectuncon @*/
146 /* Terminate (unless explcitly continuing). */
147 if (!(cbopt
->argInfo
& POPT_CBFLAG_CONTINUE
))
153 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
154 const struct poptOption
* options
, int flags
)
156 poptContext con
= malloc(sizeof(*con
));
158 if (con
== NULL
) return NULL
; /* XXX can't happen */
159 memset(con
, 0, sizeof(*con
));
161 con
->os
= con
->optionStack
;
162 con
->os
->argc
= argc
;
163 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
164 con
->os
->argv
= argv
;
165 /*@=dependenttrans =assignexpose@*/
166 con
->os
->argb
= NULL
;
168 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
169 con
->os
->next
= 1; /* skip argv[0] */
171 con
->leftovers
= calloc( (argc
+ 1), sizeof(*con
->leftovers
) );
172 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
173 con
->options
= options
;
174 /*@=dependenttrans =assignexpose@*/
180 con
->finalArgvAlloced
= argc
* 2;
181 con
->finalArgv
= calloc( con
->finalArgvAlloced
, sizeof(*con
->finalArgv
) );
182 con
->execAbsolute
= 1;
183 con
->arg_strip
= NULL
;
185 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
186 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
189 char * t
= malloc(strlen(name
) + 1);
190 if (t
) con
->appName
= strcpy(t
, name
);
194 invokeCallbacksPRE(con
, con
->options
);
200 static void cleanOSE(/*@special@*/ struct optionStackEntry
*os
)
202 /*@releases os->nextArg, os->argv, os->argb @*/
205 os
->nextArg
= _free(os
->nextArg
);
206 os
->argv
= _free(os
->argv
);
207 os
->argb
= PBM_FREE(os
->argb
);
211 void poptResetContext(poptContext con
)
215 if (con
== NULL
) return;
216 while (con
->os
> con
->optionStack
) {
219 con
->os
->argb
= PBM_FREE(con
->os
->argb
);
220 con
->os
->currAlias
= NULL
;
221 con
->os
->nextCharArg
= NULL
;
222 con
->os
->nextArg
= NULL
;
223 con
->os
->next
= 1; /* skip argv[0] */
225 con
->numLeftovers
= 0;
226 con
->nextLeftover
= 0;
227 con
->restLeftover
= 0;
230 if (con
->finalArgv
!= NULL
)
231 for (i
= 0; i
< con
->finalArgvCount
; i
++) {
232 /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
233 con
->finalArgv
[i
] = _free(con
->finalArgv
[i
]);
234 /*@=unqualifiedtrans@*/
237 con
->finalArgvCount
= 0;
238 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
239 /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
245 /* Only one of longName, shortName should be set, not both. */
247 static int handleExec(/*@special@*/ poptContext con
,
248 /*@null@*/ const char * longName
, char shortName
)
249 /*@uses con->execs, con->numExecs, con->flags, con->doExec,
250 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
256 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
259 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
260 item
= con
->execs
+ i
;
261 if (longName
&& !(item
->option
.longName
&&
262 !strcmp(longName
, item
->option
.longName
)))
264 else if (shortName
!= item
->option
.shortName
)
271 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
274 if (con
->doExec
== NULL
) {
275 con
->doExec
= con
->execs
+ i
;
279 /* We already have an exec to do; remember this option for next
281 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
282 con
->finalArgvAlloced
+= 10;
283 con
->finalArgv
= realloc(con
->finalArgv
,
284 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
287 i
= con
->finalArgvCount
++;
288 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
289 { char *s
= malloc((longName
? strlen(longName
) : 0) + 3);
290 if (s
!= NULL
) { /* XXX can't happen */
292 sprintf(s
, "--%s", longName
);
294 sprintf(s
, "-%c", shortName
);
295 con
->finalArgv
[i
] = s
;
297 con
->finalArgv
[i
] = NULL
;
300 /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
306 /* Only one of longName, shortName may be set at a time */
307 static int handleAlias(/*@special@*/ poptContext con
,
308 /*@null@*/ const char * longName
, char shortName
,
309 /*@exposed@*/ /*@null@*/ const char * nextCharArg
)
310 /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
311 con->os->currAlias, con->os->currAlias->option.longName @*/
314 poptItem item
= con
->os
->currAlias
;
319 if (longName
&& (item
->option
.longName
&&
320 !strcmp(longName
, item
->option
.longName
)))
322 if (shortName
&& shortName
== item
->option
.shortName
)
326 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
329 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
330 item
= con
->aliases
+ i
;
331 if (longName
&& !(item
->option
.longName
&&
332 !strcmp(longName
, item
->option
.longName
)))
334 else if (shortName
!= item
->option
.shortName
)
340 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
341 return POPT_ERROR_OPTSTOODEEP
;
344 if (nextCharArg
&& *nextCharArg
)
345 con
->os
->nextCharArg
= nextCharArg
;
350 con
->os
->stuffed
= 0;
351 con
->os
->nextArg
= NULL
;
352 con
->os
->nextCharArg
= NULL
;
353 con
->os
->currAlias
= con
->aliases
+ i
;
354 rc
= poptDupArgv(con
->os
->currAlias
->argc
, con
->os
->currAlias
->argv
,
355 &con
->os
->argc
, &con
->os
->argv
);
356 con
->os
->argb
= NULL
;
358 return (rc
? rc
: 1);
361 /*@-bounds -boundswrite @*/
362 static int execCommand(poptContext con
)
363 /*@globals internalState @*/
364 /*@modifies internalState @*/
366 poptItem item
= con
->doExec
;
371 if (item
== NULL
) /*XXX can't happen*/
372 return POPT_ERROR_NOARG
;
374 if (item
->argv
== NULL
|| item
->argc
< 1 ||
375 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
376 return POPT_ERROR_NOARG
;
378 argv
= malloc(sizeof(*argv
) *
379 (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
380 if (argv
== NULL
) return POPT_ERROR_MALLOC
; /* XXX can't happen */
382 if (!strchr(item
->argv
[0], '/') && con
->execPath
) {
383 char *s
= alloca(strlen(con
->execPath
) + strlen(item
->argv
[0]) + sizeof("/"));
384 sprintf(s
, "%s/%s", con
->execPath
, item
->argv
[0]);
387 argv
[argc
] = findProgramPath(item
->argv
[0]);
389 if (argv
[argc
++] == NULL
) return POPT_ERROR_NOARG
;
391 if (item
->argc
> 1) {
392 memcpy(argv
+ argc
, item
->argv
+ 1, sizeof(*argv
) * (item
->argc
- 1));
393 argc
+= (item
->argc
- 1);
396 if (con
->finalArgv
!= NULL
&& con
->finalArgvCount
> 0) {
397 memcpy(argv
+ argc
, con
->finalArgv
,
398 sizeof(*argv
) * con
->finalArgvCount
);
399 argc
+= con
->finalArgvCount
;
402 if (con
->leftovers
!= NULL
&& con
->numLeftovers
> 0) {
406 memcpy(argv
+ argc
, con
->leftovers
, sizeof(*argv
) * con
->numLeftovers
);
407 argc
+= con
->numLeftovers
;
413 rc
= setresuid(getuid(), getuid(),-1);
414 if (rc
) return POPT_ERROR_ERRNO
;
417 * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
418 * XXX sez' Timur Bakeyev <mc@bat.ru>
419 * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
421 #if defined(HAVE_SETUID)
422 rc
= setuid(getuid());
423 if (rc
) return POPT_ERROR_ERRNO
;
424 #elif defined (HAVE_SETREUID)
425 rc
= setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
426 if (rc
) return POPT_ERROR_ERRNO
;
428 ; /* Can't drop privileges */
433 return POPT_ERROR_NOARG
;
438 fprintf(stderr
, "==> execvp(%s) argv[%d]:", argv
[0], argc
);
439 for (avp
= argv
; *avp
; avp
++)
440 fprintf(stderr
, " '%s'", *avp
);
441 fprintf(stderr
, "\n");
445 rc
= execvp(argv
[0], (char *const *)argv
);
447 return POPT_ERROR_ERRNO
;
449 /*@=bounds =boundswrite @*/
452 /*@observer@*/ /*@null@*/ static const struct poptOption
*
453 findOption(const struct poptOption
* opt
, /*@null@*/ const char * longName
,
455 /*@null@*/ /*@out@*/ poptCallbackType
* callback
,
456 /*@null@*/ /*@out@*/ const void ** callbackData
,
458 /*@modifies *callback, *callbackData */
460 const struct poptOption
* cb
= NULL
;
462 /* This happens when a single - is given */
463 if (singleDash
&& !shortName
&& (longName
&& *longName
== '\0'))
466 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
468 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
469 const struct poptOption
* opt2
;
471 /* Recurse on included sub-tables. */
472 if (opt
->arg
== NULL
) continue; /* XXX program error */
473 opt2
= findOption(opt
->arg
, longName
, shortName
, callback
,
474 callbackData
, singleDash
);
475 if (opt2
== NULL
) continue;
476 /* Sub-table data will be inheirited if no data yet. */
477 if (!(callback
&& *callback
)) return opt2
;
478 if (!(callbackData
&& *callbackData
== NULL
)) return opt2
;
479 /*@-observertrans -dependenttrans @*/
480 *callbackData
= opt
->descrip
;
481 /*@=observertrans =dependenttrans @*/
483 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
) {
485 } else if (longName
&& opt
->longName
&&
486 (!singleDash
|| (opt
->argInfo
& POPT_ARGFLAG_ONEDASH
)) &&
487 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
488 !strcmp(longName
, opt
->longName
))
492 } else if (shortName
&& shortName
== opt
->shortName
) {
497 if (!opt
->longName
&& !opt
->shortName
)
499 /*@-modobserver -mods @*/
500 if (callback
) *callback
= NULL
;
501 if (callbackData
) *callbackData
= NULL
;
505 *callback
= (poptCallbackType
)cb
->arg
;
507 if (!(cb
->argInfo
& POPT_CBFLAG_INC_DATA
)) {
509 /*@-observertrans@*/ /* FIX: typedef double indirection. */
510 *callbackData
= cb
->descrip
;
514 /*@=modobserver =mods @*/
520 static const char * findNextArg(/*@special@*/ poptContext con
,
521 unsigned argx
, int delete_arg
)
522 /*@uses con->optionStack, con->os,
523 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
526 struct optionStackEntry
* os
= con
->os
;
532 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
533 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
534 if (os
->argv
!= NULL
)
535 for (i
= os
->next
; i
< os
->argc
; i
++) {
537 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
538 /*@innercontinue@*/ continue;
539 if (*os
->argv
[i
] == '-')
540 /*@innercontinue@*/ continue;
542 /*@innercontinue@*/ continue;
545 if (os
->argb
== NULL
) os
->argb
= PBM_ALLOC(os
->argc
);
546 if (os
->argb
!= NULL
) /* XXX can't happen */
547 PBM_SET(i
, os
->argb
);
549 /*@innerbreak@*/ break;
552 if (os
> con
->optionStack
) os
--;
553 } while (arg
== NULL
);
558 static /*@only@*/ /*@null@*/ const char *
559 expandNextArg(/*@special@*/ poptContext con
, const char * s
)
560 /*@uses con->optionStack, con->os,
561 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
564 const char * a
= NULL
;
567 size_t tn
= strlen(s
) + 1;
570 te
= t
= malloc(tn
);;
571 if (t
== NULL
) return NULL
; /* XXX can't happen */
572 while ((c
= *s
++) != '\0') {
574 #if 0 /* XXX can't do this */
575 case '\\': /* escape */
577 /*@switchbreak@*/ break;
580 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
581 /*@switchbreak@*/ break;
582 /* XXX Make sure that findNextArg deletes only next arg. */
584 if ((a
= findNextArg(con
, 1, 1)) == NULL
)
585 /*@switchbreak@*/ break;
594 strncpy(te
, a
, alen
); te
+= alen
;
596 /*@notreached@*/ /*@switchbreak@*/ break;
598 /*@switchbreak@*/ break;
603 t
= realloc(t
, strlen(t
) + 1); /* XXX memory leak, hard to plug */
608 static void poptStripArg(/*@special@*/ poptContext con
, int which
)
609 /*@uses con->arg_strip, con->optionStack @*/
610 /*@defines con->arg_strip @*/
614 if (con
->arg_strip
== NULL
)
615 con
->arg_strip
= PBM_ALLOC(con
->optionStack
[0].argc
);
616 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
617 PBM_SET(which
, con
->arg_strip
);
619 /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
624 int poptSaveLong(long * arg
, int argInfo
, long aLong
)
626 /* XXX Check alignment, may fail on funky platforms. */
627 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
628 return POPT_ERROR_NULLARG
;
630 if (argInfo
& POPT_ARGFLAG_NOT
)
632 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
636 case POPT_ARGFLAG_OR
:
639 case POPT_ARGFLAG_AND
:
642 case POPT_ARGFLAG_XOR
:
646 return POPT_ERROR_BADOPERATION
;
647 /*@notreached@*/ break;
652 int poptSaveInt(/*@null@*/ int * arg
, int argInfo
, long aLong
)
654 /* XXX Check alignment, may fail on funky platforms. */
655 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
656 return POPT_ERROR_NULLARG
;
658 if (argInfo
& POPT_ARGFLAG_NOT
)
660 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
664 case POPT_ARGFLAG_OR
:
667 case POPT_ARGFLAG_AND
:
670 case POPT_ARGFLAG_XOR
:
674 return POPT_ERROR_BADOPERATION
;
675 /*@notreached@*/ break;
681 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
682 int poptGetNextOpt(poptContext con
)
684 const struct poptOption
* opt
= NULL
;
690 const char * origOptString
= NULL
;
691 poptCallbackType cb
= NULL
;
692 const void * cbData
= NULL
;
693 const char * longArg
= NULL
;
697 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
698 && con
->os
> con
->optionStack
) {
701 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
703 invokeCallbacksPOST(con
, con
->options
);
705 if (con
->doExec
) return execCommand(con
);
709 /* Process next long option */
710 if (!con
->os
->nextCharArg
) {
711 char * localOptString
, * optString
;
715 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
720 thisopt
= con
->os
->next
;
721 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
722 origOptString
= con
->os
->argv
[con
->os
->next
++];
724 if (origOptString
== NULL
) /* XXX can't happen */
725 return POPT_ERROR_BADOPT
;
727 if (con
->restLeftover
|| *origOptString
!= '-') {
728 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
729 con
->restLeftover
= 1;
730 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
731 con
->os
->nextArg
= xstrdup(origOptString
);
734 if (con
->leftovers
!= NULL
) /* XXX can't happen */
735 con
->leftovers
[con
->numLeftovers
++] = origOptString
;
739 /* Make a copy we can hack at */
740 localOptString
= optString
=
741 strcpy(alloca(strlen(origOptString
) + 1), origOptString
);
743 if (optString
[0] == '\0')
744 return POPT_ERROR_BADOPT
;
746 if (optString
[1] == '-' && !optString
[2]) {
747 con
->restLeftover
= 1;
754 if (*optString
== '-')
755 singleDash
= 0, optString
++;
759 /* XXX aliases with arg substitution need "--alias=arg" */
760 if (handleAlias(con
, optString
, '\0', NULL
))
763 if (handleExec(con
, optString
, '\0'))
766 /* Check for "--long=arg" option. */
767 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
771 /* XXX longArg is mapped back to persistent storage. */
772 longArg
= origOptString
+ (oe
- localOptString
);
775 opt
= findOption(con
->options
, optString
, '\0', &cb
, &cbData
,
777 if (!opt
&& !singleDash
)
778 return POPT_ERROR_BADOPT
;
782 con
->os
->nextCharArg
= origOptString
+ 1;
784 if (con
->os
== con
->optionStack
&&
785 opt
->argInfo
& POPT_ARGFLAG_STRIP
)
788 poptStripArg(con
, thisopt
);
794 /* Process next short option */
795 /*@-branchstate@*/ /* FIX: W2DO? */
796 if (con
->os
->nextCharArg
) {
797 origOptString
= con
->os
->nextCharArg
;
799 con
->os
->nextCharArg
= NULL
;
801 if (handleAlias(con
, NULL
, *origOptString
, origOptString
+ 1))
804 if (handleExec(con
, NULL
, *origOptString
)) {
805 /* Restore rest of short options for further processing */
807 if (*origOptString
!= '\0')
808 con
->os
->nextCharArg
= origOptString
;
812 opt
= findOption(con
->options
, NULL
, *origOptString
, &cb
,
815 return POPT_ERROR_BADOPT
;
819 if (*origOptString
!= '\0')
820 con
->os
->nextCharArg
= origOptString
;
824 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
825 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
) {
826 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, 1L))
827 return POPT_ERROR_BADOPERATION
;
828 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
) {
830 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, (long)opt
->val
))
831 return POPT_ERROR_BADOPERATION
;
833 } else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
834 con
->os
->nextArg
= _free(con
->os
->nextArg
);
835 /*@-usedef@*/ /* FIX: W2DO? */
838 longArg
= expandNextArg(con
, longArg
);
839 con
->os
->nextArg
= longArg
;
840 } else if (con
->os
->nextCharArg
) {
841 longArg
= expandNextArg(con
, con
->os
->nextCharArg
);
842 con
->os
->nextArg
= longArg
;
843 con
->os
->nextCharArg
= NULL
;
845 while (con
->os
->next
== con
->os
->argc
&&
846 con
->os
> con
->optionStack
) {
849 if (con
->os
->next
== con
->os
->argc
) {
850 if (!(opt
->argInfo
& POPT_ARGFLAG_OPTIONAL
))
851 /*@-compdef@*/ /* FIX: con->os->argv not defined */
852 return POPT_ERROR_NOARG
;
854 con
->os
->nextArg
= NULL
;
858 * Make sure this isn't part of a short arg or the
859 * result of an alias expansion.
861 if (con
->os
== con
->optionStack
&&
862 (opt
->argInfo
& POPT_ARGFLAG_STRIP
) &&
864 poptStripArg(con
, con
->os
->next
);
867 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
868 /* XXX watchout: subtle side-effects live here. */
869 longArg
= con
->os
->argv
[con
->os
->next
++];
870 longArg
= expandNextArg(con
, longArg
);
871 con
->os
->nextArg
= longArg
;
878 switch (opt
->argInfo
& POPT_ARG_MASK
) {
879 case POPT_ARG_STRING
:
880 /* XXX memory leak, hard to plug */
881 *((const char **) opt
->arg
) = (con
->os
->nextArg
)
882 ? xstrdup(con
->os
->nextArg
) : NULL
;
883 /*@switchbreak@*/ break;
890 if (con
->os
->nextArg
) {
891 aLong
= strtol(con
->os
->nextArg
, &end
, 0);
892 if (!(end
&& *end
== '\0'))
893 return POPT_ERROR_BADNUMBER
;
896 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_LONG
) {
897 if (aLong
== LONG_MIN
|| aLong
== LONG_MAX
)
898 return POPT_ERROR_OVERFLOW
;
899 if (poptSaveLong((long *)opt
->arg
, opt
->argInfo
, aLong
))
900 return POPT_ERROR_BADOPERATION
;
902 if (aLong
> INT_MAX
|| aLong
< INT_MIN
)
903 return POPT_ERROR_OVERFLOW
;
904 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, aLong
))
905 return POPT_ERROR_BADOPERATION
;
907 } /*@switchbreak@*/ break;
910 case POPT_ARG_DOUBLE
:
911 { double aDouble
= 0.0;
914 if (con
->os
->nextArg
) {
916 int saveerrno
= errno
;
918 aDouble
= strtod(con
->os
->nextArg
, &end
);
920 return POPT_ERROR_OVERFLOW
;
924 return POPT_ERROR_BADNUMBER
;
927 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_DOUBLE
) {
928 *((double *) opt
->arg
) = aDouble
;
931 #define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
933 if ((_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
934 return POPT_ERROR_OVERFLOW
;
935 if ((FLT_MIN
- _ABS(aDouble
)) > DBL_EPSILON
)
936 return POPT_ERROR_OVERFLOW
;
937 *((float *) opt
->arg
) = aDouble
;
939 } /*@switchbreak@*/ break;
942 POPT_("option type (%d) not implemented in popt\n"),
943 (opt
->argInfo
& POPT_ARG_MASK
));
945 /*@notreached@*/ /*@switchbreak@*/ break;
952 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
954 } else if (opt
->val
&& ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_VAL
))
957 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
958 con
->finalArgvAlloced
+= 10;
959 con
->finalArgv
= realloc(con
->finalArgv
,
960 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
963 if (con
->finalArgv
!= NULL
)
964 { char *s
= malloc((opt
->longName
? strlen(opt
->longName
) : 0) + 3);
965 if (s
!= NULL
) { /* XXX can't happen */
968 ((opt
->argInfo
& POPT_ARGFLAG_ONEDASH
) ? "-" : "--"),
971 sprintf(s
, "-%c", opt
->shortName
);
972 con
->finalArgv
[con
->finalArgvCount
++] = s
;
974 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
977 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
)
978 /*@-ifempty@*/ ; /*@=ifempty@*/
979 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
)
980 /*@-ifempty@*/ ; /*@=ifempty@*/
981 else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
982 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
)
983 con
->finalArgv
[con
->finalArgvCount
++] =
984 /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
985 xstrdup(con
->os
->nextArg
);
990 return (opt
? opt
->val
: -1); /* XXX can't happen */
994 const char * poptGetOptArg(poptContext con
)
996 const char * ret
= NULL
;
999 ret
= con
->os
->nextArg
;
1000 con
->os
->nextArg
= NULL
;
1006 const char * poptGetArg(poptContext con
)
1008 const char * ret
= NULL
;
1009 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1010 ret
= con
->leftovers
[con
->nextLeftover
++];
1014 const char * poptPeekArg(poptContext con
)
1016 const char * ret
= NULL
;
1017 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1018 ret
= con
->leftovers
[con
->nextLeftover
];
1023 const char ** poptGetArgs(poptContext con
)
1026 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1029 /* some apps like [like RPM ;-) ] need this NULL terminated */
1030 con
->leftovers
[con
->numLeftovers
] = NULL
;
1032 /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
1033 return (con
->leftovers
+ con
->nextLeftover
);
1034 /*@=nullret =nullstate @*/
1038 poptContext
poptFreeContext(poptContext con
)
1043 if (con
== NULL
) return con
;
1044 poptResetContext(con
);
1045 con
->os
->argb
= _free(con
->os
->argb
);
1047 if (con
->aliases
!= NULL
)
1048 for (i
= 0; i
< con
->numAliases
; i
++) {
1049 item
= con
->aliases
+ i
;
1050 /*@-modobserver -observertrans -dependenttrans@*/
1051 item
->option
.longName
= _free(item
->option
.longName
);
1052 item
->option
.descrip
= _free(item
->option
.descrip
);
1053 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1054 /*@=modobserver =observertrans =dependenttrans@*/
1055 item
->argv
= _free(item
->argv
);
1057 con
->aliases
= _free(con
->aliases
);
1059 if (con
->execs
!= NULL
)
1060 for (i
= 0; i
< con
->numExecs
; i
++) {
1061 item
= con
->execs
+ i
;
1062 /*@-modobserver -observertrans -dependenttrans@*/
1063 item
->option
.longName
= _free(item
->option
.longName
);
1064 item
->option
.descrip
= _free(item
->option
.descrip
);
1065 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1066 /*@=modobserver =observertrans =dependenttrans@*/
1067 item
->argv
= _free(item
->argv
);
1069 con
->execs
= _free(con
->execs
);
1071 con
->leftovers
= _free(con
->leftovers
);
1072 con
->finalArgv
= _free(con
->finalArgv
);
1073 con
->appName
= _free(con
->appName
);
1074 con
->otherHelp
= _free(con
->otherHelp
);
1075 con
->execPath
= _free(con
->execPath
);
1076 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
1082 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1083 /*@unused@*/ int flags
)
1085 poptItem item
= alloca(sizeof(*item
));
1086 memset(item
, 0, sizeof(*item
));
1087 item
->option
.longName
= alias
.longName
;
1088 item
->option
.shortName
= alias
.shortName
;
1089 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1090 item
->option
.arg
= 0;
1091 item
->option
.val
= 0;
1092 item
->option
.descrip
= NULL
;
1093 item
->option
.argDescrip
= NULL
;
1094 item
->argc
= alias
.argc
;
1095 item
->argv
= alias
.argv
;
1096 return poptAddItem(con
, item
, 0);
1100 /*@-mustmod@*/ /* LCL: con not modified? */
1101 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1103 poptItem
* items
, item
;
1108 items
= &con
->execs
;
1109 nitems
= &con
->numExecs
;
1112 items
= &con
->aliases
;
1113 nitems
= &con
->numAliases
;
1117 /*@notreached@*/ break;
1120 *items
= realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1121 if ((*items
) == NULL
)
1124 item
= (*items
) + (*nitems
);
1126 item
->option
.longName
=
1127 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1128 item
->option
.shortName
= newItem
->option
.shortName
;
1129 item
->option
.argInfo
= newItem
->option
.argInfo
;
1130 item
->option
.arg
= newItem
->option
.arg
;
1131 item
->option
.val
= newItem
->option
.val
;
1132 item
->option
.descrip
=
1133 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1134 item
->option
.argDescrip
=
1135 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1136 item
->argc
= newItem
->argc
;
1137 item
->argv
= newItem
->argv
;
1146 const char * poptBadOption(poptContext con
, int flags
)
1148 struct optionStackEntry
* os
= NULL
;
1151 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1153 /*@-nullderef@*/ /* LCL: os->argv != NULL */
1154 return (os
&& os
->argv
? os
->argv
[os
->next
- 1] : NULL
);
1158 const char *poptStrerror(const int error
)
1161 case POPT_ERROR_NOARG
:
1162 return POPT_("missing argument");
1163 case POPT_ERROR_BADOPT
:
1164 return POPT_("unknown option");
1165 case POPT_ERROR_BADOPERATION
:
1166 return POPT_("mutually exclusive logical operations requested");
1167 case POPT_ERROR_NULLARG
:
1168 return POPT_("opt->arg should not be NULL");
1169 case POPT_ERROR_OPTSTOODEEP
:
1170 return POPT_("aliases nested too deeply");
1171 case POPT_ERROR_BADQUOTE
:
1172 return POPT_("error in parameter quoting");
1173 case POPT_ERROR_BADNUMBER
:
1174 return POPT_("invalid numeric value");
1175 case POPT_ERROR_OVERFLOW
:
1176 return POPT_("number too large or too small");
1177 case POPT_ERROR_MALLOC
:
1178 return POPT_("memory allocation failed");
1179 case POPT_ERROR_ERRNO
:
1180 return strerror(errno
);
1182 return POPT_("unknown error");
1186 int poptStuffArgs(poptContext con
, const char ** argv
)
1191 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1192 return POPT_ERROR_OPTSTOODEEP
;
1194 for (argc
= 0; argv
[argc
]; argc
++)
1199 con
->os
->nextArg
= NULL
;
1200 con
->os
->nextCharArg
= NULL
;
1201 con
->os
->currAlias
= NULL
;
1202 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1203 con
->os
->argb
= NULL
;
1204 con
->os
->stuffed
= 1;
1209 const char * poptGetInvocationName(poptContext con
)
1211 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1215 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1223 for (i
= 1; i
< argc
; i
++) {
1224 if (PBM_ISSET(i
, con
->arg_strip
))
1228 for (i
= 1; i
< argc
; i
++) {
1229 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1231 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;