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