1/*
2 * Loosely based on code bearing the following copyright:
3 *
4 *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
5 */
6
7/*
8 * Copyright 1992-2003 by The XFree86 Project, Inc.
9 * Copyright 1997 by Metro Link, Inc.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * Except as contained in this notice, the name of the copyright holder(s)
30 * and author(s) shall not be used in advertising or otherwise to promote
31 * the sale, use or other dealings in this Software without prior written
32 * authorization from the copyright holder(s) and author(s).
33 */
34
35/*
36 *
37 * Authors:
38 *	Dirk Hohndel <hohndel@XFree86.Org>
39 *	David Dawes <dawes@XFree86.Org>
40 *      Marc La France <tsi@XFree86.Org>
41 *      Egbert Eich <eich@XFree86.Org>
42 *      ... and others
43 */
44
45#ifdef HAVE_XORG_CONFIG_H
46#include <xorg-config.h>
47#endif
48
49#include <sys/types.h>
50#include <grp.h>
51
52#include "xf86.h"
53#include "xf86Modes.h"
54#include "xf86Parser.h"
55#include "xf86tokens.h"
56#include "xf86Config.h"
57#include "xf86Priv.h"
58#include "xf86_OSlib.h"
59#include "configProcs.h"
60#include "globals.h"
61#include "extension.h"
62#include "xf86pciBus.h"
63#include "xf86Xinput.h"
64#include "loaderProcs.h"
65
66#include "xkbsrv.h"
67#include "picture.h"
68#ifdef DPMSExtension
69#include "dpmsproc.h"
70#endif
71
72/*
73 * These paths define the way the config file search is done.  The escape
74 * sequences are documented in parser/scan.c.
75 */
76#ifndef ALL_CONFIGPATH
77#define ALL_CONFIGPATH	"%A," "%R," \
78			"/etc/X11/%R," "%P/etc/X11/%R," \
79			"%E," "%F," \
80			"/etc/X11/%F," "%P/etc/X11/%F," \
81			"/etc/X11/%X," "/etc/%X," \
82			"%P/etc/X11/%X.%H," \
83			"%P/etc/X11/%X," \
84			"%P/lib/X11/%X.%H," \
85			"%P/lib/X11/%X"
86#endif
87#ifndef RESTRICTED_CONFIGPATH
88#define RESTRICTED_CONFIGPATH	"/etc/X11/%S," "%P/etc/X11/%S," \
89			"/etc/X11/%G," "%P/etc/X11/%G," \
90			"/etc/X11/%X," "/etc/%X," \
91			"%P/etc/X11/%X.%H," \
92			"%P/etc/X11/%X," \
93			"%P/lib/X11/%X.%H," \
94			"%P/lib/X11/%X"
95#endif
96#ifndef ALL_CONFIGDIRPATH
97#define ALL_CONFIGDIRPATH	"%A," "%R," \
98				"/etc/X11/%R," "%C/X11/%R," \
99				"/etc/X11/%X," "%C/X11/%X"
100#endif
101#ifndef RESTRICTED_CONFIGDIRPATH
102#define RESTRICTED_CONFIGDIRPATH	"/etc/X11/%R," "%C/X11/%R," \
103					"/etc/X11/%X," "%C/X11/%X"
104#endif
105#ifndef SYS_CONFIGDIRPATH
106#define SYS_CONFIGDIRPATH	"%D/X11/%X"
107#endif
108#ifndef PROJECTROOT
109#define PROJECTROOT	"/usr/X11R6"
110#endif
111
112static ModuleDefault ModuleDefaults[] = {
113#ifdef GLXEXT
114    {.name = "glx",.toLoad = TRUE,.load_opt = NULL},
115#endif
116#ifdef __CYGWIN__
117    /* load DIX modules used by drivers first */
118    {.name = "fb",.toLoad = TRUE,.load_opt = NULL},
119    {.name = "shadow",.toLoad = TRUE,.load_opt = NULL},
120#endif
121    {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
122};
123
124/* Forward declarations */
125static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen,
126                         int scrnum, MessageType from, Bool auto_gpu_device);
127static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor);
128static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device,
129                         Bool active, Bool gpu);
130static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input,
131                        MessageType from);
132static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display);
133static Bool addDefaultModes(MonPtr monitorp);
134
135static void configDRI(XF86ConfDRIPtr drip);
136static void configExtensions(XF86ConfExtensionsPtr conf_ext);
137
138/*
139 * xf86GetPathElem --
140 *	Extract a single element from the font path string starting at
141 *	pnt.  The font path element will be returned, and pnt will be
142 *	updated to point to the start of the next element, or set to
143 *	NULL if there are no more.
144 */
145static char *
146xf86GetPathElem(char **pnt)
147{
148    char *p1;
149
150    p1 = *pnt;
151    *pnt = index(*pnt, ',');
152    if (*pnt != NULL) {
153        **pnt = '\0';
154        *pnt += 1;
155    }
156    return p1;
157}
158
159/*
160 * xf86ValidateFontPath --
161 *	Validates the user-specified font path.  Each element that
162 *	begins with a '/' is checked to make sure the directory exists.
163 *	If the directory exists, the existence of a file named 'fonts.dir'
164 *	is checked.  If either check fails, an error is printed and the
165 *	element is removed from the font path.
166 */
167
168#define DIR_FILE "/fonts.dir"
169static char *
170xf86ValidateFontPath(char *path)
171{
172    char *next, *tmp_path, *out_pnt, *path_elem, *p1, *dir_elem;
173    struct stat stat_buf;
174    int flag;
175    int dirlen;
176
177    tmp_path = calloc(1, strlen(path) + 1);
178    out_pnt = tmp_path;
179    path_elem = NULL;
180    next = path;
181    while (next != NULL) {
182        path_elem = xf86GetPathElem(&next);
183        if (*path_elem == '/') {
184            dir_elem = xnfcalloc(1, strlen(path_elem) + 1);
185            if ((p1 = strchr(path_elem, ':')) != 0)
186                dirlen = p1 - path_elem;
187            else
188                dirlen = strlen(path_elem);
189            strlcpy(dir_elem, path_elem, dirlen + 1);
190            flag = stat(dir_elem, &stat_buf);
191            if (flag == 0)
192                if (!S_ISDIR(stat_buf.st_mode))
193                    flag = -1;
194            if (flag != 0) {
195                xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n",
196                        dir_elem);
197                xf86ErrorF("\tEntry deleted from font path.\n");
198                free(dir_elem);
199                continue;
200            }
201            else {
202                XNFasprintf(&p1, "%s%s", dir_elem, DIR_FILE);
203                flag = stat(p1, &stat_buf);
204                if (flag == 0)
205                    if (!S_ISREG(stat_buf.st_mode))
206                        flag = -1;
207                free(p1);
208                if (flag != 0) {
209                    xf86Msg(X_WARNING,
210                            "`fonts.dir' not found (or not valid) in \"%s\".\n",
211                            dir_elem);
212                    xf86ErrorF("\tEntry deleted from font path.\n");
213                    xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem);
214                    free(dir_elem);
215                    continue;
216                }
217            }
218            free(dir_elem);
219        }
220
221        /*
222         * Either an OK directory, or a font server name.  So add it to
223         * the path.
224         */
225        if (out_pnt != tmp_path)
226            *out_pnt++ = ',';
227        strcat(out_pnt, path_elem);
228        out_pnt += strlen(path_elem);
229    }
230    return tmp_path;
231}
232
233#define FIND_SUITABLE(pointertype, listhead, ptr)                                            \
234    do {                                                                                     \
235        pointertype _l, _p;                                                                  \
236                                                                                             \
237        for (_l = (listhead), _p = NULL; !_p && _l; _l = (pointertype)_l->list.next) {       \
238            if (!_l->match_seat || (SeatId && xf86nameCompare(_l->match_seat, SeatId) == 0)) \
239                _p = _l;                                                                     \
240        }                                                                                    \
241                                                                                             \
242        (ptr) = _p;                                                                          \
243    } while(0)
244
245/*
246 * use the datastructure that the parser provides and pick out the parts
247 * that we need at this point
248 */
249const char **
250xf86ModulelistFromConfig(void ***optlist)
251{
252    int count = 0, i = 0;
253    const char **modulearray;
254
255    const char *ignore[] = { "GLcore", "speedo", "bitmap", "drm",
256        "freetype", "type1",
257        NULL
258    };
259    void **optarray;
260    XF86LoadPtr modp;
261    Bool found;
262
263    /*
264     * make sure the config file has been parsed and that we have a
265     * ModulePath set; if no ModulePath was given, use the default
266     * ModulePath
267     */
268    if (xf86configptr == NULL) {
269        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
270        return NULL;
271    }
272
273    if (xf86configptr->conf_modules) {
274        /* Walk the disable list and let people know what we've parsed to
275         * not be loaded
276         */
277        modp = xf86configptr->conf_modules->mod_disable_lst;
278        while (modp) {
279            xf86Msg(X_WARNING,
280                    "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n",
281                    modp->load_name);
282            modp = (XF86LoadPtr) modp->list.next;
283        }
284        /*
285         * Walk the default settings table. For each module listed to be
286         * loaded, make sure it's in the mod_load_lst. If it's not, make
287         * sure it's not in the mod_no_load_lst. If it's not disabled,
288         * append it to mod_load_lst
289         */
290        for (i = 0; ModuleDefaults[i].name != NULL; i++) {
291            if (ModuleDefaults[i].toLoad == FALSE) {
292                xf86Msg(X_WARNING,
293                        "\"%s\" is not to be loaded by default. Skipping.\n",
294                        ModuleDefaults[i].name);
295                continue;
296            }
297            found = FALSE;
298            modp = xf86configptr->conf_modules->mod_load_lst;
299            while (modp) {
300                if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
301                    xf86Msg(X_INFO,
302                            "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n",
303                            ModuleDefaults[i].name);
304                    found = TRUE;
305                    break;
306                }
307                modp = (XF86LoadPtr) modp->list.next;
308            }
309            if (found == FALSE) {
310                modp = xf86configptr->conf_modules->mod_disable_lst;
311                while (modp) {
312                    if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
313                        xf86Msg(X_INFO,
314                                "\"%s\" will be loaded even though the default is to disable it.\n",
315                                ModuleDefaults[i].name);
316                        found = TRUE;
317                        break;
318                    }
319                    modp = (XF86LoadPtr) modp->list.next;
320                }
321            }
322            if (found == FALSE) {
323                XF86LoadPtr ptr = (XF86LoadPtr) xf86configptr->conf_modules;
324
325                xf86addNewLoadDirective(ptr, ModuleDefaults[i].name,
326                                        XF86_LOAD_MODULE,
327                                        ModuleDefaults[i].load_opt);
328                xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n",
329                        ModuleDefaults[i].name);
330            }
331        }
332    }
333    else {
334        xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec));
335        for (i = 0; ModuleDefaults[i].name != NULL; i++) {
336            if (ModuleDefaults[i].toLoad == TRUE) {
337                XF86LoadPtr ptr = (XF86LoadPtr) xf86configptr->conf_modules;
338
339                xf86addNewLoadDirective(ptr, ModuleDefaults[i].name,
340                                        XF86_LOAD_MODULE,
341                                        ModuleDefaults[i].load_opt);
342            }
343        }
344    }
345
346    /*
347     * Walk the list of modules in the "Module" section to determine how
348     * many we have.
349     */
350    modp = xf86configptr->conf_modules->mod_load_lst;
351    while (modp) {
352        for (i = 0; ignore[i]; i++) {
353            if (strcmp(modp->load_name, ignore[i]) == 0)
354                modp->ignore = 1;
355        }
356        if (!modp->ignore)
357            count++;
358        modp = (XF86LoadPtr) modp->list.next;
359    }
360
361    /*
362     * allocate the memory and walk the list again to fill in the pointers
363     */
364    modulearray = xnfallocarray(count + 1, sizeof(char *));
365    optarray = xnfallocarray(count + 1, sizeof(void *));
366    count = 0;
367    if (xf86configptr->conf_modules) {
368        modp = xf86configptr->conf_modules->mod_load_lst;
369        while (modp) {
370            if (!modp->ignore) {
371                modulearray[count] = modp->load_name;
372                optarray[count] = modp->load_opt;
373                count++;
374            }
375            modp = (XF86LoadPtr) modp->list.next;
376        }
377    }
378    modulearray[count] = NULL;
379    optarray[count] = NULL;
380    if (optlist)
381        *optlist = optarray;
382    else
383        free(optarray);
384    return modulearray;
385}
386
387const char **
388xf86DriverlistFromConfig(void)
389{
390    int count = 0;
391    int j, k;
392    const char **modulearray;
393    screenLayoutPtr slp;
394
395    /*
396     * make sure the config file has been parsed and that we have a
397     * ModulePath set; if no ModulePath was given, use the default
398     * ModulePath
399     */
400    if (xf86configptr == NULL) {
401        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
402        return NULL;
403    }
404
405    /*
406     * Walk the list of driver lines in active "Device" sections to
407     * determine now many implicitly loaded modules there are.
408     *
409     */
410    if (xf86ConfigLayout.screens) {
411        slp = xf86ConfigLayout.screens;
412        while (slp->screen) {
413            count++;
414            count += slp->screen->num_gpu_devices;
415            slp++;
416        }
417    }
418
419    /*
420     * Handle the set of inactive "Device" sections.
421     */
422    j = 0;
423    while (xf86ConfigLayout.inactives[j++].identifier)
424        count++;
425
426    if (count == 0)
427        return NULL;
428
429    /*
430     * allocate the memory and walk the list again to fill in the pointers
431     */
432    modulearray = xnfallocarray(count + 1, sizeof(char *));
433    count = 0;
434    slp = xf86ConfigLayout.screens;
435    while (slp->screen) {
436        modulearray[count] = slp->screen->device->driver;
437        count++;
438        for (k = 0; k < slp->screen->num_gpu_devices; k++) {
439            modulearray[count] = slp->screen->gpu_devices[k]->driver;
440            count++;
441        }
442        slp++;
443    }
444
445    j = 0;
446
447    while (xf86ConfigLayout.inactives[j].identifier)
448        modulearray[count++] = xf86ConfigLayout.inactives[j++].driver;
449
450    modulearray[count] = NULL;
451
452    /* Remove duplicates */
453    for (count = 0; modulearray[count] != NULL; count++) {
454        int i;
455
456        for (i = 0; i < count; i++)
457            if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
458                modulearray[count] = "";
459                break;
460            }
461    }
462    return modulearray;
463}
464
465const char **
466xf86InputDriverlistFromConfig(void)
467{
468    int count = 0;
469    const char **modulearray;
470    InputInfoPtr *idp;
471
472    /*
473     * make sure the config file has been parsed and that we have a
474     * ModulePath set; if no ModulePath was given, use the default
475     * ModulePath
476     */
477    if (xf86configptr == NULL) {
478        xf86Msg(X_ERROR, "Cannot access global config data structure\n");
479        return NULL;
480    }
481
482    /*
483     * Walk the list of driver lines in active "InputDevice" sections to
484     * determine now many implicitly loaded modules there are.
485     */
486    if (xf86ConfigLayout.inputs) {
487        idp = xf86ConfigLayout.inputs;
488        while (*idp) {
489            count++;
490            idp++;
491        }
492    }
493
494    if (count == 0)
495        return NULL;
496
497    /*
498     * allocate the memory and walk the list again to fill in the pointers
499     */
500    modulearray = xnfallocarray(count + 1, sizeof(char *));
501    count = 0;
502    idp = xf86ConfigLayout.inputs;
503    while (idp && *idp) {
504        modulearray[count] = (*idp)->driver;
505        count++;
506        idp++;
507    }
508    modulearray[count] = NULL;
509
510    /* Remove duplicates */
511    for (count = 0; modulearray[count] != NULL; count++) {
512        int i;
513
514        for (i = 0; i < count; i++)
515            if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
516                modulearray[count] = "";
517                break;
518            }
519    }
520    return modulearray;
521}
522
523static void
524configFiles(XF86ConfFilesPtr fileconf)
525{
526    MessageType pathFrom;
527    Bool must_copy;
528    int size, countDirs;
529    char *temp_path, *log_buf, *start, *end;
530
531    /* FontPath */
532    must_copy = TRUE;
533
534    temp_path = defaultFontPath ? (char *) defaultFontPath : (char *) "";
535    if (xf86fpFlag)
536        pathFrom = X_CMDLINE;
537    else if (fileconf && fileconf->file_fontpath) {
538        pathFrom = X_CONFIG;
539        if (xf86Info.useDefaultFontPath) {
540            char *new_font_path;
541            if (asprintf(&new_font_path, "%s%s%s", fileconf->file_fontpath,
542                         *temp_path ? "," : "", temp_path) == -1)
543                new_font_path = NULL;
544            else
545                must_copy = FALSE;
546            defaultFontPath = new_font_path;
547        }
548        else
549            defaultFontPath = fileconf->file_fontpath;
550    }
551    else
552        pathFrom = X_DEFAULT;
553    temp_path = defaultFontPath ? (char *) defaultFontPath : (char *) "";
554
555    /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */
556    temp_path = must_copy ? xnfstrdup(defaultFontPath) : (char *) defaultFontPath;
557    defaultFontPath = xf86ValidateFontPath(temp_path);
558    free(temp_path);
559
560    /* make fontpath more readable in the logfiles */
561    countDirs = 1;
562    temp_path = (char *) defaultFontPath;
563    while ((temp_path = index(temp_path, ',')) != NULL) {
564        countDirs++;
565        temp_path++;
566    }
567
568    log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1);
569    temp_path = log_buf;
570    start = (char *) defaultFontPath;
571    while ((end = index(start, ',')) != NULL) {
572        size = (end - start) + 1;
573        *(temp_path++) = '\t';
574        strncpy(temp_path, start, size);
575        temp_path += size;
576        *(temp_path++) = '\n';
577        start += size;
578    }
579    /* copy last entry */
580    *(temp_path++) = '\t';
581    strcpy(temp_path, start);
582    xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf);
583    free(log_buf);
584
585    /* ModulePath */
586
587    if (fileconf) {
588        if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) {
589            xf86ModulePath = fileconf->file_modulepath;
590            xf86ModPathFrom = X_CONFIG;
591        }
592    }
593
594    xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath);
595
596    if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) {
597        XkbBaseDirectory = fileconf->file_xkbdir;
598        xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n",
599                XkbBaseDirectory);
600    }
601#if 0
602    /* LogFile */
603    /*
604     * XXX The problem with this is that the log file is already open.
605     * One option might be to copy the exiting contents to the new location.
606     * and re-open it.  The down side is that the default location would
607     * already have been overwritten.  Another option would be to start with
608     * unique temporary location, then copy it once the correct name is known.
609     * A problem with this is what happens if the server exits before that
610     * happens.
611     */
612    if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) {
613        xf86LogFile = fileconf->file_logfile;
614        xf86LogFileFrom = X_CONFIG;
615    }
616#endif
617
618    return;
619}
620
621typedef enum {
622    FLAG_NOTRAPSIGNALS,
623    FLAG_DONTVTSWITCH,
624    FLAG_DONTZAP,
625    FLAG_DONTZOOM,
626    FLAG_DISABLEVIDMODE,
627    FLAG_ALLOWNONLOCAL,
628    FLAG_ALLOWMOUSEOPENFAIL,
629    FLAG_SAVER_BLANKTIME,
630    FLAG_DPMS_STANDBYTIME,
631    FLAG_DPMS_SUSPENDTIME,
632    FLAG_DPMS_OFFTIME,
633    FLAG_NOPM,
634    FLAG_XINERAMA,
635    FLAG_LOG,
636    FLAG_RENDER_COLORMAP_MODE,
637    FLAG_IGNORE_ABI,
638    FLAG_ALLOW_EMPTY_INPUT,
639    FLAG_USE_DEFAULT_FONT_PATH,
640    FLAG_AUTO_ADD_DEVICES,
641    FLAG_AUTO_ENABLE_DEVICES,
642    FLAG_GLX_VISUALS,
643    FLAG_DRI2,
644    FLAG_USE_SIGIO,
645    FLAG_AUTO_ADD_GPU,
646    FLAG_MAX_CLIENTS,
647    FLAG_IGLX,
648    FLAG_DEBUG,
649} FlagValues;
650
651/**
652 * NOTE: the last value for each entry is NOT the default. It is set to TRUE
653 * if the parser found the option in the config file.
654 */
655static OptionInfoRec FlagOptions[] = {
656    {FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN,
657     {0}, FALSE},
658    {FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN,
659     {0}, FALSE},
660    {FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN,
661     {0}, FALSE},
662    {FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN,
663     {0}, FALSE},
664    {FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN,
665     {0}, FALSE},
666    {FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN,
667     {0}, FALSE},
668    {FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN,
669     {0}, FALSE},
670    {FLAG_SAVER_BLANKTIME, "BlankTime", OPTV_INTEGER,
671     {0}, FALSE},
672    {FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER,
673     {0}, FALSE},
674    {FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER,
675     {0}, FALSE},
676    {FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER,
677     {0}, FALSE},
678    {FLAG_NOPM, "NoPM", OPTV_BOOLEAN,
679     {0}, FALSE},
680    {FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN,
681     {0}, FALSE},
682    {FLAG_LOG, "Log", OPTV_STRING,
683     {0}, FALSE},
684    {FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING,
685     {0}, FALSE},
686    {FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN,
687     {0}, FALSE},
688    {FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN,
689     {0}, FALSE},
690    {FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN,
691     {0}, FALSE},
692    {FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN,
693     {0}, FALSE},
694    {FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING,
695     {0}, FALSE},
696    {FLAG_DRI2, "DRI2", OPTV_BOOLEAN,
697     {0}, FALSE},
698    {FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN,
699     {0}, FALSE},
700    {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
701     {0}, FALSE},
702    {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
703     {0}, FALSE },
704    {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN,
705     {0}, FALSE},
706    {FLAG_DEBUG, "Debug", OPTV_STRING,
707     {0}, FALSE},
708    {-1, NULL, OPTV_NONE,
709     {0}, FALSE},
710};
711
712static void
713configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
714{
715    XF86OptionPtr optp, tmp;
716    int i;
717    Bool value;
718    MessageType from;
719    const char *s;
720    XkbRMLVOSet set;
721    const char *rules;
722
723    /*
724     * Merge the ServerLayout and ServerFlags options.  The former have
725     * precedence over the latter.
726     */
727    optp = NULL;
728    if (flagsconf && flagsconf->flg_option_lst)
729        optp = xf86optionListDup(flagsconf->flg_option_lst);
730    if (layoutopts) {
731        tmp = xf86optionListDup(layoutopts);
732        if (optp)
733            optp = xf86optionListMerge(optp, tmp);
734        else
735            optp = tmp;
736    }
737
738    xf86ProcessOptions(-1, optp, FlagOptions);
739
740    xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals);
741    xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch);
742    xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap);
743    xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom);
744
745    xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI);
746    if (xf86Info.ignoreABI) {
747        xf86Msg(X_CONFIG, "Ignoring ABI Version\n");
748    }
749
750    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) {
751        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES,
752                          &xf86Info.autoAddDevices);
753        from = X_CONFIG;
754    }
755    else {
756        from = X_DEFAULT;
757    }
758    xf86Msg(from, "%sutomatically adding devices\n",
759            xf86Info.autoAddDevices ? "A" : "Not a");
760
761    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) {
762        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES,
763                          &xf86Info.autoEnableDevices);
764        from = X_CONFIG;
765    }
766    else {
767        from = X_DEFAULT;
768    }
769    xf86Msg(from, "%sutomatically enabling devices\n",
770            xf86Info.autoEnableDevices ? "A" : "Not a");
771
772    if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_GPU)) {
773        xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_GPU,
774                          &xf86Info.autoAddGPU);
775        from = X_CONFIG;
776    }
777    else {
778        from = X_DEFAULT;
779    }
780    xf86Msg(from, "%sutomatically adding GPU devices\n",
781            xf86Info.autoAddGPU ? "A" : "Not a");
782    /*
783     * Set things up based on the config file information.  Some of these
784     * settings may be overridden later when the command line options are
785     * checked.
786     */
787#ifdef XF86VIDMODE
788    if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value))
789        xf86Info.vidModeEnabled = !value;
790    if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value))
791        xf86Info.vidModeAllowNonLocal = value;
792#endif
793
794    if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value))
795        xf86Info.allowMouseOpenFail = value;
796
797    xf86Info.pmFlag = TRUE;
798    if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value))
799        xf86Info.pmFlag = !value;
800    {
801        if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) {
802            if (!xf86NameCmp(s, "flush")) {
803                xf86Msg(X_CONFIG, "Flushing logfile enabled\n");
804                LogSetParameter(XLOG_FLUSH, TRUE);
805            }
806            else if (!xf86NameCmp(s, "sync")) {
807                xf86Msg(X_CONFIG, "Syncing logfile enabled\n");
808                LogSetParameter(XLOG_FLUSH, TRUE);
809                LogSetParameter(XLOG_SYNC, TRUE);
810            }
811            else {
812                xf86Msg(X_WARNING, "Unknown Log option\n");
813            }
814        }
815    }
816
817    {
818        if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))) {
819            int policy = PictureParseCmapPolicy(s);
820
821            if (policy == PictureCmapPolicyInvalid)
822                xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s);
823            else {
824                xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s);
825                PictureCmapPolicy = policy;
826            }
827        }
828    }
829
830#ifdef GLXEXT
831    xf86Info.glxVisuals = XF86_GlxVisualsTypical;
832    xf86Info.glxVisualsFrom = X_DEFAULT;
833    if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) {
834        if (!xf86NameCmp(s, "minimal")) {
835            xf86Info.glxVisuals = XF86_GlxVisualsMinimal;
836        }
837        else if (!xf86NameCmp(s, "typical")) {
838            xf86Info.glxVisuals = XF86_GlxVisualsTypical;
839        }
840        else if (!xf86NameCmp(s, "all")) {
841            xf86Info.glxVisuals = XF86_GlxVisualsAll;
842        }
843        else {
844            xf86Msg(X_WARNING, "Unknown GlxVisuals option\n");
845        }
846    }
847
848    if (xf86Info.iglxFrom != X_CMDLINE) {
849        if (xf86GetOptValBool(FlagOptions, FLAG_IGLX, &value)) {
850            enableIndirectGLX = value;
851            xf86Info.iglxFrom = X_CONFIG;
852        }
853    }
854#endif
855
856    xf86Info.debug = xf86GetOptValString(FlagOptions, FLAG_DEBUG);
857
858    /* if we're not hotplugging, force some input devices to exist */
859    xf86Info.forceInputDevices = !(xf86Info.autoAddDevices &&
860                                   xf86Info.autoEnableDevices);
861
862    /* when forcing input devices, we use kbd. otherwise evdev, so use the
863     * evdev rules set. */
864#if defined(__linux__)
865    if (!xf86Info.forceInputDevices)
866        rules = "evdev";
867    else
868#endif
869        rules = "base";
870
871    /* Xkb default options. */
872    XkbInitRules(&set, rules, "pc105", "us", NULL, NULL);
873    XkbSetRulesDflts(&set);
874    XkbFreeRMLVOSet(&set, FALSE);
875
876    xf86Info.useDefaultFontPath = TRUE;
877    if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) {
878        xf86Info.useDefaultFontPath = value;
879    }
880
881/* Make sure that timers don't overflow CARD32's after multiplying */
882#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN)
883
884    i = -1;
885    xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i);
886    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
887        ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN;
888    else if (i != -1)
889        ErrorF("BlankTime value %d outside legal range of 0 - %d minutes\n",
890               i, MAX_TIME_IN_MIN);
891
892#ifdef DPMSExtension
893    i = -1;
894    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i);
895    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
896        DPMSStandbyTime = i * MILLI_PER_MIN;
897    else if (i != -1)
898        ErrorF("StandbyTime value %d outside legal range of 0 - %d minutes\n",
899               i, MAX_TIME_IN_MIN);
900    i = -1;
901    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i);
902    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
903        DPMSSuspendTime = i * MILLI_PER_MIN;
904    else if (i != -1)
905        ErrorF("SuspendTime value %d outside legal range of 0 - %d minutes\n",
906               i, MAX_TIME_IN_MIN);
907    i = -1;
908    xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i);
909    if ((i >= 0) && (i < MAX_TIME_IN_MIN))
910        DPMSOffTime = i * MILLI_PER_MIN;
911    else if (i != -1)
912        ErrorF("OffTime value %d outside legal range of 0 - %d minutes\n",
913               i, MAX_TIME_IN_MIN);
914#endif
915
916#ifdef PANORAMIX
917    from = X_DEFAULT;
918    if (!noPanoramiXExtension)
919        from = X_CMDLINE;
920    else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) {
921        noPanoramiXExtension = !value;
922        from = X_CONFIG;
923    }
924    if (!noPanoramiXExtension)
925        xf86Msg(from, "Xinerama: enabled\n");
926#endif
927
928#ifdef DRI2
929    xf86Info.dri2 = FALSE;
930    xf86Info.dri2From = X_DEFAULT;
931    if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) {
932        xf86Info.dri2 = value;
933        xf86Info.dri2From = X_CONFIG;
934    }
935#endif
936
937    from = X_DEFAULT;
938    if (LimitClients != LIMITCLIENTS)
939	from = X_CMDLINE;
940    i = -1;
941    if (xf86GetOptValInteger(FlagOptions, FLAG_MAX_CLIENTS, &i)) {
942        if (Ones(i) != 1 || i < 64 || i > 2048) {
943	    ErrorF("MaxClients must be one of 64, 128, 256, 512, 1024, or 2048\n");
944        } else {
945            from = X_CONFIG;
946            LimitClients = i;
947        }
948    }
949    xf86Msg(from, "Max clients allowed: %i, resource mask: 0x%x\n",
950	    LimitClients, RESOURCE_ID_MASK);
951}
952
953Bool
954xf86DRI2Enabled(void)
955{
956    return xf86Info.dri2;
957}
958
959/**
960 * Search for the pInfo in the null-terminated list given and remove (and
961 * free) it if present. All other devices are moved forward.
962 */
963static void
964freeDevice(InputInfoPtr * list, InputInfoPtr pInfo)
965{
966    InputInfoPtr *devs;
967
968    for (devs = list; devs && *devs; devs++) {
969        if (*devs == pInfo) {
970            free(*devs);
971            for (; devs && *devs; devs++)
972                devs[0] = devs[1];
973            break;
974        }
975    }
976}
977
978/**
979 * Append pInfo to the null-terminated list, allocating space as necessary.
980 * pInfo is used as the last element.
981 */
982static InputInfoPtr *
983addDevice(InputInfoPtr * list, InputInfoPtr pInfo)
984{
985    InputInfoPtr *devs;
986    int count = 1;
987
988    for (devs = list; devs && *devs; devs++)
989        count++;
990
991    list = xnfreallocarray(list, count + 1, sizeof(InputInfoPtr));
992    list[count] = NULL;
993
994    list[count - 1] = pInfo;
995    return list;
996}
997
998/*
999 * Locate the core input devices.  These can be specified/located in
1000 * the following ways, in order of priority:
1001 *
1002 *  1. The InputDevices named by the -pointer and -keyboard command line
1003 *     options.
1004 *  2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by
1005 *     the active ServerLayout.
1006 *  3. The first InputDevices marked as "CorePointer" and "CoreKeyboard".
1007 *  4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse
1008 *     driver (mouse, synaptics, evdev, vmmouse, void)
1009 *  5. Default devices with an empty (default) configuration.  These defaults
1010 *     will reference the 'mouse' and 'keyboard' drivers.
1011 */
1012
1013static Bool
1014checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
1015{
1016    InputInfoPtr corePointer = NULL, coreKeyboard = NULL;
1017    Bool foundPointer = FALSE, foundKeyboard = FALSE;
1018    const char *pointerMsg = NULL, *keyboardMsg = NULL;
1019    InputInfoPtr *devs,         /* iterator */
1020     indp;
1021    InputInfoPtr Pointer, Keyboard;
1022    XF86ConfInputPtr confInput;
1023    XF86ConfInputRec defPtr, defKbd;
1024    MessageType from = X_DEFAULT;
1025
1026    const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse",
1027        "void", NULL
1028    };
1029
1030    /*
1031     * First check if a core pointer or core keyboard have been specified
1032     * in the active ServerLayout.  If more than one is specified for either,
1033     * remove the core attribute from the later ones.
1034     */
1035    for (devs = servlayoutp->inputs; devs && *devs; devs++) {
1036        indp = *devs;
1037        if (indp->options &&
1038            xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) {
1039            if (!corePointer) {
1040                corePointer = indp;
1041            }
1042        }
1043        if (indp->options &&
1044            xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) {
1045            if (!coreKeyboard) {
1046                coreKeyboard = indp;
1047            }
1048        }
1049    }
1050
1051    confInput = NULL;
1052
1053    /* 1. Check for the -pointer command line option. */
1054    if (xf86PointerName) {
1055        confInput = xf86findInput(xf86PointerName,
1056                                  xf86configptr->conf_input_lst);
1057        if (!confInput) {
1058            xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
1059                    xf86PointerName);
1060            return FALSE;
1061        }
1062        from = X_CMDLINE;
1063        /*
1064         * If one was already specified in the ServerLayout, it needs to be
1065         * removed.
1066         */
1067        if (corePointer) {
1068            freeDevice(servlayoutp->inputs, corePointer);
1069            corePointer = NULL;
1070        }
1071        foundPointer = TRUE;
1072    }
1073
1074    /* 2. ServerLayout-specified core pointer. */
1075    if (corePointer) {
1076        foundPointer = TRUE;
1077        from = X_CONFIG;
1078    }
1079
1080    /* 3. First core pointer device. */
1081    if (!foundPointer && (xf86Info.forceInputDevices || implicitLayout)) {
1082        XF86ConfInputPtr p;
1083
1084        for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
1085            if (p->inp_option_lst &&
1086                xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) {
1087                confInput = p;
1088                foundPointer = TRUE;
1089                from = X_DEFAULT;
1090                pointerMsg = "first core pointer device";
1091                break;
1092            }
1093        }
1094    }
1095
1096    /* 4. First pointer with an allowed mouse driver. */
1097    if (!foundPointer && xf86Info.forceInputDevices) {
1098        const char **driver = mousedrivers;
1099
1100        confInput = xf86findInput(CONF_IMPLICIT_POINTER,
1101                                  xf86configptr->conf_input_lst);
1102        while (*driver && !confInput) {
1103            confInput = xf86findInputByDriver(*driver,
1104                                              xf86configptr->conf_input_lst);
1105            driver++;
1106        }
1107        if (confInput) {
1108            foundPointer = TRUE;
1109            from = X_DEFAULT;
1110            pointerMsg = "first mouse device";
1111        }
1112    }
1113
1114    /* 5. Built-in default. */
1115    if (!foundPointer && xf86Info.forceInputDevices) {
1116        memset(&defPtr, 0, sizeof(defPtr));
1117        defPtr.inp_identifier = strdup("<default pointer>");
1118        defPtr.inp_driver = strdup("mouse");
1119        confInput = &defPtr;
1120        foundPointer = TRUE;
1121        from = X_DEFAULT;
1122        pointerMsg = "default mouse configuration";
1123    }
1124
1125    /* Add the core pointer device to the layout, and set it to Core. */
1126    if (foundPointer && confInput) {
1127        Pointer = xf86AllocateInput();
1128        if (Pointer)
1129            foundPointer = configInput(Pointer, confInput, from);
1130        if (foundPointer) {
1131            Pointer->options = xf86AddNewOption(Pointer->options,
1132                                                "CorePointer", "on");
1133            Pointer->options = xf86AddNewOption(Pointer->options,
1134                                                "driver",
1135                                                confInput->inp_driver);
1136            Pointer->options =
1137                xf86AddNewOption(Pointer->options, "identifier",
1138                                 confInput->inp_identifier);
1139            servlayoutp->inputs = addDevice(servlayoutp->inputs, Pointer);
1140        }
1141    }
1142
1143    if (!foundPointer && xf86Info.forceInputDevices) {
1144        /* This shouldn't happen. */
1145        xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n");
1146        xf86DeleteInput(Pointer, 0);
1147        return FALSE;
1148    }
1149
1150    confInput = NULL;
1151
1152    /* 1. Check for the -keyboard command line option. */
1153    if (xf86KeyboardName) {
1154        confInput = xf86findInput(xf86KeyboardName,
1155                                  xf86configptr->conf_input_lst);
1156        if (!confInput) {
1157            xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
1158                    xf86KeyboardName);
1159            return FALSE;
1160        }
1161        from = X_CMDLINE;
1162        /*
1163         * If one was already specified in the ServerLayout, it needs to be
1164         * removed.
1165         */
1166        if (coreKeyboard) {
1167            freeDevice(servlayoutp->inputs, coreKeyboard);
1168            coreKeyboard = NULL;
1169        }
1170        foundKeyboard = TRUE;
1171    }
1172
1173    /* 2. ServerLayout-specified core keyboard. */
1174    if (coreKeyboard) {
1175        foundKeyboard = TRUE;
1176        from = X_CONFIG;
1177    }
1178
1179    /* 3. First core keyboard device. */
1180    if (!foundKeyboard && (xf86Info.forceInputDevices || implicitLayout)) {
1181        XF86ConfInputPtr p;
1182
1183        for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
1184            if (p->inp_option_lst &&
1185                xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) {
1186                confInput = p;
1187                foundKeyboard = TRUE;
1188                from = X_DEFAULT;
1189                keyboardMsg = "first core keyboard device";
1190                break;
1191            }
1192        }
1193    }
1194
1195    /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */
1196    if (!foundKeyboard && xf86Info.forceInputDevices) {
1197        confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD,
1198                                  xf86configptr->conf_input_lst);
1199        if (!confInput) {
1200            confInput = xf86findInputByDriver("kbd",
1201                                              xf86configptr->conf_input_lst);
1202        }
1203        if (confInput) {
1204            foundKeyboard = TRUE;
1205            from = X_DEFAULT;
1206            keyboardMsg = "first keyboard device";
1207        }
1208    }
1209
1210    /* 5. Built-in default. */
1211    if (!foundKeyboard && xf86Info.forceInputDevices) {
1212        memset(&defKbd, 0, sizeof(defKbd));
1213        defKbd.inp_identifier = strdup("<default keyboard>");
1214        defKbd.inp_driver = strdup("kbd");
1215        confInput = &defKbd;
1216        foundKeyboard = TRUE;
1217        keyboardMsg = "default keyboard configuration";
1218        from = X_DEFAULT;
1219    }
1220
1221    /* Add the core keyboard device to the layout, and set it to Core. */
1222    if (foundKeyboard && confInput) {
1223        Keyboard = xf86AllocateInput();
1224        if (Keyboard)
1225            foundKeyboard = configInput(Keyboard, confInput, from);
1226        if (foundKeyboard) {
1227            Keyboard->options = xf86AddNewOption(Keyboard->options,
1228                                                 "CoreKeyboard", "on");
1229            Keyboard->options = xf86AddNewOption(Keyboard->options,
1230                                                 "driver",
1231                                                 confInput->inp_driver);
1232            Keyboard->options =
1233                xf86AddNewOption(Keyboard->options, "identifier",
1234                                 confInput->inp_identifier);
1235            servlayoutp->inputs = addDevice(servlayoutp->inputs, Keyboard);
1236        }
1237    }
1238
1239    if (!foundKeyboard && xf86Info.forceInputDevices) {
1240        /* This shouldn't happen. */
1241        xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n");
1242        xf86DeleteInput(Keyboard, 0);
1243        return FALSE;
1244    }
1245
1246    if (pointerMsg) {
1247        if (implicitLayout)
1248            xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
1249                    pointerMsg);
1250        else
1251            xf86Msg(X_DEFAULT, "The core pointer device wasn't specified "
1252                    "explicitly in the layout.\n"
1253                    "\tUsing the %s.\n", pointerMsg);
1254    }
1255
1256    if (keyboardMsg) {
1257        if (implicitLayout)
1258            xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
1259                    keyboardMsg);
1260        else
1261            xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified "
1262                    "explicitly in the layout.\n"
1263                    "\tUsing the %s.\n", keyboardMsg);
1264    }
1265
1266    if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) {
1267#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
1268        const char *config_backend;
1269
1270#if defined(CONFIG_HAL)
1271        config_backend = "HAL";
1272#elif defined(CONFIG_UDEV)
1273        config_backend = "udev";
1274#else
1275        config_backend = "wscons";
1276#endif
1277        xf86Msg(X_INFO, "The server relies on %s to provide the list of "
1278                "input devices.\n\tIf no devices become available, "
1279                "reconfigure %s or disable AutoAddDevices.\n",
1280                config_backend, config_backend);
1281#else
1282        xf86Msg(X_WARNING, "Hotplugging requested but the server was "
1283                "compiled without a config backend. "
1284                "No input devices were configured, the server "
1285                "will start without any input devices.\n");
1286#endif
1287    }
1288
1289    return TRUE;
1290}
1291
1292typedef enum {
1293    LAYOUT_ISOLATEDEVICE,
1294    LAYOUT_SINGLECARD
1295} LayoutValues;
1296
1297static OptionInfoRec LayoutOptions[] = {
1298    {LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING,
1299     {0}, FALSE},
1300    {LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN,
1301     {0}, FALSE},
1302    {-1, NULL, OPTV_NONE,
1303     {0}, FALSE},
1304};
1305
1306static Bool
1307configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp)
1308{
1309    XF86ConfInputrefPtr irp;
1310    InputInfoPtr *indp;
1311    int count = 0;
1312
1313    /*
1314     * Count the number of input devices.
1315     */
1316    irp = layout->lay_input_lst;
1317    while (irp) {
1318        count++;
1319        irp = (XF86ConfInputrefPtr) irp->list.next;
1320    }
1321    DebugF("Found %d input devices in the layout section %s\n",
1322           count, layout->lay_identifier);
1323    indp = xnfcalloc((count + 1), sizeof(InputInfoPtr));
1324    indp[count] = NULL;
1325    irp = layout->lay_input_lst;
1326    count = 0;
1327    while (irp) {
1328        indp[count] = xf86AllocateInput();
1329        if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) {
1330            do {
1331                free(indp[count]);
1332            } while (count--);
1333            free(indp);
1334            return FALSE;
1335        }
1336        indp[count]->options = xf86OptionListMerge(indp[count]->options,
1337                                                   irp->iref_option_lst);
1338        count++;
1339        irp = (XF86ConfInputrefPtr) irp->list.next;
1340    }
1341    servlayoutp->inputs = indp;
1342
1343    return TRUE;
1344}
1345
1346/*
1347 * figure out which layout is active, which screens are used in that layout,
1348 * which drivers and monitors are used in these screens
1349 */
1350static Bool
1351configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
1352             char *default_layout)
1353{
1354    XF86ConfAdjacencyPtr adjp;
1355    XF86ConfInactivePtr idp;
1356    int saved_count, count = 0;
1357    int scrnum;
1358    XF86ConfLayoutPtr l;
1359    MessageType from;
1360    screenLayoutPtr slp;
1361    GDevPtr gdp;
1362    int i = 0, j;
1363
1364    if (!servlayoutp)
1365        return FALSE;
1366
1367    /*
1368     * which layout section is the active one?
1369     *
1370     * If there is a -layout command line option, use that one, otherwise
1371     * pick the first one.
1372     */
1373    from = X_DEFAULT;
1374    if (xf86LayoutName != NULL)
1375        from = X_CMDLINE;
1376    else if (default_layout) {
1377        xf86LayoutName = default_layout;
1378        from = X_CONFIG;
1379    }
1380    if (xf86LayoutName != NULL) {
1381        if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) {
1382            xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n",
1383                    xf86LayoutName);
1384            return FALSE;
1385        }
1386        conf_layout = l;
1387    }
1388    xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier);
1389    adjp = conf_layout->lay_adjacency_lst;
1390
1391    /*
1392     * we know that each screen is referenced exactly once on the left side
1393     * of a layout statement in the Layout section. So to allocate the right
1394     * size for the array we do a quick walk of the list to figure out how
1395     * many sections we have
1396     */
1397    while (adjp) {
1398        count++;
1399        adjp = (XF86ConfAdjacencyPtr) adjp->list.next;
1400    }
1401
1402    DebugF("Found %d screens in the layout section %s",
1403           count, conf_layout->lay_identifier);
1404    if (!count)                 /* alloc enough storage even if no screen is specified */
1405        count = 1;
1406
1407    slp = xnfcalloc((count + 1), sizeof(screenLayoutRec));
1408    slp[count].screen = NULL;
1409    /*
1410     * now that we have storage, loop over the list again and fill in our
1411     * data structure; at this point we do not fill in the adjacency
1412     * information as it is not clear if we need it at all
1413     */
1414    adjp = conf_layout->lay_adjacency_lst;
1415    count = 0;
1416    while (adjp) {
1417        slp[count].screen = xnfcalloc(1, sizeof(confScreenRec));
1418        if (adjp->adj_scrnum < 0)
1419            scrnum = count;
1420        else
1421            scrnum = adjp->adj_scrnum;
1422        if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum,
1423                          X_CONFIG, (scrnum == 0 && !adjp->list.next))) {
1424            do {
1425                free(slp[count].screen);
1426            } while (count--);
1427            free(slp);
1428            return FALSE;
1429        }
1430        slp[count].x = adjp->adj_x;
1431        slp[count].y = adjp->adj_y;
1432        slp[count].refname = adjp->adj_refscreen;
1433        switch (adjp->adj_where) {
1434        case CONF_ADJ_OBSOLETE:
1435            slp[count].where = PosObsolete;
1436            slp[count].topname = adjp->adj_top_str;
1437            slp[count].bottomname = adjp->adj_bottom_str;
1438            slp[count].leftname = adjp->adj_left_str;
1439            slp[count].rightname = adjp->adj_right_str;
1440            break;
1441        case CONF_ADJ_ABSOLUTE:
1442            slp[count].where = PosAbsolute;
1443            break;
1444        case CONF_ADJ_RIGHTOF:
1445            slp[count].where = PosRightOf;
1446            break;
1447        case CONF_ADJ_LEFTOF:
1448            slp[count].where = PosLeftOf;
1449            break;
1450        case CONF_ADJ_ABOVE:
1451            slp[count].where = PosAbove;
1452            break;
1453        case CONF_ADJ_BELOW:
1454            slp[count].where = PosBelow;
1455            break;
1456        case CONF_ADJ_RELATIVE:
1457            slp[count].where = PosRelative;
1458            break;
1459        }
1460        count++;
1461        adjp = (XF86ConfAdjacencyPtr) adjp->list.next;
1462    }
1463
1464    /* No screen was specified in the layout. take the first one from the
1465     * config file, or - if it is NULL - configScreen autogenerates one for
1466     * us */
1467    if (!count) {
1468        XF86ConfScreenPtr screen;
1469
1470        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
1471        slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
1472        if (!configScreen(slp[0].screen, screen,
1473                          0, X_CONFIG, TRUE)) {
1474            free(slp[0].screen);
1475            free(slp);
1476            return FALSE;
1477        }
1478    }
1479
1480    /* XXX Need to tie down the upper left screen. */
1481
1482    /* Fill in the refscreen and top/bottom/left/right values */
1483    for (i = 0; i < count; i++) {
1484        for (j = 0; j < count; j++) {
1485            if (slp[i].refname &&
1486                strcmp(slp[i].refname, slp[j].screen->id) == 0) {
1487                slp[i].refscreen = slp[j].screen;
1488            }
1489            if (slp[i].topname &&
1490                strcmp(slp[i].topname, slp[j].screen->id) == 0) {
1491                slp[i].top = slp[j].screen;
1492            }
1493            if (slp[i].bottomname &&
1494                strcmp(slp[i].bottomname, slp[j].screen->id) == 0) {
1495                slp[i].bottom = slp[j].screen;
1496            }
1497            if (slp[i].leftname &&
1498                strcmp(slp[i].leftname, slp[j].screen->id) == 0) {
1499                slp[i].left = slp[j].screen;
1500            }
1501            if (slp[i].rightname &&
1502                strcmp(slp[i].rightname, slp[j].screen->id) == 0) {
1503                slp[i].right = slp[j].screen;
1504            }
1505        }
1506        if (slp[i].where != PosObsolete
1507            && slp[i].where != PosAbsolute && !slp[i].refscreen) {
1508            xf86Msg(X_ERROR, "Screen %s doesn't exist: deleting placement\n",
1509                    slp[i].refname);
1510            slp[i].where = PosAbsolute;
1511            slp[i].x = 0;
1512            slp[i].y = 0;
1513        }
1514    }
1515
1516    if (!count)
1517        saved_count = 1;
1518    else
1519        saved_count = count;
1520    /*
1521     * Count the number of inactive devices.
1522     */
1523    count = 0;
1524    idp = conf_layout->lay_inactive_lst;
1525    while (idp) {
1526        count++;
1527        idp = (XF86ConfInactivePtr) idp->list.next;
1528    }
1529    DebugF("Found %d inactive devices in the layout section %s\n",
1530           count, conf_layout->lay_identifier);
1531    gdp = xnfallocarray(count + 1, sizeof(GDevRec));
1532    gdp[count].identifier = NULL;
1533    idp = conf_layout->lay_inactive_lst;
1534    count = 0;
1535    while (idp) {
1536        if (!configDevice(&gdp[count], idp->inactive_device, FALSE, FALSE))
1537            goto bail;
1538        count++;
1539        idp = (XF86ConfInactivePtr) idp->list.next;
1540    }
1541
1542    if (!configInputDevices(conf_layout, servlayoutp))
1543        goto bail;
1544
1545    servlayoutp->id = conf_layout->lay_identifier;
1546    servlayoutp->screens = slp;
1547    servlayoutp->inactives = gdp;
1548    servlayoutp->options = conf_layout->lay_option_lst;
1549    from = X_DEFAULT;
1550
1551    return TRUE;
1552
1553 bail:
1554    do {
1555        free(slp[saved_count].screen);
1556    } while (saved_count--);
1557    free(slp);
1558    free(gdp);
1559    return FALSE;
1560}
1561
1562/*
1563 * No layout section, so find the first Screen section and set that up as
1564 * the only active screen.
1565 */
1566static Bool
1567configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen,
1568                    XF86ConfigPtr conf_ptr)
1569{
1570    MessageType from;
1571    XF86ConfScreenPtr s;
1572    screenLayoutPtr slp;
1573    InputInfoPtr *indp;
1574    XF86ConfLayoutRec layout;
1575
1576    if (!servlayoutp)
1577        return FALSE;
1578
1579    /*
1580     * which screen section is the active one?
1581     *
1582     * If there is a -screen option, use that one, otherwise use the first
1583     * one.
1584     */
1585
1586    from = X_CONFIG;
1587    if (xf86ScreenName != NULL) {
1588        if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) {
1589            xf86Msg(X_ERROR, "No Screen section called \"%s\"\n",
1590                    xf86ScreenName);
1591            return FALSE;
1592        }
1593        conf_screen = s;
1594        from = X_CMDLINE;
1595    }
1596
1597    /* We have exactly one screen */
1598
1599    slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec));
1600    slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
1601    slp[1].screen = NULL;
1602    if (!configScreen(slp[0].screen, conf_screen, 0, from, TRUE)) {
1603        free(slp);
1604        return FALSE;
1605    }
1606    servlayoutp->id = "(implicit)";
1607    servlayoutp->screens = slp;
1608    servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec));
1609    servlayoutp->options = NULL;
1610
1611    memset(&layout, 0, sizeof(layout));
1612    layout.lay_identifier = servlayoutp->id;
1613    if (xf86layoutAddInputDevices(conf_ptr, &layout) > 0) {
1614        if (!configInputDevices(&layout, servlayoutp))
1615            return FALSE;
1616        from = X_DEFAULT;
1617    }
1618    else {
1619        /* Set up an empty input device list, then look for some core devices. */
1620        indp = xnfalloc(sizeof(InputInfoPtr));
1621        *indp = NULL;
1622        servlayoutp->inputs = indp;
1623    }
1624
1625    return TRUE;
1626}
1627
1628static Bool
1629configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor)
1630{
1631    int count = 0;
1632    XF86ConfVideoPortPtr conf_port;
1633
1634    xf86Msg(X_CONFIG, "|   |-->VideoAdaptor \"%s\"\n",
1635            conf_adaptor->va_identifier);
1636    adaptor->identifier = conf_adaptor->va_identifier;
1637    adaptor->options = conf_adaptor->va_option_lst;
1638    if (conf_adaptor->va_busid || conf_adaptor->va_driver) {
1639        xf86Msg(X_CONFIG, "|   | Unsupported device type, skipping entry\n");
1640        return FALSE;
1641    }
1642
1643    /*
1644     * figure out how many videoport subsections there are and fill them in
1645     */
1646    conf_port = conf_adaptor->va_port_lst;
1647    while (conf_port) {
1648        count++;
1649        conf_port = (XF86ConfVideoPortPtr) conf_port->list.next;
1650    }
1651    adaptor->ports = xnfallocarray(count, sizeof(confXvPortRec));
1652    adaptor->numports = count;
1653    count = 0;
1654    conf_port = conf_adaptor->va_port_lst;
1655    while (conf_port) {
1656        adaptor->ports[count].identifier = conf_port->vp_identifier;
1657        adaptor->ports[count].options = conf_port->vp_option_lst;
1658        count++;
1659        conf_port = (XF86ConfVideoPortPtr) conf_port->list.next;
1660    }
1661
1662    return TRUE;
1663}
1664
1665static Bool
1666configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
1667             MessageType from, Bool auto_gpu_device)
1668{
1669    int count = 0;
1670    XF86ConfDisplayPtr dispptr;
1671    XF86ConfAdaptorLinkPtr conf_adaptor;
1672    Bool defaultMonitor = FALSE;
1673    XF86ConfScreenRec local_conf_screen;
1674    int i;
1675
1676    if (!conf_screen) {
1677        memset(&local_conf_screen, 0, sizeof(local_conf_screen));
1678        conf_screen = &local_conf_screen;
1679        conf_screen->scrn_identifier = "Default Screen Section";
1680        xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n");
1681    }
1682
1683    xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier,
1684            scrnum);
1685    /*
1686     * now we fill in the elements of the screen
1687     */
1688    screenp->id = conf_screen->scrn_identifier;
1689    screenp->screennum = scrnum;
1690    screenp->defaultdepth = conf_screen->scrn_defaultdepth;
1691    screenp->defaultbpp = conf_screen->scrn_defaultbpp;
1692    screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp;
1693    screenp->monitor = xnfcalloc(1, sizeof(MonRec));
1694    /* If no monitor is specified, create a default one. */
1695    if (!conf_screen->scrn_monitor) {
1696        XF86ConfMonitorRec defMon;
1697
1698        memset(&defMon, 0, sizeof(defMon));
1699        defMon.mon_identifier = "<default monitor>";
1700        if (!configMonitor(screenp->monitor, &defMon))
1701            return FALSE;
1702        defaultMonitor = TRUE;
1703    }
1704    else {
1705        if (!configMonitor(screenp->monitor, conf_screen->scrn_monitor))
1706            return FALSE;
1707    }
1708    /* Configure the device. If there isn't one configured, attach to the
1709     * first inactive one that we can configure. If there's none that work,
1710     * set it to NULL so that the section can be autoconfigured later */
1711    screenp->device = xnfcalloc(1, sizeof(GDevRec));
1712    if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) {
1713        FIND_SUITABLE (XF86ConfDevicePtr, xf86configptr->conf_device_lst, conf_screen->scrn_device);
1714        xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n"
1715                "\tUsing the first device section listed.\n", screenp->id);
1716    }
1717    if (configDevice(screenp->device, conf_screen->scrn_device, TRUE, FALSE)) {
1718        screenp->device->myScreenSection = screenp;
1719    }
1720    else {
1721        screenp->device = NULL;
1722    }
1723
1724    if (auto_gpu_device && conf_screen->num_gpu_devices == 0 &&
1725        xf86configptr->conf_device_lst) {
1726        XF86ConfDevicePtr sdevice = xf86configptr->conf_device_lst->list.next;
1727
1728        for (i = 0; i < MAX_GPUDEVICES; i++) {
1729            if (!sdevice)
1730                break;
1731
1732            FIND_SUITABLE (XF86ConfDevicePtr, sdevice, conf_screen->scrn_gpu_devices[i]);
1733            if (!conf_screen->scrn_gpu_devices[i])
1734                break;
1735            screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec));
1736            if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) {
1737                screenp->gpu_devices[i]->myScreenSection = screenp;
1738            }
1739            sdevice = conf_screen->scrn_gpu_devices[i]->list.next;
1740        }
1741        screenp->num_gpu_devices = i;
1742
1743    } else {
1744        for (i = 0; i < conf_screen->num_gpu_devices; i++) {
1745            screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec));
1746            if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) {
1747                screenp->gpu_devices[i]->myScreenSection = screenp;
1748            }
1749        }
1750        screenp->num_gpu_devices = conf_screen->num_gpu_devices;
1751    }
1752
1753    screenp->options = conf_screen->scrn_option_lst;
1754
1755    /*
1756     * figure out how many display subsections there are and fill them in
1757     */
1758    dispptr = conf_screen->scrn_display_lst;
1759    while (dispptr) {
1760        count++;
1761        dispptr = (XF86ConfDisplayPtr) dispptr->list.next;
1762    }
1763    screenp->displays = xnfallocarray(count, sizeof(DispPtr));
1764    screenp->numdisplays = count;
1765
1766    for (count = 0, dispptr = conf_screen->scrn_display_lst;
1767         dispptr;
1768         dispptr = (XF86ConfDisplayPtr) dispptr->list.next, count++) {
1769
1770        /* Allocate individual Display records */
1771        screenp->displays[count] = xnfcalloc(1, sizeof(DispRec));
1772
1773        /* Fill in the default Virtual size, if any */
1774        if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) {
1775            screenp->displays[count]->virtualX = conf_screen->scrn_virtualX;
1776            screenp->displays[count]->virtualY = conf_screen->scrn_virtualY;
1777        }
1778
1779        /* Now do the per-Display Virtual sizes */
1780        configDisplay(screenp->displays[count], dispptr);
1781    }
1782
1783    /*
1784     * figure out how many videoadaptor references there are and fill them in
1785     */
1786    count = 0;
1787    conf_adaptor = conf_screen->scrn_adaptor_lst;
1788    while (conf_adaptor) {
1789        count++;
1790        conf_adaptor = (XF86ConfAdaptorLinkPtr) conf_adaptor->list.next;
1791    }
1792    screenp->xvadaptors = xnfallocarray(count, sizeof(confXvAdaptorRec));
1793    screenp->numxvadaptors = 0;
1794    conf_adaptor = conf_screen->scrn_adaptor_lst;
1795    while (conf_adaptor) {
1796        if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]),
1797                            conf_adaptor->al_adaptor))
1798            screenp->numxvadaptors++;
1799        conf_adaptor = (XF86ConfAdaptorLinkPtr) conf_adaptor->list.next;
1800    }
1801
1802    if (defaultMonitor) {
1803        xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n"
1804                "\tUsing a default monitor configuration.\n", screenp->id);
1805    }
1806    return TRUE;
1807}
1808
1809typedef enum {
1810    MON_REDUCEDBLANKING,
1811    MON_MAX_PIX_CLOCK,
1812} MonitorValues;
1813
1814static OptionInfoRec MonitorOptions[] = {
1815    {MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN,
1816     {0}, FALSE},
1817    {MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ,
1818     {0}, FALSE},
1819    {-1, NULL, OPTV_NONE,
1820     {0}, FALSE},
1821};
1822
1823static Bool
1824configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor)
1825{
1826    int count;
1827    DisplayModePtr mode, last = NULL;
1828    XF86ConfModeLinePtr cmodep;
1829    XF86ConfModesPtr modes;
1830    XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst;
1831    Gamma zeros = { 0.0, 0.0, 0.0 };
1832    float badgamma = 0.0;
1833    double maxPixClock;
1834
1835    xf86Msg(X_CONFIG, "|   |-->Monitor \"%s\"\n", conf_monitor->mon_identifier);
1836    monitorp->id = conf_monitor->mon_identifier;
1837    monitorp->vendor = conf_monitor->mon_vendor;
1838    monitorp->model = conf_monitor->mon_modelname;
1839    monitorp->Modes = NULL;
1840    monitorp->Last = NULL;
1841    monitorp->gamma = zeros;
1842    monitorp->widthmm = conf_monitor->mon_width;
1843    monitorp->heightmm = conf_monitor->mon_height;
1844    monitorp->reducedblanking = FALSE;
1845    monitorp->maxPixClock = 0;
1846    monitorp->options = conf_monitor->mon_option_lst;
1847
1848    /*
1849     * fill in the monitor structure
1850     */
1851    for (count = 0;
1852         count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; count++) {
1853        monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi;
1854        monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo;
1855    }
1856    monitorp->nHsync = count;
1857    for (count = 0;
1858         count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH;
1859         count++) {
1860        monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi;
1861        monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo;
1862    }
1863    monitorp->nVrefresh = count;
1864
1865    /*
1866     * first we collect the mode lines from the UseModes directive
1867     */
1868    while (modeslnk) {
1869        modes = xf86findModes(modeslnk->ml_modes_str,
1870                              xf86configptr->conf_modes_lst);
1871        modeslnk->ml_modes = modes;
1872
1873        /* now add the modes found in the modes
1874           section to the list of modes for this
1875           monitor unless it has been added before
1876           because we are reusing the same section
1877           for another screen */
1878        if (xf86itemNotSublist((GenericListPtr) conf_monitor->mon_modeline_lst,
1879                               (GenericListPtr) modes->mon_modeline_lst)) {
1880            conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr)
1881                xf86addListItem((GenericListPtr) conf_monitor->mon_modeline_lst,
1882                                (GenericListPtr) modes->mon_modeline_lst);
1883        }
1884        modeslnk = modeslnk->list.next;
1885    }
1886
1887    /*
1888     * we need to hook in the mode lines now
1889     * here both data structures use lists, only our internal one
1890     * is double linked
1891     */
1892    cmodep = conf_monitor->mon_modeline_lst;
1893    while (cmodep) {
1894        mode = xnfcalloc(1, sizeof(DisplayModeRec));
1895        mode->type = 0;
1896        mode->Clock = cmodep->ml_clock;
1897        mode->HDisplay = cmodep->ml_hdisplay;
1898        mode->HSyncStart = cmodep->ml_hsyncstart;
1899        mode->HSyncEnd = cmodep->ml_hsyncend;
1900        mode->HTotal = cmodep->ml_htotal;
1901        mode->VDisplay = cmodep->ml_vdisplay;
1902        mode->VSyncStart = cmodep->ml_vsyncstart;
1903        mode->VSyncEnd = cmodep->ml_vsyncend;
1904        mode->VTotal = cmodep->ml_vtotal;
1905        mode->Flags = cmodep->ml_flags;
1906        mode->HSkew = cmodep->ml_hskew;
1907        mode->VScan = cmodep->ml_vscan;
1908        mode->name = xnfstrdup(cmodep->ml_identifier);
1909        if (last) {
1910            mode->prev = last;
1911            last->next = mode;
1912        }
1913        else {
1914            /*
1915             * this is the first mode
1916             */
1917            monitorp->Modes = mode;
1918            mode->prev = NULL;
1919        }
1920        last = mode;
1921        cmodep = (XF86ConfModeLinePtr) cmodep->list.next;
1922    }
1923    if (last) {
1924        last->next = NULL;
1925    }
1926    monitorp->Last = last;
1927
1928    /* add the (VESA) default modes */
1929    if (!addDefaultModes(monitorp))
1930        return FALSE;
1931
1932    if (conf_monitor->mon_gamma_red > GAMMA_ZERO)
1933        monitorp->gamma.red = conf_monitor->mon_gamma_red;
1934    if (conf_monitor->mon_gamma_green > GAMMA_ZERO)
1935        monitorp->gamma.green = conf_monitor->mon_gamma_green;
1936    if (conf_monitor->mon_gamma_blue > GAMMA_ZERO)
1937        monitorp->gamma.blue = conf_monitor->mon_gamma_blue;
1938
1939    /* Check that the gamma values are within range */
1940    if (monitorp->gamma.red > GAMMA_ZERO &&
1941        (monitorp->gamma.red < GAMMA_MIN || monitorp->gamma.red > GAMMA_MAX)) {
1942        badgamma = monitorp->gamma.red;
1943    }
1944    else if (monitorp->gamma.green > GAMMA_ZERO &&
1945             (monitorp->gamma.green < GAMMA_MIN ||
1946              monitorp->gamma.green > GAMMA_MAX)) {
1947        badgamma = monitorp->gamma.green;
1948    }
1949    else if (monitorp->gamma.blue > GAMMA_ZERO &&
1950             (monitorp->gamma.blue < GAMMA_MIN ||
1951              monitorp->gamma.blue > GAMMA_MAX)) {
1952        badgamma = monitorp->gamma.blue;
1953    }
1954    if (badgamma > GAMMA_ZERO) {
1955        ErrorF("Gamma value %.f is out of range (%.2f - %.1f)\n", badgamma,
1956               GAMMA_MIN, GAMMA_MAX);
1957        return FALSE;
1958    }
1959
1960    xf86ProcessOptions(-1, monitorp->options, MonitorOptions);
1961    xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING,
1962                      &monitorp->reducedblanking);
1963    if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ,
1964                          &maxPixClock) == TRUE) {
1965        monitorp->maxPixClock = (int) maxPixClock;
1966    }
1967
1968    return TRUE;
1969}
1970
1971static int
1972lookupVisual(const char *visname)
1973{
1974    int i;
1975
1976    if (!visname || !*visname)
1977        return -1;
1978
1979    for (i = 0; i <= DirectColor; i++) {
1980        if (!xf86nameCompare(visname, xf86VisualNames[i]))
1981            break;
1982    }
1983
1984    if (i <= DirectColor)
1985        return i;
1986
1987    return -1;
1988}
1989
1990static Bool
1991configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display)
1992{
1993    int count = 0;
1994    XF86ModePtr modep;
1995
1996    displayp->frameX0 = conf_display->disp_frameX0;
1997    displayp->frameY0 = conf_display->disp_frameY0;
1998    displayp->virtualX = conf_display->disp_virtualX;
1999    displayp->virtualY = conf_display->disp_virtualY;
2000    displayp->depth = conf_display->disp_depth;
2001    displayp->fbbpp = conf_display->disp_bpp;
2002    displayp->weight.red = conf_display->disp_weight.red;
2003    displayp->weight.green = conf_display->disp_weight.green;
2004    displayp->weight.blue = conf_display->disp_weight.blue;
2005    displayp->blackColour.red = conf_display->disp_black.red;
2006    displayp->blackColour.green = conf_display->disp_black.green;
2007    displayp->blackColour.blue = conf_display->disp_black.blue;
2008    displayp->whiteColour.red = conf_display->disp_white.red;
2009    displayp->whiteColour.green = conf_display->disp_white.green;
2010    displayp->whiteColour.blue = conf_display->disp_white.blue;
2011    displayp->options = conf_display->disp_option_lst;
2012    if (conf_display->disp_visual) {
2013        displayp->defaultVisual = lookupVisual(conf_display->disp_visual);
2014        if (displayp->defaultVisual == -1) {
2015            ErrorF("Invalid visual name: \"%s\"\n", conf_display->disp_visual);
2016            return FALSE;
2017        }
2018    }
2019    else {
2020        displayp->defaultVisual = -1;
2021    }
2022
2023    /*
2024     * now hook in the modes
2025     */
2026    modep = conf_display->disp_mode_lst;
2027    while (modep) {
2028        count++;
2029        modep = (XF86ModePtr) modep->list.next;
2030    }
2031    displayp->modes = xnfallocarray(count + 1, sizeof(char *));
2032    modep = conf_display->disp_mode_lst;
2033    count = 0;
2034    while (modep) {
2035        displayp->modes[count] = modep->mode_name;
2036        count++;
2037        modep = (XF86ModePtr) modep->list.next;
2038    }
2039    displayp->modes[count] = NULL;
2040
2041    return TRUE;
2042}
2043
2044static Bool
2045configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active, Bool gpu)
2046{
2047    int i;
2048
2049    if (!conf_device) {
2050        return FALSE;
2051    }
2052
2053    if (active) {
2054        if (gpu)
2055            xf86Msg(X_CONFIG, "|   |-->GPUDevice \"%s\"\n",
2056                    conf_device->dev_identifier);
2057        else
2058            xf86Msg(X_CONFIG, "|   |-->Device \"%s\"\n",
2059                    conf_device->dev_identifier);
2060    } else
2061        xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n",
2062                conf_device->dev_identifier);
2063
2064    devicep->identifier = conf_device->dev_identifier;
2065    devicep->vendor = conf_device->dev_vendor;
2066    devicep->board = conf_device->dev_board;
2067    devicep->chipset = conf_device->dev_chipset;
2068    devicep->ramdac = conf_device->dev_ramdac;
2069    devicep->driver = conf_device->dev_driver;
2070    devicep->active = active;
2071    devicep->videoRam = conf_device->dev_videoram;
2072    devicep->MemBase = conf_device->dev_mem_base;
2073    devicep->IOBase = conf_device->dev_io_base;
2074    devicep->clockchip = conf_device->dev_clockchip;
2075    devicep->busID = conf_device->dev_busid;
2076    devicep->chipID = conf_device->dev_chipid;
2077    devicep->chipRev = conf_device->dev_chiprev;
2078    devicep->options = conf_device->dev_option_lst;
2079    devicep->irq = conf_device->dev_irq;
2080    devicep->screen = conf_device->dev_screen;
2081
2082    for (i = 0; i < MAXDACSPEEDS; i++) {
2083        if (i < CONF_MAXDACSPEEDS)
2084            devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i];
2085        else
2086            devicep->dacSpeeds[i] = 0;
2087    }
2088    devicep->numclocks = conf_device->dev_clocks;
2089    if (devicep->numclocks > MAXCLOCKS)
2090        devicep->numclocks = MAXCLOCKS;
2091    for (i = 0; i < devicep->numclocks; i++) {
2092        devicep->clock[i] = conf_device->dev_clock[i];
2093    }
2094    devicep->claimed = FALSE;
2095
2096    return TRUE;
2097}
2098
2099static void
2100configDRI(XF86ConfDRIPtr drip)
2101{
2102    struct group *grp;
2103
2104    xf86ConfigDRI.group = -1;
2105    xf86ConfigDRI.mode = 0;
2106
2107    if (drip) {
2108        if (drip->dri_group_name) {
2109            if ((grp = getgrnam(drip->dri_group_name)))
2110                xf86ConfigDRI.group = grp->gr_gid;
2111        }
2112        else {
2113            if (drip->dri_group >= 0)
2114                xf86ConfigDRI.group = drip->dri_group;
2115        }
2116        xf86ConfigDRI.mode = drip->dri_mode;
2117    }
2118}
2119
2120static void
2121configExtensions(XF86ConfExtensionsPtr conf_ext)
2122{
2123    XF86OptionPtr o;
2124
2125    if (conf_ext && conf_ext->ext_option_lst) {
2126        for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) {
2127            char *name = xf86OptionName(o);
2128            char *val = xf86OptionValue(o);
2129            char *n;
2130            Bool enable = TRUE;
2131
2132            /* Handle "No<ExtensionName>" */
2133            n = xf86NormalizeName(name);
2134            if (strncmp(n, "no", 2) == 0) {
2135                name += 2;
2136                enable = FALSE;
2137            }
2138
2139            if (!val ||
2140                xf86NameCmp(val, "enable") == 0 ||
2141                xf86NameCmp(val, "enabled") == 0 ||
2142                xf86NameCmp(val, "on") == 0 ||
2143                xf86NameCmp(val, "1") == 0 ||
2144                xf86NameCmp(val, "yes") == 0 || xf86NameCmp(val, "true") == 0) {
2145                /* NOTHING NEEDED -- enabling is handled below */
2146            }
2147            else if (xf86NameCmp(val, "disable") == 0 ||
2148                     xf86NameCmp(val, "disabled") == 0 ||
2149                     xf86NameCmp(val, "off") == 0 ||
2150                     xf86NameCmp(val, "0") == 0 ||
2151                     xf86NameCmp(val, "no") == 0 ||
2152                     xf86NameCmp(val, "false") == 0) {
2153                enable = !enable;
2154            }
2155            else {
2156                xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val);
2157                free(n);
2158                continue;
2159            }
2160
2161            if (EnableDisableExtension(name, enable)) {
2162                xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n",
2163                        name, enable ? "enabled" : "disabled");
2164            }
2165            else {
2166                xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n",
2167                        name);
2168            }
2169            free(n);
2170        }
2171    }
2172}
2173
2174static Bool
2175configInput(InputInfoPtr inputp, XF86ConfInputPtr conf_input, MessageType from)
2176{
2177    xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier);
2178    inputp->name = conf_input->inp_identifier;
2179    inputp->driver = conf_input->inp_driver;
2180    inputp->options = conf_input->inp_option_lst;
2181    inputp->attrs = NULL;
2182
2183    return TRUE;
2184}
2185
2186static Bool
2187modeIsPresent(DisplayModePtr mode, MonPtr monitorp)
2188{
2189    DisplayModePtr knownmodes = monitorp->Modes;
2190
2191    /* all I can think of is a linear search... */
2192    while (knownmodes != NULL) {
2193        if (!strcmp(mode->name, knownmodes->name) &&
2194            !(knownmodes->type & M_T_DEFAULT))
2195            return TRUE;
2196        knownmodes = knownmodes->next;
2197    }
2198    return FALSE;
2199}
2200
2201static Bool
2202addDefaultModes(MonPtr monitorp)
2203{
2204    DisplayModePtr mode;
2205    DisplayModePtr last = monitorp->Last;
2206    int i = 0;
2207
2208    for (i = 0; i < xf86NumDefaultModes; i++) {
2209        mode = xf86DuplicateMode(&xf86DefaultModes[i]);
2210        if (!modeIsPresent(mode, monitorp)) {
2211            monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode);
2212            last = mode;
2213        }
2214        else {
2215            free(mode);
2216        }
2217    }
2218    monitorp->Last = last;
2219
2220    return TRUE;
2221}
2222
2223static void
2224checkInput(serverLayoutPtr layout, Bool implicit_layout)
2225{
2226    checkCoreInputDevices(layout, implicit_layout);
2227
2228    /* Unless we're forcing input devices, disable mouse/kbd devices in the
2229     * config. Otherwise the same physical device is added multiple times,
2230     * leading to duplicate events.
2231     */
2232    if (!xf86Info.forceInputDevices && layout->inputs) {
2233        InputInfoPtr *dev = layout->inputs;
2234        BOOL warned = FALSE;
2235
2236        while (*dev) {
2237            if (strcmp((*dev)->driver, "kbd") == 0 ||
2238                strcmp((*dev)->driver, "mouse") == 0 ||
2239                strcmp((*dev)->driver, "vmmouse") == 0) {
2240                InputInfoPtr *current;
2241
2242                if (!warned) {
2243                    xf86Msg(X_WARNING, "Hotplugging is on, devices using "
2244                            "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n");
2245                    warned = TRUE;
2246                }
2247
2248                xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->name);
2249
2250                current = dev;
2251                free(*dev);
2252                *dev = NULL;
2253
2254                do {
2255                    *current = *(current + 1);
2256                    current++;
2257                } while (*current);
2258            }
2259            else
2260                dev++;
2261        }
2262    }
2263}
2264
2265/*
2266 * load the config file and fill the global data structure
2267 */
2268ConfigStatus
2269xf86HandleConfigFile(Bool autoconfig)
2270{
2271#ifdef XSERVER_LIBPCIACCESS
2272    const char *scanptr;
2273    Bool singlecard = 0;
2274#endif
2275    Bool implicit_layout = FALSE;
2276    XF86ConfLayoutPtr layout;
2277
2278    if (!autoconfig) {
2279        char *filename, *dirname, *sysdirname;
2280        const char *filesearch, *dirsearch;
2281        MessageType filefrom = X_DEFAULT;
2282        MessageType dirfrom = X_DEFAULT;
2283
2284        if (!PrivsElevated()) {
2285            filesearch = ALL_CONFIGPATH;
2286            dirsearch = ALL_CONFIGDIRPATH;
2287        }
2288        else {
2289            filesearch = RESTRICTED_CONFIGPATH;
2290            dirsearch = RESTRICTED_CONFIGDIRPATH;
2291        }
2292
2293        if (xf86ConfigFile)
2294            filefrom = X_CMDLINE;
2295        if (xf86ConfigDir)
2296            dirfrom = X_CMDLINE;
2297
2298        xf86initConfigFiles();
2299        sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL,
2300                                            PROJECTROOT);
2301        dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT);
2302        filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT);
2303        if (filename) {
2304            xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename);
2305            xf86ConfigFile = xnfstrdup(filename);
2306        }
2307        else {
2308            if (xf86ConfigFile)
2309                xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n",
2310                        xf86ConfigFile);
2311        }
2312        if (dirname) {
2313            xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n",
2314                        dirname);
2315            xf86ConfigDir = xnfstrdup(dirname);
2316        }
2317        else {
2318            if (xf86ConfigDir)
2319                xf86Msg(X_ERROR,
2320                        "Unable to locate/open config directory: \"%s\"\n",
2321                        xf86ConfigDir);
2322        }
2323        if (sysdirname)
2324            xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n",
2325                        sysdirname);
2326        if (!filename && !dirname && !sysdirname)
2327            return CONFIG_NOFILE;
2328
2329        free(filename);
2330        free(dirname);
2331        free(sysdirname);
2332    }
2333
2334    if ((xf86configptr = xf86readConfigFile()) == NULL) {
2335        xf86Msg(X_ERROR, "Problem parsing the config file\n");
2336        return CONFIG_PARSE_ERROR;
2337    }
2338    xf86closeConfigFile();
2339
2340    /* Initialise a few things. */
2341
2342    /*
2343     * now we convert part of the information contained in the parser
2344     * structures into our own structures.
2345     * The important part here is to figure out which Screen Sections
2346     * in the XF86Config file are active so that we can piece together
2347     * the modes that we need later down the road.
2348     * And while we are at it, we'll decode the rest of the stuff as well
2349     */
2350
2351    /* First check if a layout section is present, and if it is valid. */
2352    FIND_SUITABLE(XF86ConfLayoutPtr, xf86configptr->conf_layout_lst, layout);
2353    if (layout == NULL || xf86ScreenName != NULL) {
2354        XF86ConfScreenPtr screen;
2355
2356        if (xf86ScreenName == NULL) {
2357            xf86Msg(X_DEFAULT,
2358                    "No Layout section.  Using the first Screen section.\n");
2359        }
2360        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
2361        if (!configImpliedLayout(&xf86ConfigLayout,
2362                                 screen,
2363                                 xf86configptr)) {
2364            xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2365            return CONFIG_PARSE_ERROR;
2366        }
2367        implicit_layout = TRUE;
2368    }
2369    else {
2370        if (xf86configptr->conf_flags != NULL) {
2371            char *dfltlayout = NULL;
2372            void *optlist = xf86configptr->conf_flags->flg_option_lst;
2373
2374            if (optlist && xf86FindOption(optlist, "defaultserverlayout"))
2375                dfltlayout =
2376                    xf86SetStrOption(optlist, "defaultserverlayout", NULL);
2377            if (!configLayout(&xf86ConfigLayout, layout, dfltlayout)) {
2378                xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2379                return CONFIG_PARSE_ERROR;
2380            }
2381        }
2382        else {
2383            if (!configLayout(&xf86ConfigLayout, layout, NULL)) {
2384                xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
2385                return CONFIG_PARSE_ERROR;
2386            }
2387        }
2388    }
2389
2390    xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions);
2391#ifdef XSERVER_LIBPCIACCESS
2392    if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) {
2393        ;                       /* IsolateDevice specified; overrides SingleCard */
2394    }
2395    else {
2396        xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard);
2397        if (singlecard)
2398            scanptr = xf86ConfigLayout.screens->screen->device->busID;
2399    }
2400    if (scanptr) {
2401        if (strncmp(scanptr, "PCI:", 4) != 0) {
2402            xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n"
2403                    "\tIgnoring IsolateDevice option.\n");
2404        }
2405        else
2406            xf86PciIsolateDevice(scanptr);
2407    }
2408#endif
2409    /* Now process everything else */
2410    configServerFlags(xf86configptr->conf_flags, xf86ConfigLayout.options);
2411    configFiles(xf86configptr->conf_files);
2412    configExtensions(xf86configptr->conf_extensions);
2413    configDRI(xf86configptr->conf_dri);
2414
2415    checkInput(&xf86ConfigLayout, implicit_layout);
2416
2417    /*
2418     * Handle some command line options that can override some of the
2419     * ServerFlags settings.
2420     */
2421#ifdef XF86VIDMODE
2422    if (xf86VidModeDisabled)
2423        xf86Info.vidModeEnabled = FALSE;
2424    if (xf86VidModeAllowNonLocal)
2425        xf86Info.vidModeAllowNonLocal = TRUE;
2426#endif
2427
2428    if (xf86AllowMouseOpenFail)
2429        xf86Info.allowMouseOpenFail = TRUE;
2430
2431    return CONFIG_OK;
2432}
2433
2434Bool
2435xf86PathIsSafe(const char *path)
2436{
2437    return (xf86pathIsSafe(path) != 0);
2438}
2439