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 */
21 #ifdef HAVE_STDALIGN_H
23 #define ALIGNOF(x) alignof(x)
24 #elif defined __GNUC__
25 #define ALIGNOF(x) __alignof__(x)
27 #define ALIGNOF(x) sizeof(x)
34 unsigned int _poptArgMask
= POPT_ARG_MASK
;
35 unsigned int _poptGroupMask
= POPT_GROUP_MASK
;
37 #if !defined(HAVE_STRERROR)
38 static char * strerror(int errno
)
41 extern char * sys_errlist
[];
43 if ((0 <= errno
) && (errno
< sys_nerr
))
44 return sys_errlist
[errno
];
46 return POPT_("unknown errno");
51 static void prtcon(const char *msg
, poptContext con
)
53 if (msg
) fprintf(stderr
, "%s", msg
);
54 fprintf(stderr
, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
56 (con
->os
->nextCharArg
? con
->os
->nextCharArg
: ""),
57 (con
->os
->nextArg
? con
->os
->nextArg
: ""),
59 (con
->os
->argv
&& con
->os
->argv
[con
->os
->next
]
60 ? con
->os
->argv
[con
->os
->next
] : ""));
64 void poptSetExecPath(poptContext con
, const char * path
, int allowAbsolute
)
66 con
->execPath
= _free(con
->execPath
);
67 con
->execPath
= xstrdup(path
);
68 con
->execAbsolute
= allowAbsolute
;
72 static void invokeCallbacksPRE(poptContext con
, const struct poptOption
* opt
)
75 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
76 poptArg arg
= { .ptr
= opt
->arg
};
78 switch (poptArgType(opt
)) {
79 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
80 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
81 invokeCallbacksPRE(con
, arg
.opt
);
83 case POPT_ARG_CALLBACK
: /* Perform callback. */
84 if (!CBF_ISSET(opt
, PRE
))
86 arg
.cb(con
, POPT_CALLBACK_REASON_PRE
, NULL
, NULL
, opt
->descrip
);
92 static void invokeCallbacksPOST(poptContext con
, const struct poptOption
* opt
)
95 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
96 poptArg arg
= { .ptr
= opt
->arg
};
98 switch (poptArgType(opt
)) {
99 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
100 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
101 invokeCallbacksPOST(con
, arg
.opt
);
103 case POPT_ARG_CALLBACK
: /* Perform callback. */
104 if (!CBF_ISSET(opt
, POST
))
106 arg
.cb(con
, POPT_CALLBACK_REASON_POST
, NULL
, NULL
, opt
->descrip
);
112 static void invokeCallbacksOPTION(poptContext con
,
113 const struct poptOption
* opt
,
114 const struct poptOption
* myOpt
,
115 const void * myData
, int shorty
)
117 const struct poptOption
* cbopt
= NULL
;
118 poptArg cbarg
= { .ptr
= NULL
};
121 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
122 poptArg arg
= { .ptr
= opt
->arg
};
123 switch (poptArgType(opt
)) {
124 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
125 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
126 if (opt
->arg
!= NULL
)
127 invokeCallbacksOPTION(con
, opt
->arg
, myOpt
, myData
, shorty
);
129 case POPT_ARG_CALLBACK
: /* Save callback info. */
130 if (CBF_ISSET(opt
, SKIPOPTION
))
133 cbarg
.ptr
= opt
->arg
;
135 default: /* Perform callback on matching option. */
136 if (cbopt
== NULL
|| cbarg
.cb
== NULL
)
138 if ((myOpt
->shortName
&& opt
->shortName
&& shorty
&&
139 myOpt
->shortName
== opt
->shortName
)
140 || (myOpt
->longName
!= NULL
&& opt
->longName
!= NULL
&&
141 !strcmp(myOpt
->longName
, opt
->longName
)))
142 { const void *cbData
= (cbopt
->descrip
? cbopt
->descrip
: myData
);
143 cbarg
.cb(con
, POPT_CALLBACK_REASON_OPTION
,
144 myOpt
, con
->os
->nextArg
, cbData
);
145 /* Terminate (unless explcitly continuing). */
146 if (!CBF_ISSET(cbopt
, CONTINUE
))
154 poptContext
poptGetContext(const char * name
, int argc
, const char ** argv
,
155 const struct poptOption
* options
, unsigned int flags
)
157 poptContext con
= 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 con
->os
->argv
= argv
;
165 con
->os
->argb
= NULL
;
167 if (!(flags
& POPT_CONTEXT_KEEP_FIRST
))
168 con
->os
->next
= 1; /* skip argv[0] */
170 con
->leftovers
= calloc( (size_t)(argc
+ 1), sizeof(*con
->leftovers
) );
171 con
->allocLeftovers
= argc
+ 1;
172 con
->options
= options
;
178 con
->execFail
= NULL
;
179 con
->finalArgvAlloced
= argc
* 2;
180 con
->finalArgv
= calloc( (size_t)con
->finalArgvAlloced
, sizeof(*con
->finalArgv
) );
181 con
->execAbsolute
= 1;
182 con
->arg_strip
= NULL
;
184 if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
185 con
->flags
|= POPT_CONTEXT_POSIXMEHARDER
;
188 con
->appName
= xstrdup(name
);
190 invokeCallbacksPRE(con
, con
->options
);
195 static void cleanOSE(struct optionStackEntry
*os
)
197 os
->nextArg
= _free(os
->nextArg
);
198 os
->argv
= _free(os
->argv
);
199 os
->argb
= PBM_FREE(os
->argb
);
202 void poptResetContext(poptContext con
)
206 if (con
== NULL
) return;
207 while (con
->os
> con
->optionStack
) {
210 con
->os
->argb
= PBM_FREE(con
->os
->argb
);
211 con
->os
->currAlias
= NULL
;
212 con
->os
->nextCharArg
= NULL
;
213 con
->os
->nextArg
= _free(con
->os
->nextArg
);
214 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
))
215 con
->os
->next
= 1; /* skip argv[0] */
219 for (i
= 0; i
< con
->numLeftovers
; i
++) {
220 con
->leftovers
[i
] = _free(con
->leftovers
[i
]);
222 con
->numLeftovers
= 0;
223 con
->nextLeftover
= 0;
224 con
->restLeftover
= 0;
226 con
->execFail
= _free(con
->execFail
);
228 if (con
->finalArgv
!= NULL
)
229 for (i
= 0; i
< con
->finalArgvCount
; i
++) {
230 con
->finalArgv
[i
] = _free(con
->finalArgv
[i
]);
233 con
->finalArgvCount
= 0;
234 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
238 /* Only one of longName, shortName should be set, not both. */
239 static int handleExec(poptContext con
,
240 const char * longName
, char shortName
)
245 if (con
->execs
== NULL
|| con
->numExecs
<= 0) /* XXX can't happen */
248 for (i
= con
->numExecs
- 1; i
>= 0; i
--) {
249 item
= con
->execs
+ i
;
250 if (longName
&& !(item
->option
.longName
&&
251 !strcmp(longName
, item
->option
.longName
)))
253 else if (shortName
!= item
->option
.shortName
)
260 if (con
->flags
& POPT_CONTEXT_NO_EXEC
)
263 if (con
->doExec
== NULL
) {
264 con
->doExec
= con
->execs
+ i
;
268 /* We already have an exec to do; remember this option for next
270 if ((con
->finalArgvCount
+ 1) >= (con
->finalArgvAlloced
)) {
271 con
->finalArgvAlloced
+= 10;
272 con
->finalArgv
= realloc(con
->finalArgv
,
273 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
276 i
= con
->finalArgvCount
++;
277 if (con
->finalArgv
!= NULL
) /* XXX can't happen */
278 { char *s
= malloc((longName
? strlen(longName
) : 0) + sizeof("--"));
279 if (s
!= NULL
) { /* XXX can't happen */
280 con
->finalArgv
[i
] = s
;
283 s
= stpcpy( stpcpy(s
, "-"), longName
);
288 con
->finalArgv
[i
] = NULL
;
295 * Compare long option for equality, adjusting for POPT_ARGFLAG_TOGGLE.
297 * @param longName arg option
298 * @param longNameLen arg option length
299 * @return does long option match?
302 longOptionStrcmp(const struct poptOption
* opt
,
303 const char * longName
, size_t longNameLen
)
305 const char * optLongName
= opt
->longName
;
308 if (optLongName
== NULL
|| longName
== NULL
) /* XXX can't heppen */
311 if (F_ISSET(opt
, TOGGLE
)) {
312 if (optLongName
[0] == 'n' && optLongName
[1] == 'o') {
313 optLongName
+= sizeof("no") - 1;
314 if (optLongName
[0] == '-')
317 if (longName
[0] == 'n' && longName
[1] == 'o') {
318 longName
+= sizeof("no") - 1;
319 longNameLen
-= sizeof("no") - 1;
320 if (longName
[0] == '-') {
326 rc
= (int)(strlen(optLongName
) == longNameLen
);
328 rc
= (int)(strncmp(optLongName
, longName
, longNameLen
) == 0);
332 /* Only one of longName, shortName may be set at a time */
333 static int handleAlias(poptContext con
,
334 const char * longName
, size_t longNameLen
,
336 const char * nextArg
)
338 poptItem item
= con
->os
->currAlias
;
343 if (longName
&& item
->option
.longName
!= NULL
344 && longOptionStrcmp(&item
->option
, longName
, longNameLen
))
347 if (shortName
&& shortName
== item
->option
.shortName
)
351 if (con
->aliases
== NULL
|| con
->numAliases
<= 0) /* XXX can't happen */
354 for (i
= con
->numAliases
- 1; i
>= 0; i
--) {
355 item
= con
->aliases
+ i
;
357 if (item
->option
.longName
== NULL
)
359 if (!longOptionStrcmp(&item
->option
, longName
, longNameLen
))
361 } else if (shortName
!= item
->option
.shortName
)
367 if ((con
->os
- con
->optionStack
+ 1) == POPT_OPTION_DEPTH
)
368 return POPT_ERROR_OPTSTOODEEP
;
370 if (longName
== NULL
&& nextArg
!= NULL
&& *nextArg
!= '\0')
371 con
->os
->nextCharArg
= nextArg
;
375 con
->os
->stuffed
= 0;
376 con
->os
->nextArg
= NULL
;
377 con
->os
->nextCharArg
= NULL
;
378 con
->os
->currAlias
= con
->aliases
+ i
;
380 int ac
= con
->os
->currAlias
->argc
;
381 /* Append --foo=bar arg to alias argv array (if present). */
382 if (longName
&& nextArg
!= NULL
&& *nextArg
!= '\0') {
383 av
= malloc((ac
+ 1 + 1) * sizeof(*av
));
384 if (av
!= NULL
) { /* XXX won't happen. */
385 for (i
= 0; i
< ac
; i
++) {
386 av
[i
] = con
->os
->currAlias
->argv
[i
];
390 } else /* XXX revert to old popt behavior if malloc fails. */
391 av
= con
->os
->currAlias
->argv
;
393 av
= con
->os
->currAlias
->argv
;
394 rc
= poptDupArgv(ac
, av
, &con
->os
->argc
, &con
->os
->argv
);
395 if (av
!= NULL
&& av
!= con
->os
->currAlias
->argv
)
398 con
->os
->argb
= NULL
;
400 return (rc
? rc
: 1);
404 * Return absolute path to executable by searching PATH.
405 * @param argv0 name of executable
406 * @return (malloc'd) absolute path to executable (or NULL)
409 const char * findProgramPath(const char * argv0
)
411 char *path
= NULL
, *s
= NULL
, *se
;
414 if (argv0
== NULL
) return NULL
; /* XXX can't happen */
416 /* If there is a / in argv[0], it has to be an absolute path. */
417 /* XXX Hmmm, why not if (argv0[0] == '/') ... instead? */
418 if (strchr(argv0
, '/'))
419 return xstrdup(argv0
);
421 if ((path
= getenv("PATH")) == NULL
|| (path
= xstrdup(path
)) == NULL
)
424 /* The return buffer in t is big enough for any path. */
425 if ((t
= malloc(strlen(path
) + strlen(argv0
) + sizeof("/"))) != NULL
)
426 for (s
= path
; s
&& *s
; s
= se
) {
428 /* Snip PATH element into [s,se). */
429 if ((se
= strchr(s
, ':')))
432 /* Append argv0 to PATH element. */
433 (void) stpcpy(stpcpy(stpcpy(t
, s
), "/"), argv0
);
435 /* If file is executable, bingo! */
436 if (!access(t
, X_OK
))
440 /* If no executable was found in PATH, return NULL. */
441 if (!(s
&& *s
) && t
!= NULL
)
448 static int execCommand(poptContext con
)
450 poptItem item
= con
->doExec
;
451 poptArgv argv
= NULL
;
454 int ec
= POPT_ERROR_ERRNO
;
456 if (item
== NULL
) /*XXX can't happen*/
457 return POPT_ERROR_NOARG
;
459 if (item
->argv
== NULL
|| item
->argc
< 1 ||
460 (!con
->execAbsolute
&& strchr(item
->argv
[0], '/')))
461 return POPT_ERROR_NOARG
;
463 argv
= malloc(sizeof(*argv
) *
464 (6 + item
->argc
+ con
->numLeftovers
+ con
->finalArgvCount
));
465 if (argv
== NULL
) return POPT_ERROR_MALLOC
;
467 if (!strchr(item
->argv
[0], '/') && con
->execPath
!= NULL
) {
468 char *s
= malloc(strlen(con
->execPath
) + strlen(item
->argv
[0]) + sizeof("/"));
470 (void)stpcpy(stpcpy(stpcpy(s
, con
->execPath
), "/"), item
->argv
[0]);
474 argv
[argc
] = findProgramPath(item
->argv
[0]);
475 if (argv
[argc
++] == NULL
) {
476 ec
= POPT_ERROR_NOARG
;
480 if (item
->argc
> 1) {
481 memcpy(argv
+ argc
, item
->argv
+ 1, sizeof(*argv
) * (item
->argc
- 1));
482 argc
+= (item
->argc
- 1);
485 if (con
->finalArgv
!= NULL
&& con
->finalArgvCount
> 0) {
486 memcpy(argv
+ argc
, con
->finalArgv
,
487 sizeof(*argv
) * con
->finalArgvCount
);
488 argc
+= con
->finalArgvCount
;
491 if (con
->leftovers
!= NULL
&& con
->numLeftovers
> 0) {
492 memcpy(argv
+ argc
, con
->leftovers
, sizeof(*argv
) * con
->numLeftovers
);
493 argc
+= con
->numLeftovers
;
498 #if defined(hpux) || defined(__hpux)
499 rc
= setresgid(getgid(), getgid(),-1);
501 rc
= setresuid(getuid(), getuid(),-1);
505 * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
506 * XXX sez' Timur Bakeyev <mc@bat.ru>
507 * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
509 #if defined(HAVE_SETUID)
510 rc
= setgid(getgid());
512 rc
= setuid(getuid());
514 #elif defined (HAVE_SETREUID)
515 rc
= setregid(getgid(), getgid());
517 rc
= setreuid(getuid(), getuid());
520 /* refuse to exec if we cannot drop suid/sgid privileges */
521 if (getuid() != geteuid() || getgid() != getegid()) {
531 fprintf(stderr
, "==> execvp(%s) argv[%d]:", argv
[0], argc
);
532 for (avp
= argv
; *avp
; avp
++)
533 fprintf(stderr
, " '%s'", *avp
);
534 fprintf(stderr
, "\n");
538 rc
= execvp(argv
[0], (char *const *)argv
);
540 /* only reached on execvp() failure */
541 con
->execFail
= xstrdup(argv
[0]);
546 free((void *)argv
[0]);
552 static const struct poptOption
*
553 findOption(const struct poptOption
* opt
,
554 const char * longName
, size_t longNameLen
,
556 poptCallbackType
* callback
,
557 const void ** callbackData
,
558 unsigned int argInfo
)
560 const struct poptOption
* cb
= NULL
;
561 poptArg cbarg
= { .ptr
= NULL
};
563 /* This happens when a single - is given */
564 if (LF_ISSET(ONEDASH
) && !shortName
&& (longName
&& *longName
== '\0'))
567 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
568 poptArg arg
= { .ptr
= opt
->arg
};
570 switch (poptArgType(opt
)) {
571 case POPT_ARG_INCLUDE_TABLE
: /* Recurse on included sub-tables. */
572 { const struct poptOption
* opt2
;
574 poptSubstituteHelpI18N(arg
.opt
); /* XXX side effects */
575 if (arg
.ptr
== NULL
) continue; /* XXX program error */
576 opt2
= findOption(arg
.opt
, longName
, longNameLen
, shortName
, callback
,
577 callbackData
, argInfo
);
578 if (opt2
== NULL
) continue;
579 /* Sub-table data will be inheirited if no data yet. */
580 if (callback
&& *callback
581 && callbackData
&& *callbackData
== NULL
)
582 *callbackData
= opt
->descrip
;
585 case POPT_ARG_CALLBACK
:
587 cbarg
.ptr
= opt
->arg
;
594 if (longName
!= NULL
&& opt
->longName
!= NULL
&&
595 (!LF_ISSET(ONEDASH
) || F_ISSET(opt
, ONEDASH
)) &&
596 longOptionStrcmp(opt
, longName
, longNameLen
))
599 } else if (shortName
&& shortName
== opt
->shortName
) {
604 if (opt
->longName
== NULL
&& !opt
->shortName
)
608 *callback
= (cb
? cbarg
.cb
: NULL
);
610 *callbackData
= (cb
&& !CBF_ISSET(cb
, INC_DATA
) ? cb
->descrip
: NULL
);
615 static const char * findNextArg(poptContext con
,
616 unsigned argx
, int delete_arg
)
618 struct optionStackEntry
* os
= con
->os
;
624 while (os
->next
== os
->argc
&& os
> con
->optionStack
) os
--;
625 if (os
->next
== os
->argc
&& os
== con
->optionStack
) break;
626 if (os
->argv
!= NULL
)
627 for (i
= os
->next
; i
< os
->argc
; i
++) {
628 if (os
->argb
&& PBM_ISSET(i
, os
->argb
))
630 if (*os
->argv
[i
] == '-')
636 if (os
->argb
== NULL
) os
->argb
= PBM_ALLOC(os
->argc
);
637 if (os
->argb
!= NULL
) /* XXX can't happen */
638 PBM_SET(i
, os
->argb
);
642 if (os
> con
->optionStack
) os
--;
643 } while (arg
== NULL
);
648 expandNextArg(poptContext con
, const char * s
)
650 const char * a
= NULL
;
651 char *t
, *t_tmp
, *te
;
652 size_t tn
= strlen(s
) + 1;
656 if (t
== NULL
) return NULL
; /* XXX can't happen */
658 while ((c
= *s
++) != '\0') {
660 #if 0 /* XXX can't do this */
661 case '\\': /* escape */
666 if (!(s
[0] == '#' && s
[1] == ':' && s
[2] == '+'))
668 /* XXX Make sure that findNextArg deletes only next arg. */
670 if ((a
= findNextArg(con
, 1U, 1)) == NULL
)
673 s
+= sizeof("#:+") - 1;
676 { size_t pos
= (size_t) (te
- t
);
677 if ((t_tmp
= realloc(t
, tn
)) == NULL
) { /* XXX can't happen */
682 te
= stpcpy(t
+ pos
, a
);
692 /* If the new string is longer than needed, shorten. */
694 if ((te
= realloc(t
, (size_t)(te
- t
))) == NULL
)
701 static void poptStripArg(poptContext con
, int which
)
703 if (con
->arg_strip
== NULL
)
704 con
->arg_strip
= PBM_ALLOC(con
->optionStack
[0].argc
);
705 if (con
->arg_strip
!= NULL
) /* XXX can't happen */
706 PBM_SET(which
, con
->arg_strip
);
710 unsigned int _poptBitsN
= _POPT_BITS_N
;
711 unsigned int _poptBitsM
= _POPT_BITS_M
;
712 unsigned int _poptBitsK
= _POPT_BITS_K
;
714 static int _poptBitsNew(poptBits
*bitsp
)
717 return POPT_ERROR_NULLARG
;
719 /* XXX handle negated initialization. */
720 if (*bitsp
== NULL
) {
721 if (_poptBitsN
== 0) {
722 _poptBitsN
= _POPT_BITS_N
;
723 _poptBitsM
= _POPT_BITS_M
;
725 if (_poptBitsM
== 0U) _poptBitsM
= (3 * _poptBitsN
) / 2;
726 if (_poptBitsK
== 0U || _poptBitsK
> 32U) _poptBitsK
= _POPT_BITS_K
;
727 *bitsp
= PBM_ALLOC(_poptBitsM
-1);
732 int poptBitsAdd(poptBits bits
, const char * s
)
734 size_t ns
= (s
? strlen(s
) : 0);
738 if (bits
== NULL
|| ns
== 0)
739 return POPT_ERROR_NULLARG
;
741 poptJlu32lpair(s
, ns
, &h0
, &h1
);
743 for (ns
= 0; ns
< (size_t)_poptBitsK
; ns
++) {
744 uint32_t h
= h0
+ ns
* h1
;
745 uint32_t ix
= (h
% _poptBitsM
);
751 int poptBitsChk(poptBits bits
, const char * s
)
753 size_t ns
= (s
? strlen(s
) : 0);
758 if (bits
== NULL
|| ns
== 0)
759 return POPT_ERROR_NULLARG
;
761 poptJlu32lpair(s
, ns
, &h0
, &h1
);
763 for (ns
= 0; ns
< (size_t)_poptBitsK
; ns
++) {
764 uint32_t h
= h0
+ ns
* h1
;
765 uint32_t ix
= (h
% _poptBitsM
);
766 if (PBM_ISSET(ix
, bits
))
774 int poptBitsClr(poptBits bits
)
776 static size_t nbw
= (__PBM_NBITS
/8);
777 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
780 return POPT_ERROR_NULLARG
;
781 memset(bits
, 0, nw
* nbw
);
785 int poptBitsDel(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 poptBitsIntersect(poptBits
*ap
, const poptBits b
)
809 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
812 if (ap
== NULL
|| b
== NULL
|| _poptBitsNew(ap
))
813 return POPT_ERROR_NULLARG
;
814 abits
= __PBM_BITS(*ap
);
815 bbits
= __PBM_BITS(b
);
817 for (i
= 0; i
< nw
; i
++) {
818 abits
[i
] &= bbits
[i
];
824 int poptBitsUnion(poptBits
*ap
, const poptBits b
)
829 size_t nw
= (__PBM_IX(_poptBitsM
-1) + 1);
832 if (ap
== NULL
|| b
== NULL
|| _poptBitsNew(ap
))
833 return POPT_ERROR_NULLARG
;
834 abits
= __PBM_BITS(*ap
);
835 bbits
= __PBM_BITS(b
);
837 for (i
= 0; i
< nw
; i
++) {
838 abits
[i
] |= bbits
[i
];
844 int poptBitsArgs(poptContext con
, poptBits
*ap
)
849 if (con
== NULL
|| ap
== NULL
|| _poptBitsNew(ap
) ||
850 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
851 return POPT_ERROR_NULLARG
;
853 /* some apps like [like RPM ;-) ] need this NULL terminated */
854 con
->leftovers
[con
->numLeftovers
] = NULL
;
856 for (av
= con
->leftovers
+ con
->nextLeftover
; *av
!= NULL
; av
++) {
857 if ((rc
= poptBitsAdd(*ap
, *av
)) != 0)
863 int poptSaveBits(poptBits
* bitsp
,
864 UNUSED(unsigned int argInfo
), const char * s
)
870 if (bitsp
== NULL
|| s
== NULL
|| *s
== '\0' || _poptBitsNew(bitsp
))
871 return POPT_ERROR_NULLARG
;
873 /* Parse comma separated attributes. */
874 te
= tbuf
= xstrdup(s
);
875 while ((t
= te
) != NULL
&& *t
) {
876 while (*te
!= '\0' && *te
!= ',')
880 /* XXX Ignore empty strings. */
883 /* XXX Permit negated attributes. caveat emptor: false negatives. */
886 if ((rc
= poptBitsChk(*bitsp
, t
)) > 0)
887 rc
= poptBitsDel(*bitsp
, t
);
889 rc
= poptBitsAdd(*bitsp
, t
);
897 int poptSaveString(const char *** argvp
,
898 UNUSED(unsigned int argInfo
), const char * val
)
902 if (argvp
== NULL
|| val
== NULL
)
903 return POPT_ERROR_NULLARG
;
905 /* XXX likely needs an upper bound on argc. */
907 while ((*argvp
)[argc
] != NULL
)
910 if ((*argvp
= xrealloc(*argvp
, (argc
+ 1 + 1) * sizeof(**argvp
))) != NULL
) {
911 (*argvp
)[argc
++] = xstrdup(val
);
912 (*argvp
)[argc
] = NULL
;
917 static long long poptRandomValue(long long limit
)
919 #if defined(HAVE_SRANDOM)
923 srandom((unsigned)getpid());
924 srandom((unsigned)random());
928 return random() % limit
+ 1;
930 /* XXX avoid adding POPT_ERROR_UNIMPLEMENTED to minimize i18n churn. */
931 return POPT_ERROR_BADOPERATION
;
935 int poptSaveLongLong(long long * arg
, unsigned int argInfo
, long long aLongLong
)
937 /* XXX Check alignment, may fail on funky platforms. */
938 if (arg
== NULL
|| (((unsigned long)arg
) & (ALIGNOF(*arg
)-1)))
939 return POPT_ERROR_NULLARG
;
941 if (aLongLong
!= 0 && LF_ISSET(RANDOM
)) {
942 aLongLong
= poptRandomValue(aLongLong
);
947 aLongLong
= ~aLongLong
;
948 switch (LF_ISSET(LOGICALOPS
)) {
952 case POPT_ARGFLAG_OR
:
953 *(unsigned long long *)arg
|= (unsigned long long)aLongLong
;
955 case POPT_ARGFLAG_AND
:
956 *(unsigned long long *)arg
&= (unsigned long long)aLongLong
;
958 case POPT_ARGFLAG_XOR
:
959 *(unsigned long long *)arg
^= (unsigned long long)aLongLong
;
962 return POPT_ERROR_BADOPERATION
;
968 int poptSaveLong(long * arg
, unsigned int argInfo
, long aLong
)
970 /* XXX Check alignment, may fail on funky platforms. */
971 if (arg
== NULL
|| (((unsigned long)arg
) & (ALIGNOF(*arg
)-1)))
972 return POPT_ERROR_NULLARG
;
974 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
975 aLong
= (long)poptRandomValue(aLong
);
981 switch (LF_ISSET(LOGICALOPS
)) {
982 case 0: *arg
= aLong
; break;
983 case POPT_ARGFLAG_OR
: *(unsigned long *)arg
|= (unsigned long)aLong
; break;
984 case POPT_ARGFLAG_AND
: *(unsigned long *)arg
&= (unsigned long)aLong
; break;
985 case POPT_ARGFLAG_XOR
: *(unsigned long *)arg
^= (unsigned long)aLong
; break;
987 return POPT_ERROR_BADOPERATION
;
993 int poptSaveInt(int * arg
, unsigned int argInfo
, long aLong
)
995 /* XXX Check alignment, may fail on funky platforms. */
996 if (arg
== NULL
|| (((unsigned long)arg
) & (ALIGNOF(*arg
)-1)))
997 return POPT_ERROR_NULLARG
;
999 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
1000 aLong
= (int)poptRandomValue(aLong
);
1006 switch (LF_ISSET(LOGICALOPS
)) {
1007 case 0: *arg
= (int) aLong
; break;
1008 case POPT_ARGFLAG_OR
: *(unsigned int *)arg
|= (unsigned int) aLong
; break;
1009 case POPT_ARGFLAG_AND
: *(unsigned int *)arg
&= (unsigned int) aLong
; break;
1010 case POPT_ARGFLAG_XOR
: *(unsigned int *)arg
^= (unsigned int) aLong
; break;
1012 return POPT_ERROR_BADOPERATION
;
1018 int poptSaveShort(short * arg
, unsigned int argInfo
, long aLong
)
1020 /* XXX Check alignment, may fail on funky platforms. */
1021 if (arg
== NULL
|| (((unsigned long)arg
) & (ALIGNOF(*arg
)-1)))
1022 return POPT_ERROR_NULLARG
;
1024 if (aLong
!= 0 && LF_ISSET(RANDOM
)) {
1025 aLong
= (short)poptRandomValue(aLong
);
1031 switch (LF_ISSET(LOGICALOPS
)) {
1032 case 0: *arg
= (short) aLong
;
1034 case POPT_ARGFLAG_OR
: *(unsigned short *)arg
|= (unsigned short) aLong
;
1036 case POPT_ARGFLAG_AND
: *(unsigned short *)arg
&= (unsigned short) aLong
;
1038 case POPT_ARGFLAG_XOR
: *(unsigned short *)arg
^= (unsigned short) aLong
;
1040 default: return POPT_ERROR_BADOPERATION
;
1047 * Return argInfo field, handling POPT_ARGFLAG_TOGGLE overrides.
1048 * @param con context
1052 static unsigned int poptArgInfo(poptContext con
, const struct poptOption
* opt
)
1054 unsigned int argInfo
= opt
->argInfo
;
1056 if (con
->os
->argv
!= NULL
&& con
->os
->next
> 0 && opt
->longName
!= NULL
)
1057 if (LF_ISSET(TOGGLE
)) {
1058 const char * longName
= con
->os
->argv
[con
->os
->next
-1];
1059 while (*longName
== '-') longName
++;
1060 /* XXX almost good enough but consider --[no]nofoo corner cases. */
1061 if (longName
[0] != opt
->longName
[0] || longName
[1] != opt
->longName
[1])
1063 if (!LF_ISSET(XOR
)) { /* XXX dont toggle with XOR */
1064 /* Toggle POPT_BIT_SET <=> POPT_BIT_CLR. */
1065 if (LF_ISSET(LOGICALOPS
))
1066 argInfo
^= (POPT_ARGFLAG_OR
|POPT_ARGFLAG_AND
);
1067 argInfo
^= POPT_ARGFLAG_NOT
;
1075 * Parse an integer expression.
1076 * @retval *llp integer expression value
1077 * @param argInfo integer expression type
1078 * @param val integer expression string
1079 * @return 0 on success, otherwise POPT_* error.
1081 static int poptParseInteger(long long * llp
,
1082 UNUSED(unsigned int argInfo
),
1087 *llp
= strtoll(val
, &end
, 0);
1089 /* XXX parse scaling suffixes here. */
1091 if (!(end
&& *end
== '\0'))
1092 return POPT_ERROR_BADNUMBER
;
1099 * Save the option argument through the (*opt->arg) pointer.
1100 * @param con context
1102 * @return 0 on success, otherwise POPT_* error.
1104 static int poptSaveArg(poptContext con
, const struct poptOption
* opt
)
1106 poptArg arg
= { .ptr
= opt
->arg
};
1107 int rc
= 0; /* assume success */
1109 switch (poptArgType(opt
)) {
1110 case POPT_ARG_BITSET
:
1111 /* XXX memory leak, application is responsible for free. */
1112 rc
= poptSaveBits(arg
.ptr
, opt
->argInfo
, con
->os
->nextArg
);
1115 /* XXX memory leak, application is responsible for free. */
1116 rc
= poptSaveString(arg
.ptr
, opt
->argInfo
, con
->os
->nextArg
);
1118 case POPT_ARG_STRING
:
1119 /* XXX memory leak, application is responsible for free. */
1120 arg
.argv
[0] = (con
->os
->nextArg
) ? xstrdup(con
->os
->nextArg
) : NULL
;
1124 case POPT_ARG_SHORT
:
1126 case POPT_ARG_LONGLONG
:
1127 { unsigned int argInfo
= poptArgInfo(con
, opt
);
1130 if ((rc
= poptParseInteger(&aNUM
, argInfo
, con
->os
->nextArg
)) != 0)
1133 switch (poptArgType(opt
)) {
1134 case POPT_ARG_LONGLONG
:
1135 /* XXX let's not demand C99 compiler flags for <limits.h> quite yet. */
1136 #if !defined(LLONG_MAX)
1137 # define LLONG_MAX 9223372036854775807LL
1138 # define LLONG_MIN (-LLONG_MAX - 1LL)
1140 rc
= !(aNUM
== LLONG_MIN
|| aNUM
== LLONG_MAX
)
1141 ? poptSaveLongLong(arg
.longlongp
, argInfo
, aNUM
)
1142 : POPT_ERROR_OVERFLOW
;
1145 rc
= !(aNUM
< (long long)LONG_MIN
|| aNUM
> (long long)LONG_MAX
)
1146 ? poptSaveLong(arg
.longp
, argInfo
, (long)aNUM
)
1147 : POPT_ERROR_OVERFLOW
;
1150 rc
= !(aNUM
< (long long)INT_MIN
|| aNUM
> (long long)INT_MAX
)
1151 ? poptSaveInt(arg
.intp
, argInfo
, (long)aNUM
)
1152 : POPT_ERROR_OVERFLOW
;
1154 case POPT_ARG_SHORT
:
1155 rc
= !(aNUM
< (long long)SHRT_MIN
|| aNUM
> (long long)SHRT_MAX
)
1156 ? poptSaveShort(arg
.shortp
, argInfo
, (long)aNUM
)
1157 : POPT_ERROR_OVERFLOW
;
1162 case POPT_ARG_FLOAT
:
1163 case POPT_ARG_DOUBLE
:
1165 double aDouble
= 0.0;
1167 if (con
->os
->nextArg
) {
1168 int saveerrno
= errno
;
1170 aDouble
= strtod(con
->os
->nextArg
, &end
);
1171 if (errno
== ERANGE
) {
1172 rc
= POPT_ERROR_OVERFLOW
;
1177 rc
= POPT_ERROR_BADNUMBER
;
1182 switch (poptArgType(opt
)) {
1183 case POPT_ARG_DOUBLE
:
1184 arg
.doublep
[0] = aDouble
;
1186 case POPT_ARG_FLOAT
:
1187 #define POPT_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
1188 if ((FLT_MIN
- POPT_ABS(aDouble
)) > DBL_EPSILON
1189 || (POPT_ABS(aDouble
) - FLT_MAX
) > DBL_EPSILON
)
1190 rc
= POPT_ERROR_OVERFLOW
;
1192 arg
.floatp
[0] = (float) aDouble
;
1196 case POPT_ARG_MAINCALL
:
1197 con
->maincall
= opt
->arg
;
1200 fprintf(stdout
, POPT_("option type (%u) not implemented in popt\n"),
1208 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
1209 int poptGetNextOpt(poptContext con
)
1211 const struct poptOption
* opt
= NULL
;
1217 const char * origOptString
= NULL
;
1218 poptCallbackType cb
= NULL
;
1219 const void * cbData
= NULL
;
1220 const char * longArg
= NULL
;
1224 while (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
1225 && con
->os
> con
->optionStack
) {
1226 cleanOSE(con
->os
--);
1228 if (!con
->os
->nextCharArg
&& con
->os
->next
== con
->os
->argc
) {
1229 invokeCallbacksPOST(con
, con
->options
);
1231 if (con
->maincall
) {
1232 (void) (*con
->maincall
) (con
->finalArgvCount
, con
->finalArgv
);
1236 if (con
->doExec
) return execCommand(con
);
1240 /* Process next long option */
1241 if (!con
->os
->nextCharArg
) {
1242 const char * optString
;
1243 size_t optStringLen
;
1246 if (con
->os
->argb
&& PBM_ISSET(con
->os
->next
, con
->os
->argb
)) {
1250 thisopt
= con
->os
->next
;
1251 if (con
->os
->argv
!= NULL
) /* XXX can't happen */
1252 origOptString
= con
->os
->argv
[con
->os
->next
++];
1254 if (origOptString
== NULL
) /* XXX can't happen */
1255 return POPT_ERROR_BADOPT
;
1257 if (con
->restLeftover
|| *origOptString
!= '-' ||
1258 (*origOptString
== '-' && origOptString
[1] == '\0'))
1260 if (con
->flags
& POPT_CONTEXT_POSIXMEHARDER
)
1261 con
->restLeftover
= 1;
1262 if (con
->flags
& POPT_CONTEXT_ARG_OPTS
) {
1263 con
->os
->nextArg
= xstrdup(origOptString
);
1266 if (con
->leftovers
!= NULL
) { /* XXX can't happen */
1267 /* One might think we can never overflow the leftovers
1268 array. Actually, that's true, as long as you don't
1269 use poptStuffArgs()... */
1270 if ((con
->numLeftovers
+ 1) >= (con
->allocLeftovers
)) {
1271 con
->allocLeftovers
+= 10;
1273 realloc(con
->leftovers
,
1274 sizeof(*con
->leftovers
) * con
->allocLeftovers
);
1276 con
->leftovers
[con
->numLeftovers
++]
1277 = xstrdup(origOptString
); /* so a free of a stuffed
1278 argv doesn't give us a
1284 /* Make a copy we can hack at */
1285 optString
= origOptString
;
1287 if (optString
[0] == '\0')
1288 return POPT_ERROR_BADOPT
;
1290 if (optString
[1] == '-' && !optString
[2]) {
1291 con
->restLeftover
= 1;
1295 unsigned int argInfo
= 0;
1298 if (*optString
== '-')
1301 argInfo
|= POPT_ARGFLAG_ONEDASH
;
1303 /* Check for "--long=arg" option. */
1304 for (oe
= optString
; *oe
&& *oe
!= '='; oe
++)
1306 optStringLen
= (size_t)(oe
- optString
);
1310 /* XXX aliases with arg substitution need "--alias=arg" */
1311 if (handleAlias(con
, optString
, optStringLen
, '\0', longArg
)) {
1316 if (handleExec(con
, optString
, '\0'))
1319 opt
= findOption(con
->options
, optString
, optStringLen
, '\0', &cb
, &cbData
,
1321 if (!opt
&& !LF_ISSET(ONEDASH
))
1322 return POPT_ERROR_BADOPT
;
1326 con
->os
->nextCharArg
= origOptString
+ 1;
1329 if (con
->os
== con
->optionStack
&& F_ISSET(opt
, STRIP
))
1332 poptStripArg(con
, thisopt
);
1338 /* Process next short option */
1339 if (con
->os
->nextCharArg
) {
1340 const char * nextCharArg
= con
->os
->nextCharArg
;
1342 con
->os
->nextCharArg
= NULL
;
1344 if (handleAlias(con
, NULL
, 0, *nextCharArg
, nextCharArg
+ 1))
1347 if (handleExec(con
, NULL
, *nextCharArg
)) {
1348 /* Restore rest of short options for further processing */
1350 if (*nextCharArg
!= '\0')
1351 con
->os
->nextCharArg
= nextCharArg
;
1355 opt
= findOption(con
->options
, NULL
, 0, *nextCharArg
, &cb
,
1358 return POPT_ERROR_BADOPT
;
1362 if (*nextCharArg
!= '\0')
1363 con
->os
->nextCharArg
= nextCharArg
;
1366 if (opt
== NULL
) return POPT_ERROR_BADOPT
; /* XXX can't happen */
1367 if (poptArgType(opt
) == POPT_ARG_NONE
|| poptArgType(opt
) == POPT_ARG_VAL
) {
1368 if (longArg
|| (con
->os
->nextCharArg
&& con
->os
->nextCharArg
[0] == '='))
1369 return POPT_ERROR_UNWANTEDARG
;
1371 long val
= poptArgType(opt
) == POPT_ARG_VAL
? opt
->val
: 1;
1372 unsigned int argInfo
= poptArgInfo(con
, opt
);
1373 if (poptSaveInt((int *)opt
->arg
, argInfo
, val
))
1374 return POPT_ERROR_BADOPERATION
;
1379 con
->os
->nextArg
= _free(con
->os
->nextArg
);
1381 longArg
= expandNextArg(con
, longArg
);
1382 con
->os
->nextArg
= (char *) longArg
;
1383 } else if (con
->os
->nextCharArg
) {
1384 longArg
= expandNextArg(con
, con
->os
->nextCharArg
+ (int)(*con
->os
->nextCharArg
== '='));
1385 con
->os
->nextArg
= (char *) longArg
;
1386 con
->os
->nextCharArg
= NULL
;
1388 while (con
->os
->next
== con
->os
->argc
&&
1389 con
->os
> con
->optionStack
)
1391 cleanOSE(con
->os
--);
1393 if (con
->os
->next
== con
->os
->argc
) {
1394 if (!F_ISSET(opt
, OPTIONAL
))
1395 return POPT_ERROR_NOARG
;
1396 con
->os
->nextArg
= NULL
;
1400 * Make sure this isn't part of a short arg or the
1401 * result of an alias expansion.
1403 if (con
->os
== con
->optionStack
1404 && F_ISSET(opt
, STRIP
) && canstrip
)
1406 poptStripArg(con
, con
->os
->next
);
1409 if (con
->os
->argv
!= NULL
) { /* XXX can't happen */
1410 if (F_ISSET(opt
, OPTIONAL
) &&
1411 con
->os
->argv
[con
->os
->next
][0] == '-') {
1412 con
->os
->nextArg
= NULL
;
1414 /* XXX watchout: subtle side-effects live here. */
1415 longArg
= con
->os
->argv
[con
->os
->next
++];
1416 longArg
= expandNextArg(con
, longArg
);
1417 con
->os
->nextArg
= (char *) longArg
;
1424 /* Save the option argument through a (*opt->arg) pointer. */
1425 if (opt
->arg
!= NULL
&& (rc
= poptSaveArg(con
, opt
)) != 0)
1430 invokeCallbacksOPTION(con
, con
->options
, opt
, cbData
, shorty
);
1431 else if (opt
->val
&& (poptArgType(opt
) != POPT_ARG_VAL
))
1434 if ((con
->finalArgvCount
+ 2) >= (con
->finalArgvAlloced
)) {
1435 con
->finalArgvAlloced
+= 10;
1436 con
->finalArgv
= realloc(con
->finalArgv
,
1437 sizeof(*con
->finalArgv
) * con
->finalArgvAlloced
);
1440 if (con
->finalArgv
!= NULL
)
1441 { char *s
= malloc((opt
->longName
? strlen(opt
->longName
) : 0) + sizeof("--"));
1442 if (s
!= NULL
) { /* XXX can't happen */
1443 con
->finalArgv
[con
->finalArgvCount
++] = s
;
1445 if (opt
->longName
) {
1446 if (!F_ISSET(opt
, ONEDASH
))
1448 s
= stpcpy(s
, opt
->longName
);
1450 *s
++ = opt
->shortName
;
1454 con
->finalArgv
[con
->finalArgvCount
++] = NULL
;
1457 if (opt
->arg
&& poptArgType(opt
) == POPT_ARG_NONE
)
1459 else if (poptArgType(opt
) == POPT_ARG_VAL
)
1461 else if (poptArgType(opt
) != POPT_ARG_NONE
) {
1462 if (con
->finalArgv
!= NULL
&& con
->os
->nextArg
!= NULL
)
1463 con
->finalArgv
[con
->finalArgvCount
++] =
1464 xstrdup(con
->os
->nextArg
);
1468 return (opt
? opt
->val
: -1); /* XXX can't happen */
1471 char * poptGetOptArg(poptContext con
)
1475 ret
= con
->os
->nextArg
;
1476 con
->os
->nextArg
= NULL
;
1481 const char * poptGetArg(poptContext con
)
1483 const char * ret
= NULL
;
1484 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1485 ret
= con
->leftovers
[con
->nextLeftover
++];
1489 const char * poptPeekArg(poptContext con
)
1491 const char * ret
= NULL
;
1492 if (con
&& con
->leftovers
!= NULL
&& con
->nextLeftover
< con
->numLeftovers
)
1493 ret
= con
->leftovers
[con
->nextLeftover
];
1497 const char ** poptGetArgs(poptContext con
)
1500 con
->leftovers
== NULL
|| con
->numLeftovers
== con
->nextLeftover
)
1503 /* some apps like [like RPM ;-) ] need this NULL terminated */
1504 con
->leftovers
[con
->numLeftovers
] = NULL
;
1506 return (con
->leftovers
+ con
->nextLeftover
);
1510 poptItem
poptFreeItems(poptItem items
, int nitems
)
1512 if (items
!= NULL
) {
1513 poptItem item
= items
;
1514 while (--nitems
>= 0) {
1515 item
->option
.longName
= _free(item
->option
.longName
);
1516 item
->option
.descrip
= _free(item
->option
.descrip
);
1517 item
->option
.argDescrip
= _free(item
->option
.argDescrip
);
1518 item
->argv
= _free(item
->argv
);
1526 poptContext
poptFreeContext(poptContext con
)
1530 if (con
== NULL
) return con
;
1531 poptResetContext(con
);
1533 con
->aliases
= poptFreeItems(con
->aliases
, con
->numAliases
);
1534 con
->numAliases
= 0;
1536 con
->execs
= poptFreeItems(con
->execs
, con
->numExecs
);
1539 for (i
= 0; i
< con
->numLeftovers
; i
++) {
1540 con
->leftovers
[i
] = _free(con
->leftovers
[i
]);
1542 con
->leftovers
= _free(con
->leftovers
);
1544 con
->finalArgv
= _free(con
->finalArgv
);
1545 con
->appName
= _free(con
->appName
);
1546 con
->otherHelp
= _free(con
->otherHelp
);
1547 con
->execPath
= _free(con
->execPath
);
1548 con
->arg_strip
= PBM_FREE(con
->arg_strip
);
1554 int poptAddAlias(poptContext con
, struct poptAlias alias
,
1557 struct poptItem_s item_buf
;
1558 poptItem item
= &item_buf
;
1559 memset(item
, 0, sizeof(*item
));
1560 item
->option
.longName
= alias
.longName
;
1561 item
->option
.shortName
= alias
.shortName
;
1562 item
->option
.argInfo
= POPT_ARGFLAG_DOC_HIDDEN
;
1563 item
->option
.arg
= 0;
1564 item
->option
.val
= 0;
1565 item
->option
.descrip
= NULL
;
1566 item
->option
.argDescrip
= NULL
;
1567 item
->argc
= alias
.argc
;
1568 item
->argv
= alias
.argv
;
1569 return poptAddItem(con
, item
, 0);
1572 int poptAddItem(poptContext con
, poptItem newItem
, int flags
)
1574 poptItem
* items
, item_tmp
, item
;
1579 items
= &con
->execs
;
1580 nitems
= &con
->numExecs
;
1583 items
= &con
->aliases
;
1584 nitems
= &con
->numAliases
;
1591 item_tmp
= realloc((*items
), ((*nitems
) + 1) * sizeof(**items
));
1592 if (item_tmp
== NULL
)
1596 item
= (*items
) + (*nitems
);
1598 item
->option
.longName
=
1599 (newItem
->option
.longName
? xstrdup(newItem
->option
.longName
) : NULL
);
1600 item
->option
.shortName
= newItem
->option
.shortName
;
1601 item
->option
.argInfo
= newItem
->option
.argInfo
;
1602 item
->option
.arg
= newItem
->option
.arg
;
1603 item
->option
.val
= newItem
->option
.val
;
1604 item
->option
.descrip
=
1605 (newItem
->option
.descrip
? xstrdup(newItem
->option
.descrip
) : NULL
);
1606 item
->option
.argDescrip
=
1607 (newItem
->option
.argDescrip
? xstrdup(newItem
->option
.argDescrip
) : NULL
);
1608 item
->argc
= newItem
->argc
;
1609 item
->argv
= newItem
->argv
;
1616 const char * poptBadOption(poptContext con
, unsigned int flags
)
1618 struct optionStackEntry
* os
= NULL
;
1619 const char *badOpt
= NULL
;
1622 /* Stupid hack to return something semi-meaningful from exec failure */
1623 if (con
->execFail
) {
1624 badOpt
= con
->execFail
;
1626 os
= (flags
& POPT_BADOPTION_NOALIAS
) ? con
->optionStack
: con
->os
;
1627 badOpt
= os
->argv
[os
->next
- 1];
1634 const char * poptStrerror(const int error
)
1637 case POPT_ERROR_NOARG
:
1638 return POPT_("missing argument");
1639 case POPT_ERROR_UNWANTEDARG
:
1640 return POPT_("option does not take an argument");
1641 case POPT_ERROR_BADOPT
:
1642 return POPT_("unknown option");
1643 case POPT_ERROR_BADOPERATION
:
1644 return POPT_("mutually exclusive logical operations requested");
1645 case POPT_ERROR_NULLARG
:
1646 return POPT_("opt->arg should not be NULL");
1647 case POPT_ERROR_OPTSTOODEEP
:
1648 return POPT_("aliases nested too deeply");
1649 case POPT_ERROR_BADQUOTE
:
1650 return POPT_("error in parameter quoting");
1651 case POPT_ERROR_BADNUMBER
:
1652 return POPT_("invalid numeric value");
1653 case POPT_ERROR_OVERFLOW
:
1654 return POPT_("number too large or too small");
1655 case POPT_ERROR_MALLOC
:
1656 return POPT_("memory allocation failed");
1657 case POPT_ERROR_BADCONFIG
:
1658 return POPT_("config file failed sanity test");
1659 case POPT_ERROR_ERRNO
:
1660 return strerror(errno
);
1662 return POPT_("unknown error");
1666 int poptStuffArgs(poptContext con
, const char ** argv
)
1671 if ((con
->os
- con
->optionStack
) == POPT_OPTION_DEPTH
)
1672 return POPT_ERROR_OPTSTOODEEP
;
1674 for (argc
= 0; argv
[argc
]; argc
++)
1679 con
->os
->nextArg
= NULL
;
1680 con
->os
->nextCharArg
= NULL
;
1681 con
->os
->currAlias
= NULL
;
1682 rc
= poptDupArgv(argc
, argv
, &con
->os
->argc
, &con
->os
->argv
);
1683 con
->os
->argb
= NULL
;
1684 con
->os
->stuffed
= 1;
1689 const char * poptGetInvocationName(poptContext con
)
1691 return (con
->os
->argv
? con
->os
->argv
[0] : "");
1694 int poptStrippedArgv(poptContext con
, int argc
, char ** argv
)
1701 for (i
= 1; i
< argc
; i
++) {
1702 if (PBM_ISSET(i
, con
->arg_strip
))
1706 for (i
= 1; i
< argc
; i
++) {
1707 if (con
->arg_strip
&& PBM_ISSET(i
, con
->arg_strip
))
1709 argv
[j
] = (j
< numargs
) ? argv
[i
] : NULL
;