[PATCH v3] xfree86: Use xorg.conf.d directory for multiple config files
Peter Hutterer
peter.hutterer at who-t.net
Wed Dec 16 23:00:48 PST 2009
On Wed, Dec 16, 2009 at 10:38:05PM -0800, Dan Nicholson wrote:
> Currently there is a single file, xorg.conf, for configuring the server.
> This works fine most of the time, but it becomes a problem when packages
> or system services need to adjust the configuration. Instead, allow
> multiple configuration files to live in a directory. Typically this will
> be /etc/X11/xorg.conf.d.
>
> Files with a suffix of .conf will be read and added to the server
> configuration after xorg.conf. The server won't fall back to using the
> auto configuration unless there is no config file and there are no files
> in the config directory.
>
> Right now this uses a simpler search template than the config file
> search path by not using the command line or environment variable
> parameters. The matching code was refactored a bit to make this more
> coherent.
>
> Signed-off-by: Dan Nicholson <dbn.lists at gmail.com>
> ---
> This should address Peter's review. Someone with a better knowledge of
> the API should look through xf86Parser.h, though. I doubt most of those
> functions are intended to be used externally.
>
> configure.ac | 2 +
> cpprules.in | 3 +-
> hw/xfree86/common/xf86Config.c | 37 +++--
> hw/xfree86/doc/man/xorg.conf.man.pre | 53 +++++--
> hw/xfree86/parser/scan.c | 310 ++++++++++++++++++++++++---------
> hw/xfree86/parser/xf86Parser.h | 12 +-
> hw/xwin/winconfig.c | 43 ++++-
> include/xorg-config.h.in | 3 +
> 8 files changed, 341 insertions(+), 122 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 6cdef15..950dee0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1720,6 +1720,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])
> @@ -1732,6 +1733,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 7fcb9bd..7219e36 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/xf86Config.c b/hw/xfree86/common/xf86Config.c
> index e1283f9..df70950 100644
> --- a/hw/xfree86/common/xf86Config.c
> +++ b/hw/xfree86/common/xf86Config.c
> @@ -102,6 +102,13 @@ extern DeviceAssocRec mouse_assoc;
> "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
> "%P/lib/X11/%X"
> #endif
> +#ifndef DIR_CONFIGPATH
> +#define DIR_CONFIGPATH "/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
> @@ -2437,7 +2444,7 @@ checkInput(serverLayoutPtr layout, Bool implicit_layout) {
> ConfigStatus
> xf86HandleConfigFile(Bool autoconfig)
> {
> - const char *filename;
> + XF86ConfPathsPtr paths;
> char *searchpath;
> MessageType from = X_DEFAULT;
> char *scanptr;
> @@ -2453,18 +2460,26 @@ xf86HandleConfigFile(Bool autoconfig)
> if (xf86ConfigFile)
> from = X_CMDLINE;
>
> - filename = xf86openConfigFile(searchpath, xf86ConfigFile, PROJECTROOT);
> - if (filename) {
> - xf86MsgVerb(from, 0, "Using config file: \"%s\"\n", filename);
> - xf86ConfigFile = xnfstrdup(filename);
> - } else {
> - if (xf86ConfigFile)
> - xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n",
> - xf86ConfigFile);
> + paths = xf86openConfigFile(searchpath, DIR_CONFIGPATH,
> + xf86ConfigFile, PROJECTROOT);
> + if (paths && (paths->file || paths->dir)) {
> + if (paths->file) {
> + xf86MsgVerb(from, 0, "Using config file: \"%s\"\n",
> + paths->file);
> + xf86ConfigFile = xnfstrdup(paths->file);
> + } else {
> + if (xf86ConfigFile)
> + xf86Msg(X_ERROR,
> + "Unable to locate/open config file: \"%s\"\n",
> + xf86ConfigFile);
> + }
> + if (paths && paths->dir)
> + xf86MsgVerb(X_DEFAULT, 0, "Using config directory: \"%s\"\n",
> + paths->dir);
> + } else
> 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 ace041c..60ce512 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 d2e8b6d..02db351 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,23 @@
> #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 XF86ConfPathsRec configPaths = { NULL }; /* paths to configuration */
> 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 +164,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 +222,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 +324,7 @@ again:
> if (!c)
> {
> char *ret;
> - if (configFile)
> + if (numFiles > 0)
> ret = xf86getNextLine();
> else {
> if (builtinConfig[builtinIndex] == NULL)
> @@ -575,6 +593,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 +640,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,20 +770,154 @@ 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;
> +}
> +
> +/*
> * 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
> + * This function take a config file search path (optional), a config
> + * directory search path (optional), command-line specified file name
> + * (optional) and the ProjectRoot path (optional) and locates and opens
> + * a config file and config directory 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 return value is a pointer to a structure with the the actual name of
> + * the file and directory that were opened. The entries will be NULL if
> + * they are not found.
> *
> * The escape sequences allowed in the search path are defined above.
> - *
> + *
> */
>
> #ifndef DEFAULT_CONF_PATH
> @@ -776,108 +935,85 @@ DoSubstitution(const char *template, const char *cmdline, const char *projroot,
> "%P/lib/X11/%X-%M," \
> "%P/lib/X11/%X"
> #endif
> +#ifndef DEFAULT_DIR_PATH
> +#define DEFAULT_DIR_PATH "/etc/X11/%S," \
> + "%P/etc/X11/%S," \
> + "/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)
> +const XF86ConfPathsPtr
> +xf86openConfigFile(const char *filepath, const char *dirpath,
> + const char *cmdline, const char *projroot)
> {
> - char *pathcopy;
> - const char *template;
> - int cmdlineUsed = 0;
> -
> - configFile = NULL;
> + memset(configFiles, 0, sizeof(configFiles));
> + numFiles = 0;
> + curFileIndex = 0;
> 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 (!filepath || !filepath[0])
> + filepath = DEFAULT_CONF_PATH;
> + if (!dirpath || !dirpath[0])
> + dirpath = DEFAULT_DIR_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 */
> + configPaths.file = OpenConfigFile(filepath, cmdline, projroot,
> + XCONFIGFILE);
> + if (!configPaths.file)
> + configPaths.file = OpenConfigFile(filepath, cmdline, projroot,
> + XFREE86CFGFILE);
> + /* Search for the multiconf directory */
> + configPaths.dir = OpenConfigDir(dirpath, projroot, XCONFIGDIR);
>
> configBuf = malloc (CONFIG_BUF_LEN);
> configRBuf = malloc (CONFIG_BUF_LEN);
> configBuf[0] = '\0'; /* sanity ... */
>
> - return configPath;
> + return &configPaths;
> }
>
> void
> xf86closeConfigFile (void)
> {
> - free (configPath);
> - configPath = NULL;
> + int i;
> +
> + free (configPaths.file);
> + configPaths.file = NULL;
> + free (configPaths.dir);
> + configPaths.dir = 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 ... */
> @@ -888,9 +1024,11 @@ 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 +1040,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 6030800..d00c0ea 100644
> --- a/hw/xfree86/parser/xf86Parser.h
> +++ b/hw/xfree86/parser/xf86Parser.h
> @@ -453,11 +453,19 @@ typedef struct
> }
> xf86ConfigSymTabRec, *xf86ConfigSymTabPtr;
>
> +typedef struct
> +{
> + char *file; /* config file */
> + char *dir; /* multiconf directory */
> +}
> +XF86ConfPathsRec, *XF86ConfPathsPtr;
> +
> /*
> * prototypes for public functions
> */
> -extern _X_EXPORT const char *xf86openConfigFile (const char *, const char *,
> - const char *);
> +extern const XF86ConfPathsPtr
> +xf86openConfigFile(const char *filepath, const char *dirpath,
> + const char *cmdline, const char *projroot);
> extern _X_EXPORT void xf86setBuiltinConfig(const char *config[]);
> extern _X_EXPORT XF86ConfigPtr xf86readConfigFile (void);
> extern _X_EXPORT void xf86closeConfigFile (void);
> diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
> index 3e1908c..51981c4 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,9 @@ Bool
> winReadConfigfile ()
> {
> Bool retval = TRUE;
> + XF86ConfPathsPtr paths;
> const char *filename;
> + const char *dirname;
> MessageType from = X_DEFAULT;
> char *xf86ConfigFile = NULL;
>
> @@ -121,24 +130,38 @@ winReadConfigfile ()
>
> /* Parse config file into data structure */
>
> - filename = xf86openConfigFile (CONFIGPATH, xf86ConfigFile, PROJECTROOT);
> -
> + paths = xf86openConfigFile (CONFIGPATH, CONFIGDIRPATH, xf86ConfigFile,
> + PROJECTROOT);
> +
> /* Hack for backward compatibility */
> - if (!filename && from == X_DEFAULT)
> - filename = xf86openConfigFile (CONFIGPATH, "XF86Config", PROJECTROOT);
> + if (!(paths && paths->file) && from == X_DEFAULT)
> + paths = xf86openConfigFile (CONFIGPATH, CONFIGDIRPATH, "XF86Config",
> + PROJECTROOT);
>
> - if (filename)
> + if (paths && (paths->file || paths->dir))
> {
> - winMsg (from, "Using config file: \"%s\"\n", filename);
> + if (paths && paths->file)
> + {
> + winMsg (from, "Using config file: \"%s\"\n", paths->file);
> + }
> + else
> + {
> + winMsg (X_ERROR, "Unable to locate/open config file");
> + if (xf86ConfigFile)
> + ErrorF (": \"%s\"", xf86ConfigFile);
> + ErrorF ("\n");
> + }
> +
> + if (paths && paths->dir)
> + {
> + winMsg (X_DEFAULT, "Using config directory \"%s\"\n", paths->dir);
> + }
> }
> else
> {
> - winMsg (X_ERROR, "Unable to locate/open config file");
> - if (xf86ConfigFile)
> - ErrorF (": \"%s\"", xf86ConfigFile);
> - ErrorF ("\n");
> return FALSE;
> }
> +
> if ((g_xf86configptr = xf86readConfigFile ()) == NULL)
> {
> winMsg (X_ERROR, "Problem parsing the config file\n");
> diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
> index 794de7a..d28dc0d 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
>
> --
> 1.6.2.5
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
do you want to get this merged now or wait for the input class patches and
all in one go?
Cheers,
Peter
More information about the xorg-devel
mailing list