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
= (const char *)_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
, (const struct poptOption
*)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
, (const struct poptOption
*)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
, (const struct poptOption
*)opt
->arg
,
123 myOpt
, myData
, shorty
);
124 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
&&
125 !(opt
->argInfo
& POPT_CBFLAG_SKIPOPTION
)) {
126 /* Save callback info. */
128 } else if (cbopt
!= NULL
&&
129 ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
130 myOpt
->shortName
== opt
->shortName
) ||
131 (myOpt
->longName
&& opt
->longName
&&
132 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
133 !strcmp(myOpt
->longName
, opt
->longName
)))
137 poptCallbackType cb
= (poptCallbackType
)cbopt
->arg
;
139 const void * cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
140 /* Perform callback. */
141 if (cb
!= NULL
) { /* XXX program error */
142 /*@-moduncon -noeffectuncon @*/
143 cb(con
, POPT_CALLBACK_REASON_OPTION
, myOpt
,
144 con
->os
->nextArg
, cbData
);
145 /*@=moduncon =noeffectuncon @*/
147 /* Terminate (unless explcitly continuing). */
148 if (!(cbopt
->argInfo
& POPT_CBFLAG_CONTINUE
))
154 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
155 const struct poptOption
* options
, int flags
)
157 poptContext con
= (poptContext
)malloc(sizeof(*con
));
159 if (con
== NULL
) return NULL
; /* XXX can't happen */
160 memset(con
, 0, sizeof(*con
));
162 con
->os
= con
->optionStack
;
163 con
->os
->argc
= argc
;
164 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
165 con
->os
->argv
= argv
;
166 /*@=dependenttrans =assignexpose@*/
167 con
->os
->argb
= NULL
;
169 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
170 con
->os
->next
= 1; /* skip argv[0] */
172 con
->leftovers
= (const char **)calloc( (argc
+ 1),
173 sizeof(*con
->leftovers
) );
174 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
175 con
->options
= options
;
176 /*@=dependenttrans =assignexpose@*/
182 con
->finalArgvAlloced
= argc
* 2;
183 con
->finalArgv
= (const char **)calloc( con
->finalArgvAlloced
,
184 sizeof(*con
->finalArgv
) );
185 con
->execAbsolute
= 1;
186 con
->arg_strip
= NULL
;
188 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
189 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
192 char * t
= (char *)malloc(strlen(name
) + 1);
193 if (t
) con
->appName
= strcpy(t
, name
);
197 invokeCallbacksPRE(con
, con
->options
);
203 static void cleanOSE(/*@special@*/ struct optionStackEntry
*os
)
205 /*@releases os->nextArg, os->argv, os->argb @*/
208 os
->nextArg
= (const char *)_free(os
->nextArg
);
209 os
->argv
= (const char **)_free(os
->argv
);
210 os
->argb
= (pbm_set
*)PBM_FREE(os
->argb
);
214 void poptResetContext(poptContext con
)
218 if (con
== NULL
) return;
219 while (con
->os
> con
->optionStack
) {
222 con
->os
->argb
= (pbm_set
*)PBM_FREE(con
->os
->argb
);
223 con
->os
->currAlias
= NULL
;
224 con
->os
->nextCharArg
= NULL
;
225 con
->os
->nextArg
= NULL
;
226 con
->os
->next
= 1; /* skip argv[0] */
228 con
->numLeftovers
= 0;
229 con
->nextLeftover
= 0;
230 con
->restLeftover
= 0;
233 if (con
->finalArgv
!= NULL
)
234 for (i
= 0; i
< con
->finalArgvCount
; i
++) {
235 /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
236 con
->finalArgv
[i
] = (const char *)_free(con
->finalArgv
[i
]);
237 /*@=unqualifiedtrans@*/
240 con
->finalArgvCount
= 0;
241 con
->arg_strip
= ( pbm_set
*)PBM_FREE(con
->arg_strip
);
242 /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
248 /* Only one of longName, shortName should be set, not both. */
250 static int handleExec(/*@special@*/ poptContext con
,
251 /*@null@*/ const char * longName
, char shortName
)
252 /*@uses con->execs, con->numExecs, con->flags, con->doExec,
253 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
259 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
262 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
263 item
= con
->execs
+ i
;
264 if (longName
&& !(item
->option
.longName
&&
265 !strcmp(longName
, item
->option
.longName
)))
267 else if (shortName
!= item
->option
.shortName
)
274 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
277 if (con
->doExec
== NULL
) {
278 con
->doExec
= con
->execs
+ i
;
282 /* We already have an exec to do; remember this option for next
284 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
285 con
->finalArgvAlloced
+= 10;
286 con
->finalArgv
= (const char **)realloc(con
->finalArgv
,
287 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
290 i
= con
->finalArgvCount
++;
291 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
292 { char *s
= (char *)malloc((longName
? strlen(longName
) : 0) + 3);
293 if (s
!= NULL
) { /* XXX can't happen */
295 sprintf(s
, "--%s", longName
);
297 sprintf(s
, "-%c", shortName
);
298 con
->finalArgv
[i
] = s
;
300 con
->finalArgv
[i
] = NULL
;
303 /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
309 /* Only one of longName, shortName may be set at a time */
310 static int handleAlias(/*@special@*/ poptContext con
,
311 /*@null@*/ const char * longName
, char shortName
,
312 /*@exposed@*/ /*@null@*/ const char * nextCharArg
)
313 /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
314 con->os->currAlias, con->os->currAlias->option.longName @*/
317 poptItem item
= con
->os
->currAlias
;
322 if (longName
&& (item
->option
.longName
&&
323 !strcmp(longName
, item
->option
.longName
)))
325 if (shortName
&& shortName
== item
->option
.shortName
)
329 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
332 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
333 item
= con
->aliases
+ i
;
334 if (longName
&& !(item
->option
.longName
&&
335 !strcmp(longName
, item
->option
.longName
)))
337 else if (shortName
!= item
->option
.shortName
)
343 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
344 return POPT_ERROR_OPTSTOODEEP
;
347 if (nextCharArg
&& *nextCharArg
)
348 con
->os
->nextCharArg
= nextCharArg
;
353 con
->os
->stuffed
= 0;
354 con
->os
->nextArg
= NULL
;
355 con
->os
->nextCharArg
= NULL
;
356 con
->os
->currAlias
= con
->aliases
+ i
;
357 rc
= poptDupArgv(con
->os
->currAlias
->argc
, con
->os
->currAlias
->argv
,
358 &con
->os
->argc
, &con
->os
->argv
);
359 con
->os
->argb
= NULL
;
361 return (rc
? rc
: 1);
364 /*@-bounds -boundswrite @*/
365 static int execCommand(poptContext con
)
366 /*@globals internalState @*/
367 /*@modifies internalState @*/
369 poptItem item
= con
->doExec
;
374 if (item
== NULL
) /*XXX can't happen*/
375 return POPT_ERROR_NOARG
;
377 if (item
->argv
== NULL
|| item
->argc
< 1 ||
378 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
379 return POPT_ERROR_NOARG
;
381 argv
= (const char **)malloc(
382 sizeof(*argv
) * (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
383 if (argv
== NULL
) return POPT_ERROR_MALLOC
; /* XXX can't happen */
385 if (!strchr(item
->argv
[0], '/') && con
->execPath
) {
386 char *s
= (char *)alloca(
387 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 rc
= execvp(argv
[0], (char *const *)argv
);
452 return POPT_ERROR_ERRNO
;
457 /*@=bounds =boundswrite @*/
460 /*@observer@*/ /*@null@*/ static const struct poptOption
*
461 findOption(const struct poptOption
* opt
, /*@null@*/ const char * longName
,
463 /*@null@*/ /*@out@*/ poptCallbackType
* callback
,
464 /*@null@*/ /*@out@*/ const void ** callbackData
,
466 /*@modifies *callback, *callbackData */
468 const struct poptOption
* cb
= NULL
;
470 /* This happens when a single - is given */
471 if (singleDash
&& !shortName
&& (longName
&& *longName
== '\0'))
474 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
476 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
477 const struct poptOption
* opt2
;
479 /* Recurse on included sub-tables. */
480 if (opt
->arg
== NULL
) continue; /* XXX program error */
481 opt2
= findOption((const struct poptOption
*)opt
->arg
, longName
,
483 callbackData
, singleDash
);
484 if (opt2
== NULL
) continue;
485 /* Sub-table data will be inheirited if no data yet. */
486 if (!(callback
&& *callback
)) return opt2
;
487 if (!(callbackData
&& *callbackData
== NULL
)) return opt2
;
488 /*@-observertrans -dependenttrans @*/
489 *callbackData
= opt
->descrip
;
490 /*@=observertrans =dependenttrans @*/
492 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_CALLBACK
) {
494 } else if (longName
&& opt
->longName
&&
495 (!singleDash
|| (opt
->argInfo
& POPT_ARGFLAG_ONEDASH
)) &&
496 /*@-nullpass@*/ /* LCL: opt->longName != NULL */
497 !strcmp(longName
, opt
->longName
))
501 } else if (shortName
&& shortName
== opt
->shortName
) {
506 if (!opt
->longName
&& !opt
->shortName
)
508 /*@-modobserver -mods @*/
509 if (callback
) *callback
= NULL
;
510 if (callbackData
) *callbackData
= NULL
;
514 *callback
= (poptCallbackType
)cb
->arg
;
516 if (!(cb
->argInfo
& POPT_CBFLAG_INC_DATA
)) {
518 /*@-observertrans@*/ /* FIX: typedef double indirection. */
519 *callbackData
= cb
->descrip
;
523 /*@=modobserver =mods @*/
529 static const char * findNextArg(/*@special@*/ poptContext con
,
530 unsigned argx
, int delete_arg
)
531 /*@uses con->optionStack, con->os,
532 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
535 struct optionStackEntry
* os
= con
->os
;
541 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
542 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
543 if (os
->argv
!= NULL
)
544 for (i
= os
->next
; i
< os
->argc
; i
++) {
546 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
547 /*@innercontinue@*/ continue;
548 if (*os
->argv
[i
] == '-')
549 /*@innercontinue@*/ continue;
551 /*@innercontinue@*/ continue;
554 if (os
->argb
== NULL
) os
->argb
= (pbm_set
*)PBM_ALLOC(os
->argc
);
555 if (os
->argb
!= NULL
) /* XXX can't happen */
556 PBM_SET(i
, os
->argb
);
558 /*@innerbreak@*/ break;
561 if (os
> con
->optionStack
) os
--;
562 } while (arg
== NULL
);
567 static /*@only@*/ /*@null@*/ const char *
568 expandNextArg(/*@special@*/ poptContext con
, const char * s
)
569 /*@uses con->optionStack, con->os,
570 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
573 const char * a
= NULL
;
576 size_t tn
= strlen(s
) + 1;
579 te
= t
= (char *)malloc(tn
);;
580 if (t
== NULL
) return NULL
; /* XXX can't happen */
581 while ((c
= *s
++) != '\0') {
583 #if 0 /* XXX can't do this */
584 case '\\': /* escape */
586 /*@switchbreak@*/ break;
589 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
590 /*@switchbreak@*/ break;
591 /* XXX Make sure that findNextArg deletes only next arg. */
593 if ((a
= findNextArg(con
, 1, 1)) == NULL
)
594 /*@switchbreak@*/ break;
601 t
= (char *)realloc(t
, tn
);
603 strncpy(te
, a
, alen
); te
+= alen
;
605 /*@notreached@*/ /*@switchbreak@*/ break;
607 /*@switchbreak@*/ break;
612 t
= (char *)realloc(t
, strlen(t
) + 1); /* XXX memory leak, hard to plug */
617 static void poptStripArg(/*@special@*/ poptContext con
, int which
)
618 /*@uses con->arg_strip, con->optionStack @*/
619 /*@defines con->arg_strip @*/
623 if (con
->arg_strip
== NULL
)
624 con
->arg_strip
= (pbm_set
*)PBM_ALLOC(con
->optionStack
[0].argc
);
625 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
626 PBM_SET(which
, con
->arg_strip
);
628 /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
633 int poptSaveLong(long * arg
, int argInfo
, long aLong
)
635 /* XXX Check alignment, may fail on funky platforms. */
636 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
637 return POPT_ERROR_NULLARG
;
639 if (argInfo
& POPT_ARGFLAG_NOT
)
641 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
645 case POPT_ARGFLAG_OR
:
648 case POPT_ARGFLAG_AND
:
651 case POPT_ARGFLAG_XOR
:
655 return POPT_ERROR_BADOPERATION
;
656 /*@notreached@*/ break;
661 int poptSaveInt(/*@null@*/ int * arg
, int argInfo
, long aLong
)
663 /* XXX Check alignment, may fail on funky platforms. */
664 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
665 return POPT_ERROR_NULLARG
;
667 if (argInfo
& POPT_ARGFLAG_NOT
)
669 switch (argInfo
& POPT_ARGFLAG_LOGICALOPS
) {
673 case POPT_ARGFLAG_OR
:
676 case POPT_ARGFLAG_AND
:
679 case POPT_ARGFLAG_XOR
:
683 return POPT_ERROR_BADOPERATION
;
684 /*@notreached@*/ break;
690 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
691 int poptGetNextOpt(poptContext con
)
693 const struct poptOption
* opt
= NULL
;
699 const char * origOptString
= NULL
;
700 poptCallbackType cb
= NULL
;
701 const void * cbData
= NULL
;
702 const char * longArg
= NULL
;
706 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
707 && con
->os
> con
->optionStack
) {
710 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
712 invokeCallbacksPOST(con
, con
->options
);
714 if (con
->doExec
) return execCommand(con
);
718 /* Process next long option */
719 if (!con
->os
->nextCharArg
) {
720 char * localOptString
, * optString
;
724 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
729 thisopt
= con
->os
->next
;
730 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
731 origOptString
= con
->os
->argv
[con
->os
->next
++];
733 if (origOptString
== NULL
) /* XXX can't happen */
734 return POPT_ERROR_BADOPT
;
736 if (con
->restLeftover
|| *origOptString
!= '-') {
737 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
738 con
->restLeftover
= 1;
739 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
740 con
->os
->nextArg
= xstrdup(origOptString
);
743 if (con
->leftovers
!= NULL
) /* XXX can't happen */
744 con
->leftovers
[con
->numLeftovers
++] = origOptString
;
748 /* Make a copy we can hack at */
749 localOptString
= optString
=
750 strcpy((char *)alloca(strlen(origOptString
) + 1),
753 if (optString
[0] == '\0')
754 return POPT_ERROR_BADOPT
;
756 if (optString
[1] == '-' && !optString
[2]) {
757 con
->restLeftover
= 1;
764 if (*optString
== '-')
765 singleDash
= 0, optString
++;
769 /* XXX aliases with arg substitution need "--alias=arg" */
770 if (handleAlias(con
, optString
, '\0', NULL
))
773 if (handleExec(con
, optString
, '\0'))
776 /* Check for "--long=arg" option. */
777 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
781 /* XXX longArg is mapped back to persistent storage. */
782 longArg
= origOptString
+ (oe
- localOptString
);
785 opt
= findOption(con
->options
, optString
, '\0', &cb
, &cbData
,
787 if (!opt
&& !singleDash
)
788 return POPT_ERROR_BADOPT
;
792 con
->os
->nextCharArg
= origOptString
+ 1;
794 if (con
->os
== con
->optionStack
&&
795 opt
->argInfo
& POPT_ARGFLAG_STRIP
)
798 poptStripArg(con
, thisopt
);
804 /* Process next short option */
805 /*@-branchstate@*/ /* FIX: W2DO? */
806 if (con
->os
->nextCharArg
) {
807 origOptString
= con
->os
->nextCharArg
;
809 con
->os
->nextCharArg
= NULL
;
811 if (handleAlias(con
, NULL
, *origOptString
, origOptString
+ 1))
814 if (handleExec(con
, NULL
, *origOptString
)) {
815 /* Restore rest of short options for further processing */
817 if (*origOptString
!= '\0')
818 con
->os
->nextCharArg
= origOptString
;
822 opt
= findOption(con
->options
, NULL
, *origOptString
, &cb
,
825 return POPT_ERROR_BADOPT
;
829 if (*origOptString
!= '\0')
830 con
->os
->nextCharArg
= origOptString
;
834 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
835 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
) {
836 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, 1L))
837 return POPT_ERROR_BADOPERATION
;
838 } else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
) {
840 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, (long)opt
->val
))
841 return POPT_ERROR_BADOPERATION
;
843 } else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
844 con
->os
->nextArg
= (const char *)_free(con
->os
->nextArg
);
845 /*@-usedef@*/ /* FIX: W2DO? */
848 longArg
= expandNextArg(con
, longArg
);
849 con
->os
->nextArg
= longArg
;
850 } else if (con
->os
->nextCharArg
) {
851 longArg
= expandNextArg(con
, con
->os
->nextCharArg
);
852 con
->os
->nextArg
= longArg
;
853 con
->os
->nextCharArg
= NULL
;
855 while (con
->os
->next
== con
->os
->argc
&&
856 con
->os
> con
->optionStack
) {
859 if (con
->os
->next
== con
->os
->argc
) {
860 if (!(opt
->argInfo
& POPT_ARGFLAG_OPTIONAL
))
861 /*@-compdef@*/ /* FIX: con->os->argv not defined */
862 return POPT_ERROR_NOARG
;
864 con
->os
->nextArg
= NULL
;
868 * Make sure this isn't part of a short arg or the
869 * result of an alias expansion.
871 if (con
->os
== con
->optionStack
&&
872 (opt
->argInfo
& POPT_ARGFLAG_STRIP
) &&
874 poptStripArg(con
, con
->os
->next
);
877 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
878 /* XXX watchout: subtle side-effects live here. */
879 longArg
= con
->os
->argv
[con
->os
->next
++];
880 longArg
= expandNextArg(con
, longArg
);
881 con
->os
->nextArg
= longArg
;
888 switch (opt
->argInfo
& POPT_ARG_MASK
) {
889 case POPT_ARG_STRING
:
890 /* XXX memory leak, hard to plug */
891 *((const char **) opt
->arg
) = (con
->os
->nextArg
)
892 ? xstrdup(con
->os
->nextArg
) : NULL
;
893 /*@switchbreak@*/ break;
900 if (con
->os
->nextArg
) {
901 aLong
= strtol(con
->os
->nextArg
, &end
, 0);
902 if (!(end
&& *end
== '\0'))
903 return POPT_ERROR_BADNUMBER
;
906 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_LONG
) {
907 if (aLong
== LONG_MIN
|| aLong
== LONG_MAX
)
908 return POPT_ERROR_OVERFLOW
;
909 if (poptSaveLong((long *)opt
->arg
, opt
->argInfo
, aLong
))
910 return POPT_ERROR_BADOPERATION
;
912 if (aLong
> INT_MAX
|| aLong
< INT_MIN
)
913 return POPT_ERROR_OVERFLOW
;
914 if (poptSaveInt((int *)opt
->arg
, opt
->argInfo
, aLong
))
915 return POPT_ERROR_BADOPERATION
;
917 } /*@switchbreak@*/ break;
920 case POPT_ARG_DOUBLE
:
921 { double aDouble
= 0.0;
924 if (con
->os
->nextArg
) {
926 int saveerrno
= errno
;
928 aDouble
= strtod(con
->os
->nextArg
, &end
);
930 return POPT_ERROR_OVERFLOW
;
934 return POPT_ERROR_BADNUMBER
;
937 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_DOUBLE
) {
938 *((double *) opt
->arg
) = aDouble
;
941 #define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
943 if ((_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
944 return POPT_ERROR_OVERFLOW
;
945 if ((FLT_MIN
- _ABS(aDouble
)) > DBL_EPSILON
)
946 return POPT_ERROR_OVERFLOW
;
947 *((float *) opt
->arg
) = aDouble
;
949 } /*@switchbreak@*/ break;
952 POPT_("option type (%d) not implemented in popt\n"),
953 (opt
->argInfo
& POPT_ARG_MASK
));
955 /*@notreached@*/ /*@switchbreak@*/ break;
962 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
964 } else if (opt
->val
&& ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_VAL
))
967 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
968 con
->finalArgvAlloced
+= 10;
969 con
->finalArgv
= (const char **)realloc(con
->finalArgv
,
970 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
973 if (con
->finalArgv
!= NULL
)
974 { char *s
= (char *)malloc(
975 (opt
->longName
? strlen(opt
->longName
) : 0) + 3);
976 if (s
!= NULL
) { /* XXX can't happen */
979 ((opt
->argInfo
& POPT_ARGFLAG_ONEDASH
) ? "-" : "--"),
982 sprintf(s
, "-%c", opt
->shortName
);
983 con
->finalArgv
[con
->finalArgvCount
++] = s
;
985 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
988 if (opt
->arg
&& (opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_NONE
)
989 /*@-ifempty@*/ ; /*@=ifempty@*/
990 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_VAL
)
991 /*@-ifempty@*/ ; /*@=ifempty@*/
992 else if ((opt
->argInfo
& POPT_ARG_MASK
) != POPT_ARG_NONE
) {
993 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
)
994 con
->finalArgv
[con
->finalArgvCount
++] =
995 /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
996 xstrdup(con
->os
->nextArg
);
1001 return (opt
? opt
->val
: -1); /* XXX can't happen */
1005 const char * poptGetOptArg(poptContext con
)
1007 const char * ret
= NULL
;
1010 ret
= con
->os
->nextArg
;
1011 con
->os
->nextArg
= NULL
;
1017 const char * poptGetArg(poptContext con
)
1019 const char * ret
= NULL
;
1020 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1021 ret
= con
->leftovers
[con
->nextLeftover
++];
1025 const char * poptPeekArg(poptContext con
)
1027 const char * ret
= NULL
;
1028 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1029 ret
= con
->leftovers
[con
->nextLeftover
];
1034 const char ** poptGetArgs(poptContext con
)
1037 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1040 /* some apps like [like RPM ;-) ] need this NULL terminated */
1041 con
->leftovers
[con
->numLeftovers
] = NULL
;
1043 /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
1044 return (con
->leftovers
+ con
->nextLeftover
);
1045 /*@=nullret =nullstate @*/
1049 poptContext
poptFreeContext(poptContext con
)
1054 if (con
== NULL
) return con
;
1055 poptResetContext(con
);
1056 con
->os
->argb
= (pbm_set
*)_free(con
->os
->argb
);
1058 if (con
->aliases
!= NULL
)
1059 for (i
= 0; i
< con
->numAliases
; i
++) {
1060 item
= con
->aliases
+ i
;
1061 /*@-modobserver -observertrans -dependenttrans@*/
1062 item
->option
.longName
= (const char *)_free(item
->option
.longName
);
1063 item
->option
.descrip
= (const char *)_free(item
->option
.descrip
);
1064 item
->option
.argDescrip
= (const char *)_free(item
->option
.argDescrip
);
1065 /*@=modobserver =observertrans =dependenttrans@*/
1066 item
->argv
= (const char **)_free(item
->argv
);
1068 con
->aliases
= (poptItem
)_free(con
->aliases
);
1070 if (con
->execs
!= NULL
)
1071 for (i
= 0; i
< con
->numExecs
; i
++) {
1072 item
= con
->execs
+ i
;
1073 /*@-modobserver -observertrans -dependenttrans@*/
1074 item
->option
.longName
= (const char *)_free(item
->option
.longName
);
1075 item
->option
.descrip
= (const char *)_free(item
->option
.descrip
);
1076 item
->option
.argDescrip
= (const char *)_free(item
->option
.argDescrip
);
1077 /*@=modobserver =observertrans =dependenttrans@*/
1078 item
->argv
= (const char **)_free(item
->argv
);
1080 con
->execs
= (poptItem
)_free(con
->execs
);
1082 con
->leftovers
= (const char **)_free(con
->leftovers
);
1083 con
->finalArgv
= (const char **)_free(con
->finalArgv
);
1084 con
->appName
= (const char *)_free(con
->appName
);
1085 con
->otherHelp
= (const char *)_free(con
->otherHelp
);
1086 con
->execPath
= (const char *)_free(con
->execPath
);
1087 con
->arg_strip
= (pbm_set
*)PBM_FREE(con
->arg_strip
);
1089 con
= (poptContext
)_free(con
);
1093 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1094 /*@unused@*/ int flags
)
1096 poptItem item
= (poptItem
)alloca(sizeof(*item
));
1097 memset(item
, 0, sizeof(*item
));
1098 item
->option
.longName
= alias
.longName
;
1099 item
->option
.shortName
= alias
.shortName
;
1100 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1101 item
->option
.arg
= 0;
1102 item
->option
.val
= 0;
1103 item
->option
.descrip
= NULL
;
1104 item
->option
.argDescrip
= NULL
;
1105 item
->argc
= alias
.argc
;
1106 item
->argv
= alias
.argv
;
1107 return poptAddItem(con
, item
, 0);
1111 /*@-mustmod@*/ /* LCL: con not modified? */
1112 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1114 poptItem
* items
, item
;
1119 items
= &con
->execs
;
1120 nitems
= &con
->numExecs
;
1123 items
= &con
->aliases
;
1124 nitems
= &con
->numAliases
;
1128 /*@notreached@*/ break;
1131 *items
= (poptItem
)realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1132 if ((*items
) == NULL
)
1135 item
= (*items
) + (*nitems
);
1137 item
->option
.longName
=
1138 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1139 item
->option
.shortName
= newItem
->option
.shortName
;
1140 item
->option
.argInfo
= newItem
->option
.argInfo
;
1141 item
->option
.arg
= newItem
->option
.arg
;
1142 item
->option
.val
= newItem
->option
.val
;
1143 item
->option
.descrip
=
1144 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1145 item
->option
.argDescrip
=
1146 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1147 item
->argc
= newItem
->argc
;
1148 item
->argv
= newItem
->argv
;
1157 const char * poptBadOption(poptContext con
, int flags
)
1159 struct optionStackEntry
* os
= NULL
;
1162 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1164 /*@-nullderef@*/ /* LCL: os->argv != NULL */
1165 return (os
&& os
->argv
? os
->argv
[os
->next
- 1] : NULL
);
1169 const char *poptStrerror(const int error
)
1172 case POPT_ERROR_NOARG
:
1173 return POPT_("missing argument");
1174 case POPT_ERROR_BADOPT
:
1175 return POPT_("unknown option");
1176 case POPT_ERROR_BADOPERATION
:
1177 return POPT_("mutually exclusive logical operations requested");
1178 case POPT_ERROR_NULLARG
:
1179 return POPT_("opt->arg should not be NULL");
1180 case POPT_ERROR_OPTSTOODEEP
:
1181 return POPT_("aliases nested too deeply");
1182 case POPT_ERROR_BADQUOTE
:
1183 return POPT_("error in parameter quoting");
1184 case POPT_ERROR_BADNUMBER
:
1185 return POPT_("invalid numeric value");
1186 case POPT_ERROR_OVERFLOW
:
1187 return POPT_("number too large or too small");
1188 case POPT_ERROR_MALLOC
:
1189 return POPT_("memory allocation failed");
1190 case POPT_ERROR_ERRNO
:
1191 return strerror(errno
);
1193 return POPT_("unknown error");
1197 int poptStuffArgs(poptContext con
, const char ** argv
)
1202 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1203 return POPT_ERROR_OPTSTOODEEP
;
1205 for (argc
= 0; argv
[argc
]; argc
++)
1210 con
->os
->nextArg
= NULL
;
1211 con
->os
->nextCharArg
= NULL
;
1212 con
->os
->currAlias
= NULL
;
1213 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1214 con
->os
->argb
= NULL
;
1215 con
->os
->stuffed
= 1;
1220 const char * poptGetInvocationName(poptContext con
)
1222 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1226 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1234 for (i
= 1; i
< argc
; i
++) {
1235 if (PBM_ISSET(i
, con
->arg_strip
))
1239 for (i
= 1; i
< argc
; i
++) {
1240 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1242 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;