settings: Use glob enumerator to load included files
[strongswan.git] / src / libstrongswan / settings / settings.c
1 /*
2 * Copyright (C) 2010-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #define _GNU_SOURCE
18 #include <string.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "settings.h"
28
29 #include "collections/array.h"
30 #include "collections/hashtable.h"
31 #include "collections/linked_list.h"
32 #include "threading/rwlock.h"
33 #include "utils/debug.h"
34
35 #define MAX_INCLUSION_LEVEL 10
36
37 typedef struct private_settings_t private_settings_t;
38 typedef struct section_t section_t;
39 typedef struct kv_t kv_t;
40
41 /**
42 * private data of settings
43 */
44 struct private_settings_t {
45
46 /**
47 * public functions
48 */
49 settings_t public;
50
51 /**
52 * top level section
53 */
54 section_t *top;
55
56 /**
57 * contents of loaded files and in-memory settings (char*)
58 */
59 linked_list_t *contents;
60
61 /**
62 * lock to safely access the settings
63 */
64 rwlock_t *lock;
65 };
66
67 /**
68 * section containing subsections and key value pairs
69 */
70 struct section_t {
71
72 /**
73 * name of the section
74 */
75 char *name;
76
77 /**
78 * fallback sections, as section_t
79 */
80 array_t *fallbacks;
81
82 /**
83 * subsections, as section_t
84 */
85 array_t *sections;
86
87 /**
88 * key value pairs, as kv_t
89 */
90 array_t *kv;
91 };
92
93 /**
94 * Key value pair
95 */
96 struct kv_t {
97
98 /**
99 * key string, relative
100 */
101 char *key;
102
103 /**
104 * value as string
105 */
106 char *value;
107 };
108
109 /**
110 * create a key/value pair
111 */
112 static kv_t *kv_create(char *key, char *value)
113 {
114 kv_t *this;
115 INIT(this,
116 .key = strdup(key),
117 .value = value,
118 );
119 return this;
120 }
121
122 /**
123 * destroy a key/value pair
124 */
125 static void kv_destroy(kv_t *this)
126 {
127 free(this->key);
128 free(this);
129 }
130
131 /**
132 * create a section with the given name
133 */
134 static section_t *section_create(char *name)
135 {
136 section_t *this;
137 INIT(this,
138 .name = strdupnull(name),
139 );
140 return this;
141 }
142
143 /**
144 * destroy a section
145 */
146 static void section_destroy(section_t *this)
147 {
148 array_destroy_function(this->sections, (void*)section_destroy, NULL);
149 array_destroy_function(this->kv, (void*)kv_destroy, NULL);
150 array_destroy(this->fallbacks);
151 free(this->name);
152 free(this);
153 }
154
155 /**
156 * Purge contents of a section, returns if section can be safely removed.
157 */
158 static bool section_purge(section_t *this)
159 {
160 section_t *current;
161 int i;
162
163 array_destroy_function(this->kv, (void*)kv_destroy, NULL);
164 this->kv = NULL;
165 /* we ensure sections used as fallback, or configured with fallbacks (or
166 * having any such subsections) are not removed */
167 for (i = array_count(this->sections) - 1; i >= 0; i--)
168 {
169 array_get(this->sections, i, &current);
170 if (section_purge(current))
171 {
172 array_remove(this->sections, i, NULL);
173 section_destroy(current);
174 }
175 }
176 return !this->fallbacks && !array_count(this->sections);
177 }
178
179 /**
180 * callback to find a section by name
181 */
182 static int section_find(const void *a, const void *b)
183 {
184 const char *key = a;
185 const section_t *item = b;
186 return strcmp(key, item->name);
187 }
188
189 /**
190 * callback to sort sections by name
191 */
192 static int section_sort(const void *a, const void *b, void *user)
193 {
194 const section_t *sa = a, *sb = b;
195 return strcmp(sa->name, sb->name);
196 }
197
198 /**
199 * callback to find a kv pair by key
200 */
201 static int kv_find(const void *a, const void *b)
202 {
203 const char *key = a;
204 const kv_t *item = b;
205 return strcmp(key, item->key);
206 }
207
208 /**
209 * callback to sort kv pairs by key
210 */
211 static int kv_sort(const void *a, const void *b, void *user)
212 {
213 const kv_t *kva = a, *kvb = b;
214 return strcmp(kva->key, kvb->key);
215 }
216
217 /**
218 * Print a format key, but consume already processed arguments
219 */
220 static bool print_key(char *buf, int len, char *start, char *key, va_list args)
221 {
222 va_list copy;
223 char *pos = start;
224 bool res;
225
226 va_copy(copy, args);
227 while (TRUE)
228 {
229 pos = memchr(pos, '%', key - pos);
230 if (!pos)
231 {
232 break;
233 }
234 pos++;
235 switch (*pos)
236 {
237 case 'd':
238 va_arg(copy, int);
239 break;
240 case 's':
241 va_arg(copy, char*);
242 break;
243 case 'N':
244 va_arg(copy, enum_name_t*);
245 va_arg(copy, int);
246 break;
247 case '%':
248 break;
249 default:
250 DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
251 break;
252 }
253 pos++;
254 }
255 res = vsnprintf(buf, len, key, copy) < len;
256 va_end(copy);
257 return res;
258 }
259
260 /**
261 * Find a section by a given key, using buffered key, reusable buffer.
262 * If "ensure" is TRUE, the sections are created if they don't exist.
263 */
264 static section_t *find_section_buffered(section_t *section,
265 char *start, char *key, va_list args, char *buf, int len,
266 bool ensure)
267 {
268 char *pos;
269 section_t *found = NULL;
270
271 if (section == NULL)
272 {
273 return NULL;
274 }
275 pos = strchr(key, '.');
276 if (pos)
277 {
278 *pos = '\0';
279 pos++;
280 }
281 if (!print_key(buf, len, start, key, args))
282 {
283 return NULL;
284 }
285 if (!strlen(buf))
286 {
287 found = section;
288 }
289 else if (array_bsearch(section->sections, buf, section_find, &found) == -1)
290 {
291 if (ensure)
292 {
293 found = section_create(buf);
294 array_insert_create(&section->sections, ARRAY_TAIL, found);
295 array_sort(section->sections, section_sort, NULL);
296 }
297 }
298 if (found && pos)
299 {
300 return find_section_buffered(found, start, pos, args, buf, len, ensure);
301 }
302 return found;
303 }
304
305 /**
306 * Find all sections via a given key considering fallbacks, using buffered key,
307 * reusable buffer.
308 */
309 static void find_sections_buffered(section_t *section, char *start, char *key,
310 va_list args, char *buf, int len, array_t **sections)
311 {
312 section_t *found = NULL, *fallback;
313 char *pos;
314 int i;
315
316 if (!section)
317 {
318 return;
319 }
320 pos = strchr(key, '.');
321 if (pos)
322 {
323 *pos = '\0';
324 }
325 if (!print_key(buf, len, start, key, args))
326 {
327 return;
328 }
329 if (pos)
330 { /* restore so we can follow fallbacks */
331 *pos = '.';
332 }
333 if (!strlen(buf))
334 {
335 found = section;
336 }
337 else
338 {
339 array_bsearch(section->sections, buf, section_find, &found);
340 }
341 if (found)
342 {
343 if (pos)
344 {
345 find_sections_buffered(found, start, pos+1, args, buf, len,
346 sections);
347 }
348 else
349 {
350 array_insert_create(sections, ARRAY_TAIL, found);
351 for (i = 0; i < array_count(found->fallbacks); i++)
352 {
353 array_get(found->fallbacks, i, &fallback);
354 array_insert_create(sections, ARRAY_TAIL, fallback);
355 }
356 }
357 }
358 if (section->fallbacks)
359 {
360 for (i = 0; i < array_count(section->fallbacks); i++)
361 {
362 array_get(section->fallbacks, i, &fallback);
363 find_sections_buffered(fallback, start, key, args, buf, len,
364 sections);
365 }
366 }
367 }
368
369 /**
370 * Ensure that the section with the given key exists (thread-safe).
371 */
372 static section_t *ensure_section(private_settings_t *this, section_t *section,
373 const char *key, va_list args)
374 {
375 char buf[128], keybuf[512];
376 section_t *found;
377
378 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
379 {
380 return NULL;
381 }
382 /* we might have to change the tree */
383 this->lock->write_lock(this->lock);
384 found = find_section_buffered(section, keybuf, keybuf, args, buf,
385 sizeof(buf), TRUE);
386 this->lock->unlock(this->lock);
387 return found;
388 }
389
390 /**
391 * Find a section by a given key with its fallbacks (not thread-safe!).
392 * Sections are returned in depth-first order (array is allocated). NULL is
393 * returned if no sections are found.
394 */
395 static array_t *find_sections(private_settings_t *this, section_t *section,
396 char *key, va_list args)
397 {
398 char buf[128], keybuf[512];
399 array_t *sections = NULL;
400
401 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
402 {
403 return NULL;
404 }
405 find_sections_buffered(section, keybuf, keybuf, args, buf,
406 sizeof(buf), &sections);
407 return sections;
408 }
409
410 /**
411 * Check if the given fallback section already exists
412 */
413 static bool fallback_exists(section_t *section, section_t *fallback)
414 {
415 if (section == fallback)
416 {
417 return TRUE;
418 }
419 else if (section->fallbacks)
420 {
421 section_t *existing;
422 int i;
423
424 for (i = 0; i < array_count(section->fallbacks); i++)
425 {
426 array_get(section->fallbacks, i, &existing);
427 if (existing == fallback)
428 {
429 return TRUE;
430 }
431 }
432 }
433 return FALSE;
434 }
435
436 /**
437 * Ensure that the section with the given key exists and add the given fallback
438 * section (thread-safe).
439 */
440 static void add_fallback_to_section(private_settings_t *this,
441 section_t *section, const char *key, va_list args,
442 section_t *fallback)
443 {
444 char buf[128], keybuf[512];
445 section_t *found;
446
447 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
448 {
449 return;
450 }
451 this->lock->write_lock(this->lock);
452 found = find_section_buffered(section, keybuf, keybuf, args, buf,
453 sizeof(buf), TRUE);
454 if (!fallback_exists(found, fallback))
455 {
456 /* to ensure sections referred to as fallback are not purged, we create
457 * the array there too */
458 if (!fallback->fallbacks)
459 {
460 fallback->fallbacks = array_create(0, 0);
461 }
462 array_insert_create(&found->fallbacks, ARRAY_TAIL, fallback);
463 }
464 this->lock->unlock(this->lock);
465 }
466
467 /**
468 * Find the key/value pair for a key, using buffered key, reusable buffer
469 * If "ensure" is TRUE, the sections (and key/value pair) are created if they
470 * don't exist.
471 * Fallbacks are only considered if "ensure" is FALSE.
472 */
473 static kv_t *find_value_buffered(section_t *section, char *start, char *key,
474 va_list args, char *buf, int len, bool ensure)
475 {
476 int i;
477 char *pos;
478 kv_t *kv = NULL;
479 section_t *found = NULL;
480
481 if (section == NULL)
482 {
483 return NULL;
484 }
485
486 pos = strchr(key, '.');
487 if (pos)
488 {
489 *pos = '\0';
490 if (!print_key(buf, len, start, key, args))
491 {
492 return NULL;
493 }
494 /* restore so we can retry for fallbacks */
495 *pos = '.';
496 if (!strlen(buf))
497 {
498 found = section;
499 }
500 else if (array_bsearch(section->sections, buf, section_find,
501 &found) == -1)
502 {
503 if (ensure)
504 {
505 found = section_create(buf);
506 array_insert_create(&section->sections, ARRAY_TAIL, found);
507 array_sort(section->sections, section_sort, NULL);
508 }
509 }
510 if (found)
511 {
512 kv = find_value_buffered(found, start, pos+1, args, buf, len,
513 ensure);
514 }
515 if (!kv && !ensure && section->fallbacks)
516 {
517 for (i = 0; !kv && i < array_count(section->fallbacks); i++)
518 {
519 array_get(section->fallbacks, i, &found);
520 kv = find_value_buffered(found, start, key, args, buf, len,
521 ensure);
522 }
523 }
524 }
525 else
526 {
527 if (!print_key(buf, len, start, key, args))
528 {
529 return NULL;
530 }
531 if (array_bsearch(section->kv, buf, kv_find, &kv) == -1)
532 {
533 if (ensure)
534 {
535 kv = kv_create(buf, NULL);
536 array_insert_create(&section->kv, ARRAY_TAIL, kv);
537 array_sort(section->kv, kv_sort, NULL);
538 }
539 else if (section->fallbacks)
540 {
541 for (i = 0; !kv && i < array_count(section->fallbacks); i++)
542 {
543 array_get(section->fallbacks, i, &found);
544 kv = find_value_buffered(found, start, key, args, buf, len,
545 ensure);
546 }
547 }
548 }
549 }
550 return kv;
551 }
552
553 /**
554 * Find the string value for a key (thread-safe).
555 */
556 static char *find_value(private_settings_t *this, section_t *section,
557 char *key, va_list args)
558 {
559 char buf[128], keybuf[512], *value = NULL;
560 kv_t *kv;
561
562 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
563 {
564 return NULL;
565 }
566 this->lock->read_lock(this->lock);
567 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
568 FALSE);
569 if (kv)
570 {
571 value = kv->value;
572 }
573 this->lock->unlock(this->lock);
574 return value;
575 }
576
577 /**
578 * Set a value to a copy of the given string (thread-safe).
579 */
580 static void set_value(private_settings_t *this, section_t *section,
581 char *key, va_list args, char *value)
582 {
583 char buf[128], keybuf[512];
584 kv_t *kv;
585
586 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
587 {
588 return;
589 }
590 this->lock->write_lock(this->lock);
591 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
592 TRUE);
593 if (kv)
594 {
595 if (!value)
596 {
597 kv->value = NULL;
598 }
599 else if (kv->value && (strlen(value) <= strlen(kv->value)))
600 { /* overwrite in-place, if possible */
601 strcpy(kv->value, value);
602 }
603 else
604 { /* otherwise clone the string and store it in the cache */
605 kv->value = strdup(value);
606 this->contents->insert_last(this->contents, kv->value);
607 }
608 }
609 this->lock->unlock(this->lock);
610 }
611
612 METHOD(settings_t, get_str, char*,
613 private_settings_t *this, char *key, char *def, ...)
614 {
615 char *value;
616 va_list args;
617
618 va_start(args, def);
619 value = find_value(this, this->top, key, args);
620 va_end(args);
621 if (value)
622 {
623 return value;
624 }
625 return def;
626 }
627
628 /**
629 * Described in header
630 */
631 inline bool settings_value_as_bool(char *value, bool def)
632 {
633 if (value)
634 {
635 if (strcaseeq(value, "1") ||
636 strcaseeq(value, "yes") ||
637 strcaseeq(value, "true") ||
638 strcaseeq(value, "enabled"))
639 {
640 return TRUE;
641 }
642 else if (strcaseeq(value, "0") ||
643 strcaseeq(value, "no") ||
644 strcaseeq(value, "false") ||
645 strcaseeq(value, "disabled"))
646 {
647 return FALSE;
648 }
649 }
650 return def;
651 }
652
653 METHOD(settings_t, get_bool, bool,
654 private_settings_t *this, char *key, bool def, ...)
655 {
656 char *value;
657 va_list args;
658
659 va_start(args, def);
660 value = find_value(this, this->top, key, args);
661 va_end(args);
662 return settings_value_as_bool(value, def);
663 }
664
665 /**
666 * Described in header
667 */
668 inline int settings_value_as_int(char *value, int def)
669 {
670 int intval;
671 if (value)
672 {
673 errno = 0;
674 intval = strtol(value, NULL, 10);
675 if (errno == 0)
676 {
677 return intval;
678 }
679 }
680 return def;
681 }
682
683 METHOD(settings_t, get_int, int,
684 private_settings_t *this, char *key, int def, ...)
685 {
686 char *value;
687 va_list args;
688
689 va_start(args, def);
690 value = find_value(this, this->top, key, args);
691 va_end(args);
692 return settings_value_as_int(value, def);
693 }
694
695 /**
696 * Described in header
697 */
698 inline double settings_value_as_double(char *value, double def)
699 {
700 double dval;
701 if (value)
702 {
703 errno = 0;
704 dval = strtod(value, NULL);
705 if (errno == 0)
706 {
707 return dval;
708 }
709 }
710 return def;
711 }
712
713 METHOD(settings_t, get_double, double,
714 private_settings_t *this, char *key, double def, ...)
715 {
716 char *value;
717 va_list args;
718
719 va_start(args, def);
720 value = find_value(this, this->top, key, args);
721 va_end(args);
722 return settings_value_as_double(value, def);
723 }
724
725 /**
726 * Described in header
727 */
728 inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
729 {
730 char *endptr;
731 u_int32_t timeval;
732 if (value)
733 {
734 errno = 0;
735 timeval = strtoul(value, &endptr, 10);
736 if (errno == 0)
737 {
738 switch (*endptr)
739 {
740 case 'd': /* time in days */
741 timeval *= 24 * 3600;
742 break;
743 case 'h': /* time in hours */
744 timeval *= 3600;
745 break;
746 case 'm': /* time in minutes */
747 timeval *= 60;
748 break;
749 case 's': /* time in seconds */
750 default:
751 break;
752 }
753 return timeval;
754 }
755 }
756 return def;
757 }
758
759 METHOD(settings_t, get_time, u_int32_t,
760 private_settings_t *this, char *key, u_int32_t def, ...)
761 {
762 char *value;
763 va_list args;
764
765 va_start(args, def);
766 value = find_value(this, this->top, key, args);
767 va_end(args);
768 return settings_value_as_time(value, def);
769 }
770
771 METHOD(settings_t, set_str, void,
772 private_settings_t *this, char *key, char *value, ...)
773 {
774 va_list args;
775 va_start(args, value);
776 set_value(this, this->top, key, args, value);
777 va_end(args);
778 }
779
780 METHOD(settings_t, set_bool, void,
781 private_settings_t *this, char *key, bool value, ...)
782 {
783 va_list args;
784 va_start(args, value);
785 set_value(this, this->top, key, args, value ? "1" : "0");
786 va_end(args);
787 }
788
789 METHOD(settings_t, set_int, void,
790 private_settings_t *this, char *key, int value, ...)
791 {
792 char val[16];
793 va_list args;
794 va_start(args, value);
795 if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
796 {
797 set_value(this, this->top, key, args, val);
798 }
799 va_end(args);
800 }
801
802 METHOD(settings_t, set_double, void,
803 private_settings_t *this, char *key, double value, ...)
804 {
805 char val[64];
806 va_list args;
807 va_start(args, value);
808 if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
809 {
810 set_value(this, this->top, key, args, val);
811 }
812 va_end(args);
813 }
814
815 METHOD(settings_t, set_time, void,
816 private_settings_t *this, char *key, u_int32_t value, ...)
817 {
818 char val[16];
819 va_list args;
820 va_start(args, value);
821 if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
822 {
823 set_value(this, this->top, key, args, val);
824 }
825 va_end(args);
826 }
827
828 METHOD(settings_t, set_default_str, bool,
829 private_settings_t *this, char *key, char *value, ...)
830 {
831 char *old;
832 va_list args;
833
834 va_start(args, value);
835 old = find_value(this, this->top, key, args);
836 va_end(args);
837
838 if (!old)
839 {
840 va_start(args, value);
841 set_value(this, this->top, key, args, value);
842 va_end(args);
843 return TRUE;
844 }
845 return FALSE;
846 }
847
848 /**
849 * Data for enumerators
850 */
851 typedef struct {
852 /** settings_t instance */
853 private_settings_t *settings;
854 /** sections to enumerate */
855 array_t *sections;
856 /** sections/keys that were already enumerated */
857 hashtable_t *seen;
858 } enumerator_data_t;
859
860 /**
861 * Destroy enumerator data
862 */
863 static void enumerator_destroy(enumerator_data_t *this)
864 {
865 this->settings->lock->unlock(this->settings->lock);
866 this->seen->destroy(this->seen);
867 array_destroy(this->sections);
868 free(this);
869 }
870
871 /**
872 * Enumerate section names, not sections
873 */
874 static bool section_filter(hashtable_t *seen, section_t **in, char **out)
875 {
876 *out = (*in)->name;
877 if (seen->get(seen, *out))
878 {
879 return FALSE;
880 }
881 seen->put(seen, *out, *out);
882 return TRUE;
883 }
884
885 /**
886 * Enumerate sections of the given section
887 */
888 static enumerator_t *section_enumerator(section_t *section,
889 enumerator_data_t *data)
890 {
891 return enumerator_create_filter(array_create_enumerator(section->sections),
892 (void*)section_filter, data->seen, NULL);
893 }
894
895 METHOD(settings_t, create_section_enumerator, enumerator_t*,
896 private_settings_t *this, char *key, ...)
897 {
898 enumerator_data_t *data;
899 array_t *sections;
900 va_list args;
901
902 this->lock->read_lock(this->lock);
903 va_start(args, key);
904 sections = find_sections(this, this->top, key, args);
905 va_end(args);
906
907 if (!sections)
908 {
909 this->lock->unlock(this->lock);
910 return enumerator_create_empty();
911 }
912 INIT(data,
913 .settings = this,
914 .sections = sections,
915 .seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
916 );
917 return enumerator_create_nested(array_create_enumerator(sections),
918 (void*)section_enumerator, data, (void*)enumerator_destroy);
919 }
920
921 /**
922 * Enumerate key and values, not kv_t entries
923 */
924 static bool kv_filter(hashtable_t *seen, kv_t **in, char **key,
925 void *none, char **value)
926 {
927 *key = (*in)->key;
928 if (seen->get(seen, *key))
929 {
930 return FALSE;
931 }
932 *value = (*in)->value;
933 seen->put(seen, *key, *key);
934 return TRUE;
935 }
936
937 /**
938 * Enumerate key/value pairs of the given section
939 */
940 static enumerator_t *kv_enumerator(section_t *section, enumerator_data_t *data)
941 {
942 return enumerator_create_filter(array_create_enumerator(section->kv),
943 (void*)kv_filter, data->seen, NULL);
944 }
945
946 METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
947 private_settings_t *this, char *key, ...)
948 {
949 enumerator_data_t *data;
950 array_t *sections;
951 va_list args;
952
953 this->lock->read_lock(this->lock);
954 va_start(args, key);
955 sections = find_sections(this, this->top, key, args);
956 va_end(args);
957
958 if (!sections)
959 {
960 this->lock->unlock(this->lock);
961 return enumerator_create_empty();
962 }
963 INIT(data,
964 .settings = this,
965 .sections = sections,
966 .seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
967 );
968 return enumerator_create_nested(array_create_enumerator(sections),
969 (void*)kv_enumerator, data, (void*)enumerator_destroy);
970 }
971
972 METHOD(settings_t, add_fallback, void,
973 private_settings_t *this, const char *key, const char *fallback, ...)
974 {
975 section_t *section;
976 va_list args;
977
978 /* find/create the fallback */
979 va_start(args, fallback);
980 section = ensure_section(this, this->top, fallback, args);
981 va_end(args);
982
983 va_start(args, fallback);
984 add_fallback_to_section(this, this->top, key, args, section);
985 va_end(args);
986 }
987
988 /**
989 * parse text, truncate "skip" chars, delimited by term respecting brackets.
990 *
991 * Chars in "skip" are truncated at the beginning and the end of the resulting
992 * token. "term" contains a list of characters to read up to (first match),
993 * while "br" contains bracket counterparts found in "term" to skip.
994 */
995 static char parse(char **text, char *skip, char *term, char *br, char **token)
996 {
997 char *best = NULL;
998 char best_term = '\0';
999
1000 /* skip leading chars */
1001 while (strchr(skip, **text))
1002 {
1003 (*text)++;
1004 if (!**text)
1005 {
1006 return 0;
1007 }
1008 }
1009 /* mark begin of subtext */
1010 *token = *text;
1011 while (*term)
1012 {
1013 char *pos = *text;
1014 int level = 1;
1015
1016 /* find terminator */
1017 while (*pos)
1018 {
1019 if (*pos == *term)
1020 {
1021 level--;
1022 }
1023 else if (br && *pos == *br)
1024 {
1025 level++;
1026 }
1027 if (level == 0)
1028 {
1029 if (best == NULL || best > pos)
1030 {
1031 best = pos;
1032 best_term = *term;
1033 }
1034 break;
1035 }
1036 pos++;
1037 }
1038 /* try next terminator */
1039 term++;
1040 if (br)
1041 {
1042 br++;
1043 }
1044 }
1045 if (best)
1046 {
1047 /* update input */
1048 *text = best;
1049 /* null trailing bytes */
1050 do
1051 {
1052 *best = '\0';
1053 best--;
1054 }
1055 while (best >= *token && strchr(skip, *best));
1056 /* return found terminator */
1057 return best_term;
1058 }
1059 return 0;
1060 }
1061
1062 /**
1063 * Check if "text" starts with "pattern".
1064 * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
1065 * is modified to point to the character right after "pattern".
1066 */
1067 static bool starts_with(char **text, char *skip, char *pattern)
1068 {
1069 char *pos = *text;
1070 int len = strlen(pattern);
1071 while (strchr(skip, *pos))
1072 {
1073 pos++;
1074 if (!*pos)
1075 {
1076 return FALSE;
1077 }
1078 }
1079 if (strlen(pos) < len || !strneq(pos, pattern, len))
1080 {
1081 return FALSE;
1082 }
1083 *text = pos + len;
1084 return TRUE;
1085 }
1086
1087 /**
1088 * Check if what follows in "text" is an include statement.
1089 * If this function returns TRUE, "text" will point to the character right after
1090 * the include pattern, which is returned in "pattern".
1091 */
1092 static bool parse_include(char **text, char **pattern)
1093 {
1094 char *pos = *text;
1095 if (!starts_with(&pos, "\n\t ", "include"))
1096 {
1097 return FALSE;
1098 }
1099 if (starts_with(&pos, "\t ", "="))
1100 { /* ignore "include = value" */
1101 return FALSE;
1102 }
1103 *text = pos;
1104 return parse(text, "\t ", "\n", NULL, pattern) != 0;
1105 }
1106
1107 /**
1108 * Forward declaration.
1109 */
1110 static bool parse_files(linked_list_t *contents, char *file, int level,
1111 char *pattern, section_t *section);
1112
1113 /**
1114 * Parse a section
1115 */
1116 static bool parse_section(linked_list_t *contents, char *file, int level,
1117 char **text, section_t *section)
1118 {
1119 bool finished = FALSE;
1120 char *key, *value, *inner;
1121
1122 while (!finished)
1123 {
1124 if (parse_include(text, &value))
1125 {
1126 if (!parse_files(contents, file, level, value, section))
1127 {
1128 DBG1(DBG_LIB, "failed to include '%s'", value);
1129 return FALSE;
1130 }
1131 continue;
1132 }
1133 switch (parse(text, "\t\n ", "{=#", NULL, &key))
1134 {
1135 case '{':
1136 if (parse(text, "\t ", "}", "{", &inner))
1137 {
1138 section_t *sub;
1139 if (!strlen(key))
1140 {
1141 DBG1(DBG_LIB, "skipping section without name in '%s'",
1142 section->name);
1143 continue;
1144 }
1145 if (array_bsearch(section->sections, key, section_find,
1146 &sub) == -1)
1147 {
1148 sub = section_create(key);
1149 if (parse_section(contents, file, level, &inner, sub))
1150 {
1151 array_insert_create(&section->sections, ARRAY_TAIL,
1152 sub);
1153 array_sort(section->sections, section_sort, NULL);
1154 continue;
1155 }
1156 section_destroy(sub);
1157 }
1158 else
1159 { /* extend the existing section */
1160 if (parse_section(contents, file, level, &inner, sub))
1161 {
1162 continue;
1163 }
1164 }
1165 DBG1(DBG_LIB, "parsing subsection '%s' failed", key);
1166 break;
1167 }
1168 DBG1(DBG_LIB, "matching '}' not found near %s", *text);
1169 break;
1170 case '=':
1171 if (parse(text, "\t ", "\n", NULL, &value))
1172 {
1173 kv_t *kv;
1174 if (!strlen(key))
1175 {
1176 DBG1(DBG_LIB, "skipping value without key in '%s'",
1177 section->name);
1178 continue;
1179 }
1180 if (array_bsearch(section->kv, key, kv_find, &kv) == -1)
1181 {
1182 kv = kv_create(key, value);
1183 array_insert_create(&section->kv, ARRAY_TAIL, kv);
1184 array_sort(section->kv, kv_sort, NULL);
1185 }
1186 else
1187 { /* replace with the most recently read value */
1188 kv->value = value;
1189 }
1190 continue;
1191 }
1192 DBG1(DBG_LIB, "parsing value failed near %s", *text);
1193 break;
1194 case '#':
1195 parse(text, "", "\n", NULL, &value);
1196 continue;
1197 default:
1198 finished = TRUE;
1199 continue;
1200 }
1201 return FALSE;
1202 }
1203 return TRUE;
1204 }
1205
1206 /**
1207 * Parse a file and add the settings to the given section.
1208 */
1209 static bool parse_file(linked_list_t *contents, char *file, int level,
1210 section_t *section)
1211 {
1212 bool success;
1213 char *text, *pos;
1214 struct stat st;
1215 FILE *fd;
1216 int len;
1217
1218 DBG2(DBG_LIB, "loading config file '%s'", file);
1219 if (stat(file, &st) == -1)
1220 {
1221 if (errno == ENOENT)
1222 {
1223 #ifdef STRONGSWAN_CONF
1224 if (streq(file, STRONGSWAN_CONF))
1225 {
1226 DBG2(DBG_LIB, "'%s' does not exist, ignored", file);
1227 }
1228 else
1229 #endif
1230 {
1231 DBG1(DBG_LIB, "'%s' does not exist, ignored", file);
1232 }
1233 return TRUE;
1234 }
1235 DBG1(DBG_LIB, "failed to stat '%s': %s", file, strerror(errno));
1236 return FALSE;
1237 }
1238 else if (!S_ISREG(st.st_mode))
1239 {
1240 DBG1(DBG_LIB, "'%s' is not a regular file", file);
1241 return FALSE;
1242 }
1243 fd = fopen(file, "r");
1244 if (fd == NULL)
1245 {
1246 DBG1(DBG_LIB, "'%s' is not readable", file);
1247 return FALSE;
1248 }
1249 fseek(fd, 0, SEEK_END);
1250 len = ftell(fd);
1251 rewind(fd);
1252 text = malloc(len + 2);
1253 text[len] = text[len + 1] = '\0';
1254 if (fread(text, 1, len, fd) != len)
1255 {
1256 free(text);
1257 fclose(fd);
1258 return FALSE;
1259 }
1260 fclose(fd);
1261
1262 pos = text;
1263 success = parse_section(contents, file, level, &pos, section);
1264 if (!success)
1265 {
1266 free(text);
1267 }
1268 else
1269 {
1270 contents->insert_last(contents, text);
1271 }
1272 return success;
1273 }
1274
1275 /**
1276 * Load the files matching "pattern", which is resolved with glob(3), if
1277 * available.
1278 * If the pattern is relative, the directory of "file" is used as base.
1279 */
1280 static bool parse_files(linked_list_t *contents, char *file, int level,
1281 char *pattern, section_t *section)
1282 {
1283 enumerator_t *enumerator;
1284 bool success = TRUE;
1285 char pat[PATH_MAX], *expanded;
1286
1287 if (level > MAX_INCLUSION_LEVEL)
1288 {
1289 DBG1(DBG_LIB, "maximum level of %d includes reached, ignored",
1290 MAX_INCLUSION_LEVEL);
1291 return TRUE;
1292 }
1293
1294 if (!strlen(pattern))
1295 {
1296 DBG1(DBG_LIB, "empty include pattern, ignored");
1297 return TRUE;
1298 }
1299
1300 if (!file || pattern[0] == '/')
1301 { /* absolute path */
1302 if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
1303 {
1304 DBG1(DBG_LIB, "include pattern too long, ignored");
1305 return TRUE;
1306 }
1307 }
1308 else
1309 { /* base relative paths to the directory of the current file */
1310 char *dir = path_dirname(file);
1311 if (snprintf(pat, sizeof(pat), "%s/%s", dir, pattern) >= sizeof(pat))
1312 {
1313 DBG1(DBG_LIB, "include pattern too long, ignored");
1314 free(dir);
1315 return TRUE;
1316 }
1317 free(dir);
1318 }
1319 enumerator = enumerator_create_glob(pat);
1320 if (enumerator)
1321 {
1322 while (enumerator->enumerate(enumerator, &expanded, NULL))
1323 {
1324 success &= parse_file(contents, expanded, level + 1, section);
1325 if (!success)
1326 {
1327 break;
1328 }
1329 }
1330 enumerator->destroy(enumerator);
1331 }
1332 else
1333 { /* if glob(3) is not available, try to load pattern directly */
1334 success = parse_file(contents, pat, level + 1, section);
1335 }
1336 return success;
1337 }
1338
1339 /**
1340 * Recursivly extends "base" with "extension".
1341 */
1342 static void section_extend(section_t *base, section_t *extension)
1343 {
1344 enumerator_t *enumerator;
1345 section_t *sec;
1346 kv_t *kv;
1347
1348 enumerator = array_create_enumerator(extension->sections);
1349 while (enumerator->enumerate(enumerator, (void**)&sec))
1350 {
1351 section_t *found;
1352 if (array_bsearch(base->sections, sec->name, section_find,
1353 &found) != -1)
1354 {
1355 section_extend(found, sec);
1356 }
1357 else
1358 {
1359 array_remove_at(extension->sections, enumerator);
1360 array_insert_create(&base->sections, ARRAY_TAIL, sec);
1361 array_sort(base->sections, section_sort, NULL);
1362 }
1363 }
1364 enumerator->destroy(enumerator);
1365
1366 enumerator = array_create_enumerator(extension->kv);
1367 while (enumerator->enumerate(enumerator, (void**)&kv))
1368 {
1369 kv_t *found;
1370 if (array_bsearch(base->kv, kv->key, kv_find, &found) != -1)
1371 {
1372 found->value = kv->value;
1373 }
1374 else
1375 {
1376 array_remove_at(extension->kv, enumerator);
1377 array_insert_create(&base->kv, ARRAY_TAIL, kv);
1378 array_sort(base->kv, kv_sort, NULL);
1379 }
1380 }
1381 enumerator->destroy(enumerator);
1382 }
1383
1384 /**
1385 * Load settings from files matching the given file pattern.
1386 * All sections and values are added relative to "parent".
1387 * All files (even included ones) have to be loaded successfully.
1388 */
1389 static bool load_files_internal(private_settings_t *this, section_t *parent,
1390 char *pattern, bool merge)
1391 {
1392 char *text;
1393 linked_list_t *contents;
1394 section_t *section;
1395
1396 if (pattern == NULL)
1397 {
1398 #ifdef STRONGSWAN_CONF
1399 pattern = STRONGSWAN_CONF;
1400 #else
1401 return FALSE;
1402 #endif
1403 }
1404
1405 contents = linked_list_create();
1406 section = section_create(NULL);
1407
1408 if (!parse_files(contents, NULL, 0, pattern, section))
1409 {
1410 contents->destroy_function(contents, (void*)free);
1411 section_destroy(section);
1412 return FALSE;
1413 }
1414
1415 this->lock->write_lock(this->lock);
1416 if (!merge)
1417 {
1418 section_purge(parent);
1419 }
1420 /* extend parent section */
1421 section_extend(parent, section);
1422 /* move contents of loaded files to main store */
1423 while (contents->remove_first(contents, (void**)&text) == SUCCESS)
1424 {
1425 this->contents->insert_last(this->contents, text);
1426 }
1427 this->lock->unlock(this->lock);
1428
1429 section_destroy(section);
1430 contents->destroy(contents);
1431 return TRUE;
1432 }
1433
1434 METHOD(settings_t, load_files, bool,
1435 private_settings_t *this, char *pattern, bool merge)
1436 {
1437 return load_files_internal(this, this->top, pattern, merge);
1438 }
1439
1440 METHOD(settings_t, load_files_section, bool,
1441 private_settings_t *this, char *pattern, bool merge, char *key, ...)
1442 {
1443 section_t *section;
1444 va_list args;
1445
1446 va_start(args, key);
1447 section = ensure_section(this, this->top, key, args);
1448 va_end(args);
1449
1450 if (!section)
1451 {
1452 return FALSE;
1453 }
1454 return load_files_internal(this, section, pattern, merge);
1455 }
1456
1457 METHOD(settings_t, destroy, void,
1458 private_settings_t *this)
1459 {
1460 section_destroy(this->top);
1461 this->contents->destroy_function(this->contents, (void*)free);
1462 this->lock->destroy(this->lock);
1463 free(this);
1464 }
1465
1466 /*
1467 * see header file
1468 */
1469 settings_t *settings_create(char *file)
1470 {
1471 private_settings_t *this;
1472
1473 INIT(this,
1474 .public = {
1475 .get_str = _get_str,
1476 .get_int = _get_int,
1477 .get_double = _get_double,
1478 .get_time = _get_time,
1479 .get_bool = _get_bool,
1480 .set_str = _set_str,
1481 .set_int = _set_int,
1482 .set_double = _set_double,
1483 .set_time = _set_time,
1484 .set_bool = _set_bool,
1485 .set_default_str = _set_default_str,
1486 .create_section_enumerator = _create_section_enumerator,
1487 .create_key_value_enumerator = _create_key_value_enumerator,
1488 .add_fallback = _add_fallback,
1489 .load_files = _load_files,
1490 .load_files_section = _load_files_section,
1491 .destroy = _destroy,
1492 },
1493 .top = section_create(NULL),
1494 .contents = linked_list_create(),
1495 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1496 );
1497
1498 load_files(this, file, FALSE);
1499
1500 return &this->public;
1501 }