- Upgraded popt to version 1.10.2.
authorWayne Davison <wayned@samba.org>
Thu, 9 Nov 2006 00:57:55 +0000 (00:57 +0000)
committerWayne Davison <wayned@samba.org>
Thu, 9 Nov 2006 00:57:55 +0000 (00:57 +0000)
- Modified all sprintf() and strcpy() calls to use snprintf()
  and strlcpy().

popt/findme.c
popt/popt.c
popt/popt.h
popt/poptconfig.c
popt/popthelp.c
popt/poptint.h
popt/poptparse.c
popt/system.h

index e98e0611b04aacab2ea254b4a9c95c3c10535b6d..ac4cbaed203a9c889c962a9429a4b075730bd645 100644 (file)
@@ -2,18 +2,20 @@
  * \file popt/findme.c
  */
 
-/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from 
    ftp://ftp.rpm.org/pub/rpm/dist. */
 
 #include "system.h"
 #include "findme.h"
 
-const char * findProgramPath(const char * argv0) {
+const char * findProgramPath(const char * argv0)
+{
     char * path = getenv("PATH");
     char * pathbuf;
     char * start, * chptr;
     char * buf;
+    size_t bufsize;
 
     if (argv0 == NULL) return NULL;    /* XXX can't happen */
     /* If there is a / in the argv[0], it has to be an absolute path */
@@ -22,17 +24,20 @@ const char * findProgramPath(const char * argv0) {
 
     if (path == NULL) return NULL;
 
-    start = pathbuf = alloca(strlen(path) + 1);
-    buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
+    bufsize = strlen(path) + 1;
+    start = pathbuf = alloca(bufsize);
+    if (pathbuf == NULL) return NULL;  /* XXX can't happen */
+    strlcpy(pathbuf, path, bufsize);
+    bufsize += sizeof "/" - 1 + strlen(argv0);
+    buf = malloc(bufsize);
     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);
+       snprintf(buf, bufsize, "%s/%s", start, argv0);
 
        if (!access(buf, X_OK))
            return buf;
index 9e0076938165eaabb653cc7e3ca80cbeafb11402..9ce3b35578b73a1eadc2db6cdf6224307b41ecda 100644 (file)
@@ -2,7 +2,7 @@
  * \file popt/popt.c
  */
 
-/* (C) 19982000 Red Hat, Inc. -- Licensing details are in the COPYING
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from
    ftp://ftp.rpm.org/pub/rpm/dist */
 
 #include "findme.h"
 #include "poptint.h"
 
-#ifndef HAVE_STRERROR
-static char * strerror(int errno) {
+#ifdef MYDEBUG
+/*@unchecked@*/
+int _popt_debug = 0;
+#endif
+
+#if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
+static char * strerror(int errno)
+{
     extern int sys_nerr;
     extern char * sys_errlist[];
 
@@ -31,7 +37,8 @@ static char * strerror(int errno) {
 #endif
 
 #ifdef MYDEBUG
-/*@unused@*/ static void prtcon(const char *msg, poptContext con)
+/*@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",
@@ -49,7 +56,7 @@ 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? */
+    /*@-nullstate@*/ /* LCL: con->execPath not NULL */
     return;
     /*@=nullstate@*/
 }
@@ -62,17 +69,22 @@ static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
     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) {
+           void * arg = opt->arg;
+/*@-branchstate@*/
+           /* XXX sick hack to preserve pretense of ABI. */
+           if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
+/*@=branchstate@*/
            /* Recurse on included sub-tables. */
-           invokeCallbacksPRE(con, opt->arg);
+           invokeCallbacksPRE(con, 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 @*/
+           /*@-noeffectuncon @*/
            cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
-           /*@=moduncon =noeffectuncon @*/
+           /*@=noeffectuncon @*/
        }
     }
 }
@@ -85,17 +97,22 @@ static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
     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) {
+           void * arg = opt->arg;
+/*@-branchstate@*/
+           /* XXX sick hack to preserve pretense of ABI. */
+           if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
+/*@=branchstate@*/
            /* Recurse on included sub-tables. */
-           invokeCallbacksPOST(con, opt->arg);
+           invokeCallbacksPOST(con, 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 @*/
+           /*@-noeffectuncon @*/
            cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
-           /*@=moduncon =noeffectuncon @*/
+           /*@=noeffectuncon @*/
        }
     }
 }
@@ -112,6 +129,11 @@ static void invokeCallbacksOPTION(poptContext con,
     if (opt != NULL)
     for (; opt->longName || opt->shortName || opt->arg; opt++) {
        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+           void * arg = opt->arg;
+/*@-branchstate@*/
+           /* XXX sick hack to preserve pretense of ABI. */
+           if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
+/*@=branchstate@*/
            /* Recurse on included sub-tables. */
            if (opt->arg != NULL)       /* XXX program error */
                invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
@@ -133,10 +155,10 @@ static void invokeCallbacksOPTION(poptContext con,
            const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
            /* Perform callback. */
            if (cb != NULL) {   /* XXX program error */
-               /*@-moduncon -noeffectuncon @*/
+               /*@-noeffectuncon @*/
                cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
                        con->os->nextArg, cbData);
-               /*@=moduncon =noeffectuncon @*/
+               /*@=noeffectuncon @*/
            }
            /* Terminate (unless explcitly continuing). */
            if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
@@ -181,8 +203,12 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
        con->flags |= POPT_CONTEXT_POSIXMEHARDER;
 
     if (name) {
-       char * t = malloc(strlen(name) + 1);
-       if (t) con->appName = strcpy(t, name);
+       size_t bufsize = strlen(name) + 1;
+       char * t = malloc(bufsize);
+       if (t) {
+           strlcpy(t, name, bufsize);
+           con->appName = t;
+       }
     }
 
     /*@-internalglobs@*/
@@ -202,6 +228,7 @@ static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
     os->argb = PBM_FREE(os->argb);
 }
 
+/*@-boundswrite@*/
 void poptResetContext(poptContext con)
 {
     int i;
@@ -222,10 +249,11 @@ void poptResetContext(poptContext con)
     con->doExec = NULL;
 
     if (con->finalArgv != NULL)
-    for (i = 0; i < con->finalArgvCount; i++)
+    for (i = 0; i < con->finalArgvCount; i++) {
        /*@-unqualifiedtrans@*/         /* FIX: typedef double indirection. */
        con->finalArgv[i] = _free(con->finalArgv[i]);
        /*@=unqualifiedtrans@*/
+    }
 
     con->finalArgvCount = 0;
     con->arg_strip = PBM_FREE(con->arg_strip);
@@ -233,8 +261,10 @@ void poptResetContext(poptContext con)
     return;
     /*@=nullstate@*/
 }
+/*@=boundswrite@*/
 
 /* Only one of longName, shortName should be set, not both. */
+/*@-boundswrite@*/
 static int handleExec(/*@special@*/ poptContext con,
                /*@null@*/ const char * longName, char shortName)
        /*@uses con->execs, con->numExecs, con->flags, con->doExec,
@@ -277,12 +307,13 @@ static int handleExec(/*@special@*/ poptContext con,
 
     i = con->finalArgvCount++;
     if (con->finalArgv != NULL)        /* XXX can't happen */
-    {  char *s  = malloc((longName ? strlen(longName) : 0) + 3);
+    {  size_t bufsize = (longName ? strlen(longName) : 0) + 3;
+       char *s  = malloc(bufsize);
        if (s != NULL) {        /* XXX can't happen */
            if (longName)
-               sprintf(s, "--%s", longName);
+               snprintf(s, bufsize, "--%s", longName);
            else
-               sprintf(s, "-%c", shortName);
+               snprintf(s, bufsize, "-%c", shortName);
            con->finalArgv[i] = s;
        } else
            con->finalArgv[i] = NULL;
@@ -292,11 +323,12 @@ static int handleExec(/*@special@*/ poptContext con,
     return 1;
     /*@=nullstate@*/
 }
+/*@=boundswrite@*/
 
 /* Only one of longName, shortName may be set at a time */
 static int handleAlias(/*@special@*/ poptContext con,
                /*@null@*/ const char * longName, char shortName,
-               /*@keep@*/ /*@null@*/ const char * nextCharArg)
+               /*@exposed@*/ /*@null@*/ const char * nextCharArg)
        /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
                con->os->currAlias, con->os->currAlias->option.longName @*/
        /*@modifies con @*/
@@ -330,8 +362,10 @@ static int handleAlias(/*@special@*/ poptContext con,
     if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
        return POPT_ERROR_OPTSTOODEEP;
 
+/*@-boundsread@*/
     if (nextCharArg && *nextCharArg)
        con->os->nextCharArg = nextCharArg;
+/*@=boundsread@*/
 
     con->os++;
     con->os->next = 0;
@@ -346,8 +380,10 @@ static int handleAlias(/*@special@*/ poptContext con,
     return (rc ? rc : 1);
 }
 
+/*@-bounds -boundswrite @*/
 static int execCommand(poptContext con)
-    /*@*/
+       /*@globals internalState @*/
+       /*@modifies internalState @*/
 {
     poptItem item = con->doExec;
     const char ** argv;
@@ -363,15 +399,15 @@ static int execCommand(poptContext con)
 
     argv = malloc(sizeof(*argv) *
                        (6 + item->argc + con->numLeftovers + con->finalArgvCount));
-    if (argv == NULL) return POPT_ERROR_MALLOC;        /* XXX can't happen */
+    if (argv == NULL) return POPT_ERROR_MALLOC;
 
-    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]);
+    if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
+       size_t bufsize = strlen(con->execPath) + strlen(item->argv[0]) + sizeof "/";
+       char *s = alloca(bufsize);
+       snprintf(s, bufsize, "%s/%s", con->execPath, item->argv[0]);
        argv[argc] = s;
-    } else {
+    } else
        argv[argc] = findProgramPath(item->argv[0]);
-    }
     if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
 
     if (item->argc > 1) {
@@ -386,9 +422,6 @@ static int execCommand(poptContext con)
     }
 
     if (con->leftovers != NULL && con->numLeftovers > 0) {
-#if 0
-       argv[argc++] = "--";
-#endif
        memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
        argc += con->numLeftovers;
     }
