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