1 /*
2  * Copyright (c) 1997  Metro Link Incorporated
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  * Except as contained in this notice, the name of the Metro Link shall not be
23  * used in advertising or otherwise to promote the sale, use or other dealings
24  * in this Software without prior written authorization from Metro Link.
25  *
26  */
27 /*
28  * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29  *
30  * Permission is hereby granted, free of charge, to any person obtaining a
31  * copy of this software and associated documentation files (the "Software"),
32  * to deal in the Software without restriction, including without limitation
33  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34  * and/or sell copies of the Software, and to permit persons to whom the
35  * Software is furnished to do so, subject to the following conditions:
36  *
37  * The above copyright notice and this permission notice shall be included in
38  * all copies or substantial portions of the Software.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
43  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46  * OTHER DEALINGS IN THE SOFTWARE.
47  *
48  * Except as contained in this notice, the name of the copyright holder(s)
49  * and author(s) shall not be used in advertising or otherwise to promote
50  * the sale, use or other dealings in this Software without prior written
51  * authorization from the copyright holder(s) and author(s).
52  */
53 
54 #ifdef HAVE_XORG_CONFIG_H
55 #include <xorg-config.h>
56 #endif
57 
58 #include "xf86Parser.h"
59 #include "xf86tokens.h"
60 #include "Configint.h"
61 #include <X11/Xfuncproto.h>
62 #include "Xprintf.h"
63 #include "optionstr.h"
64 
65 
66 static const xf86ConfigSymTabRec ServerFlagsTab[] = {
67     {ENDSECTION, "endsection"},
68     {DONTZAP, "dontzap"},
69     {DONTZOOM, "dontzoom"},
70     {DISABLEVIDMODE, "disablevidmodeextension"},
71     {ALLOWNONLOCAL, "allownonlocalxvidtune"},
72     {DISABLEMODINDEV, "disablemodindev"},
73     {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
74     {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
75     {OPTION, "option"},
76     {BLANKTIME, "blanktime"},
77     {STANDBYTIME, "standbytime"},
78     {SUSPENDTIME, "suspendtime"},
79     {OFFTIME, "offtime"},
80     {DEFAULTLAYOUT, "defaultserverlayout"},
81     {-1, ""},
82 };
83 
84 #define CLEANUP xf86freeFlags
85 
86 XF86ConfFlagsPtr
xf86parseFlagsSection(void)87 xf86parseFlagsSection(void)
88 {
89     int token;
90 
91     parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
92 
93         while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
94         int hasvalue = FALSE;
95         int strvalue = FALSE;
96         int tokentype;
97 
98         switch (token) {
99         case COMMENT:
100             ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
101             break;
102             /*
103              * these old keywords are turned into standard generic options.
104              * we fall through here on purpose
105              */
106         case DEFAULTLAYOUT:
107             strvalue = TRUE;
108         case BLANKTIME:
109         case STANDBYTIME:
110         case SUSPENDTIME:
111         case OFFTIME:
112             hasvalue = TRUE;
113         case DONTZAP:
114         case DONTZOOM:
115         case DISABLEVIDMODE:
116         case ALLOWNONLOCAL:
117         case DISABLEMODINDEV:
118         case MODINDEVALLOWNONLOCAL:
119         case ALLOWMOUSEOPENFAIL:
120         {
121             int i = 0;
122 
123             while (ServerFlagsTab[i].token != -1) {
124                 char *tmp;
125 
126                 if (ServerFlagsTab[i].token == token) {
127                     char *valstr = NULL;
128 
129                     tmp = strdup(ServerFlagsTab[i].name);
130                     if (hasvalue) {
131                         tokentype = xf86getSubToken(&(ptr->flg_comment));
132                         if (strvalue) {
133                             if (tokentype != STRING)
134                                 Error(QUOTE_MSG, tmp);
135                             valstr = xf86_lex_val.str;
136                         }
137                         else {
138                             if (tokentype != NUMBER)
139                                 Error(NUMBER_MSG, tmp);
140                             if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
141                                 valstr = NULL;
142                         }
143                     }
144                     ptr->flg_option_lst = xf86addNewOption
145                         (ptr->flg_option_lst, tmp, valstr);
146                 }
147                 i++;
148             }
149         }
150             break;
151         case OPTION:
152             ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
153             break;
154 
155         case EOF_TOKEN:
156             Error(UNEXPECTED_EOF_MSG);
157             break;
158         default:
159             Error(INVALID_KEYWORD_MSG, xf86tokenString());
160             break;
161         }
162     }
163 
164 #ifdef DEBUG
165     printf("Flags section parsed\n");
166 #endif
167 
168     return ptr;
169 }
170 
171 #undef CLEANUP
172 
173 void
xf86printServerFlagsSection(FILE * f,XF86ConfFlagsPtr flags)174 xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
175 {
176     XF86OptionPtr p;
177 
178     if ((!flags) || (!flags->flg_option_lst))
179         return;
180     p = flags->flg_option_lst;
181     fprintf(f, "Section \"ServerFlags\"\n");
182     if (flags->flg_comment)
183         fprintf(f, "%s", flags->flg_comment);
184     xf86printOptionList(f, p, 1);
185     fprintf(f, "EndSection\n\n");
186 }
187 
188 static XF86OptionPtr
addNewOption2(XF86OptionPtr head,char * name,char * _val,int used)189 addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
190 {
191     XF86OptionPtr new, old = NULL;
192 
193     /* Don't allow duplicates, free old strings */
194     if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
195         new = old;
196         free(new->opt_name);
197         free(new->opt_val);
198     }
199     else
200         new = calloc(1, sizeof(*new));
201     new->opt_name = name;
202     new->opt_val = _val;
203     new->opt_used = used;
204 
205     if (old)
206         return head;
207     return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
208 }
209 
210 XF86OptionPtr
xf86addNewOption(XF86OptionPtr head,char * name,char * _val)211 xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
212 {
213     return addNewOption2(head, name, _val, 0);
214 }
215 
216 void
xf86freeFlags(XF86ConfFlagsPtr flags)217 xf86freeFlags(XF86ConfFlagsPtr flags)
218 {
219     if (flags == NULL)
220         return;
221     xf86optionListFree(flags->flg_option_lst);
222     TestFree(flags->flg_comment);
223     free(flags);
224 }
225 
226 XF86OptionPtr
xf86optionListDup(XF86OptionPtr opt)227 xf86optionListDup(XF86OptionPtr opt)
228 {
229     XF86OptionPtr newopt = NULL;
230     char *_val;
231 
232     while (opt) {
233         _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
234         newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
235         newopt->opt_used = opt->opt_used;
236         if (opt->opt_comment)
237             newopt->opt_comment = strdup(opt->opt_comment);
238         opt = opt->list.next;
239     }
240     return newopt;
241 }
242 
243 void
xf86optionListFree(XF86OptionPtr opt)244 xf86optionListFree(XF86OptionPtr opt)
245 {
246     XF86OptionPtr prev;
247 
248     while (opt) {
249         TestFree(opt->opt_name);
250         TestFree(opt->opt_val);
251         TestFree(opt->opt_comment);
252         prev = opt;
253         opt = opt->list.next;
254         free(prev);
255     }
256 }
257 
258 char *
xf86optionName(XF86OptionPtr opt)259 xf86optionName(XF86OptionPtr opt)
260 {
261     if (opt)
262         return opt->opt_name;
263     return 0;
264 }
265 
266 char *
xf86optionValue(XF86OptionPtr opt)267 xf86optionValue(XF86OptionPtr opt)
268 {
269     if (opt)
270         return opt->opt_val;
271     return 0;
272 }
273 
274 XF86OptionPtr
xf86newOption(char * name,char * value)275 xf86newOption(char *name, char *value)
276 {
277     XF86OptionPtr opt;
278 
279     opt = calloc(1, sizeof(*opt));
280     if (!opt)
281         return NULL;
282 
283     opt->opt_used = 0;
284     opt->list.next = 0;
285     opt->opt_name = name;
286     opt->opt_val = value;
287 
288     return opt;
289 }
290 
291 XF86OptionPtr
xf86nextOption(XF86OptionPtr list)292 xf86nextOption(XF86OptionPtr list)
293 {
294     if (!list)
295         return NULL;
296     return list->list.next;
297 }
298 
299 /*
300  * this function searches the given option list for the named option and
301  * returns a pointer to the option rec if found. If not found, it returns
302  * NULL
303  */
304 
305 XF86OptionPtr
xf86findOption(XF86OptionPtr list,const char * name)306 xf86findOption(XF86OptionPtr list, const char *name)
307 {
308     while (list) {
309         if (xf86nameCompare(list->opt_name, name) == 0)
310             return list;
311         list = list->list.next;
312     }
313     return NULL;
314 }
315 
316 /*
317  * this function searches the given option list for the named option. If
318  * found and the option has a parameter, a pointer to the parameter is
319  * returned.  If the option does not have a parameter an empty string is
320  * returned.  If the option is not found, a NULL is returned.
321  */
322 
323 const char *
xf86findOptionValue(XF86OptionPtr list,const char * name)324 xf86findOptionValue(XF86OptionPtr list, const char *name)
325 {
326     XF86OptionPtr p = xf86findOption(list, name);
327 
328     if (p) {
329         if (p->opt_val)
330             return p->opt_val;
331         else
332             return "";
333     }
334     return NULL;
335 }
336 
337 XF86OptionPtr
xf86optionListCreate(const char ** options,int count,int used)338 xf86optionListCreate(const char **options, int count, int used)
339 {
340     XF86OptionPtr p = NULL;
341     char *t1, *t2;
342     int i;
343 
344     if (count == -1) {
345         for (count = 0; options[count]; count++);
346     }
347     if ((count % 2) != 0) {
348         fprintf(stderr,
349                 "xf86optionListCreate: count must be an even number.\n");
350         return NULL;
351     }
352     for (i = 0; i < count; i += 2) {
353         t1 = strdup(options[i]);
354         t2 = strdup(options[i + 1]);
355         p = addNewOption2(p, t1, t2, used);
356     }
357 
358     return p;
359 }
360 
361 /* the 2 given lists are merged. If an option with the same name is present in
362  * both, the option from the user list - specified in the second argument -
363  * is used. The end result is a single valid list of options. Duplicates
364  * are freed, and the original lists are no longer guaranteed to be complete.
365  */
366 XF86OptionPtr
xf86optionListMerge(XF86OptionPtr head,XF86OptionPtr tail)367 xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
368 {
369     XF86OptionPtr a, b, ap = NULL, bp = NULL;
370 
371     a = tail;
372     b = head;
373     while (tail && b) {
374         if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
375             if (b == head)
376                 head = a;
377             else
378                 bp->list.next = a;
379             if (a == tail)
380                 tail = a->list.next;
381             else
382                 ap->list.next = a->list.next;
383             a->list.next = b->list.next;
384             b->list.next = NULL;
385             xf86optionListFree(b);
386             b = a->list.next;
387             bp = a;
388             a = tail;
389             ap = NULL;
390         }
391         else {
392             ap = a;
393             if (!(a = a->list.next)) {
394                 a = tail;
395                 bp = b;
396                 b = b->list.next;
397                 ap = NULL;
398             }
399         }
400     }
401 
402     if (head) {
403         for (a = head; a->list.next; a = a->list.next);
404         a->list.next = tail;
405     }
406     else
407         head = tail;
408 
409     return head;
410 }
411 
412 char *
xf86uLongToString(unsigned long i)413 xf86uLongToString(unsigned long i)
414 {
415     char *s;
416 
417     if (asprintf(&s, "%lu", i) == -1)
418         return NULL;
419     return s;
420 }
421 
422 XF86OptionPtr
xf86parseOption(XF86OptionPtr head)423 xf86parseOption(XF86OptionPtr head)
424 {
425     XF86OptionPtr option, cnew, old;
426     char *name, *comment = NULL;
427     int token;
428 
429     if ((token = xf86getSubToken(&comment)) != STRING) {
430         xf86parseError(BAD_OPTION_MSG);
431         free(comment);
432         return head;
433     }
434 
435     name = xf86_lex_val.str;
436     if ((token = xf86getSubToken(&comment)) == STRING) {
437         option = xf86newOption(name, xf86_lex_val.str);
438         option->opt_comment = comment;
439         if ((token = xf86getToken(NULL)) == COMMENT)
440             option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
441         else
442             xf86unGetToken(token);
443     }
444     else {
445         option = xf86newOption(name, NULL);
446         option->opt_comment = comment;
447         if (token == COMMENT)
448             option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
449         else
450             xf86unGetToken(token);
451     }
452 
453     old = NULL;
454 
455     /* Don't allow duplicates */
456     if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
457         cnew = old;
458         free(option->opt_name);
459         TestFree(option->opt_val);
460         TestFree(option->opt_comment);
461         free(option);
462     }
463     else
464         cnew = option;
465 
466     if (old == NULL)
467         return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
468 
469     return head;
470 }
471 
472 void
xf86printOptionList(FILE * fp,XF86OptionPtr list,int tabs)473 xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
474 {
475     int i;
476 
477     if (!list)
478         return;
479     while (list) {
480         for (i = 0; i < tabs; i++)
481             fputc('\t', fp);
482         if (list->opt_val)
483             fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name,
484                     list->opt_val);
485         else
486             fprintf(fp, "Option	    \"%s\"", list->opt_name);
487         if (list->opt_comment)
488             fprintf(fp, "%s", list->opt_comment);
489         else
490             fputc('\n', fp);
491         list = list->list.next;
492     }
493 }
494