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