From 02f377d5e2dd18537d0807ad63675a0970b5a37d Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 4 Nov 2011 08:57:20 +0100 Subject: xserver pixman mesa git update 4 nov 2011 --- xorg-server/hw/xfree86/parser/scan.c | 2343 +++++++++++++++++----------------- 1 file changed, 1176 insertions(+), 1167 deletions(-) (limited to 'xorg-server/hw/xfree86/parser') diff --git a/xorg-server/hw/xfree86/parser/scan.c b/xorg-server/hw/xfree86/parser/scan.c index b36e58e0f..99b325717 100644 --- a/xorg-server/hw/xfree86/parser/scan.c +++ b/xorg-server/hw/xfree86/parser/scan.c @@ -1,1167 +1,1176 @@ -/* - * Copyright (c) 1997 Metro Link Incorporated - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the Metro Link shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from Metro Link. - * - */ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - - -/* View/edit this file with tab stops set to 4 */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_POSIX_SOURCE) -#include -#else -#define _POSIX_SOURCE -#include -#undef _POSIX_SOURCE -#endif /* _POSIX_SOURCE */ - -#if !defined(MAXHOSTNAMELEN) -#define MAXHOSTNAMELEN 32 -#endif /* !MAXHOSTNAMELEN */ - -/* For PATH_MAX */ -#include "misc.h" - -#include "Configint.h" -#include "xf86tokens.h" - -#define CONFIG_BUF_LEN 1024 -#define CONFIG_MAX_FILES 64 - -static int StringToToken (char *, xf86ConfigSymTabRec *); - -static struct { - FILE *file; - char *path; -} configFiles[CONFIG_MAX_FILES]; -static const char **builtinConfig = NULL; -static int builtinIndex = 0; -static int configPos = 0; /* current readers position */ -static int configLineNo = 0; /* linenumber */ -static char *configBuf, *configRBuf; /* buffer for lines */ -static char *configPath; /* path to config file */ -static char *configDirPath; /* path to config dir */ -static char *configSection = NULL; /* name of current section being parsed */ -static int numFiles = 0; /* number of config files */ -static int curFileIndex = 0; /* index of current config file */ -static int pushToken = LOCK_TOKEN; -static int eol_seen = 0; /* private state to handle comments */ -LexRec val; - -/* - * xf86getNextLine -- - * - * read from the configFiles FILE stream until we encounter a new - * line; this is effectively just a big wrapper for fgets(3). - * - * xf86getToken() assumes that we will read up to the next - * newline; we need to grow configBuf and configRBuf as needed to - * support that. - */ - -static char* -xf86getNextLine(void) -{ - static int configBufLen = CONFIG_BUF_LEN; - char *tmpConfigBuf, *tmpConfigRBuf; - int c, i, pos = 0, eolFound = 0; - char *ret = NULL; - - /* - * reallocate the string if it was grown last time (i.e., is no - * longer CONFIG_BUF_LEN); we malloc the new strings first, so - * that if either of the mallocs fail, we can fall back on the - * existing buffer allocations - */ - - if (configBufLen != CONFIG_BUF_LEN) { - - tmpConfigBuf = malloc(CONFIG_BUF_LEN); - tmpConfigRBuf = malloc(CONFIG_BUF_LEN); - - if (!tmpConfigBuf || !tmpConfigRBuf) { - - /* - * at least one of the mallocs failed; keep the old buffers - * and free any partial allocations - */ - - free(tmpConfigBuf); - free(tmpConfigRBuf); - - } else { - - /* - * malloc succeeded; free the old buffers and use the new - * buffers - */ - - configBufLen = CONFIG_BUF_LEN; - - free(configBuf); - free(configRBuf); - - configBuf = tmpConfigBuf; - configRBuf = tmpConfigRBuf; - } - } - - /* read in another block of chars */ - - do { - ret = fgets(configBuf + pos, configBufLen - pos - 1, - configFiles[curFileIndex].file); - - if (!ret) { - /* - * if the file doesn't end in a newline, add one - * and trigger another read - */ - if (pos != 0) { - strcpy(&configBuf[pos], "\n"); - ret = configBuf; - } else - break; - } - - /* search for EOL in the new block of chars */ - - for (i = pos; i < (configBufLen - 1); i++) { - c = configBuf[i]; - - if (c == '\0') break; - - if ((c == '\n') || (c == '\r')) { - eolFound = 1; - break; - } - } - - /* - * if we didn't find EOL, then grow the string and - * read in more - */ - - if (!eolFound) { - - tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN); - tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN); - - if (!tmpConfigBuf || !tmpConfigRBuf) { - - /* - * at least one of the reallocations failed; use the - * new allocation that succeeded, but we have to - * fallback to the previous configBufLen size and use - * the string we have, even though we don't have an - * EOL - */ - - if (tmpConfigBuf) configBuf = tmpConfigBuf; - if (tmpConfigRBuf) configRBuf = tmpConfigRBuf; - - break; - - } else { - - /* reallocation succeeded */ - - configBuf = tmpConfigBuf; - configRBuf = tmpConfigRBuf; - pos = i; - configBufLen += CONFIG_BUF_LEN; - } - } - - } while (!eolFound); - - return ret; -} - -/* - * xf86getToken -- - * Read next Token from the config file. Handle the global variable - * pushToken. - */ -int -xf86getToken (xf86ConfigSymTabRec * tab) -{ - int c, i; - - /* - * First check whether pushToken has a different value than LOCK_TOKEN. - * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the - * oth * case the next token must be read from the input. - */ - if (pushToken == EOF_TOKEN) - return EOF_TOKEN; - else if (pushToken == LOCK_TOKEN) - { - /* - * eol_seen is only set for the first token after a newline. - */ - eol_seen = 0; - - c = configBuf[configPos]; - - /* - * Get start of next Token. EOF is handled, - * whitespaces are skipped. - */ - -again: - if (!c) - { - char *ret; - if (numFiles > 0) - ret = xf86getNextLine(); - else { - if (builtinConfig[builtinIndex] == NULL) - ret = NULL; - else { - ret = strncpy(configBuf, builtinConfig[builtinIndex], - CONFIG_BUF_LEN); - builtinIndex++; - } - } - if (ret == NULL) - { - /* - * if necessary, move to the next file and - * read the first line - */ - if (curFileIndex + 1 < numFiles) { - curFileIndex++; - configLineNo = 0; - goto again; - } - else - return pushToken = EOF_TOKEN; - } - configLineNo++; - configPos = 0; - eol_seen = 1; - } - - i = 0; - for (;;) { - c = configBuf[configPos++]; - configRBuf[i++] = c; - switch (c) { - case ' ': - case '\t': - case '\r': - continue; - case '\n': - i = 0; - continue; - } - break; - } - if (c == '\0') - goto again; - - if (c == '#') - { - do - { - configRBuf[i++] = (c = configBuf[configPos++]); - } - while ((c != '\n') && (c != '\r') && (c != '\0')); - configRBuf[i] = '\0'; - /* XXX no private copy. - * Use xf86addComment when setting a comment. - */ - val.str = configRBuf; - return COMMENT; - } - - /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */ - else if ((c == ',') && !isalpha (configBuf[configPos])) - { - return COMMA; - } - else if ((c == '-') && !isalpha (configBuf[configPos])) - { - return DASH; - } - - /* - * Numbers are returned immediately ... - */ - if (isdigit (c)) - { - int base; - - if (c == '0') - if ((configBuf[configPos] == 'x') || - (configBuf[configPos] == 'X')) - { - base = 16; - val.numType = PARSE_HEX; - } - else - { - base = 8; - val.numType = PARSE_OCTAL; - } - else - { - base = 10; - val.numType = PARSE_DECIMAL; - } - - configRBuf[0] = c; - i = 1; - while (isdigit (c = configBuf[configPos++]) || - (c == '.') || (c == 'x') || (c == 'X') || - ((base == 16) && (((c >= 'a') && (c <= 'f')) || - ((c >= 'A') && (c <= 'F'))))) - configRBuf[i++] = c; - configPos--; /* GJA -- one too far */ - configRBuf[i] = '\0'; - val.num = strtoul (configRBuf, NULL, 0); - val.realnum = atof (configRBuf); - return NUMBER; - } - - /* - * All Strings START with a \" ... - */ - else if (c == '\"') - { - i = -1; - do - { - configRBuf[++i] = (c = configBuf[configPos++]); - } - while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); - configRBuf[i] = '\0'; - val.str = malloc (strlen (configRBuf) + 1); - strcpy (val.str, configRBuf); /* private copy ! */ - return STRING; - } - - /* - * ... and now we MUST have a valid token. The search is - * handled later along with the pushed tokens. - */ - else - { - configRBuf[0] = c; - i = 0; - do - { - configRBuf[++i] = (c = configBuf[configPos++]); - } - while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#')); - --configPos; - configRBuf[i] = '\0'; - i = 0; - } - - } - else - { - - /* - * Here we deal with pushed tokens. Reinitialize pushToken again. If - * the pushed token was NUMBER || STRING return them again ... - */ - int temp = pushToken; - pushToken = LOCK_TOKEN; - - if (temp == COMMA || temp == DASH) - return temp; - if (temp == NUMBER || temp == STRING) - return temp; - } - - /* - * Joop, at last we have to lookup the token ... - */ - if (tab) - { - i = 0; - while (tab[i].token != -1) - if (xf86nameCompare (configRBuf, tab[i].name) == 0) - return tab[i].token; - else - i++; - } - - return ERROR_TOKEN; /* Error catcher */ -} - -int -xf86getSubToken (char **comment) -{ - int token; - - for (;;) { - token = xf86getToken(NULL); - if (token == COMMENT) { - if (comment) - *comment = xf86addComment(*comment, val.str); - } - else - return token; - } - /*NOTREACHED*/ -} - -int -xf86getSubTokenWithTab (char **comment, xf86ConfigSymTabRec *tab) -{ - int token; - - for (;;) { - token = xf86getToken(tab); - if (token == COMMENT) { - if (comment) - *comment = xf86addComment(*comment, val.str); - } - else - return token; - } - /*NOTREACHED*/ -} - -void -xf86unGetToken (int token) -{ - pushToken = token; -} - -char * -xf86tokenString (void) -{ - return configRBuf; -} - -int -xf86pathIsAbsolute(const char *path) -{ - if (path && path[0] == '/') - return 1; - return 0; -} - -/* A path is "safe" if it is relative and if it contains no ".." elements. */ -int -xf86pathIsSafe(const char *path) -{ - if (xf86pathIsAbsolute(path)) - return 0; - - /* Compare with ".." */ - if (!strcmp(path, "..")) - return 0; - - /* Look for leading "../" */ - if (!strncmp(path, "../", 3)) - return 0; - - /* Look for trailing "/.." */ - if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/..")) - return 0; - - /* Look for "/../" */ - if (strstr(path, "/../")) - return 0; - - return 1; -} - -/* - * This function substitutes the following escape sequences: - * - * %A cmdline argument as an absolute path (must be absolute to match) - * %R cmdline argument as a relative path - * %S cmdline argument as a "safe" path (relative, and no ".." elements) - * %X default config file name ("xorg.conf") - * %H hostname - * %E config file environment ($XORGCONFIG) as an absolute path - * %F config file environment ($XORGCONFIG) as a relative path - * %G config file environment ($XORGCONFIG) as a safe path - * %P projroot - * %C sysconfdir - * %D datadir - * %% % - */ - -#ifndef XCONFIGFILE -#define XCONFIGFILE "xorg.conf" -#endif -#ifndef XCONFIGDIR -#define XCONFIGDIR "xorg.conf.d" -#endif -#ifndef XCONFIGSUFFIX -#define XCONFIGSUFFIX ".conf" -#endif -#ifndef PROJECTROOT -#define PROJECTROOT "/usr/X11R6" -#endif -#ifndef SYSCONFDIR -#define SYSCONFDIR PROJECTROOT "/etc" -#endif -#ifndef DATADIR -#define DATADIR PROJECTROOT "/share" -#endif -#ifndef XCONFENV -#define XCONFENV "XORGCONFIG" -#endif - -#define BAIL_OUT do { \ - free(result); \ - return NULL; \ - } while (0) - -#define CHECK_LENGTH do { \ - if (l > PATH_MAX) { \ - BAIL_OUT; \ - } \ - } while (0) - -#define APPEND_STR(s) do { \ - if (strlen(s) + l > PATH_MAX) { \ - BAIL_OUT; \ - } else { \ - strcpy(result + l, s); \ - l += strlen(s); \ - } \ - } while (0) - -static char * -DoSubstitution(const char *template, const char *cmdline, const char *projroot, - int *cmdlineUsed, int *envUsed, - const char *XConfigFile) -{ - char *result; - int i, l; - static const char *env = NULL; - static char *hostname = NULL; - - if (!template) - return NULL; - - if (cmdlineUsed) - *cmdlineUsed = 0; - if (envUsed) - *envUsed = 0; - - result = malloc(PATH_MAX + 1); - l = 0; - for (i = 0; template[i]; i++) { - if (template[i] != '%') { - result[l++] = template[i]; - CHECK_LENGTH; - } else { - switch (template[++i]) { - case 'A': - if (cmdline && xf86pathIsAbsolute(cmdline)) { - APPEND_STR(cmdline); - if (cmdlineUsed) - *cmdlineUsed = 1; - } else - BAIL_OUT; - break; - case 'R': - if (cmdline && !xf86pathIsAbsolute(cmdline)) { - APPEND_STR(cmdline); - if (cmdlineUsed) - *cmdlineUsed = 1; - } else - BAIL_OUT; - break; - case 'S': - if (cmdline && xf86pathIsSafe(cmdline)) { - APPEND_STR(cmdline); - if (cmdlineUsed) - *cmdlineUsed = 1; - } else - BAIL_OUT; - break; - case 'X': - APPEND_STR(XConfigFile); - break; - case 'H': - if (!hostname) { - if ((hostname = malloc(MAXHOSTNAMELEN + 1))) { - if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { - hostname[MAXHOSTNAMELEN] = '\0'; - } else { - free(hostname); - hostname = NULL; - } - } - } - if (hostname) - APPEND_STR(hostname); - break; - case 'E': - if (!env) - env = getenv(XCONFENV); - if (env && xf86pathIsAbsolute(env)) { - APPEND_STR(env); - if (envUsed) - *envUsed = 1; - } else - BAIL_OUT; - break; - case 'F': - if (!env) - env = getenv(XCONFENV); - if (env && !xf86pathIsAbsolute(env)) { - APPEND_STR(env); - if (envUsed) - *envUsed = 1; - } else - BAIL_OUT; - break; - case 'G': - if (!env) - env = getenv(XCONFENV); - if (env && xf86pathIsSafe(env)) { - APPEND_STR(env); - if (envUsed) - *envUsed = 1; - } else - BAIL_OUT; - break; - case 'P': - if (projroot && xf86pathIsAbsolute(projroot)) - APPEND_STR(projroot); - else - BAIL_OUT; - break; - case 'C': - APPEND_STR(SYSCONFDIR); - break; - case 'D': - APPEND_STR(DATADIR); - break; - case '%': - result[l++] = '%'; - CHECK_LENGTH; - break; - default: - fprintf(stderr, "invalid escape %%%c found in path template\n", - template[i]); - BAIL_OUT; - break; - } - } - } -#ifdef DEBUG - fprintf(stderr, "Converted `%s' to `%s'\n", template, result); -#endif - return result; -} - -/* - * Given some searching parameters, locate and open the xorg config file. - */ -static char * -OpenConfigFile(const char *path, const char *cmdline, const char *projroot, - const char *confname) -{ - char *filepath = NULL; - char *pathcopy; - const char *template; - int cmdlineUsed = 0; - FILE *file = NULL; - - pathcopy = strdup(path); - for (template = strtok(pathcopy, ","); template && !file; - template = strtok(NULL, ",")) { - filepath = DoSubstitution(template, cmdline, projroot, - &cmdlineUsed, NULL, confname); - if (!filepath) - continue; - if (cmdline && !cmdlineUsed) { - free(filepath); - filepath = NULL; - continue; - } - file = fopen(filepath, "r"); - if (!file) { - free(filepath); - filepath = NULL; - } - } - - free(pathcopy); - if (file) { - configFiles[numFiles].file = file; - configFiles[numFiles].path = strdup(filepath); - numFiles++; - } - return filepath; -} - -/* - * Match non-hidden files in the xorg config directory with a .conf - * suffix. This filter is passed to scandir(3). - */ -static int -ConfigFilter(const struct dirent *de) -{ - const char *name = de->d_name; - size_t len; - size_t suflen = strlen(XCONFIGSUFFIX); - - if (!name || name[0] == '.') - return 0; - len = strlen(name); - if(len <= suflen) - return 0; - if (strcmp(&name[len-suflen], XCONFIGSUFFIX) != 0) - return 0; - return 1; -} - -static Bool -AddConfigDirFiles(const char *dirpath, struct dirent **list, int num) -{ - int i; - Bool openedFile = FALSE; - Bool warnOnce = FALSE; - - for (i = 0; i < num; i++) { - char *path; - FILE *file; - - if (numFiles >= CONFIG_MAX_FILES) { - if (!warnOnce) { - ErrorF("Maximum number of configuration " - "files opened\n"); - warnOnce = TRUE; - } - free(list[i]); - continue; - } - - path = malloc(PATH_MAX + 1); - snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, - list[i]->d_name); - free(list[i]); - file = fopen(path, "r"); - if (!file) { - free(path); - continue; - } - openedFile = TRUE; - - configFiles[numFiles].file = file; - configFiles[numFiles].path = path; - numFiles++; - } - - return openedFile; -} - -/* - * Given some searching parameters, locate and open the xorg config - * directory. The directory does not need to contain config files. - */ -static char * -OpenConfigDir(const char *path, const char *cmdline, const char *projroot, - const char *confname) -{ - char *dirpath, *pathcopy; - const char *template; - Bool found = FALSE; - int cmdlineUsed = 0; - - pathcopy = strdup(path); - for (template = strtok(pathcopy, ","); template && !found; - template = strtok(NULL, ",")) { - struct dirent **list = NULL; - int num; - - dirpath = DoSubstitution(template, cmdline, projroot, - &cmdlineUsed, NULL, confname); - if (!dirpath) - continue; - if (cmdline && !cmdlineUsed) { - free(dirpath); - dirpath = NULL; - continue; - } - - /* match files named *.conf */ - num = scandir(dirpath, &list, ConfigFilter, alphasort); - found = AddConfigDirFiles(dirpath, list, num); - if (!found) { - free(dirpath); - dirpath = NULL; - free(list); - } - } - - free(pathcopy); - return dirpath; -} - -/* - * xf86initConfigFiles -- Setup global variables and buffers. - */ -void -xf86initConfigFiles(void) -{ - curFileIndex = 0; - configPos = 0; - configLineNo = 0; - pushToken = LOCK_TOKEN; - - configBuf = malloc(CONFIG_BUF_LEN); - configRBuf = malloc(CONFIG_BUF_LEN); - configBuf[0] = '\0'; /* sanity ... */ -} - -/* - * xf86openConfigFile -- - * - * This function take a config file search path (optional), a command-line - * specified file name (optional) and the ProjectRoot path (optional) and - * locates and opens a config file based on that information. If a - * command-line file name is specified, then this function fails if none - * of the located files. - * - * The return value is a pointer to the actual name of the file that was - * opened. When no file is found, the return value is NULL. - * - * The escape sequences allowed in the search path are defined above. - * - */ - -#ifndef DEFAULT_CONF_PATH -#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" -#endif - -const char * -xf86openConfigFile(const char *path, const char *cmdline, const char *projroot) -{ - if (!path || !path[0]) - path = DEFAULT_CONF_PATH; - if (!projroot || !projroot[0]) - projroot = PROJECTROOT; - - /* Search for a config file */ - configPath = OpenConfigFile(path, cmdline, projroot, XCONFIGFILE); - return configPath; -} - -/* - * xf86openConfigDirFiles -- - * - * This function take a config directory search path (optional), a - * command-line specified directory name (optional) and the ProjectRoot path - * (optional) and locates and opens a config directory based on that - * information. If a command-line name is specified, then this function - * fails if it is not found. - * - * The return value is a pointer to the actual name of the direcoty that was - * opened. When no directory is found, the return value is NULL. - * - * The escape sequences allowed in the search path are defined above. - * - */ -const char * -xf86openConfigDirFiles(const char *path, const char *cmdline, - const char *projroot) -{ - if (!path || !path[0]) - path = DEFAULT_CONF_PATH; - if (!projroot || !projroot[0]) - projroot = PROJECTROOT; - - /* Search for the multiconf directory */ - configDirPath = OpenConfigDir(path, cmdline, projroot, XCONFIGDIR); - return configDirPath; -} - -void -xf86closeConfigFile (void) -{ - int i; - - free (configPath); - configPath = NULL; - free (configDirPath); - configDirPath = NULL; - free (configRBuf); - configRBuf = NULL; - free (configBuf); - configBuf = NULL; - - if (numFiles == 0) { - builtinConfig = NULL; - builtinIndex = 0; - } - for (i = 0; i < numFiles; i++) { - fclose(configFiles[i].file); - configFiles[i].file = NULL; - free(configFiles[i].path); - configFiles[i].path = NULL; - } - numFiles = 0; -} - -void -xf86setBuiltinConfig(const char *config[]) -{ - builtinConfig = config; -} - -void -xf86parseError (char *format,...) -{ - va_list ap; - char *filename = numFiles ? configFiles[curFileIndex].path : - ""; - - ErrorF ("Parse error on line %d of section %s in file %s\n\t", - configLineNo, configSection, filename); - va_start (ap, format); - VErrorF (format, ap); - va_end (ap); - - ErrorF ("\n"); -} - -void -xf86validationError (char *format,...) -{ - va_list ap; - char *filename = numFiles ? configFiles[curFileIndex].path : - ""; - - ErrorF ("Data incomplete in file %s\n\t", filename); - va_start (ap, format); - VErrorF (format, ap); - va_end (ap); - - ErrorF ("\n"); -} - -void -xf86setSection (char *section) -{ - free(configSection); - configSection = strdup(section); -} - -/* - * xf86getToken -- - * Lookup a string if it is actually a token in disguise. - */ -int -xf86getStringToken (xf86ConfigSymTabRec * tab) -{ - return StringToToken (val.str, tab); -} - -static int -StringToToken (char *str, xf86ConfigSymTabRec * tab) -{ - int i; - - for (i = 0; tab[i].token != -1; i++) - { - if (!xf86nameCompare (tab[i].name, str)) - return tab[i].token; - } - return ERROR_TOKEN; -} - - -/* - * Compare two names. The characters '_', ' ', and '\t' are ignored - * in the comparison. - */ -int -xf86nameCompare (const char *s1, const char *s2) -{ - char c1, c2; - - if (!s1 || *s1 == 0) { - if (!s2 || *s2 == 0) - return 0; - else - return 1; - } - - while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') - s1++; - while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') - s2++; - c1 = (isupper (*s1) ? tolower (*s1) : *s1); - c2 = (isupper (*s2) ? tolower (*s2) : *s2); - while (c1 == c2) - { - if (c1 == '\0') - return 0; - s1++; - s2++; - while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') - s1++; - while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') - s2++; - c1 = (isupper (*s1) ? tolower (*s1) : *s1); - c2 = (isupper (*s2) ? tolower (*s2) : *s2); - } - return c1 - c2; -} - -char * -xf86addComment(char *cur, char *add) -{ - char *str; - int len, curlen, iscomment, hasnewline = 0, endnewline; - - if (add == NULL || add[0] == '\0') - return cur; - - if (cur) { - curlen = strlen(cur); - if (curlen) - hasnewline = cur[curlen - 1] == '\n'; - eol_seen = 0; - } - else - curlen = 0; - - str = add; - iscomment = 0; - while (*str) { - if (*str != ' ' && *str != '\t') - break; - ++str; - } - iscomment = (*str == '#'); - - len = strlen(add); - endnewline = add[len - 1] == '\n'; - len += 1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen; - - if ((str = realloc(cur, len + curlen)) == NULL) - return cur; - - cur = str; - - if (eol_seen || (curlen && !hasnewline)) - cur[curlen++] = '\n'; - if (!iscomment) - cur[curlen++] = '#'; - strcpy(cur + curlen, add); - if (!endnewline) - strcat(cur, "\n"); - - return cur; -} - -Bool -xf86getBoolValue(Bool *val, const char *str) -{ - if (!val || !str) - return FALSE; - if (*str == '\0') { - *val = TRUE; - } else { - if (xf86nameCompare(str, "1") == 0) - *val = TRUE; - else if (xf86nameCompare(str, "on") == 0) - *val = TRUE; - else if (xf86nameCompare(str, "true") == 0) - *val = TRUE; - else if (xf86nameCompare(str, "yes") == 0) - *val = TRUE; - else if (xf86nameCompare(str, "0") == 0) - *val = FALSE; - else if (xf86nameCompare(str, "off") == 0) - *val = FALSE; - else if (xf86nameCompare(str, "false") == 0) - *val = FALSE; - else if (xf86nameCompare(str, "no") == 0) - *val = FALSE; - else - return FALSE; - } - return TRUE; -} +/* + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* View/edit this file with tab stops set to 4 */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_POSIX_SOURCE) +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif /* _POSIX_SOURCE */ + +#if !defined(MAXHOSTNAMELEN) +#define MAXHOSTNAMELEN 32 +#endif /* !MAXHOSTNAMELEN */ + +/* For PATH_MAX */ +#include "misc.h" + +#include "Configint.h" +#include "xf86tokens.h" + +#define CONFIG_BUF_LEN 1024 +#define CONFIG_MAX_FILES 64 + +static int StringToToken (char *, xf86ConfigSymTabRec *); + +static struct { + FILE *file; + char *path; +} configFiles[CONFIG_MAX_FILES]; +static const char **builtinConfig = NULL; +static int builtinIndex = 0; +static int configPos = 0; /* current readers position */ +static int configLineNo = 0; /* linenumber */ +static char *configBuf, *configRBuf; /* buffer for lines */ +static char *configPath; /* path to config file */ +static char *configDirPath; /* path to config dir */ +static char *configSection = NULL; /* name of current section being parsed */ +static int numFiles = 0; /* number of config files */ +static int curFileIndex = 0; /* index of current config file */ +static int pushToken = LOCK_TOKEN; +static int eol_seen = 0; /* private state to handle comments */ +LexRec val; + +/* + * xf86getNextLine -- + * + * read from the configFiles FILE stream until we encounter a new + * line; this is effectively just a big wrapper for fgets(3). + * + * xf86getToken() assumes that we will read up to the next + * newline; we need to grow configBuf and configRBuf as needed to + * support that. + */ + +static char* +xf86getNextLine(void) +{ + static int configBufLen = CONFIG_BUF_LEN; + char *tmpConfigBuf, *tmpConfigRBuf; + int c, i, pos = 0, eolFound = 0; + char *ret = NULL; + + /* + * reallocate the string if it was grown last time (i.e., is no + * longer CONFIG_BUF_LEN); we malloc the new strings first, so + * that if either of the mallocs fail, we can fall back on the + * existing buffer allocations + */ + + if (configBufLen != CONFIG_BUF_LEN) { + + tmpConfigBuf = malloc(CONFIG_BUF_LEN); + tmpConfigRBuf = malloc(CONFIG_BUF_LEN); + + if (!tmpConfigBuf || !tmpConfigRBuf) { + + /* + * at least one of the mallocs failed; keep the old buffers + * and free any partial allocations + */ + + free(tmpConfigBuf); + free(tmpConfigRBuf); + + } else { + + /* + * malloc succeeded; free the old buffers and use the new + * buffers + */ + + configBufLen = CONFIG_BUF_LEN; + + free(configBuf); + free(configRBuf); + + configBuf = tmpConfigBuf; + configRBuf = tmpConfigRBuf; + } + } + + /* read in another block of chars */ + + do { + ret = fgets(configBuf + pos, configBufLen - pos - 1, + configFiles[curFileIndex].file); + + if (!ret) { + /* + * if the file doesn't end in a newline, add one + * and trigger another read + */ + if (pos != 0) { + strcpy(&configBuf[pos], "\n"); + ret = configBuf; + } else + break; + } + + /* search for EOL in the new block of chars */ + + for (i = pos; i < (configBufLen - 1); i++) { + c = configBuf[i]; + + if (c == '\0') break; + + if ((c == '\n') || (c == '\r')) { + eolFound = 1; + break; + } + } + + /* + * if we didn't find EOL, then grow the string and + * read in more + */ + + if (!eolFound) { + + tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN); + tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN); + + if (!tmpConfigBuf || !tmpConfigRBuf) { + + /* + * at least one of the reallocations failed; use the + * new allocation that succeeded, but we have to + * fallback to the previous configBufLen size and use + * the string we have, even though we don't have an + * EOL + */ + + if (tmpConfigBuf) configBuf = tmpConfigBuf; + if (tmpConfigRBuf) configRBuf = tmpConfigRBuf; + + break; + + } else { + + /* reallocation succeeded */ + + configBuf = tmpConfigBuf; + configRBuf = tmpConfigRBuf; + pos = i; + configBufLen += CONFIG_BUF_LEN; + } + } + + } while (!eolFound); + + return ret; +} + +/* + * xf86getToken -- + * Read next Token from the config file. Handle the global variable + * pushToken. + */ +int +xf86getToken (xf86ConfigSymTabRec * tab) +{ + int c, i; + + /* + * First check whether pushToken has a different value than LOCK_TOKEN. + * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the + * oth * case the next token must be read from the input. + */ + if (pushToken == EOF_TOKEN) + return EOF_TOKEN; + else if (pushToken == LOCK_TOKEN) + { + /* + * eol_seen is only set for the first token after a newline. + */ + eol_seen = 0; + + c = configBuf[configPos]; + + /* + * Get start of next Token. EOF is handled, + * whitespaces are skipped. + */ + +again: + if (!c) + { + char *ret; + if (numFiles > 0) + ret = xf86getNextLine(); + else { + if (builtinConfig[builtinIndex] == NULL) + ret = NULL; + else { + ret = strncpy(configBuf, builtinConfig[builtinIndex], + CONFIG_BUF_LEN); + builtinIndex++; + } + } + if (ret == NULL) + { + /* + * if necessary, move to the next file and + * read the first line + */ + if (curFileIndex + 1 < numFiles) { + curFileIndex++; + configLineNo = 0; + goto again; + } + else + return pushToken = EOF_TOKEN; + } + configLineNo++; + configPos = 0; + eol_seen = 1; + } + + i = 0; + for (;;) { + c = configBuf[configPos++]; + configRBuf[i++] = c; + switch (c) { + case ' ': + case '\t': + case '\r': + continue; + case '\n': + i = 0; + continue; + } + break; + } + if (c == '\0') + goto again; + + if (c == '#') + { + do + { + configRBuf[i++] = (c = configBuf[configPos++]); + } + while ((c != '\n') && (c != '\r') && (c != '\0')); + configRBuf[i] = '\0'; + /* XXX no private copy. + * Use xf86addComment when setting a comment. + */ + val.str = configRBuf; + return COMMENT; + } + + /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */ + else if ((c == ',') && !isalpha (configBuf[configPos])) + { + return COMMA; + } + else if ((c == '-') && !isalpha (configBuf[configPos])) + { + return DASH; + } + + /* + * Numbers are returned immediately ... + */ + if (isdigit (c)) + { + int base; + + if (c == '0') + if ((configBuf[configPos] == 'x') || + (configBuf[configPos] == 'X')) + { + base = 16; + val.numType = PARSE_HEX; + } + else + { + base = 8; + val.numType = PARSE_OCTAL; + } + else + { + base = 10; + val.numType = PARSE_DECIMAL; + } + + configRBuf[0] = c; + i = 1; + while (isdigit (c = configBuf[configPos++]) || + (c == '.') || (c == 'x') || (c == 'X') || + ((base == 16) && (((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))))) + configRBuf[i++] = c; + configPos--; /* GJA -- one too far */ + configRBuf[i] = '\0'; + val.num = strtoul (configRBuf, NULL, 0); + val.realnum = atof (configRBuf); + return NUMBER; + } + + /* + * All Strings START with a \" ... + */ + else if (c == '\"') + { + i = -1; + do + { + configRBuf[++i] = (c = configBuf[configPos++]); + } + while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0')); + configRBuf[i] = '\0'; + val.str = malloc (strlen (configRBuf) + 1); + strcpy (val.str, configRBuf); /* private copy ! */ + return STRING; + } + + /* + * ... and now we MUST have a valid token. The search is + * handled later along with the pushed tokens. + */ + else + { + configRBuf[0] = c; + i = 0; + do + { + configRBuf[++i] = (c = configBuf[configPos++]); + } + while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (c != '#')); + --configPos; + configRBuf[i] = '\0'; + i = 0; + } + + } + else + { + + /* + * Here we deal with pushed tokens. Reinitialize pushToken again. If + * the pushed token was NUMBER || STRING return them again ... + */ + int temp = pushToken; + pushToken = LOCK_TOKEN; + + if (temp == COMMA || temp == DASH) + return temp; + if (temp == NUMBER || temp == STRING) + return temp; + } + + /* + * Joop, at last we have to lookup the token ... + */ + if (tab) + { + i = 0; + while (tab[i].token != -1) + if (xf86nameCompare (configRBuf, tab[i].name) == 0) + return tab[i].token; + else + i++; + } + + return ERROR_TOKEN; /* Error catcher */ +} + +int +xf86getSubToken (char **comment) +{ + int token; + + for (;;) { + token = xf86getToken(NULL); + if (token == COMMENT) { + if (comment) + *comment = xf86addComment(*comment, val.str); + } + else + return token; + } + /*NOTREACHED*/ +} + +int +xf86getSubTokenWithTab (char **comment, xf86ConfigSymTabRec *tab) +{ + int token; + + for (;;) { + token = xf86getToken(tab); + if (token == COMMENT) { + if (comment) + *comment = xf86addComment(*comment, val.str); + } + else + return token; + } + /*NOTREACHED*/ +} + +void +xf86unGetToken (int token) +{ + pushToken = token; +} + +char * +xf86tokenString (void) +{ + return configRBuf; +} + +int +xf86pathIsAbsolute(const char *path) +{ + if (path && path[0] == '/') + return 1; + return 0; +} + +/* A path is "safe" if it is relative and if it contains no ".." elements. */ +int +xf86pathIsSafe(const char *path) +{ + if (xf86pathIsAbsolute(path)) + return 0; + + /* Compare with ".." */ + if (!strcmp(path, "..")) + return 0; + + /* Look for leading "../" */ + if (!strncmp(path, "../", 3)) + return 0; + + /* Look for trailing "/.." */ + if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/..")) + return 0; + + /* Look for "/../" */ + if (strstr(path, "/../")) + return 0; + + return 1; +} + +/* + * This function substitutes the following escape sequences: + * + * %A cmdline argument as an absolute path (must be absolute to match) + * %R cmdline argument as a relative path + * %S cmdline argument as a "safe" path (relative, and no ".." elements) + * %X default config file name ("xorg.conf") + * %H hostname + * %E config file environment ($XORGCONFIG) as an absolute path + * %F config file environment ($XORGCONFIG) as a relative path + * %G config file environment ($XORGCONFIG) as a safe path + * %P projroot + * %C sysconfdir + * %D datadir + * %% % + */ + +#ifndef XCONFIGFILE +#define XCONFIGFILE "xorg.conf" +#endif +#ifndef XCONFIGDIR +#define XCONFIGDIR "xorg.conf.d" +#endif +#ifndef XCONFIGSUFFIX +#define XCONFIGSUFFIX ".conf" +#endif +#ifndef PROJECTROOT +#define PROJECTROOT "/usr/X11R6" +#endif +#ifndef SYSCONFDIR +#define SYSCONFDIR PROJECTROOT "/etc" +#endif +#ifndef DATADIR +#define DATADIR PROJECTROOT "/share" +#endif +#ifndef XCONFENV +#define XCONFENV "XORGCONFIG" +#endif + +#define BAIL_OUT do { \ + free(result); \ + return NULL; \ + } while (0) + +#define CHECK_LENGTH do { \ + if (l > PATH_MAX) { \ + BAIL_OUT; \ + } \ + } while (0) + +#define APPEND_STR(s) do { \ + if (strlen(s) + l > PATH_MAX) { \ + BAIL_OUT; \ + } else { \ + strcpy(result + l, s); \ + l += strlen(s); \ + } \ + } while (0) + +static char * +DoSubstitution(const char *template, const char *cmdline, const char *projroot, + int *cmdlineUsed, int *envUsed, + const char *XConfigFile) +{ + char *result; + int i, l; + static const char *env = NULL; + static char *hostname = NULL; + + if (!template) + return NULL; + + if (cmdlineUsed) + *cmdlineUsed = 0; + if (envUsed) + *envUsed = 0; + + result = malloc(PATH_MAX + 1); + l = 0; + for (i = 0; template[i]; i++) { + if (template[i] != '%') { + result[l++] = template[i]; + CHECK_LENGTH; + } else { + switch (template[++i]) { + case 'A': + if (cmdline && xf86pathIsAbsolute(cmdline)) { + APPEND_STR(cmdline); + if (cmdlineUsed) + *cmdlineUsed = 1; + } else + BAIL_OUT; + break; + case 'R': + if (cmdline && !xf86pathIsAbsolute(cmdline)) { + APPEND_STR(cmdline); + if (cmdlineUsed) + *cmdlineUsed = 1; + } else + BAIL_OUT; + break; + case 'S': + if (cmdline && xf86pathIsSafe(cmdline)) { + APPEND_STR(cmdline); + if (cmdlineUsed) + *cmdlineUsed = 1; + } else + BAIL_OUT; + break; + case 'X': + APPEND_STR(XConfigFile); + break; + case 'H': + if (!hostname) { + if ((hostname = malloc(MAXHOSTNAMELEN + 1))) { + if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { + hostname[MAXHOSTNAMELEN] = '\0'; + } else { + free(hostname); + hostname = NULL; + } + } + } + if (hostname) + APPEND_STR(hostname); + break; + case 'E': + if (!env) + env = getenv(XCONFENV); + if (env && xf86pathIsAbsolute(env)) { + APPEND_STR(env); + if (envUsed) + *envUsed = 1; + } else + BAIL_OUT; + break; + case 'F': + if (!env) + env = getenv(XCONFENV); + if (env && !xf86pathIsAbsolute(env)) { + APPEND_STR(env); + if (envUsed) + *envUsed = 1; + } else + BAIL_OUT; + break; + case 'G': + if (!env) + env = getenv(XCONFENV); + if (env && xf86pathIsSafe(env)) { + APPEND_STR(env); + if (envUsed) + *envUsed = 1; + } else + BAIL_OUT; + break; + case 'P': + if (projroot && xf86pathIsAbsolute(projroot)) + APPEND_STR(projroot); + else + BAIL_OUT; + break; + case 'C': + APPEND_STR(SYSCONFDIR); + break; + case 'D': + APPEND_STR(DATADIR); + break; + case '%': + result[l++] = '%'; + CHECK_LENGTH; + break; + default: + fprintf(stderr, "invalid escape %%%c found in path template\n", + template[i]); + BAIL_OUT; + break; + } + } + } +#ifdef DEBUG + fprintf(stderr, "Converted `%s' to `%s'\n", template, result); +#endif + return result; +} + +/* + * Given some searching parameters, locate and open the xorg config file. + */ +static char * +OpenConfigFile(const char *path, const char *cmdline, const char *projroot, + const char *confname) +{ + char *filepath = NULL; + char *pathcopy; + const char *template; + int cmdlineUsed = 0; + FILE *file = NULL; + + pathcopy = strdup(path); + for (template = strtok(pathcopy, ","); template && !file; + template = strtok(NULL, ",")) { + filepath = DoSubstitution(template, cmdline, projroot, + &cmdlineUsed, NULL, confname); + if (!filepath) + continue; + if (cmdline && !cmdlineUsed) { + free(filepath); + filepath = NULL; + continue; + } + file = fopen(filepath, "r"); + if (!file) { + free(filepath); + filepath = NULL; + } + } + + free(pathcopy); + if (file) { + configFiles[numFiles].file = file; + configFiles[numFiles].path = strdup(filepath); + numFiles++; + } + return filepath; +} + +/* + * Match non-hidden files in the xorg config directory with a .conf + * suffix. This filter is passed to scandir(3). + */ +static int +ConfigFilter(const struct dirent *de) +{ + const char *name = de->d_name; + size_t len; + size_t suflen = strlen(XCONFIGSUFFIX); + + if (!name || name[0] == '.') + return 0; + len = strlen(name); + if(len <= suflen) + return 0; + if (strcmp(&name[len-suflen], XCONFIGSUFFIX) != 0) + return 0; + return 1; +} + +static Bool +AddConfigDirFiles(const char *dirpath, struct dirent **list, int num) +{ + int i; + Bool openedFile = FALSE; + Bool warnOnce = FALSE; + + for (i = 0; i < num; i++) { + char *path; + FILE *file; + + if (numFiles >= CONFIG_MAX_FILES) { + if (!warnOnce) { + ErrorF("Maximum number of configuration " + "files opened\n"); + warnOnce = TRUE; + } + free(list[i]); + continue; + } + + path = malloc(PATH_MAX + 1); + snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, + list[i]->d_name); + free(list[i]); + file = fopen(path, "r"); + if (!file) { + free(path); + continue; + } + openedFile = TRUE; + + configFiles[numFiles].file = file; + configFiles[numFiles].path = path; + numFiles++; + } + + return openedFile; +} + +/* + * Given some searching parameters, locate and open the xorg config + * directory. The directory does not need to contain config files. + */ +static char * +OpenConfigDir(const char *path, const char *cmdline, const char *projroot, + const char *confname) +{ + char *dirpath, *pathcopy; + const char *template; + Bool found = FALSE; + int cmdlineUsed = 0; + + pathcopy = strdup(path); + for (template = strtok(pathcopy, ","); template && !found; + template = strtok(NULL, ",")) { + struct dirent **list = NULL; + int num; + + dirpath = DoSubstitution(template, cmdline, projroot, + &cmdlineUsed, NULL, confname); + if (!dirpath) + continue; + if (cmdline && !cmdlineUsed) { + free(dirpath); + dirpath = NULL; + continue; + } + + /* match files named *.conf */ + num = scandir(dirpath, &list, ConfigFilter, alphasort); + found = AddConfigDirFiles(dirpath, list, num); + if (!found) { + free(dirpath); + dirpath = NULL; + free(list); + } + } + + free(pathcopy); + return dirpath; +} + +/* + * xf86initConfigFiles -- Setup global variables and buffers. + */ +void +xf86initConfigFiles(void) +{ + curFileIndex = 0; + configPos = 0; + configLineNo = 0; + pushToken = LOCK_TOKEN; + + configBuf = malloc(CONFIG_BUF_LEN); + configRBuf = malloc(CONFIG_BUF_LEN); + configBuf[0] = '\0'; /* sanity ... */ +} + +/* + * xf86openConfigFile -- + * + * This function take a config file search path (optional), a command-line + * specified file name (optional) and the ProjectRoot path (optional) and + * locates and opens a config file based on that information. If a + * command-line file name is specified, then this function fails if none + * of the located files. + * + * The return value is a pointer to the actual name of the file that was + * opened. When no file is found, the return value is NULL. + * + * The escape sequences allowed in the search path are defined above. + * + */ + +#ifndef DEFAULT_CONF_PATH +#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" +#endif + +const char * +xf86openConfigFile(const char *path, const char *cmdline, const char *projroot) +{ + if (!path || !path[0]) + path = DEFAULT_CONF_PATH; + if (!projroot || !projroot[0]) + projroot = PROJECTROOT; + + /* Search for a config file */ + configPath = OpenConfigFile(path, cmdline, projroot, XCONFIGFILE); + return configPath; +} + +/* + * xf86openConfigDirFiles -- + * + * This function take a config directory search path (optional), a + * command-line specified directory name (optional) and the ProjectRoot path + * (optional) and locates and opens a config directory based on that + * information. If a command-line name is specified, then this function + * fails if it is not found. + * + * The return value is a pointer to the actual name of the direcoty that was + * opened. When no directory is found, the return value is NULL. + * + * The escape sequences allowed in the search path are defined above. + * + */ +const char * +xf86openConfigDirFiles(const char *path, const char *cmdline, + const char *projroot) +{ + if (!path || !path[0]) + path = DEFAULT_CONF_PATH; + if (!projroot || !projroot[0]) + projroot = PROJECTROOT; + + /* Search for the multiconf directory */ + configDirPath = OpenConfigDir(path, cmdline, projroot, XCONFIGDIR); + return configDirPath; +} + +void +xf86closeConfigFile (void) +{ + int i; + + free (configPath); + configPath = NULL; + free (configDirPath); + configDirPath = NULL; + free (configRBuf); + configRBuf = NULL; + free (configBuf); + configBuf = NULL; + + if (numFiles == 0) { + builtinConfig = NULL; + builtinIndex = 0; + } + for (i = 0; i < numFiles; i++) { + fclose(configFiles[i].file); + configFiles[i].file = NULL; + free(configFiles[i].path); + configFiles[i].path = NULL; + } + numFiles = 0; +} + +void +xf86setBuiltinConfig(const char *config[]) +{ + builtinConfig = config; +} + +void +xf86parseError (char *format,...) +{ + va_list ap; + char *filename = numFiles ? configFiles[curFileIndex].path : + ""; + + ErrorF ("Parse error on line %d of section %s in file %s\n\t", + configLineNo, configSection, filename); + va_start (ap, format); + VErrorF (format, ap); + va_end (ap); + + ErrorF ("\n"); +} + +void +xf86validationError (char *format,...) +{ + va_list ap; + char *filename = numFiles ? configFiles[curFileIndex].path : + ""; + + ErrorF ("Data incomplete in file %s\n\t", filename); + va_start (ap, format); + VErrorF (format, ap); + va_end (ap); + + ErrorF ("\n"); +} + +void +xf86setSection (char *section) +{ + free(configSection); + configSection = strdup(section); +} + +/* + * xf86getToken -- + * Lookup a string if it is actually a token in disguise. + */ +int +xf86getStringToken (xf86ConfigSymTabRec * tab) +{ + return StringToToken (val.str, tab); +} + +static int +StringToToken (char *str, xf86ConfigSymTabRec * tab) +{ + int i; + + for (i = 0; tab[i].token != -1; i++) + { + if (!xf86nameCompare (tab[i].name, str)) + return tab[i].token; + } + return ERROR_TOKEN; +} + + +/* + * Compare two names. The characters '_', ' ', and '\t' are ignored + * in the comparison. + */ +int +xf86nameCompare (const char *s1, const char *s2) +{ + char c1, c2; + + if (!s1 || *s1 == 0) { + if (!s2 || *s2 == 0) + return 0; + else + return 1; + } + + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper (*s1) ? tolower (*s1) : *s1); + c2 = (isupper (*s2) ? tolower (*s2) : *s2); + while (c1 == c2) + { + if (c1 == '\0') + return 0; + s1++; + s2++; + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper (*s1) ? tolower (*s1) : *s1); + c2 = (isupper (*s2) ? tolower (*s2) : *s2); + } + return c1 - c2; +} + +char * +xf86addComment(char *cur, char *add) +{ + char *str; + int len, curlen, iscomment, hasnewline = 0, insnewline, endnewline; + + if (add == NULL || add[0] == '\0') + return cur; + + if (cur) { + curlen = strlen(cur); + if (curlen) + hasnewline = cur[curlen - 1] == '\n'; + eol_seen = 0; + } + else + curlen = 0; + + str = add; + iscomment = 0; + while (*str) { + if (*str != ' ' && *str != '\t') + break; + ++str; + } + iscomment = (*str == '#'); + + len = strlen(add); + endnewline = add[len - 1] == '\n'; + + insnewline = eol_seen || (curlen && !hasnewline); + if (insnewline) + len++; + if (!iscomment) + len++; + if (!endnewline) + len++; + + /* Allocate + 1 char for '\0' terminator. */ + str = realloc(cur, curlen + len + 1); + if (!str) + return cur; + + cur = str; + + if (insnewline) + cur[curlen++] = '\n'; + if (!iscomment) + cur[curlen++] = '#'; + strcpy(cur + curlen, add); + if (!endnewline) + strcat(cur, "\n"); + + return cur; +} + +Bool +xf86getBoolValue(Bool *val, const char *str) +{ + if (!val || !str) + return FALSE; + if (*str == '\0') { + *val = TRUE; + } else { + if (xf86nameCompare(str, "1") == 0) + *val = TRUE; + else if (xf86nameCompare(str, "on") == 0) + *val = TRUE; + else if (xf86nameCompare(str, "true") == 0) + *val = TRUE; + else if (xf86nameCompare(str, "yes") == 0) + *val = TRUE; + else if (xf86nameCompare(str, "0") == 0) + *val = FALSE; + else if (xf86nameCompare(str, "off") == 0) + *val = FALSE; + else if (xf86nameCompare(str, "false") == 0) + *val = FALSE; + else if (xf86nameCompare(str, "no") == 0) + *val = FALSE; + else + return FALSE; + } + return TRUE; +} -- cgit v1.2.3