@@ -396,6 +429,8 @@ static int execCommand(poptContext con)
     argv[argc] = NULL;
 
 #ifdef __hpux
+    rc = setresgid(getgid(), getgid(),-1);
+    if (rc) return POPT_ERROR_ERRNO;
     rc = setresuid(getuid(), getuid(),-1);
     if (rc) return POPT_ERROR_ERRNO;
 #else
@@ -405,10 +440,14 @@ static int execCommand(poptContext con)
  * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
  */
 #if defined(HAVE_SETUID)
+    rc = setgid(getgid());
+    if (rc) return POPT_ERROR_ERRNO;
     rc = setuid(getuid());
     if (rc) return POPT_ERROR_ERRNO;
 #elif defined (HAVE_SETREUID)
-    rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
+    rc = setregid(getgid(), getgid());
+    if (rc) return POPT_ERROR_ERRNO;
+    rc = setreuid(getuid(), getuid());
     if (rc) return POPT_ERROR_ERRNO;
 #else
     ; /* Can't drop privileges */
@@ -417,7 +456,9 @@ static int execCommand(poptContext con)
 
     if (argv[0] == NULL)
        return POPT_ERROR_NOARG;
-#ifdef MYDEBUG
+
+#ifdef MYDEBUG
+if (_popt_debug)
     {  const char ** avp;
        fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
        for (avp = argv; *avp; avp++)
@@ -427,9 +468,12 @@ static int execCommand(poptContext con)
 #endif
 
     rc = execvp(argv[0], (char *const *)argv);
+
     return POPT_ERROR_ERRNO;
 }
+/*@=bounds =boundswrite @*/
 
+/*@-boundswrite@*/
 /*@observer@*/ /*@null@*/ static const struct poptOption *
 findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
                char shortName,
@@ -448,10 +492,15 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
 
        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
            const struct poptOption * opt2;
+           void * arg = opt->arg;
 
+/*@-branchstate@*/
+           /* XXX sick hack to preserve pretense of ABI. */
+           if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
+/*@=branchstate@*/
            /* Recurse on included sub-tables. */
-           if (opt->arg == NULL) continue;     /* XXX program error */
-           opt2 = findOption(opt->arg, longName, shortName, callback,
+           if (arg == NULL) continue;  /* XXX program error */
+           opt2 = findOption(arg, longName, shortName, callback,
                              callbackData, singleDash);
            if (opt2 == NULL) continue;
            /* Sub-table data will be inheirited if no data yet. */
@@ -496,6 +545,7 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
 
     return opt;
 }
+/*@=boundswrite@*/
 
 static const char * findNextArg(/*@special@*/ poptContext con,
                unsigned argx, int delete_arg)
@@ -534,6 +584,7 @@ static const char * findNextArg(/*@special@*/ poptContext con,
     return arg;
 }
 
+/*@-boundswrite@*/
 static /*@only@*/ /*@null@*/ const char *
 expandNextArg(/*@special@*/ poptContext con, const char * s)
        /*@uses con->optionStack, con->os,
@@ -541,7 +592,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
        /*@modifies con @*/
 {
     const char * a = NULL;
-    size_t alen;
+    size_t alen, pos;
     char *t, *te;
     size_t tn = strlen(s) + 1;
     char c;
@@ -567,9 +618,9 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
 
            alen = strlen(a);
            tn += alen;
-           *te = '\0';
+           pos = te - t;
            t = realloc(t, tn);
-           te = t + strlen(t);
+           te = t + pos;
            strncpy(te, a, alen); te += alen;
            continue;
            /*@notreached@*/ /*@switchbreak@*/ break;
@@ -582,6 +633,7 @@ expandNextArg(/*@special@*/ poptContext con, const char * s)
     t = realloc(t, strlen(t) + 1);     /* XXX memory leak, hard to plug */
     return t;
 }
+/*@=boundswrite@*/
 
 static void poptStripArg(/*@special@*/ poptContext con, int which)
        /*@uses con->arg_strip, con->optionStack @*/
@@ -599,26 +651,26 @@ static void poptStripArg(/*@special@*/ poptContext con, int which)
     /*@=compdef@*/
 }
 
-static int poptSaveLong(const struct poptOption * opt, long aLong)
-       /*@modifies opt->arg @*/
+int poptSaveLong(long * arg, int argInfo, long aLong)
 {
-    if (opt->arg == NULL)
+    /* XXX Check alignment, may fail on funky platforms. */
+    if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
        return POPT_ERROR_NULLARG;
 
-    if (opt->argInfo & POPT_ARGFLAG_NOT)
+    if (argInfo & POPT_ARGFLAG_NOT)
        aLong = ~aLong;
-    switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
+    switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
     case 0:
-       *((long *) opt->arg) = aLong;
+       *arg = aLong;
        break;
     case POPT_ARGFLAG_OR:
-       *((long *) opt->arg) |= aLong;
+       *arg |= aLong;
        break;
     case POPT_ARGFLAG_AND:
-       *((long *) opt->arg) &= aLong;
+       *arg &= aLong;
        break;
     case POPT_ARGFLAG_XOR:
-       *((long *) opt->arg) ^= aLong;
+       *arg ^= aLong;
        break;
     default:
        return POPT_ERROR_BADOPERATION;
@@ -627,26 +679,26 @@ static int poptSaveLong(const struct poptOption * opt, long aLong)
     return 0;
 }
 
-static int poptSaveInt(const struct poptOption * opt, long aLong)
-       /*@modifies opt->arg @*/
+int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
 {
-    if (opt->arg == NULL)
+    /* XXX Check alignment, may fail on funky platforms. */
+    if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
        return POPT_ERROR_NULLARG;
 
-    if (opt->argInfo & POPT_ARGFLAG_NOT)
+    if (argInfo & POPT_ARGFLAG_NOT)
        aLong = ~aLong;
-    switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
+    switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
     case 0:
-       *((int *) opt->arg) = aLong;
+       *arg = aLong;
        break;
     case POPT_ARGFLAG_OR:
-       *((int *) opt->arg) |= aLong;
+       *arg |= aLong;
        break;
     case POPT_ARGFLAG_AND:
-       *((int *) opt->arg) &= aLong;
+       *arg &= aLong;
        break;
     case POPT_ARGFLAG_XOR:
-       *((int *) opt->arg) ^= aLong;
+       *arg ^= aLong;
        break;
     default:
        return POPT_ERROR_BADOPERATION;
@@ -655,6 +707,7 @@ static int poptSaveInt(const struct poptOption * opt, long aLong)
     return 0;
 }
 
+/*@-boundswrite@*/
 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
 int poptGetNextOpt(poptContext con)
 {
@@ -714,8 +767,12 @@ int poptGetNextOpt(poptContext con)
            }
 
            /* Make a copy we can hack at */
-           localOptString = optString =
-               strcpy(alloca(strlen(origOptString) + 1), origOptString);
+           {   size_t bufsize = strlen(origOptString) + 1;
+               localOptString = optString = alloca(bufsize);
+               if (optString == NULL) /* XXX can't happen */
+                   return POPT_ERROR_BADOPT;
+               strlcpy(optString, origOptString, bufsize);
+           }
 
            if (optString[0] == '\0')
                return POPT_ERROR_BADOPT;
@@ -800,11 +857,11 @@ int poptGetNextOpt(poptContext con)
 
        if (opt == NULL) return POPT_ERROR_BADOPT;      /* XXX can't happen */
        if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
