Statistics
| Branch: | Revision:

janus-gateway / config.c @ 5e9e29e0

History | View | Annotate | Download (11.5 KB)

1
/*! \file    config.c
2
 * \author   Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \brief    Configuration files parsing
4
 * \details  Implementation of a parser of INI configuration files (based on libini-config).
5
 * 
6
 * \ingroup core
7
 * \ref core
8
 */
9

    
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <ctype.h>
14
#include <errno.h>
15

    
16
#include "config.h"
17
#include "debug.h"
18

    
19

    
20
/* Filename helper */
21
char *get_filename(const char *path);
22
char *get_filename(const char *path)
23
{
24
        char *filename = NULL;
25
        if(path) {
26
                filename = strrchr(path, '/')+1;
27
        }
28

    
29
        return filename;
30
}
31

    
32
/* Trimming helper */
33
char *ltrim(char *s);
34
char *ltrim(char *s)
35
{
36
    while(isspace(*s)) s++;
37
    return s;
38
}
39

    
40
char *rtrim(char *s);
41
char *rtrim(char *s)
42
{
43
    char* back = s + strlen(s);
44
    while(isspace(*--back));
45
    *(back+1) = '\0';
46
    return s;
47
}
48

    
49
char *trim(char *s);
50
char *trim(char *s)
51
{
52
    return rtrim(ltrim(s)); 
53
}
54

    
55

    
56
janus_config *janus_config_parse(const char *config_file) {
57
        if(config_file == NULL)
58
                return NULL;
59
        char *filename = get_filename(config_file);
60
        if(filename == NULL) {
61
                JANUS_DEBUG("Invalid filename %s\n", config_file);
62
                return NULL;
63
        }
64
        janus_config *jc = NULL;
65
        janus_config_category *cg = NULL;
66
        janus_config_item *ci = NULL;
67
        struct collection_item *config = NULL;
68
        struct collection_item *config_errors = NULL;
69
        int res = config_from_file(filename, config_file, &config, INI_STOP_ON_ERROR, &config_errors);
70
        if(res != 0) {
71
                JANUS_DEBUG("  -- Error reading configuration file... error %d (%s)\n", res, strerror(res));
72
        }
73
        if(config == NULL && config_errors != NULL) {
74
                /* Configuration parsing error */
75
                struct collection_iterator *iterator = NULL;
76
                res = col_bind_iterator(&iterator, config_errors, 0);
77
                if(res != 0) {
78
                        JANUS_DEBUG("  -- Error parsing configuration file... error %d (%s)\n", res, strerror(res));
79
                        free_ini_config_errors(config_errors);
80
                        return NULL;
81
                }
82
                int len = 0;
83
                struct collection_item *item = NULL;
84
                while(1) {
85
                        item = NULL;
86
                        len = 0;
87
                        res = col_iterate_collection(iterator, &item);
88
                        if(res != 0 || item == NULL)
89
                                break;
90
                        if(col_get_item_type(item) == COL_TYPE_COLLECTION) {
91
                                JANUS_PRINT("[%s]\n", col_get_item_property(item, &len));
92
                        } else if(col_get_item_type(item) == COL_TYPE_COLLECTIONREF) {
93
                                JANUS_PRINT("    [%s]\n", col_get_item_property(item, &len));
94
                        } else {
95
                                JANUS_PRINT("        %s: %s\n", col_get_item_property(item, &len), (const char *)col_get_item_data(item));
96
                        }
97
                };
98
        }
99
        if(config != NULL) {
100
                struct collection_iterator *iterator = NULL;
101
                res = col_bind_iterator(&iterator, config, 0);
102
                if(res != 0) {
103
                        JANUS_DEBUG("  -- Error parsing configuration file... error %d (%s)\n", res, strerror(res));
104
                        free_ini_config(config);
105
                        if(config_errors != NULL)
106
                                free_ini_config_errors(config_errors);
107
                        return NULL;
108
                }
109
                jc = calloc(1, sizeof(janus_config));
110
                if(jc == NULL) {
111
                        JANUS_DEBUG("Memory error!\n");
112
                        return NULL;
113
                }
114
                jc->items = NULL;
115
                jc->categories = NULL;
116
                int len = 0;
117
                struct collection_item *item = NULL;
118
                char *name = NULL, *value = NULL, *temp = NULL, *c = NULL;
119
                while(1) {
120
                        item = NULL;
121
                        len = 0;
122
                        res = col_iterate_collection(iterator, &item);
123
                        if(res != 0 || item == NULL)
124
                                break;
125
                        name = (char *)col_get_item_property(item, &len);
126
                        if(col_get_item_type(item) == COL_TYPE_COLLECTION) {
127
                                /* Configuration name */
128
                                //~ JANUS_PRINT("[%s]\n", name ? name : "??");
129
                                if(name) {
130
                                        jc->name = g_strdup(name);
131
                                        if(jc->name == NULL) {
132
                                                JANUS_DEBUG("Memory error!\n");
133
                                                free_ini_config(config);
134
                                                if(config_errors != NULL)
135
                                                        free_ini_config_errors(config_errors);
136
                                                janus_config_destroy(jc);
137
                                                return NULL;
138
                                        }
139
                                }
140
                        } else if(col_get_item_type(item) == COL_TYPE_COLLECTIONREF) {
141
                                /* Configuration category */
142
                                ci = NULL;
143
                                janus_config_category *ncg = calloc(1, sizeof(janus_config_category));
144
                                if(ncg == NULL) {
145
                                        JANUS_DEBUG("Memory error!\n");
146
                                        free_ini_config(config);
147
                                        if(config_errors != NULL)
148
                                                free_ini_config_errors(config_errors);
149
                                        janus_config_destroy(jc);
150
                                        return NULL;
151
                                }
152
                                ncg->name = NULL;
153
                                ncg->items = NULL;
154
                                ncg->next = NULL;
155
                                //~ JANUS_PRINT("    [%s]\n", name ? name : "??");
156
                                if(name) {
157
                                        ncg->name = g_strdup(name);
158
                                        if(ncg->name == NULL) {
159
                                                JANUS_DEBUG("Memory error!\n");
160
                                                free_ini_config(config);
161
                                                if(config_errors != NULL)
162
                                                        free_ini_config_errors(config_errors);
163
                                                janus_config_destroy(jc);
164
                                                return NULL;
165
                                        }
166
                                }
167
                                if(jc->categories == NULL) {
168
                                        jc->categories = ncg;
169
                                } else {
170
                                        cg->next = ncg;
171
                                }
172
                                cg = ncg;
173
                        } else {
174
                                /* Configuration item */
175
                                temp = g_strdup((char *)col_get_item_data(item));
176
                                if(temp == NULL) {
177
                                        JANUS_DEBUG("Memory error!\n");
178
                                        free_ini_config(config);
179
                                        if(config_errors != NULL)
180
                                                free_ini_config_errors(config_errors);
181
                                        janus_config_destroy(jc);
182
                                        return NULL;
183
                                }
184
                                if((c = strrchr(temp, ';')) != NULL)
185
                                        *c = '\0';
186
                                value = trim(temp);
187
                                janus_config_item *nci = calloc(1, sizeof(janus_config_item));
188
                                if(nci == NULL) {
189
                                        JANUS_DEBUG("Memory error!\n");
190
                                        free_ini_config(config);
191
                                        if(config_errors != NULL)
192
                                                free_ini_config_errors(config_errors);
193
                                        janus_config_destroy(jc);
194
                                        return NULL;
195
                                }
196
                                nci->name = NULL;
197
                                nci->value = NULL;
198
                                nci->next = NULL;
199
                                //~ JANUS_PRINT("        %s: %s\n", name ? name : "??", value ? value : "??");
200
                                if(name) {
201
                                        nci->name = g_strdup(name);
202
                                        if(nci->name == NULL) {
203
                                                JANUS_DEBUG("Memory error!\n");
204
                                                free_ini_config(config);
205
                                                if(config_errors != NULL)
206
                                                        free_ini_config_errors(config_errors);
207
                                                janus_config_destroy(jc);
208
                                                return NULL;
209
                                        }
210
                                }
211
                                if(value) {
212
                                        nci->value = g_strdup(value);
213
                                        g_free((gpointer)value);
214
                                        if(nci->value == NULL) {
215
                                                JANUS_DEBUG("Memory error!\n");
216
                                                free_ini_config(config);
217
                                                if(config_errors != NULL)
218
                                                        free_ini_config_errors(config_errors);
219
                                                janus_config_destroy(jc);
220
                                                return NULL;
221
                                        }
222
                                }
223
                                if(cg == NULL) {
224
                                        /* Uncategorized item */
225
                                        if(jc->items == NULL) {
226
                                                jc->items = nci;
227
                                        } else {
228
                                                ci->next = nci;
229
                                        }
230
                                } else {
231
                                        /* Att to current category */
232
                                        if(cg->items == NULL) {
233
                                                cg->items = nci;
234
                                        } else {
235
                                                ci->next = nci;
236
                                        }
237
                                }
238
                                ci = nci;
239
                        }
240
                };
241
        }
242
        free_ini_config(config);
243
        if(config_errors != NULL)
244
                free_ini_config_errors(config_errors);
245
        return jc;
246
}
247

    
248
janus_config *janus_config_create(const char *name) {
249
        janus_config *jc = calloc(1, sizeof(janus_config));
250
        if(jc == NULL) {
251
                JANUS_DEBUG("Memory error!\n");
252
                return NULL;
253
        }
254
        if(name != NULL) {
255
                jc->name = g_strdup(name);
256
                if(jc->name == NULL) {
257
                        JANUS_DEBUG("Memory error!\n");
258
                        janus_config_destroy(jc);
259
                        return NULL;
260
                }
261
        }
262
        return jc;
263
}
264

    
265
janus_config_category *janus_config_get_categories(janus_config *config) {
266
        if(config == NULL)
267
                return NULL;
268
        return config->categories;
269
}
270

    
271
janus_config_category *janus_config_get_category(janus_config *config, const char *name) {
272
        if(config == NULL || name == NULL)
273
                return NULL;
274
        if(config->categories == NULL)
275
                return NULL;
276
        janus_config_category *c = config->categories;
277
        while(c) {
278
                if(c->name && !strcasecmp(name, c->name))
279
                        return c;
280
                c = c->next;
281
        }
282
        return NULL;
283
}
284

    
285
janus_config_item *janus_config_get_items(janus_config_category *category) {
286
        if(category == NULL)
287
                return NULL;
288
        return category->items;
289
}
290

    
291
janus_config_item *janus_config_get_item(janus_config_category *category, const char *name) {
292
        if(category == NULL || name == NULL)
293
                return NULL;
294
        if(category->items == NULL)
295
                return NULL;
296
        janus_config_item *i = category->items;
297
        while(i) {
298
                if(i->name && !strcasecmp(name, i->name))
299
                        return i;
300
                i = i->next;
301
        }
302
        return NULL;
303
}
304

    
305
janus_config_item *janus_config_get_item_drilldown(janus_config *config, const char *category, const char *name) {
306
        if(config == NULL || category == NULL || name == NULL)
307
                return NULL;
308
        janus_config_category *c = janus_config_get_category(config, category);
309
        if(c == NULL)
310
                return NULL;
311
        if(c->items == NULL)
312
                return NULL;
313
        return janus_config_get_item(c, name);
314
}
315

    
316
janus_config_item *janus_config_add_item(janus_config *config, const char *category, const char *name, const char *value) {
317
        if(config == NULL || category == NULL || name == NULL || value == NULL)
318
                return NULL;
319
        janus_config_category *c = janus_config_get_category(config, category);
320
        if(c == NULL) {
321
                /* Create it */
322
                c = calloc(1, sizeof(janus_config_category));
323
                if(c == NULL) {
324
                        JANUS_DEBUG("Memory error!\n");
325
                        return NULL;
326
                }
327
                c->name = g_strdup(category);
328
                if(c->name == NULL) {
329
                        JANUS_DEBUG("Memory error!\n");
330
                        g_free((gpointer)c);
331
                        return NULL;
332
                }
333
                c->next = NULL;
334
                if(config->categories == NULL) {
335
                        config->categories = c;
336
                } else {
337
                        janus_config_category *tmp = config->categories;
338
                        while(tmp) {
339
                                if(tmp->next == NULL) {
340
                                        tmp->next = c;
341
                                        break;
342
                                }
343
                                tmp = tmp->next;
344
                        }
345
                }
346
        }
347
        janus_config_item *item = janus_config_get_item(c, name);
348
        if(item == NULL) {
349
                /* Create it */
350
                item = calloc(1, sizeof(janus_config_item));
351
                if(item == NULL) {
352
                        JANUS_DEBUG("Memory error!\n");
353
                        return NULL;
354
                }
355
                item->name = g_strdup(name);
356
                if(item->name == NULL) {
357
                        JANUS_DEBUG("Memory error!\n");
358
                        g_free((gpointer)item);
359
                        return NULL;
360
                }
361
                item->value = g_strdup(value);
362
                if(item->value == NULL) {
363
                        JANUS_DEBUG("Memory error!\n");
364
                        g_free((gpointer)item->name);
365
                        g_free((gpointer)item);
366
                        return NULL;
367
                }
368
                item->next = NULL;
369
                if(c->items == NULL) {
370
                        c->items = item;
371
                } else {
372
                        janus_config_item *tmp = c->items;
373
                        while(tmp) {
374
                                if(tmp->next == NULL) {
375
                                        tmp->next = item;
376
                                        break;
377
                                }
378
                                tmp = tmp->next;
379
                        }
380
                }
381
        } else {
382
                /* Update it */
383
                char *item_value = g_strdup(value);
384
                if(item_value == NULL) {
385
                        JANUS_DEBUG("Memory error!\n");
386
                        return NULL;
387
                }
388
                if(item->value)
389
                        g_free((gpointer)item->value);
390
                item->value = item_value;
391
        }
392
        return item;
393
}
394

    
395
void janus_config_print(janus_config *config) {
396
        if(config == NULL)
397
                return;
398
        JANUS_PRINT("[%s]\n", config->name ? config->name : "??");
399
        if(config->items) {
400
                janus_config_item *i = config->items;
401
                config->items = NULL;
402
                while(i) {
403
                        JANUS_PRINT("        %s: %s\n", i->name ? i->name : "??", i->value ? i->value : "??");
404
                        i = i->next;
405
                }
406
        }
407
        if(config->categories) {
408
                janus_config_category *c = config->categories;
409
                while(c) {
410
                        JANUS_PRINT("    [%s]\n", c->name ? c->name : "??");
411
                        if(c->items) {
412
                                janus_config_item *i = c->items;
413
                                while(i) {
414
                                        JANUS_PRINT("        %s: %s\n", i->name ? i->name : "??", i->value ? i->value : "??");
415
                                        i = i->next;
416
                                }
417
                        }
418
                        c = c->next;
419
                }
420
        }
421
        config = NULL;
422
}
423

    
424
void janus_config_destroy(janus_config *config) {
425
        if(config == NULL)
426
                return;
427
        if(config->items) {
428
                janus_config_item *i = config->items, *tmp = NULL;
429
                config->items = NULL;
430
                while(i) {
431
                        if(i->name)
432
                                g_free((gpointer)i->name);
433
                        if(i->value)
434
                                g_free((gpointer)i->value);
435
                        tmp = i;
436
                        i = i->next;
437
                        g_free((gpointer)tmp);
438
                        tmp = NULL;
439
                }
440
        }
441
        if(config->categories) {
442
                janus_config_category *c = config->categories, *tmp = NULL;
443
                config->categories = NULL;
444
                while(c) {
445
                        if(c->name)
446
                                g_free((gpointer)c->name);
447
                        if(c->items) {
448
                                janus_config_item *i = c->items, *tmp2 = NULL;
449
                                c->items = NULL;
450
                                while(i) {
451
                                        if(i->name)
452
                                                g_free((gpointer)i->name);
453
                                        if(i->value)
454
                                                g_free((gpointer)i->value);
455
                                        tmp2 = i;
456
                                        i = i->next;
457
                                        g_free((gpointer)tmp2);
458
                                        tmp2 = NULL;
459
                                }
460
                        }
461
                        tmp = c;
462
                        c = c->next;
463
                        g_free((gpointer)tmp);
464
                        tmp = NULL;
465
                }
466
        }
467
        if(config->name)
468
                g_free((gpointer)config->name);
469
        g_free((gpointer)config);
470
        config = NULL;
471
}