File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / popt / poptparse.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:09:30 2012 UTC (12 years, 4 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, v3_1_2p5, rsync3_0_9p0, RSYNC3_1_0, RSYNC3_0_9, HEAD
rsync

    1: /** \ingroup popt
    2:  * \file popt/poptparse.c
    3:  */
    4: 
    5: /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
    6:    file accompanying popt source distributions, available from 
    7:    ftp://ftp.rpm.org/pub/rpm/dist. */
    8: 
    9: #include "system.h"
   10: 
   11: #include "poptint.h"
   12: 
   13: #define POPT_ARGV_ARRAY_GROW_DELTA 5
   14: 
   15: /*@-boundswrite@*/
   16: int poptDupArgv(int argc, const char **argv,
   17: 		int * argcPtr, const char *** argvPtr)
   18: {
   19:     size_t nb = (argc + 1) * sizeof(*argv);
   20:     const char ** argv2;
   21:     char * dst;
   22:     int i;
   23: 
   24:     if (argc <= 0 || argv == NULL)	/* XXX can't happen */
   25: 	return POPT_ERROR_NOARG;
   26:     for (i = 0; i < argc; i++) {
   27: 	if (argv[i] == NULL)
   28: 	    return POPT_ERROR_NOARG;
   29: 	nb += strlen(argv[i]) + 1;
   30:     }
   31: 	
   32:     dst = malloc(nb);
   33:     if (dst == NULL)			/* XXX can't happen */
   34: 	return POPT_ERROR_MALLOC;
   35:     argv2 = (void *) dst;
   36:     dst += (argc + 1) * sizeof(*argv);
   37: 
   38:     /*@-branchstate@*/
   39:     for (i = 0; i < argc; i++) {
   40: 	argv2[i] = dst;
   41: 	dst += strlcpy(dst, argv[i], nb) + 1;
   42:     }
   43:     /*@=branchstate@*/
   44:     argv2[argc] = NULL;
   45: 
   46:     if (argvPtr) {
   47: 	*argvPtr = argv2;
   48:     } else {
   49: 	free(argv2);
   50: 	argv2 = NULL;
   51:     }
   52:     if (argcPtr)
   53: 	*argcPtr = argc;
   54:     return 0;
   55: }
   56: /*@=boundswrite@*/
   57: 
   58: /*@-bounds@*/
   59: int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
   60: {
   61:     const char * src;
   62:     char quote = '\0';
   63:     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
   64:     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
   65:     int argc = 0;
   66:     int buflen = strlen(s) + 1;
   67:     char * buf = memset(alloca(buflen), 0, buflen);
   68:     int rc = POPT_ERROR_MALLOC;
   69: 
   70:     if (argv == NULL) return rc;
   71:     argv[argc] = buf;
   72: 
   73:     for (src = s; *src != '\0'; src++) {
   74: 	if (quote == *src) {
   75: 	    quote = '\0';
   76: 	} else if (quote != '\0') {
   77: 	    if (*src == '\\') {
   78: 		src++;
   79: 		if (!*src) {
   80: 		    rc = POPT_ERROR_BADQUOTE;
   81: 		    goto exit;
   82: 		}
   83: 		if (*src != quote) *buf++ = '\\';
   84: 	    }
   85: 	    *buf++ = *src;
   86: 	} else if (isSpace(src)) {
   87: 	    if (*argv[argc] != '\0') {
   88: 		buf++, argc++;
   89: 		if (argc == argvAlloced) {
   90: 		    argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
   91: 		    argv = realloc(argv, sizeof(*argv) * argvAlloced);
   92: 		    if (argv == NULL) goto exit;
   93: 		}
   94: 		argv[argc] = buf;
   95: 	    }
   96: 	} else switch (*src) {
   97: 	  case '"':
   98: 	  case '\'':
   99: 	    quote = *src;
  100: 	    /*@switchbreak@*/ break;
  101: 	  case '\\':
  102: 	    src++;
  103: 	    if (!*src) {
  104: 		rc = POPT_ERROR_BADQUOTE;
  105: 		goto exit;
  106: 	    }
  107: 	    /*@fallthrough@*/
  108: 	  default:
  109: 	    *buf++ = *src;
  110: 	    /*@switchbreak@*/ break;
  111: 	}
  112:     }
  113: 
  114:     if (strlen(argv[argc])) {
  115: 	argc++, buf++;
  116:     }
  117: 
  118:     rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
  119: 
  120: exit:
  121:     if (argv) free(argv);
  122:     return rc;
  123: }
  124: /*@=bounds@*/
  125: 
  126: /* still in the dev stage.
  127:  * return values, perhaps 1== file erro
  128:  * 2== line to long
  129:  * 3== umm.... more?
  130:  */
  131: int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int flags))
  132: {
  133:     char line[999];
  134:     char * argstr;
  135:     char * p;
  136:     char * q;
  137:     char * x;
  138:     int t;
  139:     int argvlen = 0;
  140:     size_t maxlinelen = sizeof(line);
  141:     size_t linelen;
  142:     int maxargvlen = 480;
  143:     int linenum = 0;
  144: 
  145:     *argstrp = NULL;
  146: 
  147:     /*   |   this_is   =   our_line
  148:      *	     p             q      x
  149:      */
  150: 
  151:     if (fp == NULL)
  152: 	return POPT_ERROR_NULLARG;
  153: 
  154:     argstr = calloc(maxargvlen, sizeof(*argstr));
  155:     if (argstr == NULL) return POPT_ERROR_MALLOC;
  156: 
  157:     while (fgets(line, (int)maxlinelen, fp) != NULL) {
  158: 	linenum++;
  159: 	p = line;
  160: 
  161: 	/* loop until first non-space char or EOL */
  162: 	while( *p != '\0' && isSpace(p) )
  163: 	    p++;
  164: 
  165: 	linelen = strlen(p);
  166: 	if (linelen >= maxlinelen-1) {
  167: 	    free(argstr);
  168: 	    return POPT_ERROR_OVERFLOW;	/* XXX line too long */
  169: 	}
  170: 
  171: 	if (*p == '\0' || *p == '\n') continue;	/* line is empty */
  172: 	if (*p == '#') continue;		/* comment line */
  173: 
  174: 	q = p;
  175: 
  176: 	while (*q != '\0' && (!isSpace(q)) && *q != '=')
  177: 	    q++;
  178: 
  179: 	if (isSpace(q)) {
  180: 	    /* a space after the name, find next non space */
  181: 	    *q++='\0';
  182: 	    while( *q != '\0' && isSpace(q) ) q++;
  183: 	}
  184: 	if (*q == '\0') {
  185: 	    /* single command line option (ie, no name=val, just name) */
  186: 	    q[-1] = '\0';		/* kill off newline from fgets() call */
  187: 	    argvlen += (t = q - p) + (sizeof(" --")-1);
  188: 	    if (argvlen >= maxargvlen) {
  189: 		maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
  190: 		argstr = realloc(argstr, maxargvlen);
  191: 		if (argstr == NULL) return POPT_ERROR_MALLOC;
  192: 	    }
  193: 	    strlcat(argstr, " --", maxargvlen);
  194: 	    strlcat(argstr, p, maxargvlen);
  195: 	    continue;
  196: 	}
  197: 	if (*q != '=')
  198: 	    continue;	/* XXX for now, silently ignore bogus line */
  199: 		
  200: 	/* *q is an equal sign. */
  201: 	*q++ = '\0';
  202: 
  203: 	/* find next non-space letter of value */
  204: 	while (*q != '\0' && isSpace(q))
  205: 	    q++;
  206: 	if (*q == '\0')
  207: 	    continue;	/* XXX silently ignore missing value */
  208: 
  209: 	/* now, loop and strip all ending whitespace */
  210: 	x = p + linelen;
  211: 	while (isSpace(--x))
  212: 	    *x = 0;	/* null out last char if space (including fgets() NL) */
  213: 
  214: 	/* rest of line accept */
  215: 	t = x - p;
  216: 	argvlen += t + (sizeof("' --='")-1);
  217: 	if (argvlen >= maxargvlen) {
  218: 	    maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
  219: 	    argstr = realloc(argstr, maxargvlen);
  220: 	    if (argstr == NULL) return POPT_ERROR_MALLOC;
  221: 	}
  222: 	strlcat(argstr, " --", maxargvlen);
  223: 	strlcat(argstr, p, maxargvlen);
  224: 	strlcat(argstr, "=\"", maxargvlen);
  225: 	strlcat(argstr, q, maxargvlen);
  226: 	strlcat(argstr, "\"", maxargvlen);
  227:     }
  228: 
  229:     *argstrp = argstr;
  230:     return 0;
  231: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>