-           if (poptSaveInt(opt, 1L))
+           if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
                return POPT_ERROR_BADOPERATION;
        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
            if (opt->arg) {
-               if (poptSaveInt(opt, (long)opt->val))
+               if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
                    return POPT_ERROR_BADOPERATION;
            }
        } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
@@ -873,12 +930,12 @@ int poptGetNextOpt(poptContext con)
                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
                        if (aLong == LONG_MIN || aLong == LONG_MAX)
                            return POPT_ERROR_OVERFLOW;
-                       if (poptSaveLong(opt, aLong))
+                       if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
                            return POPT_ERROR_BADOPERATION;
                    } else {
                        if (aLong > INT_MAX || aLong < INT_MIN)
                            return POPT_ERROR_OVERFLOW;
-                       if (poptSaveInt(opt, aLong))
+                       if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
                            return POPT_ERROR_BADOPERATION;
                    }
                }   /*@switchbreak@*/ break;
@@ -904,13 +961,10 @@ int poptGetNextOpt(poptContext con)
                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
                        *((double *) opt->arg) = aDouble;
                    } else {
-#ifndef DBL_EPSILON
-#define DBL_EPSILON 2.2204460492503131e-16
-#endif
-#define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
-                       if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
+#define _ABS(a)        ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
+                       if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
                            return POPT_ERROR_OVERFLOW;
-                       if ((FLT_MIN - MY_ABS(aDouble)) > DBL_EPSILON)
+                       if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON)
                            return POPT_ERROR_OVERFLOW;
                        *((float *) opt->arg) = aDouble;
                    }
@@ -939,14 +993,15 @@ int poptGetNextOpt(poptContext con)
        }
 
        if (con->finalArgv != NULL)
-       {   char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
+       {   ssize_t bufsize = (opt->longName ? strlen(opt->longName) : 0) + 3;
+           char *s = malloc(bufsize);
            if (s != NULL) {    /* XXX can't happen */
                if (opt->longName)
-                   sprintf(s, "%s%s",
+                   snprintf(s, bufsize, "%s%s",
                        ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
                        opt->longName);
                else
-                   sprintf(s, "-%c", opt->shortName);
+                   snprintf(s, bufsize, "-%c", opt->shortName);
                con->finalArgv[con->finalArgvCount++] = s;
            } else
                con->finalArgv[con->finalArgvCount++] = NULL;
@@ -967,6 +1022,7 @@ int poptGetNextOpt(poptContext con)
 
     return (opt ? opt->val : -1);      /* XXX can't happen */
 }
+/*@=boundswrite@*/
 
 const char * poptGetOptArg(poptContext con)
 {
@@ -996,6 +1052,7 @@ const char * poptPeekArg(poptContext con)
     return ret;
 }
 
+/*@-boundswrite@*/
 const char ** poptGetArgs(poptContext con)
 {
     if (con == NULL ||
@@ -1009,6 +1066,7 @@ const char ** poptGetArgs(poptContext con)
     return (con->leftovers + con->nextLeftover);
     /*@=nullret =nullstate @*/
 }
+/*@=boundswrite@*/
 
 poptContext poptFreeContext(poptContext con)
 {
@@ -1071,6 +1129,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias,
     return poptAddItem(con, item, 0);
 }
 
+/*@-boundswrite@*/
 /*@-mustmod@*/ /* LCL: con not modified? */
 int poptAddItem(poptContext con, poptItem newItem, int flags)
 {
@@ -1115,6 +1174,7 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
     return 0;
 }
 /*@=mustmod@*/
+/*@=boundswrite@*/
 
 const char * poptBadOption(poptContext con, int flags)
 {
@@ -1184,6 +1244,7 @@ const char * poptGetInvocationName(poptContext con)
     return (con->os->argv ? con->os->argv[0] : "");
 }
 
+/*@-boundswrite@*/
 int poptStrippedArgv(poptContext con, int argc, char ** argv)
 {
     int numargs = argc;
@@ -1207,3 +1268,4 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
     
     return numargs;
 }
+/*@=boundswrite@*/
index 06978f3df6463833fdd818362369ebf626550e60..4f85d9e3e802b488f7f4b49a451963f1112ad4f0 100644 (file)
 /** \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 NUL */
     int argInfo;
-/*@shared@*/ /*@null@*/ void * arg;    /*!< depends on argInfo */
+/*@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 */
+/*@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 NUL */
     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().
  */
+/*@-exporttype@*/
 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. */
+/*@owned@*/
+    const char ** argv;                /*!< (alias) args, must be free()able. */
 } * poptItem;
+/*@=exporttype@*/
 
 /** \ingroup popt
  * \name Auto-generated help/usage
@@ -148,16 +157,26 @@ typedef struct poptItem_s {
 /**
  * Empty table marker to enable displaying popt alias/exec options.
  */
-/*@observer@*/ /*@checked@*/
+/*@-exportvar@*/
+/*@unchecked@*/ /*@observer@*/
 extern struct poptOption poptAliasOptions[];
+/*@=exportvar@*/
 #define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
                        0, "Options implemented via popt alias/exec:", NULL },
 
 /**
  * Auto help table options.
  */
-/*@observer@*/ /*@checked@*/
+/*@-exportvar@*/
+/*@unchecked@*/ /*@observer@*/
 extern struct poptOption poptHelpOptions[];
+/*@=exportvar@*/
+
+/*@-exportvar@*/
+/*@unchecked@*/ /*@observer@*/
+extern struct poptOption * poptHelpOptionsI18N;
+/*@=exportvar@*/
+
 #define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
                        0, "Help options:", NULL },
 
@@ -166,19 +185,25 @@ extern struct poptOption poptHelpOptions[];
 
 /** \ingroup popt
  */
+/*@-exporttype@*/
 typedef /*@abstract@*/ struct poptContext_s * poptContext;
+/*@=exporttype@*/
 
 /** \ingroup popt
  */
 #ifndef __cplusplus
-/*@-typeuse@*/
+/*@-exporttype -typeuse@*/
 typedef struct poptOption * poptOption;
-/*@=typeuse@*/
+/*@=exporttype =typeuse@*/
 #endif
 
