1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 1997 Metro Link Incorporated
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun * all copies or substantial portions of the Software.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17*4882a593Smuzhiyun * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19*4882a593Smuzhiyun * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20*4882a593Smuzhiyun * SOFTWARE.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Except as contained in this notice, the name of the Metro Link shall not be
23*4882a593Smuzhiyun * used in advertising or otherwise to promote the sale, use or other dealings
24*4882a593Smuzhiyun * in this Software without prior written authorization from Metro Link.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
31*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
32*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
33*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
35*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
38*4882a593Smuzhiyun * all copies or substantial portions of the Software.
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43*4882a593Smuzhiyun * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46*4882a593Smuzhiyun * OTHER DEALINGS IN THE SOFTWARE.
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * Except as contained in this notice, the name of the copyright holder(s)
49*4882a593Smuzhiyun * and author(s) shall not be used in advertising or otherwise to promote
50*4882a593Smuzhiyun * the sale, use or other dealings in this Software without prior written
51*4882a593Smuzhiyun * authorization from the copyright holder(s) and author(s).
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
55*4882a593Smuzhiyun #include <xorg-config.h>
56*4882a593Smuzhiyun #endif
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #include <ctype.h>
59*4882a593Smuzhiyun #include <stdio.h>
60*4882a593Smuzhiyun #include <stdlib.h>
61*4882a593Smuzhiyun #include <string.h>
62*4882a593Smuzhiyun #include <sys/types.h>
63*4882a593Smuzhiyun #include <dirent.h>
64*4882a593Smuzhiyun #include <unistd.h>
65*4882a593Smuzhiyun #include <stdarg.h>
66*4882a593Smuzhiyun #include <X11/Xdefs.h>
67*4882a593Smuzhiyun #include <X11/Xfuncproto.h>
68*4882a593Smuzhiyun #include <limits.h>
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun #if !defined(MAXHOSTNAMELEN)
71*4882a593Smuzhiyun #define MAXHOSTNAMELEN 32
72*4882a593Smuzhiyun #endif /* !MAXHOSTNAMELEN */
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* For PATH_MAX */
75*4882a593Smuzhiyun #include "misc.h"
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #include "Configint.h"
78*4882a593Smuzhiyun #include "xf86tokens.h"
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define CONFIG_BUF_LEN 1024
81*4882a593Smuzhiyun #define CONFIG_MAX_FILES 64
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun static struct {
84*4882a593Smuzhiyun FILE *file;
85*4882a593Smuzhiyun char *path;
86*4882a593Smuzhiyun } configFiles[CONFIG_MAX_FILES];
87*4882a593Smuzhiyun static const char **builtinConfig = NULL;
88*4882a593Smuzhiyun static int builtinIndex = 0;
89*4882a593Smuzhiyun static int configPos = 0; /* current readers position */
90*4882a593Smuzhiyun static int configLineNo = 0; /* linenumber */
91*4882a593Smuzhiyun static char *configBuf, *configRBuf; /* buffer for lines */
92*4882a593Smuzhiyun static char *configSection = NULL; /* name of current section being parsed */
93*4882a593Smuzhiyun static int numFiles = 0; /* number of config files */
94*4882a593Smuzhiyun static int curFileIndex = 0; /* index of current config file */
95*4882a593Smuzhiyun static int pushToken = LOCK_TOKEN;
96*4882a593Smuzhiyun static int eol_seen = 0; /* private state to handle comments */
97*4882a593Smuzhiyun LexRec xf86_lex_val;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun * xf86getNextLine --
101*4882a593Smuzhiyun *
102*4882a593Smuzhiyun * read from the configFiles FILE stream until we encounter a new
103*4882a593Smuzhiyun * line; this is effectively just a big wrapper for fgets(3).
104*4882a593Smuzhiyun *
105*4882a593Smuzhiyun * xf86getToken() assumes that we will read up to the next
106*4882a593Smuzhiyun * newline; we need to grow configBuf and configRBuf as needed to
107*4882a593Smuzhiyun * support that.
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun static char *
xf86getNextLine(void)111*4882a593Smuzhiyun xf86getNextLine(void)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun static int configBufLen = CONFIG_BUF_LEN;
114*4882a593Smuzhiyun char *tmpConfigBuf, *tmpConfigRBuf;
115*4882a593Smuzhiyun int c, i, pos = 0, eolFound = 0;
116*4882a593Smuzhiyun char *ret = NULL;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun * reallocate the string if it was grown last time (i.e., is no
120*4882a593Smuzhiyun * longer CONFIG_BUF_LEN); we malloc the new strings first, so
121*4882a593Smuzhiyun * that if either of the mallocs fail, we can fall back on the
122*4882a593Smuzhiyun * existing buffer allocations
123*4882a593Smuzhiyun */
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (configBufLen != CONFIG_BUF_LEN) {
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun tmpConfigBuf = malloc(CONFIG_BUF_LEN);
128*4882a593Smuzhiyun tmpConfigRBuf = malloc(CONFIG_BUF_LEN);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (!tmpConfigBuf || !tmpConfigRBuf) {
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /*
133*4882a593Smuzhiyun * at least one of the mallocs failed; keep the old buffers
134*4882a593Smuzhiyun * and free any partial allocations
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun free(tmpConfigBuf);
138*4882a593Smuzhiyun free(tmpConfigRBuf);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun else {
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /*
144*4882a593Smuzhiyun * malloc succeeded; free the old buffers and use the new
145*4882a593Smuzhiyun * buffers
146*4882a593Smuzhiyun */
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun configBufLen = CONFIG_BUF_LEN;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun free(configBuf);
151*4882a593Smuzhiyun free(configRBuf);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun configBuf = tmpConfigBuf;
154*4882a593Smuzhiyun configRBuf = tmpConfigRBuf;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* read in another block of chars */
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun do {
161*4882a593Smuzhiyun ret = fgets(configBuf + pos, configBufLen - pos - 1,
162*4882a593Smuzhiyun configFiles[curFileIndex].file);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (!ret) {
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun * if the file doesn't end in a newline, add one
167*4882a593Smuzhiyun * and trigger another read
168*4882a593Smuzhiyun */
169*4882a593Smuzhiyun if (pos != 0) {
170*4882a593Smuzhiyun strcpy(&configBuf[pos], "\n");
171*4882a593Smuzhiyun ret = configBuf;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun else
174*4882a593Smuzhiyun break;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* search for EOL in the new block of chars */
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun for (i = pos; i < (configBufLen - 1); i++) {
180*4882a593Smuzhiyun c = configBuf[i];
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (c == '\0')
183*4882a593Smuzhiyun break;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if ((c == '\n') || (c == '\r')) {
186*4882a593Smuzhiyun eolFound = 1;
187*4882a593Smuzhiyun break;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /*
192*4882a593Smuzhiyun * if we didn't find EOL, then grow the string and
193*4882a593Smuzhiyun * read in more
194*4882a593Smuzhiyun */
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (!eolFound) {
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun tmpConfigBuf = realloc(configBuf, configBufLen + CONFIG_BUF_LEN);
199*4882a593Smuzhiyun tmpConfigRBuf = realloc(configRBuf, configBufLen + CONFIG_BUF_LEN);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (!tmpConfigBuf || !tmpConfigRBuf) {
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /*
204*4882a593Smuzhiyun * at least one of the reallocations failed; use the
205*4882a593Smuzhiyun * new allocation that succeeded, but we have to
206*4882a593Smuzhiyun * fallback to the previous configBufLen size and use
207*4882a593Smuzhiyun * the string we have, even though we don't have an
208*4882a593Smuzhiyun * EOL
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (tmpConfigBuf)
212*4882a593Smuzhiyun configBuf = tmpConfigBuf;
213*4882a593Smuzhiyun if (tmpConfigRBuf)
214*4882a593Smuzhiyun configRBuf = tmpConfigRBuf;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun else {
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* reallocation succeeded */
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun configBuf = tmpConfigBuf;
224*4882a593Smuzhiyun configRBuf = tmpConfigRBuf;
225*4882a593Smuzhiyun pos = i;
226*4882a593Smuzhiyun configBufLen += CONFIG_BUF_LEN;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun } while (!eolFound);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return ret;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun static int
StringToToken(const char * str,const xf86ConfigSymTabRec * tab)236*4882a593Smuzhiyun StringToToken(const char *str, const xf86ConfigSymTabRec * tab)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun int i;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun for (i = 0; tab[i].token != -1; i++) {
241*4882a593Smuzhiyun if (!xf86nameCompare(tab[i].name, str))
242*4882a593Smuzhiyun return tab[i].token;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun return ERROR_TOKEN;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /*
248*4882a593Smuzhiyun * xf86getToken --
249*4882a593Smuzhiyun * Read next Token from the config file. Handle the global variable
250*4882a593Smuzhiyun * pushToken.
251*4882a593Smuzhiyun */
252*4882a593Smuzhiyun int
xf86getToken(const xf86ConfigSymTabRec * tab)253*4882a593Smuzhiyun xf86getToken(const xf86ConfigSymTabRec * tab)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun int c, i;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun /*
258*4882a593Smuzhiyun * First check whether pushToken has a different value than LOCK_TOKEN.
259*4882a593Smuzhiyun * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the
260*4882a593Smuzhiyun * oth * case the next token must be read from the input.
261*4882a593Smuzhiyun */
262*4882a593Smuzhiyun if (pushToken == EOF_TOKEN)
263*4882a593Smuzhiyun return EOF_TOKEN;
264*4882a593Smuzhiyun else if (pushToken == LOCK_TOKEN) {
265*4882a593Smuzhiyun /*
266*4882a593Smuzhiyun * eol_seen is only set for the first token after a newline.
267*4882a593Smuzhiyun */
268*4882a593Smuzhiyun eol_seen = 0;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun c = configBuf[configPos];
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /*
273*4882a593Smuzhiyun * Get start of next Token. EOF is handled,
274*4882a593Smuzhiyun * whitespaces are skipped.
275*4882a593Smuzhiyun */
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun again:
278*4882a593Smuzhiyun if (!c) {
279*4882a593Smuzhiyun char *ret;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (numFiles > 0)
282*4882a593Smuzhiyun ret = xf86getNextLine();
283*4882a593Smuzhiyun else {
284*4882a593Smuzhiyun if (builtinConfig[builtinIndex] == NULL)
285*4882a593Smuzhiyun ret = NULL;
286*4882a593Smuzhiyun else {
287*4882a593Smuzhiyun strlcpy(configBuf,
288*4882a593Smuzhiyun builtinConfig[builtinIndex], CONFIG_BUF_LEN);
289*4882a593Smuzhiyun ret = configBuf;
290*4882a593Smuzhiyun builtinIndex++;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun if (ret == NULL) {
294*4882a593Smuzhiyun /*
295*4882a593Smuzhiyun * if necessary, move to the next file and
296*4882a593Smuzhiyun * read the first line
297*4882a593Smuzhiyun */
298*4882a593Smuzhiyun if (curFileIndex + 1 < numFiles) {
299*4882a593Smuzhiyun curFileIndex++;
300*4882a593Smuzhiyun configLineNo = 0;
301*4882a593Smuzhiyun goto again;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun else
304*4882a593Smuzhiyun return pushToken = EOF_TOKEN;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun configLineNo++;
307*4882a593Smuzhiyun configPos = 0;
308*4882a593Smuzhiyun eol_seen = 1;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun i = 0;
312*4882a593Smuzhiyun for (;;) {
313*4882a593Smuzhiyun c = configBuf[configPos++];
314*4882a593Smuzhiyun configRBuf[i++] = c;
315*4882a593Smuzhiyun switch (c) {
316*4882a593Smuzhiyun case ' ':
317*4882a593Smuzhiyun case '\t':
318*4882a593Smuzhiyun case '\r':
319*4882a593Smuzhiyun continue;
320*4882a593Smuzhiyun case '\n':
321*4882a593Smuzhiyun i = 0;
322*4882a593Smuzhiyun continue;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun break;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun if (c == '\0')
327*4882a593Smuzhiyun goto again;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (c == '#') {
330*4882a593Smuzhiyun do {
331*4882a593Smuzhiyun configRBuf[i++] = (c = configBuf[configPos++]);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun while ((c != '\n') && (c != '\r') && (c != '\0'));
334*4882a593Smuzhiyun configRBuf[i] = '\0';
335*4882a593Smuzhiyun /* XXX no private copy.
336*4882a593Smuzhiyun * Use xf86addComment when setting a comment.
337*4882a593Smuzhiyun */
338*4882a593Smuzhiyun xf86_lex_val.str = configRBuf;
339*4882a593Smuzhiyun return COMMENT;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */
343*4882a593Smuzhiyun else if ((c == ',') && !isalpha(configBuf[configPos])) {
344*4882a593Smuzhiyun return COMMA;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun else if ((c == '-') && !isalpha(configBuf[configPos])) {
347*4882a593Smuzhiyun return DASH;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /*
351*4882a593Smuzhiyun * Numbers are returned immediately ...
352*4882a593Smuzhiyun */
353*4882a593Smuzhiyun if (isdigit(c)) {
354*4882a593Smuzhiyun int base;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (c == '0')
357*4882a593Smuzhiyun if ((configBuf[configPos] == 'x') ||
358*4882a593Smuzhiyun (configBuf[configPos] == 'X')) {
359*4882a593Smuzhiyun base = 16;
360*4882a593Smuzhiyun xf86_lex_val.numType = PARSE_HEX;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun else {
363*4882a593Smuzhiyun base = 8;
364*4882a593Smuzhiyun xf86_lex_val.numType = PARSE_OCTAL;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun else {
367*4882a593Smuzhiyun base = 10;
368*4882a593Smuzhiyun xf86_lex_val.numType = PARSE_DECIMAL;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun configRBuf[0] = c;
372*4882a593Smuzhiyun i = 1;
373*4882a593Smuzhiyun while (isdigit(c = configBuf[configPos++]) ||
374*4882a593Smuzhiyun (c == '.') || (c == 'x') || (c == 'X') ||
375*4882a593Smuzhiyun ((base == 16) && (((c >= 'a') && (c <= 'f')) ||
376*4882a593Smuzhiyun ((c >= 'A') && (c <= 'F')))))
377*4882a593Smuzhiyun configRBuf[i++] = c;
378*4882a593Smuzhiyun configPos--; /* GJA -- one too far */
379*4882a593Smuzhiyun configRBuf[i] = '\0';
380*4882a593Smuzhiyun xf86_lex_val.num = strtoul(configRBuf, NULL, 0);
381*4882a593Smuzhiyun xf86_lex_val.realnum = atof(configRBuf);
382*4882a593Smuzhiyun return NUMBER;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /*
386*4882a593Smuzhiyun * All Strings START with a \" ...
387*4882a593Smuzhiyun */
388*4882a593Smuzhiyun else if (c == '\"') {
389*4882a593Smuzhiyun i = -1;
390*4882a593Smuzhiyun do {
391*4882a593Smuzhiyun configRBuf[++i] = (c = configBuf[configPos++]);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
394*4882a593Smuzhiyun configRBuf[i] = '\0';
395*4882a593Smuzhiyun xf86_lex_val.str = malloc(strlen(configRBuf) + 1);
396*4882a593Smuzhiyun strcpy(xf86_lex_val.str, configRBuf); /* private copy ! */
397*4882a593Smuzhiyun return STRING;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /*
401*4882a593Smuzhiyun * ... and now we MUST have a valid token. The search is
402*4882a593Smuzhiyun * handled later along with the pushed tokens.
403*4882a593Smuzhiyun */
404*4882a593Smuzhiyun else {
405*4882a593Smuzhiyun configRBuf[0] = c;
406*4882a593Smuzhiyun i = 0;
407*4882a593Smuzhiyun do {
408*4882a593Smuzhiyun configRBuf[++i] = (c = configBuf[configPos++]);
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun while ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r') &&
411*4882a593Smuzhiyun (c != '\0') && (c != '#'));
412*4882a593Smuzhiyun --configPos;
413*4882a593Smuzhiyun configRBuf[i] = '\0';
414*4882a593Smuzhiyun i = 0;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun else {
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /*
421*4882a593Smuzhiyun * Here we deal with pushed tokens. Reinitialize pushToken again. If
422*4882a593Smuzhiyun * the pushed token was NUMBER || STRING return them again ...
423*4882a593Smuzhiyun */
424*4882a593Smuzhiyun int temp = pushToken;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun pushToken = LOCK_TOKEN;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun if (temp == COMMA || temp == DASH)
429*4882a593Smuzhiyun return temp;
430*4882a593Smuzhiyun if (temp == NUMBER || temp == STRING)
431*4882a593Smuzhiyun return temp;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /*
435*4882a593Smuzhiyun * Joop, at last we have to lookup the token ...
436*4882a593Smuzhiyun */
437*4882a593Smuzhiyun if (tab)
438*4882a593Smuzhiyun return StringToToken(configRBuf, tab);
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun return ERROR_TOKEN; /* Error catcher */
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun int
xf86getSubToken(char ** comment)444*4882a593Smuzhiyun xf86getSubToken(char **comment)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun int token;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun for (;;) {
449*4882a593Smuzhiyun token = xf86getToken(NULL);
450*4882a593Smuzhiyun if (token == COMMENT) {
451*4882a593Smuzhiyun if (comment)
452*4882a593Smuzhiyun *comment = xf86addComment(*comment, xf86_lex_val.str);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun else
455*4882a593Smuzhiyun return token;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun /*NOTREACHED*/}
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun int
xf86getSubTokenWithTab(char ** comment,const xf86ConfigSymTabRec * tab)460*4882a593Smuzhiyun xf86getSubTokenWithTab(char **comment, const xf86ConfigSymTabRec * tab)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun int token;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun for (;;) {
465*4882a593Smuzhiyun token = xf86getToken(tab);
466*4882a593Smuzhiyun if (token == COMMENT) {
467*4882a593Smuzhiyun if (comment)
468*4882a593Smuzhiyun *comment = xf86addComment(*comment, xf86_lex_val.str);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun else
471*4882a593Smuzhiyun return token;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun /*NOTREACHED*/}
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun void
xf86unGetToken(int token)476*4882a593Smuzhiyun xf86unGetToken(int token)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun pushToken = token;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun char *
xf86tokenString(void)482*4882a593Smuzhiyun xf86tokenString(void)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun return configRBuf;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun int
xf86pathIsAbsolute(const char * path)488*4882a593Smuzhiyun xf86pathIsAbsolute(const char *path)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun if (path && path[0] == '/')
491*4882a593Smuzhiyun return 1;
492*4882a593Smuzhiyun return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* A path is "safe" if it is relative and if it contains no ".." elements. */
496*4882a593Smuzhiyun int
xf86pathIsSafe(const char * path)497*4882a593Smuzhiyun xf86pathIsSafe(const char *path)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun if (xf86pathIsAbsolute(path))
500*4882a593Smuzhiyun return 0;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /* Compare with ".." */
503*4882a593Smuzhiyun if (!strcmp(path, ".."))
504*4882a593Smuzhiyun return 0;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /* Look for leading "../" */
507*4882a593Smuzhiyun if (!strncmp(path, "../", 3))
508*4882a593Smuzhiyun return 0;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /* Look for trailing "/.." */
511*4882a593Smuzhiyun if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/.."))
512*4882a593Smuzhiyun return 0;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* Look for "/../" */
515*4882a593Smuzhiyun if (strstr(path, "/../"))
516*4882a593Smuzhiyun return 0;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun return 1;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /*
522*4882a593Smuzhiyun * This function substitutes the following escape sequences:
523*4882a593Smuzhiyun *
524*4882a593Smuzhiyun * %A cmdline argument as an absolute path (must be absolute to match)
525*4882a593Smuzhiyun * %R cmdline argument as a relative path
526*4882a593Smuzhiyun * %S cmdline argument as a "safe" path (relative, and no ".." elements)
527*4882a593Smuzhiyun * %X default config file name ("xorg.conf")
528*4882a593Smuzhiyun * %H hostname
529*4882a593Smuzhiyun * %E config file environment ($XORGCONFIG) as an absolute path
530*4882a593Smuzhiyun * %F config file environment ($XORGCONFIG) as a relative path
531*4882a593Smuzhiyun * %G config file environment ($XORGCONFIG) as a safe path
532*4882a593Smuzhiyun * %P projroot
533*4882a593Smuzhiyun * %C sysconfdir
534*4882a593Smuzhiyun * %D datadir
535*4882a593Smuzhiyun * %% %
536*4882a593Smuzhiyun */
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun #define XCONFIGSUFFIX ".conf"
539*4882a593Smuzhiyun #define XCONFENV "XORGCONFIG"
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun #define BAIL_OUT do { \
542*4882a593Smuzhiyun free(result); \
543*4882a593Smuzhiyun return NULL; \
544*4882a593Smuzhiyun } while (0)
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun #define CHECK_LENGTH do { \
547*4882a593Smuzhiyun if (l > PATH_MAX) { \
548*4882a593Smuzhiyun BAIL_OUT; \
549*4882a593Smuzhiyun } \
550*4882a593Smuzhiyun } while (0)
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun #define APPEND_STR(s) do { \
553*4882a593Smuzhiyun if (strlen(s) + l > PATH_MAX) { \
554*4882a593Smuzhiyun BAIL_OUT; \
555*4882a593Smuzhiyun } else { \
556*4882a593Smuzhiyun strcpy(result + l, s); \
557*4882a593Smuzhiyun l += strlen(s); \
558*4882a593Smuzhiyun } \
559*4882a593Smuzhiyun } while (0)
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun static char *
DoSubstitution(const char * template,const char * cmdline,const char * projroot,int * cmdlineUsed,int * envUsed,const char * XConfigFile)562*4882a593Smuzhiyun DoSubstitution(const char *template, const char *cmdline, const char *projroot,
563*4882a593Smuzhiyun int *cmdlineUsed, int *envUsed, const char *XConfigFile)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun char *result;
566*4882a593Smuzhiyun int i, l;
567*4882a593Smuzhiyun static const char *env = NULL;
568*4882a593Smuzhiyun static char *hostname = NULL;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun if (!template)
571*4882a593Smuzhiyun return NULL;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun if (cmdlineUsed)
574*4882a593Smuzhiyun *cmdlineUsed = 0;
575*4882a593Smuzhiyun if (envUsed)
576*4882a593Smuzhiyun *envUsed = 0;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun result = malloc(PATH_MAX + 1);
579*4882a593Smuzhiyun l = 0;
580*4882a593Smuzhiyun for (i = 0; template[i]; i++) {
581*4882a593Smuzhiyun if (template[i] != '%') {
582*4882a593Smuzhiyun result[l++] = template[i];
583*4882a593Smuzhiyun CHECK_LENGTH;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun else {
586*4882a593Smuzhiyun switch (template[++i]) {
587*4882a593Smuzhiyun case 'A':
588*4882a593Smuzhiyun if (cmdline && xf86pathIsAbsolute(cmdline)) {
589*4882a593Smuzhiyun APPEND_STR(cmdline);
590*4882a593Smuzhiyun if (cmdlineUsed)
591*4882a593Smuzhiyun *cmdlineUsed = 1;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun else
594*4882a593Smuzhiyun BAIL_OUT;
595*4882a593Smuzhiyun break;
596*4882a593Smuzhiyun case 'R':
597*4882a593Smuzhiyun if (cmdline && !xf86pathIsAbsolute(cmdline)) {
598*4882a593Smuzhiyun APPEND_STR(cmdline);
599*4882a593Smuzhiyun if (cmdlineUsed)
600*4882a593Smuzhiyun *cmdlineUsed = 1;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun else
603*4882a593Smuzhiyun BAIL_OUT;
604*4882a593Smuzhiyun break;
605*4882a593Smuzhiyun case 'S':
606*4882a593Smuzhiyun if (cmdline && xf86pathIsSafe(cmdline)) {
607*4882a593Smuzhiyun APPEND_STR(cmdline);
608*4882a593Smuzhiyun if (cmdlineUsed)
609*4882a593Smuzhiyun *cmdlineUsed = 1;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun else
612*4882a593Smuzhiyun BAIL_OUT;
613*4882a593Smuzhiyun break;
614*4882a593Smuzhiyun case 'X':
615*4882a593Smuzhiyun APPEND_STR(XConfigFile);
616*4882a593Smuzhiyun break;
617*4882a593Smuzhiyun case 'H':
618*4882a593Smuzhiyun if (!hostname) {
619*4882a593Smuzhiyun if ((hostname = malloc(MAXHOSTNAMELEN + 1))) {
620*4882a593Smuzhiyun if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
621*4882a593Smuzhiyun hostname[MAXHOSTNAMELEN] = '\0';
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun else {
624*4882a593Smuzhiyun free(hostname);
625*4882a593Smuzhiyun hostname = NULL;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun if (hostname)
630*4882a593Smuzhiyun APPEND_STR(hostname);
631*4882a593Smuzhiyun break;
632*4882a593Smuzhiyun case 'E':
633*4882a593Smuzhiyun if (!env)
634*4882a593Smuzhiyun env = getenv(XCONFENV);
635*4882a593Smuzhiyun if (env && xf86pathIsAbsolute(env)) {
636*4882a593Smuzhiyun APPEND_STR(env);
637*4882a593Smuzhiyun if (envUsed)
638*4882a593Smuzhiyun *envUsed = 1;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun else
641*4882a593Smuzhiyun BAIL_OUT;
642*4882a593Smuzhiyun break;
643*4882a593Smuzhiyun case 'F':
644*4882a593Smuzhiyun if (!env)
645*4882a593Smuzhiyun env = getenv(XCONFENV);
646*4882a593Smuzhiyun if (env && !xf86pathIsAbsolute(env)) {
647*4882a593Smuzhiyun APPEND_STR(env);
648*4882a593Smuzhiyun if (envUsed)
649*4882a593Smuzhiyun *envUsed = 1;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun else
652*4882a593Smuzhiyun BAIL_OUT;
653*4882a593Smuzhiyun break;
654*4882a593Smuzhiyun case 'G':
655*4882a593Smuzhiyun if (!env)
656*4882a593Smuzhiyun env = getenv(XCONFENV);
657*4882a593Smuzhiyun if (env && xf86pathIsSafe(env)) {
658*4882a593Smuzhiyun APPEND_STR(env);
659*4882a593Smuzhiyun if (envUsed)
660*4882a593Smuzhiyun *envUsed = 1;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun else
663*4882a593Smuzhiyun BAIL_OUT;
664*4882a593Smuzhiyun break;
665*4882a593Smuzhiyun case 'P':
666*4882a593Smuzhiyun if (projroot && xf86pathIsAbsolute(projroot))
667*4882a593Smuzhiyun APPEND_STR(projroot);
668*4882a593Smuzhiyun else
669*4882a593Smuzhiyun BAIL_OUT;
670*4882a593Smuzhiyun break;
671*4882a593Smuzhiyun case 'C':
672*4882a593Smuzhiyun APPEND_STR(SYSCONFDIR);
673*4882a593Smuzhiyun break;
674*4882a593Smuzhiyun case 'D':
675*4882a593Smuzhiyun APPEND_STR(DATADIR);
676*4882a593Smuzhiyun break;
677*4882a593Smuzhiyun case '%':
678*4882a593Smuzhiyun result[l++] = '%';
679*4882a593Smuzhiyun CHECK_LENGTH;
680*4882a593Smuzhiyun break;
681*4882a593Smuzhiyun default:
682*4882a593Smuzhiyun fprintf(stderr, "invalid escape %%%c found in path template\n",
683*4882a593Smuzhiyun template[i]);
684*4882a593Smuzhiyun BAIL_OUT;
685*4882a593Smuzhiyun break;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun #ifdef DEBUG
690*4882a593Smuzhiyun fprintf(stderr, "Converted `%s' to `%s'\n", template, result);
691*4882a593Smuzhiyun #endif
692*4882a593Smuzhiyun return result;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun /*
696*4882a593Smuzhiyun * Given some searching parameters, locate and open the xorg config file.
697*4882a593Smuzhiyun */
698*4882a593Smuzhiyun static char *
OpenConfigFile(const char * path,const char * cmdline,const char * projroot,const char * confname)699*4882a593Smuzhiyun OpenConfigFile(const char *path, const char *cmdline, const char *projroot,
700*4882a593Smuzhiyun const char *confname)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun char *filepath = NULL;
703*4882a593Smuzhiyun char *pathcopy;
704*4882a593Smuzhiyun const char *template;
705*4882a593Smuzhiyun int cmdlineUsed = 0;
706*4882a593Smuzhiyun FILE *file = NULL;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun pathcopy = strdup(path);
709*4882a593Smuzhiyun for (template = strtok(pathcopy, ","); template && !file;
710*4882a593Smuzhiyun template = strtok(NULL, ",")) {
711*4882a593Smuzhiyun filepath = DoSubstitution(template, cmdline, projroot,
712*4882a593Smuzhiyun &cmdlineUsed, NULL, confname);
713*4882a593Smuzhiyun if (!filepath)
714*4882a593Smuzhiyun continue;
715*4882a593Smuzhiyun if (cmdline && !cmdlineUsed) {
716*4882a593Smuzhiyun free(filepath);
717*4882a593Smuzhiyun filepath = NULL;
718*4882a593Smuzhiyun continue;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun file = fopen(filepath, "r");
721*4882a593Smuzhiyun if (!file) {
722*4882a593Smuzhiyun free(filepath);
723*4882a593Smuzhiyun filepath = NULL;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun free(pathcopy);
728*4882a593Smuzhiyun if (file) {
729*4882a593Smuzhiyun configFiles[numFiles].file = file;
730*4882a593Smuzhiyun configFiles[numFiles].path = strdup(filepath);
731*4882a593Smuzhiyun numFiles++;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun return filepath;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /*
737*4882a593Smuzhiyun * Match non-hidden files in the xorg config directory with a .conf
738*4882a593Smuzhiyun * suffix. This filter is passed to scandir(3).
739*4882a593Smuzhiyun */
740*4882a593Smuzhiyun static int
ConfigFilter(const struct dirent * de)741*4882a593Smuzhiyun ConfigFilter(const struct dirent *de)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun const char *name = de->d_name;
744*4882a593Smuzhiyun size_t len;
745*4882a593Smuzhiyun size_t suflen = strlen(XCONFIGSUFFIX);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun if (!name || name[0] == '.')
748*4882a593Smuzhiyun return 0;
749*4882a593Smuzhiyun len = strlen(name);
750*4882a593Smuzhiyun if (len <= suflen)
751*4882a593Smuzhiyun return 0;
752*4882a593Smuzhiyun if (strcmp(&name[len - suflen], XCONFIGSUFFIX) != 0)
753*4882a593Smuzhiyun return 0;
754*4882a593Smuzhiyun return 1;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun static Bool
AddConfigDirFiles(const char * dirpath,struct dirent ** list,int num)758*4882a593Smuzhiyun AddConfigDirFiles(const char *dirpath, struct dirent **list, int num)
759*4882a593Smuzhiyun {
760*4882a593Smuzhiyun int i;
761*4882a593Smuzhiyun Bool openedFile = FALSE;
762*4882a593Smuzhiyun Bool warnOnce = FALSE;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun for (i = 0; i < num; i++) {
765*4882a593Smuzhiyun char *path;
766*4882a593Smuzhiyun FILE *file;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun if (numFiles >= CONFIG_MAX_FILES) {
769*4882a593Smuzhiyun if (!warnOnce) {
770*4882a593Smuzhiyun ErrorF("Maximum number of configuration " "files opened\n");
771*4882a593Smuzhiyun warnOnce = TRUE;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun continue;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun path = malloc(PATH_MAX + 1);
777*4882a593Smuzhiyun snprintf(path, PATH_MAX + 1, "%s/%s", dirpath, list[i]->d_name);
778*4882a593Smuzhiyun file = fopen(path, "r");
779*4882a593Smuzhiyun if (!file) {
780*4882a593Smuzhiyun free(path);
781*4882a593Smuzhiyun continue;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun openedFile = TRUE;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun configFiles[numFiles].file = file;
786*4882a593Smuzhiyun configFiles[numFiles].path = path;
787*4882a593Smuzhiyun numFiles++;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun return openedFile;
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun /*
794*4882a593Smuzhiyun * Given some searching parameters, locate and open the xorg config
795*4882a593Smuzhiyun * directory. The directory does not need to contain config files.
796*4882a593Smuzhiyun */
797*4882a593Smuzhiyun static char *
OpenConfigDir(const char * path,const char * cmdline,const char * projroot,const char * confname)798*4882a593Smuzhiyun OpenConfigDir(const char *path, const char *cmdline, const char *projroot,
799*4882a593Smuzhiyun const char *confname)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun char *dirpath = NULL, *pathcopy;
802*4882a593Smuzhiyun const char *template;
803*4882a593Smuzhiyun Bool found = FALSE;
804*4882a593Smuzhiyun int cmdlineUsed = 0;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun pathcopy = strdup(path);
807*4882a593Smuzhiyun for (template = strtok(pathcopy, ","); template && !found;
808*4882a593Smuzhiyun template = strtok(NULL, ",")) {
809*4882a593Smuzhiyun struct dirent **list = NULL;
810*4882a593Smuzhiyun int num;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun dirpath = DoSubstitution(template, cmdline, projroot,
813*4882a593Smuzhiyun &cmdlineUsed, NULL, confname);
814*4882a593Smuzhiyun if (!dirpath)
815*4882a593Smuzhiyun continue;
816*4882a593Smuzhiyun if (cmdline && !cmdlineUsed) {
817*4882a593Smuzhiyun free(dirpath);
818*4882a593Smuzhiyun dirpath = NULL;
819*4882a593Smuzhiyun continue;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun /* match files named *.conf */
823*4882a593Smuzhiyun num = scandir(dirpath, &list, ConfigFilter, alphasort);
824*4882a593Smuzhiyun if (num < 0) {
825*4882a593Smuzhiyun list = NULL;
826*4882a593Smuzhiyun num = 0;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun found = AddConfigDirFiles(dirpath, list, num);
829*4882a593Smuzhiyun if (!found) {
830*4882a593Smuzhiyun free(dirpath);
831*4882a593Smuzhiyun dirpath = NULL;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun while (num--)
834*4882a593Smuzhiyun free(list[num]);
835*4882a593Smuzhiyun free(list);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun free(pathcopy);
839*4882a593Smuzhiyun return dirpath;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun /*
843*4882a593Smuzhiyun * xf86initConfigFiles -- Setup global variables and buffers.
844*4882a593Smuzhiyun */
845*4882a593Smuzhiyun void
xf86initConfigFiles(void)846*4882a593Smuzhiyun xf86initConfigFiles(void)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun curFileIndex = 0;
849*4882a593Smuzhiyun configPos = 0;
850*4882a593Smuzhiyun configLineNo = 0;
851*4882a593Smuzhiyun pushToken = LOCK_TOKEN;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun configBuf = malloc(CONFIG_BUF_LEN);
854*4882a593Smuzhiyun configRBuf = malloc(CONFIG_BUF_LEN);
855*4882a593Smuzhiyun configBuf[0] = '\0'; /* sanity ... */
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun /*
859*4882a593Smuzhiyun * xf86openConfigFile --
860*4882a593Smuzhiyun *
861*4882a593Smuzhiyun * This function take a config file search path (optional), a command-line
862*4882a593Smuzhiyun * specified file name (optional) and the ProjectRoot path (optional) and
863*4882a593Smuzhiyun * locates and opens a config file based on that information. If a
864*4882a593Smuzhiyun * command-line file name is specified, then this function fails if none
865*4882a593Smuzhiyun * of the located files.
866*4882a593Smuzhiyun *
867*4882a593Smuzhiyun * The return value is a pointer to the actual name of the file that was
868*4882a593Smuzhiyun * opened. When no file is found, the return value is NULL. The caller should
869*4882a593Smuzhiyun * free() the returned value.
870*4882a593Smuzhiyun *
871*4882a593Smuzhiyun * The escape sequences allowed in the search path are defined above.
872*4882a593Smuzhiyun *
873*4882a593Smuzhiyun */
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun #ifndef DEFAULT_CONF_PATH
876*4882a593Smuzhiyun #define DEFAULT_CONF_PATH "/etc/X11/%S," \
877*4882a593Smuzhiyun "%P/etc/X11/%S," \
878*4882a593Smuzhiyun "/etc/X11/%G," \
879*4882a593Smuzhiyun "%P/etc/X11/%G," \
880*4882a593Smuzhiyun "/etc/X11/%X-%M," \
881*4882a593Smuzhiyun "/etc/X11/%X," \
882*4882a593Smuzhiyun "/etc/%X," \
883*4882a593Smuzhiyun "%P/etc/X11/%X.%H," \
884*4882a593Smuzhiyun "%P/etc/X11/%X-%M," \
885*4882a593Smuzhiyun "%P/etc/X11/%X," \
886*4882a593Smuzhiyun "%P/lib/X11/%X.%H," \
887*4882a593Smuzhiyun "%P/lib/X11/%X-%M," \
888*4882a593Smuzhiyun "%P/lib/X11/%X"
889*4882a593Smuzhiyun #endif
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun char *
xf86openConfigFile(const char * path,const char * cmdline,const char * projroot)892*4882a593Smuzhiyun xf86openConfigFile(const char *path, const char *cmdline, const char *projroot)
893*4882a593Smuzhiyun {
894*4882a593Smuzhiyun if (!path || !path[0])
895*4882a593Smuzhiyun path = DEFAULT_CONF_PATH;
896*4882a593Smuzhiyun if (!projroot || !projroot[0])
897*4882a593Smuzhiyun projroot = PROJECTROOT;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun /* Search for a config file */
900*4882a593Smuzhiyun return OpenConfigFile(path, cmdline, projroot, XCONFIGFILE);
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun /*
904*4882a593Smuzhiyun * xf86openConfigDirFiles --
905*4882a593Smuzhiyun *
906*4882a593Smuzhiyun * This function take a config directory search path (optional), a
907*4882a593Smuzhiyun * command-line specified directory name (optional) and the ProjectRoot path
908*4882a593Smuzhiyun * (optional) and locates and opens a config directory based on that
909*4882a593Smuzhiyun * information. If a command-line name is specified, then this function
910*4882a593Smuzhiyun * fails if it is not found.
911*4882a593Smuzhiyun *
912*4882a593Smuzhiyun * The return value is a pointer to the actual name of the directory that was
913*4882a593Smuzhiyun * opened. When no directory is found, the return value is NULL. The caller
914*4882a593Smuzhiyun * should free() the returned value.
915*4882a593Smuzhiyun *
916*4882a593Smuzhiyun * The escape sequences allowed in the search path are defined above.
917*4882a593Smuzhiyun *
918*4882a593Smuzhiyun */
919*4882a593Smuzhiyun char *
xf86openConfigDirFiles(const char * path,const char * cmdline,const char * projroot)920*4882a593Smuzhiyun xf86openConfigDirFiles(const char *path, const char *cmdline,
921*4882a593Smuzhiyun const char *projroot)
922*4882a593Smuzhiyun {
923*4882a593Smuzhiyun if (!path || !path[0])
924*4882a593Smuzhiyun path = DEFAULT_CONF_PATH;
925*4882a593Smuzhiyun if (!projroot || !projroot[0])
926*4882a593Smuzhiyun projroot = PROJECTROOT;
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun /* Search for the multiconf directory */
929*4882a593Smuzhiyun return OpenConfigDir(path, cmdline, projroot, XCONFIGDIR);
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun void
xf86closeConfigFile(void)933*4882a593Smuzhiyun xf86closeConfigFile(void)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun int i;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun free(configRBuf);
938*4882a593Smuzhiyun configRBuf = NULL;
939*4882a593Smuzhiyun free(configBuf);
940*4882a593Smuzhiyun configBuf = NULL;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (numFiles == 0) {
943*4882a593Smuzhiyun builtinConfig = NULL;
944*4882a593Smuzhiyun builtinIndex = 0;
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun for (i = 0; i < numFiles; i++) {
947*4882a593Smuzhiyun fclose(configFiles[i].file);
948*4882a593Smuzhiyun configFiles[i].file = NULL;
949*4882a593Smuzhiyun free(configFiles[i].path);
950*4882a593Smuzhiyun configFiles[i].path = NULL;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun numFiles = 0;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun void
xf86setBuiltinConfig(const char * config[])956*4882a593Smuzhiyun xf86setBuiltinConfig(const char *config[])
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun builtinConfig = config;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun void
xf86parseError(const char * format,...)962*4882a593Smuzhiyun xf86parseError(const char *format, ...)
963*4882a593Smuzhiyun {
964*4882a593Smuzhiyun va_list ap;
965*4882a593Smuzhiyun const char *filename = numFiles ? configFiles[curFileIndex].path
966*4882a593Smuzhiyun : "<builtin configuration>";
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun ErrorF("Parse error on line %d of section %s in file %s\n\t",
969*4882a593Smuzhiyun configLineNo, configSection, filename);
970*4882a593Smuzhiyun va_start(ap, format);
971*4882a593Smuzhiyun VErrorF(format, ap);
972*4882a593Smuzhiyun va_end(ap);
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun ErrorF("\n");
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun void
xf86validationError(const char * format,...)978*4882a593Smuzhiyun xf86validationError(const char *format, ...)
979*4882a593Smuzhiyun {
980*4882a593Smuzhiyun va_list ap;
981*4882a593Smuzhiyun const char *filename = numFiles ? configFiles[curFileIndex].path
982*4882a593Smuzhiyun : "<builtin configuration>";
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun ErrorF("Data incomplete in file %s\n\t", filename);
985*4882a593Smuzhiyun va_start(ap, format);
986*4882a593Smuzhiyun VErrorF(format, ap);
987*4882a593Smuzhiyun va_end(ap);
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun ErrorF("\n");
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun void
xf86setSection(const char * section)993*4882a593Smuzhiyun xf86setSection(const char *section)
994*4882a593Smuzhiyun {
995*4882a593Smuzhiyun free(configSection);
996*4882a593Smuzhiyun configSection = strdup(section);
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun /*
1000*4882a593Smuzhiyun * xf86getToken --
1001*4882a593Smuzhiyun * Lookup a string if it is actually a token in disguise.
1002*4882a593Smuzhiyun */
1003*4882a593Smuzhiyun int
xf86getStringToken(const xf86ConfigSymTabRec * tab)1004*4882a593Smuzhiyun xf86getStringToken(const xf86ConfigSymTabRec * tab)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun return StringToToken(xf86_lex_val.str, tab);
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun /*
1010*4882a593Smuzhiyun * Compare two names. The characters '_', ' ', and '\t' are ignored
1011*4882a593Smuzhiyun * in the comparison.
1012*4882a593Smuzhiyun */
1013*4882a593Smuzhiyun int
xf86nameCompare(const char * s1,const char * s2)1014*4882a593Smuzhiyun xf86nameCompare(const char *s1, const char *s2)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun char c1, c2;
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun if (!s1 || *s1 == 0) {
1019*4882a593Smuzhiyun if (!s2 || *s2 == 0)
1020*4882a593Smuzhiyun return 0;
1021*4882a593Smuzhiyun else
1022*4882a593Smuzhiyun return 1;
1023*4882a593Smuzhiyun } else if (!s2 || *s2 == 0) {
1024*4882a593Smuzhiyun return -1;
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
1028*4882a593Smuzhiyun s1++;
1029*4882a593Smuzhiyun while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
1030*4882a593Smuzhiyun s2++;
1031*4882a593Smuzhiyun c1 = (isupper(*s1) ? tolower(*s1) : *s1);
1032*4882a593Smuzhiyun c2 = (isupper(*s2) ? tolower(*s2) : *s2);
1033*4882a593Smuzhiyun while (c1 == c2) {
1034*4882a593Smuzhiyun if (c1 == '\0')
1035*4882a593Smuzhiyun return 0;
1036*4882a593Smuzhiyun s1++;
1037*4882a593Smuzhiyun s2++;
1038*4882a593Smuzhiyun while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
1039*4882a593Smuzhiyun s1++;
1040*4882a593Smuzhiyun while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
1041*4882a593Smuzhiyun s2++;
1042*4882a593Smuzhiyun c1 = (isupper(*s1) ? tolower(*s1) : *s1);
1043*4882a593Smuzhiyun c2 = (isupper(*s2) ? tolower(*s2) : *s2);
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun return c1 - c2;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun char *
xf86addComment(char * cur,const char * add)1049*4882a593Smuzhiyun xf86addComment(char *cur, const char *add)
1050*4882a593Smuzhiyun {
1051*4882a593Smuzhiyun char *str;
1052*4882a593Smuzhiyun const char *cstr;
1053*4882a593Smuzhiyun int len, curlen, iscomment, hasnewline = 0, insnewline, endnewline;
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun if (add == NULL || add[0] == '\0')
1056*4882a593Smuzhiyun return cur;
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun if (cur) {
1059*4882a593Smuzhiyun curlen = strlen(cur);
1060*4882a593Smuzhiyun if (curlen)
1061*4882a593Smuzhiyun hasnewline = cur[curlen - 1] == '\n';
1062*4882a593Smuzhiyun eol_seen = 0;
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun else
1065*4882a593Smuzhiyun curlen = 0;
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun cstr = add;
1068*4882a593Smuzhiyun iscomment = 0;
1069*4882a593Smuzhiyun while (*cstr) {
1070*4882a593Smuzhiyun if (*cstr != ' ' && *cstr != '\t')
1071*4882a593Smuzhiyun break;
1072*4882a593Smuzhiyun ++cstr;
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun iscomment = (*cstr == '#');
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun len = strlen(add);
1077*4882a593Smuzhiyun endnewline = add[len - 1] == '\n';
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun insnewline = eol_seen || (curlen && !hasnewline);
1080*4882a593Smuzhiyun if (insnewline)
1081*4882a593Smuzhiyun len++;
1082*4882a593Smuzhiyun if (!iscomment)
1083*4882a593Smuzhiyun len++;
1084*4882a593Smuzhiyun if (!endnewline)
1085*4882a593Smuzhiyun len++;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun /* Allocate + 1 char for '\0' terminator. */
1088*4882a593Smuzhiyun str = realloc(cur, curlen + len + 1);
1089*4882a593Smuzhiyun if (!str)
1090*4882a593Smuzhiyun return cur;
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun cur = str;
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun if (insnewline)
1095*4882a593Smuzhiyun cur[curlen++] = '\n';
1096*4882a593Smuzhiyun if (!iscomment)
1097*4882a593Smuzhiyun cur[curlen++] = '#';
1098*4882a593Smuzhiyun strcpy(cur + curlen, add);
1099*4882a593Smuzhiyun if (!endnewline)
1100*4882a593Smuzhiyun strcat(cur, "\n");
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun return cur;
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun Bool
xf86getBoolValue(Bool * val,const char * str)1106*4882a593Smuzhiyun xf86getBoolValue(Bool *val, const char *str)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun if (!val || !str)
1109*4882a593Smuzhiyun return FALSE;
1110*4882a593Smuzhiyun if (*str == '\0') {
1111*4882a593Smuzhiyun *val = TRUE;
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun else {
1114*4882a593Smuzhiyun if (xf86nameCompare(str, "1") == 0)
1115*4882a593Smuzhiyun *val = TRUE;
1116*4882a593Smuzhiyun else if (xf86nameCompare(str, "on") == 0)
1117*4882a593Smuzhiyun *val = TRUE;
1118*4882a593Smuzhiyun else if (xf86nameCompare(str, "true") == 0)
1119*4882a593Smuzhiyun *val = TRUE;
1120*4882a593Smuzhiyun else if (xf86nameCompare(str, "yes") == 0)
1121*4882a593Smuzhiyun *val = TRUE;
1122*4882a593Smuzhiyun else if (xf86nameCompare(str, "0") == 0)
1123*4882a593Smuzhiyun *val = FALSE;
1124*4882a593Smuzhiyun else if (xf86nameCompare(str, "off") == 0)
1125*4882a593Smuzhiyun *val = FALSE;
1126*4882a593Smuzhiyun else if (xf86nameCompare(str, "false") == 0)
1127*4882a593Smuzhiyun *val = FALSE;
1128*4882a593Smuzhiyun else if (xf86nameCompare(str, "no") == 0)
1129*4882a593Smuzhiyun *val = FALSE;
1130*4882a593Smuzhiyun else
1131*4882a593Smuzhiyun return FALSE;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun return TRUE;
1134*4882a593Smuzhiyun }
1135