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