-enum poptCallbackReason { POPT_CALLBACK_REASON_PRE, 
-                         POPT_CALLBACK_REASON_POST,
-                         POPT_CALLBACK_REASON_OPTION };
+/*@-exportconst@*/
+enum poptCallbackReason {
+    POPT_CALLBACK_REASON_PRE   = 0, 
+    POPT_CALLBACK_REASON_POST  = 1,
+    POPT_CALLBACK_REASON_OPTION = 2
+};
+/*@=exportconst@*/
 
 #ifdef __cplusplus
 extern "C" {
@@ -198,18 +223,20 @@ typedef void (*poptCallbackType) (poptContext con,
                /*@null@*/ const struct poptOption * opt,
                /*@null@*/ const char * arg,
                /*@null@*/ const void * data)
-       /*@*/;
+       /*@globals internalState @*/
+       /*@modifies internalState @*/;
 
 /** \ingroup popt
  * Initialize popt context.
- * @param name
+ * @param name         context name (usually argv[0] program 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(
+/*@only@*/ /*@null@*/
+poptContext poptGetContext(
                /*@dependent@*/ /*@keep@*/ const char * name,
                int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
                /*@dependent@*/ /*@keep@*/ const struct poptOption * options,
@@ -220,6 +247,7 @@ typedef void (*poptCallbackType) (poptContext con,
  * Reinitialize popt context.
  * @param con          context
  */
+/*@unused@*/
 void poptResetContext(/*@null@*/poptContext con)
        /*@modifies con @*/;
 
@@ -229,57 +257,62 @@ void poptResetContext(/*@null@*/poptContext con)
  * @return             next option val, -1 on last item, POPT_ERROR_* on error
  */
 int poptGetNextOpt(/*@null@*/poptContext con)
-       /*@globals fileSystem@*/
-       /*@modifies con, fileSystem @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies con, fileSystem, internalState @*/;
 
-/*@-redecl@*/
 /** \ingroup popt
  * Return next option argument (if any).
  * @param con          context
- * @return             option argument, NULL if no more options are available
+ * @return             option argument, NULL if no argument is available
  */
-/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
+/*@observer@*/ /*@null@*/ /*@unused@*/
+const char * poptGetOptArg(/*@null@*/poptContext con)
        /*@modifies con @*/;
 
 /** \ingroup popt
- * Return current option's argument.
+ * Return next argument.
  * @param con          context
- * @return             option argument, NULL if no more options are available
+ * @return             next argument, NULL if no argument is available
  */
-/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
+/*@observer@*/ /*@null@*/ /*@unused@*/
+const char * poptGetArg(/*@null@*/poptContext con)
        /*@modifies con @*/;
 
 /** \ingroup popt
- * Peek at current option's argument.
+ * Peek at current argument.
  * @param con          context
- * @return             option argument
+ * @return             current argument, NULL if no argument is available
  */
-/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
+/*@observer@*/ /*@null@*/ /*@unused@*/
+const char * poptPeekArg(/*@null@*/poptContext con)
        /*@*/;
 
 /** \ingroup popt
  * Return remaining arguments.
  * @param con          context
- * @return             argument array, terminated with NULL
+ * @return             argument array, NULL terminated
  */
-/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
+/*@observer@*/ /*@null@*/
+const char ** poptGetArgs(/*@null@*/poptContext con)
        /*@modifies con @*/;
 
 /** \ingroup popt
  * Return the option which caused the most recent error.
  * @param con          context
+ * @param flags
  * @return             offending option
  */
-/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags)
+/*@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)
+/*@null@*/
+poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
        /*@modifies con @*/;
 
 /** \ingroup popt
@@ -288,6 +321,7 @@ int poptGetNextOpt(/*@null@*/poptContext con)
  * @param argv         argument array, NULL terminated
  * @return             0 on success, POPT_ERROR_OPTSTOODEEP on failure
  */
+/*@unused@*/
 int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
        /*@modifies con @*/;
 
@@ -307,7 +341,7 @@ int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
 /** \ingroup popt
  * Add alias/exec item to context.
  * @param con          context
- * @param item         alias/exec item to add
+ * @param newItem      alias/exec item to add
  * @param flags                0 for alias, 1 for exec
  * @return             0 on success
  */
@@ -321,9 +355,9 @@ int poptAddItem(poptContext con, poptItem newItem, int flags)
  * @return             0 on success, POPT_ERROR_ERRNO on failure
  */
 int poptReadConfigFile(poptContext con, const char * fn)
-       /*@globals fileSystem@*/
-       /*@modifies fileSystem,
-               con->execs, con->numExecs @*/;
+       /*@globals errno, fileSystem, internalState @*/
+       /*@modifies con->execs, con->numExecs,
+               errno, fileSystem, internalState @*/;
 
 /** \ingroup popt
  * Read default configuration from /etc/popt and $HOME/.popt.
@@ -331,10 +365,11 @@ int poptReadConfigFile(poptContext con, const char * fn)
  * @param useEnv       (unused)
  * @return             0 on success, POPT_ERROR_ERRNO on failure
  */
+/*@unused@*/
 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
-       /*@globals fileSystem@*/
-       /*@modifies fileSystem,
-               con->execs, con->numExecs @*/;
+       /*@globals fileSystem, internalState @*/
+       /*@modifies con->execs, con->numExecs,
+               fileSystem, internalState @*/;
 
 /** \ingroup popt
  * Duplicate an argument array.
@@ -363,19 +398,70 @@ int poptDupArgv(int argc, /*@null@*/ const char **argv,
  * @retval argcPtr     address of returned no. of arguments
  * @retval argvPtr     address of returned argument array
  */
-int poptParseArgvString(const unsigned char * s,
+int poptParseArgvString(const char * s,
                /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
        /*@modifies *argcPtr, *argvPtr @*/;
 
+/** \ingroup popt
+ * Parses an input configuration file and returns an string that is a 
+ * command line.  For use with popt.  You must free the return value when done.
+ *
+ * Given the file:
+\verbatim
+# this line is ignored
+    #   this one too
+aaa
+  bbb
+    ccc   
+bla=bla
+
+this_is   =   fdsafdas
+     bad_line=        
+  reall bad line  
+  reall bad line  = again
+5555=   55555   
+  test = with lots of spaces
+\endverbatim
+*
+* The result is:
+\verbatim
+--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces"
+\endverbatim
+*
+* Passing this to poptParseArgvString() yields an argv of:
+\verbatim
+'--aaa'
+'--bbb' 
+'--ccc' 
+'--bla=bla' 
+'--this_is=fdsafdas' 
+'--5555=55555' 
+'--test=with lots of spaces' 
+\endverbatim
+ *
+ * @bug NULL is returned if file line is too long.
+ * @bug Silently ignores invalid lines.
+ *
+ * @param fp           file handle to read
+ * @param *argstrp     return string of options (malloc'd)
+ * @param flags                unused
+ * @return             0 on success
+ * @see                        poptParseArgvString
+ */
+/*@-fcnuse@*/
+int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
+       /*@globals fileSystem @*/
+       /*@modifies *fp, *argstrp, fileSystem @*/;
+/*@=fcnuse@*/
+
 /** \ingroup popt
  * Return formatted error string for popt failure.
  * @param error                popt error
  * @return             error string
  */
-/*@-redecl@*/
-/*@observer@*/ const char * poptStrerror(const int error)
+/*@observer@*/
+const char * poptStrerror(const int error)
        /*@*/;
-/*@=redecl@*/
 
 /** \ingroup popt
  * Limit search for executables.
@@ -383,6 +469,7 @@ int poptParseArgvString(const unsigned char * s,
  * @param path         single path to search for executables
  * @param allowAbsolute        absolute paths only?
  */
+/*@unused@*/
 void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
        /*@modifies con @*/;
 
@@ -421,10 +508,11 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
  * @param con          context
  * @return             argv[0]
  */
-/*@-redecl -fcnuse@*/
-/*@observer@*/ const char * poptGetInvocationName(poptContext con)
+/*@-fcnuse@*/
+/*@observer@*/
+const char * poptGetInvocationName(poptContext con)
        /*@*/;
-/*@=redecl =fcnuse@*/
+/*@=fcnuse@*/
 
 /** \ingroup popt
  * Shuffle argv pointers to remove stripped args, returns new argc.
@@ -438,6 +526,36 @@ int poptStrippedArgv(poptContext con, int argc, char ** argv)
        /*@modifies *argv @*/;
 /*@=fcnuse@*/
 
+/**
+ * Save a long, performing logical operation with value.
+ * @warning Alignment check may be too strict on certain platorms.
+ * @param arg          integer pointer, aligned on int boundary.
+ * @param argInfo      logical operation (see POPT_ARGFLAG_*)
+ * @param aLong                value to use
+ * @return             0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
+ */
+/*@-incondefs@*/
+/*@unused@*/
+int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
+       /*@modifies *arg @*/
+       /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
+/*@=incondefs@*/
+
+/**
+ * Save an integer, performing logical operation with value.
+ * @warning Alignment check may be too strict on certain platorms.
+ * @param arg          integer pointer, aligned on int boundary.
+ * @param argInfo      logical operation (see POPT_ARGFLAG_*)
+ * @param aLong                value to use
+ * @return             0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
+ */
+/*@-incondefs@*/
+/*@unused@*/
+int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
+       /*@modifies *arg @*/
+       /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
+/*@=incondefs@*/
+
 /*@=type@*/
 #ifdef  __cplusplus
 }
index 50235661216bf25f39309ccb647cdee07a75e1fd..63c3ee292f44cff7ff841eb674491528a03f6374 100644 (file)
@@ -2,30 +2,32 @@
  * \file popt/poptconfig.c
  */
 
-/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from 
    ftp://ftp.rpm.org/pub/rpm/dist. */
 
 #include "system.h"
 #include "poptint.h"
+/*@access poptContext @*/
 
 /*@-compmempass@*/     /* FIX: item->option.longName kept, not dependent. */
-static void configLine(poptContext con, unsigned char * line)
+static void configLine(poptContext con, char * line)
        /*@modifies con @*/
 {
-    /*@-type@*/
-    int nameLength = strlen(con->appName);
-    /*@=type@*/
+    size_t nameLength;
     const char * entryType;
     const char * opt;
     poptItem item = (poptItem) alloca(sizeof(*item));
     int i, j;
+
+    if (con->appName == NULL)
+       return;
+    nameLength = strlen(con->appName);
     
+/*@-boundswrite@*/
     memset(item, 0, sizeof(*item));
 
-    /*@-type@*/
     if (strncmp(line, con->appName, nameLength)) return;
-    /*@=type@*/
 
     line += nameLength;
     if (*line == '\0' || !isspace(*line)) return;
@@ -80,6 +82,7 @@ static void configLine(poptContext con, unsigned char * line)
        item->argc = j;
     }
     /*@=modobserver@*/
+/*@=boundswrite@*/
        
     /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
     if (!strcmp(entryType, "alias"))
@@ -92,9 +95,9 @@ static void configLine(poptContext con, unsigned char * line)
 
 int poptReadConfigFile(poptContext con, const char * fn)
 {
-    const unsigned char * file, * chptr, * end;
-    unsigned char * buf;
-/*@dependent@*/ unsigned char * dst;
+    const char * file, * chptr, * end;
+    char * buf;
+/*@dependent@*/ char * dst;
     int fd, rc;
     off_t fileLength;
 
@@ -106,9 +109,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
     if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
        rc = errno;
        (void) close(fd);
-       /*@-mods@*/
        errno = rc;
-       /*@=mods@*/
        return POPT_ERROR_ERRNO;
     }
 
@@ -116,14 +117,13 @@ int poptReadConfigFile(poptContext con, const char * fn)
     if (read(fd, (char *)file, fileLength) != fileLength) {
        rc = errno;
        (void) close(fd);
-       /*@-mods@*/
        errno = rc;
-       /*@=mods@*/
        return POPT_ERROR_ERRNO;
     }
     if (close(fd) == -1)
        return POPT_ERROR_ERRNO;
 
+/*@-boundswrite@*/
     dst = buf = alloca(fileLength + 1);
 
     chptr = file;
@@ -155,6 +155,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
        }
     }
     /*@=infloops@*/
