syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / com32 / modules / readconfig.c
1 #ident "$Id: readconfig.c,v 1.7 2005/01/21 01:35:33 hpa Exp $"
2 /* ----------------------------------------------------------------------- *
3  *   
4  *   Copyright 2004 H. Peter Anvin - All Rights Reserved
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9  *   Boston MA 02111-1307, USA; either version 2 of the License, or
10  *   (at your option) any later version; incorporated herein by reference.
11  *
12  * ----------------------------------------------------------------------- */
13
14 #define _GNU_SOURCE             /* Needed for asprintf() on Linux */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <minmax.h>
19 #include <alloca.h>
20 #ifdef __COM32__
21 # include <com32.h>
22 #endif
23
24 #include "menu.h"
25
26 int nentries  = 0;
27 int defentry  = 0;
28 int allowedit = 1;              /* Allow edits of the command line */
29 int timeout   = 0;
30
31 char *menu_title  = "";
32 char *ontimeout   = NULL;
33
34 char *menu_master_passwd = NULL;
35
36 struct menu_entry menu_entries[MAX_ENTRIES];
37 struct menu_entry *menu_hotkeys[256];
38
39 #define astrdup(x) ({ char *__x = (x); \
40                       size_t __n = strlen(__x) + 1; \
41                       char *__p = alloca(__n); \
42                       if ( __p ) memcpy(__p, __x, __n); \
43                       __p; })
44
45 const char *ipappends[32];
46                       
47 static void
48 get_ipappend(void)
49 {
50 #ifdef __COM32__
51   static com32sys_t r;
52   uint16_t *ipp;
53   int i;
54   int nipappends;
55
56   r.eax.w[0] = 0x000F;
57   __intcall(0x22, &r, &r);
58
59   nipappends = min(r.ecx.w[0], 32);
60   ipp        = MK_PTR(r.es, r.ebx.w[0]);
61   for ( i = 0 ; i < nipappends ; i++ ) {
62     ipappends[i] = MK_PTR(r.es, *ipp++);
63   }
64 #else
65   ipappends[0] = "ip=foo:bar:baz:quux";
66   ipappends[1] = "BOOTIF=01-aa-bb-cc-dd-ee-ff";
67 #endif
68 }
69
70 static const char *
71 get_config(void)
72 {
73 #ifdef __COM32__
74   static com32sys_t r;
75   
76   r.eax.w[0] = 0x000E;
77   __intcall(0x22, &r, &r);
78
79   return MK_PTR(r.es, r.ebx.w[0]);
80 #else
81   return "syslinux.cfg";        /* Dummy default name */
82 #endif
83 }
84   
85 #define MAX_LINE 512
86
87 static char *
88 skipspace(char *p)
89 {
90   while ( *p && *p <= ' ' )
91     p++;
92   
93   return p;
94 }
95
96 /* Check to see if we are at a certain keyword (case insensitive) */
97 static int
98 looking_at(const char *line, const char *kwd)
99 {
100   const char *p = line;
101   const char *q = kwd;
102
103   while ( *p && *q && ((*p^*q) & ~0x20) == 0 ) {
104     p++;
105     q++;
106   }
107
108   if ( *q )
109     return 0;                   /* Didn't see the keyword */
110
111   return *p <= ' ';             /* Must be EOL or whitespace */
112 }
113
114 struct labeldata {
115   char *label;
116   char *kernel;
117   char *append;
118   char *menulabel;
119   char *passwd;
120   unsigned int ipappend;
121   unsigned int menuhide;
122   unsigned int menudefault;
123 };
124
125 static void
126 record(struct labeldata *ld, char *append)
127 {
128   char ipoptions[256], *ipp;
129   int i;
130   struct menu_entry *me = &menu_entries[nentries];
131
132   if ( ld->label ) {
133     char *a, *s;
134     me->displayname = ld->menulabel ? ld->menulabel : ld->label;
135     me->label       = ld->label;
136     me->passwd      = ld->passwd;
137     me->hotkey = 0;
138
139     if ( ld->menulabel ) {
140       unsigned char *p = (unsigned char *)strchr(ld->menulabel, '^');
141       if ( p && p[1] ) {
142         int hotkey = p[1] & ~0x20;
143         if ( !menu_hotkeys[hotkey] ) {
144           me->hotkey = hotkey;
145         }
146       }
147     }
148
149     ipp = ipoptions;
150     *ipp = '\0';
151     for ( i = 0 ; i < 32 ; i++ ) {
152       if ( (ld->ipappend & (1U << i)) && ipappends[i] )
153         ipp += sprintf(ipp, " %s", ipappends[i]);
154     }
155
156     a = ld->append;
157     if ( !a ) a = append;
158     if ( !a || (a[0] == '-' && !a[1]) ) a = "";
159     s = a[0] ? " " : "";
160     asprintf(&me->cmdline, "%s%s%s%s", ld->kernel, ipoptions, s, a);
161
162     ld->label = NULL;
163     free(ld->kernel);
164     if ( ld->append )
165       free(ld->append);
166
167     if ( !ld->menuhide ) {
168       if ( me->hotkey )
169         menu_hotkeys[me->hotkey] = me;
170
171       if ( ld->menudefault )
172         defentry = nentries;
173
174       nentries++;
175     }
176   }
177 }
178
179 void parse_config(const char *filename)
180 {
181   char line[MAX_LINE], *p;
182   FILE *f;
183   char *append = NULL;
184   static struct labeldata ld;
185
186   get_ipappend();
187
188   if ( !filename )
189     filename = get_config();
190
191   f = fopen(filename, "r");
192   if ( !f )
193     return;
194
195   while ( fgets(line, sizeof line, f) ) {
196     p = strchr(line, '\r');
197     if ( p )
198       *p = '\0';
199     p = strchr(line, '\n');
200     if ( p )
201       *p = '\0';
202
203     p = skipspace(line);
204
205     if ( looking_at(p, "menu") ) {
206       p = skipspace(p+4);
207       
208       if ( looking_at(p, "title") ) {
209         menu_title = strdup(skipspace(p+5));
210       } else if ( looking_at(p, "label") ) {
211         if ( ld.label )
212           ld.menulabel = strdup(skipspace(p+5));
213       } else if ( looking_at(p, "default") ) {
214         ld.menudefault = 1;
215       } else if ( looking_at(p, "hide") ) {
216         ld.menuhide = 1;
217       } else if ( looking_at(p, "passwd") ) {
218         ld.passwd = strdup(skipspace(p+6));
219       } else if ( looking_at(p, "master") ) {
220         p = skipspace(p+6);
221         if ( looking_at (p, "passwd") ) {
222           menu_master_passwd = strdup(skipspace(p+6));
223         }
224       } else {
225         /* Unknown, ignore for now */
226       }
227     } else if ( looking_at(p, "append") ) {
228       char *a = strdup(skipspace(p+6));
229       if ( ld.label )
230         ld.append = a;
231       else
232         append = a;
233     } else if ( looking_at(p, "label") ) {
234       p = skipspace(p+5);
235       record(&ld, append);
236       ld.label     = strdup(p);
237       ld.kernel    = strdup(p);
238       ld.append    = NULL;
239       ld.menulabel = NULL;
240       ld.ipappend  = ld.menudefault = ld.menuhide = 0;
241     } else if ( looking_at(p, "kernel") ) {
242       if ( ld.label ) {
243         free(ld.kernel);
244         ld.kernel = strdup(skipspace(p+6));
245       }
246     } else if ( looking_at(p, "timeout") ) {
247       timeout = atoi(skipspace(p+7));
248     } else if ( looking_at(p, "ontimeout") ) {
249       ontimeout = strdup(skipspace(p+9));
250     } else if ( looking_at(p, "allowoptions") ) {
251       allowedit = atoi(skipspace(p+12));
252     } else if ( looking_at(p, "ipappend") ) {
253       ld.ipappend = atoi(skipspace(p+8));
254     }
255   }
256   
257   record(&ld, append);
258   fclose(f);
259 }