popt 1.18
poptparse.c
Go to the documentation of this file.
1
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
13int 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
54int 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 int argc = 0;
61 size_t buflen = strlen(s) + 1;
62 char * buf, * bufOrig = NULL;
63 int rc = POPT_ERROR_MALLOC;
64
65 if (argv == NULL) return rc;
66 buf = bufOrig = calloc((size_t)1, buflen);
67 if (buf == NULL) {
68 free(argv);
69 return rc;
70 }
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) {
81 goto exit;
82 }
83 if (*src != quote) *buf++ = '\\';
84 }
85 *buf++ = *src;
86 } else if (_isspaceptr(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 break;
101 case '\\':
102 src++;
103 if (!*src) {
105 goto exit;
106 }
107 /* fallthrough */
108 default:
109 *buf++ = *src;
110 break;
111 }
112 }
113
114 if (strlen(argv[argc])) {
115 argc++, buf++;
116 }
117
118 rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
119
120exit:
121 if (bufOrig) free(bufOrig);
122 if (argv) free(argv);
123 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 */
131int poptConfigFileToString(FILE *fp, char ** argstrp,
132 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 size_t argvlen = 0;
141 size_t maxlinelen = sizeof(line);
142 size_t linelen;
143 size_t maxargvlen = (size_t)480;
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 p = line;
159
160 /* loop until first non-space char or EOL */
161 while( *p != '\0' && _isspaceptr(p) )
162 p++;
163
164 linelen = strlen(p);
165 if (linelen >= maxlinelen-1) {
166 free(argstr);
167 return POPT_ERROR_OVERFLOW; /* XXX line too long */
168 }
169
170 if (*p == '\0' || *p == '\n') continue; /* line is empty */
171 if (*p == '#') continue; /* comment line */
172
173 q = p;
174
175 while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
176 q++;
177
178 if (_isspaceptr(q)) {
179 /* a space after the name, find next non space */
180 *q++='\0';
181 while( *q != '\0' && _isspaceptr(q) ) q++;
182 }
183 if (*q == '\0') {
184 /* single command line option (ie, no name=val, just name) */
185 q[-1] = '\0'; /* kill off newline from fgets() call */
186 argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
187 if (argvlen >= maxargvlen) {
188 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
189 argstr = realloc(argstr, maxargvlen);
190 if (argstr == NULL) return POPT_ERROR_MALLOC;
191 }
192 strcat(argstr, " --");
193 strcat(argstr, p);
194 continue;
195 }
196 if (*q != '=')
197 continue; /* XXX for now, silently ignore bogus line */
198
199 /* *q is an equal sign. */
200 *q++ = '\0';
201
202 /* find next non-space letter of value */
203 while (*q != '\0' && _isspaceptr(q))
204 q++;
205 if (*q == '\0')
206 continue; /* XXX silently ignore missing value */
207
208 /* now, loop and strip all ending whitespace */
209 x = p + linelen;
210 while (_isspaceptr(--x))
211 *x = '\0'; /* null out last char if space (including fgets() NL) */
212
213 /* rest of line accept */
214 t = (size_t)(x - p);
215 argvlen += t + (sizeof("' --='")-1);
216 if (argvlen >= maxargvlen) {
217 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
218 argstr = realloc(argstr, maxargvlen);
219 if (argstr == NULL) return POPT_ERROR_MALLOC;
220 }
221 strcat(argstr, " --");
222 strcat(argstr, p);
223 strcat(argstr, "=\"");
224 strcat(argstr, q);
225 strcat(argstr, "\"");
226 }
227
228 *argstrp = argstr;
229 return 0;
230}
#define POPT_ERROR_OVERFLOW
Definition popt.h:99
#define POPT_ERROR_NOARG
Definition popt.h:93
#define POPT_ERROR_BADQUOTE
Definition popt.h:96
#define POPT_ERROR_MALLOC
Definition popt.h:102
#define POPT_ERROR_NULLARG
Definition popt.h:101
int poptConfigFileToString(FILE *fp, char **argstrp, int flags)
Parses an input configuration file and returns an string that is a command line.
Definition poptparse.c:131
int poptDupArgv(int argc, const char **argv, int *argcPtr, const char ***argvPtr)
Duplicate an argument array.
Definition poptparse.c:13
#define POPT_ARGV_ARRAY_GROW_DELTA
Definition poptparse.c:11
int poptParseArgvString(const char *s, int *argcPtr, const char ***argvPtr)
Parse a string into an argument array.
Definition poptparse.c:54
#define _isspaceptr(_chp)
Definition system.h:12
#define UNUSED(x)
Definition system.h:65
static char * stpcpy(char *dest, const char *src)
Definition system.h:31