+/*@=boundswrite@*/
 
     return 0;
 }
@@ -164,18 +165,16 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
     char * fn, * home;
     int rc;
 
-    /*@-type@*/
-    if (!con->appName) return 0;
-    /*@=type@*/
+    if (con->appName == NULL) return 0;
 
     rc = poptReadConfigFile(con, "/etc/popt");
     if (rc) return rc;
-    if (getuid() != geteuid()) return 0;
 
     if ((home = getenv("HOME"))) {
-       fn = alloca(strlen(home) + 20);
-       strcpy(fn, home);
-       strcat(fn, "/.popt");
+       size_t bufsize = strlen(home) + 20;
+       fn = alloca(bufsize);
+       if (fn == NULL) return 0;
+       snprintf(fn, bufsize, "%s/.popt", home);
        rc = poptReadConfigFile(con, fn);
        if (rc) return rc;
     }
index 07020370f55112de2ace2edcf148171f8ed9a663..eb735ffba27611eeca21091aa28cfeda6bd615b9 100644 (file)
@@ -1,20 +1,31 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
-/*@-type@*/
 /** \ingroup popt
  * \file popt/popthelp.c
  */
 
-/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from 
    ftp://ftp.rpm.org/pub/rpm/dist. */
 
 #include "system.h"
+
+#define        POPT_WCHAR_HACK
+#ifdef         POPT_WCHAR_HACK
+#include <wchar.h>                     /* for mbsrtowcs */
+/*@access mbstate_t @*/
+#endif
 #include "poptint.h"
 
+/*@access poptContext@*/
+
 /**
+ * Display arguments.
  * @param con          context
+ * @param foo          (unused)
  * @param key          option(s)
+ * @param arg          (unused)
+ * @param data         (unused)
  */
 static void displayArgs(poptContext con,
                /*@unused@*/ UNUSED(enum poptCallbackReason foo),
@@ -49,6 +60,17 @@ struct poptOption poptAliasOptions[] = {
 /*@-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 },
+    POPT_TABLEEND
+} ;
+
+/*@observer@*/ /*@unchecked@*/
+static struct poptOption poptHelpOptions2[] = {
+/*@-readonlytrans@*/
+  { NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL},
+/*@=readonlytrans@*/
   { 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 },
@@ -58,6 +80,9 @@ struct poptOption poptHelpOptions[] = {
 #endif
     POPT_TABLEEND
 } ;
+
+/*@observer@*/ /*@unchecked@*/
+struct poptOption * poptHelpOptionsI18N = poptHelpOptions2;
 /*@=castfcnptr@*/
 
 /**
@@ -83,7 +108,7 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
  */
 /*@observer@*/ /*@null@*/ static const char *
 getArgDescrip(const struct poptOption * opt,
-               /*@-paramuse@*/         /* FIX: wazzup? */
+               /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
                /*@null@*/ UNUSED(const char * translation_domain))
                /*@=paramuse@*/
        /*@*/
@@ -97,7 +122,11 @@ getArgDescrip(const struct poptOption * opt,
 
     switch (opt->argInfo & POPT_ARG_MASK) {
     case POPT_ARG_NONE:                return POPT_("NONE");
+#ifdef DYING
     case POPT_ARG_VAL:         return POPT_("VAL");
+#else
+    case POPT_ARG_VAL:         return NULL;
+#endif
     case POPT_ARG_INT:         return POPT_("INT");
     case POPT_ARG_LONG:                return POPT_("LONG");
     case POPT_ARG_STRING:      return POPT_("STRING");
@@ -108,61 +137,65 @@ getArgDescrip(const struct poptOption * opt,
 }
 
 /**
+ * Display default value for an option.
+ * @param lineLength   display positions remaining
  * @param opt          option(s)
  * @param translation_domain   translation domain
+ * @return
  */
 static /*@only@*/ /*@null@*/ char *
-singleOptionDefaultValue(int lineLength,
+singleOptionDefaultValue(size_t lineLength,
                const struct poptOption * opt,
-               /*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
+               /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
                /*@null@*/ UNUSED(const char * translation_domain))
                /*@=paramuse@*/
        /*@*/
 {
     const char * defstr = D_(translation_domain, "default");
-    char * le = malloc(4*lineLength + 1);
+    size_t limit, bufsize = 4*lineLength + 1;
+    char * le = malloc(bufsize);
     char * l = le;
 
     if (le == NULL) return NULL;       /* XXX can't happen */
-    *le = '\0';
+/*@-boundswrite@*/
     *le++ = '(';
-    strcpy(le, defstr);        le += strlen(le);
+    le += strlcpy(le, defstr, bufsize - 3);
     *le++ = ':';
     *le++ = ' ';
+    limit = bufsize - (le - l) - 1; /* -1 for closing paren */
     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);
-       sprintf(le, "%ld", aLong);
-       le += strlen(le);
+       le += snprintf(le, limit, "%ld", aLong);
     }  break;
     case POPT_ARG_LONG:
     {  long aLong = *((long *)opt->arg);
-       sprintf(le, "%ld", aLong);
-       le += strlen(le);
+       le += snprintf(le, limit, "%ld", aLong);
     }  break;
     case POPT_ARG_FLOAT:
     {  double aDouble = *((float *)opt->arg);
-       sprintf(le, "%g", aDouble);
-       le += strlen(le);
+       le += snprintf(le, limit, "%g", aDouble);
     }  break;
     case POPT_ARG_DOUBLE:
     {  double aDouble = *((double *)opt->arg);
-       sprintf(le, "%g", aDouble);
-       le += strlen(le);
+       le += snprintf(le, limit, "%g", aDouble);
     }  break;
     case POPT_ARG_STRING:
     {  const char * s = *(const char **)opt->arg;
        if (s == NULL) {
-           strcpy(le, "null"); le += strlen(le);
+           le += strlcpy(le, "null", limit);
        } else {
-           size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
+           size_t len;
+           limit -= 2; /* make room for quotes */
            *le++ = '"';
-           strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);    
-           if (slen < strlen(s)) {
-               strcpy(le, "...");      le += strlen(le);
-           }
+           len = strlcpy(le, s, limit);
+           if (len >= limit) {
+               le += limit - 3 - 1;
+               *le++ = '.'; *le++ = '.'; *le++ = '.';
+           } else
+               le += len;
            *le++ = '"';
        }
     }  break;
@@ -174,50 +207,57 @@ singleOptionDefaultValue(int lineLength,
     }
     *le++ = ')';
     *le = '\0';
+/*@=boundswrite@*/
 
     return l;
 }
 
 /**
+ * Display help text for an option.
  * @param fp           output file handle
+ * @param maxLeftCol   largest argument display width
  * @param opt          option(s)
  * @param translation_domain   translation domain
  */
-static void singleOptionHelp(FILE * fp, int maxLeftCol, 
+static void singleOptionHelp(FILE * fp, size_t maxLeftCol, 
                const struct poptOption * opt,
-               /*@null@*/ const char * translation_domain)
+               /*@null@*/ UNUSED(const char * translation_domain))
        /*@globals fileSystem @*/
        /*@modifies *fp, fileSystem @*/
 {
-    int indentLength = maxLeftCol + 5;
-    int lineLength = 79 - indentLength;
-    const unsigned char * help = D_(translation_domain, opt->descrip);
+    size_t indentLength = maxLeftCol + 5;
+    size_t lineLength = 79 - indentLength;
+    const char * help = D_(translation_domain, opt->descrip);
     const char * argDescrip = getArgDescrip(opt, translation_domain);
-    int helpLength;
-    unsigned char * defs = NULL;
-    unsigned char * left;
-    int nb = maxLeftCol + 1;
+    size_t helpLength;
+    char * defs = NULL;
+    char * left;
+    size_t lelen, limit;
+    size_t nb = maxLeftCol + 1;
+    int displaypad = 0;
 
     /* Make sure there's more than enough room in target buffer. */
     if (opt->longName) nb += strlen(opt->longName);
     if (argDescrip)    nb += strlen(argDescrip);
 
+/*@-boundswrite@*/
     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%s", opt->shortName,
+       snprintf(left, nb, "-%c, %s%s", opt->shortName,
                ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
                opt->longName);
     else if (opt->shortName != '\0') 
-       sprintf(left, "-%c", opt->shortName);
+       snprintf(left, nb, "-%c", opt->shortName);
     else if (opt->longName)
-       sprintf(left, "%s%s",
+       snprintf(left, nb, "%s%s",
                ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
                opt->longName);
     if (!*left) goto out;
+
     if (argDescrip) {
        char * le = left + strlen(left);
 
@@ -229,16 +269,10 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
        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(" "));
+               size_t bufsize = (help ? strlen(help) : 0) + sizeof " " + strlen(defs);
+               char * t = malloc(bufsize);
                if (t) {
-                   char * te = t;
-                   *te = '\0';
-                   if (help) {
-                       strcpy(te, help);       te += strlen(te);
-                   }
-                   *te++ = ' ';
-                   strcpy(te, defs);
+                   snprintf(t, bufsize, "%s %s", help ? help : "", defs);
                    defs = _free(defs);
                }
                defs = t;
@@ -251,6 +285,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
            case POPT_ARG_NONE:
                break;
            case POPT_ARG_VAL:
+#ifdef NOTNOW  /* XXX pug ugly nerdy output */
            {   long aLong = opt->val;
                int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
                int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
@@ -272,50 +307,78 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
                default:
                    /*@innerbreak@*/ break;
                }
-               *le++ = '=';
+               *le++ = (opt->longName != NULL ? '=' : ' ');
                if (negate) *le++ = '~';
                /*@-formatconst@*/
-               sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
-               le += strlen(le);
+               limit = nb - (le - left);
+               lelen = snprintf(le, limit, (ops ? "0x%lx" : "%ld"), aLong);
+               le += lelen >= limit ? limit - 1 : lelen;
                /*@=formatconst@*/
                *le++ = ']';
-           }   break;
+           }
+#endif
+               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);
+               *le++ = (opt->longName != NULL ? '=' : ' ');
+               limit = nb - (le - left);
+               lelen = strlcpy(le, argDescrip, limit);
+               le += lelen >= limit ? limit - 1 : lelen;
                break;
            default:
                break;
            }
        } else {
+
            *le++ = '=';
-           strcpy(le, argDescrip);             le += strlen(le);
+           limit = nb - (le - left);
+           lelen = strlcpy(le, argDescrip, limit);
+           if (lelen >= limit)
+               lelen = limit - 1;
+           le += lelen;
+
+#ifdef POPT_WCHAR_HACK
+           {   const char * scopy = argDescrip;
+               mbstate_t t;
+               size_t n;
+
+               memset ((void *)&t, '\0', sizeof (t));  /* In initial state.  */
+               /* Determine number of characters.  */
+               n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
+
+               displaypad = (int) (lelen-n);
+           }
+#endif
        }
        if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
            *le++ = ']';
        *le = '\0';
     }
