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