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