+/*@=boundswrite@*/
 
     if (help)
-       fprintf(fp,"  %-*s   ", maxLeftCol, left);
+       fprintf(fp,"  %-*s   ", maxLeftCol+displaypad, left);
     else {
        fprintf(fp,"  %s\n", left); 
        goto out;
     }
 
     left = _free(left);
+/*@-branchstate@*/
     if (defs) {
-       help = defs; defs = NULL;
+       help = defs;
+       defs = NULL;
     }
+/*@=branchstate@*/
 
     helpLength = strlen(help);
+/*@-boundsread@*/
     while (helpLength > lineLength) {
-       const unsigned char * ch;
-       char format[10];
+       const char * ch;
+       char format[16];
 
        ch = help + lineLength - 1;
        while (ch > help && !isspace(*ch)) ch--;
@@ -323,7 +386,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
        while (ch > (help + 1) && isspace(*ch)) ch--;
        ch++;
 
-       sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
+       snprintf(format, sizeof format, "%%.%ds\n%%%ds", (int) (ch - help), (int) indentLength);
        /*@-formatconst@*/
        fprintf(fp, format, help, " ");
        /*@=formatconst@*/
@@ -331,6 +394,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
        while (isspace(*help) && *help) help++;
        helpLength = strlen(help);
     }
+/*@=boundsread@*/
 
     if (helpLength) fprintf(fp, "%s\n", help);
 
@@ -342,15 +406,17 @@ out:
 }
 
 /**
+ * Find display width for longest argument string.
  * @param opt          option(s)
  * @param translation_domain   translation domain
+ * @return             display width
  */
-static int maxArgWidth(const struct poptOption * opt,
-                      /*@null@*/ const char * translation_domain)
+static size_t maxArgWidth(const struct poptOption * opt,
+                      /*@null@*/ UNUSED(const char * translation_domain))
        /*@*/
 {
-    int max = 0;
-    int len = 0;
+    size_t max = 0;
+    size_t len = 0;
     const char * s;
     
     if (opt != NULL)
@@ -370,8 +436,26 @@ static int maxArgWidth(const struct poptOption * opt,
            }
 
            s = getArgDescrip(opt, translation_domain);
+
+#ifdef POPT_WCHAR_HACK
+           /* XXX Calculate no. of display characters. */
+           if (s) {
+               const char * scopy = s;
+               mbstate_t t;
+               size_t n;
+
+/*@-boundswrite@*/
+               memset ((void *)&t, '\0', sizeof (t));  /* In initial state.  */
+/*@=boundswrite@*/
+               /* Determine number of characters.  */
+               n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
+               len += sizeof("=")-1 + n;
+           }
+#else
            if (s)
                len += sizeof("=")-1 + strlen(s);
+#endif
+
            if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
            if (len > max) max = len;
        }
