135c4bbdfSmrg/* 205b261ecSmrg * Copyright (c) 1997 Metro Link Incorporated 335c4bbdfSmrg * 405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 535c4bbdfSmrg * copy of this software and associated documentation files (the "Software"), 605b261ecSmrg * to deal in the Software without restriction, including without limitation 705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 905b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1035c4bbdfSmrg * 1105b261ecSmrg * The above copyright notice and this permission notice shall be included in 1205b261ecSmrg * all copies or substantial portions of the Software. 1335c4bbdfSmrg * 1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1705b261ecSmrg * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 1805b261ecSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 1905b261ecSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2005b261ecSmrg * SOFTWARE. 2135c4bbdfSmrg * 2205b261ecSmrg * Except as contained in this notice, the name of the Metro Link shall not be 2305b261ecSmrg * used in advertising or otherwise to promote the sale, use or other dealings 2405b261ecSmrg * in this Software without prior written authorization from Metro Link. 2535c4bbdfSmrg * 2605b261ecSmrg */ 2705b261ecSmrg/* 2805b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc. 2905b261ecSmrg * 3005b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 3105b261ecSmrg * copy of this software and associated documentation files (the "Software"), 3205b261ecSmrg * to deal in the Software without restriction, including without limitation 3305b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 3405b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 3505b261ecSmrg * Software is furnished to do so, subject to the following conditions: 3605b261ecSmrg * 3705b261ecSmrg * The above copyright notice and this permission notice shall be included in 3805b261ecSmrg * all copies or substantial portions of the Software. 3905b261ecSmrg * 4005b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4105b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4205b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 4305b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 4405b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 4505b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 4605b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 4705b261ecSmrg * 4805b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 4905b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 5005b261ecSmrg * the sale, use or other dealings in this Software without prior written 5105b261ecSmrg * authorization from the copyright holder(s) and author(s). 5205b261ecSmrg */ 5305b261ecSmrg 5405b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 5505b261ecSmrg#include <xorg-config.h> 5605b261ecSmrg#endif 5705b261ecSmrg 5805b261ecSmrg#include <ctype.h> 5905b261ecSmrg#include <stdio.h> 6005b261ecSmrg#include <stdlib.h> 6105b261ecSmrg#include <string.h> 626747b715Smrg#include <sys/types.h> 636747b715Smrg#include <dirent.h> 6405b261ecSmrg#include <unistd.h> 6505b261ecSmrg#include <stdarg.h> 666747b715Smrg#include <X11/Xdefs.h> 674642e01fSmrg#include <X11/Xfuncproto.h> 6805b261ecSmrg#include <limits.h> 6905b261ecSmrg 7005b261ecSmrg#if !defined(MAXHOSTNAMELEN) 7105b261ecSmrg#define MAXHOSTNAMELEN 32 7235c4bbdfSmrg#endif /* !MAXHOSTNAMELEN */ 7335c4bbdfSmrg 7435c4bbdfSmrg/* For PATH_MAX */ 7535c4bbdfSmrg#include "misc.h" 7605b261ecSmrg 7705b261ecSmrg#include "Configint.h" 7805b261ecSmrg#include "xf86tokens.h" 7905b261ecSmrg 8005b261ecSmrg#define CONFIG_BUF_LEN 1024 816747b715Smrg#define CONFIG_MAX_FILES 64 8205b261ecSmrg 836747b715Smrgstatic struct { 8435c4bbdfSmrg FILE *file; 8535c4bbdfSmrg char *path; 866747b715Smrg} configFiles[CONFIG_MAX_FILES]; 8705b261ecSmrgstatic const char **builtinConfig = NULL; 8805b261ecSmrgstatic int builtinIndex = 0; 8935c4bbdfSmrgstatic int configPos = 0; /* current readers position */ 9035c4bbdfSmrgstatic int configLineNo = 0; /* linenumber */ 9135c4bbdfSmrgstatic char *configBuf, *configRBuf; /* buffer for lines */ 9235c4bbdfSmrgstatic char *configSection = NULL; /* name of current section being parsed */ 9335c4bbdfSmrgstatic int numFiles = 0; /* number of config files */ 9435c4bbdfSmrgstatic int curFileIndex = 0; /* index of current config file */ 9505b261ecSmrgstatic int pushToken = LOCK_TOKEN; 9635c4bbdfSmrgstatic int eol_seen = 0; /* private state to handle comments */ 9735c4bbdfSmrgLexRec xf86_lex_val; 9805b261ecSmrg 9905b261ecSmrg/* 10005b261ecSmrg * xf86getNextLine -- 10105b261ecSmrg * 1026747b715Smrg * read from the configFiles FILE stream until we encounter a new 10305b261ecSmrg * line; this is effectively just a big wrapper for fgets(3). 10405b261ecSmrg * 10505b261ecSmrg * xf86getToken() assumes that we will read up to the next 10605b261ecSmrg * newline; we need to grow configBuf and configRBuf as needed to 10705b261ecSmrg * support that. 10805b261ecSmrg */ 10905b261ecSmrg 11035c4bbdfSmrgstatic char * 11105b261ecSmrgxf86getNextLine(void) 11205b261ecSmrg{ 11335c4bbdfSmrg static int configBufLen = CONFIG_BUF_LEN; 11435c4bbdfSmrg char *tmpConfigBuf, *tmpConfigRBuf; 11535c4bbdfSmrg int c, i, pos = 0, eolFound = 0; 11635c4bbdfSmrg char *ret = NULL; 11705b261ecSmrg 11835c4bbdfSmrg /* 11935c4bbdfSmrg * reallocate the string if it was grown last time (i.e., is no 12035c4bbdfSmrg * longer CONFIG_BUF_LEN); we malloc the new strings first, so 12135c4bbdfSmrg * that if either of the mallocs fail, we can fall back on the 12235c4bbdfSmrg * existing buffer allocations 12335c4bbdfSmrg */ 12405b261ecSmrg 12535c4bbdfSmrg if (configBufLen != CONFIG_BUF_LEN) { 12605b261ecSmrg 12735c4bbdfSmrg tmpConfigBuf = malloc(CONFIG_BUF_LEN); 12835c4bbdfSmrg tmpConfigRBuf = malloc(CONFIG_BUF_LEN); 12905b261ecSmrg 13035c4bbdfSmrg if (!tmpConfigBuf || !tmpConfigRBuf) { 13105b261ecSmrg 13235c4bbdfSmrg /* 13335c4bbdfSmrg * at least one of the mallocs failed; keep the old buffers 13435c4bbdfSmrg * and free any partial allocations 13535c4bbdfSmrg */ 13605b261ecSmrg 13735c4bbdfSmrg free(tmpConfigBuf); 13835c4bbdfSmrg free(tmpConfigRBuf); 13905b261ecSmrg 14035c4bbdfSmrg } 14135c4bbdfSmrg else { 14205b261ecSmrg 14335c4bbdfSmrg /* 14435c4bbdfSmrg * malloc succeeded; free the old buffers and use the new 14535c4bbdfSmrg * buffers 14635c4bbdfSmrg */ 14705b261ecSmrg 14835c4bbdfSmrg configBufLen = CONFIG_BUF_LEN; 14905b261ecSmrg 15035c4bbdfSmrg free(configBuf); 15135c4bbdfSmrg free(configRBuf); 15205b261ecSmrg 15335c4bbdfSmrg configBuf = tmpConfigBuf; 15435c4bbdfSmrg configRBuf = tmpConfigRBuf; 15535c4bbdfSmrg } 15635c4bbdfSmrg } 15705b261ecSmrg 15835c4bbdfSmrg /* read in another block of chars */ 15905b261ecSmrg 16035c4bbdfSmrg do { 16135c4bbdfSmrg ret = fgets(configBuf + pos, configBufLen - pos - 1, 16235c4bbdfSmrg configFiles[curFileIndex].file); 16305b261ecSmrg 16435c4bbdfSmrg if (!ret) { 16535c4bbdfSmrg /* 16635c4bbdfSmrg * if the file doesn't end in a newline, add one 16735c4bbdfSmrg * and trigger another read 16835c4bbdfSmrg */ 16935c4bbdfSmrg if (pos != 0) { 17035c4bbdfSmrg strcpy(&configBuf[pos], "\n"); 17135c4bbdfSmrg ret = configBuf; 17235c4bbdfSmrg } 17335c4bbdfSmrg else 17435c4bbdfSmrg break; 17535c4bbdfSmrg } 17605b261ecSmrg 17735c4bbdfSmrg /* search for EOL in the new block of chars */ 17805b261ecSmrg 17935c4bbdfSmrg for (i = pos; i < (configBufLen - 1); i++) { 18035c4bbdfSmrg c = configBuf[i]; 18105b261ecSmrg 18235c4bbdfSmrg if (c == '\0') 18335c4bbdfSmrg break; 18405b261ecSmrg 18535c4bbdfSmrg if ((c == '\n') || (c == '\r')) { 18635c4bbdfSmrg eolFound = 1; 18735c4bbdfSmrg break; 18835c4bbdfSmrg } 18935c4bbdfSmrg } 19005b261ecSmrg 19135c4bbdfSmrg /* 19235c4bbdfSmrg * if we didn't find EOL, then grow the string and 19335c4bbdfSmrg * read in more 19435c4bbdfSmrg */ 19505b261ecSmrg 19635c4bbdfSmrg if (!eolFound) { 19705b261ecSmrg 19835c4bbdfSmrg tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN); 19935c4bbdfSmrg tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN); 20005b261ecSmrg 20135c4bbdfSmrg if (!tmpConfigBuf || !tmpConfigRBuf) { 20205b261ecSmrg 20335c4bbdfSmrg /* 20435c4bbdfSmrg * at least one of the reallocations failed; use the 20535c4bbdfSmrg * new allocation that succeeded, but we have to 20635c4bbdfSmrg * fallback to the previous configBufLen size and use 20735c4bbdfSmrg * the string we have, even though we don't have an 20835c4bbdfSmrg * EOL 20935c4bbdfSmrg */ 21005b261ecSmrg 21135c4bbdfSmrg if (tmpConfigBuf) 21235c4bbdfSmrg configBuf = tmpConfigBuf; 21335c4bbdfSmrg if (tmpConfigRBuf) 21435c4bbdfSmrg configRBuf = tmpConfigRBuf; 21505b261ecSmrg 21635c4bbdfSmrg break; 21705b261ecSmrg 21835c4bbdfSmrg } 21935c4bbdfSmrg else { 22005b261ecSmrg 22135c4bbdfSmrg /* reallocation succeeded */ 22205b261ecSmrg 22335c4bbdfSmrg configBuf = tmpConfigBuf; 22435c4bbdfSmrg configRBuf = tmpConfigRBuf; 22535c4bbdfSmrg pos = i; 22635c4bbdfSmrg configBufLen += CONFIG_BUF_LEN; 22735c4bbdfSmrg } 22835c4bbdfSmrg } 22905b261ecSmrg 23035c4bbdfSmrg } while (!eolFound); 23105b261ecSmrg 23235c4bbdfSmrg return ret; 23305b261ecSmrg} 23405b261ecSmrg 2351b5d61b8Smrgstatic int 2361b5d61b8SmrgStringToToken(const char *str, const xf86ConfigSymTabRec * tab) 2371b5d61b8Smrg{ 2381b5d61b8Smrg int i; 2391b5d61b8Smrg 2401b5d61b8Smrg for (i = 0; tab[i].token != -1; i++) { 2411b5d61b8Smrg if (!xf86nameCompare(tab[i].name, str)) 2421b5d61b8Smrg return tab[i].token; 2431b5d61b8Smrg } 2441b5d61b8Smrg return ERROR_TOKEN; 2451b5d61b8Smrg} 2461b5d61b8Smrg 24735c4bbdfSmrg/* 24805b261ecSmrg * xf86getToken -- 24905b261ecSmrg * Read next Token from the config file. Handle the global variable 25005b261ecSmrg * pushToken. 25105b261ecSmrg */ 25205b261ecSmrgint 2531b5d61b8Smrgxf86getToken(const xf86ConfigSymTabRec * tab) 25405b261ecSmrg{ 25535c4bbdfSmrg int c, i; 25635c4bbdfSmrg 25735c4bbdfSmrg /* 25835c4bbdfSmrg * First check whether pushToken has a different value than LOCK_TOKEN. 25935c4bbdfSmrg * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the 26035c4bbdfSmrg * oth * case the next token must be read from the input. 26135c4bbdfSmrg */ 26235c4bbdfSmrg if (pushToken == EOF_TOKEN) 26335c4bbdfSmrg return EOF_TOKEN; 26435c4bbdfSmrg else if (pushToken == LOCK_TOKEN) { 26535c4bbdfSmrg /* 26635c4bbdfSmrg * eol_seen is only set for the first token after a newline. 26735c4bbdfSmrg */ 26835c4bbdfSmrg eol_seen = 0; 26935c4bbdfSmrg 27035c4bbdfSmrg c = configBuf[configPos]; 27135c4bbdfSmrg 27235c4bbdfSmrg /* 27335c4bbdfSmrg * Get start of next Token. EOF is handled, 27435c4bbdfSmrg * whitespaces are skipped. 27535c4bbdfSmrg */ 27635c4bbdfSmrg 27735c4bbdfSmrg again: 27835c4bbdfSmrg if (!c) { 27935c4bbdfSmrg char *ret; 28035c4bbdfSmrg 28135c4bbdfSmrg if (numFiles > 0) 28235c4bbdfSmrg ret = xf86getNextLine(); 28335c4bbdfSmrg else { 28435c4bbdfSmrg if (builtinConfig[builtinIndex] == NULL) 28535c4bbdfSmrg ret = NULL; 28635c4bbdfSmrg else { 28735c4bbdfSmrg strlcpy(configBuf, 28835c4bbdfSmrg builtinConfig[builtinIndex], CONFIG_BUF_LEN); 28935c4bbdfSmrg ret = configBuf; 29035c4bbdfSmrg builtinIndex++; 29135c4bbdfSmrg } 29235c4bbdfSmrg } 29335c4bbdfSmrg if (ret == NULL) { 29435c4bbdfSmrg /* 29535c4bbdfSmrg * if necessary, move to the next file and 29635c4bbdfSmrg * read the first line 29735c4bbdfSmrg */ 29835c4bbdfSmrg if (curFileIndex + 1 < numFiles) { 29935c4bbdfSmrg curFileIndex++; 30035c4bbdfSmrg configLineNo = 0; 30135c4bbdfSmrg goto again; 30235c4bbdfSmrg } 30335c4bbdfSmrg else 30435c4bbdfSmrg return pushToken = EOF_TOKEN; 30535c4bbdfSmrg } 30635c4bbdfSmrg configLineNo++; 30735c4bbdfSmrg configPos = 0; 30835c4bbdfSmrg eol_seen = 1; 30935c4bbdfSmrg } 31035c4bbdfSmrg 31135c4bbdfSmrg i = 0; 31235c4bbdfSmrg for (;;) { 31335c4bbdfSmrg c = configBuf[configPos++]; 31435c4bbdfSmrg configRBuf[i++] = c; 31535c4bbdfSmrg switch (c) { 31635c4bbdfSmrg case ' ': 31735c4bbdfSmrg case '\t': 31835c4bbdfSmrg case '\r': 31935c4bbdfSmrg continue; 32035c4bbdfSmrg case '\n': 32135c4bbdfSmrg i = 0; 32235c4bbdfSmrg continue; 32335c4bbdfSmrg } 32435c4bbdfSmrg break; 32535c4bbdfSmrg } 32635c4bbdfSmrg if (c == '\0') 32735c4bbdfSmrg goto again; 32835c4bbdfSmrg 32935c4bbdfSmrg if (c == '#') { 33035c4bbdfSmrg do { 33135c4bbdfSmrg configRBuf[i++] = (c = configBuf[configPos++]); 33235c4bbdfSmrg } 33335c4bbdfSmrg while ((c != '\n') && (c != '\r') && (c != '\0')); 33435c4bbdfSmrg configRBuf[i] = '\0'; 33558cf2af7Smrg /* XXX private copy. 33635c4bbdfSmrg * Use xf86addComment when setting a comment. 33735c4bbdfSmrg */ 33858cf2af7Smrg xf86_lex_val.str = strdup(configRBuf); 33935c4bbdfSmrg return COMMENT; 34035c4bbdfSmrg } 34135c4bbdfSmrg 34235c4bbdfSmrg /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */ 34335c4bbdfSmrg else if ((c == ',') && !isalpha(configBuf[configPos])) { 34435c4bbdfSmrg return COMMA; 34535c4bbdfSmrg } 34635c4bbdfSmrg else if ((c == '-') && !isalpha(configBuf[configPos])) { 34735c4bbdfSmrg return DASH; 34835c4bbdfSmrg } 34935c4bbdfSmrg 35035c4bbdfSmrg /* 35135c4bbdfSmrg * Numbers are returned immediately ... 35235c4bbdfSmrg */ 35335c4bbdfSmrg if (isdigit(c)) { 35435c4bbdfSmrg int base; 35535c4bbdfSmrg 35635c4bbdfSmrg if (c == '0') 35735c4bbdfSmrg if ((configBuf[configPos] == 'x') || 35835c4bbdfSmrg (configBuf[configPos] == 'X')) { 35935c4bbdfSmrg base = 16; 36035c4bbdfSmrg xf86_lex_val.numType = PARSE_HEX; 36135c4bbdfSmrg } 36235c4bbdfSmrg else { 36335c4bbdfSmrg base = 8; 36435c4bbdfSmrg xf86_lex_val.numType = PARSE_OCTAL; 36535c4bbdfSmrg } 36635c4bbdfSmrg else { 36735c4bbdfSmrg base = 10; 36835c4bbdfSmrg xf86_lex_val.numType = PARSE_DECIMAL; 36935c4bbdfSmrg } 37035c4bbdfSmrg 37135c4bbdfSmrg configRBuf[0] = c; 37235c4bbdfSmrg i = 1; 37335c4bbdfSmrg while (isdigit(c = configBuf[configPos++]) || 37435c4bbdfSmrg (c == '.') || (c == 'x') || (c == 'X') || 37535c4bbdfSmrg ((base == 16) && (((c >= 'a') && (c <= 'f')) || 37635c4bbdfSmrg ((c >= 'A') && (c <= 'F'))))) 37735c4bbdfSmrg configRBuf[i++] = c; 37835c4bbdfSmrg configPos--; /* GJA -- one too far */ 37935c4bbdfSmrg configRBuf[i] = '\0'; 38035c4bbdfSmrg xf86_lex_val.num = strtoul(configRBuf, NULL, 0); 38135c4bbdfSmrg xf86_lex_val.realnum = atof(configRBuf); 38235c4bbdfSmrg return NUMBER; 38335c4bbdfSmrg } 38435c4bbdfSmrg 38535c4bbdfSmrg /* 38635c4bbdfSmrg * All Strings START with a \" ... 38735c4bbdfSmrg */ 38835c4bbdfSmrg else if (c == '\"') { 38935c4bbdfSmrg i = -1; 39035c4bbdfSmrg do { 39135c4bbdfSmrg configRBuf[++i] = (c = configBuf[configPos++]); 39235c4bbdfSmrg } 39335c4bbdfSmrg while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); 39435c4bbdfSmrg configRBuf[i] = '\0'; 39535c4bbdfSmrg xf86_lex_val.str = malloc(strlen(configRBuf) + 1); 39635c4bbdfSmrg strcpy(xf86_lex_val.str, configRBuf); /* private copy ! */ 39735c4bbdfSmrg return STRING; 39835c4bbdfSmrg } 39935c4bbdfSmrg 40035c4bbdfSmrg /* 40135c4bbdfSmrg * ... and now we MUST have a valid token. The search is 40235c4bbdfSmrg * handled later along with the pushed tokens. 40335c4bbdfSmrg */ 40435c4bbdfSmrg else { 40535c4bbdfSmrg configRBuf[0] = c; 40635c4bbdfSmrg i = 0; 40735c4bbdfSmrg do { 40835c4bbdfSmrg configRBuf[++i] = (c = configBuf[configPos++]); 40935c4bbdfSmrg } 41035c4bbdfSmrg while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && 41135c4bbdfSmrg (c != '\0') && (c != '#')); 41235c4bbdfSmrg --configPos; 41335c4bbdfSmrg configRBuf[i] = '\0'; 41435c4bbdfSmrg i = 0; 41535c4bbdfSmrg } 41635c4bbdfSmrg 41735c4bbdfSmrg } 41835c4bbdfSmrg else { 41935c4bbdfSmrg 42035c4bbdfSmrg /* 42135c4bbdfSmrg * Here we deal with pushed tokens. Reinitialize pushToken again. If 42235c4bbdfSmrg * the pushed token was NUMBER || STRING return them again ... 42335c4bbdfSmrg */ 42435c4bbdfSmrg int temp = pushToken; 42535c4bbdfSmrg 42635c4bbdfSmrg pushToken = LOCK_TOKEN; 42735c4bbdfSmrg 42835c4bbdfSmrg if (temp == COMMA || temp == DASH) 42935c4bbdfSmrg return temp; 43035c4bbdfSmrg if (temp == NUMBER || temp == STRING) 43135c4bbdfSmrg return temp; 43235c4bbdfSmrg } 43335c4bbdfSmrg 43435c4bbdfSmrg /* 43535c4bbdfSmrg * Joop, at last we have to lookup the token ... 43635c4bbdfSmrg */ 4371b5d61b8Smrg if (tab) 4381b5d61b8Smrg return StringToToken(configRBuf, tab); 43935c4bbdfSmrg 44035c4bbdfSmrg return ERROR_TOKEN; /* Error catcher */ 44105b261ecSmrg} 44205b261ecSmrg 44305b261ecSmrgint 44435c4bbdfSmrgxf86getSubToken(char **comment) 44505b261ecSmrg{ 44635c4bbdfSmrg int token; 44735c4bbdfSmrg 44835c4bbdfSmrg for (;;) { 44935c4bbdfSmrg token = xf86getToken(NULL); 45035c4bbdfSmrg if (token == COMMENT) { 45158cf2af7Smrg if (comment) { 45235c4bbdfSmrg *comment = xf86addComment(*comment, xf86_lex_val.str); 45358cf2af7Smrg free(xf86_lex_val.str); 45458cf2af7Smrg xf86_lex_val.str = NULL; 45558cf2af7Smrg } 45635c4bbdfSmrg } 45735c4bbdfSmrg else 45835c4bbdfSmrg return token; 45935c4bbdfSmrg } 46035c4bbdfSmrg /*NOTREACHED*/} 46105b261ecSmrg 46205b261ecSmrgint 4631b5d61b8Smrgxf86getSubTokenWithTab(char **comment, const xf86ConfigSymTabRec * tab) 46405b261ecSmrg{ 46535c4bbdfSmrg int token; 46635c4bbdfSmrg 46735c4bbdfSmrg for (;;) { 46835c4bbdfSmrg token = xf86getToken(tab); 46935c4bbdfSmrg if (token == COMMENT) { 47058cf2af7Smrg if (comment) { 47135c4bbdfSmrg *comment = xf86addComment(*comment, xf86_lex_val.str); 47258cf2af7Smrg free(xf86_lex_val.str); 47358cf2af7Smrg xf86_lex_val.str = NULL; 47458cf2af7Smrg } 47535c4bbdfSmrg } 47635c4bbdfSmrg else 47735c4bbdfSmrg return token; 47835c4bbdfSmrg } 47935c4bbdfSmrg /*NOTREACHED*/} 48005b261ecSmrg 48105b261ecSmrgvoid 48235c4bbdfSmrgxf86unGetToken(int token) 48305b261ecSmrg{ 48435c4bbdfSmrg pushToken = token; 48505b261ecSmrg} 48605b261ecSmrg 48705b261ecSmrgchar * 48835c4bbdfSmrgxf86tokenString(void) 48905b261ecSmrg{ 49035c4bbdfSmrg return configRBuf; 49105b261ecSmrg} 49205b261ecSmrg 49305b261ecSmrgint 49405b261ecSmrgxf86pathIsAbsolute(const char *path) 49505b261ecSmrg{ 49635c4bbdfSmrg if (path && path[0] == '/') 49735c4bbdfSmrg return 1; 49835c4bbdfSmrg return 0; 49905b261ecSmrg} 50005b261ecSmrg 50105b261ecSmrg/* A path is "safe" if it is relative and if it contains no ".." elements. */ 50205b261ecSmrgint 50305b261ecSmrgxf86pathIsSafe(const char *path) 50405b261ecSmrg{ 50535c4bbdfSmrg if (xf86pathIsAbsolute(path)) 50635c4bbdfSmrg return 0; 50705b261ecSmrg 50835c4bbdfSmrg /* Compare with ".." */ 50935c4bbdfSmrg if (!strcmp(path, "..")) 51035c4bbdfSmrg return 0; 51105b261ecSmrg 51235c4bbdfSmrg /* Look for leading "../" */ 51335c4bbdfSmrg if (!strncmp(path, "../", 3)) 51435c4bbdfSmrg return 0; 51505b261ecSmrg 51635c4bbdfSmrg /* Look for trailing "/.." */ 51735c4bbdfSmrg if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/..")) 51835c4bbdfSmrg return 0; 51905b261ecSmrg 52035c4bbdfSmrg /* Look for "/../" */ 52135c4bbdfSmrg if (strstr(path, "/../")) 52235c4bbdfSmrg return 0; 52305b261ecSmrg 52435c4bbdfSmrg return 1; 52505b261ecSmrg} 52605b261ecSmrg 52705b261ecSmrg/* 52805b261ecSmrg * This function substitutes the following escape sequences: 52905b261ecSmrg * 53005b261ecSmrg * %A cmdline argument as an absolute path (must be absolute to match) 53105b261ecSmrg * %R cmdline argument as a relative path 53205b261ecSmrg * %S cmdline argument as a "safe" path (relative, and no ".." elements) 53305b261ecSmrg * %X default config file name ("xorg.conf") 53405b261ecSmrg * %H hostname 53505b261ecSmrg * %E config file environment ($XORGCONFIG) as an absolute path 53605b261ecSmrg * %F config file environment ($XORGCONFIG) as a relative path 53705b261ecSmrg * %G config file environment ($XORGCONFIG) as a safe path 53805b261ecSmrg * %P projroot 5396747b715Smrg * %C sysconfdir 5406747b715Smrg * %D datadir 54105b261ecSmrg * %% % 54205b261ecSmrg */ 54305b261ecSmrg 5446747b715Smrg#define XCONFIGSUFFIX ".conf" 5456747b715Smrg#define XCONFENV "XORGCONFIG" 54605b261ecSmrg 54705b261ecSmrg#define BAIL_OUT do { \ 5486747b715Smrg free(result); \ 54905b261ecSmrg return NULL; \ 55005b261ecSmrg } while (0) 55105b261ecSmrg 55205b261ecSmrg#define CHECK_LENGTH do { \ 55305b261ecSmrg if (l > PATH_MAX) { \ 55405b261ecSmrg BAIL_OUT; \ 55505b261ecSmrg } \ 55605b261ecSmrg } while (0) 55705b261ecSmrg 55805b261ecSmrg#define APPEND_STR(s) do { \ 55905b261ecSmrg if (strlen(s) + l > PATH_MAX) { \ 56005b261ecSmrg BAIL_OUT; \ 56105b261ecSmrg } else { \ 56205b261ecSmrg strcpy(result + l, s); \ 56305b261ecSmrg l += strlen(s); \ 56405b261ecSmrg } \ 56505b261ecSmrg } while (0) 56605b261ecSmrg 56705b261ecSmrgstatic char * 56805b261ecSmrgDoSubstitution(const char *template, const char *cmdline, const char *projroot, 56935c4bbdfSmrg int *cmdlineUsed, int *envUsed, const char *XConfigFile) 57005b261ecSmrg{ 57135c4bbdfSmrg char *result; 57235c4bbdfSmrg int i, l; 57335c4bbdfSmrg static const char *env = NULL; 57435c4bbdfSmrg static char *hostname = NULL; 57535c4bbdfSmrg 57635c4bbdfSmrg if (!template) 57735c4bbdfSmrg return NULL; 57835c4bbdfSmrg 57935c4bbdfSmrg if (cmdlineUsed) 58035c4bbdfSmrg *cmdlineUsed = 0; 58135c4bbdfSmrg if (envUsed) 58235c4bbdfSmrg *envUsed = 0; 58335c4bbdfSmrg 58435c4bbdfSmrg result = malloc(PATH_MAX + 1); 58535c4bbdfSmrg l = 0; 58635c4bbdfSmrg for (i = 0; template[i]; i++) { 58735c4bbdfSmrg if (template[i] != '%') { 58835c4bbdfSmrg result[l++] = template[i]; 58935c4bbdfSmrg CHECK_LENGTH; 59035c4bbdfSmrg } 59135c4bbdfSmrg else { 59235c4bbdfSmrg switch (template[++i]) { 59335c4bbdfSmrg case 'A': 59435c4bbdfSmrg if (cmdline && xf86pathIsAbsolute(cmdline)) { 59535c4bbdfSmrg APPEND_STR(cmdline); 59635c4bbdfSmrg if (cmdlineUsed) 59735c4bbdfSmrg *cmdlineUsed = 1; 59835c4bbdfSmrg } 59935c4bbdfSmrg else 60035c4bbdfSmrg BAIL_OUT; 60135c4bbdfSmrg break; 60235c4bbdfSmrg case 'R': 60335c4bbdfSmrg if (cmdline && !xf86pathIsAbsolute(cmdline)) { 60435c4bbdfSmrg APPEND_STR(cmdline); 60535c4bbdfSmrg if (cmdlineUsed) 60635c4bbdfSmrg *cmdlineUsed = 1; 60735c4bbdfSmrg } 60835c4bbdfSmrg else 60935c4bbdfSmrg BAIL_OUT; 61035c4bbdfSmrg break; 61135c4bbdfSmrg case 'S': 61235c4bbdfSmrg if (cmdline && xf86pathIsSafe(cmdline)) { 61335c4bbdfSmrg APPEND_STR(cmdline); 61435c4bbdfSmrg if (cmdlineUsed) 61535c4bbdfSmrg *cmdlineUsed = 1; 61635c4bbdfSmrg } 61735c4bbdfSmrg else 61835c4bbdfSmrg BAIL_OUT; 61935c4bbdfSmrg break; 62035c4bbdfSmrg case 'X': 62135c4bbdfSmrg APPEND_STR(XConfigFile); 62235c4bbdfSmrg break; 62335c4bbdfSmrg case 'H': 62435c4bbdfSmrg if (!hostname) { 62535c4bbdfSmrg if ((hostname = malloc(MAXHOSTNAMELEN + 1))) { 62635c4bbdfSmrg if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { 62735c4bbdfSmrg hostname[MAXHOSTNAMELEN] = '\0'; 62835c4bbdfSmrg } 62935c4bbdfSmrg else { 63035c4bbdfSmrg free(hostname); 63135c4bbdfSmrg hostname = NULL; 63235c4bbdfSmrg } 63335c4bbdfSmrg } 63435c4bbdfSmrg } 63535c4bbdfSmrg if (hostname) 63635c4bbdfSmrg APPEND_STR(hostname); 63735c4bbdfSmrg break; 63835c4bbdfSmrg case 'E': 63935c4bbdfSmrg if (!env) 64035c4bbdfSmrg env = getenv(XCONFENV); 64135c4bbdfSmrg if (env && xf86pathIsAbsolute(env)) { 64235c4bbdfSmrg APPEND_STR(env); 64335c4bbdfSmrg if (envUsed) 64435c4bbdfSmrg *envUsed = 1; 64535c4bbdfSmrg } 64635c4bbdfSmrg else 64735c4bbdfSmrg BAIL_OUT; 64835c4bbdfSmrg break; 64935c4bbdfSmrg case 'F': 65035c4bbdfSmrg if (!env) 65135c4bbdfSmrg env = getenv(XCONFENV); 65235c4bbdfSmrg if (env && !xf86pathIsAbsolute(env)) { 65335c4bbdfSmrg APPEND_STR(env); 65435c4bbdfSmrg if (envUsed) 65535c4bbdfSmrg *envUsed = 1; 65635c4bbdfSmrg } 65735c4bbdfSmrg else 65835c4bbdfSmrg BAIL_OUT; 65935c4bbdfSmrg break; 66035c4bbdfSmrg case 'G': 66135c4bbdfSmrg if (!env) 66235c4bbdfSmrg env = getenv(XCONFENV); 66335c4bbdfSmrg if (env && xf86pathIsSafe(env)) { 66435c4bbdfSmrg APPEND_STR(env); 66535c4bbdfSmrg if (envUsed) 66635c4bbdfSmrg *envUsed = 1; 66735c4bbdfSmrg } 66835c4bbdfSmrg else 66935c4bbdfSmrg BAIL_OUT; 67035c4bbdfSmrg break; 67135c4bbdfSmrg case 'P': 67235c4bbdfSmrg if (projroot && xf86pathIsAbsolute(projroot)) 67335c4bbdfSmrg APPEND_STR(projroot); 67435c4bbdfSmrg else 67535c4bbdfSmrg BAIL_OUT; 67635c4bbdfSmrg break; 67735c4bbdfSmrg case 'C': 67835c4bbdfSmrg APPEND_STR(SYSCONFDIR); 67935c4bbdfSmrg break; 68035c4bbdfSmrg case 'D': 68135c4bbdfSmrg APPEND_STR(DATADIR); 68235c4bbdfSmrg break; 68335c4bbdfSmrg case '%': 68435c4bbdfSmrg result[l++] = '%'; 68535c4bbdfSmrg CHECK_LENGTH; 68635c4bbdfSmrg break; 68735c4bbdfSmrg default: 68835c4bbdfSmrg fprintf(stderr, "invalid escape %%%c found in path template\n", 68935c4bbdfSmrg template[i]); 69035c4bbdfSmrg BAIL_OUT; 69135c4bbdfSmrg break; 69235c4bbdfSmrg } 69335c4bbdfSmrg } 69435c4bbdfSmrg } 69505b261ecSmrg#ifdef DEBUG 69635c4bbdfSmrg fprintf(stderr, "Converted `%s' to `%s'\n", template, result); 69705b261ecSmrg#endif 69835c4bbdfSmrg return result; 69905b261ecSmrg} 70005b261ecSmrg 7016747b715Smrg/* 7026747b715Smrg * Given some searching parameters, locate and open the xorg config file. 7036747b715Smrg */ 7046747b715Smrgstatic char * 7056747b715SmrgOpenConfigFile(const char *path, const char *cmdline, const char *projroot, 70635c4bbdfSmrg const char *confname) 7076747b715Smrg{ 70835c4bbdfSmrg char *filepath = NULL; 70935c4bbdfSmrg char *pathcopy; 71035c4bbdfSmrg const char *template; 71135c4bbdfSmrg int cmdlineUsed = 0; 71235c4bbdfSmrg FILE *file = NULL; 71335c4bbdfSmrg 71435c4bbdfSmrg pathcopy = strdup(path); 71535c4bbdfSmrg for (template = strtok(pathcopy, ","); template && !file; 71635c4bbdfSmrg template = strtok(NULL, ",")) { 71735c4bbdfSmrg filepath = DoSubstitution(template, cmdline, projroot, 71835c4bbdfSmrg &cmdlineUsed, NULL, confname); 71935c4bbdfSmrg if (!filepath) 72035c4bbdfSmrg continue; 72135c4bbdfSmrg if (cmdline && !cmdlineUsed) { 72235c4bbdfSmrg free(filepath); 72335c4bbdfSmrg filepath = NULL; 72435c4bbdfSmrg continue; 72535c4bbdfSmrg } 72635c4bbdfSmrg file = fopen(filepath, "r"); 72735c4bbdfSmrg if (!file) { 72835c4bbdfSmrg free(filepath); 72935c4bbdfSmrg filepath = NULL; 73035c4bbdfSmrg } 73135c4bbdfSmrg } 73235c4bbdfSmrg 73335c4bbdfSmrg free(pathcopy); 73435c4bbdfSmrg if (file) { 73535c4bbdfSmrg configFiles[numFiles].file = file; 73635c4bbdfSmrg configFiles[numFiles].path = strdup(filepath); 73735c4bbdfSmrg numFiles++; 73835c4bbdfSmrg } 73935c4bbdfSmrg return filepath; 7406747b715Smrg} 7416747b715Smrg 7426747b715Smrg/* 7436747b715Smrg * Match non-hidden files in the xorg config directory with a .conf 7446747b715Smrg * suffix. This filter is passed to scandir(3). 7456747b715Smrg */ 7466747b715Smrgstatic int 7476747b715SmrgConfigFilter(const struct dirent *de) 7486747b715Smrg{ 74935c4bbdfSmrg const char *name = de->d_name; 75035c4bbdfSmrg size_t len; 75135c4bbdfSmrg size_t suflen = strlen(XCONFIGSUFFIX); 75235c4bbdfSmrg 75335c4bbdfSmrg if (!name || name[0] == '.') 75435c4bbdfSmrg return 0; 75535c4bbdfSmrg len = strlen(name); 75635c4bbdfSmrg if (len <= suflen) 75735c4bbdfSmrg return 0; 75835c4bbdfSmrg if (strcmp(&name[len - suflen], XCONFIGSUFFIX) != 0) 75935c4bbdfSmrg return 0; 76035c4bbdfSmrg return 1; 7616747b715Smrg} 7626747b715Smrg 7636747b715Smrgstatic Bool 7646747b715SmrgAddConfigDirFiles(const char *dirpath, struct dirent **list, int num) 7656747b715Smrg{ 76635c4bbdfSmrg int i; 76735c4bbdfSmrg Bool openedFile = FALSE; 76835c4bbdfSmrg Bool warnOnce = FALSE; 76935c4bbdfSmrg 77035c4bbdfSmrg for (i = 0; i < num; i++) { 77135c4bbdfSmrg char *path; 77235c4bbdfSmrg FILE *file; 77335c4bbdfSmrg 77435c4bbdfSmrg if (numFiles >= CONFIG_MAX_FILES) { 77535c4bbdfSmrg if (!warnOnce) { 77635c4bbdfSmrg ErrorF("Maximum number of configuration " "files opened\n"); 77735c4bbdfSmrg warnOnce = TRUE; 77835c4bbdfSmrg } 77935c4bbdfSmrg continue; 78035c4bbdfSmrg } 78135c4bbdfSmrg 78235c4bbdfSmrg path = malloc(PATH_MAX + 1); 78335c4bbdfSmrg snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, list[i]->d_name); 78435c4bbdfSmrg file = fopen(path, "r"); 78535c4bbdfSmrg if (!file) { 78635c4bbdfSmrg free(path); 78735c4bbdfSmrg continue; 78835c4bbdfSmrg } 78935c4bbdfSmrg openedFile = TRUE; 79035c4bbdfSmrg 79135c4bbdfSmrg configFiles[numFiles].file = file; 79235c4bbdfSmrg configFiles[numFiles].path = path; 79335c4bbdfSmrg numFiles++; 79435c4bbdfSmrg } 79535c4bbdfSmrg 79635c4bbdfSmrg return openedFile; 7976747b715Smrg} 7986747b715Smrg 7996747b715Smrg/* 8006747b715Smrg * Given some searching parameters, locate and open the xorg config 8016747b715Smrg * directory. The directory does not need to contain config files. 8026747b715Smrg */ 8036747b715Smrgstatic char * 8046747b715SmrgOpenConfigDir(const char *path, const char *cmdline, const char *projroot, 80535c4bbdfSmrg const char *confname) 8066747b715Smrg{ 80735c4bbdfSmrg char *dirpath = NULL, *pathcopy; 80835c4bbdfSmrg const char *template; 80935c4bbdfSmrg Bool found = FALSE; 81035c4bbdfSmrg int cmdlineUsed = 0; 81135c4bbdfSmrg 81235c4bbdfSmrg pathcopy = strdup(path); 81335c4bbdfSmrg for (template = strtok(pathcopy, ","); template && !found; 81435c4bbdfSmrg template = strtok(NULL, ",")) { 81535c4bbdfSmrg struct dirent **list = NULL; 81635c4bbdfSmrg int num; 81735c4bbdfSmrg 81835c4bbdfSmrg dirpath = DoSubstitution(template, cmdline, projroot, 81935c4bbdfSmrg &cmdlineUsed, NULL, confname); 82035c4bbdfSmrg if (!dirpath) 82135c4bbdfSmrg continue; 82235c4bbdfSmrg if (cmdline && !cmdlineUsed) { 82335c4bbdfSmrg free(dirpath); 82435c4bbdfSmrg dirpath = NULL; 82535c4bbdfSmrg continue; 82635c4bbdfSmrg } 82735c4bbdfSmrg 82835c4bbdfSmrg /* match files named *.conf */ 82935c4bbdfSmrg num = scandir(dirpath, &list, ConfigFilter, alphasort); 83035c4bbdfSmrg if (num < 0) { 83135c4bbdfSmrg list = NULL; 83235c4bbdfSmrg num = 0; 83335c4bbdfSmrg } 83435c4bbdfSmrg found = AddConfigDirFiles(dirpath, list, num); 83535c4bbdfSmrg if (!found) { 83635c4bbdfSmrg free(dirpath); 83735c4bbdfSmrg dirpath = NULL; 83835c4bbdfSmrg } 83935c4bbdfSmrg while (num--) 84035c4bbdfSmrg free(list[num]); 84135c4bbdfSmrg free(list); 84235c4bbdfSmrg } 84335c4bbdfSmrg 84435c4bbdfSmrg free(pathcopy); 84535c4bbdfSmrg return dirpath; 8466747b715Smrg} 8476747b715Smrg 8486747b715Smrg/* 8496747b715Smrg * xf86initConfigFiles -- Setup global variables and buffers. 8506747b715Smrg */ 8516747b715Smrgvoid 8526747b715Smrgxf86initConfigFiles(void) 8536747b715Smrg{ 85435c4bbdfSmrg curFileIndex = 0; 85535c4bbdfSmrg configPos = 0; 85635c4bbdfSmrg configLineNo = 0; 85735c4bbdfSmrg pushToken = LOCK_TOKEN; 85835c4bbdfSmrg 85935c4bbdfSmrg configBuf = malloc(CONFIG_BUF_LEN); 86035c4bbdfSmrg configRBuf = malloc(CONFIG_BUF_LEN); 86135c4bbdfSmrg configBuf[0] = '\0'; /* sanity ... */ 8626747b715Smrg} 8636747b715Smrg 8646747b715Smrg/* 86505b261ecSmrg * xf86openConfigFile -- 86605b261ecSmrg * 86705b261ecSmrg * This function take a config file search path (optional), a command-line 86805b261ecSmrg * specified file name (optional) and the ProjectRoot path (optional) and 86905b261ecSmrg * locates and opens a config file based on that information. If a 87005b261ecSmrg * command-line file name is specified, then this function fails if none 87105b261ecSmrg * of the located files. 87205b261ecSmrg * 87305b261ecSmrg * The return value is a pointer to the actual name of the file that was 87435c4bbdfSmrg * opened. When no file is found, the return value is NULL. The caller should 87535c4bbdfSmrg * free() the returned value. 87605b261ecSmrg * 87705b261ecSmrg * The escape sequences allowed in the search path are defined above. 8786747b715Smrg * 87905b261ecSmrg */ 88005b261ecSmrg 88105b261ecSmrg#ifndef DEFAULT_CONF_PATH 88205b261ecSmrg#define DEFAULT_CONF_PATH "/etc/X11/%S," \ 88305b261ecSmrg "%P/etc/X11/%S," \ 88405b261ecSmrg "/etc/X11/%G," \ 88505b261ecSmrg "%P/etc/X11/%G," \ 88605b261ecSmrg "/etc/X11/%X-%M," \ 88705b261ecSmrg "/etc/X11/%X," \ 88805b261ecSmrg "/etc/%X," \ 88905b261ecSmrg "%P/etc/X11/%X.%H," \ 89005b261ecSmrg "%P/etc/X11/%X-%M," \ 89105b261ecSmrg "%P/etc/X11/%X," \ 89205b261ecSmrg "%P/lib/X11/%X.%H," \ 89305b261ecSmrg "%P/lib/X11/%X-%M," \ 89405b261ecSmrg "%P/lib/X11/%X" 89505b261ecSmrg#endif 89605b261ecSmrg 89735c4bbdfSmrgchar * 89805b261ecSmrgxf86openConfigFile(const char *path, const char *cmdline, const char *projroot) 89905b261ecSmrg{ 90035c4bbdfSmrg if (!path || !path[0]) 90135c4bbdfSmrg path = DEFAULT_CONF_PATH; 90235c4bbdfSmrg if (!projroot || !projroot[0]) 90335c4bbdfSmrg projroot = PROJECTROOT; 90435c4bbdfSmrg 90535c4bbdfSmrg /* Search for a config file */ 90635c4bbdfSmrg return OpenConfigFile(path, cmdline, projroot, XCONFIGFILE); 9076747b715Smrg} 90805b261ecSmrg 9096747b715Smrg/* 9106747b715Smrg * xf86openConfigDirFiles -- 9116747b715Smrg * 9126747b715Smrg * This function take a config directory search path (optional), a 9136747b715Smrg * command-line specified directory name (optional) and the ProjectRoot path 9146747b715Smrg * (optional) and locates and opens a config directory based on that 9156747b715Smrg * information. If a command-line name is specified, then this function 9166747b715Smrg * fails if it is not found. 9176747b715Smrg * 9181b5d61b8Smrg * The return value is a pointer to the actual name of the directory that was 91935c4bbdfSmrg * opened. When no directory is found, the return value is NULL. The caller 92035c4bbdfSmrg * should free() the returned value. 9216747b715Smrg * 9226747b715Smrg * The escape sequences allowed in the search path are defined above. 9236747b715Smrg * 9246747b715Smrg */ 92535c4bbdfSmrgchar * 9266747b715Smrgxf86openConfigDirFiles(const char *path, const char *cmdline, 92735c4bbdfSmrg const char *projroot) 9286747b715Smrg{ 92935c4bbdfSmrg if (!path || !path[0]) 93035c4bbdfSmrg path = DEFAULT_CONF_PATH; 93135c4bbdfSmrg if (!projroot || !projroot[0]) 93235c4bbdfSmrg projroot = PROJECTROOT; 93335c4bbdfSmrg 93435c4bbdfSmrg /* Search for the multiconf directory */ 93535c4bbdfSmrg return OpenConfigDir(path, cmdline, projroot, XCONFIGDIR); 93605b261ecSmrg} 93705b261ecSmrg 93805b261ecSmrgvoid 93935c4bbdfSmrgxf86closeConfigFile(void) 94005b261ecSmrg{ 94135c4bbdfSmrg int i; 94235c4bbdfSmrg 94335c4bbdfSmrg free(configRBuf); 94435c4bbdfSmrg configRBuf = NULL; 94535c4bbdfSmrg free(configBuf); 94635c4bbdfSmrg configBuf = NULL; 94735c4bbdfSmrg 94835c4bbdfSmrg if (numFiles == 0) { 94935c4bbdfSmrg builtinConfig = NULL; 95035c4bbdfSmrg builtinIndex = 0; 95135c4bbdfSmrg } 95235c4bbdfSmrg for (i = 0; i < numFiles; i++) { 95335c4bbdfSmrg fclose(configFiles[i].file); 95435c4bbdfSmrg configFiles[i].file = NULL; 95535c4bbdfSmrg free(configFiles[i].path); 95635c4bbdfSmrg configFiles[i].path = NULL; 95735c4bbdfSmrg } 95835c4bbdfSmrg numFiles = 0; 95905b261ecSmrg} 96005b261ecSmrg 96105b261ecSmrgvoid 96205b261ecSmrgxf86setBuiltinConfig(const char *config[]) 96305b261ecSmrg{ 96435c4bbdfSmrg builtinConfig = config; 96505b261ecSmrg} 96605b261ecSmrg 96705b261ecSmrgvoid 96835c4bbdfSmrgxf86parseError(const char *format, ...) 96905b261ecSmrg{ 97035c4bbdfSmrg va_list ap; 97135c4bbdfSmrg const char *filename = numFiles ? configFiles[curFileIndex].path 97235c4bbdfSmrg : "<builtin configuration>"; 97305b261ecSmrg 97435c4bbdfSmrg ErrorF("Parse error on line %d of section %s in file %s\n\t", 97535c4bbdfSmrg configLineNo, configSection, filename); 97635c4bbdfSmrg va_start(ap, format); 97735c4bbdfSmrg VErrorF(format, ap); 97835c4bbdfSmrg va_end(ap); 97905b261ecSmrg 98035c4bbdfSmrg ErrorF("\n"); 98105b261ecSmrg} 98205b261ecSmrg 98305b261ecSmrgvoid 98435c4bbdfSmrgxf86validationError(const char *format, ...) 98505b261ecSmrg{ 98635c4bbdfSmrg va_list ap; 98735c4bbdfSmrg const char *filename = numFiles ? configFiles[curFileIndex].path 98835c4bbdfSmrg : "<builtin configuration>"; 98905b261ecSmrg 99035c4bbdfSmrg ErrorF("Data incomplete in file %s\n\t", filename); 99135c4bbdfSmrg va_start(ap, format); 99235c4bbdfSmrg VErrorF(format, ap); 99335c4bbdfSmrg va_end(ap); 99405b261ecSmrg 99535c4bbdfSmrg ErrorF("\n"); 99605b261ecSmrg} 99705b261ecSmrg 99805b261ecSmrgvoid 99935c4bbdfSmrgxf86setSection(const char *section) 100005b261ecSmrg{ 100135c4bbdfSmrg free(configSection); 100235c4bbdfSmrg configSection = strdup(section); 100305b261ecSmrg} 100405b261ecSmrg 100535c4bbdfSmrg/* 100605b261ecSmrg * xf86getToken -- 100705b261ecSmrg * Lookup a string if it is actually a token in disguise. 100805b261ecSmrg */ 100905b261ecSmrgint 10101b5d61b8Smrgxf86getStringToken(const xf86ConfigSymTabRec * tab) 101105b261ecSmrg{ 101235c4bbdfSmrg return StringToToken(xf86_lex_val.str, tab); 101305b261ecSmrg} 101405b261ecSmrg 101535c4bbdfSmrg/* 101605b261ecSmrg * Compare two names. The characters '_', ' ', and '\t' are ignored 101705b261ecSmrg * in the comparison. 101805b261ecSmrg */ 10196747b715Smrgint 102035c4bbdfSmrgxf86nameCompare(const char *s1, const char *s2) 102105b261ecSmrg{ 102235c4bbdfSmrg char c1, c2; 102335c4bbdfSmrg 102435c4bbdfSmrg if (!s1 || *s1 == 0) { 102535c4bbdfSmrg if (!s2 || *s2 == 0) 102635c4bbdfSmrg return 0; 102735c4bbdfSmrg else 102835c4bbdfSmrg return 1; 10291b5d61b8Smrg } else if (!s2 || *s2 == 0) { 10301b5d61b8Smrg return -1; 103135c4bbdfSmrg } 103235c4bbdfSmrg 103335c4bbdfSmrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 103435c4bbdfSmrg s1++; 103535c4bbdfSmrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 103635c4bbdfSmrg s2++; 103735c4bbdfSmrg c1 = (isupper(*s1) ? tolower(*s1) : *s1); 103835c4bbdfSmrg c2 = (isupper(*s2) ? tolower(*s2) : *s2); 103935c4bbdfSmrg while (c1 == c2) { 104035c4bbdfSmrg if (c1 == '\0') 104135c4bbdfSmrg return 0; 104235c4bbdfSmrg s1++; 104335c4bbdfSmrg s2++; 104435c4bbdfSmrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 104535c4bbdfSmrg s1++; 104635c4bbdfSmrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 104735c4bbdfSmrg s2++; 104835c4bbdfSmrg c1 = (isupper(*s1) ? tolower(*s1) : *s1); 104935c4bbdfSmrg c2 = (isupper(*s2) ? tolower(*s2) : *s2); 105035c4bbdfSmrg } 105135c4bbdfSmrg return c1 - c2; 105205b261ecSmrg} 105305b261ecSmrg 105405b261ecSmrgchar * 105535c4bbdfSmrgxf86addComment(char *cur, const char *add) 105605b261ecSmrg{ 105735c4bbdfSmrg char *str; 105835c4bbdfSmrg const char *cstr; 105935c4bbdfSmrg int len, curlen, iscomment, hasnewline = 0, insnewline, endnewline; 106035c4bbdfSmrg 106135c4bbdfSmrg if (add == NULL || add[0] == '\0') 106235c4bbdfSmrg return cur; 106335c4bbdfSmrg 106435c4bbdfSmrg if (cur) { 106535c4bbdfSmrg curlen = strlen(cur); 106635c4bbdfSmrg if (curlen) 106735c4bbdfSmrg hasnewline = cur[curlen - 1] == '\n'; 106835c4bbdfSmrg eol_seen = 0; 106935c4bbdfSmrg } 107035c4bbdfSmrg else 107135c4bbdfSmrg curlen = 0; 107235c4bbdfSmrg 107335c4bbdfSmrg cstr = add; 107435c4bbdfSmrg iscomment = 0; 107535c4bbdfSmrg while (*cstr) { 107635c4bbdfSmrg if (*cstr != ' ' && *cstr != '\t') 107735c4bbdfSmrg break; 107835c4bbdfSmrg ++cstr; 107935c4bbdfSmrg } 108035c4bbdfSmrg iscomment = (*cstr == '#'); 108135c4bbdfSmrg 108235c4bbdfSmrg len = strlen(add); 108335c4bbdfSmrg endnewline = add[len - 1] == '\n'; 108435c4bbdfSmrg 108535c4bbdfSmrg insnewline = eol_seen || (curlen && !hasnewline); 108635c4bbdfSmrg if (insnewline) 108735c4bbdfSmrg len++; 108835c4bbdfSmrg if (!iscomment) 108935c4bbdfSmrg len++; 109035c4bbdfSmrg if (!endnewline) 109135c4bbdfSmrg len++; 109235c4bbdfSmrg 109335c4bbdfSmrg /* Allocate + 1 char for '\0' terminator. */ 109435c4bbdfSmrg str = realloc(cur, curlen + len + 1); 109535c4bbdfSmrg if (!str) 109635c4bbdfSmrg return cur; 109735c4bbdfSmrg 109835c4bbdfSmrg cur = str; 109935c4bbdfSmrg 110035c4bbdfSmrg if (insnewline) 110135c4bbdfSmrg cur[curlen++] = '\n'; 110235c4bbdfSmrg if (!iscomment) 110335c4bbdfSmrg cur[curlen++] = '#'; 110435c4bbdfSmrg strcpy(cur + curlen, add); 110535c4bbdfSmrg if (!endnewline) 110635c4bbdfSmrg strcat(cur, "\n"); 110735c4bbdfSmrg 110835c4bbdfSmrg return cur; 11096747b715Smrg} 11106747b715Smrg 11116747b715SmrgBool 11126747b715Smrgxf86getBoolValue(Bool *val, const char *str) 11136747b715Smrg{ 111435c4bbdfSmrg if (!val || !str) 111535c4bbdfSmrg return FALSE; 111635c4bbdfSmrg if (*str == '\0') { 111735c4bbdfSmrg *val = TRUE; 111835c4bbdfSmrg } 111935c4bbdfSmrg else { 112035c4bbdfSmrg if (xf86nameCompare(str, "1") == 0) 112135c4bbdfSmrg *val = TRUE; 112235c4bbdfSmrg else if (xf86nameCompare(str, "on") == 0) 112335c4bbdfSmrg *val = TRUE; 112435c4bbdfSmrg else if (xf86nameCompare(str, "true") == 0) 112535c4bbdfSmrg *val = TRUE; 112635c4bbdfSmrg else if (xf86nameCompare(str, "yes") == 0) 112735c4bbdfSmrg *val = TRUE; 112835c4bbdfSmrg else if (xf86nameCompare(str, "0") == 0) 112935c4bbdfSmrg *val = FALSE; 113035c4bbdfSmrg else if (xf86nameCompare(str, "off") == 0) 113135c4bbdfSmrg *val = FALSE; 113235c4bbdfSmrg else if (xf86nameCompare(str, "false") == 0) 113335c4bbdfSmrg *val = FALSE; 113435c4bbdfSmrg else if (xf86nameCompare(str, "no") == 0) 113535c4bbdfSmrg *val = FALSE; 113635c4bbdfSmrg else 113735c4bbdfSmrg return FALSE; 113835c4bbdfSmrg } 113935c4bbdfSmrg return TRUE; 114005b261ecSmrg} 1141