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 */
13 #if defined(__LCLINT__)
14 /*@-declundef -exportheader @*/
15 extern long long int strtoll(const char *nptr
, /*@null@*/ char **endptr
,
17 /*@modifies *endptr@*/;
18 /*@=declundef =exportheader @*/
34 unsigned int _poptArgMask
= POPT_ARG_MASK
;
36 unsigned int _poptGroupMask
= POPT_GROUP_MASK
;
38 #if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
39 static char * strerror(int errno
)
42 extern char * sys_errlist
[];
44 if ((0 <= errno
) && (errno
< sys_nerr
))
45 return sys_errlist
[errno
];
47 return POPT_("unknown errno");
53 static void prtcon(const char *msg
, poptContext con
)
55 if (msg
) fprintf(stderr
, "%s", msg
);
56 fprintf(stderr
, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
58 (con
->os
->nextCharArg
? con
->os
->nextCharArg
: ""),
59 (con
->os
->nextArg
? con
->os
->nextArg
: ""),
61 (con
->os
->argv
&& con
->os
->argv
[con
->os
->next
]
62 ? con
->os
->argv
[con
->os
->next
] : ""));
66 void poptSetExecPath(poptContext con
, const char * path
, int allowAbsolute
)
68 con
->execPath
= _free(con
->execPath
);
69 con
->execPath
= xstrdup(path
);
70 con
->execAbsolute
= allowAbsolute
;
74 static void invokeCallbacksPRE(poptContext con
, const struct poptOption
* opt
)
75 /*@globals internalState@*/
76 /*@modifies internalState@*/
79 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
80 poptArg arg
= { .ptr
= opt
->arg
};
82 switch (poptArgType(opt
)) {
83 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
84 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
85 invokeCallbacksPRE(con
, arg
.opt
);
86 /*@switchbreak@*/ break;
87 case POPT_ARG_CALLBACK
: /* Perform callback. */
88 if (!CBF_ISSET(opt
, PRE
))
89 /*@switchbreak@*/ break;
90 /*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */
91 arg
.cb(con
, POPT_CALLBACK_REASON_PRE
, NULL
, NULL
, opt
->descrip
);
93 /*@switchbreak@*/ break;
98 static void invokeCallbacksPOST(poptContext con
, const struct poptOption
* opt
)
99 /*@globals internalState@*/
100 /*@modifies internalState@*/
103 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
104 poptArg arg
= { .ptr
= opt
->arg
};
106 switch (poptArgType(opt
)) {
107 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
108 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
109 invokeCallbacksPOST(con
, arg
.opt
);
110 /*@switchbreak@*/ break;
111 case POPT_ARG_CALLBACK
: /* Perform callback. */
112 if (!CBF_ISSET(opt
, POST
))
113 /*@switchbreak@*/ break;
114 /*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */
115 arg
.cb(con
, POPT_CALLBACK_REASON_POST
, NULL
, NULL
, opt
->descrip
);
116 /*@=noeffectuncon @*/
117 /*@switchbreak@*/ break;
122 static void invokeCallbacksOPTION(poptContext con
,
123 const struct poptOption
* opt
,
124 const struct poptOption
* myOpt
,
125 /*@null@*/ const void * myData
, int shorty
)
126 /*@globals internalState@*/
127 /*@modifies internalState@*/
129 const struct poptOption
* cbopt
= NULL
;
130 poptArg cbarg
= { .ptr
= NULL
};
133 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
134 poptArg arg
= { .ptr
= opt
->arg
};
135 switch (poptArgType(opt
)) {
136 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
137 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
138 if (opt
->arg
!= NULL
)
139 invokeCallbacksOPTION(con
, opt
->arg
, myOpt
, myData
, shorty
);
140 /*@switchbreak@*/ break;
141 case POPT_ARG_CALLBACK
: /* Save callback info. */
142 if (CBF_ISSET(opt
, SKIPOPTION
))
143 /*@switchbreak@*/ break;
145 cbarg
.ptr
= opt
->arg
;
146 /*@switchbreak@*/ break;
147 default: /* Perform callback on matching option. */
148 if (cbopt
== NULL
|| cbarg
.cb
== NULL
)
149 /*@switchbreak@*/ break;
150 if ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
151 myOpt
->shortName
== opt
->shortName
)
152 || (myOpt
->longName
!= NULL
&& opt
->longName
!= NULL
&&
153 !strcmp(myOpt
->longName
, opt
->longName
)))
154 { const void *cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
155 /*@-noeffectuncon @*/ /* XXX no known way to annotate (*vector) calls. */
156 cbarg
.cb(con
, POPT_CALLBACK_REASON_OPTION
,
157 myOpt
, con
->os
->nextArg
, cbData
);
158 /*@=noeffectuncon @*/
159 /* Terminate (unless explcitly continuing). */
160 if (!CBF_ISSET(cbopt
, CONTINUE
))
163 /*@switchbreak@*/ break;
168 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
169 const struct poptOption
* options
, unsigned int flags
)
171 poptContext con
= malloc(sizeof(*con
));
173 if (con
== NULL
) return NULL
; /* XXX can't happen */
174 memset(con
, 0, sizeof(*con
));
176 con
->os
= con
->optionStack
;
177 con
->os
->argc
= argc
;
178 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
179 con
->os
->argv
= argv
;
180 /*@=dependenttrans =assignexpose@*/
181 con
->os
->argb
= NULL
;
183 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
184 con
->os
->next
= 1; /* skip argv[0] */
186 con
->leftovers
= calloc( (size_t)(argc
+ 1), sizeof(*con
->leftovers
) );
187 /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
188 con
->options
= options
;
189 /*@=dependenttrans =assignexpose@*/
195 con
->finalArgvAlloced
= argc
* 2;
196 con
->finalArgv
= calloc( (size_t)con
->finalArgvAlloced
, sizeof(*con
->finalArgv
) );
197 con
->execAbsolute
= 1;
198 con
->arg_strip
= NULL
;
200 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
201 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
204 con
->appName
= xstrdup(name
);
206 invokeCallbacksPRE(con
, con
->options
);
211 static void cleanOSE(/*@special@*/ struct optionStackEntry
*os
)
213 /*@releases os->nextArg, os->argv, os->argb @*/
216 os
->nextArg
= _free(os
->nextArg
);
217 os
->argv
= _free(os
->argv
);
218 os
->argb
= PBM_FREE(os
->argb
);
221 void poptResetContext(poptContext con
)
225 if (con
== NULL
) return;
226 while (con
->os
> con
->optionStack
) {
229 con
->os
->argb
= PBM_FREE(con
->os
->argb
);
230 con
->os
->currAlias
= NULL
;
231 con
->os
->nextCharArg
= NULL
;
232 con
->os
->nextArg
= NULL
;
233 con
->os
->next
= 1; /* skip argv[0] */
235 con
->numLeftovers
= 0;
236 con
->nextLeftover
= 0;
237 con
->restLeftover
= 0;
240 if (con
->finalArgv
!= NULL
)
241 for (i
= 0; i
< con
->finalArgvCount
; i
++) {
242 /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
243 con
->finalArgv
[i
] = _free(con
->finalArgv
[i
]);
244 /*@=unqualifiedtrans@*/
247 con
->finalArgvCount
= 0;
248 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
249 /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
254 /* Only one of longName, shortName should be set, not both. */
255 static int handleExec(/*@special@*/ poptContext con
,
256 /*@null@*/ const char * longName
, char shortName
)
257 /*@uses con->execs, con->numExecs, con->flags, con->doExec,
258 con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
264 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
267 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
268 item
= con
->execs
+ i
;
269 if (longName
&& !(item
->option
.longName
&&
270 !strcmp(longName
, item
->option
.longName
)))
272 else if (shortName
!= item
->option
.shortName
)
279 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
282 if (con
->doExec
== NULL
) {
283 con
->doExec
= con
->execs
+ i
;
287 /* We already have an exec to do; remember this option for next
289 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
290 con
->finalArgvAlloced
+= 10;
291 con
->finalArgv
= realloc(con
->finalArgv
,
292 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
295 i
= con
->finalArgvCount
++;
296 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
297 { char *s
= malloc((longName
? strlen(longName
) : 0) + sizeof("--"));
298 if (s
!= NULL
) { /* XXX can't happen */
299 con
->finalArgv
[i
] = s
;
302 s
= stpcpy( stpcpy(s
, "-"), longName
);
307 con
->finalArgv
[i
] = NULL
;
314 * Compare long option for equality, adjusting for POPT_ARGFLAG_TOGGLE.
316 * @param longName arg option
317 * @param longNameLen arg option length
318 * @return does long option match?
321 longOptionStrcmp(const struct poptOption
* opt
,
322 /*@null@*/ const char * longName
, size_t longNameLen
)
325 const char * optLongName
= opt
->longName
;
328 if (optLongName
== NULL
|| longName
== NULL
) /* XXX can't heppen */
331 if (F_ISSET(opt
, TOGGLE
)) {
332 if (optLongName
[0] == 'n' && optLongName
[1] == 'o') {
333 optLongName
+= sizeof("no") - 1;
334 if (optLongName
[0] == '-')
337 if (longName
[0] == 'n' && longName
[1] == 'o') {
338 longName
+= sizeof("no") - 1;
339 longNameLen
-= sizeof("no") - 1;
340 if (longName
[0] == '-') {
346 rc
= (int)(strlen(optLongName
) == longNameLen
);
348 rc
= (int)(strncmp(optLongName
, longName
, longNameLen
) == 0);
352 /* Only one of longName, shortName may be set at a time */
353 static int handleAlias(/*@special@*/ poptContext con
,
354 /*@null@*/ const char * longName
, size_t longNameLen
,
356 /*@exposed@*/ /*@null@*/ const char * nextArg
)
357 /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
358 con->os->currAlias, con->os->currAlias->option.longName @*/
361 poptItem item
= con
->os
->currAlias
;
366 if (longName
&& item
->option
.longName
!= NULL
367 && longOptionStrcmp(&item
->option
, longName
, longNameLen
))
370 if (shortName
&& shortName
== item
->option
.shortName
)
374 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
377 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
378 item
= con
->aliases
+ i
;
380 if (item
->option
.longName
== NULL
)
382 if (!longOptionStrcmp(&item
->option
, longName
, longNameLen
))
384 } else if (shortName
!= item
->option
.shortName
)
390 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
391 return POPT_ERROR_OPTSTOODEEP
;
393 if (longName
== NULL
&& nextArg
!= NULL
&& *nextArg
!= '\0')
394 con
->os
->nextCharArg
= nextArg
;
398 con
->os
->stuffed
= 0;
399 con
->os
->nextArg
= NULL
;
400 con
->os
->nextCharArg
= NULL
;
401 con
->os
->currAlias
= con
->aliases
+ i
;
403 int ac
= con
->os
->currAlias
->argc
;
404 /* Append --foo=bar arg to alias argv array (if present). */
405 if (longName
&& nextArg
!= NULL
&& *nextArg
!= '\0') {
406 av
= malloc((ac
+ 1 + 1) * sizeof(*av
));
407 if (av
!= NULL
) { /* XXX won't happen. */
408 for (i
= 0; i
< ac
; i
++) {
409 av
[i
] = con
->os
->currAlias
->argv
[i
];
413 } else /* XXX revert to old popt behavior if malloc fails. */
414 av
= con
->os
->currAlias
->argv
;
416 av
= con
->os
->currAlias
->argv
;
417 rc
= poptDupArgv(ac
, av
, &con
->os
->argc
, &con
->os
->argv
);
418 if (av
!= NULL
&& av
!= con
->os
->currAlias
->argv
)
421 con
->os
->argb
= NULL
;
423 return (rc
? rc
: 1);
427 * Return absolute path to executable by searching PATH.
428 * @param argv0 name of executable
429 * @return (malloc'd) absolute path to executable (or NULL)
432 const char * findProgramPath(/*@null@*/ const char * argv0
)
435 char *path
= NULL
, *s
= NULL
, *se
;
438 if (argv0
== NULL
) return NULL
; /* XXX can't happen */
440 /* If there is a / in argv[0], it has to be an absolute path. */
441 /* XXX Hmmm, why not if (argv0[0] == '/') ... instead? */
442 if (strchr(argv0
, '/'))
443 return xstrdup(argv0
);
445 if ((path
= getenv("PATH")) == NULL
|| (path
= xstrdup(path
)) == NULL
)
448 /* The return buffer in t is big enough for any path. */
449 if ((t
= malloc(strlen(path
) + strlen(argv0
) + sizeof("/"))) != NULL
)
450 for (s
= path
; s
&& *s
; s
= se
) {
452 /* Snip PATH element into [s,se). */
453 if ((se
= strchr(s
, ':')))
456 /* Append argv0 to PATH element. */
457 (void) stpcpy(stpcpy(stpcpy(t
, s
), "/"), argv0
);
459 /* If file is executable, bingo! */
460 if (!access(t
, X_OK
))
464 /* If no executable was found in PATH, return NULL. */
466 if (!(s
&& *s
) && t
!= NULL
)
469 /*@-modobserver -observertrans -usedef @*/
471 /*@=modobserver =observertrans =usedef @*/
476 static int execCommand(poptContext con
)
477 /*@globals internalState @*/
478 /*@modifies internalState @*/
480 poptItem item
= con
->doExec
;
481 poptArgv argv
= NULL
;
484 int ec
= POPT_ERROR_ERRNO
;
486 if (item
== NULL
) /*XXX can't happen*/
487 return POPT_ERROR_NOARG
;
489 if (item
->argv
== NULL
|| item
->argc
< 1 ||
490 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
491 return POPT_ERROR_NOARG
;
493 argv
= malloc(sizeof(*argv
) *
494 (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
495 if (argv
== NULL
) return POPT_ERROR_MALLOC
;
497 if (!strchr(item
->argv
[0], '/') && con
->execPath
!= NULL
) {
498 char *s
= malloc(strlen(con
->execPath
) + strlen(item
->argv
[0]) + sizeof("/"));
500 (void)stpcpy(stpcpy(stpcpy(s
, con
->execPath
), "/"), item
->argv
[0]);
504 argv
[argc
] = findProgramPath(item
->argv
[0]);
505 if (argv
[argc
++] == NULL
) {
506 ec
= POPT_ERROR_NOARG
;
510 if (item
->argc
> 1) {
511 memcpy(argv
+ argc
, item
->argv
+ 1, sizeof(*argv
) * (item
->argc
- 1));
512 argc
+= (item
->argc
- 1);
515 if (con
->finalArgv
!= NULL
&& con
->finalArgvCount
> 0) {
516 memcpy(argv
+ argc
, con
->finalArgv
,
517 sizeof(*argv
) * con
->finalArgvCount
);
518 argc
+= con
->finalArgvCount
;
521 if (con
->leftovers
!= NULL
&& con
->numLeftovers
> 0) {
522 memcpy(argv
+ argc
, con
->leftovers
, sizeof(*argv
) * con
->numLeftovers
);
523 argc
+= con
->numLeftovers
;
528 #if defined(hpux) || defined(__hpux)
529 rc
= setresgid(getgid(), getgid(),-1);
531 rc
= setresuid(getuid(), getuid(),-1);
535 * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
536 * XXX sez' Timur Bakeyev <mc@bat.ru>
537 * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
539 #if defined(HAVE_SETUID)
540 rc
= setgid(getgid());
542 rc
= setuid(getuid());
544 #elif defined (HAVE_SETREUID)
545 rc
= setregid(getgid(), getgid());
547 rc
= setreuid(getuid(), getuid());
550 ; /* Can't drop privileges */
557 fprintf(stderr
, "==> execvp(%s) argv[%d]:", argv
[0], argc
);
558 for (avp
= argv
; *avp
; avp
++)
559 fprintf(stderr
, " '%s'", *avp
);
560 fprintf(stderr
, "\n");
565 rc
= execvp(argv
[0], (char *const *)argv
);
571 free((void *)argv
[0]);
577 /*@observer@*/ /*@null@*/
578 static const struct poptOption
*
579 findOption(const struct poptOption
* opt
,
580 /*@null@*/ const char * longName
, size_t longNameLen
,
582 /*@null@*/ /*@out@*/ poptCallbackType
* callback
,
583 /*@null@*/ /*@out@*/ const void ** callbackData
,
584 unsigned int argInfo
)
585 /*@modifies *callback, *callbackData */
587 const struct poptOption
* cb
= NULL
;
588 poptArg cbarg
= { .ptr
= NULL
};
590 /* This happens when a single - is given */
591 if (LF_ISSET(ONEDASH
) && !shortName
&& (longName
&& *longName
== '\0'))
594 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
595 poptArg arg
= { .ptr
= opt
->arg
};
597 switch (poptArgType(opt
)) {
598 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
599 { const struct poptOption
* opt2
;
601 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
602 if (arg
.ptr
== NULL
) continue; /* XXX program error */
603 opt2
= findOption(arg
.opt
, longName
, longNameLen
, shortName
, callback
,
604 callbackData
, argInfo
);
605 if (opt2
== NULL
) continue;
606 /* Sub-table data will be inheirited if no data yet. */
607 /*@-observertrans -dependenttrans @*/
608 if (callback
&& *callback
609 && callbackData
&& *callbackData
== NULL
)
610 *callbackData
= opt
->descrip
;
611 /*@=observertrans =dependenttrans @*/
613 } /*@notreached@*/ /*@switchbreak@*/ break;
614 case POPT_ARG_CALLBACK
:
616 cbarg
.ptr
= opt
->arg
;
618 /*@notreached@*/ /*@switchbreak@*/ break;
620 /*@switchbreak@*/ break;
623 if (longName
!= NULL
&& opt
->longName
!= NULL
&&
624 (!LF_ISSET(ONEDASH
) || F_ISSET(opt
, ONEDASH
)) &&
625 longOptionStrcmp(opt
, longName
, longNameLen
))
628 } else if (shortName
&& shortName
== opt
->shortName
) {
633 if (opt
->longName
== NULL
&& !opt
->shortName
)
636 /*@-modobserver -mods @*/
638 *callback
= (cb
? cbarg
.cb
: NULL
);
640 /*@-observertrans -dependenttrans @*/
641 *callbackData
= (cb
&& !CBF_ISSET(cb
, INC_DATA
) ? cb
->descrip
: NULL
);
642 /*@=observertrans =dependenttrans @*/
643 /*@=modobserver =mods @*/
648 static const char * findNextArg(/*@special@*/ poptContext con
,
649 unsigned argx
, int delete_arg
)
650 /*@uses con->optionStack, con->os,
651 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
654 struct optionStackEntry
* os
= con
->os
;
660 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
661 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
662 if (os
->argv
!= NULL
)
663 for (i
= os
->next
; i
< os
->argc
; i
++) {
665 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
666 /*@innercontinue@*/ continue;
667 if (*os
->argv
[i
] == '-')
668 /*@innercontinue@*/ continue;
670 /*@innercontinue@*/ continue;
673 if (os
->argb
== NULL
) os
->argb
= PBM_ALLOC(os
->argc
);
674 if (os
->argb
!= NULL
) /* XXX can't happen */
675 PBM_SET(i
, os
->argb
);
677 /*@innerbreak@*/ break;
680 if (os
> con
->optionStack
) os
--;
681 } while (arg
== NULL
);
685 static /*@only@*/ /*@null@*/ const char *
686 expandNextArg(/*@special@*/ poptContext con
, const char * s
)
687 /*@uses con->optionStack, con->os,
688 con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
691 const char * a
= NULL
;
693 size_t tn
= strlen(s
) + 1;
697 if (t
== NULL
) return NULL
; /* XXX can't happen */
699 while ((c
= *s
++) != '\0') {
701 #if 0 /* XXX can't do this */
702 case '\\': /* escape */
704 /*@switchbreak@*/ break;
707 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
708 /*@switchbreak@*/ break;
709 /* XXX Make sure that findNextArg deletes only next arg. */
711 if ((a
= findNextArg(con
, 1U, 1)) == NULL
)
712 /*@switchbreak@*/ break;
714 s
+= sizeof("#:+") - 1;
717 { size_t pos
= (size_t) (te
- t
);
718 if ((t
= realloc(t
, tn
)) == NULL
) /* XXX can't happen */
720 te
= stpcpy(t
+ pos
, a
);
723 /*@notreached@*/ /*@switchbreak@*/ break;
725 /*@switchbreak@*/ break;
730 /* If the new string is longer than needed, shorten. */
732 /*@-usereleased@*/ /* XXX splint can't follow the pointers. */
733 if ((te
= realloc(t
, (size_t)(te
- t
))) == NULL
)
741 static void poptStripArg(/*@special@*/ poptContext con
, int which
)
742 /*@uses con->optionStack @*/
743 /*@defines con->arg_strip @*/
746 /*@-compdef -sizeoftype -usedef @*/
747 if (con
->arg_strip
== NULL
)
748 con
->arg_strip
= PBM_ALLOC(con
->optionStack
[0].argc
);
749 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
750 PBM_SET(which
, con
->arg_strip
);
752 /*@=compdef =sizeoftype =usedef @*/
756 unsigned int _poptBitsN
= _POPT_BITS_N
;
758 unsigned int _poptBitsM
= _POPT_BITS_M
;
760 unsigned int _poptBitsK
= _POPT_BITS_K
;
763 static int _poptBitsNew(/*@null@*/ poptBits
*bitsp
)
764 /*@globals _poptBitsN, _poptBitsM, _poptBitsK @*/
765 /*@modifies *bitsp, _poptBitsN, _poptBitsM, _poptBitsK @*/
768 return POPT_ERROR_NULLARG
;
770 /* XXX handle negated initialization. */
771 if (*bitsp
== NULL
) {
772 if (_poptBitsN
== 0) {
773 _poptBitsN
= _POPT_BITS_N
;
774 _poptBitsM
= _POPT_BITS_M
;
776 if (_poptBitsM
== 0U) _poptBitsM
= (3 * _poptBitsN
) / 2;
777 if (_poptBitsK
== 0U || _poptBitsK
> 32U) _poptBitsK
= _POPT_BITS_K
;
778 *bitsp
= PBM_ALLOC(_poptBitsM
-1);
785 int poptBitsAdd(poptBits bits
, const char * s
)
787 size_t ns
= (s
? strlen(s
) : 0);
791 if (bits
== NULL
|| ns
== 0)
792 return POPT_ERROR_NULLARG
;
794 poptJlu32lpair(s
, ns
, &h0
, &h1
);
796 for (ns
= 0; ns
< (size_t)_poptBitsK
; ns
++) {
797 uint32_t h
= h0
+ ns
* h1
;
798 uint32_t ix
= (h
% _poptBitsM
);
804 int poptBitsChk(poptBits bits
, const char * s
)
806 size_t ns
= (s
? strlen(s
) : 0);
811 if (bits
== NULL
|| ns
== 0)
812 return POPT_ERROR_NULLARG
;
814 poptJlu32lpair(s
, ns
, &h0
, &h1
);
816 for (ns
= 0; ns
< (size_t)_poptBitsK
; ns
++) {
817 uint32_t h
= h0
+ ns
* h1
;
818 uint32_t ix
= (h
% _poptBitsM
);
819 if (PBM_ISSET(ix
, bits
))
827 int poptBitsClr(poptBits bits
)
829 static size_t nbw
= (__PBM_NBITS
/8);
830 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
833 return POPT_ERROR_NULLARG
;
834 memset(bits
, 0, nw
* nbw
);
838 int poptBitsDel(poptBits bits
, const char * s
)
840 size_t ns
= (s
? strlen(s
) : 0);
844 if (bits
== NULL
|| ns
== 0)
845 return POPT_ERROR_NULLARG
;
847 poptJlu32lpair(s
, ns
, &h0
, &h1
);
849 for (ns
= 0; ns
< (size_t)_poptBitsK
; ns
++) {
850 uint32_t h
= h0
+ ns
* h1
;
851 uint32_t ix
= (h
% _poptBitsM
);
857 int poptBitsIntersect(poptBits
*ap
, const poptBits b
)
862 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
865 if (ap
== NULL
|| b
== NULL
|| _poptBitsNew(ap
))
866 return POPT_ERROR_NULLARG
;
867 abits
= __PBM_BITS(*ap
);
868 bbits
= __PBM_BITS(b
);
870 for (i
= 0; i
< nw
; i
++) {
871 abits
[i
] &= bbits
[i
];
877 int poptBitsUnion(poptBits
*ap
, const poptBits b
)
882 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
885 if (ap
== NULL
|| b
== NULL
|| _poptBitsNew(ap
))
886 return POPT_ERROR_NULLARG
;
887 abits
= __PBM_BITS(*ap
);
888 bbits
= __PBM_BITS(b
);
890 for (i
= 0; i
< nw
; i
++) {
891 abits
[i
] |= bbits
[i
];
897 int poptBitsArgs(poptContext con
, poptBits
*ap
)
902 if (con
== NULL
|| ap
== NULL
|| _poptBitsNew(ap
) ||
903 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
904 return POPT_ERROR_NULLARG
;
906 /* some apps like [like RPM ;-) ] need this NULL terminated */
907 con
->leftovers
[con
->numLeftovers
] = NULL
;
909 for (av
= con
->leftovers
+ con
->nextLeftover
; *av
!= NULL
; av
++) {
910 if ((rc
= poptBitsAdd(*ap
, *av
)) != 0)
918 int poptSaveBits(poptBits
* bitsp
,
919 /*@unused@*/ UNUSED(unsigned int argInfo
), const char * s
)
925 if (bitsp
== NULL
|| s
== NULL
|| *s
== '\0' || _poptBitsNew(bitsp
))
926 return POPT_ERROR_NULLARG
;
928 /* Parse comma separated attributes. */
929 te
= tbuf
= xstrdup(s
);
930 while ((t
= te
) != NULL
&& *t
) {
931 while (*te
!= '\0' && *te
!= ',')
935 /* XXX Ignore empty strings. */
938 /* XXX Permit negated attributes. caveat emptor: false negatives. */
941 if ((rc
= poptBitsChk(*bitsp
, t
)) > 0)
942 rc
= poptBitsDel(*bitsp
, t
);
944 rc
= poptBitsAdd(*bitsp
, t
);
953 int poptSaveString(const char *** argvp
,
954 /*@unused@*/ UNUSED(unsigned int argInfo
), const char * val
)
958 if (argvp
== NULL
|| val
== NULL
)
959 return POPT_ERROR_NULLARG
;
961 /* XXX likely needs an upper bound on argc. */
963 while ((*argvp
)[argc
] != NULL
)
966 /*@-unqualifiedtrans -nullstate@*/ /* XXX no annotation for (*argvp) */
967 if ((*argvp
= xrealloc(*argvp
, (argc
+ 1 + 1) * sizeof(**argvp
))) != NULL
) {
968 (*argvp
)[argc
++] = xstrdup(val
);
969 (*argvp
)[argc
] = NULL
;
972 /*@=unqualifiedtrans =nullstate@*/
976 static unsigned int seed
= 0;
978 int poptSaveLongLong(long long * arg
, unsigned int argInfo
, long long aLongLong
)
982 /* XXX Check alignment, may fail on funky platforms. */
983 || (((unsigned long long)arg
) & (sizeof(*arg
)-1))
986 return POPT_ERROR_NULLARG
;
988 if (aLongLong
!= 0 && LF_ISSET(RANDOM
)) {
989 #if defined(HAVE_SRANDOM)
991 srandom((unsigned)getpid());
992 srandom((unsigned)random());
994 aLongLong
= (long long)(random() % (aLongLong
> 0 ? aLongLong
: -aLongLong
));
997 /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
998 return POPT_ERROR_BADOPERATION
;
1002 aLongLong
= ~aLongLong
;
1003 switch (LF_ISSET(LOGICALOPS
)) {
1007 case POPT_ARGFLAG_OR
:
1008 *(unsigned long long *)arg
|= (unsigned long long)aLongLong
;
1010 case POPT_ARGFLAG_AND
:
1011 *(unsigned long long *)arg
&= (unsigned long long)aLongLong
;
1013 case POPT_ARGFLAG_XOR
:
1014 *(unsigned long long *)arg
^= (unsigned long long)aLongLong
;
1017 return POPT_ERROR_BADOPERATION
;
1018 /*@notreached@*/ break;
1023 int poptSaveLong(long * arg
, unsigned int argInfo
, long aLong
)
1025 /* XXX Check alignment, may fail on funky platforms. */
1026 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
1027 return POPT_ERROR_NULLARG
;
1029 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
1030 #if defined(HAVE_SRANDOM)
1032 srandom((unsigned)getpid());
1033 srandom((unsigned)random());
1035 aLong
= random() % (aLong
> 0 ? aLong
: -aLong
);
1038 /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
1039 return POPT_ERROR_BADOPERATION
;
1044 switch (LF_ISSET(LOGICALOPS
)) {
1045 case 0: *arg
= aLong
; break;
1046 case POPT_ARGFLAG_OR
: *(unsigned long *)arg
|= (unsigned long)aLong
; break;
1047 case POPT_ARGFLAG_AND
: *(unsigned long *)arg
&= (unsigned long)aLong
; break;
1048 case POPT_ARGFLAG_XOR
: *(unsigned long *)arg
^= (unsigned long)aLong
; break;
1050 return POPT_ERROR_BADOPERATION
;
1051 /*@notreached@*/ break;
1056 int poptSaveInt(/*@null@*/ int * arg
, unsigned int argInfo
, long aLong
)
1058 /* XXX Check alignment, may fail on funky platforms. */
1059 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
1060 return POPT_ERROR_NULLARG
;
1062 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
1063 #if defined(HAVE_SRANDOM)
1065 srandom((unsigned)getpid());
1066 srandom((unsigned)random());
1068 aLong
= random() % (aLong
> 0 ? aLong
: -aLong
);
1071 /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
1072 return POPT_ERROR_BADOPERATION
;
1077 switch (LF_ISSET(LOGICALOPS
)) {
1078 case 0: *arg
= (int) aLong
; break;
1079 case POPT_ARGFLAG_OR
: *(unsigned int *)arg
|= (unsigned int) aLong
; break;
1080 case POPT_ARGFLAG_AND
: *(unsigned int *)arg
&= (unsigned int) aLong
; break;
1081 case POPT_ARGFLAG_XOR
: *(unsigned int *)arg
^= (unsigned int) aLong
; break;
1083 return POPT_ERROR_BADOPERATION
;
1084 /*@notreached@*/ break;
1089 int poptSaveShort(/*@null@*/ short * arg
, unsigned int argInfo
, long aLong
)
1091 /* XXX Check alignment, may fail on funky platforms. */
1092 if (arg
== NULL
|| (((unsigned long)arg
) & (sizeof(*arg
)-1)))
1093 return POPT_ERROR_NULLARG
;
1095 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
1096 #if defined(HAVE_SRANDOM)
1098 srandom((unsigned)getpid());
1099 srandom((unsigned)random());
1101 aLong
= random() % (aLong
> 0 ? aLong
: -aLong
);
1104 /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
1105 return POPT_ERROR_BADOPERATION
;
1110 switch (LF_ISSET(LOGICALOPS
)) {
1111 case 0: *arg
= (short) aLong
;
1113 case POPT_ARGFLAG_OR
: *(unsigned short *)arg
|= (unsigned short) aLong
;
1115 case POPT_ARGFLAG_AND
: *(unsigned short *)arg
&= (unsigned short) aLong
;
1117 case POPT_ARGFLAG_XOR
: *(unsigned short *)arg
^= (unsigned short) aLong
;
1119 default: return POPT_ERROR_BADOPERATION
;
1120 /*@notreached@*/ break;
1126 * Return argInfo field, handling POPT_ARGFLAG_TOGGLE overrides.
1127 * @param con context
1131 static unsigned int poptArgInfo(poptContext con
, const struct poptOption
* opt
)
1134 unsigned int argInfo
= opt
->argInfo
;
1136 if (con
->os
->argv
!= NULL
&& con
->os
->next
> 0 && opt
->longName
!= NULL
)
1137 if (LF_ISSET(TOGGLE
)) {
1138 const char * longName
= con
->os
->argv
[con
->os
->next
-1];
1139 while (*longName
== '-') longName
++;
1140 /* XXX almost good enough but consider --[no]nofoo corner cases. */
1141 if (longName
[0] != opt
->longName
[0] || longName
[1] != opt
->longName
[1])
1143 if (!LF_ISSET(XOR
)) { /* XXX dont toggle with XOR */
1144 /* Toggle POPT_BIT_SET <=> POPT_BIT_CLR. */
1145 if (LF_ISSET(LOGICALOPS
))
1146 argInfo
^= (POPT_ARGFLAG_OR
|POPT_ARGFLAG_AND
);
1147 argInfo
^= POPT_ARGFLAG_NOT
;
1155 * Parse an integer expression.
1156 * @retval *llp integer expression value
1157 * @param argInfo integer expression type
1158 * @param val integer expression string
1159 * @return 0 on success, otherwise POPT_* error.
1161 static int poptParseInteger(long long * llp
,
1162 /*@unused@*/ UNUSED(unsigned int argInfo
),
1163 /*@null@*/ const char * val
)
1164 /*@modifies *llp @*/
1168 *llp
= strtoll(val
, &end
, 0);
1170 /* XXX parse scaling suffixes here. */
1172 if (!(end
&& *end
== '\0'))
1173 return POPT_ERROR_BADNUMBER
;
1180 * Save the option argument through the (*opt->arg) pointer.
1181 * @param con context
1183 * @return 0 on success, otherwise POPT_* error.
1185 static int poptSaveArg(poptContext con
, const struct poptOption
* opt
)
1186 /*@globals fileSystem, internalState @*/
1187 /*@modifies con, fileSystem, internalState @*/
1189 poptArg arg
= { .ptr
= opt
->arg
};
1190 int rc
= 0; /* assume success */
1192 switch (poptArgType(opt
)) {
1193 case POPT_ARG_BITSET
:
1194 /* XXX memory leak, application is responsible for free. */
1195 rc
= poptSaveBits(arg
.ptr
, opt
->argInfo
, con
->os
->nextArg
);
1196 /*@switchbreak@*/ break;
1198 /* XXX memory leak, application is responsible for free. */
1199 rc
= poptSaveString(arg
.ptr
, opt
->argInfo
, con
->os
->nextArg
);
1200 /*@switchbreak@*/ break;
1201 case POPT_ARG_STRING
:
1202 /* XXX memory leak, application is responsible for free. */
1203 arg
.argv
[0] = (con
->os
->nextArg
) ? xstrdup(con
->os
->nextArg
) : NULL
;
1204 /*@switchbreak@*/ break;
1207 case POPT_ARG_SHORT
:
1209 case POPT_ARG_LONGLONG
:
1210 { unsigned int argInfo
= poptArgInfo(con
, opt
);
1213 if ((rc
= poptParseInteger(&aNUM
, argInfo
, con
->os
->nextArg
)) != 0)
1216 switch (poptArgType(opt
)) {
1217 case POPT_ARG_LONGLONG
:
1218 /* XXX let's not demand C99 compiler flags for <limits.h> quite yet. */
1219 #if !defined(LLONG_MAX)
1220 # define LLONG_MAX 9223372036854775807LL
1221 # define LLONG_MIN (-LLONG_MAX - 1LL)
1223 rc
= !(aNUM
== LLONG_MIN
|| aNUM
== LLONG_MAX
)
1224 ? poptSaveLongLong(arg
.longlongp
, argInfo
, aNUM
)
1225 : POPT_ERROR_OVERFLOW
;
1226 /*@innerbreak@*/ break;
1228 rc
= !(aNUM
< (long long)LONG_MIN
|| aNUM
> (long long)LONG_MAX
)
1229 ? poptSaveLong(arg
.longp
, argInfo
, (long)aNUM
)
1230 : POPT_ERROR_OVERFLOW
;
1231 /*@innerbreak@*/ break;
1233 rc
= !(aNUM
< (long long)INT_MIN
|| aNUM
> (long long)INT_MAX
)
1234 ? poptSaveInt(arg
.intp
, argInfo
, (long)aNUM
)
1235 : POPT_ERROR_OVERFLOW
;
1236 /*@innerbreak@*/ break;
1237 case POPT_ARG_SHORT
:
1238 rc
= !(aNUM
< (long long)SHRT_MIN
|| aNUM
> (long long)SHRT_MAX
)
1239 ? poptSaveShort(arg
.shortp
, argInfo
, (long)aNUM
)
1240 : POPT_ERROR_OVERFLOW
;
1241 /*@innerbreak@*/ break;
1243 } /*@switchbreak@*/ break;
1245 case POPT_ARG_FLOAT
:
1246 case POPT_ARG_DOUBLE
:
1248 double aDouble
= 0.0;
1250 if (con
->os
->nextArg
) {
1252 int saveerrno
= errno
;
1254 aDouble
= strtod(con
->os
->nextArg
, &end
);
1255 if (errno
== ERANGE
) {
1256 rc
= POPT_ERROR_OVERFLOW
;
1262 rc
= POPT_ERROR_BADNUMBER
;
1267 switch (poptArgType(opt
)) {
1268 case POPT_ARG_DOUBLE
:
1269 arg
.doublep
[0] = aDouble
;
1270 /*@innerbreak@*/ break;
1271 case POPT_ARG_FLOAT
:
1272 #if !defined(DBL_EPSILON) && !defined(__LCLINT__)
1273 #define DBL_EPSILON 2.2204460492503131e-16
1275 #define POPT_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
1276 if ((FLT_MIN
- POPT_ABS(aDouble
)) > DBL_EPSILON
1277 || (POPT_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
1278 rc
= POPT_ERROR_OVERFLOW
;
1280 arg
.floatp
[0] = (float) aDouble
;
1281 /*@innerbreak@*/ break;
1283 } /*@switchbreak@*/ break;
1284 case POPT_ARG_MAINCALL
:
1285 /*@-assignexpose -type@*/
1286 con
->maincall
= opt
->arg
;
1287 /*@=assignexpose =type@*/
1288 /*@switchbreak@*/ break;
1290 fprintf(stdout
, POPT_("option type (%u) not implemented in popt\n"),
1293 /*@notreached@*/ /*@switchbreak@*/ break;
1298 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
1299 int poptGetNextOpt(poptContext con
)
1301 const struct poptOption
* opt
= NULL
;
1307 const char * origOptString
= NULL
;
1308 poptCallbackType cb
= NULL
;
1309 const void * cbData
= NULL
;
1310 const char * longArg
= NULL
;
1314 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
1315 && con
->os
> con
->optionStack
) {
1316 cleanOSE(con
->os
--);
1318 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
1319 invokeCallbacksPOST(con
, con
->options
);
1321 if (con
->maincall
) {
1322 /*@-noeffectuncon @*/
1323 (void) (*con
->maincall
) (con
->finalArgvCount
, con
->finalArgv
);
1324 /*@=noeffectuncon @*/
1328 if (con
->doExec
) return execCommand(con
);
1332 /* Process next long option */
1333 if (!con
->os
->nextCharArg
) {
1334 const char * optString
;
1335 size_t optStringLen
;
1339 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
1344 thisopt
= con
->os
->next
;
1345 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
1346 origOptString
= con
->os
->argv
[con
->os
->next
++];
1348 if (origOptString
== NULL
) /* XXX can't happen */
1349 return POPT_ERROR_BADOPT
;
1351 if (con
->restLeftover
|| *origOptString
!= '-' ||
1352 (*origOptString
== '-' && origOptString
[1] == '\0'))
1354 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
1355 con
->restLeftover
= 1;
1356 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
1357 con
->os
->nextArg
= xstrdup(origOptString
);
1360 if (con
->leftovers
!= NULL
) /* XXX can't happen */
1361 con
->leftovers
[con
->numLeftovers
++] = origOptString
;
1365 /* Make a copy we can hack at */
1366 optString
= origOptString
;
1368 if (optString
[0] == '\0')
1369 return POPT_ERROR_BADOPT
;
1371 if (optString
[1] == '-' && !optString
[2]) {
1372 con
->restLeftover
= 1;
1376 unsigned int argInfo
= 0;
1379 if (*optString
== '-')
1382 argInfo
|= POPT_ARGFLAG_ONEDASH
;
1384 /* Check for "--long=arg" option. */
1385 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
1387 optStringLen
= (size_t)(oe
- optString
);
1391 /* XXX aliases with arg substitution need "--alias=arg" */
1392 if (handleAlias(con
, optString
, optStringLen
, '\0', longArg
)) {
1397 if (handleExec(con
, optString
, '\0'))
1400 opt
= findOption(con
->options
, optString
, optStringLen
, '\0', &cb
, &cbData
,
1402 if (!opt
&& !LF_ISSET(ONEDASH
))
1403 return POPT_ERROR_BADOPT
;
1407 con
->os
->nextCharArg
= origOptString
+ 1;
1410 if (con
->os
== con
->optionStack
&& F_ISSET(opt
, STRIP
))
1413 poptStripArg(con
, thisopt
);
1419 /* Process next short option */
1420 if (con
->os
->nextCharArg
) {
1421 const char * nextCharArg
= con
->os
->nextCharArg
;
1423 con
->os
->nextCharArg
= NULL
;
1425 if (handleAlias(con
, NULL
, 0, *nextCharArg
, nextCharArg
+ 1))
1428 if (handleExec(con
, NULL
, *nextCharArg
)) {
1429 /* Restore rest of short options for further processing */
1431 if (*nextCharArg
!= '\0')
1432 con
->os
->nextCharArg
= nextCharArg
;
1436 opt
= findOption(con
->options
, NULL
, 0, *nextCharArg
, &cb
,
1439 return POPT_ERROR_BADOPT
;
1443 if (*nextCharArg
!= '\0')
1444 con
->os
->nextCharArg
= nextCharArg
+ (int)(*nextCharArg
== '=');
1447 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
1448 if (opt
->arg
&& poptArgType(opt
) == POPT_ARG_NONE
) {
1449 unsigned int argInfo
= poptArgInfo(con
, opt
);
1450 if (poptSaveInt((int *)opt
->arg
, argInfo
, 1L))
1451 return POPT_ERROR_BADOPERATION
;
1452 } else if (poptArgType(opt
) == POPT_ARG_VAL
) {
1454 unsigned int argInfo
= poptArgInfo(con
, opt
);
1455 if (poptSaveInt((int *)opt
->arg
, argInfo
, (long)opt
->val
))
1456 return POPT_ERROR_BADOPERATION
;
1458 } else if (poptArgType(opt
) != POPT_ARG_NONE
) {
1461 con
->os
->nextArg
= _free(con
->os
->nextArg
);
1463 longArg
= expandNextArg(con
, longArg
);
1464 con
->os
->nextArg
= (char *) longArg
;
1465 } else if (con
->os
->nextCharArg
) {
1466 longArg
= expandNextArg(con
, con
->os
->nextCharArg
);
1467 con
->os
->nextArg
= (char *) longArg
;
1468 con
->os
->nextCharArg
= NULL
;
1470 while (con
->os
->next
== con
->os
->argc
&&
1471 con
->os
> con
->optionStack
)
1473 cleanOSE(con
->os
--);
1475 if (con
->os
->next
== con
->os
->argc
) {
1476 if (!F_ISSET(opt
, OPTIONAL
))
1477 return POPT_ERROR_NOARG
;
1478 con
->os
->nextArg
= NULL
;
1482 * Make sure this isn't part of a short arg or the
1483 * result of an alias expansion.
1485 if (con
->os
== con
->optionStack
1486 && F_ISSET(opt
, STRIP
) && canstrip
)
1488 poptStripArg(con
, con
->os
->next
);
1491 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
1492 if (F_ISSET(opt
, OPTIONAL
) &&
1493 con
->os
->argv
[con
->os
->next
][0] == '-') {
1494 con
->os
->nextArg
= NULL
;
1496 /* XXX watchout: subtle side-effects live here. */
1497 longArg
= con
->os
->argv
[con
->os
->next
++];
1498 longArg
= expandNextArg(con
, longArg
);
1499 con
->os
->nextArg
= (char *) longArg
;
1506 /* Save the option argument through a (*opt->arg) pointer. */
1507 if (opt
->arg
!= NULL
&& (rc
= poptSaveArg(con
, opt
)) != 0)
1512 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
1513 else if (opt
->val
&& (poptArgType(opt
) != POPT_ARG_VAL
))
1516 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
1517 con
->finalArgvAlloced
+= 10;
1518 con
->finalArgv
= realloc(con
->finalArgv
,
1519 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
1522 if (con
->finalArgv
!= NULL
)
1523 { char *s
= malloc((opt
->longName
? strlen(opt
->longName
) : 0) + sizeof("--"));
1524 if (s
!= NULL
) { /* XXX can't happen */
1525 con
->finalArgv
[con
->finalArgvCount
++] = s
;
1527 if (opt
->longName
) {
1528 if (!F_ISSET(opt
, ONEDASH
))
1530 s
= stpcpy(s
, opt
->longName
);
1532 *s
++ = opt
->shortName
;
1536 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
1539 if (opt
->arg
&& poptArgType(opt
) == POPT_ARG_NONE
)
1540 /*@-ifempty@*/ ; /*@=ifempty@*/
1541 else if (poptArgType(opt
) == POPT_ARG_VAL
)
1542 /*@-ifempty@*/ ; /*@=ifempty@*/
1543 else if (poptArgType(opt
) != POPT_ARG_NONE
) {
1544 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
!= NULL
)
1545 con
->finalArgv
[con
->finalArgvCount
++] =
1546 xstrdup(con
->os
->nextArg
);
1550 return (opt
? opt
->val
: -1); /* XXX can't happen */
1553 char * poptGetOptArg(poptContext con
)
1557 ret
= con
->os
->nextArg
;
1558 con
->os
->nextArg
= NULL
;
1563 const char * poptGetArg(poptContext con
)
1565 const char * ret
= NULL
;
1566 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1567 ret
= con
->leftovers
[con
->nextLeftover
++];
1571 const char * poptPeekArg(poptContext con
)
1573 const char * ret
= NULL
;
1574 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1575 ret
= con
->leftovers
[con
->nextLeftover
];
1579 const char ** poptGetArgs(poptContext con
)
1582 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1585 /* some apps like [like RPM ;-) ] need this NULL terminated */
1586 con
->leftovers
[con
->numLeftovers
] = NULL
;
1588 /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
1589 return (con
->leftovers
+ con
->nextLeftover
);
1590 /*@=nullret =nullstate @*/
1594 poptItem
poptFreeItems(/*@only@*/ /*@null@*/ poptItem items
, int nitems
)
1595 /*@modifies items @*/
1597 if (items
!= NULL
) {
1598 poptItem item
= items
;
1599 while (--nitems
>= 0) {
1600 /*@-modobserver -observertrans -dependenttrans@*/
1601 item
->option
.longName
= _free(item
->option
.longName
);
1602 item
->option
.descrip
= _free(item
->option
.descrip
);
1603 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1604 /*@=modobserver =observertrans =dependenttrans@*/
1605 item
->argv
= _free(item
->argv
);
1608 items
= _free(items
);
1613 poptContext
poptFreeContext(poptContext con
)
1615 if (con
== NULL
) return con
;
1616 poptResetContext(con
);
1617 con
->os
->argb
= _free(con
->os
->argb
);
1619 con
->aliases
= poptFreeItems(con
->aliases
, con
->numAliases
);
1620 con
->numAliases
= 0;
1622 con
->execs
= poptFreeItems(con
->execs
, con
->numExecs
);
1625 con
->leftovers
= _free(con
->leftovers
);
1626 con
->finalArgv
= _free(con
->finalArgv
);
1627 con
->appName
= _free(con
->appName
);
1628 con
->otherHelp
= _free(con
->otherHelp
);
1629 con
->execPath
= _free(con
->execPath
);
1630 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
1636 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1637 /*@unused@*/ UNUSED(int flags
))
1639 struct poptItem_s item_buf
;
1640 poptItem item
= &item_buf
;
1641 memset(item
, 0, sizeof(*item
));
1642 item
->option
.longName
= alias
.longName
;
1643 item
->option
.shortName
= alias
.shortName
;
1644 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1645 item
->option
.arg
= 0;
1646 item
->option
.val
= 0;
1647 item
->option
.descrip
= NULL
;
1648 item
->option
.argDescrip
= NULL
;
1649 item
->argc
= alias
.argc
;
1650 item
->argv
= alias
.argv
;
1651 return poptAddItem(con
, item
, 0);
1654 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1656 poptItem
* items
, item
;
1661 items
= &con
->execs
;
1662 nitems
= &con
->numExecs
;
1665 items
= &con
->aliases
;
1666 nitems
= &con
->numAliases
;
1670 /*@notreached@*/ break;
1673 *items
= realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1674 if ((*items
) == NULL
)
1677 item
= (*items
) + (*nitems
);
1679 item
->option
.longName
=
1680 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1681 item
->option
.shortName
= newItem
->option
.shortName
;
1682 item
->option
.argInfo
= newItem
->option
.argInfo
;
1683 item
->option
.arg
= newItem
->option
.arg
;
1684 item
->option
.val
= newItem
->option
.val
;
1685 item
->option
.descrip
=
1686 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1687 item
->option
.argDescrip
=
1688 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1689 item
->argc
= newItem
->argc
;
1690 item
->argv
= newItem
->argv
;
1697 const char * poptBadOption(poptContext con
, unsigned int flags
)
1699 struct optionStackEntry
* os
= NULL
;
1702 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1704 return (os
!= NULL
&& os
->argv
!= NULL
? os
->argv
[os
->next
- 1] : NULL
);
1707 const char * poptStrerror(const int error
)
1710 case POPT_ERROR_NOARG
:
1711 return POPT_("missing argument");
1712 case POPT_ERROR_BADOPT
:
1713 return POPT_("unknown option");
1714 case POPT_ERROR_BADOPERATION
:
1715 return POPT_("mutually exclusive logical operations requested");
1716 case POPT_ERROR_NULLARG
:
1717 return POPT_("opt->arg should not be NULL");
1718 case POPT_ERROR_OPTSTOODEEP
:
1719 return POPT_("aliases nested too deeply");
1720 case POPT_ERROR_BADQUOTE
:
1721 return POPT_("error in parameter quoting");
1722 case POPT_ERROR_BADNUMBER
:
1723 return POPT_("invalid numeric value");
1724 case POPT_ERROR_OVERFLOW
:
1725 return POPT_("number too large or too small");
1726 case POPT_ERROR_MALLOC
:
1727 return POPT_("memory allocation failed");
1728 case POPT_ERROR_BADCONFIG
:
1729 return POPT_("config file failed sanity test");
1730 case POPT_ERROR_ERRNO
:
1731 return strerror(errno
);
1733 return POPT_("unknown error");
1737 int poptStuffArgs(poptContext con
, const char ** argv
)
1742 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1743 return POPT_ERROR_OPTSTOODEEP
;
1745 for (argc
= 0; argv
[argc
]; argc
++)
1750 con
->os
->nextArg
= NULL
;
1751 con
->os
->nextCharArg
= NULL
;
1752 con
->os
->currAlias
= NULL
;
1753 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1754 con
->os
->argb
= NULL
;
1755 con
->os
->stuffed
= 1;
1760 const char * poptGetInvocationName(poptContext con
)
1762 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1765 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1773 for (i
= 1; i
< argc
; i
++) {
1774 if (PBM_ISSET(i
, con
->arg_strip
))
1778 for (i
= 1; i
< argc
; i
++) {
1779 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1781 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;