Annotation of embedaddon/rsync/popt/poptparse.c, revision 1.1

1.1     ! misho       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>