1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5 
6 #include "configlib.h"
7 
8 #define MAXLINE 1024
9 
parseConfig(char * filename)10 config_t *parseConfig ( char *filename )
11 {
12   FILE *configFile;
13   int size, i;
14   int bufsize = 256;
15   char c;
16   char *buf;
17   config_t *config;
18   confObj_t *confObj;
19 
20   if ( (configFile = fopen( filename, "r" )) == NULL )
21   {
22     fprintf(stderr, "Unable to open config file.\n");
23     return NULL;
24   }
25 
26   config = (config_t *)calloc(1, sizeof(config_t));
27   config->next = NULL;
28   config->conf = NULL;
29 
30   buf = (char *)calloc(bufsize, 1);
31   memset(buf, 0, bufsize);
32 
33   i = 0;
34   while (feof(configFile) == 0)
35   {
36     size = fread(&c, 1, 1, configFile);
37     if (size <= 0)
38     {
39       if (feof(configFile))
40         break;
41       else
42       {
43         printf("Error reading config file.\n");
44         return NULL;
45       }
46     }
47 
48     if (bufsize < i + 64)
49     {
50       bufsize += 64;
51       buf = realloc(buf, bufsize);
52     }
53 
54     switch (c)
55     {
56       case '\n':
57         buf[i] = 0;
58         if (_conf_is_valid_line(buf, i))
59         {
60           if ( (confObj = _conf_parseLine(buf)) != NULL)
61             _conf_setValue(config, confObj);
62         }
63 
64         i = 0;
65         break;
66 
67       default:
68         buf[i++] = c;
69     }
70   }
71   free(buf); /* Thx dunky */
72   return config;
73 }
74 
75 /* Warning, the content of the line could be modified by
76  * this function.
77  */
_conf_is_valid_line(char * line,unsigned int size)78 int _conf_is_valid_line ( char *line, unsigned int size )
79 {
80   int i;
81   int state = 0;
82 
83   if (size <= 0)
84     return 0;
85 
86   for (i = 0; i < size; i++)
87   {
88     if (line[i] != ' ')
89     {
90       if ( ((line[i] >= 'a') && (line[i] <= 'z')) ||
91            ((line[i] >= 'A') && (line[i] <= 'Z'))
92          )
93         break;
94       else
95         return 0;
96     }
97   }
98 
99   for (i = (size - 1); i >= 0; i--)
100   {
101     if (line[i] == '/')
102     {
103       if (state == 0)
104       {
105         state = 1;
106       } else {
107         line[i] = 0;
108       }
109     } else if (line[i] == '\"')
110       return 1;
111 
112   }
113 
114   return 1;
115 }
116 
_conf_parseLine(char * line)117 confObj_t *_conf_parseLine( char *line )
118 {
119   int i, j, k;
120   int linelen, len;
121   int quote, space, state;
122   char *buf;
123   char c;
124   void *ptr;
125   confObj_t *confObj;
126 
127   if ((line == NULL) || (*line == '\0'))
128     return NULL;
129 
130   linelen = strlen(line) + 1;
131   confObj = (confObj_t *)calloc(1, sizeof(confObj_t));
132   buf = calloc(linelen, 1);
133 
134   for (i = 0, quote = 0, space = 0, j = 0, state = 0; i < linelen; i++)
135   {
136     c = line[i];
137 
138     switch (c)
139     {
140       case '"':
141         quote ^= 1;
142         break;
143 
144       case '=':
145         if (j == 0)
146         {
147           fprintf(stderr, "CONFIG ERROR: Incorrect Line. Should not start with '='\n");
148           free(confObj);
149           free(buf);
150           return NULL;
151         }
152 
153         state = 1;
154         buf[j] = 0;
155         j = 0;
156         len = strlen(buf);
157 
158         /* Strip ending spaces */
159         for (k = len-1; k > 0 && buf[k] == ' '; k--)
160           if (buf[k] == ' ') continue;
161 
162         buf[k+1] = 0;
163         confObj->var = strdup(buf);
164         break;
165 
166       default:
167         if ((c == ' ') && (space == 0))
168           space = 1;
169         else if (c != ' ')
170           space = 0;
171 
172         if ((space == 1) && (quote == 0))
173           break; /* Discards */
174         if ((space == 1) && (j == 0))
175           break; /* Discards */
176 
177         buf[j++] = c;
178     }
179   }
180 
181   if ((j == 0) || (confObj->var == NULL))
182   {
183     fprintf(stderr, "Invalid entry: variable defined, but without val.\n");
184     free(confObj);
185     free(buf);
186     return NULL;
187   }
188 
189   buf[j] = 0;
190 
191   len = strlen(buf);
192 
193   /* Ugly strip */
194   for (k = len-1; k > 0 && buf[k] == ' '; k--);
195 
196   buf[k+1] = 0;
197 
198   len = strlen(buf);
199   ptr = buf;
200 
201   for (k = 0; k < len && buf[k] == ' '; k++) buf++;
202 
203   confObj->val = strdup(buf);
204 
205   free(ptr);
206 
207   return confObj;
208 }
209 
_conf_setValue(config_t * start,confObj_t * confObj)210 config_t *_conf_setValue( config_t *start, confObj_t *confObj )
211 {
212   config_t *work;
213   config_t *last;
214 
215   if (start == NULL)
216   {
217     fprintf(stderr, "Error: config start is NULL.\n");
218     return NULL;
219   }
220 
221   if (start->conf != NULL)
222   {
223     work = (config_t *)calloc(1, sizeof(config_t));
224     work->next = NULL;
225     work->conf = confObj;
226     last = start;
227     while (last->next != NULL)
228       last = last->next;
229     last->next = work;
230   } else
231     start->conf = confObj;
232 
233   return start;
234 }
235 
conf_setValue(config_t ** start,const char * var,const char * val)236 void conf_setValue( config_t **start, const char *var, const char *val )
237 {
238   confObj_t *obj;
239 
240   if ((var == NULL) || (val == NULL))
241     return;
242 
243   if ((*start) == NULL)
244   {
245     (*start) = (config_t *)calloc(1, sizeof(config_t));
246     (*start)->next = NULL;
247     (*start)->conf = NULL;
248   }
249 
250   obj = (confObj_t *)calloc(1, sizeof(confObj_t));
251   obj->var = strdup(var);
252   obj->val = strdup(val);
253 
254   (*start) = _conf_setValue( *start, obj );
255 }
256 
mystr_eq(char * s1,char * s2)257 int mystr_eq(char *s1, char *s2)
258 {
259   int len1, len2;
260   if ((s1 == NULL) || (s2 == NULL))
261     return 0;
262 
263   len1 = strlen(s1);
264   len2 = strlen(s2);
265 
266   if (len1 != len2)
267     return 0;
268 
269   if (strncmp(s1, s2, len1) == 0)
270     return 1;
271 
272   return 0;
273 }
274 
_conf_getValue(config_t * start,char * var,char ** dest)275 config_t *_conf_getValue( config_t *start, char *var, char **dest )
276 {
277   while (start != NULL)
278   {
279     if ((start->conf == NULL) || (start->conf->var == NULL))
280     {
281       *dest = NULL;
282       return NULL;
283     }
284 
285     if (mystr_eq(start->conf->var, var) == 1)
286     {
287       *dest = strdup(start->conf->val);
288       return start->next;
289     }
290     start = start->next;
291   }
292 
293   *dest = NULL;
294   return NULL;
295 }
296 
_conf_printConfig(config_t * start)297 void _conf_printConfig ( config_t *start )
298 {
299   while (start != NULL)
300   {
301     printf("var: `%s' val: `%s'\n", start->conf->var, start->conf->val);
302     start = start->next;
303   }
304 }
305 
_conf_freeConfig(config_t * start)306 void _conf_freeConfig( config_t *start )
307 {
308   config_t *old;
309 
310   while (start != NULL)
311   {
312     if (start->conf != NULL)
313     {
314       if (start->conf->var != NULL)
315         free(start->conf->var);
316       if (start->conf->val != NULL)
317         free(start->conf->val);
318 
319       free(start->conf);
320     }
321     old = start;
322     start = start->next;
323     free(old);
324   }
325 }
326 
_conf_writeConfig(FILE * stream,config_t * config)327 void _conf_writeConfig( FILE *stream, config_t *config )
328 {
329   char line[MAXLINE];
330   char *lastvar = NULL;
331   int len;
332 
333   fwrite("// Configuration file for cPige written using GUI\n", 50, 1, stream);
334   fwrite("// http://ed.zehome.com/?page=cpige-en\n", 39, 1, stream);
335 
336   while (config != NULL)
337   {
338     if (config->conf != NULL)
339     {
340       if ((config->conf->var) && (config->conf->val))
341       {
342         if (mystr_eq(lastvar, config->conf->var) == 0)
343           fwrite("\n", 1, 1, stream);
344 
345         len = snprintf(line, MAXLINE, "%s = \"%s\"\n", config->conf->var, config->conf->val);
346         fwrite(line, len, 1, stream);
347         lastvar = config->conf->var;
348       }
349     }
350 
351     config = config->next;
352   }
353 }
354 
set_str_from_conf(config_t * config,char * type,char ** value,char * def,char * errMsg,int exit_n)355 void set_str_from_conf(config_t *config, char *type, char **value, char *def, char *errMsg, int exit_n)
356 {
357   _conf_getValue(config, type, value);
358 
359   if (*value == NULL)
360   {
361     fprintf(stderr, errMsg);
362     if (def != NULL)
363       *value = strdup(def);
364     if (exit_n > 0)
365     {
366       fprintf(stderr, "Will quit with exit code %d\n", exit_n);
367       exit(exit_n);
368     }
369   }
370 }
371 
set_int_from_conf(config_t * config,char * type,int * value,int def,char * errMsg,int exit_n)372 void set_int_from_conf(config_t *config, char *type, int *value, int def, char *errMsg, int exit_n)
373 {
374   char *tmp;
375   _conf_getValue(config, type, &tmp);
376 
377   if ( tmp == NULL )
378   {
379     fprintf(stderr, errMsg);
380     *value = def;
381     if (exit_n > 0)
382     {
383       fprintf(stderr, "Will quit with exit code %d\n", exit_n);
384       exit(exit_n);
385     }
386   } else {
387     *value = atoi(tmp);
388     free(tmp);
389   }
390 }
391 
set_bool_from_conf(config_t * config,char * type,int * value,int def,char * errMsg,int exit_n)392 void set_bool_from_conf(config_t *config, char *type, int *value, int def, char *errMsg, int exit_n)
393 {
394   char *tmp;
395   _conf_getValue(config, type, &tmp);
396 
397   if ( tmp == NULL )
398   {
399     fprintf(stderr, errMsg);
400     *value = def;
401     if (exit_n > 0)
402     {
403       fprintf(stderr, "Will quit with exit code %d\n", exit_n);
404       exit(exit_n);
405     }
406   } else {
407     *value = atoi(tmp);
408     if ( (*value) != 1)
409       *value = 0;
410     free(tmp);
411   }
412 }
413