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     {NOTRAPSIGNALS, "notrapsignals"},
69     {DONTZAP, "dontzap"},
70     {DONTZOOM, "dontzoom"},
71     {DISABLEVIDMODE, "disablevidmodeextension"},
72     {ALLOWNONLOCAL, "allownonlocalxvidtune"},
73     {DISABLEMODINDEV, "disablemodindev"},
74     {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
75     {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
76     {OPTION, "option"},
77     {BLANKTIME, "blanktime"},
78     {STANDBYTIME, "standbytime"},
79     {SUSPENDTIME, "suspendtime"},
80     {OFFTIME, "offtime"},
81     {DEFAULTLAYOUT, "defaultserverlayout"},
82     {-1, ""},
83 };
84 
85 #define CLEANUP xf86freeFlags
86 
87 XF86ConfFlagsPtr
xf86parseFlagsSection(void)88 xf86parseFlagsSection(void)
89 {
90     int token;
91 
92     parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec)
93 
94         while ((token = xf86getToken(ServerFlagsTab)) != ENDSECTION) {
95         int hasvalue = FALSE;
96         int strvalue = FALSE;
97         int tokentype;
98 
99         switch (token) {
100         case COMMENT:
101             ptr->flg_comment = xf86addComment(ptr->flg_comment, xf86_lex_val.str);
102             break;
103             /*
104              * these old keywords are turned into standard generic options.
105              * we fall through here on purpose
106              */
107         case DEFAULTLAYOUT:
108             strvalue = TRUE;
109         case BLANKTIME:
110         case STANDBYTIME:
111         case SUSPENDTIME:
112         case OFFTIME:
113             hasvalue = TRUE;
114         case NOTRAPSIGNALS:
115         case DONTZAP:
116         case DONTZOOM:
117         case DISABLEVIDMODE:
118         case ALLOWNONLOCAL:
119         case DISABLEMODINDEV:
120         case MODINDEVALLOWNONLOCAL:
121         case ALLOWMOUSEOPENFAIL:
122         {
123             int i = 0;
124 
125             while (ServerFlagsTab[i].token != -1) {
126                 char *tmp;
127 
128                 if (ServerFlagsTab[i].token == token) {
129                     char *valstr = NULL;
130 
131                     tmp = strdup(ServerFlagsTab[i].name);
132                     if (hasvalue) {
133                         tokentype = xf86getSubToken(&(ptr->flg_comment));
134                         if (strvalue) {
135                             if (tokentype != STRING)
136                                 Error(QUOTE_MSG, tmp);
137                             valstr = xf86_lex_val.str;
138                         }
139                         else {
140                             if (tokentype != NUMBER)
141                                 Error(NUMBER_MSG, tmp);
142                             if (asprintf(&valstr, "%d", xf86_lex_val.num) == -1)
143                                 valstr = NULL;
144                         }
145                     }
146                     ptr->flg_option_lst = xf86addNewOption
147                         (ptr->flg_option_lst, tmp, valstr);
148                 }
149                 i++;
150             }
151         }
152             break;
153         case OPTION:
154             ptr->flg_option_lst = xf86parseOption(ptr->flg_option_lst);
155             break;
156 
157         case EOF_TOKEN:
158             Error(UNEXPECTED_EOF_MSG);
159             break;
160         default:
161             Error(INVALID_KEYWORD_MSG, xf86tokenString());
162             break;
163         }
164     }
165 
166 #ifdef DEBUG
167     printf("Flags section parsed\n");
168 #endif
169 
170     return ptr;
171 }
172 
173 #undef CLEANUP
174 
175 void
xf86printServerFlagsSection(FILE * f,XF86ConfFlagsPtr flags)176 xf86printServerFlagsSection(FILE * f, XF86ConfFlagsPtr flags)
177 {
178     XF86OptionPtr p;
179 
180     if ((!flags) || (!flags->flg_option_lst))
181         return;
182     p = flags->flg_option_lst;
183     fprintf(f, "Section \"ServerFlags\"\n");
184     if (flags->flg_comment)
185         fprintf(f, "%s", flags->flg_comment);
186     xf86printOptionList(f, p, 1);
187     fprintf(f, "EndSection\n\n");
188 }
189 
190 static XF86OptionPtr
addNewOption2(XF86OptionPtr head,char * name,char * _val,int used)191 addNewOption2(XF86OptionPtr head, char *name, char *_val, int used)
192 {
193     XF86OptionPtr new, old = NULL;
194 
195     /* Don't allow duplicates, free old strings */
196     if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
197         new = old;
198         free(new->opt_name);
199         free(new->opt_val);
200     }
201     else
202         new = calloc(1, sizeof(*new));
203     new->opt_name = name;
204     new->opt_val = _val;
205     new->opt_used = used;
206 
207     if (old)
208         return head;
209     return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) new));
210 }
211 
212 XF86OptionPtr
xf86addNewOption(XF86OptionPtr head,char * name,char * _val)213 xf86addNewOption(XF86OptionPtr head, char *name, char *_val)
214 {
215     return addNewOption2(head, name, _val, 0);
216 }
217 
218 void
xf86freeFlags(XF86ConfFlagsPtr flags)219 xf86freeFlags(XF86ConfFlagsPtr flags)
220 {
221     if (flags == NULL)
222         return;
223     xf86optionListFree(flags->flg_option_lst);
224     TestFree(flags->flg_comment);
225     free(flags);
226 }
227 
228 XF86OptionPtr
xf86optionListDup(XF86OptionPtr opt)229 xf86optionListDup(XF86OptionPtr opt)
230 {
231     XF86OptionPtr newopt = NULL;
232     char *_val;
233 
234     while (opt) {
235         _val = opt->opt_val ? strdup(opt->opt_val) : NULL;
236         newopt = xf86addNewOption(newopt, strdup(opt->opt_name), _val);
237         newopt->opt_used = opt->opt_used;
238         if (opt->opt_comment)
239             newopt->opt_comment = strdup(opt->opt_comment);
240         opt = opt->list.next;
241     }
242     return newopt;
243 }
244 
245 void
xf86optionListFree(XF86OptionPtr opt)246 xf86optionListFree(XF86OptionPtr opt)
247 {
248     XF86OptionPtr prev;
249 
250     while (opt) {
251         TestFree(opt->opt_name);
252         TestFree(opt->opt_val);
253         TestFree(opt->opt_comment);
254         prev = opt;
255         opt = opt->list.next;
256         free(prev);
257     }
258 }
259 
260 char *
xf86optionName(XF86OptionPtr opt)261 xf86optionName(XF86OptionPtr opt)
262 {
263     if (opt)
264         return opt->opt_name;
265     return 0;
266 }
267 
268 char *
xf86optionValue(XF86OptionPtr opt)269 xf86optionValue(XF86OptionPtr opt)
270 {
271     if (opt)
272         return opt->opt_val;
273     return 0;
274 }
275 
276 XF86OptionPtr
xf86newOption(char * name,char * value)277 xf86newOption(char *name, char *value)
278 {
279     XF86OptionPtr opt;
280 
281     opt = calloc(1, sizeof(*opt));
282     if (!opt)
283         return NULL;
284 
285     opt->opt_used = 0;
286     opt->list.next = 0;
287     opt->opt_name = name;
288     opt->opt_val = value;
289 
290     return opt;
291 }
292 
293 XF86OptionPtr
xf86nextOption(XF86OptionPtr list)294 xf86nextOption(XF86OptionPtr list)
295 {
296     if (!list)
297         return NULL;
298     return list->list.next;
299 }
300 
301 /*
302  * this function searches the given option list for the named option and
303  * returns a pointer to the option rec if found. If not found, it returns
304  * NULL
305  */
306 
307 XF86OptionPtr
xf86findOption(XF86OptionPtr list,const char * name)308 xf86findOption(XF86OptionPtr list, const char *name)
309 {
310     while (list) {
311         if (xf86nameCompare(list->opt_name, name) == 0)
312             return list;
313         list = list->list.next;
314     }
315     return NULL;
316 }
317 
318 /*
319  * this function searches the given option list for the named option. If
320  * found and the option has a parameter, a pointer to the parameter is
321  * returned.  If the option does not have a parameter an empty string is
322  * returned.  If the option is not found, a NULL is returned.
323  */
324 
325 const char *
xf86findOptionValue(XF86OptionPtr list,const char * name)326 xf86findOptionValue(XF86OptionPtr list, const char *name)
327 {
328     XF86OptionPtr p = xf86findOption(list, name);
329 
330     if (p) {
331         if (p->opt_val)
332             return p->opt_val;
333         else
334             return "";
335     }
336     return NULL;
337 }
338 
339 XF86OptionPtr
xf86optionListCreate(const char ** options,int count,int used)340 xf86optionListCreate(const char **options, int count, int used)
341 {
342     XF86OptionPtr p = NULL;
343     char *t1, *t2;
344     int i;
345 
346     if (count == -1) {
347         for (count = 0; options[count]; count++);
348     }
349     if ((count % 2) != 0) {
350         fprintf(stderr,
351                 "xf86optionListCreate: count must be an even number.\n");
352         return NULL;
353     }
354     for (i = 0; i < count; i += 2) {
355         t1 = strdup(options[i]);
356         t2 = strdup(options[i + 1]);
357         p = addNewOption2(p, t1, t2, used);
358     }
359 
360     return p;
361 }
362 
363 /* the 2 given lists are merged. If an option with the same name is present in
364  * both, the option from the user list - specified in the second argument -
365  * is used. The end result is a single valid list of options. Duplicates
366  * are freed, and the original lists are no longer guaranteed to be complete.
367  */
368 XF86OptionPtr
xf86optionListMerge(XF86OptionPtr head,XF86OptionPtr tail)369 xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail)
370 {
371     XF86OptionPtr a, b, ap = NULL, bp = NULL;
372 
373     a = tail;
374     b = head;
375     while (tail && b) {
376         if (xf86nameCompare(a->opt_name, b->opt_name) == 0) {
377             if (b == head)
378                 head = a;
379             else
380                 bp->list.next = a;
381             if (a == tail)
382                 tail = a->list.next;
383             else
384                 ap->list.next = a->list.next;
385             a->list.next = b->list.next;
386             b->list.next = NULL;
387             xf86optionListFree(b);
388             b = a->list.next;
389             bp = a;
390             a = tail;
391             ap = NULL;
392         }
393         else {
394             ap = a;
395             if (!(a = a->list.next)) {
396                 a = tail;
397                 bp = b;
398                 b = b->list.next;
399                 ap = NULL;
400             }
401         }
402     }
403 
404     if (head) {
405         for (a = head; a->list.next; a = a->list.next);
406         a->list.next = tail;
407     }
408     else
409         head = tail;
410 
411     return head;
412 }
413 
414 char *
xf86uLongToString(unsigned long i)415 xf86uLongToString(unsigned long i)
416 {
417     char *s;
418 
419     if (asprintf(&s, "%lu", i) == -1)
420         return NULL;
421     return s;
422 }
423 
424 XF86OptionPtr
xf86parseOption(XF86OptionPtr head)425 xf86parseOption(XF86OptionPtr head)
426 {
427     XF86OptionPtr option, cnew, old;
428     char *name, *comment = NULL;
429     int token;
430 
431     if ((token = xf86getSubToken(&comment)) != STRING) {
432         xf86parseError(BAD_OPTION_MSG);
433         free(comment);
434         return head;
435     }
436 
437     name = xf86_lex_val.str;
438     if ((token = xf86getSubToken(&comment)) == STRING) {
439         option = xf86newOption(name, xf86_lex_val.str);
440         option->opt_comment = comment;
441         if ((token = xf86getToken(NULL)) == COMMENT)
442             option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
443         else
444             xf86unGetToken(token);
445     }
446     else {
447         option = xf86newOption(name, NULL);
448         option->opt_comment = comment;
449         if (token == COMMENT)
450             option->opt_comment = xf86addComment(option->opt_comment, xf86_lex_val.str);
451         else
452             xf86unGetToken(token);
453     }
454 
455     old = NULL;
456 
457     /* Don't allow duplicates */
458     if (head != NULL && (old = xf86findOption(head, name)) != NULL) {
459         cnew = old;
460         free(option->opt_name);
461         TestFree(option->opt_val);
462         TestFree(option->opt_comment);
463         free(option);
464     }
465     else
466         cnew = option;
467 
468     if (old == NULL)
469         return ((XF86OptionPtr) xf86addListItem((glp) head, (glp) cnew));
470 
471     return head;
472 }
473 
474 void
xf86printOptionList(FILE * fp,XF86OptionPtr list,int tabs)475 xf86printOptionList(FILE * fp, XF86OptionPtr list, int tabs)
476 {
477     int i;
478 
479     if (!list)
480         return;
481     while (list) {
482         for (i = 0; i < tabs; i++)
483             fputc('\t', fp);
484         if (list->opt_val)
485             fprintf(fp, "Option	    \"%s\" \"%s\"", list->opt_name,
486                     list->opt_val);
487         else
488             fprintf(fp, "Option	    \"%s\"", list->opt_name);
489         if (list->opt_comment)
490             fprintf(fp, "%s", list->opt_comment);
491         else
492             fputc('\n', fp);
493         list = list->list.next;
494     }
495 }
496