123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /** \ingroup popt
- * \file popt/poptparse.c
- */
- /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
- file accompanying popt source distributions, available from
- ftp://ftp.rpm.org/pub/rpm/dist. */
- #include "system.h"
- #define POPT_ARGV_ARRAY_GROW_DELTA 5
- int poptDupArgv(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) /* XXX can't happen */
- 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) /* XXX can't happen */
- return POPT_ERROR_MALLOC;
- argv2 = (void *) dst;
- dst += (argc + 1) * sizeof(*argv);
- *dst = '\0';
- for (i = 0; i < argc; i++) {
- argv2[i] = dst;
- dst = stpcpy(dst, argv[i]);
- dst++; /* trailing NUL */
- }
- argv2[argc] = NULL;
- if (argvPtr) {
- *argvPtr = argv2;
- } else {
- free(argv2);
- argv2 = NULL;
- }
- if (argcPtr)
- *argcPtr = argc;
- return 0;
- }
- int poptParseArgvString(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;
- size_t buflen = strlen(s) + 1;
- char * buf, * bufOrig = NULL;
- int rc = POPT_ERROR_MALLOC;
- if (argv == NULL) return rc;
- buf = bufOrig = calloc((size_t)1, buflen);
- if (buf == NULL) {
- free(argv);
- 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 (_isspaceptr(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;
- /*@switchbreak@*/ break;
- case '\\':
- src++;
- if (!*src) {
- rc = POPT_ERROR_BADQUOTE;
- goto exit;
- }
- /*@fallthrough@*/
- default:
- *buf++ = *src;
- /*@switchbreak@*/ break;
- }
- }
- if (strlen(argv[argc])) {
- argc++, buf++;
- }
- rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
- exit:
- if (bufOrig) free(bufOrig);
- if (argv) free(argv);
- return rc;
- }
- /* still in the dev stage.
- * return values, perhaps 1== file erro
- * 2== line to long
- * 3== umm.... more?
- */
- int poptConfigFileToString(FILE *fp, char ** argstrp,
- /*@unused@*/ UNUSED(int flags))
- {
- char line[999];
- char * argstr;
- char * p;
- char * q;
- char * x;
- size_t t;
- size_t argvlen = 0;
- size_t maxlinelen = sizeof(line);
- size_t linelen;
- size_t maxargvlen = (size_t)480;
- *argstrp = NULL;
- /* | this_is = our_line
- * p q x
- */
- if (fp == NULL)
- return POPT_ERROR_NULLARG;
- argstr = calloc(maxargvlen, sizeof(*argstr));
- if (argstr == NULL) return POPT_ERROR_MALLOC;
- while (fgets(line, (int)maxlinelen, fp) != NULL) {
- p = line;
- /* loop until first non-space char or EOL */
- while( *p != '\0' && _isspaceptr(p) )
- p++;
- linelen = strlen(p);
- if (linelen >= maxlinelen-1) {
- free(argstr);
- return POPT_ERROR_OVERFLOW; /* XXX line too long */
- }
- if (*p == '\0' || *p == '\n') continue; /* line is empty */
- if (*p == '#') continue; /* comment line */
- q = p;
- while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
- q++;
- if (_isspaceptr(q)) {
- /* a space after the name, find next non space */
- *q++='\0';
- while( *q != '\0' && _isspaceptr(q) ) q++;
- }
- if (*q == '\0') {
- /* single command line option (ie, no name=val, just name) */
- q[-1] = '\0'; /* kill off newline from fgets() call */
- argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
- if (argvlen >= maxargvlen) {
- maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
- argstr = realloc(argstr, maxargvlen);
- if (argstr == NULL) return POPT_ERROR_MALLOC;
- }
- strcat(argstr, " --");
- strcat(argstr, p);
- continue;
- }
- if (*q != '=')
- continue; /* XXX for now, silently ignore bogus line */
-
- /* *q is an equal sign. */
- *q++ = '\0';
- /* find next non-space letter of value */
- while (*q != '\0' && _isspaceptr(q))
- q++;
- if (*q == '\0')
- continue; /* XXX silently ignore missing value */
- /* now, loop and strip all ending whitespace */
- x = p + linelen;
- while (_isspaceptr(--x))
- *x = '\0'; /* null out last char if space (including fgets() NL) */
- /* rest of line accept */
- t = (size_t)(x - p);
- argvlen += t + (sizeof("' --='")-1);
- if (argvlen >= maxargvlen) {
- maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
- argstr = realloc(argstr, maxargvlen);
- if (argstr == NULL) return POPT_ERROR_MALLOC;
- }
- strcat(argstr, " --");
- strcat(argstr, p);
- strcat(argstr, "=\"");
- strcat(argstr, q);
- strcat(argstr, "\"");
- }
- *argstrp = argstr;
- return 0;
- }
|