1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 1997 Metro Link Incorporated 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19706f2543Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20706f2543Smrg * SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Except as contained in this notice, the name of the Metro Link shall not be 23706f2543Smrg * used in advertising or otherwise to promote the sale, use or other dealings 24706f2543Smrg * in this Software without prior written authorization from Metro Link. 25706f2543Smrg * 26706f2543Smrg */ 27706f2543Smrg/* 28706f2543Smrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 29706f2543Smrg * 30706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 31706f2543Smrg * copy of this software and associated documentation files (the "Software"), 32706f2543Smrg * to deal in the Software without restriction, including without limitation 33706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 34706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 35706f2543Smrg * Software is furnished to do so, subject to the following conditions: 36706f2543Smrg * 37706f2543Smrg * The above copyright notice and this permission notice shall be included in 38706f2543Smrg * all copies or substantial portions of the Software. 39706f2543Smrg * 40706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 43706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 44706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 45706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 46706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 47706f2543Smrg * 48706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 49706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 50706f2543Smrg * the sale, use or other dealings in this Software without prior written 51706f2543Smrg * authorization from the copyright holder(s) and author(s). 52706f2543Smrg */ 53706f2543Smrg 54706f2543Smrg 55706f2543Smrg/* View/edit this file with tab stops set to 4 */ 56706f2543Smrg 57706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 58706f2543Smrg#include <xorg-config.h> 59706f2543Smrg#endif 60706f2543Smrg 61706f2543Smrg#include <ctype.h> 62706f2543Smrg#include <stdio.h> 63706f2543Smrg#include <stdlib.h> 64706f2543Smrg#include <string.h> 65706f2543Smrg#include <sys/types.h> 66706f2543Smrg#include <dirent.h> 67706f2543Smrg#include <unistd.h> 68706f2543Smrg#include <stdarg.h> 69706f2543Smrg#include <X11/Xdefs.h> 70706f2543Smrg#include <X11/Xfuncproto.h> 71706f2543Smrg 72706f2543Smrg#if defined(_POSIX_SOURCE) 73706f2543Smrg#include <limits.h> 74706f2543Smrg#else 75706f2543Smrg#define _POSIX_SOURCE 76706f2543Smrg#include <limits.h> 77706f2543Smrg#undef _POSIX_SOURCE 78706f2543Smrg#endif /* _POSIX_SOURCE */ 79706f2543Smrg 80706f2543Smrg#if !defined(PATH_MAX) 81706f2543Smrg#if defined(MAXPATHLEN) 82706f2543Smrg#define PATH_MAX MAXPATHLEN 83706f2543Smrg#else 84706f2543Smrg#define PATH_MAX 1024 85706f2543Smrg#endif /* MAXPATHLEN */ 86706f2543Smrg#endif /* !PATH_MAX */ 87706f2543Smrg 88706f2543Smrg#if !defined(MAXHOSTNAMELEN) 89706f2543Smrg#define MAXHOSTNAMELEN 32 90706f2543Smrg#endif /* !MAXHOSTNAMELEN */ 91706f2543Smrg 92706f2543Smrg#include "Configint.h" 93706f2543Smrg#include "xf86tokens.h" 94706f2543Smrg 95706f2543Smrg#define CONFIG_BUF_LEN 1024 96706f2543Smrg#define CONFIG_MAX_FILES 64 97706f2543Smrg 98706f2543Smrgstatic int StringToToken (char *, xf86ConfigSymTabRec *); 99706f2543Smrg 100706f2543Smrgstatic struct { 101706f2543Smrg FILE *file; 102706f2543Smrg char *path; 103706f2543Smrg} configFiles[CONFIG_MAX_FILES]; 104706f2543Smrgstatic const char **builtinConfig = NULL; 105706f2543Smrgstatic int builtinIndex = 0; 106706f2543Smrgstatic int configPos = 0; /* current readers position */ 107706f2543Smrgstatic int configLineNo = 0; /* linenumber */ 108706f2543Smrgstatic char *configBuf, *configRBuf; /* buffer for lines */ 109706f2543Smrgstatic char *configPath; /* path to config file */ 110706f2543Smrgstatic char *configDirPath; /* path to config dir */ 111706f2543Smrgstatic char *configSection = NULL; /* name of current section being parsed */ 112706f2543Smrgstatic int numFiles = 0; /* number of config files */ 113706f2543Smrgstatic int curFileIndex = 0; /* index of current config file */ 114706f2543Smrgstatic int pushToken = LOCK_TOKEN; 115706f2543Smrgstatic int eol_seen = 0; /* private state to handle comments */ 116706f2543SmrgLexRec val; 117706f2543Smrg 118706f2543Smrg/* 119706f2543Smrg * xf86getNextLine -- 120706f2543Smrg * 121706f2543Smrg * read from the configFiles FILE stream until we encounter a new 122706f2543Smrg * line; this is effectively just a big wrapper for fgets(3). 123706f2543Smrg * 124706f2543Smrg * xf86getToken() assumes that we will read up to the next 125706f2543Smrg * newline; we need to grow configBuf and configRBuf as needed to 126706f2543Smrg * support that. 127706f2543Smrg */ 128706f2543Smrg 129706f2543Smrgstatic char* 130706f2543Smrgxf86getNextLine(void) 131706f2543Smrg{ 132706f2543Smrg static int configBufLen = CONFIG_BUF_LEN; 133706f2543Smrg char *tmpConfigBuf, *tmpConfigRBuf; 134706f2543Smrg int c, i, pos = 0, eolFound = 0; 135706f2543Smrg char *ret = NULL; 136706f2543Smrg 137706f2543Smrg /* 138706f2543Smrg * reallocate the string if it was grown last time (i.e., is no 139706f2543Smrg * longer CONFIG_BUF_LEN); we malloc the new strings first, so 140706f2543Smrg * that if either of the mallocs fail, we can fall back on the 141706f2543Smrg * existing buffer allocations 142706f2543Smrg */ 143706f2543Smrg 144706f2543Smrg if (configBufLen != CONFIG_BUF_LEN) { 145706f2543Smrg 146706f2543Smrg tmpConfigBuf = malloc(CONFIG_BUF_LEN); 147706f2543Smrg tmpConfigRBuf = malloc(CONFIG_BUF_LEN); 148706f2543Smrg 149706f2543Smrg if (!tmpConfigBuf || !tmpConfigRBuf) { 150706f2543Smrg 151706f2543Smrg /* 152706f2543Smrg * at least one of the mallocs failed; keep the old buffers 153706f2543Smrg * and free any partial allocations 154706f2543Smrg */ 155706f2543Smrg 156706f2543Smrg free(tmpConfigBuf); 157706f2543Smrg free(tmpConfigRBuf); 158706f2543Smrg 159706f2543Smrg } else { 160706f2543Smrg 161706f2543Smrg /* 162706f2543Smrg * malloc succeeded; free the old buffers and use the new 163706f2543Smrg * buffers 164706f2543Smrg */ 165706f2543Smrg 166706f2543Smrg configBufLen = CONFIG_BUF_LEN; 167706f2543Smrg 168706f2543Smrg free(configBuf); 169706f2543Smrg free(configRBuf); 170706f2543Smrg 171706f2543Smrg configBuf = tmpConfigBuf; 172706f2543Smrg configRBuf = tmpConfigRBuf; 173706f2543Smrg } 174706f2543Smrg } 175706f2543Smrg 176706f2543Smrg /* read in another block of chars */ 177706f2543Smrg 178706f2543Smrg do { 179706f2543Smrg ret = fgets(configBuf + pos, configBufLen - pos - 1, 180706f2543Smrg configFiles[curFileIndex].file); 181706f2543Smrg 182706f2543Smrg if (!ret) { 183706f2543Smrg /* 184706f2543Smrg * if the file doesn't end in a newline, add one 185706f2543Smrg * and trigger another read 186706f2543Smrg */ 187706f2543Smrg if (pos != 0) { 188706f2543Smrg strcpy(&configBuf[pos], "\n"); 189706f2543Smrg ret = configBuf; 190706f2543Smrg } else 191706f2543Smrg break; 192706f2543Smrg } 193706f2543Smrg 194706f2543Smrg /* search for EOL in the new block of chars */ 195706f2543Smrg 196706f2543Smrg for (i = pos; i < (configBufLen - 1); i++) { 197706f2543Smrg c = configBuf[i]; 198706f2543Smrg 199706f2543Smrg if (c == '\0') break; 200706f2543Smrg 201706f2543Smrg if ((c == '\n') || (c == '\r')) { 202706f2543Smrg eolFound = 1; 203706f2543Smrg break; 204706f2543Smrg } 205706f2543Smrg } 206706f2543Smrg 207706f2543Smrg /* 208706f2543Smrg * if we didn't find EOL, then grow the string and 209706f2543Smrg * read in more 210706f2543Smrg */ 211706f2543Smrg 212706f2543Smrg if (!eolFound) { 213706f2543Smrg 214706f2543Smrg tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN); 215706f2543Smrg tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN); 216706f2543Smrg 217706f2543Smrg if (!tmpConfigBuf || !tmpConfigRBuf) { 218706f2543Smrg 219706f2543Smrg /* 220706f2543Smrg * at least one of the reallocations failed; use the 221706f2543Smrg * new allocation that succeeded, but we have to 222706f2543Smrg * fallback to the previous configBufLen size and use 223706f2543Smrg * the string we have, even though we don't have an 224706f2543Smrg * EOL 225706f2543Smrg */ 226706f2543Smrg 227706f2543Smrg if (tmpConfigBuf) configBuf = tmpConfigBuf; 228706f2543Smrg if (tmpConfigRBuf) configRBuf = tmpConfigRBuf; 229706f2543Smrg 230706f2543Smrg break; 231706f2543Smrg 232706f2543Smrg } else { 233706f2543Smrg 234706f2543Smrg /* reallocation succeeded */ 235706f2543Smrg 236706f2543Smrg configBuf = tmpConfigBuf; 237706f2543Smrg configRBuf = tmpConfigRBuf; 238706f2543Smrg pos = i; 239706f2543Smrg configBufLen += CONFIG_BUF_LEN; 240706f2543Smrg } 241706f2543Smrg } 242706f2543Smrg 243706f2543Smrg } while (!eolFound); 244706f2543Smrg 245706f2543Smrg return ret; 246706f2543Smrg} 247706f2543Smrg 248706f2543Smrg/* 249706f2543Smrg * xf86getToken -- 250706f2543Smrg * Read next Token from the config file. Handle the global variable 251706f2543Smrg * pushToken. 252706f2543Smrg */ 253706f2543Smrgint 254706f2543Smrgxf86getToken (xf86ConfigSymTabRec * tab) 255706f2543Smrg{ 256706f2543Smrg int c, i; 257706f2543Smrg 258706f2543Smrg /* 259706f2543Smrg * First check whether pushToken has a different value than LOCK_TOKEN. 260706f2543Smrg * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the 261706f2543Smrg * oth * case the next token must be read from the input. 262706f2543Smrg */ 263706f2543Smrg if (pushToken == EOF_TOKEN) 264706f2543Smrg return EOF_TOKEN; 265706f2543Smrg else if (pushToken == LOCK_TOKEN) 266706f2543Smrg { 267706f2543Smrg /* 268706f2543Smrg * eol_seen is only set for the first token after a newline. 269706f2543Smrg */ 270706f2543Smrg eol_seen = 0; 271706f2543Smrg 272706f2543Smrg c = configBuf[configPos]; 273706f2543Smrg 274706f2543Smrg /* 275706f2543Smrg * Get start of next Token. EOF is handled, 276706f2543Smrg * whitespaces are skipped. 277706f2543Smrg */ 278706f2543Smrg 279706f2543Smrgagain: 280706f2543Smrg if (!c) 281706f2543Smrg { 282706f2543Smrg char *ret; 283706f2543Smrg if (numFiles > 0) 284706f2543Smrg ret = xf86getNextLine(); 285706f2543Smrg else { 286706f2543Smrg if (builtinConfig[builtinIndex] == NULL) 287706f2543Smrg ret = NULL; 288706f2543Smrg else { 289706f2543Smrg ret = strncpy(configBuf, builtinConfig[builtinIndex], 290706f2543Smrg CONFIG_BUF_LEN); 291706f2543Smrg builtinIndex++; 292706f2543Smrg } 293706f2543Smrg } 294706f2543Smrg if (ret == NULL) 295706f2543Smrg { 296706f2543Smrg /* 297706f2543Smrg * if necessary, move to the next file and 298706f2543Smrg * read the first line 299706f2543Smrg */ 300706f2543Smrg if (curFileIndex + 1 < numFiles) { 301706f2543Smrg curFileIndex++; 302706f2543Smrg configLineNo = 0; 303706f2543Smrg goto again; 304706f2543Smrg } 305706f2543Smrg else 306706f2543Smrg return pushToken = EOF_TOKEN; 307706f2543Smrg } 308706f2543Smrg configLineNo++; 309706f2543Smrg configPos = 0; 310706f2543Smrg eol_seen = 1; 311706f2543Smrg } 312706f2543Smrg 313706f2543Smrg i = 0; 314706f2543Smrg for (;;) { 315706f2543Smrg c = configBuf[configPos++]; 316706f2543Smrg configRBuf[i++] = c; 317706f2543Smrg switch (c) { 318706f2543Smrg case ' ': 319706f2543Smrg case '\t': 320706f2543Smrg case '\r': 321706f2543Smrg continue; 322706f2543Smrg case '\n': 323706f2543Smrg i = 0; 324706f2543Smrg continue; 325706f2543Smrg } 326706f2543Smrg break; 327706f2543Smrg } 328706f2543Smrg if (c == '\0') 329706f2543Smrg goto again; 330706f2543Smrg 331706f2543Smrg if (c == '#') 332706f2543Smrg { 333706f2543Smrg do 334706f2543Smrg { 335706f2543Smrg configRBuf[i++] = (c = configBuf[configPos++]); 336706f2543Smrg } 337706f2543Smrg while ((c != '\n') && (c != '\r') && (c != '\0')); 338706f2543Smrg configRBuf[i] = '\0'; 339706f2543Smrg /* XXX no private copy. 340706f2543Smrg * Use xf86addComment when setting a comment. 341706f2543Smrg */ 342706f2543Smrg val.str = configRBuf; 343706f2543Smrg return COMMENT; 344706f2543Smrg } 345706f2543Smrg 346706f2543Smrg /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */ 347706f2543Smrg else if ((c == ',') && !isalpha (configBuf[configPos])) 348706f2543Smrg { 349706f2543Smrg return COMMA; 350706f2543Smrg } 351706f2543Smrg else if ((c == '-') && !isalpha (configBuf[configPos])) 352706f2543Smrg { 353706f2543Smrg return DASH; 354706f2543Smrg } 355706f2543Smrg 356706f2543Smrg /* 357706f2543Smrg * Numbers are returned immediately ... 358706f2543Smrg */ 359706f2543Smrg if (isdigit (c)) 360706f2543Smrg { 361706f2543Smrg int base; 362706f2543Smrg 363706f2543Smrg if (c == '0') 364706f2543Smrg if ((configBuf[configPos] == 'x') || 365706f2543Smrg (configBuf[configPos] == 'X')) 366706f2543Smrg { 367706f2543Smrg base = 16; 368706f2543Smrg val.numType = PARSE_HEX; 369706f2543Smrg } 370706f2543Smrg else 371706f2543Smrg { 372706f2543Smrg base = 8; 373706f2543Smrg val.numType = PARSE_OCTAL; 374706f2543Smrg } 375706f2543Smrg else 376706f2543Smrg { 377706f2543Smrg base = 10; 378706f2543Smrg val.numType = PARSE_DECIMAL; 379706f2543Smrg } 380706f2543Smrg 381706f2543Smrg configRBuf[0] = c; 382706f2543Smrg i = 1; 383706f2543Smrg while (isdigit (c = configBuf[configPos++]) || 384706f2543Smrg (c == '.') || (c == 'x') || (c == 'X') || 385706f2543Smrg ((base == 16) && (((c >= 'a') && (c <= 'f')) || 386706f2543Smrg ((c >= 'A') && (c <= 'F'))))) 387706f2543Smrg configRBuf[i++] = c; 388706f2543Smrg configPos--; /* GJA -- one too far */ 389706f2543Smrg configRBuf[i] = '\0'; 390706f2543Smrg val.num = strtoul (configRBuf, NULL, 0); 391706f2543Smrg val.realnum = atof (configRBuf); 392706f2543Smrg return NUMBER; 393706f2543Smrg } 394706f2543Smrg 395706f2543Smrg /* 396706f2543Smrg * All Strings START with a \" ... 397706f2543Smrg */ 398706f2543Smrg else if (c == '\"') 399706f2543Smrg { 400706f2543Smrg i = -1; 401706f2543Smrg do 402706f2543Smrg { 403706f2543Smrg configRBuf[++i] = (c = configBuf[configPos++]); 404706f2543Smrg } 405706f2543Smrg while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); 406706f2543Smrg configRBuf[i] = '\0'; 407706f2543Smrg val.str = malloc (strlen (configRBuf) + 1); 408706f2543Smrg strcpy (val.str, configRBuf); /* private copy ! */ 409706f2543Smrg return STRING; 410706f2543Smrg } 411706f2543Smrg 412706f2543Smrg /* 413706f2543Smrg * ... and now we MUST have a valid token. The search is 414706f2543Smrg * handled later along with the pushed tokens. 415706f2543Smrg */ 416706f2543Smrg else 417706f2543Smrg { 418706f2543Smrg configRBuf[0] = c; 419706f2543Smrg i = 0; 420706f2543Smrg do 421706f2543Smrg { 422706f2543Smrg configRBuf[++i] = (c = configBuf[configPos++]); 423706f2543Smrg } 424706f2543Smrg while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#')); 425706f2543Smrg --configPos; 426706f2543Smrg configRBuf[i] = '\0'; 427706f2543Smrg i = 0; 428706f2543Smrg } 429706f2543Smrg 430706f2543Smrg } 431706f2543Smrg else 432706f2543Smrg { 433706f2543Smrg 434706f2543Smrg /* 435706f2543Smrg * Here we deal with pushed tokens. Reinitialize pushToken again. If 436706f2543Smrg * the pushed token was NUMBER || STRING return them again ... 437706f2543Smrg */ 438706f2543Smrg int temp = pushToken; 439706f2543Smrg pushToken = LOCK_TOKEN; 440706f2543Smrg 441706f2543Smrg if (temp == COMMA || temp == DASH) 442706f2543Smrg return temp; 443706f2543Smrg if (temp == NUMBER || temp == STRING) 444706f2543Smrg return temp; 445706f2543Smrg } 446706f2543Smrg 447706f2543Smrg /* 448706f2543Smrg * Joop, at last we have to lookup the token ... 449706f2543Smrg */ 450706f2543Smrg if (tab) 451706f2543Smrg { 452706f2543Smrg i = 0; 453706f2543Smrg while (tab[i].token != -1) 454706f2543Smrg if (xf86nameCompare (configRBuf, tab[i].name) == 0) 455706f2543Smrg return tab[i].token; 456706f2543Smrg else 457706f2543Smrg i++; 458706f2543Smrg } 459706f2543Smrg 460706f2543Smrg return ERROR_TOKEN; /* Error catcher */ 461706f2543Smrg} 462706f2543Smrg 463706f2543Smrgint 464706f2543Smrgxf86getSubToken (char **comment) 465706f2543Smrg{ 466706f2543Smrg int token; 467706f2543Smrg 468706f2543Smrg for (;;) { 469706f2543Smrg token = xf86getToken(NULL); 470706f2543Smrg if (token == COMMENT) { 471706f2543Smrg if (comment) 472706f2543Smrg *comment = xf86addComment(*comment, val.str); 473706f2543Smrg } 474706f2543Smrg else 475706f2543Smrg return token; 476706f2543Smrg } 477706f2543Smrg /*NOTREACHED*/ 478706f2543Smrg} 479706f2543Smrg 480706f2543Smrgint 481706f2543Smrgxf86getSubTokenWithTab (char **comment, xf86ConfigSymTabRec *tab) 482706f2543Smrg{ 483706f2543Smrg int token; 484706f2543Smrg 485706f2543Smrg for (;;) { 486706f2543Smrg token = xf86getToken(tab); 487706f2543Smrg if (token == COMMENT) { 488706f2543Smrg if (comment) 489706f2543Smrg *comment = xf86addComment(*comment, val.str); 490706f2543Smrg } 491706f2543Smrg else 492706f2543Smrg return token; 493706f2543Smrg } 494706f2543Smrg /*NOTREACHED*/ 495706f2543Smrg} 496706f2543Smrg 497706f2543Smrgvoid 498706f2543Smrgxf86unGetToken (int token) 499706f2543Smrg{ 500706f2543Smrg pushToken = token; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrgchar * 504706f2543Smrgxf86tokenString (void) 505706f2543Smrg{ 506706f2543Smrg return configRBuf; 507706f2543Smrg} 508706f2543Smrg 509706f2543Smrgint 510706f2543Smrgxf86pathIsAbsolute(const char *path) 511706f2543Smrg{ 512706f2543Smrg if (path && path[0] == '/') 513706f2543Smrg return 1; 514706f2543Smrg return 0; 515706f2543Smrg} 516706f2543Smrg 517706f2543Smrg/* A path is "safe" if it is relative and if it contains no ".." elements. */ 518706f2543Smrgint 519706f2543Smrgxf86pathIsSafe(const char *path) 520706f2543Smrg{ 521706f2543Smrg if (xf86pathIsAbsolute(path)) 522706f2543Smrg return 0; 523706f2543Smrg 524706f2543Smrg /* Compare with ".." */ 525706f2543Smrg if (!strcmp(path, "..")) 526706f2543Smrg return 0; 527706f2543Smrg 528706f2543Smrg /* Look for leading "../" */ 529706f2543Smrg if (!strncmp(path, "../", 3)) 530706f2543Smrg return 0; 531706f2543Smrg 532706f2543Smrg /* Look for trailing "/.." */ 533706f2543Smrg if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/..")) 534706f2543Smrg return 0; 535706f2543Smrg 536706f2543Smrg /* Look for "/../" */ 537706f2543Smrg if (strstr(path, "/../")) 538706f2543Smrg return 0; 539706f2543Smrg 540706f2543Smrg return 1; 541706f2543Smrg} 542706f2543Smrg 543706f2543Smrg/* 544706f2543Smrg * This function substitutes the following escape sequences: 545706f2543Smrg * 546706f2543Smrg * %A cmdline argument as an absolute path (must be absolute to match) 547706f2543Smrg * %R cmdline argument as a relative path 548706f2543Smrg * %S cmdline argument as a "safe" path (relative, and no ".." elements) 549706f2543Smrg * %X default config file name ("xorg.conf") 550706f2543Smrg * %H hostname 551706f2543Smrg * %E config file environment ($XORGCONFIG) as an absolute path 552706f2543Smrg * %F config file environment ($XORGCONFIG) as a relative path 553706f2543Smrg * %G config file environment ($XORGCONFIG) as a safe path 554706f2543Smrg * %P projroot 555706f2543Smrg * %C sysconfdir 556706f2543Smrg * %D datadir 557706f2543Smrg * %% % 558706f2543Smrg */ 559706f2543Smrg 560706f2543Smrg#ifndef XCONFIGFILE 561706f2543Smrg#define XCONFIGFILE "xorg.conf" 562706f2543Smrg#endif 563706f2543Smrg#ifndef XCONFIGDIR 564706f2543Smrg#define XCONFIGDIR "xorg.conf.d" 565706f2543Smrg#endif 566706f2543Smrg#ifndef XCONFIGSUFFIX 567706f2543Smrg#define XCONFIGSUFFIX ".conf" 568706f2543Smrg#endif 569706f2543Smrg#ifndef PROJECTROOT 570706f2543Smrg#define PROJECTROOT "/usr/X11R6" 571706f2543Smrg#endif 572706f2543Smrg#ifndef SYSCONFDIR 573706f2543Smrg#define SYSCONFDIR PROJECTROOT "/etc" 574706f2543Smrg#endif 575706f2543Smrg#ifndef DATADIR 576706f2543Smrg#define DATADIR PROJECTROOT "/share" 577706f2543Smrg#endif 578706f2543Smrg#ifndef XCONFENV 579706f2543Smrg#define XCONFENV "XORGCONFIG" 580706f2543Smrg#endif 581706f2543Smrg 582706f2543Smrg#define BAIL_OUT do { \ 583706f2543Smrg free(result); \ 584706f2543Smrg return NULL; \ 585706f2543Smrg } while (0) 586706f2543Smrg 587706f2543Smrg#define CHECK_LENGTH do { \ 588706f2543Smrg if (l > PATH_MAX) { \ 589706f2543Smrg BAIL_OUT; \ 590706f2543Smrg } \ 591706f2543Smrg } while (0) 592706f2543Smrg 593706f2543Smrg#define APPEND_STR(s) do { \ 594706f2543Smrg if (strlen(s) + l > PATH_MAX) { \ 595706f2543Smrg BAIL_OUT; \ 596706f2543Smrg } else { \ 597706f2543Smrg strcpy(result + l, s); \ 598706f2543Smrg l += strlen(s); \ 599706f2543Smrg } \ 600706f2543Smrg } while (0) 601706f2543Smrg 602706f2543Smrgstatic char * 603706f2543SmrgDoSubstitution(const char *template, const char *cmdline, const char *projroot, 604706f2543Smrg int *cmdlineUsed, int *envUsed, 605706f2543Smrg const char *XConfigFile) 606706f2543Smrg{ 607706f2543Smrg char *result; 608706f2543Smrg int i, l; 609706f2543Smrg static const char *env = NULL; 610706f2543Smrg static char *hostname = NULL; 611706f2543Smrg 612706f2543Smrg if (!template) 613706f2543Smrg return NULL; 614706f2543Smrg 615706f2543Smrg if (cmdlineUsed) 616706f2543Smrg *cmdlineUsed = 0; 617706f2543Smrg if (envUsed) 618706f2543Smrg *envUsed = 0; 619706f2543Smrg 620706f2543Smrg result = malloc(PATH_MAX + 1); 621706f2543Smrg l = 0; 622706f2543Smrg for (i = 0; template[i]; i++) { 623706f2543Smrg if (template[i] != '%') { 624706f2543Smrg result[l++] = template[i]; 625706f2543Smrg CHECK_LENGTH; 626706f2543Smrg } else { 627706f2543Smrg switch (template[++i]) { 628706f2543Smrg case 'A': 629706f2543Smrg if (cmdline && xf86pathIsAbsolute(cmdline)) { 630706f2543Smrg APPEND_STR(cmdline); 631706f2543Smrg if (cmdlineUsed) 632706f2543Smrg *cmdlineUsed = 1; 633706f2543Smrg } else 634706f2543Smrg BAIL_OUT; 635706f2543Smrg break; 636706f2543Smrg case 'R': 637706f2543Smrg if (cmdline && !xf86pathIsAbsolute(cmdline)) { 638706f2543Smrg APPEND_STR(cmdline); 639706f2543Smrg if (cmdlineUsed) 640706f2543Smrg *cmdlineUsed = 1; 641706f2543Smrg } else 642706f2543Smrg BAIL_OUT; 643706f2543Smrg break; 644706f2543Smrg case 'S': 645706f2543Smrg if (cmdline && xf86pathIsSafe(cmdline)) { 646706f2543Smrg APPEND_STR(cmdline); 647706f2543Smrg if (cmdlineUsed) 648706f2543Smrg *cmdlineUsed = 1; 649706f2543Smrg } else 650706f2543Smrg BAIL_OUT; 651706f2543Smrg break; 652706f2543Smrg case 'X': 653706f2543Smrg APPEND_STR(XConfigFile); 654706f2543Smrg break; 655706f2543Smrg case 'H': 656706f2543Smrg if (!hostname) { 657706f2543Smrg if ((hostname = malloc(MAXHOSTNAMELEN + 1))) { 658706f2543Smrg if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { 659706f2543Smrg hostname[MAXHOSTNAMELEN] = '\0'; 660706f2543Smrg } else { 661706f2543Smrg free(hostname); 662706f2543Smrg hostname = NULL; 663706f2543Smrg } 664706f2543Smrg } 665706f2543Smrg } 666706f2543Smrg if (hostname) 667706f2543Smrg APPEND_STR(hostname); 668706f2543Smrg break; 669706f2543Smrg case 'E': 670706f2543Smrg if (!env) 671706f2543Smrg env = getenv(XCONFENV); 672706f2543Smrg if (env && xf86pathIsAbsolute(env)) { 673706f2543Smrg APPEND_STR(env); 674706f2543Smrg if (envUsed) 675706f2543Smrg *envUsed = 1; 676706f2543Smrg } else 677706f2543Smrg BAIL_OUT; 678706f2543Smrg break; 679706f2543Smrg case 'F': 680706f2543Smrg if (!env) 681706f2543Smrg env = getenv(XCONFENV); 682706f2543Smrg if (env && !xf86pathIsAbsolute(env)) { 683706f2543Smrg APPEND_STR(env); 684706f2543Smrg if (envUsed) 685706f2543Smrg *envUsed = 1; 686706f2543Smrg } else 687706f2543Smrg BAIL_OUT; 688706f2543Smrg break; 689706f2543Smrg case 'G': 690706f2543Smrg if (!env) 691706f2543Smrg env = getenv(XCONFENV); 692706f2543Smrg if (env && xf86pathIsSafe(env)) { 693706f2543Smrg APPEND_STR(env); 694706f2543Smrg if (envUsed) 695706f2543Smrg *envUsed = 1; 696706f2543Smrg } else 697706f2543Smrg BAIL_OUT; 698706f2543Smrg break; 699706f2543Smrg case 'P': 700706f2543Smrg if (projroot && xf86pathIsAbsolute(projroot)) 701706f2543Smrg APPEND_STR(projroot); 702706f2543Smrg else 703706f2543Smrg BAIL_OUT; 704706f2543Smrg break; 705706f2543Smrg case 'C': 706706f2543Smrg APPEND_STR(SYSCONFDIR); 707706f2543Smrg break; 708706f2543Smrg case 'D': 709706f2543Smrg APPEND_STR(DATADIR); 710706f2543Smrg break; 711706f2543Smrg case '%': 712706f2543Smrg result[l++] = '%'; 713706f2543Smrg CHECK_LENGTH; 714706f2543Smrg break; 715706f2543Smrg default: 716706f2543Smrg fprintf(stderr, "invalid escape %%%c found in path template\n", 717706f2543Smrg template[i]); 718706f2543Smrg BAIL_OUT; 719706f2543Smrg break; 720706f2543Smrg } 721706f2543Smrg } 722706f2543Smrg } 723706f2543Smrg#ifdef DEBUG 724706f2543Smrg fprintf(stderr, "Converted `%s' to `%s'\n", template, result); 725706f2543Smrg#endif 726706f2543Smrg return result; 727706f2543Smrg} 728706f2543Smrg 729706f2543Smrg/* 730706f2543Smrg * Given some searching parameters, locate and open the xorg config file. 731706f2543Smrg */ 732706f2543Smrgstatic char * 733706f2543SmrgOpenConfigFile(const char *path, const char *cmdline, const char *projroot, 734706f2543Smrg const char *confname) 735706f2543Smrg{ 736706f2543Smrg char *filepath = NULL; 737706f2543Smrg char *pathcopy; 738706f2543Smrg const char *template; 739706f2543Smrg int cmdlineUsed = 0; 740706f2543Smrg FILE *file = NULL; 741706f2543Smrg 742706f2543Smrg pathcopy = strdup(path); 743706f2543Smrg for (template = strtok(pathcopy, ","); template && !file; 744706f2543Smrg template = strtok(NULL, ",")) { 745706f2543Smrg filepath = DoSubstitution(template, cmdline, projroot, 746706f2543Smrg &cmdlineUsed, NULL, confname); 747706f2543Smrg if (!filepath) 748706f2543Smrg continue; 749706f2543Smrg if (cmdline && !cmdlineUsed) { 750706f2543Smrg free(filepath); 751706f2543Smrg filepath = NULL; 752706f2543Smrg continue; 753706f2543Smrg } 754706f2543Smrg file = fopen(filepath, "r"); 755706f2543Smrg if (!file) { 756706f2543Smrg free(filepath); 757706f2543Smrg filepath = NULL; 758706f2543Smrg } 759706f2543Smrg } 760706f2543Smrg 761706f2543Smrg free(pathcopy); 762706f2543Smrg if (file) { 763706f2543Smrg configFiles[numFiles].file = file; 764706f2543Smrg configFiles[numFiles].path = strdup(filepath); 765706f2543Smrg numFiles++; 766706f2543Smrg } 767706f2543Smrg return filepath; 768706f2543Smrg} 769706f2543Smrg 770706f2543Smrg/* 771706f2543Smrg * Match non-hidden files in the xorg config directory with a .conf 772706f2543Smrg * suffix. This filter is passed to scandir(3). 773706f2543Smrg */ 774706f2543Smrgstatic int 775706f2543SmrgConfigFilter(const struct dirent *de) 776706f2543Smrg{ 777706f2543Smrg const char *name = de->d_name; 778706f2543Smrg size_t len; 779706f2543Smrg size_t suflen = strlen(XCONFIGSUFFIX); 780706f2543Smrg 781706f2543Smrg if (!name || name[0] == '.') 782706f2543Smrg return 0; 783706f2543Smrg len = strlen(name); 784706f2543Smrg if(len <= suflen) 785706f2543Smrg return 0; 786706f2543Smrg if (strcmp(&name[len-suflen], XCONFIGSUFFIX) != 0) 787706f2543Smrg return 0; 788706f2543Smrg return 1; 789706f2543Smrg} 790706f2543Smrg 791706f2543Smrgstatic Bool 792706f2543SmrgAddConfigDirFiles(const char *dirpath, struct dirent **list, int num) 793706f2543Smrg{ 794706f2543Smrg int i; 795706f2543Smrg Bool openedFile = FALSE; 796706f2543Smrg Bool warnOnce = FALSE; 797706f2543Smrg 798706f2543Smrg for (i = 0; i < num; i++) { 799706f2543Smrg char *path; 800706f2543Smrg FILE *file; 801706f2543Smrg 802706f2543Smrg if (numFiles >= CONFIG_MAX_FILES) { 803706f2543Smrg if (!warnOnce) { 804706f2543Smrg ErrorF("Maximum number of configuration " 805706f2543Smrg "files opened\n"); 806706f2543Smrg warnOnce = TRUE; 807706f2543Smrg } 808706f2543Smrg free(list[i]); 809706f2543Smrg continue; 810706f2543Smrg } 811706f2543Smrg 812706f2543Smrg path = malloc(PATH_MAX + 1); 813706f2543Smrg snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, 814706f2543Smrg list[i]->d_name); 815706f2543Smrg free(list[i]); 816706f2543Smrg file = fopen(path, "r"); 817706f2543Smrg if (!file) { 818706f2543Smrg free(path); 819706f2543Smrg continue; 820706f2543Smrg } 821706f2543Smrg openedFile = TRUE; 822706f2543Smrg 823706f2543Smrg configFiles[numFiles].file = file; 824706f2543Smrg configFiles[numFiles].path = path; 825706f2543Smrg numFiles++; 826706f2543Smrg } 827706f2543Smrg 828706f2543Smrg return openedFile; 829706f2543Smrg} 830706f2543Smrg 831706f2543Smrg/* 832706f2543Smrg * Given some searching parameters, locate and open the xorg config 833706f2543Smrg * directory. The directory does not need to contain config files. 834706f2543Smrg */ 835706f2543Smrgstatic char * 836706f2543SmrgOpenConfigDir(const char *path, const char *cmdline, const char *projroot, 837706f2543Smrg const char *confname) 838706f2543Smrg{ 839706f2543Smrg char *dirpath, *pathcopy; 840706f2543Smrg const char *template; 841706f2543Smrg Bool found = FALSE; 842706f2543Smrg int cmdlineUsed = 0; 843706f2543Smrg 844706f2543Smrg pathcopy = strdup(path); 845706f2543Smrg for (template = strtok(pathcopy, ","); template && !found; 846706f2543Smrg template = strtok(NULL, ",")) { 847706f2543Smrg struct dirent **list = NULL; 848706f2543Smrg int num; 849706f2543Smrg 850706f2543Smrg dirpath = DoSubstitution(template, cmdline, projroot, 851706f2543Smrg &cmdlineUsed, NULL, confname); 852706f2543Smrg if (!dirpath) 853706f2543Smrg continue; 854706f2543Smrg if (cmdline && !cmdlineUsed) { 855706f2543Smrg free(dirpath); 856706f2543Smrg dirpath = NULL; 857706f2543Smrg continue; 858706f2543Smrg } 859706f2543Smrg 860706f2543Smrg /* match files named *.conf */ 861706f2543Smrg num = scandir(dirpath, &list, ConfigFilter, alphasort); 862706f2543Smrg found = AddConfigDirFiles(dirpath, list, num); 863706f2543Smrg if (!found) { 864706f2543Smrg free(dirpath); 865706f2543Smrg dirpath = NULL; 866706f2543Smrg free(list); 867706f2543Smrg } 868706f2543Smrg } 869706f2543Smrg 870706f2543Smrg free(pathcopy); 871706f2543Smrg return dirpath; 872706f2543Smrg} 873706f2543Smrg 874706f2543Smrg/* 875706f2543Smrg * xf86initConfigFiles -- Setup global variables and buffers. 876706f2543Smrg */ 877706f2543Smrgvoid 878706f2543Smrgxf86initConfigFiles(void) 879706f2543Smrg{ 880706f2543Smrg curFileIndex = 0; 881706f2543Smrg configPos = 0; 882706f2543Smrg configLineNo = 0; 883706f2543Smrg pushToken = LOCK_TOKEN; 884706f2543Smrg 885706f2543Smrg configBuf = malloc(CONFIG_BUF_LEN); 886706f2543Smrg configRBuf = malloc(CONFIG_BUF_LEN); 887706f2543Smrg configBuf[0] = '\0'; /* sanity ... */ 888706f2543Smrg} 889706f2543Smrg 890706f2543Smrg/* 891706f2543Smrg * xf86openConfigFile -- 892706f2543Smrg * 893706f2543Smrg * This function take a config file search path (optional), a command-line 894706f2543Smrg * specified file name (optional) and the ProjectRoot path (optional) and 895706f2543Smrg * locates and opens a config file based on that information. If a 896706f2543Smrg * command-line file name is specified, then this function fails if none 897706f2543Smrg * of the located files. 898706f2543Smrg * 899706f2543Smrg * The return value is a pointer to the actual name of the file that was 900706f2543Smrg * opened. When no file is found, the return value is NULL. 901706f2543Smrg * 902706f2543Smrg * The escape sequences allowed in the search path are defined above. 903706f2543Smrg * 904706f2543Smrg */ 905706f2543Smrg 906706f2543Smrg#ifndef DEFAULT_CONF_PATH 907706f2543Smrg#define DEFAULT_CONF_PATH "/etc/X11/%S," \ 908706f2543Smrg "%P/etc/X11/%S," \ 909706f2543Smrg "/etc/X11/%G," \ 910706f2543Smrg "%P/etc/X11/%G," \ 911706f2543Smrg "/etc/X11/%X-%M," \ 912706f2543Smrg "/etc/X11/%X," \ 913706f2543Smrg "/etc/%X," \ 914706f2543Smrg "%P/etc/X11/%X.%H," \ 915706f2543Smrg "%P/etc/X11/%X-%M," \ 916706f2543Smrg "%P/etc/X11/%X," \ 917706f2543Smrg "%P/lib/X11/%X.%H," \ 918706f2543Smrg "%P/lib/X11/%X-%M," \ 919706f2543Smrg "%P/lib/X11/%X" 920706f2543Smrg#endif 921706f2543Smrg 922706f2543Smrgconst char * 923706f2543Smrgxf86openConfigFile(const char *path, const char *cmdline, const char *projroot) 924706f2543Smrg{ 925706f2543Smrg if (!path || !path[0]) 926706f2543Smrg path = DEFAULT_CONF_PATH; 927706f2543Smrg if (!projroot || !projroot[0]) 928706f2543Smrg projroot = PROJECTROOT; 929706f2543Smrg 930706f2543Smrg /* Search for a config file */ 931706f2543Smrg configPath = OpenConfigFile(path, cmdline, projroot, XCONFIGFILE); 932706f2543Smrg return configPath; 933706f2543Smrg} 934706f2543Smrg 935706f2543Smrg/* 936706f2543Smrg * xf86openConfigDirFiles -- 937706f2543Smrg * 938706f2543Smrg * This function take a config directory search path (optional), a 939706f2543Smrg * command-line specified directory name (optional) and the ProjectRoot path 940706f2543Smrg * (optional) and locates and opens a config directory based on that 941706f2543Smrg * information. If a command-line name is specified, then this function 942706f2543Smrg * fails if it is not found. 943706f2543Smrg * 944706f2543Smrg * The return value is a pointer to the actual name of the direcoty that was 945706f2543Smrg * opened. When no directory is found, the return value is NULL. 946706f2543Smrg * 947706f2543Smrg * The escape sequences allowed in the search path are defined above. 948706f2543Smrg * 949706f2543Smrg */ 950706f2543Smrgconst char * 951706f2543Smrgxf86openConfigDirFiles(const char *path, const char *cmdline, 952706f2543Smrg const char *projroot) 953706f2543Smrg{ 954706f2543Smrg if (!path || !path[0]) 955706f2543Smrg path = DEFAULT_CONF_PATH; 956706f2543Smrg if (!projroot || !projroot[0]) 957706f2543Smrg projroot = PROJECTROOT; 958706f2543Smrg 959706f2543Smrg /* Search for the multiconf directory */ 960706f2543Smrg configDirPath = OpenConfigDir(path, cmdline, projroot, XCONFIGDIR); 961706f2543Smrg return configDirPath; 962706f2543Smrg} 963706f2543Smrg 964706f2543Smrgvoid 965706f2543Smrgxf86closeConfigFile (void) 966706f2543Smrg{ 967706f2543Smrg int i; 968706f2543Smrg 969706f2543Smrg free (configPath); 970706f2543Smrg configPath = NULL; 971706f2543Smrg free (configDirPath); 972706f2543Smrg configDirPath = NULL; 973706f2543Smrg free (configRBuf); 974706f2543Smrg configRBuf = NULL; 975706f2543Smrg free (configBuf); 976706f2543Smrg configBuf = NULL; 977706f2543Smrg 978706f2543Smrg if (numFiles == 0) { 979706f2543Smrg builtinConfig = NULL; 980706f2543Smrg builtinIndex = 0; 981706f2543Smrg } 982706f2543Smrg for (i = 0; i < numFiles; i++) { 983706f2543Smrg fclose(configFiles[i].file); 984706f2543Smrg configFiles[i].file = NULL; 985706f2543Smrg free(configFiles[i].path); 986706f2543Smrg configFiles[i].path = NULL; 987706f2543Smrg } 988706f2543Smrg numFiles = 0; 989706f2543Smrg} 990706f2543Smrg 991706f2543Smrgvoid 992706f2543Smrgxf86setBuiltinConfig(const char *config[]) 993706f2543Smrg{ 994706f2543Smrg builtinConfig = config; 995706f2543Smrg} 996706f2543Smrg 997706f2543Smrgvoid 998706f2543Smrgxf86parseError (char *format,...) 999706f2543Smrg{ 1000706f2543Smrg va_list ap; 1001706f2543Smrg char *filename = numFiles ? configFiles[curFileIndex].path : 1002706f2543Smrg "<builtin configuration>"; 1003706f2543Smrg 1004706f2543Smrg ErrorF ("Parse error on line %d of section %s in file %s\n\t", 1005706f2543Smrg configLineNo, configSection, filename); 1006706f2543Smrg va_start (ap, format); 1007706f2543Smrg VErrorF (format, ap); 1008706f2543Smrg va_end (ap); 1009706f2543Smrg 1010706f2543Smrg ErrorF ("\n"); 1011706f2543Smrg} 1012706f2543Smrg 1013706f2543Smrgvoid 1014706f2543Smrgxf86validationError (char *format,...) 1015706f2543Smrg{ 1016706f2543Smrg va_list ap; 1017706f2543Smrg char *filename = numFiles ? configFiles[curFileIndex].path : 1018706f2543Smrg "<builtin configuration>"; 1019706f2543Smrg 1020706f2543Smrg ErrorF ("Data incomplete in file %s\n\t", filename); 1021706f2543Smrg va_start (ap, format); 1022706f2543Smrg VErrorF (format, ap); 1023706f2543Smrg va_end (ap); 1024706f2543Smrg 1025706f2543Smrg ErrorF ("\n"); 1026706f2543Smrg} 1027706f2543Smrg 1028706f2543Smrgvoid 1029706f2543Smrgxf86setSection (char *section) 1030706f2543Smrg{ 1031706f2543Smrg free(configSection); 1032706f2543Smrg configSection = strdup(section); 1033706f2543Smrg} 1034706f2543Smrg 1035706f2543Smrg/* 1036706f2543Smrg * xf86getToken -- 1037706f2543Smrg * Lookup a string if it is actually a token in disguise. 1038706f2543Smrg */ 1039706f2543Smrgint 1040706f2543Smrgxf86getStringToken (xf86ConfigSymTabRec * tab) 1041706f2543Smrg{ 1042706f2543Smrg return StringToToken (val.str, tab); 1043706f2543Smrg} 1044706f2543Smrg 1045706f2543Smrgstatic int 1046706f2543SmrgStringToToken (char *str, xf86ConfigSymTabRec * tab) 1047706f2543Smrg{ 1048706f2543Smrg int i; 1049706f2543Smrg 1050706f2543Smrg for (i = 0; tab[i].token != -1; i++) 1051706f2543Smrg { 1052706f2543Smrg if (!xf86nameCompare (tab[i].name, str)) 1053706f2543Smrg return tab[i].token; 1054706f2543Smrg } 1055706f2543Smrg return ERROR_TOKEN; 1056706f2543Smrg} 1057706f2543Smrg 1058706f2543Smrg 1059706f2543Smrg/* 1060706f2543Smrg * Compare two names. The characters '_', ' ', and '\t' are ignored 1061706f2543Smrg * in the comparison. 1062706f2543Smrg */ 1063706f2543Smrgint 1064706f2543Smrgxf86nameCompare (const char *s1, const char *s2) 1065706f2543Smrg{ 1066706f2543Smrg char c1, c2; 1067706f2543Smrg 1068706f2543Smrg if (!s1 || *s1 == 0) { 1069706f2543Smrg if (!s2 || *s2 == 0) 1070706f2543Smrg return 0; 1071706f2543Smrg else 1072706f2543Smrg return 1; 1073706f2543Smrg } 1074706f2543Smrg 1075706f2543Smrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 1076706f2543Smrg s1++; 1077706f2543Smrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 1078706f2543Smrg s2++; 1079706f2543Smrg c1 = (isupper (*s1) ? tolower (*s1) : *s1); 1080706f2543Smrg c2 = (isupper (*s2) ? tolower (*s2) : *s2); 1081706f2543Smrg while (c1 == c2) 1082706f2543Smrg { 1083706f2543Smrg if (c1 == '\0') 1084706f2543Smrg return 0; 1085706f2543Smrg s1++; 1086706f2543Smrg s2++; 1087706f2543Smrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 1088706f2543Smrg s1++; 1089706f2543Smrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 1090706f2543Smrg s2++; 1091706f2543Smrg c1 = (isupper (*s1) ? tolower (*s1) : *s1); 1092706f2543Smrg c2 = (isupper (*s2) ? tolower (*s2) : *s2); 1093706f2543Smrg } 1094706f2543Smrg return c1 - c2; 1095706f2543Smrg} 1096706f2543Smrg 1097706f2543Smrgchar * 1098706f2543Smrgxf86addComment(char *cur, char *add) 1099706f2543Smrg{ 1100706f2543Smrg char *str; 1101706f2543Smrg int len, curlen, iscomment, hasnewline = 0, endnewline; 1102706f2543Smrg 1103706f2543Smrg if (add == NULL || add[0] == '\0') 1104706f2543Smrg return cur; 1105706f2543Smrg 1106706f2543Smrg if (cur) { 1107706f2543Smrg curlen = strlen(cur); 1108706f2543Smrg if (curlen) 1109706f2543Smrg hasnewline = cur[curlen - 1] == '\n'; 1110706f2543Smrg eol_seen = 0; 1111706f2543Smrg } 1112706f2543Smrg else 1113706f2543Smrg curlen = 0; 1114706f2543Smrg 1115706f2543Smrg str = add; 1116706f2543Smrg iscomment = 0; 1117706f2543Smrg while (*str) { 1118706f2543Smrg if (*str != ' ' && *str != '\t') 1119706f2543Smrg break; 1120706f2543Smrg ++str; 1121706f2543Smrg } 1122706f2543Smrg iscomment = (*str == '#'); 1123706f2543Smrg 1124706f2543Smrg len = strlen(add); 1125706f2543Smrg endnewline = add[len - 1] == '\n'; 1126706f2543Smrg len += 1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen; 1127706f2543Smrg 1128706f2543Smrg if ((str = realloc(cur, len + curlen)) == NULL) 1129706f2543Smrg return cur; 1130706f2543Smrg 1131706f2543Smrg cur = str; 1132706f2543Smrg 1133706f2543Smrg if (eol_seen || (curlen && !hasnewline)) 1134706f2543Smrg cur[curlen++] = '\n'; 1135706f2543Smrg if (!iscomment) 1136706f2543Smrg cur[curlen++] = '#'; 1137706f2543Smrg strcpy(cur + curlen, add); 1138706f2543Smrg if (!endnewline) 1139706f2543Smrg strcat(cur, "\n"); 1140706f2543Smrg 1141706f2543Smrg return cur; 1142706f2543Smrg} 1143706f2543Smrg 1144706f2543SmrgBool 1145706f2543Smrgxf86getBoolValue(Bool *val, const char *str) 1146706f2543Smrg{ 1147706f2543Smrg if (!val || !str) 1148706f2543Smrg return FALSE; 1149706f2543Smrg if (*str == '\0') { 1150706f2543Smrg *val = TRUE; 1151706f2543Smrg } else { 1152706f2543Smrg if (xf86nameCompare(str, "1") == 0) 1153706f2543Smrg *val = TRUE; 1154706f2543Smrg else if (xf86nameCompare(str, "on") == 0) 1155706f2543Smrg *val = TRUE; 1156706f2543Smrg else if (xf86nameCompare(str, "true") == 0) 1157706f2543Smrg *val = TRUE; 1158706f2543Smrg else if (xf86nameCompare(str, "yes") == 0) 1159706f2543Smrg *val = TRUE; 1160706f2543Smrg else if (xf86nameCompare(str, "0") == 0) 1161706f2543Smrg *val = FALSE; 1162706f2543Smrg else if (xf86nameCompare(str, "off") == 0) 1163706f2543Smrg *val = FALSE; 1164706f2543Smrg else if (xf86nameCompare(str, "false") == 0) 1165706f2543Smrg *val = FALSE; 1166706f2543Smrg else if (xf86nameCompare(str, "no") == 0) 1167706f2543Smrg *val = FALSE; 1168706f2543Smrg else 1169706f2543Smrg return FALSE; 1170706f2543Smrg } 1171706f2543Smrg return TRUE; 1172706f2543Smrg} 1173