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 */
29 static char * strerror(int errno
) {
31 extern char * sys_errlist
[];
33 if ((0 <= errno
) && (errno
< sys_nerr
))
34 return sys_errlist
[errno
];
36 return POPT_("unknown errno");
41 /*@unused@*/ static void prtcon(const char *msg
, poptContext con
)
43 if (msg
) fprintf(stderr
, "%s", msg
);
44 fprintf(stderr
, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
46 (con
->os
->nextCharArg
? con
->os
->nextCharArg
: ""),
47 (con
->os
->nextArg
? con
->os
->nextArg
: ""),
49 (con
->os
->argv
&& con
->os
->argv
[con
->os
->next
]
50 ? con
->os
->argv
[con
->os
->next
] : ""));
54 void poptSetExecPath(poptContext con
, const char * path
, int allowAbsolute
)
56 con
->execPath
= _free(con
->execPath
);
57 con
->execPath
= xstrdup(path
);
58 con
->execAbsolute
= allowAbsolute
;
59 /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
64 static void invokeCallbacksPRE(poptContext con
, const struct poptOption
* opt
)
65 /*@globals internalState@*/
66 /*@modifies internalState@*/
69 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
70 if (opt
->arg
== NULL
) continue; /* XXX program error. */
71 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
72 /* Recurse on included sub-tables. */
73 invokeCallbacksPRE(con
, opt
->arg
);
74 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
75 (opt
->argInfo
& POPT_CBFLAG_PRE
))
77 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
79 /* Perform callback. */
80 /*@-moduncon -noeffectuncon @*/
81 cb(con
, POPT_CALLBACK_REASON_PRE
, NULL
, NULL
, opt
->descrip
);
82 /*@=moduncon =noeffectuncon @*/
87 static void invokeCallbacksPOST(poptContext con
, const struct poptOption
* opt
)
88 /*@globals internalState@*/
89 /*@modifies internalState@*/
92 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
93 if (opt
->arg
== NULL
) continue; /* XXX program error. */
94 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
95 /* Recurse on included sub-tables. */
96 invokeCallbacksPOST(con
, opt
->arg
);
97 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
98 (opt
->argInfo
& POPT_CBFLAG_POST
))
100 poptCallbackType cb
= (poptCallbackType
)opt
->arg
;
102 /* Perform callback. */
103 /*@-moduncon -noeffectuncon @*/
104 cb(con
, POPT_CALLBACK_REASON_POST
, NULL
, NULL
, opt
->descrip
);
105 /*@=moduncon =noeffectuncon @*/
110 static void invokeCallbacksOPTION(poptContext con
,
111 const struct poptOption
* opt
,
112 const struct poptOption
* myOpt
,
113 /*@null@*/ const void * myData
, int shorty
)
114 /*@globals internalState@*/
115 /*@modifies internalState@*/
117 const struct poptOption
* cbopt
= NULL
;
120 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
121 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
122 /* Recurse on included sub-tables. */
123 if (opt
->arg
!= NULL
) /* XXX program error */
124 invokeCallbacksOPTION(con
, opt
->arg
, myOpt
, myData
, shorty
);
125 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
126 !(opt
->argInfo
& POPT_CBFLAG_SKIPOPTION
)) {
127 /* Save callback info. */
129 } else if (cbopt
!= NULL
&&
130 ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
131 myOpt
->shortName
== opt
->shortName
) ||
132 (myOpt
->longName
&& opt
->longName
&&
133 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
134 !strcmp(myOpt
->longName
, opt
->longName
)))
138 poptCallbackType cb
= (poptCallbackType
)cbopt
->arg
;
140 const void * cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
141 /* Perform callback. */
142 if (cb
!= NULL
) { /* XXX program error */
143 /*@-moduncon -noeffectuncon @*/
144 cb(con
, POPT_CALLBACK_REASON_OPTION
, myOpt
,
145 con
->os
->nextArg
, cbData
);
146 /*@=moduncon =noeffectuncon @*/
148 /* Terminate (unless explcitly continuing). */
149 if (!(cbopt
->argInfo
& POPT_CBFLAG_CONTINUE
))
155 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
156 const struct poptOption
* options
, int flags
)
158 poptContext con
= malloc(sizeof(*con
));
160 if (con
== NULL
) return NULL
; /* XXX can't happen */
161 memset(con
, 0, sizeof(*con
));
163 con
->os
= con
->optionStack
;
164 con
->os
->argc
= argc
;
165 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
166 con
->os
->argv
= argv
;
167 /*@=dependenttrans =assignexpose@*/
168 con
->os
->argb
= NULL
;
170 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
171 con
->os
->next
= 1; /* skip argv[0] */
173 con
->leftovers
= calloc( (argc
+ 1), sizeof(*con
->leftovers
) );
174 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
175 con
->options
= options
;
176 /*@=dependenttrans =assignexpose@*/
182 con
->finalArgvAlloced
= argc
* 2;
183 con
->finalArgv
= calloc( con
->finalArgvAlloced
, sizeof(*con
->finalArgv
) );
184 con
->execAbsolute
= 1;
185 con
->arg_strip
= NULL
;
187 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
188 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
191 char * t
= malloc(strlen(name
) + 1);
192 if (t
) con
->appName
= strcpy(t
, name
);
196 invokeCallbacksPRE(con
, con
->options
);
202 static void cleanOSE(/*@special@*/ struct optionStackEntry
*os
)
204 /*@releases os->nextArg, os->argv, os->argb @*/
207 os
->nextArg
= _free(os
->nextArg
);
208 os
->argv
= _free(os
->argv
);
209 os
->argb
= PBM_FREE(os
->argb
);
213 void poptResetContext(poptContext con
)
217 if (con
== NULL
) return;
218 while (con
->os
> con
->optionStack
) {
221 con
->os
->argb
= PBM_FREE(con
->os
->argb
);
222 con
->os
->currAlias
= NULL
;
223 con
->os
->nextCharArg
= NULL
;
224 con
->os
->nextArg
= NULL
;
225 con
->os
->next
= 1; /* skip argv[0] */
227 con
->numLeftovers
= 0;
228 con
->nextLeftover
= 0;
229 con
->restLeftover
= 0;
232 if (con
->finalArgv
!= NULL
)
233 for (i
= 0; i
< con
->finalArgvCount
; i
++) {
234 /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
235 con
->finalArgv
[i
] = _free(con
->finalArgv
[i
]);
236 /*@=unqualifiedtrans@*/
239 con
->finalArgvCount
= 0;
240 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
241 /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
247 /* Only one of longName, shortName should be set, not both. */
249 static int handleExec(/*@special@*/ poptContext con
,
250 /*@null@*/ const char * longName
, char shortName
)
251 /*@uses con->execs, con->numExecs, con->flags, con->doExec,
252 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
258 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
261 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
262 item
= con
->execs
+ i
;
263 if (longName
&& !(item
->option
.longName
&&
264 !strcmp(longName
, item
->option
.longName
)))
266 else if (shortName
!= item
->option
.shortName
)
273 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
276 if (con
->doExec
== NULL
) {
277 con
->doExec
= con
->execs
+ i
;
281 /* We already have an exec to do; remember this option for next
283 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
284 con
->finalArgvAlloced
+= 10;
285 con
->finalArgv
= realloc(con
->finalArgv
,
286 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
289 i
= con
->finalArgvCount
++;
290 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
291 { char *s
= malloc((longName
? strlen(longName
) : 0) + 3);
292 if (s
!= NULL
) { /* XXX can't happen */
294 sprintf(s
, "--%s", longName
);
296 sprintf(s
, "-%c", shortName
);
297 con
->finalArgv
[i
] = s
;
299 con
->finalArgv
[i
] = NULL
;
302 /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
308 /* Only one of longName, shortName may be set at a time */
309 static int handleAlias(/*@special@*/ poptContext con
,
310 /*@null@*/ const char * longName
, char shortName
,
311 /*@exposed@*/ /*@null@*/ const char * nextCharArg
)
312 /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
313 con->os->currAlias, con->os->currAlias->option.longName @*/
316 poptItem item
= con
->os
->currAlias
;
321 if (longName
&& (item
->option
.longName
&&
322 !strcmp(longName
, item
->option
.longName
)))
324 if (shortName
&& shortName
== item
->option
.shortName
)
328 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
331 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
332 item
= con
->aliases
+ i
;
333 if (longName
&& !(item
->option
.longName
&&
334 !strcmp(longName
, item
->option
.longName
)))
336 else if (shortName
!= item
->option
.shortName
)
342 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
343 return POPT_ERROR_OPTSTOODEEP
;
346 if (nextCharArg
&& *nextCharArg
)
347 con
->os
->nextCharArg
= nextCharArg
;
352 con
->os
->stuffed
= 0;
353 con
->os
->nextArg
= NULL
;
354 con
->os
->nextCharArg
= NULL
;
355 con
->os
->currAlias
= con
->aliases
+ i
;
356 rc
= poptDupArgv(con
->os
->currAlias
->argc
, con
->os
->currAlias
->argv
,
357 &con
->os
->argc
, &con
->os
->argv
);
358 con
->os
->argb
= NULL
;
360 return (rc
? rc
: 1);
363 /*@-bounds -boundswrite @*/
364 static int execCommand(poptContext con
)
365 /*@globals internalState @*/
366 /*@modifies internalState @*/
368 poptItem item
= con
->doExec
;
371 #if defined(__hpux) || defined(HAVE_SETUID) || defined(HAVE_SETREUID)
375 if (item
== NULL
) /*XXX can't happen*/
376 return POPT_ERROR_NOARG
;
378 if (item
->argv
== NULL
|| item
->argc
< 1 ||
379 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
380 return POPT_ERROR_NOARG
;
382 argv
= malloc(sizeof(*argv
) *
383 (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
384 if (argv
== NULL
) return POPT_ERROR_MALLOC
; /* XXX can't happen */
386 if (!strchr(item
->argv
[0], '/') && con
->execPath
) {
387 char *s
= alloca(strlen(con
->execPath
) + strlen(item
->argv
[0]) + sizeof("/"));
388 sprintf(s
, "%s/%s", con
->execPath
, item
->argv
[0]);
391 argv
[argc
] = findProgramPath(item
->argv
[0]);
393 if (argv
[argc
++] == NULL
) return POPT_ERROR_NOARG
;
395 if (item
->argc
> 1) {
396 memcpy(argv
+ argc
, item
->argv
+ 1, sizeof(*argv
) * (item
->argc
- 1));
397 argc
+= (item
->argc
- 1);
400 if (con
->finalArgv
!= NULL
&& con
->finalArgvCount
> 0) {
401 memcpy(argv
+ argc
, con
->finalArgv
,
402 sizeof(*argv
) * con
->finalArgvCount
);
403 argc
+= con
->finalArgvCount
;
406 if (con
->leftovers
!= NULL
&& con
->numLeftovers
> 0) {
410 memcpy(argv
+ argc
, con
->leftovers
, sizeof(*argv
) * con
->numLeftovers
);
411 argc
+= con
->numLeftovers
;
417 rc
= setresuid(getuid(), getuid(),-1);
418 if (rc
) return POPT_ERROR_ERRNO
;
421 * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
422 * XXX sez' Timur Bakeyev <mc@bat.ru>
423 * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
425 #if defined(HAVE_SETUID)
426 rc
= setuid(getuid());
427 if (rc
) return POPT_ERROR_ERRNO
;
428 #elif defined (HAVE_SETREUID)
429 rc
= setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
430 if (rc
) return POPT_ERROR_ERRNO
;
432 ; /* Can't drop privileges */
437 return POPT_ERROR_NOARG
;
442 fprintf(stderr
, "==> execvp(%s) argv[%d]:", argv
[0], argc
);
443 for (avp
= argv
; *avp
; avp
++)
444 fprintf(stderr
, " '%s'", *avp
);
445 fprintf(stderr
, "\n");
449 (void) execvp(argv
[0], (char *const *)(intptr_t)argv
);
451 return POPT_ERROR_ERRNO
;
453 /*@=bounds =boundswrite @*/
456 /*@observer@*/ /*@null@*/ static const struct poptOption
*
457 findOption(const struct poptOption
* opt
, /*@null@*/ const char * longName
,
459 /*@null@*/ /*@out@*/ poptCallbackType
* callback
,
460 /*@null@*/ /*@out@*/ const void ** callbackData
,
462 /*@modifies *callback, *callbackData */
464 const struct poptOption
* cb
= NULL
;
466 /* This happens when a single - is given */
467 if (singleDash
&& !shortName
&& (longName
&& *longName
== '\0'))
470 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
472 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
473 const struct poptOption
* opt2
;
475 /* Recurse on included sub-tables. */
476 if (opt
->arg
== NULL
) continue; /* XXX program error */
477 opt2
= findOption(opt
->arg
, longName
, shortName
, callback
,
478 callbackData
, singleDash
);
479 if (opt2
== NULL
) continue;
480 /* Sub-table data will be inheirited if no data yet. */
481 if (!(callback
&& *callback
)) return opt2
;
482 if (!(callbackData
&& *callbackData
== NULL
)) return opt2
;
483 /*@-observertrans -dependenttrans @*/
484 *callbackData
= opt
->descrip
;
485 /*@=observertrans =dependenttrans @*/
487 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
) {
489 } else if (longName
&& opt
->longName
&&
490 (!singleDash
|| (opt
->argInfo
& POPT_ARGFLAG_ONEDASH
)) &&
491 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
492 !strcmp(longName
, opt
->longName
))
496 } else if (shortName
&& shortName
== opt
->shortName
) {
501 if (!opt
->longName
&& !opt
->shortName
)
503 /*@-modobserver -mods @*/
504 if (callback
) *callback
= NULL
;
505 if (callbackData
) *callbackData
= NULL
;
509 *callback
= (poptCallbackType
)cb
->arg
;
511 if (!(cb
->argInfo
& POPT_CBFLAG_INC_DATA
)) {
513 /*@-observertrans@*/ /* FIX: typedef double indirection. */
514 *callbackData
= cb
->descrip
;
518 /*@=modobserver =mods @*/
524 static const char * findNextArg(/*@special@*/ poptContext con
,
525 unsigned argx
, int delete_arg
)
526 /*@uses con->optionStack, con->os,
527 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
530 struct optionStackEntry
* os
= con
->os
;
536 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
537 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
538 if (os
->argv
!= NULL
)
539 for (i
= os
->next
; i
< os
->argc
; i
++) {
541 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
542 /*@innercontinue@*/ continue;
543 if (*os
->argv
[i
] == '-')
544 /*@innercontinue@*/ continue;
546 /*@innercontinue@*/ continue;
549 if (os
->argb
== NULL
) os
->argb
= PBM_ALLOC(os
->argc
);
550 if (os
->argb
!= NULL
) /* XXX can't happen */
551 PBM_SET(i
, os
->argb
);
553 /*@innerbreak@*/ break;
556 if (os
> con
->optionStack
) os
--;
557 } while (arg
== NULL
);
562 static /*@only@*/ /*@null@*/ const char *
563 expandNextArg(/*@special@*/ poptContext con
, const char * s
)
564 /*@uses con->optionStack, con->os,
565 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
568 const char * a
= NULL
;
571 size_t tn
= strlen(s
) + 1;
574 te
= t
= malloc(tn
);;
575 if (t
== NULL
) return NULL
; /* XXX can't happen */
576 while ((c
= *s
++) != '\0') {
578 #if 0 /* XXX can't do this */
579 case '\\': /* escape */
581 /*@switchbreak@*/ break;
584 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
585 /*@switchbreak@*/ break;
586 /* XXX Make sure that findNextArg deletes only next arg. */
588 if ((a
= findNextArg(con
, 1, 1)) == NULL
)
589 /*@switchbreak@*/ break;
598 strncpy(te
, a
, alen
); te
+= alen
;
600 /*@notreached@*/ /*@switchbreak@*/ break;
602 /*@switchbreak@*/ break;
607 t
= realloc(t
, strlen(t
) + 1); /* XXX memory leak, hard to plug */
612 static void poptStripArg(/*@special@*/ poptContext con
, int which
)
613 /*@uses con->arg_strip, con->optionStack @*/
614 /*@defines con->arg_strip @*/
618 if (con
->arg_strip
== NULL
)
619 con
->arg_strip
= PBM_ALLOC(con
->optionStack
[0].argc
);
620 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
621 PBM_SET(which
, con
->arg_strip
);
623 /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
628 int poptSaveLong(long * arg
, int argInfo
, long aLong
)
630 /* XXX Check alignment, may fail on funky platforms. */
631 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
632 return POPT_ERROR_NULLARG
;
634 if (argInfo
& POPT_ARGFLAG_NOT
)
636 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
640 case POPT_ARGFLAG_OR
:
643 case POPT_ARGFLAG_AND
:
646 case POPT_ARGFLAG_XOR
:
650 return POPT_ERROR_BADOPERATION
;
651 /*@notreached@*/ break;
656 int poptSaveInt(/*@null@*/ int * arg
, int argInfo
, long aLong
)
658 /* XXX Check alignment, may fail on funky platforms. */
659 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
660 return POPT_ERROR_NULLARG
;
662 if (argInfo
& POPT_ARGFLAG_NOT
)
664 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
668 case POPT_ARGFLAG_OR
:
671 case POPT_ARGFLAG_AND
:
674 case POPT_ARGFLAG_XOR
:
678 return POPT_ERROR_BADOPERATION
;
679 /*@notreached@*/ break;
685 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
686 int poptGetNextOpt(poptContext con
)
688 const struct poptOption
* opt
= NULL
;
694 const char * origOptString
= NULL
;
695 poptCallbackType cb
= NULL
;
696 const void * cbData
= NULL
;
697 const char * longArg
= NULL
;
701 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
702 && con
->os
> con
->optionStack
) {
705 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
707 invokeCallbacksPOST(con
, con
->options
);
709 if (con
->doExec
) return execCommand(con
);
713 /* Process next long option */
714 if (!con
->os
->nextCharArg
) {
715 char * localOptString
, * optString
;
719 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
724 thisopt
= con
->os
->next
;
725 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
726 origOptString
= con
->os
->argv
[con
->os
->next
++];
728 if (origOptString
== NULL
) /* XXX can't happen */
729 return POPT_ERROR_BADOPT
;
731 if (con
->restLeftover
|| *origOptString
!= '-') {
732 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
733 con
->restLeftover
= 1;
734 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
735 con
->os
->nextArg
= xstrdup(origOptString
);
738 if (con
->leftovers
!= NULL
) /* XXX can't happen */
739 con
->leftovers
[con
->numLeftovers
++] = origOptString
;
743 /* Make a copy we can hack at */
744 localOptString
= optString
=
745 strcpy(alloca(strlen(origOptString
) + 1), origOptString
);
747 if (optString
[0] == '\0')
748 return POPT_ERROR_BADOPT
;
750 if (optString
[1] == '-' && !optString
[2]) {
751 con
->restLeftover
= 1;
758 if (*optString
== '-')
759 singleDash
= 0, optString
++;
763 /* XXX aliases with arg substitution need "--alias=arg" */
764 if (handleAlias(con
, optString
, '\0', NULL
))
767 if (handleExec(con
, optString
, '\0'))
770 /* Check for "--long=arg" option. */
771 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
775 /* XXX longArg is mapped back to persistent storage. */
776 longArg
= origOptString
+ (oe
- localOptString
);
779 opt
= findOption(con
->options
, optString
, '\0', &cb
, &cbData
,
781 if (!opt
&& !singleDash
)
782 return POPT_ERROR_BADOPT
;
786 con
->os
->nextCharArg
= origOptString
+ 1;
788 if (con
->os
== con
->optionStack
&&
789 opt
->argInfo
& POPT_ARGFLAG_STRIP
)
792 poptStripArg(con
, thisopt
);
798 /* Process next short option */
799 /*@-branchstate@*/ /* FIX: W2DO? */
800 if (con
->os
->nextCharArg
) {
801 origOptString
= con
->os
->nextCharArg
;
803 con
->os
->nextCharArg
= NULL
;
805 if (handleAlias(con
, NULL
, *origOptString
, origOptString
+ 1))
808 if (handleExec(con
, NULL
, *origOptString
)) {
809 /* Restore rest of short options for further processing */
811 if (*origOptString
!= '\0')
812 con
->os
->nextCharArg
= origOptString
;
816 opt
= findOption(con
->options
, NULL
, *origOptString
, &cb
,
819 return POPT_ERROR_BADOPT
;
823 if (*origOptString
!= '\0')
824 con
->os
->nextCharArg
= origOptString
;
828 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
829 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
) {
830 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, 1L))
831 return POPT_ERROR_BADOPERATION
;
832 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
) {
834 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, (long)opt
->val
))
835 return POPT_ERROR_BADOPERATION
;
837 } else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
838 con
->os
->nextArg
= _free(con
->os
->nextArg
);
839 /*@-usedef@*/ /* FIX: W2DO? */
842 longArg
= expandNextArg(con
, longArg
);
843 con
->os
->nextArg
= longArg
;
844 } else if (con
->os
->nextCharArg
) {
845 longArg
= expandNextArg(con
, con
->os
->nextCharArg
);
846 con
->os
->nextArg
= longArg
;
847 con
->os
->nextCharArg
= NULL
;
849 while (con
->os
->next
== con
->os
->argc
&&
850 con
->os
> con
->optionStack
) {
853 if (con
->os
->next
== con
->os
->argc
) {
854 if (!(opt
->argInfo
& POPT_ARGFLAG_OPTIONAL
))
855 /*@-compdef@*/ /* FIX: con->os->argv not defined */
856 return POPT_ERROR_NOARG
;
858 con
->os
->nextArg
= NULL
;
862 * Make sure this isn't part of a short arg or the
863 * result of an alias expansion.
865 if (con
->os
== con
->optionStack
&&
866 (opt
->argInfo
& POPT_ARGFLAG_STRIP
) &&
868 poptStripArg(con
, con
->os
->next
);
871 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
872 /* XXX watchout: subtle side-effects live here. */
873 longArg
= con
->os
->argv
[con
->os
->next
++];
874 longArg
= expandNextArg(con
, longArg
);
875 con
->os
->nextArg
= longArg
;
882 switch (opt
->argInfo
& POPT_ARG_MASK
) {
883 case POPT_ARG_STRING
:
884 /* XXX memory leak, hard to plug */
885 *((const char **) opt
->arg
) = (con
->os
->nextArg
)
886 ? xstrdup(con
->os
->nextArg
) : NULL
;
887 /*@switchbreak@*/ break;
894 if (con
->os
->nextArg
) {
895 aLong
= strtol(con
->os
->nextArg
, &end
, 0);
896 if (!(end
&& *end
== '\0'))
897 return POPT_ERROR_BADNUMBER
;
900 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_LONG
) {
901 if (aLong
== LONG_MIN
|| aLong
== LONG_MAX
)
902 return POPT_ERROR_OVERFLOW
;
903 if (poptSaveLong((long *)opt
->arg
, opt
->argInfo
, aLong
))
904 return POPT_ERROR_BADOPERATION
;
906 if (aLong
> INT_MAX
|| aLong
< INT_MIN
)
907 return POPT_ERROR_OVERFLOW
;
908 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, aLong
))
909 return POPT_ERROR_BADOPERATION
;
911 } /*@switchbreak@*/ break;
914 case POPT_ARG_DOUBLE
:
915 { double aDouble
= 0.0;
918 if (con
->os
->nextArg
) {
920 int saveerrno
= errno
;
922 aDouble
= strtod(con
->os
->nextArg
, &end
);
924 return POPT_ERROR_OVERFLOW
;
928 return POPT_ERROR_BADNUMBER
;
931 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_DOUBLE
) {
932 *((double *) opt
->arg
) = aDouble
;
934 #define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
935 if ((_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
936 return POPT_ERROR_OVERFLOW
;
937 if ((FLT_MIN
- _ABS(aDouble
)) > DBL_EPSILON
)
938 return POPT_ERROR_OVERFLOW
;
939 *((float *) opt
->arg
) = aDouble
;
941 } /*@switchbreak@*/ break;
944 POPT_("option type (%d) not implemented in popt\n"),
945 (opt
->argInfo
& POPT_ARG_MASK
));
947 /*@notreached@*/ /*@switchbreak@*/ break;
954 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
956 } else if (opt
->val
&& ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_VAL
))
959 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
960 con
->finalArgvAlloced
+= 10;
961 con
->finalArgv
= realloc(con
->finalArgv
,
962 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
965 if (con
->finalArgv
!= NULL
)
966 { char *s
= malloc((opt
->longName
? strlen(opt
->longName
) : 0) + 3);
967 if (s
!= NULL
) { /* XXX can't happen */
970 ((opt
->argInfo
& POPT_ARGFLAG_ONEDASH
) ? "-" : "--"),
973 sprintf(s
, "-%c", opt
->shortName
);
974 con
->finalArgv
[con
->finalArgvCount
++] = s
;
976 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
979 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
)
980 /*@-ifempty@*/ ; /*@=ifempty@*/
981 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
)
982 /*@-ifempty@*/ ; /*@=ifempty@*/
983 else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
984 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
)
985 con
->finalArgv
[con
->finalArgvCount
++] =
986 /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
987 xstrdup(con
->os
->nextArg
);
992 return (opt
? opt
->val
: -1); /* XXX can't happen */
996 const char * poptGetOptArg(poptContext con
)
998 const char * ret
= NULL
;
1001 ret
= con
->os
->nextArg
;
1002 con
->os
->nextArg
= NULL
;
1008 const char * poptGetArg(poptContext con
)
1010 const char * ret
= NULL
;
1011 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1012 ret
= con
->leftovers
[con
->nextLeftover
++];
1016 const char * poptPeekArg(poptContext con
)
1018 const char * ret
= NULL
;
1019 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1020 ret
= con
->leftovers
[con
->nextLeftover
];
1025 const char ** poptGetArgs(poptContext con
)
1028 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1031 /* some apps like [like RPM ;-) ] need this NULL terminated */
1032 con
->leftovers
[con
->numLeftovers
] = NULL
;
1034 /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
1035 return (con
->leftovers
+ con
->nextLeftover
);
1036 /*@=nullret =nullstate @*/
1040 poptContext
poptFreeContext(poptContext con
)
1045 if (con
== NULL
) return con
;
1046 poptResetContext(con
);
1047 con
->os
->argb
= _free(con
->os
->argb
);
1049 if (con
->aliases
!= NULL
)
1050 for (i
= 0; i
< con
->numAliases
; i
++) {
1051 item
= con
->aliases
+ i
;
1052 /*@-modobserver -observertrans -dependenttrans@*/
1053 item
->option
.longName
= _free(item
->option
.longName
);
1054 item
->option
.descrip
= _free(item
->option
.descrip
);
1055 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1056 /*@=modobserver =observertrans =dependenttrans@*/
1057 item
->argv
= _free(item
->argv
);
1059 con
->aliases
= _free(con
->aliases
);
1061 if (con
->execs
!= NULL
)
1062 for (i
= 0; i
< con
->numExecs
; i
++) {
1063 item
= con
->execs
+ i
;
1064 /*@-modobserver -observertrans -dependenttrans@*/
1065 item
->option
.longName
= _free(item
->option
.longName
);
1066 item
->option
.descrip
= _free(item
->option
.descrip
);
1067 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1068 /*@=modobserver =observertrans =dependenttrans@*/
1069 item
->argv
= _free(item
->argv
);
1071 con
->execs
= _free(con
->execs
);
1073 con
->leftovers
= _free(con
->leftovers
);
1074 con
->finalArgv
= _free(con
->finalArgv
);
1075 con
->appName
= _free(con
->appName
);
1076 con
->otherHelp
= _free(con
->otherHelp
);
1077 con
->execPath
= _free(con
->execPath
);
1078 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
1084 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1085 /*@unused@*/ int flags
)
1087 poptItem item
= alloca(sizeof(*item
));
1088 memset(item
, 0, sizeof(*item
));
1089 item
->option
.longName
= alias
.longName
;
1090 item
->option
.shortName
= alias
.shortName
;
1091 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1092 item
->option
.arg
= 0;
1093 item
->option
.val
= 0;
1094 item
->option
.descrip
= NULL
;
1095 item
->option
.argDescrip
= NULL
;
1096 item
->argc
= alias
.argc
;
1097 item
->argv
= alias
.argv
;
1098 return poptAddItem(con
, item
, 0);
1102 /*@-mustmod@*/ /* LCL: con not modified? */
1103 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1105 poptItem
* items
, item
;
1110 items
= &con
->execs
;
1111 nitems
= &con
->numExecs
;
1114 items
= &con
->aliases
;
1115 nitems
= &con
->numAliases
;
1119 /*@notreached@*/ break;
1122 *items
= realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1123 if ((*items
) == NULL
)
1126 item
= (*items
) + (*nitems
);
1128 item
->option
.longName
=
1129 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1130 item
->option
.shortName
= newItem
->option
.shortName
;
1131 item
->option
.argInfo
= newItem
->option
.argInfo
;
1132 item
->option
.arg
= newItem
->option
.arg
;
1133 item
->option
.val
= newItem
->option
.val
;
1134 item
->option
.descrip
=
1135 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1136 item
->option
.argDescrip
=
1137 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1138 item
->argc
= newItem
->argc
;
1139 item
->argv
= newItem
->argv
;
1148 const char * poptBadOption(poptContext con
, int flags
)
1150 struct optionStackEntry
* os
= NULL
;
1153 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1155 /*@-nullderef@*/ /* LCL: os->argv != NULL */
1156 return (os
&& os
->argv
? os
->argv
[os
->next
- 1] : NULL
);
1160 const char *poptStrerror(const int error
)
1163 case POPT_ERROR_NOARG
:
1164 return POPT_("missing argument");
1165 case POPT_ERROR_BADOPT
:
1166 return POPT_("unknown option");
1167 case POPT_ERROR_BADOPERATION
:
1168 return POPT_("mutually exclusive logical operations requested");
1169 case POPT_ERROR_NULLARG
:
1170 return POPT_("opt->arg should not be NULL");
1171 case POPT_ERROR_OPTSTOODEEP
:
1172 return POPT_("aliases nested too deeply");
1173 case POPT_ERROR_BADQUOTE
:
1174 return POPT_("error in parameter quoting");
1175 case POPT_ERROR_BADNUMBER
:
1176 return POPT_("invalid numeric value");
1177 case POPT_ERROR_OVERFLOW
:
1178 return POPT_("number too large or too small");
1179 case POPT_ERROR_MALLOC
:
1180 return POPT_("memory allocation failed");
1181 case POPT_ERROR_ERRNO
:
1182 return strerror(errno
);
1184 return POPT_("unknown error");
1188 int poptStuffArgs(poptContext con
, const char ** argv
)
1193 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1194 return POPT_ERROR_OPTSTOODEEP
;
1196 for (argc
= 0; argv
[argc
]; argc
++)
1201 con
->os
->nextArg
= NULL
;
1202 con
->os
->nextCharArg
= NULL
;
1203 con
->os
->currAlias
= NULL
;
1204 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1205 con
->os
->argb
= NULL
;
1206 con
->os
->stuffed
= 1;
1211 const char * poptGetInvocationName(poptContext con
)
1213 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1217 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1225 for (i
= 1; i
< argc
; i
++) {
1226 if (PBM_ISSET(i
, con
->arg_strip
))
1230 for (i
= 1; i
< argc
; i
++) {
1231 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1233 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;