File: | hw/xfree86/parser/scan.c |
Location: | line 241, column 5 |
Description: | Use of memory after it is freed |
1 | /* | |||
2 | * Copyright (c) 1997 Metro Link Incorporated | |||
3 | * | |||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
5 | * copy of this software and associated documentation files (the "Software"), | |||
6 | * to deal in the Software without restriction, including without limitation | |||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
8 | * and/or sell copies of the Software, and to permit persons to whom the | |||
9 | * Software is furnished to do so, subject to the following conditions: | |||
10 | * | |||
11 | * The above copyright notice and this permission notice shall be included in | |||
12 | * all copies or substantial portions of the Software. | |||
13 | * | |||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
17 | * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |||
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | |||
19 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
20 | * SOFTWARE. | |||
21 | * | |||
22 | * Except as contained in this notice, the name of the Metro Link shall not be | |||
23 | * used in advertising or otherwise to promote the sale, use or other dealings | |||
24 | * in this Software without prior written authorization from Metro Link. | |||
25 | * | |||
26 | */ | |||
27 | /* | |||
28 | * Copyright (c) 1997-2003 by The XFree86 Project, Inc. | |||
29 | * | |||
30 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
31 | * copy of this software and associated documentation files (the "Software"), | |||
32 | * to deal in the Software without restriction, including without limitation | |||
33 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
34 | * and/or sell copies of the Software, and to permit persons to whom the | |||
35 | * Software is furnished to do so, subject to the following conditions: | |||
36 | * | |||
37 | * The above copyright notice and this permission notice shall be included in | |||
38 | * all copies or substantial portions of the Software. | |||
39 | * | |||
40 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
41 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
42 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
43 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
44 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
45 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
46 | * OTHER DEALINGS IN THE SOFTWARE. | |||
47 | * | |||
48 | * Except as contained in this notice, the name of the copyright holder(s) | |||
49 | * and author(s) shall not be used in advertising or otherwise to promote | |||
50 | * the sale, use or other dealings in this Software without prior written | |||
51 | * authorization from the copyright holder(s) and author(s). | |||
52 | */ | |||
53 | ||||
54 | #ifdef HAVE_XORG_CONFIG_H1 | |||
55 | #include <xorg-config.h> | |||
56 | #endif | |||
57 | ||||
58 | #include <ctype.h> | |||
59 | #include <stdio.h> | |||
60 | #include <stdlib.h> | |||
61 | #include <string.h> | |||
62 | #include <sys/types.h> | |||
63 | #include <dirent.h> | |||
64 | #include <unistd.h> | |||
65 | #include <stdarg.h> | |||
66 | #include <X11/Xdefs.h> | |||
67 | #include <X11/Xfuncproto.h> | |||
68 | ||||
69 | #if defined(_POSIX_SOURCE) | |||
70 | #include <limits.h> | |||
71 | #else | |||
72 | #define _POSIX_SOURCE | |||
73 | #include <limits.h> | |||
74 | #undef _POSIX_SOURCE | |||
75 | #endif /* _POSIX_SOURCE */ | |||
76 | ||||
77 | #if !defined(MAXHOSTNAMELEN32) | |||
78 | #define MAXHOSTNAMELEN32 32 | |||
79 | #endif /* !MAXHOSTNAMELEN */ | |||
80 | ||||
81 | /* For PATH_MAX */ | |||
82 | #include "misc.h" | |||
83 | ||||
84 | #include "Configint.h" | |||
85 | #include "xf86tokens.h" | |||
86 | ||||
87 | #define CONFIG_BUF_LEN1024 1024 | |||
88 | #define CONFIG_MAX_FILES64 64 | |||
89 | ||||
90 | static int StringToToken(const char *, xf86ConfigSymTabRec *); | |||
91 | ||||
92 | static struct { | |||
93 | FILE *file; | |||
94 | char *path; | |||
95 | } configFiles[CONFIG_MAX_FILES64]; | |||
96 | static const char **builtinConfig = NULL((void*)0); | |||
97 | static int builtinIndex = 0; | |||
98 | static int configPos = 0; /* current readers position */ | |||
99 | static int configLineNo = 0; /* linenumber */ | |||
100 | static char *configBuf, *configRBuf; /* buffer for lines */ | |||
101 | static char *configSection = NULL((void*)0); /* name of current section being parsed */ | |||
102 | static int numFiles = 0; /* number of config files */ | |||
103 | static int curFileIndex = 0; /* index of current config file */ | |||
104 | static int pushToken = LOCK_TOKEN; | |||
105 | static int eol_seen = 0; /* private state to handle comments */ | |||
106 | LexRec xf86_lex_val; | |||
107 | ||||
108 | /* | |||
109 | * xf86getNextLine -- | |||
110 | * | |||
111 | * read from the configFiles FILE stream until we encounter a new | |||
112 | * line; this is effectively just a big wrapper for fgets(3). | |||
113 | * | |||
114 | * xf86getToken() assumes that we will read up to the next | |||
115 | * newline; we need to grow configBuf and configRBuf as needed to | |||
116 | * support that. | |||
117 | */ | |||
118 | ||||
119 | static char * | |||
120 | xf86getNextLine(void) | |||
121 | { | |||
122 | static int configBufLen = CONFIG_BUF_LEN1024; | |||
123 | char *tmpConfigBuf, *tmpConfigRBuf; | |||
124 | int c, i, pos = 0, eolFound = 0; | |||
125 | char *ret = NULL((void*)0); | |||
126 | ||||
127 | /* | |||
128 | * reallocate the string if it was grown last time (i.e., is no | |||
129 | * longer CONFIG_BUF_LEN); we malloc the new strings first, so | |||
130 | * that if either of the mallocs fail, we can fall back on the | |||
131 | * existing buffer allocations | |||
132 | */ | |||
133 | ||||
134 | if (configBufLen != CONFIG_BUF_LEN1024) { | |||
| ||||
135 | ||||
136 | tmpConfigBuf = malloc(CONFIG_BUF_LEN1024); | |||
137 | tmpConfigRBuf = malloc(CONFIG_BUF_LEN1024); | |||
138 | ||||
139 | if (!tmpConfigBuf || !tmpConfigRBuf) { | |||
140 | ||||
141 | /* | |||
142 | * at least one of the mallocs failed; keep the old buffers | |||
143 | * and free any partial allocations | |||
144 | */ | |||
145 | ||||
146 | free(tmpConfigBuf); | |||
147 | free(tmpConfigRBuf); | |||
148 | ||||
149 | } | |||
150 | else { | |||
151 | ||||
152 | /* | |||
153 | * malloc succeeded; free the old buffers and use the new | |||
154 | * buffers | |||
155 | */ | |||
156 | ||||
157 | configBufLen = CONFIG_BUF_LEN1024; | |||
158 | ||||
159 | free(configBuf); | |||
160 | free(configRBuf); | |||
161 | ||||
162 | configBuf = tmpConfigBuf; | |||
163 | configRBuf = tmpConfigRBuf; | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | /* read in another block of chars */ | |||
168 | ||||
169 | do { | |||
170 | ret = fgets(configBuf + pos, configBufLen - pos - 1, | |||
171 | configFiles[curFileIndex].file); | |||
172 | ||||
173 | if (!ret) { | |||
174 | /* | |||
175 | * if the file doesn't end in a newline, add one | |||
176 | * and trigger another read | |||
177 | */ | |||
178 | if (pos != 0) { | |||
179 | strcpy(&configBuf[pos], "\n")__builtin___strcpy_chk (&configBuf[pos], "\n", __builtin_object_size (&configBuf[pos], 2 > 1 ? 1 : 0)); | |||
180 | ret = configBuf; | |||
181 | } | |||
182 | else | |||
183 | break; | |||
184 | } | |||
185 | ||||
186 | /* search for EOL in the new block of chars */ | |||
187 | ||||
188 | for (i = pos; i < (configBufLen - 1); i++) { | |||
189 | c = configBuf[i]; | |||
190 | ||||
191 | if (c == '\0') | |||
192 | break; | |||
193 | ||||
194 | if ((c == '\n') || (c == '\r')) { | |||
195 | eolFound = 1; | |||
196 | break; | |||
197 | } | |||
198 | } | |||
199 | ||||
200 | /* | |||
201 | * if we didn't find EOL, then grow the string and | |||
202 | * read in more | |||
203 | */ | |||
204 | ||||
205 | if (!eolFound) { | |||
206 | ||||
207 | tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN1024); | |||
208 | tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN1024); | |||
209 | ||||
210 | if (!tmpConfigBuf || !tmpConfigRBuf) { | |||
211 | ||||
212 | /* | |||
213 | * at least one of the reallocations failed; use the | |||
214 | * new allocation that succeeded, but we have to | |||
215 | * fallback to the previous configBufLen size and use | |||
216 | * the string we have, even though we don't have an | |||
217 | * EOL | |||
218 | */ | |||
219 | ||||
220 | if (tmpConfigBuf) | |||
221 | configBuf = tmpConfigBuf; | |||
222 | if (tmpConfigRBuf) | |||
223 | configRBuf = tmpConfigRBuf; | |||
224 | ||||
225 | break; | |||
226 | ||||
227 | } | |||
228 | else { | |||
229 | ||||
230 | /* reallocation succeeded */ | |||
231 | ||||
232 | configBuf = tmpConfigBuf; | |||
233 | configRBuf = tmpConfigRBuf; | |||
234 | pos = i; | |||
235 | configBufLen += CONFIG_BUF_LEN1024; | |||
236 | } | |||
237 | } | |||
238 | ||||
239 | } while (!eolFound); | |||
240 | ||||
241 | return ret; | |||
| ||||
242 | } | |||
243 | ||||
244 | /* | |||
245 | * xf86getToken -- | |||
246 | * Read next Token from the config file. Handle the global variable | |||
247 | * pushToken. | |||
248 | */ | |||
249 | int | |||
250 | xf86getToken(xf86ConfigSymTabRec * tab) | |||
251 | { | |||
252 | int c, i; | |||
253 | ||||
254 | /* | |||
255 | * First check whether pushToken has a different value than LOCK_TOKEN. | |||
256 | * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the | |||
257 | * oth * case the next token must be read from the input. | |||
258 | */ | |||
259 | if (pushToken == EOF_TOKEN) | |||
260 | return EOF_TOKEN; | |||
261 | else if (pushToken == LOCK_TOKEN) { | |||
262 | /* | |||
263 | * eol_seen is only set for the first token after a newline. | |||
264 | */ | |||
265 | eol_seen = 0; | |||
266 | ||||
267 | c = configBuf[configPos]; | |||
268 | ||||
269 | /* | |||
270 | * Get start of next Token. EOF is handled, | |||
271 | * whitespaces are skipped. | |||
272 | */ | |||
273 | ||||
274 | again: | |||
275 | if (!c) { | |||
276 | char *ret; | |||
277 | ||||
278 | if (numFiles > 0) | |||
279 | ret = xf86getNextLine(); | |||
280 | else { | |||
281 | if (builtinConfig[builtinIndex] == NULL((void*)0)) | |||
282 | ret = NULL((void*)0); | |||
283 | else { | |||
284 | strlcpy(configBuf,__builtin___strlcpy_chk (configBuf, builtinConfig[builtinIndex ], 1024, __builtin_object_size (configBuf, 2 > 1 ? 1 : 0)) | |||
285 | builtinConfig[builtinIndex], CONFIG_BUF_LEN)__builtin___strlcpy_chk (configBuf, builtinConfig[builtinIndex ], 1024, __builtin_object_size (configBuf, 2 > 1 ? 1 : 0)); | |||
286 | ret = configBuf; | |||
287 | builtinIndex++; | |||
288 | } | |||
289 | } | |||
290 | if (ret == NULL((void*)0)) { | |||
291 | /* | |||
292 | * if necessary, move to the next file and | |||
293 | * read the first line | |||
294 | */ | |||
295 | if (curFileIndex + 1 < numFiles) { | |||
296 | curFileIndex++; | |||
297 | configLineNo = 0; | |||
298 | goto again; | |||
299 | } | |||
300 | else | |||
301 | return pushToken = EOF_TOKEN; | |||
302 | } | |||
303 | configLineNo++; | |||
304 | configPos = 0; | |||
305 | eol_seen = 1; | |||
306 | } | |||
307 | ||||
308 | i = 0; | |||
309 | for (;;) { | |||
310 | c = configBuf[configPos++]; | |||
311 | configRBuf[i++] = c; | |||
312 | switch (c) { | |||
313 | case ' ': | |||
314 | case '\t': | |||
315 | case '\r': | |||
316 | continue; | |||
317 | case '\n': | |||
318 | i = 0; | |||
319 | continue; | |||
320 | } | |||
321 | break; | |||
322 | } | |||
323 | if (c == '\0') | |||
324 | goto again; | |||
325 | ||||
326 | if (c == '#') { | |||
327 | do { | |||
328 | configRBuf[i++] = (c = configBuf[configPos++]); | |||
329 | } | |||
330 | while ((c != '\n') && (c != '\r') && (c != '\0')); | |||
331 | configRBuf[i] = '\0'; | |||
332 | /* XXX no private copy. | |||
333 | * Use xf86addComment when setting a comment. | |||
334 | */ | |||
335 | xf86_lex_val.str = configRBuf; | |||
336 | return COMMENT; | |||
337 | } | |||
338 | ||||
339 | /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */ | |||
340 | else if ((c == ',') && !isalpha(configBuf[configPos])) { | |||
341 | return COMMA; | |||
342 | } | |||
343 | else if ((c == '-') && !isalpha(configBuf[configPos])) { | |||
344 | return DASH; | |||
345 | } | |||
346 | ||||
347 | /* | |||
348 | * Numbers are returned immediately ... | |||
349 | */ | |||
350 | if (isdigit(c)) { | |||
351 | int base; | |||
352 | ||||
353 | if (c == '0') | |||
354 | if ((configBuf[configPos] == 'x') || | |||
355 | (configBuf[configPos] == 'X')) { | |||
356 | base = 16; | |||
357 | xf86_lex_val.numType = PARSE_HEX; | |||
358 | } | |||
359 | else { | |||
360 | base = 8; | |||
361 | xf86_lex_val.numType = PARSE_OCTAL; | |||
362 | } | |||
363 | else { | |||
364 | base = 10; | |||
365 | xf86_lex_val.numType = PARSE_DECIMAL; | |||
366 | } | |||
367 | ||||
368 | configRBuf[0] = c; | |||
369 | i = 1; | |||
370 | while (isdigit(c = configBuf[configPos++]) || | |||
371 | (c == '.') || (c == 'x') || (c == 'X') || | |||
372 | ((base == 16) && (((c >= 'a') && (c <= 'f')) || | |||
373 | ((c >= 'A') && (c <= 'F'))))) | |||
374 | configRBuf[i++] = c; | |||
375 | configPos--; /* GJA -- one too far */ | |||
376 | configRBuf[i] = '\0'; | |||
377 | xf86_lex_val.num = strtoul(configRBuf, NULL((void*)0), 0); | |||
378 | xf86_lex_val.realnum = atof(configRBuf); | |||
379 | return NUMBER; | |||
380 | } | |||
381 | ||||
382 | /* | |||
383 | * All Strings START with a \" ... | |||
384 | */ | |||
385 | else if (c == '\"') { | |||
386 | i = -1; | |||
387 | do { | |||
388 | configRBuf[++i] = (c = configBuf[configPos++]); | |||
389 | } | |||
390 | while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); | |||
391 | configRBuf[i] = '\0'; | |||
392 | xf86_lex_val.str = malloc(strlen(configRBuf) + 1); | |||
393 | strcpy(xf86_lex_val.str, configRBuf)__builtin___strcpy_chk (xf86_lex_val.str, configRBuf, __builtin_object_size (xf86_lex_val.str, 2 > 1 ? 1 : 0)); /* private copy ! */ | |||
394 | return STRING; | |||
395 | } | |||
396 | ||||
397 | /* | |||
398 | * ... and now we MUST have a valid token. The search is | |||
399 | * handled later along with the pushed tokens. | |||
400 | */ | |||
401 | else { | |||
402 | configRBuf[0] = c; | |||
403 | i = 0; | |||
404 | do { | |||
405 | configRBuf[++i] = (c = configBuf[configPos++]); | |||
406 | } | |||
407 | while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && | |||
408 | (c != '\0') && (c != '#')); | |||
409 | --configPos; | |||
410 | configRBuf[i] = '\0'; | |||
411 | i = 0; | |||
412 | } | |||
413 | ||||
414 | } | |||
415 | else { | |||
416 | ||||
417 | /* | |||
418 | * Here we deal with pushed tokens. Reinitialize pushToken again. If | |||
419 | * the pushed token was NUMBER || STRING return them again ... | |||
420 | */ | |||
421 | int temp = pushToken; | |||
422 | ||||
423 | pushToken = LOCK_TOKEN; | |||
424 | ||||
425 | if (temp == COMMA || temp == DASH) | |||
426 | return temp; | |||
427 | if (temp == NUMBER || temp == STRING) | |||
428 | return temp; | |||
429 | } | |||
430 | ||||
431 | /* | |||
432 | * Joop, at last we have to lookup the token ... | |||
433 | */ | |||
434 | if (tab) { | |||
435 | i = 0; | |||
436 | while (tab[i].token != -1) | |||
437 | if (xf86nameCompare(configRBuf, tab[i].name) == 0) | |||
438 | return tab[i].token; | |||
439 | else | |||
440 | i++; | |||
441 | } | |||
442 | ||||
443 | return ERROR_TOKEN; /* Error catcher */ | |||
444 | } | |||
445 | ||||
446 | int | |||
447 | xf86getSubToken(char **comment) | |||
448 | { | |||
449 | int token; | |||
450 | ||||
451 | for (;;) { | |||
452 | token = xf86getToken(NULL((void*)0)); | |||
453 | if (token == COMMENT) { | |||
454 | if (comment) | |||
455 | *comment = xf86addComment(*comment, xf86_lex_val.str); | |||
456 | } | |||
457 | else | |||
458 | return token; | |||
459 | } | |||
460 | /*NOTREACHED*/} | |||
461 | ||||
462 | int | |||
463 | xf86getSubTokenWithTab(char **comment, xf86ConfigSymTabRec * tab) | |||
464 | { | |||
465 | int token; | |||
466 | ||||
467 | for (;;) { | |||
468 | token = xf86getToken(tab); | |||
469 | if (token == COMMENT) { | |||
470 | if (comment) | |||
471 | *comment = xf86addComment(*comment, xf86_lex_val.str); | |||
472 | } | |||
473 | else | |||
474 | return token; | |||
475 | } | |||
476 | /*NOTREACHED*/} | |||
477 | ||||
478 | void | |||
479 | xf86unGetToken(int token) | |||
480 | { | |||
481 | pushToken = token; | |||
482 | } | |||
483 | ||||
484 | char * | |||
485 | xf86tokenString(void) | |||
486 | { | |||
487 | return configRBuf; | |||
488 | } | |||
489 | ||||
490 | int | |||
491 | xf86pathIsAbsolute(const char *path) | |||
492 | { | |||
493 | if (path && path[0] == '/') | |||
494 | return 1; | |||
495 | return 0; | |||
496 | } | |||
497 | ||||
498 | /* A path is "safe" if it is relative and if it contains no ".." elements. */ | |||
499 | int | |||
500 | xf86pathIsSafe(const char *path) | |||
501 | { | |||
502 | if (xf86pathIsAbsolute(path)) | |||
503 | return 0; | |||
504 | ||||
505 | /* Compare with ".." */ | |||
506 | if (!strcmp(path, "..")) | |||
507 | return 0; | |||
508 | ||||
509 | /* Look for leading "../" */ | |||
510 | if (!strncmp(path, "../", 3)) | |||
511 | return 0; | |||
512 | ||||
513 | /* Look for trailing "/.." */ | |||
514 | if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/..")) | |||
515 | return 0; | |||
516 | ||||
517 | /* Look for "/../" */ | |||
518 | if (strstr(path, "/../")) | |||
519 | return 0; | |||
520 | ||||
521 | return 1; | |||
522 | } | |||
523 | ||||
524 | /* | |||
525 | * This function substitutes the following escape sequences: | |||
526 | * | |||
527 | * %A cmdline argument as an absolute path (must be absolute to match) | |||
528 | * %R cmdline argument as a relative path | |||
529 | * %S cmdline argument as a "safe" path (relative, and no ".." elements) | |||
530 | * %X default config file name ("xorg.conf") | |||
531 | * %H hostname | |||
532 | * %E config file environment ($XORGCONFIG) as an absolute path | |||
533 | * %F config file environment ($XORGCONFIG) as a relative path | |||
534 | * %G config file environment ($XORGCONFIG) as a safe path | |||
535 | * %P projroot | |||
536 | * %C sysconfdir | |||
537 | * %D datadir | |||
538 | * %% % | |||
539 | */ | |||
540 | ||||
541 | #ifndef XCONFIGFILE"xorg.conf" | |||
542 | #define XCONFIGFILE"xorg.conf" "xorg.conf" | |||
543 | #endif | |||
544 | #ifndef XCONFIGDIR"xorg.conf.d" | |||
545 | #define XCONFIGDIR"xorg.conf.d" "xorg.conf.d" | |||
546 | #endif | |||
547 | #ifndef XCONFIGSUFFIX".conf" | |||
548 | #define XCONFIGSUFFIX".conf" ".conf" | |||
549 | #endif | |||
550 | #ifndef PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build" | |||
551 | #define PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build" "/usr/X11R6" | |||
552 | #endif | |||
553 | #ifndef SYSCONFDIR"/Users/jeremy/src/freedesktop/jhbuild/build/etc" | |||
554 | #define SYSCONFDIR"/Users/jeremy/src/freedesktop/jhbuild/build/etc" PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build" "/etc" | |||
555 | #endif | |||
556 | #ifndef DATADIR"/Users/jeremy/src/freedesktop/jhbuild/build/share" | |||
557 | #define DATADIR"/Users/jeremy/src/freedesktop/jhbuild/build/share" PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build" "/share" | |||
558 | #endif | |||
559 | #ifndef XCONFENV"XORGCONFIG" | |||
560 | #define XCONFENV"XORGCONFIG" "XORGCONFIG" | |||
561 | #endif | |||
562 | ||||
563 | #define BAIL_OUTdo { free(result); return ((void*)0); } while (0) do { \ | |||
564 | free(result); \ | |||
565 | return NULL((void*)0); \ | |||
566 | } while (0) | |||
567 | ||||
568 | #define CHECK_LENGTHdo { if (l > 1024) { do { free(result); return ((void*)0); } while (0); } } while (0) do { \ | |||
569 | if (l > PATH_MAX1024) { \ | |||
570 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); \ | |||
571 | } \ | |||
572 | } while (0) | |||
573 | ||||
574 | #define APPEND_STR(s)do { if (strlen(s) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, s, __builtin_object_size (result + l, 2 > 1 ? 1 : 0) ); l += strlen(s); } } while (0) do { \ | |||
575 | if (strlen(s) + l > PATH_MAX1024) { \ | |||
576 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); \ | |||
577 | } else { \ | |||
578 | strcpy(result + l, s)__builtin___strcpy_chk (result + l, s, __builtin_object_size ( result + l, 2 > 1 ? 1 : 0)); \ | |||
579 | l += strlen(s); \ | |||
580 | } \ | |||
581 | } while (0) | |||
582 | ||||
583 | static char * | |||
584 | DoSubstitution(const char *template, const char *cmdline, const char *projroot, | |||
585 | int *cmdlineUsed, int *envUsed, const char *XConfigFile) | |||
586 | { | |||
587 | char *result; | |||
588 | int i, l; | |||
589 | static const char *env = NULL((void*)0); | |||
590 | static char *hostname = NULL((void*)0); | |||
591 | ||||
592 | if (!template) | |||
593 | return NULL((void*)0); | |||
594 | ||||
595 | if (cmdlineUsed) | |||
596 | *cmdlineUsed = 0; | |||
597 | if (envUsed) | |||
598 | *envUsed = 0; | |||
599 | ||||
600 | result = malloc(PATH_MAX1024 + 1); | |||
601 | l = 0; | |||
602 | for (i = 0; template[i]; i++) { | |||
603 | if (template[i] != '%') { | |||
604 | result[l++] = template[i]; | |||
605 | CHECK_LENGTHdo { if (l > 1024) { do { free(result); return ((void*)0); } while (0); } } while (0); | |||
606 | } | |||
607 | else { | |||
608 | switch (template[++i]) { | |||
609 | case 'A': | |||
610 | if (cmdline && xf86pathIsAbsolute(cmdline)) { | |||
611 | APPEND_STR(cmdline)do { if (strlen(cmdline) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, cmdline, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(cmdline); } } while (0); | |||
612 | if (cmdlineUsed) | |||
613 | *cmdlineUsed = 1; | |||
614 | } | |||
615 | else | |||
616 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
617 | break; | |||
618 | case 'R': | |||
619 | if (cmdline && !xf86pathIsAbsolute(cmdline)) { | |||
620 | APPEND_STR(cmdline)do { if (strlen(cmdline) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, cmdline, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(cmdline); } } while (0); | |||
621 | if (cmdlineUsed) | |||
622 | *cmdlineUsed = 1; | |||
623 | } | |||
624 | else | |||
625 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
626 | break; | |||
627 | case 'S': | |||
628 | if (cmdline && xf86pathIsSafe(cmdline)) { | |||
629 | APPEND_STR(cmdline)do { if (strlen(cmdline) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, cmdline, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(cmdline); } } while (0); | |||
630 | if (cmdlineUsed) | |||
631 | *cmdlineUsed = 1; | |||
632 | } | |||
633 | else | |||
634 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
635 | break; | |||
636 | case 'X': | |||
637 | APPEND_STR(XConfigFile)do { if (strlen(XConfigFile) + l > 1024) { do { free(result ); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, XConfigFile, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(XConfigFile); } } while (0); | |||
638 | break; | |||
639 | case 'H': | |||
640 | if (!hostname) { | |||
641 | if ((hostname = malloc(MAXHOSTNAMELEN32 + 1))) { | |||
642 | if (gethostname(hostname, MAXHOSTNAMELEN32) == 0) { | |||
643 | hostname[MAXHOSTNAMELEN32] = '\0'; | |||
644 | } | |||
645 | else { | |||
646 | free(hostname); | |||
647 | hostname = NULL((void*)0); | |||
648 | } | |||
649 | } | |||
650 | } | |||
651 | if (hostname) | |||
652 | APPEND_STR(hostname)do { if (strlen(hostname) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, hostname, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(hostname); } } while (0); | |||
653 | break; | |||
654 | case 'E': | |||
655 | if (!env) | |||
656 | env = getenv(XCONFENV"XORGCONFIG"); | |||
657 | if (env && xf86pathIsAbsolute(env)) { | |||
658 | APPEND_STR(env)do { if (strlen(env) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, env, __builtin_object_size (result + l, 2 > 1 ? 1 : 0 )); l += strlen(env); } } while (0); | |||
659 | if (envUsed) | |||
660 | *envUsed = 1; | |||
661 | } | |||
662 | else | |||
663 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
664 | break; | |||
665 | case 'F': | |||
666 | if (!env) | |||
667 | env = getenv(XCONFENV"XORGCONFIG"); | |||
668 | if (env && !xf86pathIsAbsolute(env)) { | |||
669 | APPEND_STR(env)do { if (strlen(env) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, env, __builtin_object_size (result + l, 2 > 1 ? 1 : 0 )); l += strlen(env); } } while (0); | |||
670 | if (envUsed) | |||
671 | *envUsed = 1; | |||
672 | } | |||
673 | else | |||
674 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
675 | break; | |||
676 | case 'G': | |||
677 | if (!env) | |||
678 | env = getenv(XCONFENV"XORGCONFIG"); | |||
679 | if (env && xf86pathIsSafe(env)) { | |||
680 | APPEND_STR(env)do { if (strlen(env) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, env, __builtin_object_size (result + l, 2 > 1 ? 1 : 0 )); l += strlen(env); } } while (0); | |||
681 | if (envUsed) | |||
682 | *envUsed = 1; | |||
683 | } | |||
684 | else | |||
685 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
686 | break; | |||
687 | case 'P': | |||
688 | if (projroot && xf86pathIsAbsolute(projroot)) | |||
689 | APPEND_STR(projroot)do { if (strlen(projroot) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, projroot, __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen(projroot); } } while (0); | |||
690 | else | |||
691 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
692 | break; | |||
693 | case 'C': | |||
694 | APPEND_STR(SYSCONFDIR)do { if (strlen("/Users/jeremy/src/freedesktop/jhbuild/build/etc" ) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, "/Users/jeremy/src/freedesktop/jhbuild/build/etc" , __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen("/Users/jeremy/src/freedesktop/jhbuild/build/etc"); } } while (0); | |||
695 | break; | |||
696 | case 'D': | |||
697 | APPEND_STR(DATADIR)do { if (strlen("/Users/jeremy/src/freedesktop/jhbuild/build/share" ) + l > 1024) { do { free(result); return ((void*)0); } while (0); } else { __builtin___strcpy_chk (result + l, "/Users/jeremy/src/freedesktop/jhbuild/build/share" , __builtin_object_size (result + l, 2 > 1 ? 1 : 0)); l += strlen("/Users/jeremy/src/freedesktop/jhbuild/build/share"); } } while (0); | |||
698 | break; | |||
699 | case '%': | |||
700 | result[l++] = '%'; | |||
701 | CHECK_LENGTHdo { if (l > 1024) { do { free(result); return ((void*)0); } while (0); } } while (0); | |||
702 | break; | |||
703 | default: | |||
704 | fprintf(stderr__stderrp, "invalid escape %%%c found in path template\n", | |||
705 | template[i]); | |||
706 | BAIL_OUTdo { free(result); return ((void*)0); } while (0); | |||
707 | break; | |||
708 | } | |||
709 | } | |||
710 | } | |||
711 | #ifdef DEBUG | |||
712 | fprintf(stderr__stderrp, "Converted `%s' to `%s'\n", template, result); | |||
713 | #endif | |||
714 | return result; | |||
715 | } | |||
716 | ||||
717 | /* | |||
718 | * Given some searching parameters, locate and open the xorg config file. | |||
719 | */ | |||
720 | static char * | |||
721 | OpenConfigFile(const char *path, const char *cmdline, const char *projroot, | |||
722 | const char *confname) | |||
723 | { | |||
724 | char *filepath = NULL((void*)0); | |||
725 | char *pathcopy; | |||
726 | const char *template; | |||
727 | int cmdlineUsed = 0; | |||
728 | FILE *file = NULL((void*)0); | |||
729 | ||||
730 | pathcopy = strdup(path); | |||
731 | for (template = strtok(pathcopy, ","); template && !file; | |||
732 | template = strtok(NULL((void*)0), ",")) { | |||
733 | filepath = DoSubstitution(template, cmdline, projroot, | |||
734 | &cmdlineUsed, NULL((void*)0), confname); | |||
735 | if (!filepath) | |||
736 | continue; | |||
737 | if (cmdline && !cmdlineUsed) { | |||
738 | free(filepath); | |||
739 | filepath = NULL((void*)0); | |||
740 | continue; | |||
741 | } | |||
742 | file = fopen(filepath, "r"); | |||
743 | if (!file) { | |||
744 | free(filepath); | |||
745 | filepath = NULL((void*)0); | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | free(pathcopy); | |||
750 | if (file) { | |||
751 | configFiles[numFiles].file = file; | |||
752 | configFiles[numFiles].path = strdup(filepath); | |||
753 | numFiles++; | |||
754 | } | |||
755 | return filepath; | |||
756 | } | |||
757 | ||||
758 | /* | |||
759 | * Match non-hidden files in the xorg config directory with a .conf | |||
760 | * suffix. This filter is passed to scandir(3). | |||
761 | */ | |||
762 | static int | |||
763 | ConfigFilter(const struct dirent *de) | |||
764 | { | |||
765 | const char *name = de->d_name; | |||
766 | size_t len; | |||
767 | size_t suflen = strlen(XCONFIGSUFFIX".conf"); | |||
768 | ||||
769 | if (!name || name[0] == '.') | |||
770 | return 0; | |||
771 | len = strlen(name); | |||
772 | if (len <= suflen) | |||
773 | return 0; | |||
774 | if (strcmp(&name[len - suflen], XCONFIGSUFFIX".conf") != 0) | |||
775 | return 0; | |||
776 | return 1; | |||
777 | } | |||
778 | ||||
779 | static Bool | |||
780 | AddConfigDirFiles(const char *dirpath, struct dirent **list, int num) | |||
781 | { | |||
782 | int i; | |||
783 | Bool openedFile = FALSE0; | |||
784 | Bool warnOnce = FALSE0; | |||
785 | ||||
786 | for (i = 0; i < num; i++) { | |||
787 | char *path; | |||
788 | FILE *file; | |||
789 | ||||
790 | if (numFiles >= CONFIG_MAX_FILES64) { | |||
791 | if (!warnOnce) { | |||
792 | ErrorF("Maximum number of configuration " "files opened\n"); | |||
793 | warnOnce = TRUE1; | |||
794 | } | |||
795 | continue; | |||
796 | } | |||
797 | ||||
798 | path = malloc(PATH_MAX1024 + 1); | |||
799 | snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, list[i]->d_name)__builtin___snprintf_chk (path, 1024 + 1, 0, __builtin_object_size (path, 2 > 1 ? 1 : 0), "%s/%s", dirpath, list[i]->d_name ); | |||
800 | file = fopen(path, "r"); | |||
801 | if (!file) { | |||
802 | free(path); | |||
803 | continue; | |||
804 | } | |||
805 | openedFile = TRUE1; | |||
806 | ||||
807 | configFiles[numFiles].file = file; | |||
808 | configFiles[numFiles].path = path; | |||
809 | numFiles++; | |||
810 | } | |||
811 | ||||
812 | return openedFile; | |||
813 | } | |||
814 | ||||
815 | /* | |||
816 | * Given some searching parameters, locate and open the xorg config | |||
817 | * directory. The directory does not need to contain config files. | |||
818 | */ | |||
819 | static char * | |||
820 | OpenConfigDir(const char *path, const char *cmdline, const char *projroot, | |||
821 | const char *confname) | |||
822 | { | |||
823 | char *dirpath = NULL((void*)0), *pathcopy; | |||
824 | const char *template; | |||
825 | Bool found = FALSE0; | |||
826 | int cmdlineUsed = 0; | |||
827 | ||||
828 | pathcopy = strdup(path); | |||
829 | for (template = strtok(pathcopy, ","); template && !found; | |||
830 | template = strtok(NULL((void*)0), ",")) { | |||
831 | struct dirent **list = NULL((void*)0); | |||
832 | int num; | |||
833 | ||||
834 | dirpath = DoSubstitution(template, cmdline, projroot, | |||
835 | &cmdlineUsed, NULL((void*)0), confname); | |||
836 | if (!dirpath) | |||
837 | continue; | |||
838 | if (cmdline && !cmdlineUsed) { | |||
839 | free(dirpath); | |||
840 | dirpath = NULL((void*)0); | |||
841 | continue; | |||
842 | } | |||
843 | ||||
844 | /* match files named *.conf */ | |||
845 | num = scandir(dirpath, &list, ConfigFilter, alphasort); | |||
846 | if (num < 0) { | |||
847 | list = NULL((void*)0); | |||
848 | num = 0; | |||
849 | } | |||
850 | found = AddConfigDirFiles(dirpath, list, num); | |||
851 | if (!found) { | |||
852 | free(dirpath); | |||
853 | dirpath = NULL((void*)0); | |||
854 | } | |||
855 | while (num--) | |||
856 | free(list[num]); | |||
857 | free(list); | |||
858 | } | |||
859 | ||||
860 | free(pathcopy); | |||
861 | return dirpath; | |||
862 | } | |||
863 | ||||
864 | /* | |||
865 | * xf86initConfigFiles -- Setup global variables and buffers. | |||
866 | */ | |||
867 | void | |||
868 | xf86initConfigFiles(void) | |||
869 | { | |||
870 | curFileIndex = 0; | |||
871 | configPos = 0; | |||
872 | configLineNo = 0; | |||
873 | pushToken = LOCK_TOKEN; | |||
874 | ||||
875 | configBuf = malloc(CONFIG_BUF_LEN1024); | |||
876 | configRBuf = malloc(CONFIG_BUF_LEN1024); | |||
877 | configBuf[0] = '\0'; /* sanity ... */ | |||
878 | } | |||
879 | ||||
880 | /* | |||
881 | * xf86openConfigFile -- | |||
882 | * | |||
883 | * This function take a config file search path (optional), a command-line | |||
884 | * specified file name (optional) and the ProjectRoot path (optional) and | |||
885 | * locates and opens a config file based on that information. If a | |||
886 | * command-line file name is specified, then this function fails if none | |||
887 | * of the located files. | |||
888 | * | |||
889 | * The return value is a pointer to the actual name of the file that was | |||
890 | * opened. When no file is found, the return value is NULL. The caller should | |||
891 | * free() the returned value. | |||
892 | * | |||
893 | * The escape sequences allowed in the search path are defined above. | |||
894 | * | |||
895 | */ | |||
896 | ||||
897 | #ifndef DEFAULT_CONF_PATH"/etc/X11/%S," "%P/etc/X11/%S," "/etc/X11/%G," "%P/etc/X11/%G," "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," "%P/etc/X11/%X," "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," "%P/lib/X11/%X" | |||
898 | #define DEFAULT_CONF_PATH"/etc/X11/%S," "%P/etc/X11/%S," "/etc/X11/%G," "%P/etc/X11/%G," "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," "%P/etc/X11/%X," "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," "%P/lib/X11/%X" "/etc/X11/%S," \ | |||
899 | "%P/etc/X11/%S," \ | |||
900 | "/etc/X11/%G," \ | |||
901 | "%P/etc/X11/%G," \ | |||
902 | "/etc/X11/%X-%M," \ | |||
903 | "/etc/X11/%X," \ | |||
904 | "/etc/%X," \ | |||
905 | "%P/etc/X11/%X.%H," \ | |||
906 | "%P/etc/X11/%X-%M," \ | |||
907 | "%P/etc/X11/%X," \ | |||
908 | "%P/lib/X11/%X.%H," \ | |||
909 | "%P/lib/X11/%X-%M," \ | |||
910 | "%P/lib/X11/%X" | |||
911 | #endif | |||
912 | ||||
913 | char * | |||
914 | xf86openConfigFile(const char *path, const char *cmdline, const char *projroot) | |||
915 | { | |||
916 | if (!path || !path[0]) | |||
917 | path = DEFAULT_CONF_PATH"/etc/X11/%S," "%P/etc/X11/%S," "/etc/X11/%G," "%P/etc/X11/%G," "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," "%P/etc/X11/%X," "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," "%P/lib/X11/%X"; | |||
918 | if (!projroot || !projroot[0]) | |||
919 | projroot = PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build"; | |||
920 | ||||
921 | /* Search for a config file */ | |||
922 | return OpenConfigFile(path, cmdline, projroot, XCONFIGFILE"xorg.conf"); | |||
923 | } | |||
924 | ||||
925 | /* | |||
926 | * xf86openConfigDirFiles -- | |||
927 | * | |||
928 | * This function take a config directory search path (optional), a | |||
929 | * command-line specified directory name (optional) and the ProjectRoot path | |||
930 | * (optional) and locates and opens a config directory based on that | |||
931 | * information. If a command-line name is specified, then this function | |||
932 | * fails if it is not found. | |||
933 | * | |||
934 | * The return value is a pointer to the actual name of the direcoty that was | |||
935 | * opened. When no directory is found, the return value is NULL. The caller | |||
936 | * should free() the returned value. | |||
937 | * | |||
938 | * The escape sequences allowed in the search path are defined above. | |||
939 | * | |||
940 | */ | |||
941 | char * | |||
942 | xf86openConfigDirFiles(const char *path, const char *cmdline, | |||
943 | const char *projroot) | |||
944 | { | |||
945 | if (!path || !path[0]) | |||
946 | path = DEFAULT_CONF_PATH"/etc/X11/%S," "%P/etc/X11/%S," "/etc/X11/%G," "%P/etc/X11/%G," "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," "%P/etc/X11/%X," "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," "%P/lib/X11/%X"; | |||
947 | if (!projroot || !projroot[0]) | |||
948 | projroot = PROJECTROOT"/Users/jeremy/src/freedesktop/jhbuild/build"; | |||
949 | ||||
950 | /* Search for the multiconf directory */ | |||
951 | return OpenConfigDir(path, cmdline, projroot, XCONFIGDIR"xorg.conf.d"); | |||
952 | } | |||
953 | ||||
954 | void | |||
955 | xf86closeConfigFile(void) | |||
956 | { | |||
957 | int i; | |||
958 | ||||
959 | free(configRBuf); | |||
960 | configRBuf = NULL((void*)0); | |||
961 | free(configBuf); | |||
962 | configBuf = NULL((void*)0); | |||
963 | ||||
964 | if (numFiles == 0) { | |||
965 | builtinConfig = NULL((void*)0); | |||
966 | builtinIndex = 0; | |||
967 | } | |||
968 | for (i = 0; i < numFiles; i++) { | |||
969 | fclose(configFiles[i].file); | |||
970 | configFiles[i].file = NULL((void*)0); | |||
971 | free(configFiles[i].path); | |||
972 | configFiles[i].path = NULL((void*)0); | |||
973 | } | |||
974 | numFiles = 0; | |||
975 | } | |||
976 | ||||
977 | void | |||
978 | xf86setBuiltinConfig(const char *config[]) | |||
979 | { | |||
980 | builtinConfig = config; | |||
981 | } | |||
982 | ||||
983 | void | |||
984 | xf86parseError(const char *format, ...) | |||
985 | { | |||
986 | va_list ap; | |||
987 | const char *filename = numFiles ? configFiles[curFileIndex].path | |||
988 | : "<builtin configuration>"; | |||
989 | ||||
990 | ErrorF("Parse error on line %d of section %s in file %s\n\t", | |||
991 | configLineNo, configSection, filename); | |||
992 | va_start(ap, format)__builtin_va_start(ap, format); | |||
993 | VErrorF(format, ap); | |||
994 | va_end(ap)__builtin_va_end(ap); | |||
995 | ||||
996 | ErrorF("\n"); | |||
997 | } | |||
998 | ||||
999 | void | |||
1000 | xf86validationError(const char *format, ...) | |||
1001 | { | |||
1002 | va_list ap; | |||
1003 | const char *filename = numFiles ? configFiles[curFileIndex].path | |||
1004 | : "<builtin configuration>"; | |||
1005 | ||||
1006 | ErrorF("Data incomplete in file %s\n\t", filename); | |||
1007 | va_start(ap, format)__builtin_va_start(ap, format); | |||
1008 | VErrorF(format, ap); | |||
1009 | va_end(ap)__builtin_va_end(ap); | |||
1010 | ||||
1011 | ErrorF("\n"); | |||
1012 | } | |||
1013 | ||||
1014 | void | |||
1015 | xf86setSection(const char *section) | |||
1016 | { | |||
1017 | free(configSection); | |||
1018 | configSection = strdup(section); | |||
1019 | } | |||
1020 | ||||
1021 | /* | |||
1022 | * xf86getToken -- | |||
1023 | * Lookup a string if it is actually a token in disguise. | |||
1024 | */ | |||
1025 | int | |||
1026 | xf86getStringToken(xf86ConfigSymTabRec * tab) | |||
1027 | { | |||
1028 | return StringToToken(xf86_lex_val.str, tab); | |||
1029 | } | |||
1030 | ||||
1031 | static int | |||
1032 | StringToToken(const char *str, xf86ConfigSymTabRec * tab) | |||
1033 | { | |||
1034 | int i; | |||
1035 | ||||
1036 | for (i = 0; tab[i].token != -1; i++) { | |||
1037 | if (!xf86nameCompare(tab[i].name, str)) | |||
1038 | return tab[i].token; | |||
1039 | } | |||
1040 | return ERROR_TOKEN; | |||
1041 | } | |||
1042 | ||||
1043 | /* | |||
1044 | * Compare two names. The characters '_', ' ', and '\t' are ignored | |||
1045 | * in the comparison. | |||
1046 | */ | |||
1047 | int | |||
1048 | xf86nameCompare(const char *s1, const char *s2) | |||
1049 | { | |||
1050 | char c1, c2; | |||
1051 | ||||
1052 | if (!s1 || *s1 == 0) { | |||
1053 | if (!s2 || *s2 == 0) | |||
1054 | return 0; | |||
1055 | else | |||
1056 | return 1; | |||
1057 | } | |||
1058 | ||||
1059 | while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') | |||
1060 | s1++; | |||
1061 | while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') | |||
1062 | s2++; | |||
1063 | c1 = (isupper(*s1) ? tolower(*s1) : *s1); | |||
1064 | c2 = (isupper(*s2) ? tolower(*s2) : *s2); | |||
1065 | while (c1 == c2) { | |||
1066 | if (c1 == '\0') | |||
1067 | return 0; | |||
1068 | s1++; | |||
1069 | s2++; | |||
1070 | while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') | |||
1071 | s1++; | |||
1072 | while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') | |||
1073 | s2++; | |||
1074 | c1 = (isupper(*s1) ? tolower(*s1) : *s1); | |||
1075 | c2 = (isupper(*s2) ? tolower(*s2) : *s2); | |||
1076 | } | |||
1077 | return c1 - c2; | |||
1078 | } | |||
1079 | ||||
1080 | char * | |||
1081 | xf86addComment(char *cur, const char *add) | |||
1082 | { | |||
1083 | char *str; | |||
1084 | const char *cstr; | |||
1085 | int len, curlen, iscomment, hasnewline = 0, insnewline, endnewline; | |||
1086 | ||||
1087 | if (add == NULL((void*)0) || add[0] == '\0') | |||
1088 | return cur; | |||
1089 | ||||
1090 | if (cur) { | |||
1091 | curlen = strlen(cur); | |||
1092 | if (curlen) | |||
1093 | hasnewline = cur[curlen - 1] == '\n'; | |||
1094 | eol_seen = 0; | |||
1095 | } | |||
1096 | else | |||
1097 | curlen = 0; | |||
1098 | ||||
1099 | cstr = add; | |||
1100 | iscomment = 0; | |||
1101 | while (*cstr) { | |||
1102 | if (*cstr != ' ' && *cstr != '\t') | |||
1103 | break; | |||
1104 | ++cstr; | |||
1105 | } | |||
1106 | iscomment = (*cstr == '#'); | |||
1107 | ||||
1108 | len = strlen(add); | |||
1109 | endnewline = add[len - 1] == '\n'; | |||
1110 | ||||
1111 | insnewline = eol_seen || (curlen && !hasnewline); | |||
1112 | if (insnewline) | |||
1113 | len++; | |||
1114 | if (!iscomment) | |||
1115 | len++; | |||
1116 | if (!endnewline) | |||
1117 | len++; | |||
1118 | ||||
1119 | /* Allocate + 1 char for '\0' terminator. */ | |||
1120 | str = realloc(cur, curlen + len + 1); | |||
1121 | if (!str) | |||
1122 | return cur; | |||
1123 | ||||
1124 | cur = str; | |||
1125 | ||||
1126 | if (insnewline) | |||
1127 | cur[curlen++] = '\n'; | |||
1128 | if (!iscomment) | |||
1129 | cur[curlen++] = '#'; | |||
1130 | strcpy(cur + curlen, add)__builtin___strcpy_chk (cur + curlen, add, __builtin_object_size (cur + curlen, 2 > 1 ? 1 : 0)); | |||
1131 | if (!endnewline) | |||
1132 | strcat(cur, "\n")__builtin___strcat_chk (cur, "\n", __builtin_object_size (cur , 2 > 1 ? 1 : 0)); | |||
1133 | ||||
1134 | return cur; | |||
1135 | } | |||
1136 | ||||
1137 | Bool | |||
1138 | xf86getBoolValue(Bool *val, const char *str) | |||
1139 | { | |||
1140 | if (!val || !str) | |||
1141 | return FALSE0; | |||
1142 | if (*str == '\0') { | |||
1143 | *val = TRUE1; | |||
1144 | } | |||
1145 | else { | |||
1146 | if (xf86nameCompare(str, "1") == 0) | |||
1147 | *val = TRUE1; | |||
1148 | else if (xf86nameCompare(str, "on") == 0) | |||
1149 | *val = TRUE1; | |||
1150 | else if (xf86nameCompare(str, "true") == 0) | |||
1151 | *val = TRUE1; | |||
1152 | else if (xf86nameCompare(str, "yes") == 0) | |||
1153 | *val = TRUE1; | |||
1154 | else if (xf86nameCompare(str, "0") == 0) | |||
1155 | *val = FALSE0; | |||
1156 | else if (xf86nameCompare(str, "off") == 0) | |||
1157 | *val = FALSE0; | |||
1158 | else if (xf86nameCompare(str, "false") == 0) | |||
1159 | *val = FALSE0; | |||
1160 | else if (xf86nameCompare(str, "no") == 0) | |||
1161 | *val = FALSE0; | |||
1162 | else | |||
1163 | return FALSE0; | |||
1164 | } | |||
1165 | return TRUE1; | |||
1166 | } |