diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | cpprules.in | 3 | ||||
-rw-r--r-- | hw/xfree86/common/xf86AutoConfig.c | 3 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Config.c | 19 | ||||
-rw-r--r-- | hw/xfree86/doc/man/xorg.conf.man.pre | 53 | ||||
-rw-r--r-- | hw/xfree86/parser/scan.c | 317 | ||||
-rw-r--r-- | hw/xfree86/parser/xf86Parser.h | 7 | ||||
-rw-r--r-- | hw/xwin/winconfig.c | 21 | ||||
-rw-r--r-- | include/xorg-config.h.in | 3 |
9 files changed, 321 insertions, 107 deletions
diff --git a/configure.ac b/configure.ac index 723c1fddf..b55eaaa35 100644 --- a/configure.ac +++ b/configure.ac @@ -1737,6 +1737,7 @@ if test "x$XORG" = xyes; then dnl these only go in xorg-config.h XF86CONFIGFILE="xorg.conf" + XF86CONFIGDIR="xorg.conf.d" CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" LOGPREFIX="$logdir/Xorg." AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) @@ -1749,6 +1750,7 @@ if test "x$XORG" = xyes; then AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) AC_DEFINE_DIR(__XCONFIGFILE__, XF86CONFIGFILE, [Name of configuration file]) AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file]) + AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) diff --git a/cpprules.in b/cpprules.in index 7fcb9bd6f..7219e361f 100644 --- a/cpprules.in +++ b/cpprules.in @@ -36,7 +36,8 @@ MANDEFS = \ -D__adminmansuffix__=$(ADMIN_MAN_SUFFIX) \ -D__mandir__=$(mandir) \ -D__projectroot__=$(prefix) \ - -D__xconfigfile__=$(__XCONFIGFILE__) -D__xconfigdir__=$(XCONFIGDIR) \ + -D__xconfigfile__=$(__XCONFIGFILE__) \ + -D__xconfigdir__=$(__XCONFIGDIR__) \ -D__xkbdir__=$(XKB_BASE_DIRECTORY) \ -D__modulepath__="$(DEFAULT_MODULE_PATH)" \ -D__xlogfile__=$(XLOGFILE) -D__xservername__=$(XSERVERNAME) diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c index a6199b0e8..1c4595e36 100644 --- a/hw/xfree86/common/xf86AutoConfig.c +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -272,7 +272,8 @@ xf86AutoConfig(void) for (cp = builtinConfig; *cp; cp++) xf86ErrorFVerb(3, "\t%s", *cp); xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n"); - + + xf86initConfigFiles(); xf86setBuiltinConfig(builtinConfig); ret = xf86HandleConfigFile(TRUE); FreeConfig(); diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 5ad5e702d..ffb964386 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -95,6 +95,13 @@ extern DeviceAssocRec mouse_assoc; "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ "%P/lib/X11/%X" #endif +#ifndef CONFIGDIRPATH +#define CONFIGDIRPATH "/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 #ifndef PROJECTROOT #define PROJECTROOT "/usr/X11R6" #endif @@ -2389,7 +2396,7 @@ checkInput(serverLayoutPtr layout, Bool implicit_layout) { ConfigStatus xf86HandleConfigFile(Bool autoconfig) { - const char *filename; + const char *filename, *dirname; char *searchpath; MessageType from = X_DEFAULT; char *scanptr; @@ -2405,7 +2412,9 @@ xf86HandleConfigFile(Bool autoconfig) if (xf86ConfigFile) from = X_CMDLINE; + xf86initConfigFiles(); filename = xf86openConfigFile(searchpath, xf86ConfigFile, PROJECTROOT); + dirname = xf86openConfigDirFiles(CONFIGDIRPATH, NULL, PROJECTROOT); if (filename) { xf86MsgVerb(from, 0, "Using config file: \"%s\"\n", filename); xf86ConfigFile = xnfstrdup(filename); @@ -2413,10 +2422,14 @@ xf86HandleConfigFile(Bool autoconfig) if (xf86ConfigFile) xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n", xf86ConfigFile); - return CONFIG_NOFILE; } + if (dirname) + xf86MsgVerb(X_DEFAULT, 0, "Using config directory: \"%s\"\n", + dirname); + if (!filename && !dirname) + return CONFIG_NOFILE; } - + if ((xf86configptr = xf86readConfigFile ()) == NULL) { xf86Msg(X_ERROR, "Problem parsing the config file\n"); return CONFIG_PARSE_ERROR; diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre index 84be12c8b..749eab068 100644 --- a/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/hw/xfree86/doc/man/xorg.conf.man.pre @@ -2,27 +2,35 @@ .ds q \N'34' .TH __xconfigfile__ __filemansuffix__ __vendorversion__ .SH NAME -__xconfigfile__ \- configuration File for __xservername__ X server +__xconfigfile__ and __xconfigdir__ \- configuration files for +__xservername__ X server .SH INTRODUCTION .B __xservername__ supports several mechanisms for supplying/obtaining configuration and run-time parameters: command line options, environment variables, the -__xconfigfile__ configuration file, auto-detection, and fallback defaults. -When the same information is supplied in more than one way, the highest -precedence mechanism is used. The list of mechanisms is ordered from -highest precedence to lowest. Note that not all parameters can be -supplied via all methods. The available command line options and -environment variables (and some defaults) are described in the Xserver(__appmansuffix__) -and __xservername__(__appmansuffix__) manual pages. Most configuration file parameters, with -their defaults, are described below. Driver and module specific -configuration parameters are described in the relevant driver or module -manual page. +__xconfigfile__ and __xconfigdir__ configuration files, auto-detection, +and fallback defaults. When the same information is supplied in more +than one way, the highest precedence mechanism is used. The list of +mechanisms is ordered from highest precedence to lowest. Note that not +all parameters can be supplied via all methods. The available command +line options and environment variables (and some defaults) are +described in the Xserver(__appmansuffix__) and +__xservername__(__appmansuffix__) manual pages. Most configuration file +parameters, with their defaults, are described below. Driver and module +specific configuration parameters are described in the relevant driver +or module manual page. .SH DESCRIPTION .B __xservername__ uses a configuration file called .I __xconfigfile__ +and files ending in the suffix +.I .conf +from the directory +.I __xconfigdir__ for its initial setup. -This configuration file is searched for in the following places when the +The +.I __xconfigfile__ +configuration file is searched for in the following places when the server is started as a normal user: .PP .RS 4 @@ -93,9 +101,28 @@ directory), and is the machine's hostname as reported by .BR gethostname (__libmansuffix__). .PP +Additional configuration files are searched for in the following +directories: +.PP +.RS 4 +.nf +.I /etc/X11/__xconfigdir__\-4 +.I /etc/X11/__xconfigdir__ +.I /etc/__xconfigdir__ +.IR __projectroot__/etc/X11/__xconfigdir__. <hostname> +.I __projectroot__/etc/X11/__xconfigdir__\-4 +.I __projectroot__/etc/X11/__xconfigdir__ +.IR __projectroot__/lib/X11/__xconfigdir__. <hostname> +.I __projectroot__/lib/X11/__xconfigdir__\-4 +.I __projectroot__/lib/X11/__xconfigdir__ +.fi +.RE +.PP The .I __xconfigfile__ -file is composed of a number of sections which may be present in any order, +and +.I __xconfigdir__ +files are composed of a number of sections which may be present in any order, or omitted to use default configuration values. Each section has the form: .PP diff --git a/hw/xfree86/parser/scan.c b/hw/xfree86/parser/scan.c index d2e8b6d2b..24260e282 100644 --- a/hw/xfree86/parser/scan.c +++ b/hw/xfree86/parser/scan.c @@ -62,8 +62,11 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/types.h> +#include <dirent.h> #include <unistd.h> #include <stdarg.h> +#include <X11/Xdefs.h> #include <X11/Xfuncproto.h> #if defined(_POSIX_SOURCE) @@ -90,17 +93,24 @@ #include "xf86tokens.h" #define CONFIG_BUF_LEN 1024 +#define CONFIG_MAX_FILES 64 static int StringToToken (char *, xf86ConfigSymTabRec *); -static FILE *configFile = NULL; +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; @@ -155,7 +165,7 @@ xf86strToUL (char *str) /* * xf86getNextLine -- * - * read from the configFile FILE stream until we encounter a new + * 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 @@ -213,9 +223,18 @@ xf86getNextLine(void) /* read in another block of chars */ do { - ret = fgets(configBuf + pos, configBufLen - pos - 1, configFile); + ret = fgets(configBuf + pos, configBufLen - pos - 1, + configFiles[curFileIndex].file); - if (!ret) break; + if (!ret) { + /* stop if there are no more files */ + if (++curFileIndex >= numFiles) { + curFileIndex = 0; + break; + } + configLineNo = 0; + continue; + } /* search for EOL in the new block of chars */ @@ -306,7 +325,7 @@ again: if (!c) { char *ret; - if (configFile) + if (numFiles > 0) ret = xf86getNextLine(); else { if (builtinConfig[builtinIndex] == NULL) @@ -575,6 +594,12 @@ xf86pathIsSafe(const char *path) #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 @@ -616,7 +641,8 @@ xf86pathIsSafe(const char *path) static char * DoSubstitution(const char *template, const char *cmdline, const char *projroot, - int *cmdlineUsed, int *envUsed, char *XConfigFile) + int *cmdlineUsed, int *envUsed, + const char *XConfigFile) { char *result; int i, l; @@ -745,7 +771,155 @@ DoSubstitution(const char *template, const char *cmdline, const char *projroot, 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; + } + } + + 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 = strlen(name); + size_t suflen = strlen(XCONFIGSUFFIX); + + if (!name || name[0] == '.' || 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 *projroot, const char *confname) +{ + char *dirpath, *pathcopy; + const char *template; + Bool found = FALSE; + + pathcopy = strdup(path); + for (template = strtok(pathcopy, ","); template && !found; + template = strtok(NULL, ",")) { + struct dirent **list = NULL; + int num; + + if (!(dirpath = DoSubstitution(template, NULL, projroot, + NULL, NULL, confname))) + continue; + /* match files named *.conf */ + num = scandir(dirpath, &list, ConfigFilter, alphasort); + found = AddConfigDirFiles(dirpath, list, num); + if (!found) { + free(dirpath); + dirpath = NULL; + if (list) + free(list); + } + } + + 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 @@ -758,7 +932,7 @@ DoSubstitution(const char *template, const char *cmdline, const char *projroot, * 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 @@ -780,117 +954,90 @@ DoSubstitution(const char *template, const char *cmdline, const char *projroot, const char * xf86openConfigFile(const char *path, const char *cmdline, const char *projroot) { - char *pathcopy; - const char *template; - int cmdlineUsed = 0; - - configFile = NULL; - configPos = 0; /* current readers position */ - configLineNo = 0; /* linenumber */ - pushToken = LOCK_TOKEN; - if (!path || !path[0]) path = DEFAULT_CONF_PATH; - pathcopy = malloc(strlen(path) + 1); - strcpy(pathcopy, path); if (!projroot || !projroot[0]) projroot = PROJECTROOT; - template = strtok(pathcopy, ","); - - /* First, search for a config file. */ - while (template && !configFile) { - if ((configPath = DoSubstitution(template, cmdline, projroot, - &cmdlineUsed, NULL, - XCONFIGFILE))) { - if ((configFile = fopen(configPath, "r")) != 0) { - if (cmdline && !cmdlineUsed) { - fclose(configFile); - configFile = NULL; - } - } - } - if (configPath && !configFile) { - free(configPath); - configPath = NULL; - } - template = strtok(NULL, ","); - } - - /* Then search for fallback */ - if (!configFile) { - strcpy(pathcopy, path); - template = strtok(pathcopy, ","); - - while (template && !configFile) { - if ((configPath = DoSubstitution(template, cmdline, projroot, - &cmdlineUsed, NULL, - XFREE86CFGFILE))) { - if ((configFile = fopen(configPath, "r")) != 0) { - if (cmdline && !cmdlineUsed) { - fclose(configFile); - configFile = NULL; - } - } - } - if (configPath && !configFile) { - free(configPath); - configPath = NULL; - } - template = strtok(NULL, ","); - } - } - - free(pathcopy); - if (!configFile) { - - return NULL; - } + /* Search for a config file or a fallback */ + configPath = OpenConfigFile(path, cmdline, projroot, XCONFIGFILE); + if (!configPath) + configPath = OpenConfigFile(path, cmdline, projroot, + XFREE86CFGFILE); + return configPath; +} - configBuf = malloc (CONFIG_BUF_LEN); - configRBuf = malloc (CONFIG_BUF_LEN); - configBuf[0] = '\0'; /* sanity ... */ +/* + * 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; - return configPath; + /* Search for the multiconf directory */ + configDirPath = OpenConfigDir(path, 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 (configFile) { - fclose (configFile); - configFile = NULL; - } else { + 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; - configPath = strdup("<builtin configuration>"); - configBuf = malloc (CONFIG_BUF_LEN); - configRBuf = malloc (CONFIG_BUF_LEN); - configBuf[0] = '\0'; /* sanity ... */ - } void xf86parseError (char *format,...) { va_list ap; + char *filename = numFiles ? configFiles[curFileIndex].path : + "<builtin configuration>"; ErrorF ("Parse error on line %d of section %s in file %s\n\t", - configLineNo, configSection, configPath); + configLineNo, configSection, filename); va_start (ap, format); VErrorF (format, ap); va_end (ap); @@ -902,8 +1049,10 @@ void xf86validationError (char *format,...) { va_list ap; + char *filename = numFiles ? configFiles[curFileIndex].path : + "<builtin configuration>"; - ErrorF ("Data incomplete in file %s\n\t", configPath); + ErrorF ("Data incomplete in file %s\n\t", filename); va_start (ap, format); VErrorF (format, ap); va_end (ap); diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h index efa1b8553..12bcd6e65 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -456,8 +456,11 @@ xf86ConfigSymTabRec, *xf86ConfigSymTabPtr; /* * prototypes for public functions */ -extern const char *xf86openConfigFile(const char *, const char *, - const char *); +extern void xf86initConfigFiles(void); +extern const char *xf86openConfigFile(const char *path, const char *cmdline, + const char *projroot); +extern const char *xf86openConfigDirFiles(const char *path, const char *cmdline, + const char *projroot); extern void xf86setBuiltinConfig(const char *config[]); extern XF86ConfigPtr xf86readConfigFile(void); extern void xf86closeConfigFile(void); diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c index 3e1908c90..6efd7cae8 100644 --- a/hw/xwin/winconfig.c +++ b/hw/xwin/winconfig.c @@ -50,6 +50,13 @@ "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ "%P/lib/X11/%X" #endif +#ifndef CONFIGDIRPATH +#define CONFIGDIRPATH "/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 XF86ConfigPtr g_xf86configptr = NULL; #endif @@ -109,7 +116,7 @@ Bool winReadConfigfile () { Bool retval = TRUE; - const char *filename; + const char *filename, *dirname; MessageType from = X_DEFAULT; char *xf86ConfigFile = NULL; @@ -120,9 +127,10 @@ winReadConfigfile () } /* Parse config file into data structure */ - + xf86initConfigFiles(); filename = xf86openConfigFile (CONFIGPATH, xf86ConfigFile, PROJECTROOT); - + dirname = xf86openConfigDirFiles (CONFIGDIRPATH, NULL, PROJECTROOT); + /* Hack for backward compatibility */ if (!filename && from == X_DEFAULT) filename = xf86openConfigFile (CONFIGPATH, "XF86Config", PROJECTROOT); @@ -137,6 +145,13 @@ winReadConfigfile () if (xf86ConfigFile) ErrorF (": \"%s\"", xf86ConfigFile); ErrorF ("\n"); + } + if (dirname) + { + winMsg (from, "Using config directory: \"%s\"\n", dirname); + } + if (!filename && !dirname) + { return FALSE; } if ((g_xf86configptr = xf86readConfigFile ()) == NULL) diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in index 9fe7cdef5..8946a6538 100644 --- a/include/xorg-config.h.in +++ b/include/xorg-config.h.in @@ -36,6 +36,9 @@ /* Path to configuration file. */ #undef __XCONFIGFILE__ +/* Name of configuration directory. */ +#undef __XCONFIGDIR__ + /* Path to loadable modules. */ #undef DEFAULT_MODULE_PATH |