Commit cc248aae authored by Wayne Davison's avatar Wayne Davison

Updated to version 1.6.4.

parent ca23c51a
1.3 ->
1.5 -> 1.6
- add ability to perform callbacks for every, not just first, match.
1.3 -> 1.5
- heavy dose of const's
- poptParseArgvString() now NULL terminates the list
......
......@@ -5,7 +5,7 @@ to getopt(3), it contains a number of enhancements, including:
2) popt can parse arbitrary argv[] style arrays while
getopt(2) makes this quite difficult
3) popt allows users to alias command line arguments
4) popt provides convience functions for parsting strings
4) popt provides convience functions for parsing strings
into argv[] style arrays
popt is used by rpm, the Red Hat install program, and many other Red Hat
......
Unlike zlib, this is a perfectly ordinary copy of libpopt. It's only
used on platforms that don't have a sufficiently up-to-date copy of
their own. If you build rsync on a platform which has popt, this
directory should not be used. (You can control that using
--with-included-popt.)
This is a perfectly ordinary copy of libpopt. It is only used on platforms
that do not have a sufficiently up-to-date copy of their own. If you build
rsync on a platform which has popt, this directory should not be used. (You
can control that using the --with-included-popt configure flag.)
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/findme.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "findme.h"
......@@ -9,38 +13,38 @@ const char * findProgramPath(const char * argv0) {
char * path = getenv("PATH");
char * pathbuf;
char * start, * chptr;
char * buf, *local = NULL;
char * buf;
/* If there is a / in the argv[0], it has to be an absolute
path */
if (argv0 == NULL) return NULL; /* XXX can't happen */
/* If there is a / in the argv[0], it has to be an absolute path */
if (strchr(argv0, '/'))
return xstrdup(argv0);
if (!path) return NULL;
if (path == NULL) return NULL;
local = start = pathbuf = malloc(strlen(path) + 1);
buf = malloc(strlen(path) + strlen(argv0) + 2);
start = pathbuf = alloca(strlen(path) + 1);
buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
if (buf == NULL) return NULL; /* XXX can't happen */
strcpy(pathbuf, path);
chptr = NULL;
/*@-branchstate@*/
do {
if ((chptr = strchr(start, ':')))
*chptr = '\0';
sprintf(buf, "%s/%s", start, argv0);
if (!access(buf, X_OK)) {
if (local) free(local);
return buf;
}
if (!access(buf, X_OK))
return buf;
if (chptr)
start = chptr + 1;
else
start = NULL;
} while (start && *start);
/*@=branchstate@*/
free(buf);
if (local) free(local);
return NULL;
}
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/findme.h
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_FINDME
#define H_FINDME
const char * findProgramPath(const char * argv0);
/**
* Return absolute path to executable by searching PATH.
* @param argv0 name of executable
* @return (malloc'd) absolute path to executable (or NULL)
*/
/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0)
/*@*/;
#endif
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/popt.c
*/
/* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist */
#undef MYDEBUG
#include "system.h"
#if HAVE_FLOAT_H
#include <float.h>
#endif
#include <math.h>
#include "findme.h"
#include "poptint.h"
......@@ -18,47 +30,143 @@ static char * strerror(int errno) {
}
#endif
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) {
if (con->execPath) xfree(con->execPath);
#ifdef MYDEBUG
/*@unused@*/ static void prtcon(const char *msg, poptContext con)
{
if (msg) fprintf(stderr, "%s", msg);
fprintf(stderr, "\tcon %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)
{
con->execPath = _free(con->execPath);
con->execPath = xstrdup(path);
con->execAbsolute = allowAbsolute;
/*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
return;
/*@=nullstate@*/
}
static void invokeCallbacks(poptContext con, const struct poptOption * table,
int post) {
const struct poptOption * opt = table;
poptCallbackType cb;
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. */
invokeCallbacksPRE(con, opt->arg);
} 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 @*/
}
}
}
while (opt->longName || opt->shortName || opt->arg) {
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) {
invokeCallbacks(con, opt->arg, post);
} else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) &&
((!post && (opt->argInfo & POPT_CBFLAG_PRE)) ||
( post && (opt->argInfo & POPT_CBFLAG_POST)))) {
cb = (poptCallbackType)opt->arg;
cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE,
NULL, NULL, opt->descrip);
/* Recurse on included sub-tables. */
invokeCallbacksPOST(con, opt->arg);
} 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 @*/
}
}
}
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++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
/* Recurse on included sub-tables. */
if (opt->arg != NULL) /* XXX program error */
invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
} 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;
}
opt++;
}
}
poptContext poptGetContext(const char * name, int argc, const char ** argv,
const struct poptOption * options, int flags) {
const struct poptOption * options, int flags)
{
poptContext con = malloc(sizeof(*con));
if (con == NULL) return NULL; /* XXX can't happen */
memset(con, 0, sizeof(*con));
con->os = con->optionStack;
con->os->argc = argc;
/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
con->os->argv = argv;
/*@=dependenttrans =assignexpose@*/
con->os->argb = NULL;
if (!(flags & POPT_CONTEXT_KEEP_FIRST))
con->os->next = 1; /* skip argv[0] */
con->leftovers = calloc( (argc + 1), sizeof(char *) );
con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
/*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
con->options = options;
/*@=dependenttrans =assignexpose@*/
con->aliases = NULL;
con->numAliases = 0;
con->flags = flags;
......@@ -72,40 +180,37 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
if (name)
con->appName = strcpy(malloc(strlen(name) + 1), name);
if (name) {
char * t = malloc(strlen(name) + 1);
if (t) con->appName = strcpy(t, name);
}
invokeCallbacks(con, con->options, 0);
/*@-internalglobs@*/
invokeCallbacksPRE(con, con->options);
/*@=internalglobs@*/
return con;
}
static void cleanOSE(struct optionStackEntry *os)
static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
/*@uses os @*/
/*@releases os->nextArg, os->argv, os->argb @*/
/*@modifies os @*/
{
if (os->nextArg) {
xfree(os->nextArg);
os->nextArg = NULL;
}
if (os->argv) {
xfree(os->argv);
os->argv = NULL;
}
if (os->argb) {
PBM_FREE(os->argb);
os->argb = NULL;
}
os->nextArg = _free(os->nextArg);
os->argv = _free(os->argv);
os->argb = PBM_FREE(os->argb);
}
void poptResetContext(poptContext con) {
void poptResetContext(poptContext con)
{
int i;
if (con == NULL) return;
while (con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (con->os->argb) {
PBM_FREE(con->os->argb);
con->os->argb = NULL;
}
con->os->argb = PBM_FREE(con->os->argb);
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
......@@ -116,36 +221,44 @@ void poptResetContext(poptContext con) {
con->restLeftover = 0;
con->doExec = NULL;
for (i = 0; i < con->finalArgvCount; i++) {
if (con->finalArgv[i]) {
xfree(con->finalArgv[i]);
con->finalArgv[i] = NULL;
}
}
if (con->finalArgv != NULL)
for (i = 0; i < con->finalArgvCount; i++)
/*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
con->finalArgv[i] = _free(con->finalArgv[i]);
/*@=unqualifiedtrans@*/
con->finalArgvCount = 0;
if (con->arg_strip) {
PBM_FREE(con->arg_strip);
con->arg_strip = NULL;
}
con->arg_strip = PBM_FREE(con->arg_strip);
/*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
return;
/*@=nullstate@*/
}
/* Only one of longName, shortName may be set at a time */
static int handleExec(poptContext con, char * longName, char shortName) {
/* Only one of longName, shortName should be set, not both. */
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;
int i;
i = con->numExecs - 1;
if (longName) {
while (i >= 0 && (!con->execs[i].longName ||
strcmp(con->execs[i].longName, longName))) i--;
} else {
while (i >= 0 &&
con->execs[i].shortName != shortName) i--;
}
if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */
return 0;
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;
}
if (i < 0) return 0;
if (con->flags & POPT_CONTEXT_NO_EXEC)
return 1;
......@@ -163,38 +276,55 @@ static int handleExec(poptContext con, char * longName, char shortName) {
}
i = con->finalArgvCount++;
if (con->finalArgv != NULL) /* XXX can't happen */
{ char *s = malloc((longName ? strlen(longName) : 0) + 3);
if (longName)
sprintf(s, "--%s", longName);
else
sprintf(s, "-%c", shortName);
con->finalArgv[i] = s;
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;
}
/*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
return 1;
/*@=nullstate@*/
}
/* Only one of longName, shortName may be set at a time */
static int handleAlias(poptContext con, const char * longName, char shortName,
/*@keep@*/ const char * nextCharArg) {
static int handleAlias(/*@special@*/ poptContext con,
/*@null@*/ const char * longName, char shortName,
/*@keep@*/ /*@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;
int i;
if (con->os->currAlias && con->os->currAlias->longName && longName &&
!strcmp(con->os->currAlias->longName, longName))
return 0;
if (con->os->currAlias && shortName &&
shortName == con->os->currAlias->shortName)
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 */
return 0;
i = con->numAliases - 1;
if (longName) {
while (i >= 0 && (!con->aliases[i].longName ||
strcmp(con->aliases[i].longName, longName))) i--;
} else {
while (i >= 0 &&
con->aliases[i].shortName != shortName) i--;
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;
}
if (i < 0) return 0;
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
......@@ -209,49 +339,65 @@ static int handleAlias(poptContext con, const char * longName, char shortName,
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = con->aliases + i;
poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
&con->os->argc, &con->os->argv);
con->os->argb = NULL;
return 1;
return (rc ? rc : 1);
}
static void execCommand(poptContext con) {
static int execCommand(poptContext con)
/*@*/
{
poptItem item = con->doExec;
const char ** argv;
int pos = 0;
const char * script = con->doExec->script;
int argc = 0;
int rc;
argv = malloc(sizeof(*argv) *
(6 + con->numLeftovers + con->finalArgvCount));
if (item == NULL) /*XXX can't happen*/
return POPT_ERROR_NOARG;
if (!con->execAbsolute && strchr(script, '/')) return;
if (item->argv == NULL || item->argc < 1 ||
(!con->execAbsolute && strchr(item->argv[0], '/')))
return POPT_ERROR_NOARG;
argv = malloc(sizeof(*argv) *
(6 + item->argc + con->numLeftovers + con->finalArgvCount));
if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */
if (!strchr(script, '/') && con->execPath) {
char *s = malloc(strlen(con->execPath) + strlen(script) + 2);
sprintf(s, "%s/%s", con->execPath, script);
argv[pos] = s;
if (!strchr(item->argv[0], '/') && con->execPath) {
char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
sprintf(s, "%s/%s", con->execPath, item->argv[0]);
argv[argc] = s;
} else {
argv[pos] = script;
argv[argc] = findProgramPath(item->argv[0]);
}
pos++;
if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
argv[pos] = findProgramPath(con->os->argv[0]);
if (argv[pos]) pos++;
argv[pos++] = ";";
if (item->argc > 1) {
memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
argc += (item->argc - 1);
}
memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount);
pos += con->finalArgvCount;
if (con->finalArgv != NULL && con->finalArgvCount > 0) {
memcpy(argv + argc, con->finalArgv,
sizeof(*argv) * con->finalArgvCount);
argc += con->finalArgvCount;
}
if (con->numLeftovers) {
argv[pos++] = "--";
memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers);
pos += con->numLeftovers;
if (con->leftovers != NULL && con->numLeftovers > 0) {
#if 0
argv[argc++] = "--";
#endif
memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
argc += con->numLeftovers;
}
argv[pos++] = NULL;
argv[argc] = NULL;
#ifdef __hpux
setresuid(getuid(), getuid(),-1);
rc = setresuid(getuid(), getuid(),-1);
if (rc) return POPT_ERROR_ERRNO;
#else
/*
* XXX " ... on BSD systems setuid() should be preferred over setreuid()"
......@@ -259,65 +405,103 @@ static void execCommand(poptContext con) {
* XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
*/
#if defined(HAVE_SETUID)
setuid(getuid());
rc = setuid(getuid());
if (rc) return POPT_ERROR_ERRNO;
#elif defined (HAVE_SETREUID)
setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
if (rc) return POPT_ERROR_ERRNO;
#else
; /* Can't drop privileges */
#endif
#endif
execvp(argv[0], (char *const *)argv);
if (argv[0] == NULL)
return POPT_ERROR_NOARG;
#ifdef MYDEBUG
{ 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);
return POPT_ERROR_ERRNO;
}
/*@observer@*/ static const struct poptOption *
findOption(const struct poptOption * table, const char * longName,
char shortName,
/*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData,
int singleDash)
/*@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 */
{
const struct poptOption * opt = table;
const struct poptOption * opt2;
const struct poptOption * cb = NULL;
/* This happens when a single - is given */
if (singleDash && !shortName && !*longName)
if (singleDash && !shortName && (longName && *longName == '\0'))
shortName = '-';
while (opt->longName || opt->shortName || opt->arg) {
for (; opt->longName || opt->shortName || opt->arg; opt++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
const struct poptOption * opt2;
/* Recurse on included sub-tables. */
if (opt->arg == NULL) continue; /* XXX program error */
opt2 = findOption(opt->arg, longName, shortName, callback,
callbackData, singleDash);
if (opt2) {
if (*callback && !*callbackData)
*callbackData = opt->descrip;
return opt2;
}
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;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
cb = opt;
} else if (longName && opt->longName &&
(!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
!strcmp(longName, opt->longName)) {
/*@-nullpass@*/ /* LCL: opt->longName != NULL */
!strcmp(longName, opt->longName))
/*@=nullpass@*/
{
break;
} else if (shortName && shortName == opt->shortName) {
break;
}
opt++;
}
if (!opt->longName && !opt->shortName) return NULL;
*callbackData = NULL;
*callback = NULL;
if (!opt->longName && !opt->shortName)
return NULL;
/*@-modobserver -mods @*/
if (callback) *callback = NULL;
if (callbackData) *callbackData = NULL;
if (cb) {
*callback = (poptCallbackType)cb->arg;
if (!(cb->argInfo & POPT_CBFLAG_INC_DATA))
*callbackData = cb->descrip;
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@*/
}
}
/*@=modobserver =mods @*/
return opt;
}
static const char *findNextArg(poptContext con, unsigned argx, int delete)
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 @*/
{
struct optionStackEntry * os = con->os;
const char * arg;
......@@ -327,43 +511,58 @@ static const char *findNextArg(poptContext con, unsigned argx, int delete)
arg = NULL;
while (os->next == os->argc && os > con->optionStack) os--;
if (os->next == os->argc && os == con->optionStack) break;
if (os->argv != NULL)
for (i = os->next; i < os->argc; i++) {
if (os->argb && PBM_ISSET(i, os->argb)) continue;
if (*os->argv[i] == '-') continue;
if (--argx > 0) continue;
/*@-sizeoftype@*/
if (os->argb && PBM_ISSET(i, os->argb))
/*@innercontinue@*/ continue;
if (*os->argv[i] == '-')
/*@innercontinue@*/ continue;
if (--argx > 0)
/*@innercontinue@*/ continue;
arg = os->argv[i];
if (delete) {
if (delete_arg) {
if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
if (os->argb != NULL) /* XXX can't happen */
PBM_SET(i, os->argb);
}
break;
/*@innerbreak@*/ break;
/*@=sizeoftype@*/
}
if (os > con->optionStack) os--;
} while (arg == NULL);
return arg;
}
static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
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 @*/
{
const char *a;
const char * a = NULL;
size_t alen;
char *t, *te;
size_t tn = strlen(s) + 1;
char c;
te = t = malloc(tn);;
if (t == NULL) return NULL; /* XXX can't happen */
while ((c = *s++) != '\0') {
switch (c) {
#if 0 /* XXX can't do this */
case '\\': /* escape */
c = *s++;
break;
/*@switchbreak@*/ break;
#endif
case '!':
if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
break;
if ((a = findNextArg(con, 1, 1)) == NULL)
break;
/*@switchbreak@*/ break;
/* XXX Make sure that findNextArg deletes only next arg. */
if (a == NULL) {
if ((a = findNextArg(con, 1, 1)) == NULL)
/*@switchbreak@*/ break;
}
s += 3;
alen = strlen(a);
......@@ -373,23 +572,87 @@ static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
te = t + strlen(t);
strncpy(te, a, alen); te += alen;
continue;
/*@notreached@*/ break;
/*@notreached@*/ /*@switchbreak@*/ break;
default:
break;
/*@switchbreak@*/ break;
}
*te++ = c;
}
*te = '\0';
t = realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */
t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
return t;
}
static void poptStripArg(poptContext con, int which)
static void poptStripArg(/*@special@*/ poptContext con, int which)
/*@uses con->arg_strip, con->optionStack @*/
/*@defines con->arg_strip @*/
/*@modifies con @*/
{
if(con->arg_strip == NULL) {
/*@-sizeoftype@*/
if (con->arg_strip == NULL)
con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
}
if (con->arg_strip != NULL) /* XXX can't happen */
PBM_SET(which, con->arg_strip);
/*@=sizeoftype@*/
/*@-compdef@*/ /* LCL: con->arg_strip udefined? */
return;
/*@=compdef@*/
}
static int poptSaveLong(const struct poptOption * opt, long aLong)
/*@modifies opt->arg @*/
{
if (opt->arg == NULL)
return POPT_ERROR_NULLARG;
if (opt->argInfo & POPT_ARGFLAG_NOT)
aLong = ~aLong;
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
case 0:
*((long *) opt->arg) = aLong;
break;
case POPT_ARGFLAG_OR:
*((long *) opt->arg) |= aLong;
break;
case POPT_ARGFLAG_AND:
*((long *) opt->arg) &= aLong;
break;
case POPT_ARGFLAG_XOR:
*((long *) opt->arg) ^= aLong;
break;
default:
return POPT_ERROR_BADOPERATION;
/*@notreached@*/ break;
}
return 0;
}
static int poptSaveInt(const struct poptOption * opt, long aLong)
/*@modifies opt->arg @*/
{
if (opt->arg == NULL)
return POPT_ERROR_NULLARG;
if (opt->argInfo & POPT_ARGFLAG_NOT)
aLong = ~aLong;
switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
case 0:
*((int *) opt->arg) = aLong;
break;
case POPT_ARGFLAG_OR:
*((int *) opt->arg) |= aLong;
break;
case POPT_ARGFLAG_AND:
*((int *) opt->arg) &= aLong;
break;
case POPT_ARGFLAG_XOR:
*((int *) opt->arg) ^= aLong;
break;
default:
return POPT_ERROR_BADOPERATION;
/*@notreached@*/ break;
}
return 0;
}
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
......@@ -398,28 +661,25 @@ int poptGetNextOpt(poptContext con)
const struct poptOption * opt = NULL;
int done = 0;
/* looks a bit tricky to get rid of alloca properly in this fn */
#if HAVE_ALLOCA_H
#define ALLOCA(x) alloca(x)
#else
#define ALLOCA(x) malloc(x)
#endif
if (con == NULL)
return -1;
while (!done) {
const char * origOptString = NULL;
poptCallbackType cb = NULL;
const void * cbData = NULL;
const char * longArg = NULL;
int canstrip = 0;
int shorty = 0;
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) {
invokeCallbacks(con, con->options, 1);
if (con->doExec) execCommand(con);
/*@-internalglobs@*/
invokeCallbacksPOST(con, con->options);
/*@=internalglobs@*/
if (con->doExec) return execCommand(con);
return -1;
}
......@@ -428,26 +688,36 @@ int poptGetNextOpt(poptContext con)
char * localOptString, * optString;
int thisopt;
/*@-sizeoftype@*/
if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
con->os->next++;
continue;
}
thisopt=con->os->next;
/*@=sizeoftype@*/
thisopt = con->os->next;
if (con->os->argv != NULL) /* XXX can't happen */
origOptString = con->os->argv[con->os->next++];
if (origOptString == NULL) /* XXX can't happen */
return POPT_ERROR_BADOPT;
if (con->restLeftover || *origOptString != '-') {
con->leftovers[con->numLeftovers++] = origOptString;
if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
con->restLeftover = 1;
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;
continue;
}
/* Make a copy we can hack at */
localOptString = optString =
strcpy(ALLOCA(strlen(origOptString) + 1),
origOptString);
strcpy(alloca(strlen(origOptString) + 1), origOptString);
if (!optString[0])
if (optString[0] == '\0')
return POPT_ERROR_BADOPT;
if (optString[1] == '-' && !optString[2]) {
......@@ -466,12 +736,13 @@ int poptGetNextOpt(poptContext con)
/* XXX aliases with arg substitution need "--alias=arg" */
if (handleAlias(con, optString, '\0', NULL))
continue;
if (handleExec(con, optString, '\0'))
continue;
/* Check for "--long=arg" option. */
for (oe = optString; *oe && *oe != '='; oe++)
;
{};
if (*oe == '=') {
*oe++ = '\0';
/* XXX longArg is mapped back to persistent storage. */
......@@ -487,110 +758,175 @@ int poptGetNextOpt(poptContext con)
if (!opt) {
con->os->nextCharArg = origOptString + 1;
} else {
if(con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP) {
if (con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP)
{
canstrip = 1;
poptStripArg(con, thisopt);
}
shorty = 0;
}
}
/* Process next short option */
/*@-branchstate@*/ /* FIX: W2DO? */
if (con->os->nextCharArg) {
origOptString = con->os->nextCharArg;
con->os->nextCharArg = NULL;
if (handleAlias(con, NULL, *origOptString,
origOptString + 1)) {
if (handleAlias(con, NULL, *origOptString, origOptString + 1))
continue;
if (handleExec(con, NULL, *origOptString)) {
/* Restore rest of short options for further processing */
origOptString++;
if (*origOptString != '\0')
con->os->nextCharArg = origOptString;
continue;
}
if (handleExec(con, NULL, *origOptString))
continue;
opt = findOption(con->options, NULL, *origOptString, &cb,
&cbData, 0);
if (!opt)
return POPT_ERROR_BADOPT;
shorty = 1;
origOptString++;
if (*origOptString)
if (*origOptString != '\0')
con->os->nextCharArg = origOptString;
}
/*@=branchstate@*/
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
*((int *)opt->arg) = 1;
if (poptSaveInt(opt, 1L))
return POPT_ERROR_BADOPERATION;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
if (opt->arg)
*((int *) opt->arg) = opt->val;
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
if (con->os->nextArg) {
xfree(con->os->nextArg);
con->os->nextArg = NULL;
if (opt->arg) {
if (poptSaveInt(opt, (long)opt->val))
return POPT_ERROR_BADOPERATION;
}
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
con->os->nextArg = _free(con->os->nextArg);
/*@-usedef@*/ /* FIX: W2DO? */
if (longArg) {
con->os->nextArg = expandNextArg(con, longArg);
/*@=usedef@*/
longArg = expandNextArg(con, longArg);
con->os->nextArg = longArg;
} else if (con->os->nextCharArg) {
con->os->nextArg = expandNextArg(con, con->os->nextCharArg);
longArg = expandNextArg(con, con->os->nextCharArg);
con->os->nextArg = longArg;
con->os->nextCharArg = NULL;
} else {
while (con->os->next == con->os->argc &&
con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (con->os->next == con->os->argc)
return POPT_ERROR_NOARG;
/* 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);
}
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);
}
con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]);
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;
}
}
}
longArg = NULL;
if (opt->arg) {
long aLong;
char *end;
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_STRING:
case POPT_ARG_STRING:
/* XXX memory leak, hard to plug */
*((const char **) opt->arg) = xstrdup(con->os->nextArg);
break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
aLong = strtol(con->os->nextArg, &end, 0);
if (!(end && *end == '\0'))
return POPT_ERROR_BADNUMBER;
*((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;
}
if (aLong == LONG_MIN || aLong == LONG_MAX)
return POPT_ERROR_OVERFLOW;
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
*((long *) opt->arg) = aLong;
if (aLong == LONG_MIN || aLong == LONG_MAX)
return POPT_ERROR_OVERFLOW;
if (poptSaveLong(opt, aLong))
return POPT_ERROR_BADOPERATION;
} else {
if (aLong > INT_MAX || aLong < INT_MIN)
return POPT_ERROR_OVERFLOW;
*((int *) opt->arg) = aLong;
if (poptSaveInt(opt, 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;
}
break;
default:
fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"),
opt->argInfo & POPT_ARG_MASK);
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
*((double *) opt->arg) = aDouble;
} else {
#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
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));
exit(EXIT_FAILURE);
/*@notreached@*/ /*@switchbreak@*/ break;
}
}
}
if (cb)
cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData);
else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
if (cb) {
/*@-internalglobs@*/
invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
/*@=internalglobs@*/
} else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
done = 1;
if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
......@@ -599,131 +935,217 @@ int poptGetNextOpt(poptContext con)
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
{ char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
if (opt->longName)
sprintf(s, "--%s", opt->longName);
else
sprintf(s, "-%c", opt->shortName);
con->finalArgv[con->finalArgvCount++] = s;
if (con->finalArgv != NULL)
{ char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
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;
}
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE
&& (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) {
con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg);
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@*/
}
}
return opt->val;
return (opt ? opt->val : -1); /* XXX can't happen */
}
const char * poptGetOptArg(poptContext con) {
const char * ret = con->os->nextArg;
con->os->nextArg = NULL;
const char * poptGetOptArg(poptContext con)
{
const char * ret = NULL;
/*@-branchstate@*/
if (con) {
ret = con->os->nextArg;
con->os->nextArg = NULL;
}
/*@=branchstate@*/
return ret;
}
const char * poptGetArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return con->leftovers[con->nextLeftover++];
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;
}
const char * poptPeekArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return con->leftovers[con->nextLeftover];
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;
}
const char ** poptGetArgs(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
const char ** poptGetArgs(poptContext con)
{
if (con == NULL ||
con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
return NULL;
/* some apps like [like RPM ;-) ] need this NULL terminated */
con->leftovers[con->numLeftovers] = NULL;
/*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
return (con->leftovers + con->nextLeftover);
/*@=nullret =nullstate @*/
}
void poptFreeContext(poptContext con) {
poptContext poptFreeContext(poptContext con)
{
poptItem item;
int i;
if (con == NULL) return con;
poptResetContext(con);
if (con->os->argb) free(con->os->argb);
con->os->argb = _free(con->os->argb);
if (con->aliases != NULL)
for (i = 0; i < con->numAliases; i++) {
if (con->aliases[i].longName) xfree(con->aliases[i].longName);
free(con->aliases[i].argv);
item = con->aliases + i;
/*@-modobserver -observertrans -dependenttrans@*/
item->option.longName = _free(item->option.longName);
item->option.descrip = _free(item->option.descrip);
item->option.argDescrip = _free(item->option.argDescrip);
/*@=modobserver =observertrans =dependenttrans@*/
item->argv = _free(item->argv);
}
con->aliases = _free(con->aliases);
if (con->execs != NULL)
for (i = 0; i < con->numExecs; i++) {
if (con->execs[i].longName) xfree(con->execs[i].longName);
xfree(con->execs[i].script);
item = con->execs + i;
/*@-modobserver -observertrans -dependenttrans@*/
item->option.longName = _free(item->option.longName);
item->option.descrip = _free(item->option.descrip);
item->option.argDescrip = _free(item->option.argDescrip);
/*@=modobserver =observertrans =dependenttrans@*/
item->argv = _free(item->argv);
}
if (con->execs) xfree(con->execs);
free(con->leftovers);
free(con->finalArgv);
if (con->appName) xfree(con->appName);
if (con->aliases) free(con->aliases);
if (con->otherHelp) xfree(con->otherHelp);
if (con->execPath) xfree(con->execPath);
if (con->arg_strip) PBM_FREE(con->arg_strip);
con->execs = _free(con->execs);
con->leftovers = _free(con->leftovers);
con->finalArgv = _free(con->finalArgv);
con->appName = _free(con->appName);
con->otherHelp = _free(con->otherHelp);
con->execPath = _free(con->execPath);
con->arg_strip = PBM_FREE(con->arg_strip);
free(con);
con = _free(con);
return con;
}
int poptAddAlias(poptContext con, struct poptAlias newAlias,
int poptAddAlias(poptContext con, struct poptAlias alias,
/*@unused@*/ int flags)
{
int aliasNum = con->numAliases++;
struct poptAlias * alias;
poptItem item = alloca(sizeof(*item));
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);
}
/* SunOS won't realloc(NULL, ...) */
if (!con->aliases)
con->aliases = malloc(sizeof(newAlias) * con->numAliases);
else
con->aliases = realloc(con->aliases,
sizeof(newAlias) * con->numAliases);
alias = con->aliases + aliasNum;
/*@-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;
}
*items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
if ((*items) == NULL)
return 1;
item = (*items) + (*nitems);
alias->longName = (newAlias.longName)
? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName)
: NULL;
alias->shortName = newAlias.shortName;
alias->argc = newAlias.argc;
alias->argv = newAlias.argv;
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)++;
return 0;
}
/*@=mustmod@*/
const char * poptBadOption(poptContext con, int flags) {
struct optionStackEntry * os;
const char * poptBadOption(poptContext con, int flags)
{
struct optionStackEntry * os = NULL;
if (flags & POPT_BADOPTION_NOALIAS)
os = con->optionStack;
else
os = con->os;
if (con != NULL)
os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
return os->argv[os->next - 1];
/*@-nullderef@*/ /* LCL: os->argv != NULL */
return (os && os->argv ? os->argv[os->next - 1] : NULL);
/*@=nullderef@*/
}
#define POPT_ERROR_NOARG -10
#define POPT_ERROR_BADOPT -11
#define POPT_ERROR_OPTSTOODEEP -13
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
const char *const poptStrerror(const int error) {
const char *const poptStrerror(const int error)
{
switch (error) {
case POPT_ERROR_NOARG:
return POPT_("missing argument");
case POPT_ERROR_BADOPT:
return POPT_("unknown option");
case POPT_ERROR_BADOPERATION:
return POPT_("mutually exclusive logical operations requested");
case POPT_ERROR_NULLARG:
return POPT_("opt->arg should not be NULL");
case POPT_ERROR_OPTSTOODEEP:
return POPT_("aliases nested too deeply");
case POPT_ERROR_BADQUOTE:
return POPT_("error in paramter quoting");
return POPT_("error in parameter quoting");
case POPT_ERROR_BADNUMBER:
return POPT_("invalid numeric value");
case POPT_ERROR_OVERFLOW:
return POPT_("number too large or too small");
case POPT_ERROR_MALLOC:
return POPT_("memory allocation failed");
case POPT_ERROR_ERRNO:
return strerror(errno);
default:
......@@ -731,52 +1153,54 @@ const char *const poptStrerror(const int error) {
}
}
int poptStuffArgs(poptContext con, const char ** argv) {
int poptStuffArgs(poptContext con, const char ** argv)
{
int argc;
int rc;
if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
for (argc = 0; argv[argc]; argc++)
;
{};
con->os++;
con->os->next = 0;
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = NULL;
poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
con->os->argb = NULL;
con->os->stuffed = 1;
return 0;
return rc;
}
const char * poptGetInvocationName(poptContext con) {
return con->os->argv[0];
const char * poptGetInvocationName(poptContext con)
{
return (con->os->argv ? con->os->argv[0] : "");
}
int poptStrippedArgv(poptContext con, int argc, char **argv)
int poptStrippedArgv(poptContext con, int argc, char ** argv)
{
int i,j=1, numargs=argc;
int numargs = argc;
int j = 1;
int i;
for(i=1; i<argc; i++) {
if(PBM_ISSET(i, con->arg_strip)) {
/*@-sizeoftype@*/
if (con->arg_strip)
for (i = 1; i < argc; i++) {
if (PBM_ISSET(i, con->arg_strip))
numargs--;
}
}
for(i=1; i<argc; i++) {
if(PBM_ISSET(i, con->arg_strip)) {
for (i = 1; i < argc; i++) {
if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
continue;
} else {
if(j<numargs) {
argv[j++]=argv[i];
} else {
argv[j++]='\0';
}
}
argv[j] = (j < numargs) ? argv[i] : NULL;
j++;
}
/*@=sizeoftype@*/
return(numargs);
return numargs;
}
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \file popt/popt.h
* \ingroup popt
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPT
#define H_POPT
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h> /* for FILE * */
#define POPT_OPTION_DEPTH 10
#define POPT_ARG_NONE 0
#define POPT_ARG_STRING 1
#define POPT_ARG_INT 2
#define POPT_ARG_LONG 3
#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */
#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be
/** \ingroup popt
* \name Arg type identifiers
*/
/*@{*/
#define POPT_ARG_NONE 0 /*!< no arg */
#define POPT_ARG_STRING 1 /*!< arg will be saved as string */
#define POPT_ARG_INT 2 /*!< arg will be converted to int */
#define POPT_ARG_LONG 3 /*!< arg will be converted to long */
#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */
#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be
set first in table; arg points
to callback, descrip points to
callback data to pass */
#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain
#define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain
for this table and any
included tables; arg points
to the domain string */
#define POPT_ARG_VAL 7 /* arg should take value val */
#define POPT_ARG_VAL 7 /*!< arg should take value val */
#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */
#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */
#define POPT_ARG_MASK 0x0000FFFF
#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */
#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line,
/*@}*/
/** \ingroup popt
* \name Arg modifiers
*/
/*@{*/
#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */
#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */
#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */
#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */
#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */
#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */
#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */
#define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */
#define POPT_ARGFLAG_LOGICALOPS \
(POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR)
#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR)
/*!< set arg bit(s) */
#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND)
/*!< clear arg bit(s) */
#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */
/*@}*/
/** \ingroup popt
* \name Callback modifiers
*/
/*@{*/
#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line,
not the subtable */
#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */
#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */
/*@}*/
#define POPT_ERROR_NOARG -10
#define POPT_ERROR_BADOPT -11
#define POPT_ERROR_OPTSTOODEEP -13
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
#define POPT_ERROR_BADNUMBER -17
#define POPT_ERROR_OVERFLOW -18
/** \ingroup popt
* \name Error return values
*/
/*@{*/
#define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */
#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */
#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */
#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */
#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */
/*@}*/
/* poptBadOption() flags */
#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */
/** \ingroup popt
* \name poptBadOption() flags
*/
/*@{*/
#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */
/*@}*/
/* poptGetContext() flags */
#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */
/** \ingroup popt
* \name poptGetContext() flags
*/
/*@{*/
#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */
#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */
/*@}*/
/** \ingroup popt
*/
struct poptOption {
/*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */
char shortName; /* may be '\0' */
/*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
int argInfo;
/*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */
int val; /* 0 means don't return, just update flag */
/*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */
/*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */
/*@shared@*/ /*@null@*/ void * arg; /*!< depends on argInfo */
int val; /*!< 0 means don't return, just update flag */
/*@observer@*/ /*@null@*/ const char * descrip; /*!< description for autohelp -- may be NULL */
/*@observer@*/ /*@null@*/ const char * argDescrip; /*!< argument description for autohelp */
};
/** \ingroup popt
* A popt alias argument for poptAddAlias().
*/
struct poptAlias {
/*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */
char shortName; /* may be '\0' */
/*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */
char shortName; /*!< may be '\0' */
int argc;
/*@owned@*/ const char ** argv; /* must be free()able */
/*@owned@*/ const char ** argv; /*!< must be free()able */
};
/** \ingroup popt
* A popt alias or exec argument for poptAddItem().
*/
typedef struct poptItem_s {
struct poptOption option; /*!< alias/exec name(s) and description. */
int argc; /*!< (alias) no. of args. */
/*@owned@*/ const char ** argv; /*!< (alias) args, must be free()able. */
} * poptItem;
/** \ingroup popt
* \name Auto-generated help/usage
*/
/*@{*/
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@observer@*/ /*@checked@*/
extern struct poptOption poptAliasOptions[];
#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
0, "Options implemented via popt alias/exec:", NULL },
/**
* Auto help table options.
*/
/*@observer@*/ /*@checked@*/
extern struct poptOption poptHelpOptions[];
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options", NULL },
0, "Help options:", NULL },
typedef struct poptContext_s * poptContext;
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
/*@}*/
/** \ingroup popt
*/
typedef /*@abstract@*/ struct poptContext_s * poptContext;
/** \ingroup popt
*/
#ifndef __cplusplus
/*@-typeuse@*/
typedef struct poptOption * poptOption;
/*@=typeuse@*/
#endif
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
POPT_CALLBACK_REASON_POST,
POPT_CALLBACK_REASON_OPTION };
typedef void (*poptCallbackType)(poptContext con,
enum poptCallbackReason reason,
const struct poptOption * opt,
const char * arg, const void * data);
/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name,
int argc, /*@keep@*/ const char ** argv,
/*@keep@*/ const struct poptOption * options, int flags);
void poptResetContext(poptContext con);
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con);
/* returns NULL if no argument is available */
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con);
/* returns NULL if no more options are available */
/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con);
/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con);
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con);
/* returns the option which caused the most recent error */
/*@observer@*/ const char * poptBadOption(poptContext con, int flags);
void poptFreeContext( /*@only@*/ poptContext con);
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv);
int poptAddAlias(poptContext con, struct poptAlias alias, int flags);
int poptReadConfigFile(poptContext con, const char * fn);
/* like above, but reads /etc/popt and $HOME/.popt along with environment
vars */
int poptReadDefaultConfig(poptContext con, int useEnv);
/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated
the same as " and both may include \ quotes */
int poptDupArgv(int argc, const char **argv,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
#ifdef __cplusplus
extern "C" {
#endif
/*@-type@*/
/** \ingroup popt
* Table callback prototype.
* @param con context
* @param reason reason for callback
* @param opt option that triggered callback
* @param arg @todo Document.
* @param data @todo Document.
*/
typedef void (*poptCallbackType) (poptContext con,
enum poptCallbackReason reason,
/*@null@*/ const struct poptOption * opt,
/*@null@*/ const char * arg,
/*@null@*/ const void * data)
/*@*/;
/** \ingroup popt
* Initialize popt context.
* @param name
* @param argc no. of arguments
* @param argv argument array
* @param options address of popt option table
* @param flags or'd POPT_CONTEXT_* bits
* @return initialized popt context
*/
/*@only@*/ /*@null@*/ poptContext poptGetContext(
/*@dependent@*/ /*@keep@*/ const char * name,
int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
/*@dependent@*/ /*@keep@*/ const struct poptOption * options,
int flags)
/*@*/;
/** \ingroup popt
* Reinitialize popt context.
* @param con context
*/
void poptResetContext(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return value of next option found.
* @param con context
* @return next option val, -1 on last item, POPT_ERROR_* on error
*/
int poptGetNextOpt(/*@null@*/poptContext con)
/*@globals fileSystem@*/
/*@modifies con, fileSystem @*/;
/*@-redecl@*/
/** \ingroup popt
* Return next option argument (if any).
* @param con context
* @return option argument, NULL if no more options are available
*/
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return current option's argument.
* @param con context
* @return option argument, NULL if no more options are available
*/
/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Peek at current option's argument.
* @param con context
* @return option argument
*/
/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
/*@*/;
/** \ingroup popt
* Return remaining arguments.
* @param con context
* @return argument array, terminated with NULL
*/
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Return the option which caused the most recent error.
* @param con context
* @return offending option
*/
/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags)
/*@*/;
/*@=redecl@*/
/** \ingroup popt
* Destroy context.
* @param con context
* @return NULL always
*/
/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
/*@modifies con @*/;
/** \ingroup popt
* Add arguments to context.
* @param con context
* @param argv argument array, NULL terminated
* @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
*/
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
/*@modifies con @*/;
/** \ingroup popt
* Add alias to context.
* @todo Pass alias by reference, not value.
* @deprecated Use poptAddItem instead.
* @param con context
* @param alias alias to add
* @param flags (unused)
* @return 0 on success
*/
/*@unused@*/
int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
/*@modifies con @*/;
/** \ingroup popt
* Add alias/exec item to context.
* @param con context
* @param item alias/exec item to add
* @param flags 0 for alias, 1 for exec
* @return 0 on success
*/
int poptAddItem(poptContext con, poptItem newItem, int flags)
/*@modifies con @*/;
/** \ingroup popt
* Read configuration file.
* @param con context
* @param fn file name to read
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
int poptReadConfigFile(poptContext con, const char * fn)
/*@globals fileSystem@*/
/*@modifies fileSystem,
con->execs, con->numExecs @*/;
/** \ingroup popt
* Read default configuration from /etc/popt and $HOME/.popt.
* @param con context
* @param useEnv (unused)
* @return 0 on success, POPT_ERROR_ERRNO on failure
*/
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
/*@globals fileSystem@*/
/*@modifies fileSystem,
con->execs, con->numExecs @*/;
/** \ingroup popt
* Duplicate an argument array.
* @note: The argument array is malloc'd as a single area, so only argv must
* be free'd.
*
* @param argc no. of arguments
* @param argv argument array
* @retval argcPtr address of returned no. of arguments
* @retval argvPtr address of returned argument array
* @return 0 on success, POPT_ERROR_NOARG on failure
*/
int poptDupArgv(int argc, /*@null@*/ const char **argv,
/*@null@*/ /*@out@*/ int * argcPtr,
/*@null@*/ /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
/** \ingroup popt
* Parse a string into an argument array.
* The parse allows ', ", and \ quoting, but ' is treated the same as " and
* both may include \ quotes.
* @note: The argument array is malloc'd as a single area, so only argv must
* be free'd.
*
* @param s string to parse
* @retval argcPtr address of returned no. of arguments
* @retval argvPtr address of returned argument array
*/
int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
/*@observer@*/ const char *const poptStrerror(const int error);
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
void poptPrintHelp(poptContext con, FILE * f, int flags);
void poptPrintUsage(poptContext con, FILE * f, int flags);
void poptSetOtherOptionHelp(poptContext con, const char * text);
/*@observer@*/ const char * poptGetInvocationName(poptContext con);
/* shuffles argv pointers to remove stripped args, returns new argc */
int poptStrippedArgv(poptContext con, int argc, char **argv);
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
/*@modifies *argcPtr, *argvPtr @*/;
/** \ingroup popt
* Return formatted error string for popt failure.
* @param error popt error
* @return error string
*/
/*@-redecl@*/
/*@observer@*/ const char *const poptStrerror(const int error)
/*@*/;
/*@=redecl@*/
/** \ingroup popt
* Limit search for executables.
* @param con context
* @param path single path to search for executables
* @param allowAbsolute absolute paths only?
*/
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
/*@modifies con @*/;
/** \ingroup popt
* Print detailed description of options.
* @param con context
* @param fp ouput file handle
* @param flags (unused)
*/
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/;
/** \ingroup popt
* Print terse description of options.
* @param con context
* @param fp ouput file handle
* @param flags (unused)
*/
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/;
/** \ingroup popt
* Provide text to replace default "[OPTION...]" in help/usage output.
* @param con context
* @param text replacement text
*/
/*@-fcnuse@*/
void poptSetOtherOptionHelp(poptContext con, const char * text)
/*@modifies con @*/;
/*@=fcnuse@*/
/** \ingroup popt
* Return argv[0] from context.
* @param con context
* @return argv[0]
*/
/*@-redecl -fcnuse@*/
/*@observer@*/ const char * poptGetInvocationName(poptContext con)
/*@*/;
/*@=redecl =fcnuse@*/
/** \ingroup popt
* Shuffle argv pointers to remove stripped args, returns new argc.
* @param con context
* @param argc no. of args
* @param argv arg vector
* @return new argc
*/
/*@-fcnuse@*/
int poptStrippedArgv(poptContext con, int argc, char ** argv)
/*@modifies *argv @*/;
/*@=fcnuse@*/
/*@=type@*/
#ifdef __cplusplus
}
#endif
......
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/poptconfig.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
static void configLine(poptContext con, char * line) {
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
static void configLine(poptContext con, char * line)
/*@modifies con @*/
{
/*@-type@*/
int nameLength = strlen(con->appName);
char * opt;
struct poptAlias alias;
char * entryType;
char * longName = NULL;
char shortName = '\0';
/*@=type@*/
const char * entryType;
const char * opt;
poptItem item = alloca(sizeof(*item));
int i, j;
memset(item, 0, sizeof(*item));
/*@-type@*/
if (strncmp(line, con->appName, nameLength)) return;
/*@=type@*/
line += nameLength;
if (!*line || !isspace(*line)) return;
while (*line && isspace(*line)) line++;
entryType = line;
if (*line == '\0' || !isspace(*line)) return;
while (!*line || !isspace(*line)) line++;
while (*line != '\0' && isspace(*line)) line++;
entryType = line;
while (*line == '\0' || !isspace(*line)) line++;
*line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
opt = line;
while (!*line || !isspace(*line)) line++;
while (*line != '\0' && isspace(*line)) line++;
if (*line == '\0') return;
opt = line;
while (*line == '\0' || !isspace(*line)) line++;
*line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
while (*line != '\0' && isspace(*line)) line++;
if (*line == '\0') return;
/*@-temptrans@*/ /* FIX: line alias is saved */
if (opt[0] == '-' && opt[1] == '-')
longName = opt + 2;
else if (opt[0] == '-' && !opt[2])
shortName = opt[1];
if (!strcmp(entryType, "alias")) {
if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
alias.longName = longName, alias.shortName = shortName;
poptAddAlias(con, alias, 0);
} else if (!strcmp(entryType, "exec")) {
con->execs = realloc(con->execs,
sizeof(*con->execs) * (con->numExecs + 1));
if (longName)
con->execs[con->numExecs].longName = xstrdup(longName);
else
con->execs[con->numExecs].longName = NULL;
con->execs[con->numExecs].shortName = shortName;
con->execs[con->numExecs].script = xstrdup(line);
con->numExecs++;
item->option.longName = opt + 2;
else if (opt[0] == '-' && opt[2] == '\0')
item->option.shortName = opt[1];
/*@=temptrans@*/
if (poptParseArgvString(line, &item->argc, &item->argv)) return;
/*@-modobserver@*/
item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
for (i = 0, j = 0; i < item->argc; i++, j++) {
const char * f;
if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
f = item->argv[i] + sizeof("--POPTdesc=");
if (f[0] == '$' && f[1] == '"') f++;
item->option.descrip = f;
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
j--;
} else
if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
f = item->argv[i] + sizeof("--POPTargs=");
if (f[0] == '$' && f[1] == '"') f++;
item->option.argDescrip = f;
item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
item->option.argInfo |= POPT_ARG_STRING;
j--;
} else
if (j != i)
item->argv[j] = item->argv[i];
}
if (j != i) {
item->argv[j] = NULL;
item->argc = j;
}
/*@=modobserver@*/
/*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
if (!strcmp(entryType, "alias"))
(void) poptAddItem(con, item, 0);
else if (!strcmp(entryType, "exec"))
(void) poptAddItem(con, item, 1);
/*@=nullstate@*/
}
/*@=compmempass@*/
int poptReadConfigFile(poptContext con, const char * fn) {
char * file=NULL, * chptr, * end;
char * buf=NULL, * dst;
int poptReadConfigFile(poptContext con, const char * fn)
{
const char * file, * chptr, * end;
char * buf;
/*@dependent@*/ char * dst;
int fd, rc;
int fileLength;
off_t fileLength;
fd = open(fn, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return 0;
else
return POPT_ERROR_ERRNO;
}
if (fd < 0)
return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
fileLength = lseek(fd, 0, SEEK_END);
(void) lseek(fd, 0, 0);
if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
rc = errno;
(void) close(fd);
/*@-mods@*/
errno = rc;
/*@=mods@*/
return POPT_ERROR_ERRNO;
}
file = malloc(fileLength + 1);
if (read(fd, file, fileLength) != fileLength) {
file = alloca(fileLength + 1);
if (read(fd, (char *)file, fileLength) != fileLength) {
rc = errno;
close(fd);
(void) close(fd);
/*@-mods@*/
errno = rc;
if (file) free(file);
/*@=mods@*/
return POPT_ERROR_ERRNO;
}
close(fd);
if (close(fd) == -1)
return POPT_ERROR_ERRNO;
dst = buf = malloc(fileLength + 1);
dst = buf = alloca(fileLength + 1);
chptr = file;
end = (file + fileLength);
/*@-infloops@*/ /* LCL: can't detect chptr++ */
while (chptr < end) {
switch (*chptr) {
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isspace(*dst)) dst++;
if (*dst && *dst != '#') {
if (*dst && *dst != '#')
configLine(con, dst);
}
chptr++;
break;
/*@switchbreak@*/ break;
case '\\':
*dst++ = *chptr++;
if (chptr < end) {
......@@ -105,15 +148,13 @@ int poptReadConfigFile(poptContext con, const char * fn) {
else
*dst++ = *chptr++;
}
break;
/*@switchbreak@*/ break;
default:
*dst++ = *chptr++;
break;
/*@switchbreak@*/ break;
}
}
free(file);
free(buf);
/*@=infloops@*/
return 0;
}
......@@ -122,21 +163,21 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
char * fn, * home;
int rc;
/*@-type@*/
if (!con->appName) return 0;
/*@=type@*/
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
if (getuid() != geteuid()) return 0;
if ((home = getenv("HOME"))) {
fn = malloc(strlen(home) + 20);
fn = alloca(strlen(home) + 20);
strcpy(fn, home);
strcat(fn, "/.popt");
rc = poptReadConfigFile(con, fn);
free(fn);
if (rc) return rc;
}
return 0;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/*@-type@*/
/** \ingroup popt
* \file popt/popthelp.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
/**
* @param con context
* @param key option(s)
*/
static void displayArgs(poptContext con,
/*@unused@*/ enum poptCallbackReason foo,
struct poptOption * key,
/*@unused@*/ const char * arg, /*@unused@*/ void * data) {
if (key->shortName== '?')
/*@unused@*/ const char * arg, /*@unused@*/ void * data)
/*@globals fileSystem@*/
/*@modifies fileSystem@*/
{
if (key->shortName == '?')
poptPrintHelp(con, stdout, 0);
else
poptPrintUsage(con, stdout, 0);
exit(0);
}
#ifdef NOTYET
/*@unchecked@*/
static int show_option_defaults = 0;
#endif
/**
* Empty table marker to enable displaying popt alias/exec options.
*/
/*@observer@*/ /*@unchecked@*/
struct poptOption poptAliasOptions[] = {
POPT_TABLEEND
};
/**
* Auto help table options.
*/
/*@-castfcnptr@*/
/*@observer@*/ /*@unchecked@*/
struct poptOption poptHelpOptions[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
#ifdef NOTYET
{ "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
N_("Display option defaults in message"), NULL },
#endif
POPT_TABLEEND
} ;
/*@=castfcnptr@*/
/**
* @param table option(s)
*/
/*@observer@*/ /*@null@*/ static const char *const
getTableTranslationDomain(const struct poptOption *table)
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
/*@*/
{
const struct poptOption *opt;
for(opt = table;
opt->longName || opt->shortName || opt->arg;
opt++) {
if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
return opt->arg;
}
const struct poptOption *opt;
return NULL;
if (table != NULL)
for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
return opt->arg;
}
return NULL;
}
/**
* @param opt option(s)
* @param translation_domain translation domain
*/
/*@observer@*/ /*@null@*/ static const char *const
getArgDescrip(const struct poptOption * opt, const char *translation_domain)
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: wazzup? */
/*@null@*/ const char * translation_domain)
/*@=paramuse@*/
/*@*/
{
if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
......@@ -50,45 +94,224 @@ getArgDescrip(const struct poptOption * opt, const char *translation_domain)
if (opt->argDescrip) return POPT_(opt->argDescrip);
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
return POPT_("ARG");
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE: return POPT_("NONE");
case POPT_ARG_VAL: return POPT_("VAL");
case POPT_ARG_INT: return POPT_("INT");
case POPT_ARG_LONG: return POPT_("LONG");
case POPT_ARG_STRING: return POPT_("STRING");
case POPT_ARG_FLOAT: return POPT_("FLOAT");
case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
default: return POPT_("ARG");
}
}
/**
* @param opt option(s)
* @param translation_domain translation domain
*/
static /*@only@*/ /*@null@*/ char *
singleOptionDefaultValue(int lineLength,
const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
/*@null@*/ const char * translation_domain)
/*@=paramuse@*/
/*@*/
{
const char * defstr = D_(translation_domain, "default");
char * le = malloc(4*lineLength + 1);
char * l = le;
if (le == NULL) return NULL; /* XXX can't happen */
*le = '\0';
*le++ = '(';
strcpy(le, defstr); le += strlen(le);
*le++ = ':';
*le++ = ' ';
if (opt->arg) /* XXX programmer error */
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_VAL:
case POPT_ARG_INT:
{ long aLong = *((int *)opt->arg);
le += sprintf(le, "%ld", aLong);
} break;
case POPT_ARG_LONG:
{ long aLong = *((long *)opt->arg);
le += sprintf(le, "%ld", aLong);
} break;
case POPT_ARG_FLOAT:
{ double aDouble = *((float *)opt->arg);
le += sprintf(le, "%g", aDouble);
} break;
case POPT_ARG_DOUBLE:
{ double aDouble = *((double *)opt->arg);
le += sprintf(le, "%g", aDouble);
} break;
case POPT_ARG_STRING:
{ const char * s = *(const char **)opt->arg;
if (s == NULL) {
strcpy(le, "null"); le += strlen(le);
} else {
size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
*le++ = '"';
strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
if (slen < strlen(s)) {
strcpy(le, "..."); le += strlen(le);
}
*le++ = '"';
}
} break;
case POPT_ARG_NONE:
default:
l = _free(l);
return NULL;
/*@notreached@*/ break;
}
*le++ = ')';
*le = '\0';
return l;
}
static void singleOptionHelp(FILE * f, int maxLeftCol,
const struct poptOption * opt,
const char *translation_domain) {
/**
* @param fp output file handle
* @param opt option(s)
* @param translation_domain translation domain
*/
static void singleOptionHelp(FILE * fp, int maxLeftCol,
const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip);
const char * argDescrip = getArgDescrip(opt, translation_domain);
int helpLength;
const char * ch;
char format[10];
char * defs = NULL;
char * left;
const char * argDescrip = getArgDescrip(opt, translation_domain);
int nb = maxLeftCol + 1;
/* Make sure there's more than enough room in target buffer. */
if (opt->longName) nb += strlen(opt->longName);
if (argDescrip) nb += strlen(argDescrip);
left = malloc(maxLeftCol + 1);
*left = '\0';
left = malloc(nb);
if (left == NULL) return; /* XXX can't happen */
left[0] = '\0';
left[maxLeftCol] = '\0';
if (opt->longName && opt->shortName)
sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
else if (opt->shortName)
sprintf(left, "-%c, %s%s", opt->shortName,
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
else if (opt->shortName != '\0')
sprintf(left, "-%c", opt->shortName);
else if (opt->longName)
sprintf(left, "--%s", opt->longName);
if (!*left) return ;
sprintf(left, "%s%s",
((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
opt->longName);
if (!*left) goto out;
if (argDescrip) {
strcat(left, "=");
strcat(left, argDescrip);
char * le = left + strlen(left);
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
*le++ = '[';
/* Choose type of output */
/*@-branchstate@*/
if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) {
defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
if (defs) {
char * t = malloc((help ? strlen(help) : 0) +
strlen(defs) + sizeof(" "));
if (t) {
char * te = t;
*te = '\0';
if (help) {
strcpy(te, help); te += strlen(te);
}
*te++ = ' ';
strcpy(te, defs);
defs = _free(defs);
}
defs = t;
}
}
/*@=branchstate@*/
if (opt->argDescrip == NULL) {
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE:
break;
case POPT_ARG_VAL:
{ long aLong = opt->val;
int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
/* Don't bother displaying typical values */
if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
break;
*le++ = '[';
switch (ops) {
case POPT_ARGFLAG_OR:
*le++ = '|';
/*@innerbreak@*/ break;
case POPT_ARGFLAG_AND:
*le++ = '&';
/*@innerbreak@*/ break;
case POPT_ARGFLAG_XOR:
*le++ = '^';
/*@innerbreak@*/ break;
default:
/*@innerbreak@*/ break;
}
*le++ = '=';
if (negate) *le++ = '~';
/*@-formatconst@*/
le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
/*@=formatconst@*/
*le++ = ']';
} break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
case POPT_ARG_FLOAT:
case POPT_ARG_DOUBLE:
case POPT_ARG_STRING:
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
break;
default:
break;
}
} else {
*le++ = '=';
strcpy(le, argDescrip); le += strlen(le);
}
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
*le++ = ']';
*le = '\0';
}
if (help)
fprintf(f," %-*s ", maxLeftCol, left);
fprintf(fp," %-*s ", maxLeftCol, left);
else {
fprintf(f," %s\n", left);
fprintf(fp," %s\n", left);
goto out;
}
left = _free(left);
if (defs) {
help = defs; defs = NULL;
}
helpLength = strlen(help);
while (helpLength > lineLength) {
const char * ch;
char format[10];
ch = help + lineLength - 1;
while (ch > help && !isspace(*ch)) ch--;
if (ch == help) break; /* give up */
......@@ -96,39 +319,56 @@ static void singleOptionHelp(FILE * f, int maxLeftCol,
ch++;
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
fprintf(f, format, help, " ");
/*@-formatconst@*/
fprintf(fp, format, help, " ");
/*@=formatconst@*/
help = ch;
while (isspace(*help) && *help) help++;
helpLength = strlen(help);
}
if (helpLength) fprintf(f, "%s\n", help);
if (helpLength) fprintf(fp, "%s\n", help);
out:
free(left);
/*@-dependenttrans@*/
defs = _free(defs);
/*@=dependenttrans@*/
left = _free(left);
}
/**
* @param opt option(s)
* @param translation_domain translation domain
*/
static int maxArgWidth(const struct poptOption * opt,
const char * translation_domain) {
/*@null@*/ const char * translation_domain)
/*@*/
{
int max = 0;
int this;
int len = 0;
const char * s;
if (opt != NULL)
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
this = maxArgWidth(opt->arg, translation_domain);
if (this > max) max = this;
if (opt->arg) /* XXX program error */
len = maxArgWidth(opt->arg, translation_domain);
if (len > max) max = len;
} else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
this = opt->shortName ? 2 : 0;
len = sizeof(" ")-1;
if (opt->shortName != '\0') len += sizeof("-X")-1;
if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1;
if (opt->longName) {
if (this) this += 2;
this += strlen(opt->longName) + 2;
len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
? sizeof("-")-1 : sizeof("--")-1);
len += strlen(opt->longName);
}
s = getArgDescrip(opt, translation_domain);
if (s)
this += strlen(s) + 1;
if (this > max) max = this;
len += sizeof("=")-1 + strlen(s);
if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
if (len > max) max = len;
}
opt++;
......@@ -137,77 +377,134 @@ static int maxArgWidth(const struct poptOption * opt,
return max;
}
static void singleTableHelp(FILE * f, const struct poptOption * table,
int left,
const char *translation_domain) {
/**
* Display popt alias and exec help.
* @param fp output file handle
* @param items alias/exec array
* @param nitems no. of alias/exec entries
* @param translation_domain translation domain
*/
static void itemHelp(FILE * fp,
/*@null@*/ poptItem items, int nitems, int left,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
poptItem item;
int i;
if (items != NULL)
for (i = 0, item = items; i < nitems; i++, item++) {
const struct poptOption * opt;
opt = &item->option;
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
singleOptionHelp(fp, left, opt, translation_domain);
}
}
/**
* @param fp output file handle
* @param table option(s)
* @param translation_domain translation domain
*/
static void singleTableHelp(poptContext con, FILE * fp,
/*@null@*/ const struct poptOption * table, int left,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
const struct poptOption * opt;
const char *sub_transdom;
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if (table == poptAliasOptions) {
itemHelp(fp, con->aliases, con->numAliases, left, NULL);
itemHelp(fp, con->execs, con->numExecs, left, NULL);
return;
}
if (table != NULL)
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
singleOptionHelp(f, left, opt, translation_domain);
opt++;
singleOptionHelp(fp, left, opt, translation_domain);
}
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
sub_transdom = getTableTranslationDomain(opt->arg);
if(!sub_transdom)
sub_transdom = translation_domain;
if (table != NULL)
for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE)
continue;
sub_transdom = getTableTranslationDomain(opt->arg);
if (sub_transdom == NULL)
sub_transdom = translation_domain;
if (opt->descrip)
fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
if (opt->descrip)
fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(f, opt->arg, left, sub_transdom);
}
opt++;
singleTableHelp(con, fp, opt->arg, left, sub_transdom);
}
}
static int showHelpIntro(poptContext con, FILE * f) {
/**
* @param con context
* @param fp output file handle
*/
static int showHelpIntro(poptContext con, FILE * fp)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int len = 6;
const char * fn;
fprintf(f, POPT_("Usage:"));
fprintf(fp, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
/*@-nullderef@*/ /* LCL: wazzup? */
fn = con->optionStack->argv[0];
if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
fprintf(f, " %s", fn);
/*@=nullderef@*/
if (fn == NULL) return len;
if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
fprintf(fp, " %s", fn);
len += strlen(fn) + 1;
}
return len;
}
void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) {
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
{
int leftColWidth;
showHelpIntro(con, f);
(void) showHelpIntro(con, fp);
if (con->otherHelp)
fprintf(f, " %s\n", con->otherHelp);
fprintf(fp, " %s\n", con->otherHelp);
else
fprintf(f, " %s\n", POPT_("[OPTION...]"));
fprintf(fp, " %s\n", POPT_("[OPTION...]"));
leftColWidth = maxArgWidth(con->options, NULL);
singleTableHelp(f, con->options, leftColWidth, NULL);
singleTableHelp(con, fp, con->options, leftColWidth, NULL);
}
static int singleOptionUsage(FILE * f, int cursor,
const struct poptOption * opt,
const char *translation_domain) {
/**
* @param fp output file handle
* @param opt option(s)
* @param translation_domain translation domain
*/
static int singleOptionUsage(FILE * fp, int cursor,
const struct poptOption * opt,
/*@null@*/ const char *translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int len = 3;
char shortStr[2] = { '\0', '\0' };
const char * item = shortStr;
const char * argDescrip = getArgDescrip(opt, translation_domain);
if (opt->shortName) {
if (opt->shortName!= '\0' ) {
if (!(opt->argInfo & POPT_ARG_MASK))
return cursor; /* we did these already */
len++;
*shortStr = opt->shortName;
shortStr[0] = opt->shortName;
shortStr[1] = '\0';
} else if (opt->longName) {
len += 1 + strlen(opt->longName);
......@@ -220,82 +517,140 @@ static int singleOptionUsage(FILE * f, int cursor,
len += strlen(argDescrip) + 1;
if ((cursor + len) > 79) {
fprintf(f, "\n ");
fprintf(fp, "\n ");
cursor = 7;
}
fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
argDescrip ? (opt->shortName ? " " : "=") : "",
argDescrip ? argDescrip : "");
fprintf(fp, " [-%s%s%s%s]",
((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
item,
(argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
(argDescrip ? argDescrip : ""));
return cursor + len + 1;
}
static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
const char *translation_domain) {
const struct poptOption * opt;
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
/**
* Display popt alias and exec usage.
* @param fp output file handle
* @param item alias/exec array
* @param nitems no. of ara/exec entries
* @param translation_domain translation domain
*/
static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
int i;
/*@-branchstate@*/ /* FIX: W2DO? */
if (item != NULL)
for (i = 0; i < nitems; i++, item++) {
const struct poptOption * opt;
opt = &item->option;
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
cursor = singleTableUsage(f, cursor, opt->arg,
translation_domain);
else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
cursor = singleOptionUsage(f, cursor, opt, translation_domain);
} else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
}
}
/*@=branchstate@*/
opt++;
return cursor;
}
/**
* @param fp output file handle
* @param opt option(s)
* @param translation_domain translation domain
*/
static int singleTableUsage(poptContext con, FILE * fp,
int cursor, const struct poptOption * opt,
/*@null@*/ const char * translation_domain)
/*@globals fileSystem @*/
/*@modifies *fp, fileSystem @*/
{
/*@-branchstate@*/ /* FIX: W2DO? */
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
if (opt->arg) /* XXX program error */
cursor = singleTableUsage(con, fp, cursor, opt->arg,
translation_domain);
} else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
}
}
/*@=branchstate@*/
return cursor;
}
static int showShortOptions(const struct poptOption * opt, FILE * f,
char * str) {
char s[300]; /* this is larger then the ascii set, so
it should do just fine */
/**
* Return concatenated short options for display.
* @param opt option(s)
* @param fp output file handle
* @retval str concatenation of short options
* @return length of display string
*/
static int showShortOptions(const struct poptOption * opt, FILE * fp,
/*@null@*/ char * str)
/*@globals fileSystem @*/
/*@modifies *str, *fp, fileSystem @*/
{
char * s = alloca(300); /* larger then the ascii set */
s[0] = '\0';
/*@-branchstate@*/ /* FIX: W2DO? */
if (str == NULL) {
memset(s, 0, sizeof(s));
str = s;
}
/*@=branchstate@*/
while (opt->longName || opt->shortName || opt->arg) {
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
str[strlen(str)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
showShortOptions(opt->arg, f, str);
opt++;
if (opt->arg) /* XXX program error */
(void) showShortOptions(opt->arg, fp, str);
}
if (s != str || !*s)
if (s != str || *s != '\0')
return 0;
fprintf(f, " [-%s]", s);
fprintf(fp, " [-%s]", s);
return strlen(s) + 4;
}
void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) {
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
{
int cursor;
cursor = showHelpIntro(con, f);
cursor += showShortOptions(con->options, f, NULL);
singleTableUsage(f, cursor, con->options, NULL);
cursor = showHelpIntro(con, fp);
cursor += showShortOptions(con->options, fp, NULL);
(void) singleTableUsage(con, fp, cursor, con->options, NULL);
(void) itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
(void) itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
if (con->otherHelp) {
cursor += strlen(con->otherHelp) + 1;
if (cursor > 79) fprintf(f, "\n ");
fprintf(f, " %s", con->otherHelp);
if (cursor > 79) fprintf(fp, "\n ");
fprintf(fp, " %s", con->otherHelp);
}
fprintf(f, "\n");
fprintf(fp, "\n");
}
void poptSetOtherOptionHelp(poptContext con, const char * text) {
if (con->otherHelp) xfree(con->otherHelp);
void poptSetOtherOptionHelp(poptContext con, const char * text)
{
con->otherHelp = _free(con->otherHelp);
con->otherHelp = xstrdup(text);
}
/*@=type@*/
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/poptint.h
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPTINT
#define H_POPTINT
/**
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
* @param p memory to free
* @retval NULL always
*/
/*@unused@*/ static inline /*@null@*/ void *
_free(/*@only@*/ /*@null@*/ const void * p)
/*@modifies p @*/
{
if (p != NULL) free((void *)p);
return NULL;
}
/* Bit mask macros. */
typedef unsigned int __pbm_bits;
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS))
#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
typedef struct {
__pbm_bits bits[1];
} pbm_set;
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
#define PBM_FREE(s) free(s);
#define PBM_FREE(s) _free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
struct optionStackEntry {
int argc;
/*@only@*/ const char ** argv;
/*@only@*/ pbm_set * argb;
/*@only@*/ /*@null@*/ const char ** argv;
/*@only@*/ /*@null@*/ pbm_set * argb;
int next;
/*@only@*/ const char * nextArg;
/*@keep@*/ const char * nextCharArg;
/*@dependent@*/ struct poptAlias * currAlias;
/*@only@*/ /*@null@*/ const char * nextArg;
/*@keep@*/ /*@null@*/ const char * nextCharArg;
/*@dependent@*/ /*@null@*/ poptItem currAlias;
int stuffed;
};
struct execEntry {
const char * longName;
char shortName;
const char * script;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/ struct optionStackEntry * os;
/*@owned@*/ const char ** leftovers;
/*@dependent@*/ struct optionStackEntry * os;
/*@owned@*/ /*@null@*/ const char ** leftovers;
int numLeftovers;
int nextLeftover;
/*@keep@*/ const struct poptOption * options;
/*@keep@*/ const struct poptOption * options;
int restLeftover;
/*@only@*/ const char * appName;
/*@only@*/ struct poptAlias * aliases;
/*@only@*/ /*@null@*/ const char * appName;
/*@only@*/ /*@null@*/ poptItem aliases;
int numAliases;
int flags;
struct execEntry * execs;
/*@owned@*/ /*@null@*/ poptItem execs;
int numExecs;
/*@only@*/ const char ** finalArgv;
/*@only@*/ /*@null@*/ const char ** finalArgv;
int finalArgvCount;
int finalArgvAlloced;
/*@dependent@*/ struct execEntry * doExec;
/*@only@*/ const char * execPath;
/*@dependent@*/ /*@null@*/ poptItem doExec;
/*@only@*/ const char * execPath;
int execAbsolute;
/*@only@*/ const char * otherHelp;
pbm_set * arg_strip;
/*@only@*/ const char * otherHelp;
/*@null@*/ pbm_set * arg_strip;
};
#define xfree(_a) free((void *)_a)
#ifdef HAVE_LIBINTL_H
#include <libintl.h>
#endif
......@@ -71,17 +80,17 @@ struct poptContext_s {
#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
#define _(foo) gettext(foo)
#else
#define _(foo) (foo)
#define _(foo) foo
#endif
#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else
#define POPT_(foo) (foo)
#define D_(dom, str) (str)
#define D_(dom, str) str
#define POPT_(foo) foo
#endif
#define N_(foo) (foo)
#define N_(foo) foo
#endif
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
/** \ingroup popt
* \file popt/poptparse.c
*/
/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
......@@ -14,6 +18,8 @@ int poptDupArgv(int argc, const char **argv,
char * dst;
int i;
if (argc <= 0 || argv == NULL) /* XXX can't happen */
return POPT_ERROR_NOARG;
for (i = 0; i < argc; i++) {
if (argv[i] == NULL)
return POPT_ERROR_NOARG;
......@@ -21,17 +27,27 @@ int poptDupArgv(int argc, const char **argv,
}
dst = malloc(nb);
if (dst == NULL) /* XXX can't happen */
return POPT_ERROR_MALLOC;
argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv);
/*@-branchstate@*/
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst += strlen(strcpy(dst, argv[i])) + 1;
}
/*@=branchstate@*/
argv2[argc] = NULL;
*argvPtr = argv2;
*argcPtr = argc;
if (argvPtr) {
*argvPtr = argv2;
} else {
free(argv2);
argv2 = NULL;
}
if (argcPtr)
*argcPtr = argc;
return 0;
}
......@@ -43,31 +59,32 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;
int buflen = strlen(s) + 1;
char *buf0 = calloc(buflen, 1);
char *buf = buf0;
char * buf = memset(alloca(buflen), 0, buflen);
int rc = POPT_ERROR_MALLOC;
if (argv == NULL) return rc;
argv[argc] = buf;
for (src = s; *src; src++) {
for (src = s; *src != '\0'; src++) {
if (quote == *src) {
quote = '\0';
} else if (quote) {
} else if (quote != '\0') {
if (*src == '\\') {
src++;
if (!*src) {
free(argv);
free(buf0);
return POPT_ERROR_BADQUOTE;
rc = POPT_ERROR_BADQUOTE;
goto exit;
}
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isspace(*src)) {
if (*argv[argc]) {
if (*argv[argc] != '\0') {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
if (argv == NULL) goto exit;
}
argv[argc] = buf;
}
......@@ -75,18 +92,17 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
case '"':
case '\'':
quote = *src;
break;
/*@switchbreak@*/ break;
case '\\':
src++;
if (!*src) {
free(argv);
free(buf0);
return POPT_ERROR_BADQUOTE;
rc = POPT_ERROR_BADQUOTE;
goto exit;
}
/*@fallthrough@*/
default:
*buf++ = *src;
break;
/*@switchbreak@*/ break;
}
}
......@@ -94,9 +110,9 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
argc++, buf++;
}
(void) poptDupArgv(argc, argv, argcPtr, argvPtr);
rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
free(argv);
free(buf0);
return 0;
exit:
if (argv) free(argv);
return rc;
}
......@@ -25,6 +25,14 @@
#include <libc.h>
#endif
#if defined(__LCLINT__)
/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
/*@only@*/ void * alloca (size_t __size)
/*@ensures MaxSet(result) == (__size - 1) @*/
/*@*/;
/*@=declundef =incondefs =redecl@*/
#endif
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
......@@ -42,7 +50,10 @@ char *alloca ();
#define alloca __builtin_alloca
#endif
/*@only@*/ char * xstrdup (const char *str);
/*@-redecl -redef@*/
/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
/*@*/;
/*@=redecl =redef@*/
#if HAVE_MCHECK_H && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment