2006-05-17 04:04:09 +04:00
/** \ingroup popt
* \ file popt / popt . c
*/
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
2001-10-23 18:16:22 +04:00
file accompanying popt source distributions , available from
2006-05-17 04:04:09 +04:00
ftp : //ftp.rpm.org/pub/rpm/dist */
# undef MYDEBUG
2001-10-23 18:16:22 +04:00
# include "system.h"
2006-05-17 04:04:09 +04:00
# if HAVE_FLOAT_H
# include <float.h>
# endif
# include <math.h>
2001-10-23 18:16:22 +04:00
# include "findme.h"
# include "poptint.h"
2006-05-17 04:04:09 +04:00
# ifdef MYDEBUG
/*@unchecked@*/
int _popt_debug = 0 ;
# endif
2001-10-23 18:16:22 +04:00
# ifndef HAVE_STRERROR
static char * strerror ( int errno ) {
extern int sys_nerr ;
extern char * sys_errlist [ ] ;
if ( ( 0 < = errno ) & & ( errno < sys_nerr ) )
return sys_errlist [ errno ] ;
else
return POPT_ ( " unknown errno " ) ;
}
# endif
2006-05-17 04:04:09 +04:00
# ifdef MYDEBUG
/*@unused@*/ static void prtcon ( const char * msg , poptContext con )
{
if ( msg ) fprintf ( stderr , " %s " , msg ) ;
fprintf ( stderr , " \t con %p os %p nextCharArg \" %s \" nextArg \" %s \" argv[%d] \" %s \" \n " ,
con , con - > os ,
( con - > os - > nextCharArg ? con - > os - > nextCharArg : " " ) ,
( con - > os - > nextArg ? con - > os - > nextArg : " " ) ,
con - > os - > next ,
( con - > os - > argv & & con - > os - > argv [ con - > os - > next ]
? con - > os - > argv [ con - > os - > next ] : " " ) ) ;
}
# endif
void poptSetExecPath ( poptContext con , const char * path , int allowAbsolute )
{
2006-08-01 01:11:03 +04:00
con - > execPath = ( const char * ) _free ( con - > execPath ) ;
2001-10-23 18:16:22 +04:00
con - > execPath = xstrdup ( path ) ;
con - > execAbsolute = allowAbsolute ;
2006-05-17 04:04:09 +04:00
/*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
return ;
/*@=nullstate@*/
}
static void invokeCallbacksPRE ( poptContext con , const struct poptOption * opt )
/*@globals internalState@*/
/*@modifies internalState@*/
{
if ( opt ! = NULL )
for ( ; opt - > longName | | opt - > shortName | | opt - > arg ; opt + + ) {
if ( opt - > arg = = NULL ) continue ; /* XXX program error. */
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_INCLUDE_TABLE ) {
/* Recurse on included sub-tables. */
2006-08-01 01:11:03 +04:00
invokeCallbacksPRE ( con , ( const struct poptOption * ) opt - > arg ) ;
2006-05-17 04:04:09 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_CALLBACK & &
( opt - > argInfo & POPT_CBFLAG_PRE ) )
{ /*@-castfcnptr@*/
poptCallbackType cb = ( poptCallbackType ) opt - > arg ;
/*@=castfcnptr@*/
/* Perform callback. */
/*@-moduncon -noeffectuncon @*/
cb ( con , POPT_CALLBACK_REASON_PRE , NULL , NULL , opt - > descrip ) ;
/*@=moduncon =noeffectuncon @*/
}
}
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
static void invokeCallbacksPOST ( poptContext con , const struct poptOption * opt )
/*@globals internalState@*/
/*@modifies internalState@*/
{
if ( opt ! = NULL )
for ( ; opt - > longName | | opt - > shortName | | opt - > arg ; opt + + ) {
if ( opt - > arg = = NULL ) continue ; /* XXX program error. */
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_INCLUDE_TABLE ) {
/* Recurse on included sub-tables. */
2006-08-01 01:11:03 +04:00
invokeCallbacksPOST ( con , ( const struct poptOption * ) opt - > arg ) ;
2006-05-17 04:04:09 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_CALLBACK & &
( opt - > argInfo & POPT_CBFLAG_POST ) )
{ /*@-castfcnptr@*/
poptCallbackType cb = ( poptCallbackType ) opt - > arg ;
/*@=castfcnptr@*/
/* Perform callback. */
/*@-moduncon -noeffectuncon @*/
cb ( con , POPT_CALLBACK_REASON_POST , NULL , NULL , opt - > descrip ) ;
/*@=moduncon =noeffectuncon @*/
}
}
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
static void invokeCallbacksOPTION ( poptContext con ,
const struct poptOption * opt ,
const struct poptOption * myOpt ,
/*@null@*/ const void * myData , int shorty )
/*@globals internalState@*/
/*@modifies internalState@*/
{
const struct poptOption * cbopt = NULL ;
if ( opt ! = NULL )
for ( ; opt - > longName | | opt - > shortName | | opt - > arg ; opt + + ) {
2001-10-23 18:16:22 +04:00
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_INCLUDE_TABLE ) {
2006-05-17 04:04:09 +04:00
/* Recurse on included sub-tables. */
if ( opt - > arg ! = NULL ) /* XXX program error */
2006-08-01 01:11:03 +04:00
invokeCallbacksOPTION ( con , ( const struct poptOption * ) opt - > arg ,
myOpt , myData , shorty ) ;
2006-05-17 04:04:09 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_CALLBACK & &
! ( opt - > argInfo & POPT_CBFLAG_SKIPOPTION ) ) {
/* Save callback info. */
cbopt = opt ;
} else if ( cbopt ! = NULL & &
( ( myOpt - > shortName & & opt - > shortName & & shorty & &
myOpt - > shortName = = opt - > shortName ) | |
( myOpt - > longName & & opt - > longName & &
/*@-nullpass@*/ /* LCL: opt->longName != NULL */
! strcmp ( myOpt - > longName , opt - > longName ) ) )
/*@=nullpass@*/
)
{ /*@-castfcnptr@*/
poptCallbackType cb = ( poptCallbackType ) cbopt - > arg ;
/*@=castfcnptr@*/
const void * cbData = ( cbopt - > descrip ? cbopt - > descrip : myData ) ;
/* Perform callback. */
if ( cb ! = NULL ) { /* XXX program error */
/*@-moduncon -noeffectuncon @*/
cb ( con , POPT_CALLBACK_REASON_OPTION , myOpt ,
con - > os - > nextArg , cbData ) ;
/*@=moduncon =noeffectuncon @*/
}
/* Terminate (unless explcitly continuing). */
if ( ! ( cbopt - > argInfo & POPT_CBFLAG_CONTINUE ) )
return ;
2001-10-23 18:16:22 +04:00
}
}
}
poptContext poptGetContext ( const char * name , int argc , const char * * argv ,
2006-05-17 04:04:09 +04:00
const struct poptOption * options , int flags )
{
2006-08-01 01:11:03 +04:00
poptContext con = ( poptContext ) malloc ( sizeof ( * con ) ) ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con = = NULL ) return NULL ; /* XXX can't happen */
2001-10-23 18:16:22 +04:00
memset ( con , 0 , sizeof ( * con ) ) ;
con - > os = con - > optionStack ;
con - > os - > argc = argc ;
2006-05-17 04:04:09 +04:00
/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
2001-10-23 18:16:22 +04:00
con - > os - > argv = argv ;
2006-05-17 04:04:09 +04:00
/*@=dependenttrans =assignexpose@*/
2001-10-23 18:16:22 +04:00
con - > os - > argb = NULL ;
if ( ! ( flags & POPT_CONTEXT_KEEP_FIRST ) )
con - > os - > next = 1 ; /* skip argv[0] */
2006-08-01 01:11:03 +04:00
con - > leftovers = ( const char * * ) calloc ( ( argc + 1 ) ,
sizeof ( * con - > leftovers ) ) ;
2006-05-17 04:04:09 +04:00
/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
2001-10-23 18:16:22 +04:00
con - > options = options ;
2006-05-17 04:04:09 +04:00
/*@=dependenttrans =assignexpose@*/
2001-10-23 18:16:22 +04:00
con - > aliases = NULL ;
con - > numAliases = 0 ;
con - > flags = flags ;
con - > execs = NULL ;
con - > numExecs = 0 ;
con - > finalArgvAlloced = argc * 2 ;
2006-08-01 01:11:03 +04:00
con - > finalArgv = ( const char * * ) calloc ( con - > finalArgvAlloced ,
sizeof ( * con - > finalArgv ) ) ;
2001-10-23 18:16:22 +04:00
con - > execAbsolute = 1 ;
con - > arg_strip = NULL ;
if ( getenv ( " POSIXLY_CORRECT " ) | | getenv ( " POSIX_ME_HARDER " ) )
con - > flags | = POPT_CONTEXT_POSIXMEHARDER ;
2006-05-17 04:04:09 +04:00
if ( name ) {
2006-08-01 01:11:03 +04:00
char * t = ( char * ) malloc ( strlen ( name ) + 1 ) ;
2006-05-17 04:04:09 +04:00
if ( t ) con - > appName = strcpy ( t , name ) ;
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
/*@-internalglobs@*/
invokeCallbacksPRE ( con , con - > options ) ;
/*@=internalglobs@*/
2001-10-23 18:16:22 +04:00
return con ;
}
2006-05-17 04:04:09 +04:00
static void cleanOSE ( /*@special@*/ struct optionStackEntry * os )
/*@uses os @*/
/*@releases os->nextArg, os->argv, os->argb @*/
/*@modifies os @*/
2001-10-23 18:16:22 +04:00
{
2006-08-01 01:11:03 +04:00
os - > nextArg = ( const char * ) _free ( os - > nextArg ) ;
os - > argv = ( const char * * ) _free ( os - > argv ) ;
os - > argb = ( pbm_set * ) PBM_FREE ( os - > argb ) ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@-boundswrite@*/
void poptResetContext ( poptContext con )
{
2001-10-23 18:16:22 +04:00
int i ;
2006-05-17 04:04:09 +04:00
if ( con = = NULL ) return ;
2001-10-23 18:16:22 +04:00
while ( con - > os > con - > optionStack ) {
cleanOSE ( con - > os - - ) ;
}
2006-08-01 01:11:03 +04:00
con - > os - > argb = ( pbm_set * ) PBM_FREE ( con - > os - > argb ) ;
2001-10-23 18:16:22 +04:00
con - > os - > currAlias = NULL ;
con - > os - > nextCharArg = NULL ;
con - > os - > nextArg = NULL ;
con - > os - > next = 1 ; /* skip argv[0] */
con - > numLeftovers = 0 ;
con - > nextLeftover = 0 ;
con - > restLeftover = 0 ;
con - > doExec = NULL ;
2006-05-17 04:04:09 +04:00
if ( con - > finalArgv ! = NULL )
2001-10-23 18:16:22 +04:00
for ( i = 0 ; i < con - > finalArgvCount ; i + + ) {
2006-05-17 04:04:09 +04:00
/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
2006-08-01 01:11:03 +04:00
con - > finalArgv [ i ] = ( const char * ) _free ( con - > finalArgv [ i ] ) ;
2006-05-17 04:04:09 +04:00
/*@=unqualifiedtrans@*/
2001-10-23 18:16:22 +04:00
}
con - > finalArgvCount = 0 ;
2006-08-01 01:11:03 +04:00
con - > arg_strip = ( pbm_set * ) PBM_FREE ( con - > arg_strip ) ;
2006-05-17 04:04:09 +04:00
/*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
return ;
/*@=nullstate@*/
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
/* Only one of longName, shortName should be set, not both. */
/*@-boundswrite@*/
static int handleExec ( /*@special@*/ poptContext con ,
/*@null@*/ const char * longName , char shortName )
/*@uses con->execs, con->numExecs, con->flags, con->doExec,
con - > finalArgv , con - > finalArgvAlloced , con - > finalArgvCount @ */
/*@modifies con @*/
{
poptItem item ;
2001-10-23 18:16:22 +04:00
int i ;
2006-05-17 04:04:09 +04:00
if ( con - > execs = = NULL | | con - > numExecs < = 0 ) /* XXX can't happen */
return 0 ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
for ( i = con - > numExecs - 1 ; i > = 0 ; i - - ) {
item = con - > execs + i ;
if ( longName & & ! ( item - > option . longName & &
! strcmp ( longName , item - > option . longName ) ) )
continue ;
else if ( shortName ! = item - > option . shortName )
continue ;
break ;
}
2001-10-23 18:16:22 +04:00
if ( i < 0 ) return 0 ;
2006-05-17 04:04:09 +04:00
2001-10-23 18:16:22 +04:00
if ( con - > flags & POPT_CONTEXT_NO_EXEC )
return 1 ;
if ( con - > doExec = = NULL ) {
con - > doExec = con - > execs + i ;
return 1 ;
}
/* We already have an exec to do; remember this option for next
time ' round */
if ( ( con - > finalArgvCount + 1 ) > = ( con - > finalArgvAlloced ) ) {
con - > finalArgvAlloced + = 10 ;
2006-08-01 01:11:03 +04:00
con - > finalArgv = ( const char * * ) realloc ( con - > finalArgv ,
2001-10-23 18:16:22 +04:00
sizeof ( * con - > finalArgv ) * con - > finalArgvAlloced ) ;
}
i = con - > finalArgvCount + + ;
2006-05-17 04:04:09 +04:00
if ( con - > finalArgv ! = NULL ) /* XXX can't happen */
2006-08-01 01:11:03 +04:00
{ char * s = ( char * ) malloc ( ( longName ? strlen ( longName ) : 0 ) + 3 ) ;
2006-05-17 04:04:09 +04:00
if ( s ! = NULL ) { /* XXX can't happen */
if ( longName )
sprintf ( s , " --%s " , longName ) ;
else
sprintf ( s , " -%c " , shortName ) ;
con - > finalArgv [ i ] = s ;
} else
con - > finalArgv [ i ] = NULL ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
2001-10-23 18:16:22 +04:00
return 1 ;
2006-05-17 04:04:09 +04:00
/*@=nullstate@*/
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
/* Only one of longName, shortName may be set at a time */
2006-05-17 04:04:09 +04:00
static int handleAlias ( /*@special@*/ poptContext con ,
/*@null@*/ const char * longName , char shortName ,
/*@exposed@*/ /*@null@*/ const char * nextCharArg )
/*@uses con->aliases, con->numAliases, con->optionStack, con->os,
con - > os - > currAlias , con - > os - > currAlias - > option . longName @ */
/*@modifies con @*/
{
poptItem item = con - > os - > currAlias ;
int rc ;
2001-10-23 18:16:22 +04:00
int i ;
2006-05-17 04:04:09 +04:00
if ( item ) {
if ( longName & & ( item - > option . longName & &
! strcmp ( longName , item - > option . longName ) ) )
return 0 ;
if ( shortName & & shortName = = item - > option . shortName )
return 0 ;
}
if ( con - > aliases = = NULL | | con - > numAliases < = 0 ) /* XXX can't happen */
2001-10-23 18:16:22 +04:00
return 0 ;
2006-05-17 04:04:09 +04:00
for ( i = con - > numAliases - 1 ; i > = 0 ; i - - ) {
item = con - > aliases + i ;
if ( longName & & ! ( item - > option . longName & &
! strcmp ( longName , item - > option . longName ) ) )
continue ;
else if ( shortName ! = item - > option . shortName )
continue ;
break ;
2001-10-23 18:16:22 +04:00
}
if ( i < 0 ) return 0 ;
if ( ( con - > os - con - > optionStack + 1 ) = = POPT_OPTION_DEPTH )
return POPT_ERROR_OPTSTOODEEP ;
2006-05-17 04:04:09 +04:00
/*@-boundsread@*/
2001-10-23 18:16:22 +04:00
if ( nextCharArg & & * nextCharArg )
con - > os - > nextCharArg = nextCharArg ;
2006-05-17 04:04:09 +04:00
/*@=boundsread@*/
2001-10-23 18:16:22 +04:00
con - > os + + ;
con - > os - > next = 0 ;
con - > os - > stuffed = 0 ;
con - > os - > nextArg = NULL ;
con - > os - > nextCharArg = NULL ;
con - > os - > currAlias = con - > aliases + i ;
2006-05-17 04:04:09 +04:00
rc = poptDupArgv ( con - > os - > currAlias - > argc , con - > os - > currAlias - > argv ,
2001-10-23 18:16:22 +04:00
& con - > os - > argc , & con - > os - > argv ) ;
con - > os - > argb = NULL ;
2006-05-17 04:04:09 +04:00
return ( rc ? rc : 1 ) ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@-bounds -boundswrite @*/
static int execCommand ( poptContext con )
/*@globals internalState @*/
/*@modifies internalState @*/
{
poptItem item = con - > doExec ;
2001-10-23 18:16:22 +04:00
const char * * argv ;
2006-05-17 04:04:09 +04:00
int argc = 0 ;
int rc ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( item = = NULL ) /*XXX can't happen*/
return POPT_ERROR_NOARG ;
if ( item - > argv = = NULL | | item - > argc < 1 | |
( ! con - > execAbsolute & & strchr ( item - > argv [ 0 ] , ' / ' ) ) )
return POPT_ERROR_NOARG ;
2001-10-23 18:16:22 +04:00
2006-08-01 01:11:03 +04:00
argv = ( const char * * ) malloc (
sizeof ( * argv ) * ( 6 + item - > argc + con - > numLeftovers + con - > finalArgvCount ) ) ;
2006-05-17 04:04:09 +04:00
if ( argv = = NULL ) return POPT_ERROR_MALLOC ; /* XXX can't happen */
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( ! strchr ( item - > argv [ 0 ] , ' / ' ) & & con - > execPath ) {
2006-08-01 01:11:03 +04:00
char * s = ( char * ) alloca (
strlen ( con - > execPath ) + strlen ( item - > argv [ 0 ] ) + sizeof ( " / " ) ) ;
2006-05-17 04:04:09 +04:00
sprintf ( s , " %s/%s " , con - > execPath , item - > argv [ 0 ] ) ;
argv [ argc ] = s ;
2001-10-23 18:16:22 +04:00
} else {
2006-05-17 04:04:09 +04:00
argv [ argc ] = findProgramPath ( item - > argv [ 0 ] ) ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
if ( argv [ argc + + ] = = NULL ) return POPT_ERROR_NOARG ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( item - > argc > 1 ) {
memcpy ( argv + argc , item - > argv + 1 , sizeof ( * argv ) * ( item - > argc - 1 ) ) ;
argc + = ( item - > argc - 1 ) ;
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con - > finalArgv ! = NULL & & con - > finalArgvCount > 0 ) {
memcpy ( argv + argc , con - > finalArgv ,
sizeof ( * argv ) * con - > finalArgvCount ) ;
argc + = con - > finalArgvCount ;
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con - > leftovers ! = NULL & & con - > numLeftovers > 0 ) {
#if 0
argv [ argc + + ] = " -- " ;
# endif
memcpy ( argv + argc , con - > leftovers , sizeof ( * argv ) * con - > numLeftovers ) ;
argc + = con - > numLeftovers ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
argv [ argc ] = NULL ;
2001-10-23 18:16:22 +04:00
# ifdef __hpux
2006-05-17 04:04:09 +04:00
rc = setresuid ( getuid ( ) , getuid ( ) , - 1 ) ;
if ( rc ) return POPT_ERROR_ERRNO ;
2001-10-23 18:16:22 +04:00
# else
/*
* XXX " ... on BSD systems setuid() should be preferred over setreuid() "
* XXX sez ' Timur Bakeyev < mc @ bat . ru >
* XXX from Norbert Warmuth < nwarmuth @ privat . circular . de >
*/
# if defined(HAVE_SETUID)
2006-05-17 04:04:09 +04:00
rc = setuid ( getuid ( ) ) ;
if ( rc ) return POPT_ERROR_ERRNO ;
2001-10-23 18:16:22 +04:00
# elif defined (HAVE_SETREUID)
2006-05-17 04:04:09 +04:00
rc = setreuid ( getuid ( ) , getuid ( ) ) ; /*hlauer: not portable to hpux9.01 */
if ( rc ) return POPT_ERROR_ERRNO ;
2001-10-23 18:16:22 +04:00
# else
; /* Can't drop privileges */
# endif
# endif
2006-05-17 04:04:09 +04:00
if ( argv [ 0 ] = = NULL )
return POPT_ERROR_NOARG ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
# ifdef MYDEBUG
if ( _popt_debug )
{ const char * * avp ;
fprintf ( stderr , " ==> execvp(%s) argv[%d]: " , argv [ 0 ] , argc ) ;
for ( avp = argv ; * avp ; avp + + )
fprintf ( stderr , " '%s' " , * avp ) ;
fprintf ( stderr , " \n " ) ;
}
# endif
rc = execvp ( argv [ 0 ] , ( char * const * ) argv ) ;
2006-07-01 05:03:01 +04:00
/* notreached */
if ( rc ) {
return POPT_ERROR_ERRNO ;
}
return 0 ;
2006-05-17 04:04:09 +04:00
}
/*@=bounds =boundswrite @*/
/*@-boundswrite@*/
/*@observer@*/ /*@null@*/ static const struct poptOption *
findOption ( const struct poptOption * opt , /*@null@*/ const char * longName ,
char shortName ,
/*@null@*/ /*@out@*/ poptCallbackType * callback ,
/*@null@*/ /*@out@*/ const void * * callbackData ,
int singleDash )
/*@modifies *callback, *callbackData */
2001-10-23 18:16:22 +04:00
{
const struct poptOption * cb = NULL ;
/* This happens when a single - is given */
2006-05-17 04:04:09 +04:00
if ( singleDash & & ! shortName & & ( longName & & * longName = = ' \0 ' ) )
2001-10-23 18:16:22 +04:00
shortName = ' - ' ;
2006-05-17 04:04:09 +04:00
for ( ; opt - > longName | | opt - > shortName | | opt - > arg ; opt + + ) {
2001-10-23 18:16:22 +04:00
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_INCLUDE_TABLE ) {
2006-05-17 04:04:09 +04:00
const struct poptOption * opt2 ;
/* Recurse on included sub-tables. */
if ( opt - > arg = = NULL ) continue ; /* XXX program error */
2006-08-01 01:11:03 +04:00
opt2 = findOption ( ( const struct poptOption * ) opt - > arg , longName ,
shortName , callback ,
2001-10-23 18:16:22 +04:00
callbackData , singleDash ) ;
2006-05-17 04:04:09 +04:00
if ( opt2 = = NULL ) continue ;
/* Sub-table data will be inheirited if no data yet. */
if ( ! ( callback & & * callback ) ) return opt2 ;
if ( ! ( callbackData & & * callbackData = = NULL ) ) return opt2 ;
/*@-observertrans -dependenttrans @*/
* callbackData = opt - > descrip ;
/*@=observertrans =dependenttrans @*/
return opt2 ;
2001-10-23 18:16:22 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_CALLBACK ) {
cb = opt ;
} else if ( longName & & opt - > longName & &
( ! singleDash | | ( opt - > argInfo & POPT_ARGFLAG_ONEDASH ) ) & &
2006-05-17 04:04:09 +04:00
/*@-nullpass@*/ /* LCL: opt->longName != NULL */
! strcmp ( longName , opt - > longName ) )
/*@=nullpass@*/
{
2001-10-23 18:16:22 +04:00
break ;
} else if ( shortName & & shortName = = opt - > shortName ) {
break ;
}
}
2006-05-17 04:04:09 +04:00
if ( ! opt - > longName & & ! opt - > shortName )
return NULL ;
/*@-modobserver -mods @*/
if ( callback ) * callback = NULL ;
if ( callbackData ) * callbackData = NULL ;
2001-10-23 18:16:22 +04:00
if ( cb ) {
2006-05-17 04:04:09 +04:00
if ( callback )
/*@-castfcnptr@*/
* callback = ( poptCallbackType ) cb - > arg ;
/*@=castfcnptr@*/
if ( ! ( cb - > argInfo & POPT_CBFLAG_INC_DATA ) ) {
if ( callbackData )
/*@-observertrans@*/ /* FIX: typedef double indirection. */
* callbackData = cb - > descrip ;
/*@=observertrans@*/
}
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=modobserver =mods @*/
2001-10-23 18:16:22 +04:00
return opt ;
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
static const char * findNextArg ( /*@special@*/ poptContext con ,
unsigned argx , int delete_arg )
/*@uses con->optionStack, con->os,
con - > os - > next , con - > os - > argb , con - > os - > argc , con - > os - > argv @ */
/*@modifies con @*/
2001-10-23 18:16:22 +04:00
{
struct optionStackEntry * os = con - > os ;
const char * arg ;
do {
int i ;
arg = NULL ;
while ( os - > next = = os - > argc & & os > con - > optionStack ) os - - ;
if ( os - > next = = os - > argc & & os = = con - > optionStack ) break ;
2006-05-17 04:04:09 +04:00
if ( os - > argv ! = NULL )
2001-10-23 18:16:22 +04:00
for ( i = os - > next ; i < os - > argc ; i + + ) {
2006-05-17 04:04:09 +04:00
/*@-sizeoftype@*/
if ( os - > argb & & PBM_ISSET ( i , os - > argb ) )
/*@innercontinue@*/ continue ;
if ( * os - > argv [ i ] = = ' - ' )
/*@innercontinue@*/ continue ;
if ( - - argx > 0 )
/*@innercontinue@*/ continue ;
2001-10-23 18:16:22 +04:00
arg = os - > argv [ i ] ;
2006-05-17 04:04:09 +04:00
if ( delete_arg ) {
2006-08-01 01:11:03 +04:00
if ( os - > argb = = NULL ) os - > argb = ( pbm_set * ) PBM_ALLOC ( os - > argc ) ;
2006-05-17 04:04:09 +04:00
if ( os - > argb ! = NULL ) /* XXX can't happen */
2001-10-23 18:16:22 +04:00
PBM_SET ( i , os - > argb ) ;
}
2006-05-17 04:04:09 +04:00
/*@innerbreak@*/ break ;
/*@=sizeoftype@*/
2001-10-23 18:16:22 +04:00
}
if ( os > con - > optionStack ) os - - ;
} while ( arg = = NULL ) ;
return arg ;
}
2006-05-17 04:04:09 +04:00
/*@-boundswrite@*/
static /*@only@*/ /*@null@*/ const char *
expandNextArg ( /*@special@*/ poptContext con , const char * s )
/*@uses con->optionStack, con->os,
con - > os - > next , con - > os - > argb , con - > os - > argc , con - > os - > argv @ */
/*@modifies con @*/
2001-10-23 18:16:22 +04:00
{
2006-05-17 04:04:09 +04:00
const char * a = NULL ;
2001-10-23 18:16:22 +04:00
size_t alen ;
char * t , * te ;
size_t tn = strlen ( s ) + 1 ;
char c ;
2006-08-01 01:11:03 +04:00
te = t = ( char * ) malloc ( tn ) ; ;
2006-05-17 04:04:09 +04:00
if ( t = = NULL ) return NULL ; /* XXX can't happen */
2001-10-23 18:16:22 +04:00
while ( ( c = * s + + ) ! = ' \0 ' ) {
switch ( c ) {
#if 0 /* XXX can't do this */
case ' \\ ' : /* escape */
c = * s + + ;
2006-05-17 04:04:09 +04:00
/*@switchbreak@*/ break ;
2001-10-23 18:16:22 +04:00
# endif
case ' ! ' :
if ( ! ( s [ 0 ] = = ' # ' & & s [ 1 ] = = ' : ' & & s [ 2 ] = = ' + ' ) )
2006-05-17 04:04:09 +04:00
/*@switchbreak@*/ break ;
/* XXX Make sure that findNextArg deletes only next arg. */
if ( a = = NULL ) {
if ( ( a = findNextArg ( con , 1 , 1 ) ) = = NULL )
/*@switchbreak@*/ break ;
}
2001-10-23 18:16:22 +04:00
s + = 3 ;
alen = strlen ( a ) ;
tn + = alen ;
* te = ' \0 ' ;
2006-08-01 01:11:03 +04:00
t = ( char * ) realloc ( t , tn ) ;
2001-10-23 18:16:22 +04:00
te = t + strlen ( t ) ;
strncpy ( te , a , alen ) ; te + = alen ;
continue ;
2006-05-17 04:04:09 +04:00
/*@notreached@*/ /*@switchbreak@*/ break ;
2001-10-23 18:16:22 +04:00
default :
2006-05-17 04:04:09 +04:00
/*@switchbreak@*/ break ;
2001-10-23 18:16:22 +04:00
}
* te + + = c ;
}
* te = ' \0 ' ;
2006-08-01 01:11:03 +04:00
t = ( char * ) realloc ( t , strlen ( t ) + 1 ) ; /* XXX memory leak, hard to plug */
2001-10-23 18:16:22 +04:00
return t ;
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
static void poptStripArg ( /*@special@*/ poptContext con , int which )
/*@uses con->arg_strip, con->optionStack @*/
/*@defines con->arg_strip @*/
/*@modifies con @*/
2001-10-23 18:16:22 +04:00
{
2006-05-17 04:04:09 +04:00
/*@-sizeoftype@*/
if ( con - > arg_strip = = NULL )
2006-08-01 01:11:03 +04:00
con - > arg_strip = ( pbm_set * ) PBM_ALLOC ( con - > optionStack [ 0 ] . argc ) ;
2006-05-17 04:04:09 +04:00
if ( con - > arg_strip ! = NULL ) /* XXX can't happen */
2001-10-23 18:16:22 +04:00
PBM_SET ( which , con - > arg_strip ) ;
2006-05-17 04:04:09 +04:00
/*@=sizeoftype@*/
/*@-compdef@*/ /* LCL: con->arg_strip udefined? */
return ;
/*@=compdef@*/
}
int poptSaveLong ( long * arg , int argInfo , long aLong )
{
/* XXX Check alignment, may fail on funky platforms. */
if ( arg = = NULL | | ( ( ( unsigned long ) arg ) & ( sizeof ( * arg ) - 1 ) ) )
return POPT_ERROR_NULLARG ;
if ( argInfo & POPT_ARGFLAG_NOT )
aLong = ~ aLong ;
switch ( argInfo & POPT_ARGFLAG_LOGICALOPS ) {
case 0 :
* arg = aLong ;
break ;
case POPT_ARGFLAG_OR :
* arg | = aLong ;
break ;
case POPT_ARGFLAG_AND :
* arg & = aLong ;
break ;
case POPT_ARGFLAG_XOR :
* arg ^ = aLong ;
break ;
default :
return POPT_ERROR_BADOPERATION ;
/*@notreached@*/ break ;
}
return 0 ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
int poptSaveInt ( /*@null@*/ int * arg , int argInfo , long aLong )
{
/* XXX Check alignment, may fail on funky platforms. */
if ( arg = = NULL | | ( ( ( unsigned long ) arg ) & ( sizeof ( * arg ) - 1 ) ) )
return POPT_ERROR_NULLARG ;
if ( argInfo & POPT_ARGFLAG_NOT )
aLong = ~ aLong ;
switch ( argInfo & POPT_ARGFLAG_LOGICALOPS ) {
case 0 :
* arg = aLong ;
break ;
case POPT_ARGFLAG_OR :
* arg | = aLong ;
break ;
case POPT_ARGFLAG_AND :
* arg & = aLong ;
break ;
case POPT_ARGFLAG_XOR :
* arg ^ = aLong ;
break ;
default :
return POPT_ERROR_BADOPERATION ;
/*@notreached@*/ break ;
}
return 0 ;
}
/*@-boundswrite@*/
2001-10-23 18:16:22 +04:00
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt ( poptContext con )
{
const struct poptOption * opt = NULL ;
int done = 0 ;
2006-05-17 04:04:09 +04:00
if ( con = = NULL )
return - 1 ;
2001-10-23 18:16:22 +04:00
while ( ! done ) {
const char * origOptString = NULL ;
poptCallbackType cb = NULL ;
const void * cbData = NULL ;
const char * longArg = NULL ;
int canstrip = 0 ;
2006-05-17 04:04:09 +04:00
int shorty = 0 ;
2001-10-23 18:16:22 +04:00
while ( ! con - > os - > nextCharArg & & con - > os - > next = = con - > os - > argc
& & con - > os > con - > optionStack ) {
cleanOSE ( con - > os - - ) ;
}
if ( ! con - > os - > nextCharArg & & con - > os - > next = = con - > os - > argc ) {
2006-05-17 04:04:09 +04:00
/*@-internalglobs@*/
invokeCallbacksPOST ( con , con - > options ) ;
/*@=internalglobs@*/
if ( con - > doExec ) return execCommand ( con ) ;
2001-10-23 18:16:22 +04:00
return - 1 ;
}
/* Process next long option */
if ( ! con - > os - > nextCharArg ) {
char * localOptString , * optString ;
int thisopt ;
2006-05-17 04:04:09 +04:00
/*@-sizeoftype@*/
2001-10-23 18:16:22 +04:00
if ( con - > os - > argb & & PBM_ISSET ( con - > os - > next , con - > os - > argb ) ) {
con - > os - > next + + ;
continue ;
}
2006-05-17 04:04:09 +04:00
/*@=sizeoftype@*/
thisopt = con - > os - > next ;
if ( con - > os - > argv ! = NULL ) /* XXX can't happen */
2001-10-23 18:16:22 +04:00
origOptString = con - > os - > argv [ con - > os - > next + + ] ;
2006-05-17 04:04:09 +04:00
if ( origOptString = = NULL ) /* XXX can't happen */
return POPT_ERROR_BADOPT ;
2001-10-23 18:16:22 +04:00
if ( con - > restLeftover | | * origOptString ! = ' - ' ) {
if ( con - > flags & POPT_CONTEXT_POSIXMEHARDER )
con - > restLeftover = 1 ;
2006-05-17 04:04:09 +04:00
if ( con - > flags & POPT_CONTEXT_ARG_OPTS ) {
con - > os - > nextArg = xstrdup ( origOptString ) ;
return 0 ;
}
if ( con - > leftovers ! = NULL ) /* XXX can't happen */
con - > leftovers [ con - > numLeftovers + + ] = origOptString ;
2001-10-23 18:16:22 +04:00
continue ;
}
/* Make a copy we can hack at */
localOptString = optString =
2006-08-01 01:11:03 +04:00
strcpy ( ( char * ) alloca ( strlen ( origOptString ) + 1 ) ,
origOptString ) ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( optString [ 0 ] = = ' \0 ' )
2001-10-23 18:16:22 +04:00
return POPT_ERROR_BADOPT ;
if ( optString [ 1 ] = = ' - ' & & ! optString [ 2 ] ) {
con - > restLeftover = 1 ;
continue ;
} else {
char * oe ;
int singleDash ;
optString + + ;
if ( * optString = = ' - ' )
singleDash = 0 , optString + + ;
else
singleDash = 1 ;
/* XXX aliases with arg substitution need "--alias=arg" */
if ( handleAlias ( con , optString , ' \0 ' , NULL ) )
continue ;
2006-05-17 04:04:09 +04:00
2001-10-23 18:16:22 +04:00
if ( handleExec ( con , optString , ' \0 ' ) )
continue ;
/* Check for "--long=arg" option. */
for ( oe = optString ; * oe & & * oe ! = ' = ' ; oe + + )
2006-05-17 04:04:09 +04:00
{ } ;
2001-10-23 18:16:22 +04:00
if ( * oe = = ' = ' ) {
* oe + + = ' \0 ' ;
/* XXX longArg is mapped back to persistent storage. */
longArg = origOptString + ( oe - localOptString ) ;
}
opt = findOption ( con - > options , optString , ' \0 ' , & cb , & cbData ,
singleDash ) ;
if ( ! opt & & ! singleDash )
return POPT_ERROR_BADOPT ;
}
if ( ! opt ) {
con - > os - > nextCharArg = origOptString + 1 ;
} else {
2006-05-17 04:04:09 +04:00
if ( con - > os = = con - > optionStack & &
opt - > argInfo & POPT_ARGFLAG_STRIP )
{
2001-10-23 18:16:22 +04:00
canstrip = 1 ;
poptStripArg ( con , thisopt ) ;
}
2006-05-17 04:04:09 +04:00
shorty = 0 ;
2001-10-23 18:16:22 +04:00
}
}
/* Process next short option */
2006-05-17 04:04:09 +04:00
/*@-branchstate@*/ /* FIX: W2DO? */
2001-10-23 18:16:22 +04:00
if ( con - > os - > nextCharArg ) {
origOptString = con - > os - > nextCharArg ;
con - > os - > nextCharArg = NULL ;
2006-05-17 04:04:09 +04:00
if ( handleAlias ( con , NULL , * origOptString , origOptString + 1 ) )
continue ;
if ( handleExec ( con , NULL , * origOptString ) ) {
/* Restore rest of short options for further processing */
2001-10-23 18:16:22 +04:00
origOptString + + ;
2006-05-17 04:04:09 +04:00
if ( * origOptString ! = ' \0 ' )
con - > os - > nextCharArg = origOptString ;
2001-10-23 18:16:22 +04:00
continue ;
}
opt = findOption ( con - > options , NULL , * origOptString , & cb ,
& cbData , 0 ) ;
if ( ! opt )
return POPT_ERROR_BADOPT ;
2006-05-17 04:04:09 +04:00
shorty = 1 ;
2001-10-23 18:16:22 +04:00
origOptString + + ;
2006-05-17 04:04:09 +04:00
if ( * origOptString ! = ' \0 ' )
2001-10-23 18:16:22 +04:00
con - > os - > nextCharArg = origOptString ;
}
2006-05-17 04:04:09 +04:00
/*@=branchstate@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( opt = = NULL ) return POPT_ERROR_BADOPT ; /* XXX can't happen */
2001-10-23 18:16:22 +04:00
if ( opt - > arg & & ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_NONE ) {
2006-05-17 04:04:09 +04:00
if ( poptSaveInt ( ( int * ) opt - > arg , opt - > argInfo , 1L ) )
return POPT_ERROR_BADOPERATION ;
2001-10-23 18:16:22 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_VAL ) {
2006-05-17 04:04:09 +04:00
if ( opt - > arg ) {
if ( poptSaveInt ( ( int * ) opt - > arg , opt - > argInfo , ( long ) opt - > val ) )
return POPT_ERROR_BADOPERATION ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
} else if ( ( opt - > argInfo & POPT_ARG_MASK ) ! = POPT_ARG_NONE ) {
2006-08-01 01:11:03 +04:00
con - > os - > nextArg = ( const char * ) _free ( con - > os - > nextArg ) ;
2006-05-17 04:04:09 +04:00
/*@-usedef@*/ /* FIX: W2DO? */
2001-10-23 18:16:22 +04:00
if ( longArg ) {
2006-05-17 04:04:09 +04:00
/*@=usedef@*/
longArg = expandNextArg ( con , longArg ) ;
con - > os - > nextArg = longArg ;
2001-10-23 18:16:22 +04:00
} else if ( con - > os - > nextCharArg ) {
2006-05-17 04:04:09 +04:00
longArg = expandNextArg ( con , con - > os - > nextCharArg ) ;
con - > os - > nextArg = longArg ;
2001-10-23 18:16:22 +04:00
con - > os - > nextCharArg = NULL ;
} else {
while ( con - > os - > next = = con - > os - > argc & &
con - > os > con - > optionStack ) {
cleanOSE ( con - > os - - ) ;
}
2006-05-17 04:04:09 +04:00
if ( con - > os - > next = = con - > os - > argc ) {
if ( ! ( opt - > argInfo & POPT_ARGFLAG_OPTIONAL ) )
/*@-compdef@*/ /* FIX: con->os->argv not defined */
return POPT_ERROR_NOARG ;
/*@=compdef@*/
con - > os - > nextArg = NULL ;
} else {
/*
* Make sure this isn ' t part of a short arg or the
* result of an alias expansion .
*/
if ( con - > os = = con - > optionStack & &
( opt - > argInfo & POPT_ARGFLAG_STRIP ) & &
canstrip ) {
poptStripArg ( con , con - > os - > next ) ;
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con - > os - > argv ! = NULL ) { /* XXX can't happen */
/* XXX watchout: subtle side-effects live here. */
longArg = con - > os - > argv [ con - > os - > next + + ] ;
longArg = expandNextArg ( con , longArg ) ;
con - > os - > nextArg = longArg ;
}
}
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
longArg = NULL ;
2001-10-23 18:16:22 +04:00
if ( opt - > arg ) {
switch ( opt - > argInfo & POPT_ARG_MASK ) {
2006-05-17 04:04:09 +04:00
case POPT_ARG_STRING :
2001-10-23 18:16:22 +04:00
/* XXX memory leak, hard to plug */
2006-05-17 04:04:09 +04:00
* ( ( const char * * ) opt - > arg ) = ( con - > os - > nextArg )
? xstrdup ( con - > os - > nextArg ) : NULL ;
/*@switchbreak@*/ break ;
case POPT_ARG_INT :
case POPT_ARG_LONG :
{ long aLong = 0 ;
char * end ;
if ( con - > os - > nextArg ) {
aLong = strtol ( con - > os - > nextArg , & end , 0 ) ;
if ( ! ( end & & * end = = ' \0 ' ) )
return POPT_ERROR_BADNUMBER ;
}
2001-10-23 18:16:22 +04:00
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_LONG ) {
2006-05-17 04:04:09 +04:00
if ( aLong = = LONG_MIN | | aLong = = LONG_MAX )
return POPT_ERROR_OVERFLOW ;
if ( poptSaveLong ( ( long * ) opt - > arg , opt - > argInfo , aLong ) )
return POPT_ERROR_BADOPERATION ;
2001-10-23 18:16:22 +04:00
} else {
if ( aLong > INT_MAX | | aLong < INT_MIN )
return POPT_ERROR_OVERFLOW ;
2006-05-17 04:04:09 +04:00
if ( poptSaveInt ( ( int * ) opt - > arg , opt - > argInfo , aLong ) )
return POPT_ERROR_BADOPERATION ;
}
} /*@switchbreak@*/ break ;
case POPT_ARG_FLOAT :
case POPT_ARG_DOUBLE :
{ double aDouble = 0.0 ;
char * end ;
if ( con - > os - > nextArg ) {
/*@-mods@*/
int saveerrno = errno ;
errno = 0 ;
aDouble = strtod ( con - > os - > nextArg , & end ) ;
if ( errno = = ERANGE )
return POPT_ERROR_OVERFLOW ;
errno = saveerrno ;
/*@=mods@*/
if ( * end ! = ' \0 ' )
return POPT_ERROR_BADNUMBER ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_DOUBLE ) {
* ( ( double * ) opt - > arg ) = aDouble ;
} else {
2006-06-23 10:19:45 +04:00
# ifndef _ABS
2006-05-17 04:04:09 +04:00
# define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
2006-06-23 10:19:45 +04:00
# endif
2006-05-17 04:04:09 +04:00
if ( ( _ABS ( aDouble ) - FLT_MAX ) > DBL_EPSILON )
return POPT_ERROR_OVERFLOW ;
if ( ( FLT_MIN - _ABS ( aDouble ) ) > DBL_EPSILON )
return POPT_ERROR_OVERFLOW ;
* ( ( float * ) opt - > arg ) = aDouble ;
}
} /*@switchbreak@*/ break ;
default :
fprintf ( stdout ,
POPT_ ( " option type (%d) not implemented in popt \n " ) ,
( opt - > argInfo & POPT_ARG_MASK ) ) ;
2001-10-23 18:16:22 +04:00
exit ( EXIT_FAILURE ) ;
2006-05-17 04:04:09 +04:00
/*@notreached@*/ /*@switchbreak@*/ break ;
2001-10-23 18:16:22 +04:00
}
}
}
2006-05-17 04:04:09 +04:00
if ( cb ) {
/*@-internalglobs@*/
invokeCallbacksOPTION ( con , con - > options , opt , cbData , shorty ) ;
/*@=internalglobs@*/
} else if ( opt - > val & & ( ( opt - > argInfo & POPT_ARG_MASK ) ! = POPT_ARG_VAL ) )
2001-10-23 18:16:22 +04:00
done = 1 ;
if ( ( con - > finalArgvCount + 2 ) > = ( con - > finalArgvAlloced ) ) {
con - > finalArgvAlloced + = 10 ;
2006-08-01 01:11:03 +04:00
con - > finalArgv = ( const char * * ) realloc ( con - > finalArgv ,
2001-10-23 18:16:22 +04:00
sizeof ( * con - > finalArgv ) * con - > finalArgvAlloced ) ;
}
2006-05-17 04:04:09 +04:00
if ( con - > finalArgv ! = NULL )
2006-08-01 01:11:03 +04:00
{ char * s = ( char * ) malloc (
( opt - > longName ? strlen ( opt - > longName ) : 0 ) + 3 ) ;
2006-05-17 04:04:09 +04:00
if ( s ! = NULL ) { /* XXX can't happen */
if ( opt - > longName )
sprintf ( s , " %s%s " ,
( ( opt - > argInfo & POPT_ARGFLAG_ONEDASH ) ? " - " : " -- " ) ,
opt - > longName ) ;
else
sprintf ( s , " -%c " , opt - > shortName ) ;
con - > finalArgv [ con - > finalArgvCount + + ] = s ;
} else
con - > finalArgv [ con - > finalArgvCount + + ] = NULL ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
if ( opt - > arg & & ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_NONE )
/*@-ifempty@*/ ; /*@=ifempty@*/
else if ( ( opt - > argInfo & POPT_ARG_MASK ) = = POPT_ARG_VAL )
/*@-ifempty@*/ ; /*@=ifempty@*/
else if ( ( opt - > argInfo & POPT_ARG_MASK ) ! = POPT_ARG_NONE ) {
if ( con - > finalArgv ! = NULL & & con - > os - > nextArg )
con - > finalArgv [ con - > finalArgvCount + + ] =
/*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
xstrdup ( con - > os - > nextArg ) ;
/*@=nullpass@*/
2001-10-23 18:16:22 +04:00
}
}
2006-05-17 04:04:09 +04:00
return ( opt ? opt - > val : - 1 ) ; /* XXX can't happen */
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
const char * poptGetOptArg ( poptContext con )
{
const char * ret = NULL ;
/*@-branchstate@*/
if ( con ) {
ret = con - > os - > nextArg ;
con - > os - > nextArg = NULL ;
}
/*@=branchstate@*/
2001-10-23 18:16:22 +04:00
return ret ;
}
2006-05-17 04:04:09 +04:00
const char * poptGetArg ( poptContext con )
{
const char * ret = NULL ;
if ( con & & con - > leftovers ! = NULL & & con - > nextLeftover < con - > numLeftovers )
ret = con - > leftovers [ con - > nextLeftover + + ] ;
return ret ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
const char * poptPeekArg ( poptContext con )
{
const char * ret = NULL ;
if ( con & & con - > leftovers ! = NULL & & con - > nextLeftover < con - > numLeftovers )
ret = con - > leftovers [ con - > nextLeftover ] ;
return ret ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@-boundswrite@*/
const char * * poptGetArgs ( poptContext con )
{
if ( con = = NULL | |
con - > leftovers = = NULL | | con - > numLeftovers = = con - > nextLeftover )
return NULL ;
2001-10-23 18:16:22 +04:00
/* some apps like [like RPM ;-) ] need this NULL terminated */
con - > leftovers [ con - > numLeftovers ] = NULL ;
2006-05-17 04:04:09 +04:00
/*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
2001-10-23 18:16:22 +04:00
return ( con - > leftovers + con - > nextLeftover ) ;
2006-05-17 04:04:09 +04:00
/*@=nullret =nullstate @*/
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
poptContext poptFreeContext ( poptContext con )
{
poptItem item ;
2001-10-23 18:16:22 +04:00
int i ;
2006-05-17 04:04:09 +04:00
if ( con = = NULL ) return con ;
2001-10-23 18:16:22 +04:00
poptResetContext ( con ) ;
2006-08-01 01:11:03 +04:00
con - > os - > argb = ( pbm_set * ) _free ( con - > os - > argb ) ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con - > aliases ! = NULL )
2001-10-23 18:16:22 +04:00
for ( i = 0 ; i < con - > numAliases ; i + + ) {
2006-05-17 04:04:09 +04:00
item = con - > aliases + i ;
/*@-modobserver -observertrans -dependenttrans@*/
2006-08-01 01:11:03 +04:00
item - > option . longName = ( const char * ) _free ( item - > option . longName ) ;
item - > option . descrip = ( const char * ) _free ( item - > option . descrip ) ;
item - > option . argDescrip = ( const char * ) _free ( item - > option . argDescrip ) ;
2006-05-17 04:04:09 +04:00
/*@=modobserver =observertrans =dependenttrans@*/
2006-08-01 01:11:03 +04:00
item - > argv = ( const char * * ) _free ( item - > argv ) ;
2001-10-23 18:16:22 +04:00
}
2006-08-01 01:11:03 +04:00
con - > aliases = ( poptItem ) _free ( con - > aliases ) ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con - > execs ! = NULL )
2001-10-23 18:16:22 +04:00
for ( i = 0 ; i < con - > numExecs ; i + + ) {
2006-05-17 04:04:09 +04:00
item = con - > execs + i ;
/*@-modobserver -observertrans -dependenttrans@*/
2006-08-01 01:11:03 +04:00
item - > option . longName = ( const char * ) _free ( item - > option . longName ) ;
item - > option . descrip = ( const char * ) _free ( item - > option . descrip ) ;
item - > option . argDescrip = ( const char * ) _free ( item - > option . argDescrip ) ;
2006-05-17 04:04:09 +04:00
/*@=modobserver =observertrans =dependenttrans@*/
2006-08-01 01:11:03 +04:00
item - > argv = ( const char * * ) _free ( item - > argv ) ;
2001-10-23 18:16:22 +04:00
}
2006-08-01 01:11:03 +04:00
con - > execs = ( poptItem ) _free ( con - > execs ) ;
con - > leftovers = ( const char * * ) _free ( con - > leftovers ) ;
con - > finalArgv = ( const char * * ) _free ( con - > finalArgv ) ;
con - > appName = ( const char * ) _free ( con - > appName ) ;
con - > otherHelp = ( const char * ) _free ( con - > otherHelp ) ;
con - > execPath = ( const char * ) _free ( con - > execPath ) ;
con - > arg_strip = ( pbm_set * ) PBM_FREE ( con - > arg_strip ) ;
2001-10-23 18:16:22 +04:00
2006-08-01 01:11:03 +04:00
con = ( poptContext ) _free ( con ) ;
2006-05-17 04:04:09 +04:00
return con ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
int poptAddAlias ( poptContext con , struct poptAlias alias ,
2001-10-23 18:16:22 +04:00
/*@unused@*/ int flags )
{
2006-08-01 01:11:03 +04:00
poptItem item = ( poptItem ) alloca ( sizeof ( * item ) ) ;
2006-05-17 04:04:09 +04:00
memset ( item , 0 , sizeof ( * item ) ) ;
item - > option . longName = alias . longName ;
item - > option . shortName = alias . shortName ;
item - > option . argInfo = POPT_ARGFLAG_DOC_HIDDEN ;
item - > option . arg = 0 ;
item - > option . val = 0 ;
item - > option . descrip = NULL ;
item - > option . argDescrip = NULL ;
item - > argc = alias . argc ;
item - > argv = alias . argv ;
return poptAddItem ( con , item , 0 ) ;
}
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
/*@-boundswrite@*/
/*@-mustmod@*/ /* LCL: con not modified? */
int poptAddItem ( poptContext con , poptItem newItem , int flags )
{
poptItem * items , item ;
int * nitems ;
switch ( flags ) {
case 1 :
items = & con - > execs ;
nitems = & con - > numExecs ;
break ;
case 0 :
items = & con - > aliases ;
nitems = & con - > numAliases ;
break ;
default :
return 1 ;
/*@notreached@*/ break ;
}
2006-08-01 01:11:03 +04:00
* items = ( poptItem ) realloc ( ( * items ) , ( ( * nitems ) + 1 ) * sizeof ( * * items ) ) ;
2006-05-17 04:04:09 +04:00
if ( ( * items ) = = NULL )
return 1 ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
item = ( * items ) + ( * nitems ) ;
item - > option . longName =
( newItem - > option . longName ? xstrdup ( newItem - > option . longName ) : NULL ) ;
item - > option . shortName = newItem - > option . shortName ;
item - > option . argInfo = newItem - > option . argInfo ;
item - > option . arg = newItem - > option . arg ;
item - > option . val = newItem - > option . val ;
item - > option . descrip =
( newItem - > option . descrip ? xstrdup ( newItem - > option . descrip ) : NULL ) ;
item - > option . argDescrip =
( newItem - > option . argDescrip ? xstrdup ( newItem - > option . argDescrip ) : NULL ) ;
item - > argc = newItem - > argc ;
item - > argv = newItem - > argv ;
( * nitems ) + + ;
2001-10-23 18:16:22 +04:00
return 0 ;
}
2006-05-17 04:04:09 +04:00
/*@=mustmod@*/
/*@=boundswrite@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
const char * poptBadOption ( poptContext con , int flags )
{
struct optionStackEntry * os = NULL ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
if ( con ! = NULL )
os = ( flags & POPT_BADOPTION_NOALIAS ) ? con - > optionStack : con - > os ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
/*@-nullderef@*/ /* LCL: os->argv != NULL */
return ( os & & os - > argv ? os - > argv [ os - > next - 1 ] : NULL ) ;
/*@=nullderef@*/
2001-10-23 18:16:22 +04:00
}
2006-05-18 08:10:52 +04:00
const char * poptStrerror ( const int error )
2006-05-17 04:04:09 +04:00
{
2001-10-23 18:16:22 +04:00
switch ( error ) {
case POPT_ERROR_NOARG :
return POPT_ ( " missing argument " ) ;
case POPT_ERROR_BADOPT :
return POPT_ ( " unknown option " ) ;
2006-05-17 04:04:09 +04:00
case POPT_ERROR_BADOPERATION :
return POPT_ ( " mutually exclusive logical operations requested " ) ;
case POPT_ERROR_NULLARG :
return POPT_ ( " opt->arg should not be NULL " ) ;
2001-10-23 18:16:22 +04:00
case POPT_ERROR_OPTSTOODEEP :
return POPT_ ( " aliases nested too deeply " ) ;
case POPT_ERROR_BADQUOTE :
2006-05-17 04:04:09 +04:00
return POPT_ ( " error in parameter quoting " ) ;
2001-10-23 18:16:22 +04:00
case POPT_ERROR_BADNUMBER :
return POPT_ ( " invalid numeric value " ) ;
case POPT_ERROR_OVERFLOW :
return POPT_ ( " number too large or too small " ) ;
2006-05-17 04:04:09 +04:00
case POPT_ERROR_MALLOC :
return POPT_ ( " memory allocation failed " ) ;
2001-10-23 18:16:22 +04:00
case POPT_ERROR_ERRNO :
return strerror ( errno ) ;
default :
return POPT_ ( " unknown error " ) ;
}
}
2006-05-17 04:04:09 +04:00
int poptStuffArgs ( poptContext con , const char * * argv )
{
2001-10-23 18:16:22 +04:00
int argc ;
2006-05-17 04:04:09 +04:00
int rc ;
2001-10-23 18:16:22 +04:00
if ( ( con - > os - con - > optionStack ) = = POPT_OPTION_DEPTH )
return POPT_ERROR_OPTSTOODEEP ;
for ( argc = 0 ; argv [ argc ] ; argc + + )
2006-05-17 04:04:09 +04:00
{ } ;
2001-10-23 18:16:22 +04:00
con - > os + + ;
con - > os - > next = 0 ;
con - > os - > nextArg = NULL ;
con - > os - > nextCharArg = NULL ;
con - > os - > currAlias = NULL ;
2006-05-17 04:04:09 +04:00
rc = poptDupArgv ( argc , argv , & con - > os - > argc , & con - > os - > argv ) ;
2001-10-23 18:16:22 +04:00
con - > os - > argb = NULL ;
con - > os - > stuffed = 1 ;
2006-05-17 04:04:09 +04:00
return rc ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
const char * poptGetInvocationName ( poptContext con )
{
return ( con - > os - > argv ? con - > os - > argv [ 0 ] : " " ) ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@-boundswrite@*/
int poptStrippedArgv ( poptContext con , int argc , char * * argv )
2001-10-23 18:16:22 +04:00
{
2006-05-17 04:04:09 +04:00
int numargs = argc ;
int j = 1 ;
int i ;
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
/*@-sizeoftype@*/
if ( con - > arg_strip )
for ( i = 1 ; i < argc ; i + + ) {
if ( PBM_ISSET ( i , con - > arg_strip ) )
2001-10-23 18:16:22 +04:00
numargs - - ;
}
2006-05-17 04:04:09 +04:00
for ( i = 1 ; i < argc ; i + + ) {
if ( con - > arg_strip & & PBM_ISSET ( i , con - > arg_strip ) )
2001-10-23 18:16:22 +04:00
continue ;
2006-05-17 04:04:09 +04:00
argv [ j ] = ( j < numargs ) ? argv [ i ] : NULL ;
j + + ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=sizeoftype@*/
2001-10-23 18:16:22 +04:00
2006-05-17 04:04:09 +04:00
return numargs ;
2001-10-23 18:16:22 +04:00
}
2006-05-17 04:04:09 +04:00
/*@=boundswrite@*/