*** /dev/null Sat Nov 23 01:16:19 2024
--- - Sat Nov 23 01:16:25 2024
***************
*** 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 <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <limits.h>
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ #include <unistd.h>
+
+ #ifndef __GNUC__
+ # if HAVE_ALLOCA_H
+ # include <alloca.h>
+ # 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 <libintl.h>
+ #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 <float.h>
+ #endif
+ #include <math.h>
+
+ 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);
+ }
|