Index: ossp-pkg/popt/popt.c RCS File: /v/ossp/cvs/ossp-pkg/popt/popt.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/popt/popt.c,v' | diff -u /dev/null - -L'ossp-pkg/popt/popt.c' 2>/dev/null --- ossp-pkg/popt/popt.c +++ - 2024-05-18 09:30:05.394432297 +0200 @@ -0,0 +1,2148 @@ +/* + * Option Parsing Library (POPT) + * Copyright (c) 1998-2002 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the X Consortium shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from the X Consortium. + * + * NOTICE: + * This is an automatically generated, stripped down version of the + * POPT 1.6.3 library from Red Hat, Inc. This version is still + * distributed under above Open Source license, but Red Hat is no longer + * responsible for this version. Contact The OSSP Project instead. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifndef __GNUC__ +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX +#pragma alloca +# else +# ifndef alloca +char *alloca(); +# endif +# endif +# endif +#elif defined(__GNUC__) && defined(__STRICT_ANSI__) +#define alloca __builtin_alloca +#endif +#include "popt.h" + +#ifndef H_POPTINT +#define H_POPTINT + +static void *_free(const void *p) +{ + if (p != NULL) + free((void *)p); + return NULL; +} + +typedef unsigned int __pbm_bits; +#define __PBM_NBITS (8 * sizeof (__pbm_bits)) +#define __PBM_IX(d) ((d) / __PBM_NBITS) +#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS)) +typedef struct { + __pbm_bits bits[1]; +} pbm_set; +#define __PBM_BITS(set) ((set)->bits) + +#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) +#define PBM_FREE(s) _free(s); +#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) +#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) +#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) + +struct optionStackEntry { + int argc; + const char **argv; + pbm_set *argb; + int next; + const char *nextArg; + const char *nextCharArg; + popt_item currAlias; + int stuffed; +}; + +struct popt_context_s { + struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; + struct optionStackEntry *os; + const char **leftovers; + int numLeftovers; + int nextLeftover; + const struct popt_option *options; + int restLeftover; + const char *appName; + popt_item aliases; + int numAliases; + int flags; + popt_item execs; + int numExecs; + const char **finalArgv; + int finalArgvCount; + int finalArgvAlloced; + popt_item doExec; + const char *execPath; + int execAbsolute; + const char *otherHelp; + pbm_set *arg_strip; +}; + +#ifdef HAVE_LIBINTL_H +#include +#endif + +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__) +#define _(foo) gettext(foo) +#else +#define _(foo) foo +#endif + +#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__) +#define D_(dom, str) dgettext(dom, str) +#define POPT_(foo) D_("popt", foo) +#else +#define D_(dom, str) str +#define POPT_(foo) foo +#endif + +#define N_(foo) foo + +#endif + +static const char *findProgramPath(const char *argv0) +{ + char *path = getenv("PATH"); + char *pathbuf; + char *start, *chptr; + char *buf; + + if (argv0 == NULL) + return NULL; + if (strchr(argv0, '/')) + return strdup(argv0); + + if (path == NULL) + return NULL; + + start = pathbuf = alloca(strlen(path) + 1); + buf = malloc(strlen(path) + strlen(argv0) + sizeof ("/")); + if (buf == NULL) + return NULL; + strcpy(pathbuf, path); + + chptr = NULL; + do { + if ((chptr = strchr(start, ':'))) + *chptr = '\0'; + sprintf(buf, "%s/%s", start, argv0); + + if (!access(buf, X_OK)) + return buf; + + if (chptr) + start = chptr + 1; + else + start = NULL; + } while (start && *start); + + free(buf); + + return NULL; +} + +#if HAVE_FLOAT_H +#include +#endif +#include + +void popt_setexecpath(popt_context con, const char *path, int allowAbsolute) +{ + con->execPath = _free(con->execPath); + con->execPath = strdup(path); + con->execAbsolute = allowAbsolute; +} + +static void invokeCallbacksPRE(popt_context con, + const struct popt_option *opt) +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->arg == NULL) + continue; + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + invokeCallbacksPRE(con, opt->arg); + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + (opt->argInfo & POPT_CBFLAG_PRE)) { + popt_callbacktype cb = (popt_callbacktype) opt->arg; + + cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); + + } + } +} + +static void invokeCallbacksPOST(popt_context con, + const struct popt_option *opt) +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->arg == NULL) + continue; + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + invokeCallbacksPOST(con, opt->arg); + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + (opt->argInfo & POPT_CBFLAG_POST)) { + popt_callbacktype cb = (popt_callbacktype) opt->arg; + + cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); + + } + } +} + +static void invokeCallbacksOPTION(popt_context con, + const struct popt_option *opt, + const struct popt_option *myOpt, + const void *myData, int shorty) +{ + const struct popt_option *cbopt = NULL; + + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + if (opt->arg != NULL) + invokeCallbacksOPTION(con, opt->arg, myOpt, myData, + shorty); + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) { + cbopt = opt; + } + else if (cbopt != NULL && + ((myOpt->shortName && opt->shortName && shorty && + myOpt->shortName == opt->shortName) || + (myOpt->longName && opt->longName && + !strcmp(myOpt->longName, opt->longName))) + + ) { + popt_callbacktype cb = (popt_callbacktype) cbopt->arg; + + const void *cbData = + (cbopt->descrip ? cbopt->descrip : myData); + if (cb != NULL) { + + cb(con, POPT_CALLBACK_REASON_OPTION, myOpt, + con->os->nextArg, cbData); + + } + if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE)) + return; + } + } +} + +popt_context popt_getcontext(const char *name, int argc, const char **argv, + const struct popt_option * options, int flags) +{ + popt_context con = malloc(sizeof (*con)); + + if (con == NULL) + return NULL; + memset(con, 0, sizeof (*con)); + + con->os = con->optionStack; + con->os->argc = argc; + con->os->argv = argv; + + con->os->argb = NULL; + + if (!(flags & POPT_CONTEXT_KEEP_FIRST)) + con->os->next = 1; + + con->leftovers = calloc((argc + 1), sizeof (char *)); + con->options = options; + + con->aliases = NULL; + con->numAliases = 0; + con->flags = flags; + con->execs = NULL; + con->numExecs = 0; + con->finalArgvAlloced = argc * 2; + con->finalArgv = calloc(con->finalArgvAlloced, sizeof (*con->finalArgv)); + con->execAbsolute = 1; + con->arg_strip = NULL; + + if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) + con->flags |= POPT_CONTEXT_POSIXMEHARDER; + + if (name) { + char *t = malloc(strlen(name) + 1); + if (t) + con->appName = strcpy(t, name); + } + + invokeCallbacksPRE(con, con->options); + + return con; +} + +static void cleanOSE(struct optionStackEntry *os) +{ + os->nextArg = _free(os->nextArg); + os->argv = _free(os->argv); + os->argb = PBM_FREE(os->argb); +} + +void popt_resetcontext(popt_context con) +{ + int i; + + if (con == NULL) + return; + while (con->os > con->optionStack) { + cleanOSE(con->os--); + } + con->os->argb = PBM_FREE(con->os->argb); + con->os->currAlias = NULL; + con->os->nextCharArg = NULL; + con->os->nextArg = NULL; + con->os->next = 1; + + con->numLeftovers = 0; + con->nextLeftover = 0; + con->restLeftover = 0; + con->doExec = NULL; + + if (con->finalArgv != NULL) + for (i = 0; i < con->finalArgvCount; i++) + con->finalArgv[i] = _free(con->finalArgv[i]); + + con->finalArgvCount = 0; + con->arg_strip = PBM_FREE(con->arg_strip); + return; + +} + +static int handleExec(popt_context con, const char *longName, char shortName) +{ + popt_item item; + int i; + + if (con->execs == NULL || con->numExecs <= 0) + return 0; + + for (i = con->numExecs - 1; i >= 0; i--) { + item = con->execs + i; + if (longName && !(item->option.longName && + !strcmp(longName, item->option.longName))) + continue; + else if (shortName != item->option.shortName) + continue; + break; + } + if (i < 0) + return 0; + + if (con->flags & POPT_CONTEXT_NO_EXEC) + return 1; + + if (con->doExec == NULL) { + con->doExec = con->execs + i; + return 1; + } + + if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof (*con->finalArgv) * + con->finalArgvAlloced); + } + + i = con->finalArgvCount++; + if (con->finalArgv != NULL) { + char *s = malloc((longName ? strlen(longName) : 0) + 3); + if (s != NULL) { + if (longName) + sprintf(s, "--%s", longName); + else + sprintf(s, "-%c", shortName); + con->finalArgv[i] = s; + } + else + con->finalArgv[i] = NULL; + } + + return 1; + +} + +static int handleAlias(popt_context con, + const char *longName, char shortName, + const char *nextCharArg) +{ + popt_item item = con->os->currAlias; + int rc; + int i; + + if (item) { + if (longName && (item->option.longName && + !strcmp(longName, item->option.longName))) + return 0; + if (shortName && shortName == item->option.shortName) + return 0; + } + + if (con->aliases == NULL || con->numAliases <= 0) + return 0; + + for (i = con->numAliases - 1; i >= 0; i--) { + item = con->aliases + i; + if (longName && !(item->option.longName && + !strcmp(longName, item->option.longName))) + continue; + else if (shortName != item->option.shortName) + continue; + break; + } + if (i < 0) + return 0; + + if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + if (nextCharArg && *nextCharArg) + con->os->nextCharArg = nextCharArg; + + con->os++; + con->os->next = 0; + con->os->stuffed = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = con->aliases + i; + rc = popt_dupargv(con->os->currAlias->argc, con->os->currAlias->argv, + &con->os->argc, &con->os->argv); + con->os->argb = NULL; + + return (rc ? rc : 1); +} + +static int execCommand(popt_context con) +{ + popt_item item = con->doExec; + const char **argv; + int argc = 0; + int rc; + + if (item == NULL) + return POPT_ERROR_NOARG; + + if (item->argv == NULL || item->argc < 1 || + (!con->execAbsolute && strchr(item->argv[0], '/'))) + return POPT_ERROR_NOARG; + + argv = malloc(sizeof (*argv) * + (6 + item->argc + con->numLeftovers + con->finalArgvCount)); + if (argv == NULL) + return POPT_ERROR_MALLOC; + + if (!strchr(item->argv[0], '/') && con->execPath) { + char *s = + alloca(strlen(con->execPath) + strlen(item->argv[0]) + + sizeof ("/")); + sprintf(s, "%s/%s", con->execPath, item->argv[0]); + argv[argc] = s; + } + else { + argv[argc] = findProgramPath(item->argv[0]); + } + if (argv[argc++] == NULL) + return POPT_ERROR_NOARG; + + if (item->argc > 1) { + memcpy(argv + argc, item->argv + 1, + sizeof (*argv) * (item->argc - 1)); + argc += (item->argc - 1); + } + + if (con->finalArgv != NULL && con->finalArgvCount > 0) { + memcpy(argv + argc, con->finalArgv, + sizeof (*argv) * con->finalArgvCount); + argc += con->finalArgvCount; + } + + if (con->leftovers != NULL && con->numLeftovers > 0) { + + memcpy(argv + argc, con->leftovers, + sizeof (*argv) * con->numLeftovers); + argc += con->numLeftovers; + } + + argv[argc] = NULL; + +#ifdef __hpux + rc = setresuid(getuid(), getuid(), -1); + if (rc) + return POPT_ERROR_ERRNO; +#else +#if defined(HAVE_SETUID) + rc = setuid(getuid()); + if (rc) + return POPT_ERROR_ERRNO; +#elif defined (HAVE_SETREUID) + rc = setreuid(getuid(), getuid()); + if (rc) + return POPT_ERROR_ERRNO; +#else + ; +#endif +#endif + + if (argv[0] == NULL) + return POPT_ERROR_NOARG; + + rc = execvp(argv[0], (char *const *)argv); + return POPT_ERROR_ERRNO; +} + +static const struct popt_option *findOption(const struct popt_option *opt, + const char *longName, + char shortName, + popt_callbacktype * callback, + const void **callbackData, + int singleDash) +{ + const struct popt_option *cb = NULL; + + if (singleDash && !shortName && (longName && *longName == '\0')) + shortName = '-'; + + for (; opt->longName || opt->shortName || opt->arg; opt++) { + + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + const struct popt_option *opt2; + + if (opt->arg == NULL) + continue; + opt2 = findOption(opt->arg, longName, shortName, callback, + callbackData, singleDash); + if (opt2 == NULL) + continue; + if (!(callback && *callback)) + return opt2; + if (!(callbackData && *callbackData == NULL)) + return opt2; + + *callbackData = opt->descrip; + + return opt2; + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { + cb = opt; + } + else if (longName && opt->longName && + (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && + !strcmp(longName, opt->longName)) + { + break; + } + else if (shortName && shortName == opt->shortName) { + break; + } + } + + if (!opt->longName && !opt->shortName) + return NULL; + + if (callback) + *callback = NULL; + if (callbackData) + *callbackData = NULL; + if (cb) { + if (callback) + + *callback = (popt_callbacktype) cb->arg; + + if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) { + if (callbackData) + *callbackData = cb->descrip; + + } + } + + return opt; +} + +static const char *findNextArg(popt_context con, + unsigned argx, int delete_arg) +{ + struct optionStackEntry *os = con->os; + const char *arg; + + do { + int i; + arg = NULL; + while (os->next == os->argc && os > con->optionStack) + os--; + if (os->next == os->argc && os == con->optionStack) + break; + if (os->argv != NULL) + for (i = os->next; i < os->argc; i++) { + if (os->argb && PBM_ISSET(i, os->argb)) + continue; + if (*os->argv[i] == '-') + continue; + if (--argx > 0) + continue; + arg = os->argv[i]; + if (delete_arg) { + if (os->argb == NULL) + os->argb = PBM_ALLOC(os->argc); + if (os->argb != NULL) + PBM_SET(i, os->argb); + } + break; + } + if (os > con->optionStack) + os--; + } while (arg == NULL); + return arg; +} + +static const char *expandNextArg(popt_context con, const char *s) +{ + const char *a = NULL; + size_t alen; + char *t, *te; + size_t tn = strlen(s) + 1; + char c; + + te = t = malloc(tn);; + if (t == NULL) + return NULL; + while ((c = *s++) != '\0') { + switch (c) { + + case '!': + if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) + break; + if (a == NULL) { + if ((a = findNextArg(con, 1, 1)) == NULL) + break; + } + s += 3; + + alen = strlen(a); + tn += alen; + *te = '\0'; + t = realloc(t, tn); + te = t + strlen(t); + strncpy(te, a, alen); + te += alen; + continue; + break; + default: + break; + } + *te++ = c; + } + *te = '\0'; + t = realloc(t, strlen(t) + 1); + return t; +} + +static void poptStripArg(popt_context con, int which) +{ + if (con->arg_strip == NULL) + con->arg_strip = PBM_ALLOC(con->optionStack[0].argc); + if (con->arg_strip != NULL) + PBM_SET(which, con->arg_strip); +} + +static int poptSaveLong(const struct popt_option *opt, long aLong) +{ + if (opt->arg == NULL) + return POPT_ERROR_NULLARG; + + if (opt->argInfo & POPT_ARGFLAG_NOT) + aLong = ~aLong; + switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) { + case 0: + *((long *)opt->arg) = aLong; + break; + case POPT_ARGFLAG_OR: + *((long *)opt->arg) |= aLong; + break; + case POPT_ARGFLAG_AND: + *((long *)opt->arg) &= aLong; + break; + case POPT_ARGFLAG_XOR: + *((long *)opt->arg) ^= aLong; + break; + default: + return POPT_ERROR_BADOPERATION; + break; + } + return 0; +} + +static int poptSaveInt(const struct popt_option *opt, long aLong) +{ + if (opt->arg == NULL) + return POPT_ERROR_NULLARG; + + if (opt->argInfo & POPT_ARGFLAG_NOT) + aLong = ~aLong; + switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) { + case 0: + *((int *)opt->arg) = aLong; + break; + case POPT_ARGFLAG_OR: + *((int *)opt->arg) |= aLong; + break; + case POPT_ARGFLAG_AND: + *((int *)opt->arg) &= aLong; + break; + case POPT_ARGFLAG_XOR: + *((int *)opt->arg) ^= aLong; + break; + default: + return POPT_ERROR_BADOPERATION; + break; + } + return 0; +} + +int popt_getnextopt(popt_context con) +{ + const struct popt_option *opt = NULL; + int done = 0; + + if (con == NULL) + return -1; + while (!done) { + const char *origOptString = NULL; + popt_callbacktype cb = NULL; + const void *cbData = NULL; + const char *longArg = NULL; + int canstrip = 0; + int shorty = 0; + + while (!con->os->nextCharArg && con->os->next == con->os->argc + && con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (!con->os->nextCharArg && con->os->next == con->os->argc) { + invokeCallbacksPOST(con, con->options); + if (con->doExec) + return execCommand(con); + return -1; + } + + if (!con->os->nextCharArg) { + char *localOptString, *optString; + int thisopt; + + if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { + con->os->next++; + continue; + } + thisopt = con->os->next; + if (con->os->argv != NULL) + origOptString = con->os->argv[con->os->next++]; + + if (origOptString == NULL) + return POPT_ERROR_BADOPT; + + if (con->restLeftover || *origOptString != '-') { + if (con->flags & POPT_CONTEXT_POSIXMEHARDER) + con->restLeftover = 1; + if (con->flags & POPT_CONTEXT_ARG_OPTS) { + con->os->nextArg = strdup(origOptString); + return 0; + } + if (con->leftovers != NULL) + con->leftovers[con->numLeftovers++] = origOptString; + continue; + } + + localOptString = optString = + strcpy(alloca(strlen(origOptString) + 1), origOptString); + + if (optString[0] == '\0') + return POPT_ERROR_BADOPT; + + if (optString[1] == '-' && !optString[2]) { + con->restLeftover = 1; + continue; + } + else { + char *oe; + int singleDash; + + optString++; + if (*optString == '-') + singleDash = 0, optString++; + else + singleDash = 1; + + if (handleAlias(con, optString, '\0', NULL)) + continue; + + if (handleExec(con, optString, '\0')) + continue; + + for (oe = optString; *oe && *oe != '='; oe++) { + }; + if (*oe == '=') { + *oe++ = '\0'; + longArg = origOptString + (oe - localOptString); + } + + opt = findOption(con->options, optString, '\0', &cb, &cbData, + singleDash); + if (!opt && !singleDash) + return POPT_ERROR_BADOPT; + } + + if (!opt) { + con->os->nextCharArg = origOptString + 1; + } + else { + if (con->os == con->optionStack && + opt->argInfo & POPT_ARGFLAG_STRIP) { + canstrip = 1; + poptStripArg(con, thisopt); + } + shorty = 0; + } + } + + if (con->os->nextCharArg) { + origOptString = con->os->nextCharArg; + + con->os->nextCharArg = NULL; + + if (handleAlias(con, NULL, *origOptString, origOptString + 1)) + continue; + + if (handleExec(con, NULL, *origOptString)) { + origOptString++; + if (*origOptString != '\0') + con->os->nextCharArg = origOptString; + continue; + } + + opt = findOption(con->options, NULL, *origOptString, &cb, + &cbData, 0); + if (!opt) + return POPT_ERROR_BADOPT; + shorty = 1; + + origOptString++; + if (*origOptString != '\0') + con->os->nextCharArg = origOptString; + + } + + if (opt == NULL) + return POPT_ERROR_BADOPT; + if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) { + if (poptSaveInt(opt, 1L)) + return POPT_ERROR_BADOPERATION; + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) { + if (opt->arg) { + if (poptSaveInt(opt, (long)opt->val)) + return POPT_ERROR_BADOPERATION; + } + } + else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { + con->os->nextArg = _free(con->os->nextArg); + if (longArg) { + + longArg = expandNextArg(con, longArg); + con->os->nextArg = longArg; + } + else if (con->os->nextCharArg) { + longArg = expandNextArg(con, con->os->nextCharArg); + con->os->nextArg = longArg; + con->os->nextCharArg = NULL; + } + else { + while (con->os->next == con->os->argc && + con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (con->os->next == con->os->argc) { + if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL)) + return POPT_ERROR_NOARG; + + con->os->nextArg = NULL; + } + else { + + if (con->os == con->optionStack && + (opt->argInfo & POPT_ARGFLAG_STRIP) && canstrip) { + poptStripArg(con, con->os->next); + } + + if (con->os->argv != NULL) { + longArg = con->os->argv[con->os->next++]; + longArg = expandNextArg(con, longArg); + con->os->nextArg = longArg; + } + } + } + longArg = NULL; + + if (opt->arg) { + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_STRING: + *((const char **)opt->arg) = (con->os->nextArg) + ? strdup(con->os->nextArg) : NULL; + break; + + case POPT_ARG_INT: + case POPT_ARG_LONG: + { + long aLong = 0; + char *end; + + if (con->os->nextArg) { + aLong = strtol(con->os->nextArg, &end, 0); + if (!(end && *end == '\0')) + return POPT_ERROR_BADNUMBER; + } + + if ((opt->argInfo & POPT_ARG_MASK) == + POPT_ARG_LONG) { + if (aLong == LONG_MIN || aLong == LONG_MAX) + return POPT_ERROR_OVERFLOW; + if (poptSaveLong(opt, aLong)) + return POPT_ERROR_BADOPERATION; + } + else { + if (aLong > INT_MAX || aLong < INT_MIN) + return POPT_ERROR_OVERFLOW; + if (poptSaveInt(opt, aLong)) + return POPT_ERROR_BADOPERATION; + } + } + break; + + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + { + double aDouble = 0.0; + char *end; + + if (con->os->nextArg) { + int saveerrno = errno; + errno = 0; + aDouble = strtod(con->os->nextArg, &end); + if (errno == ERANGE) + return POPT_ERROR_OVERFLOW; + errno = saveerrno; + if (*end != '\0') + return POPT_ERROR_BADNUMBER; + } + + if ((opt->argInfo & POPT_ARG_MASK) == + POPT_ARG_DOUBLE) { + *((double *)opt->arg) = aDouble; + } + else { +#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a)) + if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON) + return POPT_ERROR_OVERFLOW; + if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON) + return POPT_ERROR_OVERFLOW; + *((float *)opt->arg) = aDouble; + } + } break; + default: + fprintf(stdout, + POPT_ + ("option type (%d) not implemented in popt\n"), + (opt->argInfo & POPT_ARG_MASK)); + exit(EXIT_FAILURE); + } + } + } + + if (cb) + invokeCallbacksOPTION(con, con->options, opt, cbData, shorty); + else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) + done = 1; + + if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof (*con->finalArgv) * + con->finalArgvAlloced); + } + + if (con->finalArgv != NULL) { + char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); + if (s != NULL) { + if (opt->longName) + sprintf(s, "%s%s", + ((opt-> + argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + else + sprintf(s, "-%c", opt->shortName); + con->finalArgv[con->finalArgvCount++] = s; + } + else + con->finalArgv[con->finalArgvCount++] = NULL; + } + + if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) ; + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) ; + else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { + if (con->finalArgv != NULL && con->os->nextArg) + con->finalArgv[con->finalArgvCount++] = + strdup(con->os->nextArg); + + } + } + + return (opt ? opt->val : -1); +} + +const char *popt_getoptarg(popt_context con) +{ + const char *ret = NULL; + if (con) { + ret = con->os->nextArg; + con->os->nextArg = NULL; + } + return ret; +} + +const char *popt_getarg(popt_context con) +{ + const char *ret = NULL; + if (con && con->leftovers != NULL + && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover++]; + return ret; +} + +const char *popt_peekarg(popt_context con) +{ + const char *ret = NULL; + if (con && con->leftovers != NULL + && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover]; + return ret; +} + +const char **popt_getargs(popt_context con) +{ + if (con == NULL || + con->leftovers == NULL || con->numLeftovers == con->nextLeftover) + return NULL; + + con->leftovers[con->numLeftovers] = NULL; + + return (con->leftovers + con->nextLeftover); + +} + +popt_context popt_freecontext(popt_context con) +{ + popt_item item; + int i; + + if (con == NULL) + return con; + popt_resetcontext(con); + con->os->argb = _free(con->os->argb); + + if (con->aliases != NULL) + for (i = 0; i < con->numAliases; i++) { + item = con->aliases + i; + + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); + + item->argv = _free(item->argv); + } + con->aliases = _free(con->aliases); + + if (con->execs != NULL) + for (i = 0; i < con->numExecs; i++) { + item = con->execs + i; + + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); + + item->argv = _free(item->argv); + } + con->execs = _free(con->execs); + + con->leftovers = _free(con->leftovers); + con->finalArgv = _free(con->finalArgv); + con->appName = _free(con->appName); + con->otherHelp = _free(con->otherHelp); + con->execPath = _free(con->execPath); + con->arg_strip = PBM_FREE(con->arg_strip); + + con = _free(con); + return con; +} + +int popt_addalias(popt_context con, struct popt_alias newAlias, int flags) +{ + popt_item item = alloca(sizeof (*item)); + memset(item, 0, sizeof (*item)); + item->option.longName = newAlias.longName; + item->option.shortName = newAlias.shortName; + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + item->option.arg = 0; + item->option.val = 0; + item->option.descrip = NULL; + item->option.argDescrip = NULL; + item->argc = newAlias.argc; + item->argv = newAlias.argv; + return popt_additem(con, item, 0); +} + +int popt_additem(popt_context con, popt_item newItem, int flags) +{ + popt_item *items, item; + int *nitems; + + switch (flags) { + case 1: + items = &con->execs; + nitems = &con->numExecs; + break; + case 0: + items = &con->aliases; + nitems = &con->numAliases; + break; + default: + return 1; + break; + } + + *items = realloc((*items), ((*nitems) + 1) * sizeof (**items)); + if ((*items) == NULL) + return 1; + + item = (*items) + (*nitems); + + item->option.longName = + (newItem->option.longName ? strdup(newItem->option.longName) : NULL); + item->option.shortName = newItem->option.shortName; + item->option.argInfo = newItem->option.argInfo; + item->option.arg = newItem->option.arg; + item->option.val = newItem->option.val; + item->option.descrip = + (newItem->option.descrip ? strdup(newItem->option.descrip) : NULL); + item->option.argDescrip = + (newItem->option. + argDescrip ? strdup(newItem->option.argDescrip) : NULL); + item->argc = newItem->argc; + item->argv = newItem->argv; + + (*nitems)++; + + return 0; +} + +const char *popt_badoption(popt_context con, int flags) +{ + struct optionStackEntry *os = NULL; + + if (con != NULL) + os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os; + + return (os && os->argv ? os->argv[os->next - 1] : NULL); + +} + +const char *const popt_strerror(const int error) +{ + switch (error) { + case POPT_ERROR_NOARG: + return POPT_("missing argument"); + case POPT_ERROR_BADOPT: + return POPT_("unknown option"); + case POPT_ERROR_BADOPERATION: + return POPT_("mutually exclusive logical operations requested"); + case POPT_ERROR_NULLARG: + return POPT_("opt->arg should not be NULL"); + case POPT_ERROR_OPTSTOODEEP: + return POPT_("aliases nested too deeply"); + case POPT_ERROR_BADQUOTE: + return POPT_("error in parameter quoting"); + case POPT_ERROR_BADNUMBER: + return POPT_("invalid numeric value"); + case POPT_ERROR_OVERFLOW: + return POPT_("number too large or too small"); + case POPT_ERROR_MALLOC: + return POPT_("memory allocation failed"); + case POPT_ERROR_ERRNO: + return strerror(errno); + default: + return POPT_("unknown error"); + } +} + +int popt_stuffargs(popt_context con, const char **argv) +{ + int argc; + int rc; + + if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + for (argc = 0; argv[argc]; argc++) { + }; + + con->os++; + con->os->next = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = NULL; + rc = popt_dupargv(argc, argv, &con->os->argc, &con->os->argv); + con->os->argb = NULL; + con->os->stuffed = 1; + + return rc; +} + +const char *popt_getinvocationname(popt_context con) +{ + return (con->os->argv ? con->os->argv[0] : ""); +} + +int popt_strippedargv(popt_context con, int argc, char **argv) +{ + int numargs = argc; + int j = 1; + int i; + + if (con->arg_strip) + for (i = 1; i < argc; i++) { + if (PBM_ISSET(i, con->arg_strip)) + numargs--; + } + + for (i = 1; i < argc; i++) { + if (con->arg_strip && PBM_ISSET(i, con->arg_strip)) + continue; + argv[j] = (j < numargs) ? argv[i] : NULL; + j++; + } + + return numargs; +} + +#define POPT_ARGV_ARRAY_GROW_DELTA 5 + +int popt_dupargv(int argc, const char **argv, + int *argcPtr, const char ***argvPtr) +{ + size_t nb = (argc + 1) * sizeof (*argv); + const char **argv2; + char *dst; + int i; + + if (argc <= 0 || argv == NULL) + return POPT_ERROR_NOARG; + for (i = 0; i < argc; i++) { + if (argv[i] == NULL) + return POPT_ERROR_NOARG; + nb += strlen(argv[i]) + 1; + } + + dst = malloc(nb); + if (dst == NULL) + return POPT_ERROR_MALLOC; + argv2 = (void *)dst; + dst += (argc + 1) * sizeof (*argv); + + for (i = 0; i < argc; i++) { + argv2[i] = dst; + dst += strlen(strcpy(dst, argv[i])) + 1; + } + argv2[argc] = NULL; + + if (argvPtr) { + *argvPtr = argv2; + } + else { + free(argv2); + argv2 = NULL; + } + if (argcPtr) + *argcPtr = argc; + return 0; +} + +int popt_parseargvstring(const char *s, int *argcPtr, const char ***argvPtr) +{ + const char *src; + char quote = '\0'; + int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; + const char **argv = malloc(sizeof (*argv) * argvAlloced); + int argc = 0; + int buflen = strlen(s) + 1; + char *buf = memset(alloca(buflen), 0, buflen); + int rc = POPT_ERROR_MALLOC; + + if (argv == NULL) + return rc; + argv[argc] = buf; + + for (src = s; *src != '\0'; src++) { + if (quote == *src) { + quote = '\0'; + } + else if (quote != '\0') { + if (*src == '\\') { + src++; + if (!*src) { + rc = POPT_ERROR_BADQUOTE; + goto exit; + } + if (*src != quote) + *buf++ = '\\'; + } + *buf++ = *src; + } + else if (isspace(*src)) { + if (*argv[argc] != '\0') { + buf++, argc++; + if (argc == argvAlloced) { + argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; + argv = realloc(argv, sizeof (*argv) * argvAlloced); + if (argv == NULL) + goto exit; + } + argv[argc] = buf; + } + } + else + switch (*src) { + case '"': + case '\'': + quote = *src; + break; + case '\\': + src++; + if (!*src) { + rc = POPT_ERROR_BADQUOTE; + goto exit; + } + + default: + *buf++ = *src; + break; + } + } + + if (strlen(argv[argc])) { + argc++, buf++; + } + + rc = popt_dupargv(argc, argv, argcPtr, argvPtr); + + exit: + if (argv) + free(argv); + return rc; +} + +static void configLine(popt_context con, char *line) +{ + int nameLength = strlen(con->appName); + const char *entryType; + const char *opt; + popt_item item = alloca(sizeof (*item)); + int i, j; + + memset(item, 0, sizeof (*item)); + + if (strncmp(line, con->appName, nameLength)) + return; + line += nameLength; + if (*line == '\0' || !isspace(*line)) + return; + + while (*line != '\0' && isspace(*line)) + line++; + entryType = line; + while (*line == '\0' || !isspace(*line)) + line++; + *line++ = '\0'; + + while (*line != '\0' && isspace(*line)) + line++; + if (*line == '\0') + return; + opt = line; + while (*line == '\0' || !isspace(*line)) + line++; + *line++ = '\0'; + + while (*line != '\0' && isspace(*line)) + line++; + if (*line == '\0') + return; + + if (opt[0] == '-' && opt[1] == '-') + item->option.longName = opt + 2; + else if (opt[0] == '-' && opt[2] == '\0') + item->option.shortName = opt[1]; + + if (popt_parseargvstring(line, &item->argc, &item->argv)) + return; + + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + for (i = 0, j = 0; i < item->argc; i++, j++) { + const char *f; + if (!strncmp + (item->argv[i], "--POPTdesc=", sizeof ("--POPTdesc=") - 1)) { + f = item->argv[i] + sizeof ("--POPTdesc="); + if (f[0] == '$' && f[1] == '"') + f++; + item->option.descrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + j--; + } + else if (!strncmp + (item->argv[i], "--POPTargs=", sizeof ("--POPTargs=") - 1)) { + f = item->argv[i] + sizeof ("--POPTargs="); + if (f[0] == '$' && f[1] == '"') + f++; + item->option.argDescrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + item->option.argInfo |= POPT_ARG_STRING; + j--; + } + else if (j != i) + item->argv[j] = item->argv[i]; + } + if (j != i) { + item->argv[j] = NULL; + item->argc = j; + } + + if (!strcmp(entryType, "alias")) + (void)popt_additem(con, item, 0); + else if (!strcmp(entryType, "exec")) + (void)popt_additem(con, item, 1); +} + +int popt_readconfigfile(popt_context con, const char *fn) +{ + const char *file, *chptr, *end; + char *buf; + char *dst; + int fd, rc; + off_t fileLength; + + fd = open(fn, O_RDONLY); + if (fd < 0) + return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); + + fileLength = lseek(fd, 0, SEEK_END); + if (fileLength == -1 || lseek(fd, 0, 0) == -1) { + rc = errno; + (void)close(fd); + errno = rc; + return POPT_ERROR_ERRNO; + } + + file = alloca(fileLength + 1); + if (read(fd, (char *)file, fileLength) != fileLength) { + rc = errno; + (void)close(fd); + errno = rc; + return POPT_ERROR_ERRNO; + } + if (close(fd) == -1) + return POPT_ERROR_ERRNO; + + dst = buf = alloca(fileLength + 1); + + chptr = file; + end = (file + fileLength); + while (chptr < end) { + switch (*chptr) { + case '\n': + *dst = '\0'; + dst = buf; + while (*dst && isspace(*dst)) + dst++; + if (*dst && *dst != '#') + configLine(con, dst); + chptr++; + break; + case '\\': + *dst++ = *chptr++; + if (chptr < end) { + if (*chptr == '\n') + dst--, chptr++; + else + *dst++ = *chptr++; + } + break; + default: + *dst++ = *chptr++; + break; + } + } + + return 0; +} + +int popt_readdefaultconfig(popt_context con, int useEnv) +{ + char *fn, *home; + int rc; + + if (!con->appName) + return 0; + + rc = popt_readconfigfile(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"); + rc = popt_readconfigfile(con, fn); + if (rc) + return rc; + } + + return 0; +} + +static void displayArgs(popt_context con, + enum popt_callbackreason foo, + struct popt_option *key, const char *arg, void *data) +{ + if (key->shortName == '?') + popt_printhelp(con, stdout, 0); + else + popt_printusage(con, stdout, 0); + exit(0); +} + +struct popt_option popt_aliasOptions[] = { + POPT_TABLEEND +}; + +struct popt_option popt_helpoptions[] = { + {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 +}; + +static const char *const +getTableTranslationDomain(const struct popt_option *table) +{ + const struct popt_option *opt; + + if (table != NULL) + for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->argInfo == POPT_ARG_INTL_DOMAIN) + return opt->arg; + } + return NULL; +} + +static const char *const +getArgDescrip(const struct popt_option *opt, const char *translation_domain) +{ + if (!(opt->argInfo & POPT_ARG_MASK)) + return NULL; + + if (opt == (popt_helpoptions + 1) || opt == (popt_helpoptions + 2)) + if (opt->argDescrip) + return POPT_(opt->argDescrip); + + if (opt->argDescrip) + return D_(translation_domain, opt->argDescrip); + + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_NONE: + return POPT_("NONE"); + case POPT_ARG_VAL: + return POPT_("VAL"); + case POPT_ARG_INT: + return POPT_("INT"); + case POPT_ARG_LONG: + return POPT_("LONG"); + case POPT_ARG_STRING: + return POPT_("STRING"); + case POPT_ARG_FLOAT: + return POPT_("FLOAT"); + case POPT_ARG_DOUBLE: + return POPT_("DOUBLE"); + default: + return POPT_("ARG"); + } +} + +static char *singleOptionDefaultValue(int lineLength, + const struct popt_option *opt, + const char *translation_domain) +{ + const char *defstr = D_(translation_domain, "default"); + char *le = malloc(4 * lineLength + 1); + char *l = le; + + if (l == NULL) + return NULL; + *le = '\0'; + *le++ = '('; + strcpy(le, defstr); + le += strlen(le); + *le++ = ':'; + *le++ = ' '; + if (opt->arg) + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_VAL: + case POPT_ARG_INT: + { + long aLong = *((int *)opt->arg); + le += sprintf(le, "%ld", aLong); + } break; + case POPT_ARG_LONG: + { + long aLong = *((long *)opt->arg); + le += sprintf(le, "%ld", aLong); + } break; + case POPT_ARG_FLOAT: + { + double aDouble = *((float *)opt->arg); + le += sprintf(le, "%g", aDouble); + } break; + case POPT_ARG_DOUBLE: + { + double aDouble = *((double *)opt->arg); + le += sprintf(le, "%g", aDouble); + } break; + case POPT_ARG_STRING: + { + const char *s = *(const char **)opt->arg; + if (s == NULL) { + strcpy(le, "null"); + le += strlen(le); + } + else { + size_t slen = + 4 * lineLength - (le - l) - sizeof ("\"...\")"); + *le++ = '"'; + strncpy(le, s, slen); + le[slen] = '\0'; + le += strlen(le); + if (slen < strlen(s)) { + strcpy(le, "..."); + le += strlen(le); + } + *le++ = '"'; + } + } + break; + case POPT_ARG_NONE: + default: + l = _free(l); + return NULL; + break; + } + *le++ = ')'; + *le = '\0'; + + return l; +} + +static void singleOptionHelp(FILE * fp, int maxLeftCol, + const struct popt_option *opt, + const char *translation_domain) +{ + int indentLength = maxLeftCol + 5; + int lineLength = 79 - indentLength; + const char *help = D_(translation_domain, opt->descrip); + const char *argDescrip = getArgDescrip(opt, translation_domain); + int helpLength; + char *defs = NULL; + char *left; + int nb = maxLeftCol + 1; + + if (opt->longName) + nb += strlen(opt->longName); + if (argDescrip) + nb += strlen(argDescrip); + + left = malloc(nb); + if (left == NULL) + return; + left[0] = '\0'; + left[maxLeftCol] = '\0'; + + if (opt->longName && opt->shortName) + sprintf(left, "-%c, %s%s", opt->shortName, + ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + else if (opt->shortName != '\0') + sprintf(left, "-%c", opt->shortName); + else if (opt->longName) + sprintf(left, "%s%s", + ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + if (!*left) + goto out; + if (argDescrip) { + char *le = left + strlen(left); + + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + *le++ = '['; + + if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) { + defs = + singleOptionDefaultValue(lineLength, opt, translation_domain); + if (defs) { + char *t = malloc((help ? strlen(help) : 0) + + strlen(defs) + sizeof (" ")); + if (t) { + char *te = t; + *te = '\0'; + if (help) { + strcpy(te, help); + te += strlen(te); + } + *te++ = ' '; + strcpy(te, defs); + defs = _free(defs); + } + defs = t; + } + } + + if (opt->argDescrip == NULL) { + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_NONE: + break; + case POPT_ARG_VAL: + { + long aLong = opt->val; + int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS); + int negate = (opt->argInfo & POPT_ARGFLAG_NOT); + + if (!ops + && (aLong == 0L || aLong == 1L || aLong == -1L)) + break; + *le++ = '['; + switch (ops) { + case POPT_ARGFLAG_OR: + *le++ = '|'; + break; + case POPT_ARGFLAG_AND: + *le++ = '&'; + break; + case POPT_ARGFLAG_XOR: + *le++ = '^'; + break; + default: + break; + } + *le++ = '='; + if (negate) + *le++ = '~'; + + le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong); + + *le++ = ']'; + } + break; + case POPT_ARG_INT: + case POPT_ARG_LONG: + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + case POPT_ARG_STRING: + *le++ = '='; + strcpy(le, argDescrip); + le += strlen(le); + break; + default: + break; + } + } + else { + *le++ = '='; + strcpy(le, argDescrip); + le += strlen(le); + } + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + *le++ = ']'; + *le = '\0'; + } + + if (help) + fprintf(fp, " %-*s ", maxLeftCol, left); + else { + fprintf(fp, " %s\n", left); + goto out; + } + + left = _free(left); + if (defs) { + help = defs; + defs = NULL; + } + + helpLength = strlen(help); + while (helpLength > lineLength) { + const char *ch; + char format[10]; + + ch = help + lineLength - 1; + while (ch > help && !isspace(*ch)) + ch--; + if (ch == help) + break; + while (ch > (help + 1) && isspace(*ch)) + ch--; + ch++; + + sprintf(format, "%%.%ds\n%%%ds", (int)(ch - help), indentLength); + + fprintf(fp, format, help, " "); + + help = ch; + while (isspace(*help) && *help) + help++; + helpLength = strlen(help); + } + + if (helpLength) + fprintf(fp, "%s\n", help); + + out: + defs = _free(defs); + left = _free(left); +} + +static int maxArgWidth(const struct popt_option *opt, + const char *translation_domain) +{ + int max = 0; + int len = 0; + const char *s; + + if (opt != NULL) + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + if (opt->arg) + len = maxArgWidth(opt->arg, translation_domain); + if (len > max) + max = len; + } + else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + len = sizeof (" ") - 1; + if (opt->shortName != '\0') + len += sizeof ("-X") - 1; + if (opt->shortName != '\0' && opt->longName) + len += sizeof (", ") - 1; + if (opt->longName) { + len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH) + ? sizeof ("-") - 1 : sizeof ("--") - 1); + len += strlen(opt->longName); + } + + s = getArgDescrip(opt, translation_domain); + if (s) + len += sizeof ("=") - 1 + strlen(s); + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + len += sizeof ("[]") - 1; + if (len > max) + max = len; + } + + opt++; + } + + return max; +} + +static void itemHelp(FILE * fp, + popt_item items, int nitems, int left, + const char *translation_domain) +{ + popt_item item; + int i; + + if (items != NULL) + for (i = 0, item = items; i < nitems; i++, item++) { + const struct popt_option *opt; + opt = &item->option; + if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + singleOptionHelp(fp, left, opt, translation_domain); + } +} + +static void singleTableHelp(popt_context con, FILE * fp, + const struct popt_option *table, int left, + const char *translation_domain) +{ + const struct popt_option *opt; + const char *sub_transdom; + + if (table == popt_aliasOptions) { + itemHelp(fp, con->aliases, con->numAliases, left, NULL); + itemHelp(fp, con->execs, con->numExecs, left, NULL); + return; + } + + if (table != NULL) + for (opt = table; (opt->longName || opt->shortName || opt->arg); + opt++) { + if ((opt->longName || opt->shortName) + && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + singleOptionHelp(fp, left, opt, translation_domain); + } + + if (table != NULL) + for (opt = table; (opt->longName || opt->shortName || opt->arg); + opt++) { + if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE) + continue; + sub_transdom = getTableTranslationDomain(opt->arg); + if (sub_transdom == NULL) + sub_transdom = translation_domain; + + if (opt->descrip) + fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip)); + + singleTableHelp(con, fp, opt->arg, left, sub_transdom); + } +} + +static int showHelpIntro(popt_context con, FILE * fp) +{ + int len = 6; + const char *fn; + + fprintf(fp, POPT_("Usage:")); + if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { + fn = con->optionStack->argv[0]; + + if (fn == NULL) + return len; + if (strchr(fn, '/')) + fn = strrchr(fn, '/') + 1; + fprintf(fp, " %s", fn); + len += strlen(fn) + 1; + } + + return len; +} + +void popt_printhelp(popt_context con, FILE * fp, int flags) +{ + int leftColWidth; + + (void)showHelpIntro(con, fp); + if (con->otherHelp) + fprintf(fp, " %s\n", con->otherHelp); + else + fprintf(fp, " %s\n", POPT_("[OPTION...]")); + + leftColWidth = maxArgWidth(con->options, NULL); + singleTableHelp(con, fp, con->options, leftColWidth, NULL); +} + +static int singleOptionUsage(FILE * fp, int cursor, + const struct popt_option *opt, + const char *translation_domain) +{ + int len = 3; + 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; + len++; + shortStr[0] = opt->shortName; + shortStr[1] = '\0'; + } + else if (opt->longName) { + len += 1 + strlen(opt->longName); + item = opt->longName; + } + + if (len == 3) + return cursor; + + if (argDescrip) + len += strlen(argDescrip) + 1; + + 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 : "")); + + return cursor + len + 1; +} + +static int itemUsage(FILE * fp, int cursor, popt_item item, int nitems, + const char *translation_domain) +{ + int i; + + if (item != NULL) + for (i = 0; i < nitems; i++, item++) { + const struct popt_option *opt; + opt = &item->option; + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { + translation_domain = (const char *)opt->arg; + } + else if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + cursor = + singleOptionUsage(fp, cursor, opt, translation_domain); + } + } + + return cursor; +} + +static int singleTableUsage(popt_context con, FILE * fp, + int cursor, const struct popt_option *opt, + const char *translation_domain) +{ + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg); opt++) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { + translation_domain = (const char *)opt->arg; + } + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + if (opt->arg) + cursor = singleTableUsage(con, fp, cursor, opt->arg, + translation_domain); + } + else if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + cursor = + singleOptionUsage(fp, cursor, opt, translation_domain); + } + } + + return cursor; +} + +static int showShortOptions(const struct popt_option *opt, FILE * fp, + char *str) +{ + char *s = alloca(300); + + s[0] = '\0'; + if (str == NULL) { + memset(s, 0, sizeof (s)); + str = s; + } + + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg); opt++) { + if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) + str[strlen(str)] = opt->shortName; + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) + if (opt->arg) + (void)showShortOptions(opt->arg, fp, str); + } + + if (s != str || *s != '\0') + return 0; + + fprintf(fp, " [-%s]", s); + return strlen(s) + 4; +} + +void popt_printusage(popt_context con, FILE * fp, int flags) +{ + int cursor; + + cursor = showHelpIntro(con, fp); + cursor += showShortOptions(con->options, fp, NULL); + (void)singleTableUsage(con, fp, cursor, con->options, NULL); + (void)itemUsage(fp, cursor, con->aliases, con->numAliases, NULL); + (void)itemUsage(fp, cursor, con->execs, con->numExecs, NULL); + + if (con->otherHelp) { + cursor += strlen(con->otherHelp) + 1; + if (cursor > 79) + fprintf(fp, "\n "); + fprintf(fp, " %s", con->otherHelp); + } + + fprintf(fp, "\n"); +} + +void popt_setotheroptionhelp(popt_context con, const char *text) +{ + con->otherHelp = _free(con->otherHelp); + con->otherHelp = strdup(text); +} Index: ossp-pkg/popt/popt.h RCS File: /v/ossp/cvs/ossp-pkg/popt/popt.h,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/popt/popt.h,v' | diff -u /dev/null - -L'ossp-pkg/popt/popt.h' 2>/dev/null --- ossp-pkg/popt/popt.h +++ - 2024-05-18 09:30:05.398114597 +0200 @@ -0,0 +1,207 @@ +/* + * Option Parsing Library (POPT) + * Copyright (c) 1998-2002 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the X Consortium shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from the X Consortium. + * + * NOTICE: + * This is an automatically generated, stripped down version of the + * POPT 1.6.3 library from Red Hat, Inc. This version is still + * distributed under above Open Source license, but Red Hat is no longer + * responsible for this version. Contact The OSSP Project instead. + */ + +#ifndef __POPT_H__ +#define __POPT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define POPT_OPTION_DEPTH 10 + +#define POPT_ARG_NONE 0 +#define POPT_ARG_STRING 1 +#define POPT_ARG_INT 2 +#define POPT_ARG_LONG 3 +#define POPT_ARG_INCLUDE_TABLE 4 +#define POPT_ARG_CALLBACK 5 +#define POPT_ARG_INTL_DOMAIN 6 +#define POPT_ARG_VAL 7 +#define POPT_ARG_FLOAT 8 +#define POPT_ARG_DOUBLE 9 + +#define POPT_ARG_MASK 0x0000FFFF + +#define POPT_ARGFLAG_ONEDASH 0x80000000 +#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 +#define POPT_ARGFLAG_STRIP 0x20000000 +#define POPT_ARGFLAG_OPTIONAL 0x10000000 + +#define POPT_ARGFLAG_OR 0x08000000 +#define POPT_ARGFLAG_NOR 0x09000000 +#define POPT_ARGFLAG_AND 0x04000000 +#define POPT_ARGFLAG_NAND 0x05000000 +#define POPT_ARGFLAG_XOR 0x02000000 +#define POPT_ARGFLAG_NOT 0x01000000 +#define POPT_ARGFLAG_LOGICALOPS \ + (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR) + +#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR) + +#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND) + +#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 + +#define POPT_CBFLAG_PRE 0x80000000 +#define POPT_CBFLAG_POST 0x40000000 +#define POPT_CBFLAG_INC_DATA 0x20000000 +#define POPT_CBFLAG_SKIPOPTION 0x10000000 +#define POPT_CBFLAG_CONTINUE 0x08000000 + +#define POPT_ERROR_NOARG -10 +#define POPT_ERROR_BADOPT -11 +#define POPT_ERROR_OPTSTOODEEP -13 +#define POPT_ERROR_BADQUOTE -15 +#define POPT_ERROR_ERRNO -16 +#define POPT_ERROR_BADNUMBER -17 +#define POPT_ERROR_OVERFLOW -18 +#define POPT_ERROR_BADOPERATION -19 +#define POPT_ERROR_NULLARG -20 +#define POPT_ERROR_MALLOC -21 + +#define POPT_BADOPTION_NOALIAS (1 << 0) + +#define POPT_CONTEXT_NO_EXEC (1 << 0) +#define POPT_CONTEXT_KEEP_FIRST (1 << 1) +#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) +#define POPT_CONTEXT_ARG_OPTS (1 << 4) + + struct popt_option { + const char *longName; + char shortName; + int argInfo; + void *arg; + int val; + const char *descrip; + const char *argDescrip; + }; + + struct popt_alias { + const char *longName; + char shortName; + int argc; + const char **argv; + }; + + typedef struct popt_item_s { + struct popt_option option; + int argc; + const char **argv; + } *popt_item; + + extern struct popt_option popt_aliasOptions[]; +#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_aliasOptions, \ + 0, "Options implemented via popt alias/exec:", NULL }, + + extern struct popt_option popt_helpoptions[]; +#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_helpoptions, \ + 0, "Help options:", NULL }, + +#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL } + + typedef struct popt_context_s *popt_context; + +#ifndef __cplusplus + + typedef struct popt_option *popt_option; + +#endif + + enum popt_callbackreason { POPT_CALLBACK_REASON_PRE, + POPT_CALLBACK_REASON_POST, + POPT_CALLBACK_REASON_OPTION + }; + + typedef void (*popt_callbacktype) (popt_context con, + enum popt_callbackreason reason, + const struct popt_option * opt, + const char *arg, const void *data); + + popt_context popt_getcontext(const char *name, + int argc, const char **argv, + const struct popt_option *options, + int flags); + + void popt_resetcontext(popt_context con); + + int popt_getnextopt(popt_context con); + + const char *popt_getoptarg(popt_context con); + + const char *popt_getarg(popt_context con); + + const char *popt_peekarg(popt_context con); + + const char **popt_getargs(popt_context con); + + const char *popt_badoption(popt_context con, int flags); + + popt_context popt_freecontext(popt_context con); + + int popt_stuffargs(popt_context con, const char **argv); + + int popt_addalias(popt_context con, struct popt_alias alias, int flags); + + int popt_additem(popt_context con, popt_item newItem, int flags); + + int popt_readconfigfile(popt_context con, const char *fn); + + int popt_readdefaultconfig(popt_context con, int useEnv); + + int popt_dupargv(int argc, const char **argv, + int *argcPtr, const char ***argvPtr); + + int popt_parseargvstring(const char *s, + int *argcPtr, const char ***argvPtr); + + const char *const popt_strerror(const int error); + + void popt_setexecpath(popt_context con, const char *path, + int allowAbsolute); + + void popt_printhelp(popt_context con, FILE * fp, int flags); + + void popt_printusage(popt_context con, FILE * fp, int flags); + + void popt_setotheroptionhelp(popt_context con, const char *text); + + const char *popt_getinvocationname(popt_context con); + + int popt_strippedargv(popt_context con, int argc, char **argv); + +#ifdef __cplusplus +} +#endif +#endif