From: Wayne Davison Date: Thu, 9 Nov 2006 00:57:55 +0000 (+0000) Subject: - Upgraded popt to version 1.10.2. X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/bc93ee842fd5dd2a1cc2b2cb25656a98c673d772 - Upgraded popt to version 1.10.2. - Modified all sprintf() and strcpy() calls to use snprintf() and strlcpy(). --- diff --git a/popt/findme.c b/popt/findme.c index e98e0611..ac4cbaed 100644 --- a/popt/findme.c +++ b/popt/findme.c @@ -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; diff --git a/popt/popt.c b/popt/popt.c index 9e007693..9ce3b355 100644 --- a/popt/popt.c +++ b/popt/popt.c @@ -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 */ @@ -18,8 +18,14 @@ #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 */ #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@*/ diff --git a/popt/popt.h b/popt/popt.h index 06978f3d..4f85d9e3 100644 --- a/popt/popt.h +++ b/popt/popt.h @@ -112,33 +112,42 @@ /** \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 } diff --git a/popt/poptconfig.c b/popt/poptconfig.c index 50235661..63c3ee29 100644 --- a/popt/poptconfig.c +++ b/popt/poptconfig.c @@ -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; } diff --git a/popt/popthelp.c b/popt/popthelp.c index 07020370..eb735ffb 100644 --- a/popt/popthelp.c +++ b/popt/popthelp.c @@ -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 /* 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@*/ diff --git a/popt/poptint.h b/popt/poptint.h index 30172fea..5e75712c 100644 --- a/popt/poptint.h +++ b/popt/poptint.h @@ -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 diff --git a/popt/poptparse.c b/popt/poptparse.c index ff770175..ccc2ac82 100644 --- a/popt/poptparse.c +++ b/popt/poptparse.c @@ -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; +} diff --git a/popt/system.h b/popt/system.h index 02f05c18..db63dd4b 100644 --- a/popt/system.h +++ b/popt/system.h @@ -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 + #include #include #include @@ -19,12 +29,8 @@ #include #endif -#if !defined(__GNUC__) || defined(APPLE) -/* Apparently the OS X port of gcc gags on __attribute__. - * - * */ +#ifndef __GNUC__ #define __attribute__(x) - #endif #ifdef __NeXT @@ -34,11 +40,12 @@ #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"