ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/confparse.C
Revision: 1.7
Committed: Sun Sep 9 20:05:52 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +2 -1 lines
Log Message:
- changed configurations to the c++ stdlib
- more #defines to enum
- removed getopt.h and link.h from the system as they were unused
- reworked logstreams
- added an itoa with old syntax
- made klines objects
- moved some global variables into appropriate classes
- fixed boost.foreach's compiler workaround #if's
- allow other files to add exceptions with ADD_EXCEPTION
- changed mynick_t to c++ object
- moved servers.h out of atheme.h
- corrected PING from inspircd 1.2

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * confparse.C: Parsing of the configuration file.
3 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
4 pippijn 1.1 *
5 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 pippijn 1.1 */
7    
8 pippijn 1.7 static char const rcsid[] = "$Id: confparse.C,v 1.6 2007-08-30 19:56:24 pippijn Exp $";
9 pippijn 1.1
10     #include "atheme.h"
11 pippijn 1.7 #include "confparse.h"
12 pippijn 1.1
13 pippijn 1.4 static void
14     config_entry_free (config_entry_t *ceptr)
15     {
16     config_entry_t *nptr;
17    
18     for (; ceptr; ceptr = nptr)
19     {
20     nptr = ceptr->ce_next;
21     if (ceptr->ce_entries)
22     config_entry_free (ceptr->ce_entries);
23     if (ceptr->ce_varname)
24     sfree (ceptr->ce_varname);
25     if (ceptr->ce_vardata)
26     sfree (ceptr->ce_vardata);
27     delete ceptr;
28     }
29     }
30    
31     void
32     config_free (config_file_t *cfptr)
33     {
34     config_file_t *nptr;
35    
36     for (; cfptr; cfptr = nptr)
37     {
38     nptr = cfptr->cf_next;
39     if (cfptr->cf_entries)
40     config_entry_free (cfptr->cf_entries);
41     if (cfptr->cf_filename)
42     sfree (cfptr->cf_filename);
43     delete cfptr;
44     }
45     }
46    
47 pippijn 1.1
48     static void
49 pippijn 1.4 config_error (char const * const format, ...)
50 pippijn 1.1 {
51     va_list ap;
52     char buffer[1024];
53     char *ptr;
54    
55     va_start (ap, format);
56     vsnprintf (buffer, 1024, format, ap);
57     va_end (ap);
58     if ((ptr = strchr (buffer, '\n')) != NULL)
59     *ptr = '\0';
60     slog (LG_ERROR, "config_parse(): %s", buffer);
61     }
62    
63     static config_file_t *
64     config_parse (char *filename, char *confdata)
65     {
66     char *ptr;
67     char *start;
68     int linenumber = 1;
69     config_entry_t *curce;
70     config_entry_t **lastce;
71     config_entry_t *cursection;
72    
73     config_file_t *curcf;
74     config_file_t *lastcf;
75    
76 pippijn 1.4 lastcf = curcf = new config_file_t;
77 pippijn 1.1 curcf->cf_filename = sstrdup (filename);
78     lastce = &(curcf->cf_entries);
79     curce = NULL;
80     cursection = NULL;
81    
82     for (ptr = confdata; *ptr; ptr++)
83     {
84     switch (*ptr)
85     {
86     case '#':
87     while (*++ptr && (*ptr != '\n'))
88     ;
89     if (!*ptr)
90     {
91     /* make for(;;) exit from the loop */
92     ptr--;
93     continue;
94     }
95     linenumber++;
96     break;
97     case ';':
98     if (!curce)
99     {
100     config_error ("%s:%i Ignoring extra semicolon\n", filename, linenumber);
101     break;
102     }
103     if (!strcmp (curce->ce_varname, "include"))
104     {
105     config_file_t *cfptr;
106    
107     if (!curce->ce_vardata)
108     {
109     config_error ("%s:%i Ignoring \"include\": No filename given\n", filename, linenumber);
110     config_entry_free (curce);
111     curce = NULL;
112     continue;
113     }
114     if (strlen (curce->ce_vardata) > 255)
115     curce->ce_vardata[255] = '\0';
116     cfptr = config_load (curce->ce_vardata);
117     if (cfptr)
118     {
119     lastcf->cf_next = cfptr;
120     lastcf = cfptr;
121     }
122     config_entry_free (curce);
123     curce = NULL;
124     continue;
125     }
126     *lastce = curce;
127     lastce = &(curce->ce_next);
128     curce->ce_fileposend = (ptr - confdata);
129     curce = NULL;
130     break;
131     case '{':
132     if (!curce)
133     {
134     config_error ("%s:%i: No name for section start\n", filename, linenumber);
135     continue;
136     }
137     else if (curce->ce_entries)
138     {
139     config_error ("%s:%i: Ignoring extra section start\n", filename, linenumber);
140     continue;
141     }
142     curce->ce_sectlinenum = linenumber;
143     lastce = &(curce->ce_entries);
144     cursection = curce;
145     curce = NULL;
146     break;
147     case '}':
148     if (curce)
149     {
150     config_error ("%s:%i: Missing semicolon before close brace\n", filename, linenumber);
151     config_entry_free (curce);
152     config_free (curcf);
153     return NULL;
154     }
155     else if (!cursection)
156     {
157     config_error ("%s:%i: Ignoring extra close brace\n", filename, linenumber);
158     continue;
159     }
160     curce = cursection;
161     cursection->ce_fileposend = (ptr - confdata);
162     cursection = cursection->ce_prevlevel;
163     if (!cursection)
164     lastce = &(curcf->cf_entries);
165     else
166     lastce = &(cursection->ce_entries);
167     for (; *lastce; lastce = &((*lastce)->ce_next))
168     continue;
169     break;
170     case '/':
171     if (*(ptr + 1) == '/')
172     {
173     ptr += 2;
174     while (*ptr && (*ptr != '\n'))
175     ptr++;
176     if (!*ptr)
177     break;
178     ptr--; /* grab the \n on next loop thru */
179     continue;
180     }
181     else if (*(ptr + 1) == '*')
182     {
183     int commentstart = linenumber;
184    
185     for (ptr += 2; *ptr; ptr++)
186     {
187     if ((*ptr == '*') && (*(ptr + 1) == '/'))
188     {
189     ptr++;
190     break;
191     }
192     else if (*ptr == '\n')
193     linenumber++;
194     }
195     if (!*ptr)
196     {
197     config_error ("%s:%i Comment on this line does not end\n", filename, commentstart);
198     config_entry_free (curce);
199     config_free (curcf);
200     return NULL;
201     }
202     }
203     break;
204     case '\"':
205     start = ++ptr;
206     for (; *ptr; ptr++)
207     {
208     if ((*ptr == '\\') && (*(ptr + 1) == '\"'))
209     {
210     char *tptr = ptr;
211     while ((*tptr = *(tptr + 1)))
212     tptr++;
213     }
214     else if ((*ptr == '\"') || (*ptr == '\n'))
215     break;
216     }
217     if (!*ptr || (*ptr == '\n'))
218     {
219     config_error ("%s:%i: Unterminated quote found\n", filename, linenumber);
220     config_entry_free (curce);
221     config_free (curcf);
222     return NULL;
223     }
224     if (curce)
225     {
226     if (curce->ce_vardata)
227 pippijn 1.5 config_error ("%s:%i: Ignoring extra data\n", filename, linenumber);
228 pippijn 1.1 else
229     {
230     char *eptr;
231    
232 pippijn 1.6 curce->ce_vardata = salloc<char> (ptr - start + 1);
233 pippijn 1.1 strlcpy (curce->ce_vardata, start, ptr - start + 1);
234     curce->ce_vardatanum = strtol (curce->ce_vardata, &eptr, 0) & 0xffffffff; /* we only want 32bits and long is 64bit on 64bit compiles */
235     if (eptr != (curce->ce_vardata + (ptr - start)))
236 pippijn 1.5 curce->ce_vardatanum = 0;
237 pippijn 1.1 }
238     }
239     else
240     {
241 pippijn 1.4 curce = new config_entry_t;
242 pippijn 1.6 curce->ce_varname = salloc<char> (ptr - start + 1);
243 pippijn 1.1 strlcpy (curce->ce_varname, start, ptr - start + 1);
244     curce->ce_varlinenum = linenumber;
245     curce->ce_fileptr = curcf;
246     curce->ce_prevlevel = cursection;
247     curce->ce_fileposstart = (start - confdata);
248     }
249     break;
250     case '\n':
251     linenumber++;
252     break;
253     case '\t':
254     case ' ':
255     case '=':
256     case '\r':
257     break;
258     default:
259     if ((*ptr == '*') && (*(ptr + 1) == '/'))
260     {
261     config_error ("%s:%i Ignoring extra end comment\n", filename, linenumber);
262     ptr++;
263     break;
264     }
265     start = ptr;
266     for (; *ptr; ptr++)
267     {
268     if ((*ptr == ' ') || (*ptr == '\t') || (*ptr == '\n') || (*ptr == ';'))
269     break;
270     }
271     if (!*ptr)
272     {
273     if (curce)
274     config_error ("%s: Unexpected EOF for variable starting at %i\n", filename, curce->ce_varlinenum);
275     else if (cursection)
276     config_error ("%s: Unexpected EOF for section starting at %i\n", filename, curce->ce_sectlinenum);
277     else
278     config_error ("%s: Unexpected EOF.\n", filename);
279     config_entry_free (curce);
280     config_free (curcf);
281     return NULL;
282     }
283     if (curce)
284     {
285     if (curce->ce_vardata)
286     {
287     config_error ("%s:%i: Ignoring extra data\n", filename, linenumber);
288     }
289     else
290     {
291     char *eptr;
292    
293 pippijn 1.6 curce->ce_vardata = salloc<char> (ptr - start + 1);
294 pippijn 1.1 strlcpy (curce->ce_vardata, start, ptr - start + 1);
295     curce->ce_vardatanum = strtol (curce->ce_vardata, &eptr, 0) & 0xffffffff; /* we only want 32bits and long is 64bit on 64bit compiles */
296     if (eptr != (curce->ce_vardata + (ptr - start)))
297     {
298     curce->ce_vardatanum = 0;
299     }
300     }
301     }
302     else
303     {
304 pippijn 1.4 curce = new config_entry_t;
305 pippijn 1.6 curce->ce_varname = salloc<char> (ptr - start + 1);
306 pippijn 1.1 strlcpy (curce->ce_varname, start, ptr - start + 1);
307     curce->ce_varlinenum = linenumber;
308     curce->ce_fileptr = curcf;
309     curce->ce_prevlevel = cursection;
310     curce->ce_fileposstart = (start - confdata);
311     }
312     if ((*ptr == ';') || (*ptr == '\n'))
313     ptr--;
314     break;
315     } /* switch */
316     } /* for */
317     if (curce)
318     {
319     config_error ("%s: Unexpected EOF for variable starting on line %i\n", filename, curce->ce_varlinenum);
320     config_entry_free (curce);
321     config_free (curcf);
322     return NULL;
323     }
324     else if (cursection)
325     {
326     config_error ("%s: Unexpected EOF for section starting on line %i\n", filename, cursection->ce_sectlinenum);
327     config_free (curcf);
328     return NULL;
329     }
330     return curcf;
331     }
332    
333     config_file_t *
334     config_load (char *filename)
335     {
336     struct stat sb;
337     FILE *fd;
338     int ret;
339     char *buf = NULL;
340     config_file_t *cfptr;
341    
342     fd = fopen (filename, "rb");
343     if (!fd)
344     {
345     config_error ("Couldn't open \"%s\": %s\n", filename, strerror (errno));
346     return NULL;
347     }
348     if (stat (filename, &sb) == -1)
349     {
350     config_error ("Couldn't fstat \"%s\": %s\n", filename, strerror (errno));
351     fclose (fd);
352     return NULL;
353     }
354     if (!sb.st_size)
355     {
356     fclose (fd);
357     return NULL;
358     }
359 pippijn 1.6 buf = salloc<char> (sb.st_size + 1);
360 pippijn 1.1 if (buf == NULL)
361     {
362     config_error ("Out of memory trying to load \"%s\"\n", filename);
363     fclose (fd);
364     return NULL;
365     }
366     ret = fread (buf, 1, sb.st_size, fd);
367     if (ret != sb.st_size)
368     {
369     config_error ("Error reading \"%s\": %s\n", filename, ret == -1 ? strerror (errno) : strerror (EFAULT));
370 pippijn 1.4 sfree (buf);
371 pippijn 1.1 fclose (fd);
372     return NULL;
373     }
374     buf[ret] = '\0';
375     fclose (fd);
376     cfptr = config_parse (filename, buf);
377 pippijn 1.4 sfree (buf);
378 pippijn 1.1 return cfptr;
379     }
380    
381     config_entry_t *
382     config_find (config_entry_t *ceptr, char *name)
383     {
384     for (; ceptr; ceptr = ceptr->ce_next)
385     if (!strcmp (ceptr->ce_varname, name))
386     break;
387     return ceptr;
388     }
389    
390     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
391     * vim:ts=8
392     * vim:sw=8
393     * vim:noexpandtab
394     */