@@ -387,11 +471,12 @@ static int maxArgWidth(const struct poptOption * opt,
  * @param fp           output file handle
  * @param items                alias/exec array
  * @param nitems       no. of alias/exec entries
+ * @param left         largest argument display width
  * @param translation_domain   translation domain
  */
 static void itemHelp(FILE * fp,
-               /*@null@*/ poptItem items, int nitems, int left,
-               /*@null@*/ const char * translation_domain)
+               /*@null@*/ poptItem items, int nitems, size_t left,
+               /*@null@*/ UNUSED(const char * translation_domain))
        /*@globals fileSystem @*/
        /*@modifies *fp, fileSystem @*/
 {
@@ -409,13 +494,16 @@ static void itemHelp(FILE * fp,
 }
 
 /**
+ * Display help text for a table of options.
+ * @param con          context
  * @param fp           output file handle
  * @param table                option(s)
+ * @param left         largest argument display width
  * @param translation_domain   translation domain
  */
 static void singleTableHelp(poptContext con, FILE * fp,
-               /*@null@*/ const struct poptOption * table, int left,
-               /*@null@*/ const char * translation_domain)
+               /*@null@*/ const struct poptOption * table, size_t left,
+               /*@null@*/ UNUSED(const char * translation_domain))
        /*@globals fileSystem @*/
        /*@modifies *fp, fileSystem @*/
 {
@@ -463,9 +551,11 @@ static int showHelpIntro(poptContext con, FILE * fp)
 
     fprintf(fp, POPT_("Usage:"));
     if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
-       /*@-nullderef@*/        /* LCL: wazzup? */
+/*@-boundsread@*/
+       /*@-nullderef -type@*/  /* LCL: wazzup? */
        fn = con->optionStack->argv[0];
-       /*@=nullderef@*/
+       /*@=nullderef =type@*/
+/*@=boundsread@*/
        if (fn == NULL) return len;
        if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
        fprintf(fp, " %s", fn);
@@ -477,7 +567,7 @@ static int showHelpIntro(poptContext con, FILE * fp)
 
 void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
 {
-    int leftColWidth;
+    size_t leftColWidth;
 
     (void) showHelpIntro(con, fp);
     if (con->otherHelp)
@@ -490,47 +580,76 @@ void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
 }
 
 /**
+ * Display usage text for an option.
  * @param fp           output file handle
+ * @param cursor       current display position
  * @param opt          option(s)
  * @param translation_domain   translation domain
  */
-static int singleOptionUsage(FILE * fp, int cursor, 
+static size_t singleOptionUsage(FILE * fp, size_t cursor, 
                const struct poptOption * opt,
                /*@null@*/ const char *translation_domain)
        /*@globals fileSystem @*/
        /*@modifies *fp, fileSystem @*/
 {
-    int len = 3;
+    size_t len = 4;
     char shortStr[2] = { '\0', '\0' };
     const char * item = shortStr;
     const char * argDescrip = getArgDescrip(opt, translation_domain);
 
-    if (opt->shortName!= '\0' ) {
-       if (!(opt->argInfo & POPT_ARG_MASK)) 
-           return cursor;      /* we did these already */
+    if (opt->shortName != '\0' && opt->longName != NULL) {
+       len += 2;
+       if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
+       len += strlen(opt->longName);
+    } else if (opt->shortName != '\0') {
        len++;
        shortStr[0] = opt->shortName;
        shortStr[1] = '\0';
     } else if (opt->longName) {
-       len += 1 + strlen(opt->longName);
+       len += strlen(opt->longName);
+       if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
        item = opt->longName;
     }
 
-    if (len == 3) return cursor;
+    if (len == 4) return cursor;
 
+#ifdef POPT_WCHAR_HACK
+    /* XXX Calculate no. of display characters. */
+    if (argDescrip) {
+       const char * scopy = argDescrip;
+       mbstate_t t;
+       size_t n;
+
+/*@-boundswrite@*/
+       memset ((void *)&t, '\0', sizeof (t));  /* In initial state.  */
+/*@=boundswrite@*/
+       /* Determine number of characters.  */
+       n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t);
+       len += sizeof("=")-1 + n;
+    }
+#else
     if (argDescrip) 
-       len += strlen(argDescrip) + 1;
+       len += sizeof("=")-1 + strlen(argDescrip);
+#endif
 
     if ((cursor + len) > 79) {
        fprintf(fp, "\n       ");
        cursor = 7;
     } 
 
-    fprintf(fp, " [-%s%s%s%s]",
-       ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
-       item,
-       (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
-       (argDescrip ? argDescrip : ""));
+    if (opt->longName && opt->shortName) {
+       fprintf(fp, " [-%c|-%s%s%s%s]",
+           opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
+           opt->longName,
+           (argDescrip ? " " : ""),
+           (argDescrip ? argDescrip : ""));
+    } else {
+       fprintf(fp, " [-%s%s%s%s]",
+           ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
+           item,
+           (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
+           (argDescrip ? argDescrip : ""));
+    }
 
     return cursor + len + 1;
 }
@@ -538,12 +657,14 @@ static int singleOptionUsage(FILE * fp, int cursor,
 /**
  * Display popt alias and exec usage.
  * @param fp           output file handle
+ * @param cursor       current display position
  * @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)
+static size_t itemUsage(FILE * fp, size_t cursor,
+               /*@null@*/ poptItem item, int nitems,
+               /*@null@*/ UNUSED(const char * translation_domain))
        /*@globals fileSystem @*/
        /*@modifies *fp, fileSystem @*/
 {
@@ -567,15 +688,30 @@ static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
 }
 
 /**
+ * Keep track of option tables already processed.
+ */
+typedef struct poptDone_s {
+    int nopts;
+    int maxopts;
+    const void ** opts;
+} * poptDone;
+
+/**
+ * Display usage text for a table of options.
+ * @param con          context
  * @param fp           output file handle
+ * @param cursor       current display position
  * @param opt          option(s)
  * @param translation_domain   translation domain
+ * @param done         tables already processed
+ * @return
  */
-static int singleTableUsage(poptContext con, FILE * fp,
-               int cursor, const struct poptOption * opt,
-               /*@null@*/ const char * translation_domain)
+static size_t singleTableUsage(poptContext con, FILE * fp, size_t cursor,
+               /*@null@*/ const struct poptOption * opt,
+               /*@null@*/ UNUSED(const char * translation_domain),
+               /*@null@*/ poptDone done)
        /*@globals fileSystem @*/
-       /*@modifies *fp, fileSystem @*/
+       /*@modifies *fp, done, fileSystem @*/
 {
     /*@-branchstate@*/         /* FIX: W2DO? */
     if (opt != NULL)
@@ -583,9 +719,26 @@ static int singleTableUsage(poptContext con, FILE * fp,
         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 */
+           if (done) {
+               int i = 0;
+               for (i = 0; i < done->nopts; i++) {
+/*@-boundsread@*/
+                   const void * that = done->opts[i];
+/*@=boundsread@*/
+                   if (that == NULL || that != opt->arg)
+                       /*@innercontinue@*/ continue;
+                   /*@innerbreak@*/ break;
+               }
+               /* Skip if this table has already been processed. */
+               if (opt->arg == NULL || i < done->nopts)
+                   continue;
+/*@-boundswrite@*/
+               if (done->nopts < done->maxopts)
+                   done->opts[done->nopts++] = (const void *) opt->arg;
+/*@=boundswrite@*/
+           }
            cursor = singleTableUsage(con, fp, cursor, opt->arg,
-                       translation_domain);
+                       translation_domain, done);
        } else if ((opt->longName || opt->shortName) &&
                 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
            cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
@@ -598,6 +751,7 @@ static int singleTableUsage(poptContext con, FILE * fp,
 
 /**
  * Return concatenated short options for display.
+ * @todo Sub-tables should be recursed.
  * @param opt          option(s)
  * @param fp           output file handle
  * @retval str         concatenation of short options
@@ -607,42 +761,51 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
                /*@null@*/ char * str)
        /*@globals fileSystem @*/
        /*@modifies *str, *fp, fileSystem @*/
+       /*@requires maxRead(str) >= 0 @*/
 {
-    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@*/
+    /* bufsize larger then the ascii set, lazy alloca on top level call. */
+    char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
+    int len = 0;
 
+/*@-boundswrite@*/
     if (opt != NULL)
     for (; (opt->longName || opt->shortName || opt->arg); opt++) {
        if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
-           str[strlen(str)] = opt->shortName;
+           s[strlen(s)] = opt->shortName;
        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
            if (opt->arg)       /* XXX program error */
-               (void) showShortOptions(opt->arg, fp, str);
+               len = showShortOptions(opt->arg, fp, s);
     } 
+/*@=boundswrite@*/
 
-    if (s != str || *s != '\0')
-       return 0;
-
-    fprintf(fp, " [-%s]", s);
-    return strlen(s) + 4;
+    /* On return to top level, print the short options, return print length. */
+    if (s == str && *s != '\0') {
+       fprintf(fp, " [-%s]", s);
+       len = strlen(s) + sizeof(" [-]")-1;
+    }
+    return len;
 }
 
 void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
 {
-    int cursor;
+    poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
+    size_t cursor;
+
+    done->nopts = 0;
+    done->maxopts = 64;
+    cursor = done->maxopts * sizeof(*done->opts);
+/*@-boundswrite@*/
+    done->opts = memset(alloca(cursor), 0, cursor);
+    /*@-keeptrans@*/
+    done->opts[done->nopts++] = (const void *) con->options;
+    /*@=keeptrans@*/
+/*@=boundswrite@*/
 
     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);
+    cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
+    cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
+    cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
 
     if (con->otherHelp) {
        cursor += strlen(con->otherHelp) + 1;
@@ -658,4 +821,3 @@ void poptSetOtherOptionHelp(poptContext con, const char * text)
     con->otherHelp = _free(con->otherHelp);
     con->otherHelp = xstrdup(text);
 }
-/*@=type@*/
index 30172fea8c9a81f1255988f31f2d8cc740bfcd74..5e75712c95693569a1f67f9b1f2dbc50070c410f 100644 (file)
@@ -23,13 +23,17 @@ _free(/*@only@*/ /*@null@*/ const void * p)
 }
 
 /* Bit mask macros. */
+/*@-exporttype -redef @*/
 typedef        unsigned int __pbm_bits;
+/*@=exporttype =redef @*/
 #define        __PBM_NBITS             (8 * sizeof (__pbm_bits))
 #define        __PBM_IX(d)             ((d) / __PBM_NBITS)
 #define __PBM_MASK(d)          ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
+/*@-exporttype -redef @*/
 typedef struct {
     __pbm_bits bits[1];
 } pbm_set;
+/*@=exporttype =redef @*/
 #define        __PBM_BITS(set) ((set)->bits)
 
 #define        PBM_ALLOC(d)    calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
@@ -40,37 +44,53 @@ typedef struct {
 
 struct optionStackEntry {
     int argc;
-/*@only@*/ /*@null@*/ const char ** argv;
-/*@only@*/ /*@null@*/ pbm_set * argb;
+/*@only@*/ /*@null@*/
+    const char ** argv;
+/*@only@*/ /*@null@*/
+    pbm_set * argb;
     int next;
-/*@only@*/ /*@null@*/ const char * nextArg;
-/*@keep@*/ /*@null@*/ const char * nextCharArg;
-/*@dependent@*/ /*@null@*/ poptItem currAlias;
+/*@only@*/ /*@null@*/
+    const char * nextArg;
+/*@observer@*/ /*@null@*/
+    const char * nextCharArg;
+/*@dependent@*/ /*@null@*/
+    poptItem currAlias;
     int stuffed;
 };
 
 struct poptContext_s {
     struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
-/*@dependent@*/ struct optionStackEntry * os;
-/*@owned@*/ /*@null@*/ 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@*/ /*@null@*/ const char * appName;
-/*@only@*/ /*@null@*/ poptItem aliases;
+/*@only@*/ /*@null@*/
+    const char * appName;
+/*@only@*/ /*@null@*/
+    poptItem aliases;
     int numAliases;
     int flags;
-/*@owned@*/ /*@null@*/ poptItem execs;
+/*@owned@*/ /*@null@*/
+    poptItem execs;
     int numExecs;
-/*@only@*/ /*@null@*/ const char ** finalArgv;
+/*@only@*/ /*@null@*/
+    const char ** finalArgv;
     int finalArgvCount;
     int finalArgvAlloced;
-/*@dependent@*/ /*@null@*/ poptItem doExec;
-/*@only@*/ const char * execPath;
+/*@dependent@*/ /*@null@*/
+    poptItem doExec;
+/*@only@*/
+    const char * execPath;
     int execAbsolute;
-/*@only@*/ const char * otherHelp;
-/*@null@*/ pbm_set * arg_strip;
+/*@only@*/ /*@relnull@*/
+    const char * otherHelp;
+/*@null@*/
+    pbm_set * arg_strip;
 };
 
 #ifdef HAVE_LIBINTL_H
@@ -83,7 +103,7 @@ struct poptContext_s {
 #define _(foo) foo
 #endif
 
-#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
+#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
 #define D_(dom, str) dgettext(dom, str)
 #define POPT_(foo) D_("popt", foo)
 #else
index ff770175821989c717e171ffffb80108fd90fe0e..ccc2ac826bcba07c125e7977c3d5699b4d4907ff 100644 (file)
@@ -2,7 +2,7 @@
  * \file popt/poptparse.c
  */
 
-/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from 
    ftp://ftp.rpm.org/pub/rpm/dist. */
 
@@ -10,6 +10,7 @@
 
 #define POPT_ARGV_ARRAY_GROW_DELTA 5
 
+/*@-boundswrite@*/
 int poptDupArgv(int argc, const char **argv,
                int * argcPtr, const char *** argvPtr)
 {
@@ -35,7 +36,7 @@ int poptDupArgv(int argc, const char **argv,
     /*@-branchstate@*/
     for (i = 0; i < argc; i++) {
        argv2[i] = dst;
-       dst += strlen(strcpy(dst, argv[i])) + 1;
+       dst += strlcpy(dst, argv[i], nb) + 1;
     }
     /*@=branchstate@*/
     argv2[argc] = NULL;
@@ -50,11 +51,13 @@ int poptDupArgv(int argc, const char **argv,
        *argcPtr = argc;
     return 0;
 }
+/*@=boundswrite@*/
 
-int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
+/*@-bounds@*/
+int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
 {
-    const unsigned char * src;
-    unsigned char quote = '\0';
+    const char * src;
+    char quote = '\0';
     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
     int argc = 0;
@@ -116,3 +119,109 @@ exit:
     if (argv) free(argv);
     return rc;
 }
+/*@=bounds@*/
+
+/* still in the dev stage.
+ * return values, perhaps 1== file erro
+ * 2== line to long
+ * 3== umm.... more?
+ */
+int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
+{
+    char line[999];
+    char * argstr;
+    char * p;
+    char * q;
+    char * x;
+    int t;
+    int argvlen = 0;
+    size_t maxlinelen = sizeof(line);
+    size_t linelen;
+    int maxargvlen = 480;
+    int linenum = 0;
+
+    *argstrp = NULL;
+
+    /*   |   this_is   =   our_line
+     *      p             q      x
+     */
+
+    if (fp == NULL)
+       return POPT_ERROR_NULLARG;
+
+    argstr = calloc(maxargvlen, sizeof(*argstr));
+    if (argstr == NULL) return POPT_ERROR_MALLOC;
+
+    while (fgets(line, (int)maxlinelen, fp) != NULL) {
+       linenum++;
+       p = line;
+
+       /* loop until first non-space char or EOL */
+       while( *p != '\0' && isspace(*p) )
+           p++;
+
+       linelen = strlen(p);
+       if (linelen >= maxlinelen-1)
+           return POPT_ERROR_OVERFLOW; /* XXX line too long */
+
+       if (*p == '\0' || *p == '\n') continue; /* line is empty */
+       if (*p == '#') continue;                /* comment line */
+
+       q = p;
+
+       while (*q != '\0' && (!isspace(*q)) && *q != '=')
+           q++;
+
+       if (isspace(*q)) {
+           /* a space after the name, find next non space */
+           *q++='\0';
+           while( *q != '\0' && isspace((int)*q) ) q++;
+       }
+       if (*q == '\0') {
+           /* single command line option (ie, no name=val, just name) */
+           q[-1] = '\0';               /* kill off newline from fgets() call */
+           argvlen += (t = q - p) + (sizeof(" --")-1);
+           if (argvlen >= maxargvlen) {
+               maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
+               argstr = realloc(argstr, maxargvlen);
+               if (argstr == NULL) return POPT_ERROR_MALLOC;
+           }
+           strcat(argstr, " --");
+           strcat(argstr, p);
+           continue;
+       }
+       if (*q != '=')
+           continue;   /* XXX for now, silently ignore bogus line */
+               
+       /* *q is an equal sign. */
+       *q++ = '\0';
+
+       /* find next non-space letter of value */
+       while (*q != '\0' && isspace(*q))
+           q++;
+       if (*q == '\0')
+           continue;   /* XXX silently ignore missing value */
+
+       /* now, loop and strip all ending whitespace */
+       x = p + linelen;
+       while (isspace(*--x))
+           *x = 0;     /* null out last char if space (including fgets() NL) */
+
+       /* rest of line accept */
+       t = x - p;
+       argvlen += t + (sizeof("' --='")-1);
+       if (argvlen >= maxargvlen) {
+           maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
+           argstr = realloc(argstr, maxargvlen);
+           if (argstr == NULL) return POPT_ERROR_MALLOC;
+       }
+       strcat(argstr, " --");
+       strcat(argstr, p);
+       strcat(argstr, "=\"");
+       strcat(argstr, q);
+       strcat(argstr, "\"");
+    }
+
+    *argstrp = argstr;
+    return 0;
+}
index 02f05c188ee718e479047f53724aa5fa6d014145..db63dd4ba237cfeedbce3a61a3be8ab1cf5a40f4 100644 (file)
@@ -2,7 +2,17 @@
 #include "config.h"
 #endif
 
+#if defined (__GLIBC__) && defined(__LCLINT__)
+/*@-declundef@*/
+/*@unchecked@*/
+extern __const __int32_t *__ctype_tolower;
+/*@unchecked@*/
+extern __const __int32_t *__ctype_toupper;
+/*@=declundef@*/
+#endif
+
 #include <ctype.h>
+
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <unistd.h>
 #endif
 
-#if !defined(__GNUC__) || defined(APPLE)
-/* Apparently the OS X port of gcc gags on __attribute__.
- *
- * <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
+#ifndef __GNUC__
 #define __attribute__(x) 
-
 #endif
 
 #ifdef __NeXT
 #endif
 
 #if defined(__LCLINT__)
-/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
-/*@only@*/ void * alloca (size_t __size)
+/*@-declundef -incondefs @*/ /* LCL: missing annotation */
+/*@only@*/ /*@out@*/
+void * alloca (size_t __size)
        /*@ensures MaxSet(result) == (__size - 1) @*/
        /*@*/;
-/*@=declundef =incondefs =redecl@*/
+/*@=declundef =incondefs @*/
 #endif
 
 /* AIX requires this to be the first thing in the file.  */ 
@@ -49,7 +56,7 @@
 #  ifdef _AIX
 #pragma alloca
 #  else
-#   if HAVE_ALLOCA
+#   ifdef HAVE_ALLOCA
 #    ifndef alloca /* predefined by HP cc +Olibcalls */
 char *alloca ();
 #    endif
@@ -66,7 +73,8 @@ char *alloca ();
 #endif
 
 /*@-redecl -redef@*/
-/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
+/*@mayexit@*/ /*@only@*/ /*@unused@*/
+char * xstrdup (const char *str)
        /*@*/;
 /*@=redecl =redef@*/
 
@@ -77,6 +85,28 @@ char *alloca ();
 #define        xstrdup(_str)   strdup(_str)
 #endif  /* HAVE_MCHECK_H && defined(__GNUC__) */
 
+#if HAVE___SECURE_GETENV && !defined(__LCLINT__)
+#define        getenv(_s)      __secure_getenv(_s)
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *d, const char *s, size_t bufsize);
+#endif
+
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *d, const char *s, size_t bufsize);
+#endif
+
 #define UNUSED(x) x __attribute__((__unused__))
 
+#define PACKAGE "rsync"
+
+#ifndef DBL_EPSILON
+#define DBL_EPSILON 2.2204460492503131e-16
+#endif
+
+#ifdef _ABS
+#undef _ABS
+#endif
+
 #include "popt.h"