make IMC/IMV pairs independent of libcharon
[strongswan.git] / src / libstrongswan / settings.c
1 /*
2 * Copyright (C) 2010 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 <libgen.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27
28 #ifdef HAVE_GLOB_H
29 #include <glob.h>
30 #endif /* HAVE_GLOB_H */
31
32 #include "settings.h"
33
34 #include "debug.h"
35 #include "utils/linked_list.h"
36 #include "threading/rwlock.h"
37
38 #define MAX_INCLUSION_LEVEL 10
39
40 typedef struct private_settings_t private_settings_t;
41 typedef struct section_t section_t;
42 typedef struct kv_t kv_t;
43
44 /**
45 * private data of settings
46 */
47 struct private_settings_t {
48
49 /**
50 * public functions
51 */
52 settings_t public;
53
54 /**
55 * top level section
56 */
57 section_t *top;
58
59 /**
60 * contents of loaded files and in-memory settings (char*)
61 */
62 linked_list_t *contents;
63
64 /**
65 * lock to safely access the settings
66 */
67 rwlock_t *lock;
68 };
69
70 /**
71 * section containing subsections and key value pairs
72 */
73 struct section_t {
74
75 /**
76 * name of the section
77 */
78 char *name;
79
80 /**
81 * subsections, as section_t
82 */
83 linked_list_t *sections;
84
85 /**
86 * key value pairs, as kv_t
87 */
88 linked_list_t *kv;
89 };
90
91 /**
92 * Key value pair
93 */
94 struct kv_t {
95
96 /**
97 * key string, relative
98 */
99 char *key;
100
101 /**
102 * value as string
103 */
104 char *value;
105 };
106
107 /**
108 * create a key/value pair
109 */
110 static kv_t *kv_create(char *key, char *value)
111 {
112 kv_t *this;
113 INIT(this,
114 .key = strdup(key),
115 .value = value,
116 );
117 return this;
118 }
119
120 /**
121 * destroy a key/value pair
122 */
123 static void kv_destroy(kv_t *this)
124 {
125 free(this->key);
126 free(this);
127 }
128
129 /**
130 * create a section with the given name
131 */
132 static section_t *section_create(char *name)
133 {
134 section_t *this;
135 INIT(this,
136 .name = strdupnull(name),
137 .sections = linked_list_create(),
138 .kv = linked_list_create(),
139 );
140 return this;
141 }
142
143 /**
144 * destroy a section
145 */
146 static void section_destroy(section_t *this)
147 {
148 this->kv->destroy_function(this->kv, (void*)kv_destroy);
149 this->sections->destroy_function(this->sections, (void*)section_destroy);
150 free(this->name);
151 free(this);
152 }
153
154 /**
155 * Purge contents of a section
156 */
157 static void section_purge(section_t *this)
158 {
159 this->kv->destroy_function(this->kv, (void*)kv_destroy);
160 this->kv = linked_list_create();
161 this->sections->destroy_function(this->sections, (void*)section_destroy);
162 this->sections = linked_list_create();
163 }
164
165 /**
166 * callback to find a section by name
167 */
168 static bool section_find(section_t *this, char *name)
169 {
170 return streq(this->name, name);
171 }
172
173 /**
174 * callback to find a kv pair by key
175 */
176 static bool kv_find(kv_t *this, char *key)
177 {
178 return streq(this->key, key);
179 }
180
181 /**
182 * Print a format key, but consume already processed arguments
183 */
184 static bool print_key(char *buf, int len, char *start, char *key, va_list args)
185 {
186 va_list copy;
187 bool res;
188 char *pos;
189
190 va_copy(copy, args);
191 while (start < key)
192 {
193 pos = strchr(start, '%');
194 if (!pos)
195 {
196 start += strlen(start) + 1;
197 continue;
198 }
199 pos++;
200 switch (*pos)
201 {
202 case 'd':
203 va_arg(copy, int);
204 break;
205 case 's':
206 va_arg(copy, char*);
207 break;
208 case 'N':
209 va_arg(copy, enum_name_t*);
210 va_arg(copy, int);
211 break;
212 case '%':
213 break;
214 default:
215 DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
216 break;
217 }
218 start = pos;
219 if (*start)
220 {
221 start++;
222 }
223 }
224 res = vsnprintf(buf, len, key, copy) < len;
225 va_end(copy);
226 return res;
227 }
228
229 /**
230 * Find a section by a given key, using buffered key, reusable buffer.
231 * If "ensure" is TRUE, the sections are created if they don't exist.
232 */
233 static section_t *find_section_buffered(section_t *section,
234 char *start, char *key, va_list args, char *buf, int len,
235 bool ensure)
236 {
237 char *pos;
238 section_t *found = NULL;
239
240 if (section == NULL)
241 {
242 return NULL;
243 }
244 pos = strchr(key, '.');
245 if (pos)
246 {
247 *pos = '\0';
248 pos++;
249 }
250 if (!print_key(buf, len, start, key, args))
251 {
252 return NULL;
253 }
254 if (section->sections->find_first(section->sections,
255 (linked_list_match_t)section_find,
256 (void**)&found, buf) != SUCCESS)
257 {
258 if (ensure)
259 {
260 found = section_create(buf);
261 section->sections->insert_last(section->sections, found);
262 }
263 }
264 if (found && pos)
265 {
266 return find_section_buffered(found, start, pos, args, buf, len, ensure);
267 }
268 return found;
269 }
270
271 /**
272 * Find a section by a given key (thread-safe).
273 */
274 static section_t *find_section(private_settings_t *this, section_t *section,
275 char *key, va_list args)
276 {
277 char buf[128], keybuf[512];
278 section_t *found;
279
280 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
281 {
282 return NULL;
283 }
284 this->lock->read_lock(this->lock);
285 found = find_section_buffered(section, keybuf, keybuf, args, buf,
286 sizeof(buf), FALSE);
287 this->lock->unlock(this->lock);
288 return found;
289 }
290
291 /**
292 * Ensure that the section with the given key exists (thread-safe).
293 */
294 static section_t *ensure_section(private_settings_t *this, section_t *section,
295 char *key, va_list args)
296 {
297 char buf[128], keybuf[512];
298 section_t *found;
299
300 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
301 {
302 return NULL;
303 }
304 /* we might have to change the tree */
305 this->lock->write_lock(this->lock);
306 found = find_section_buffered(section, keybuf, keybuf, args, buf,
307 sizeof(buf), TRUE);
308 this->lock->unlock(this->lock);
309 return found;
310 }
311
312 /**
313 * Find the key/value pair for a key, using buffered key, reusable buffer
314 * If "ensure" is TRUE, the sections (and key/value pair) are created if they
315 * don't exist.
316 */
317 static kv_t *find_value_buffered(section_t *section, char *start, char *key,
318 va_list args, char *buf, int len, bool ensure)
319 {
320 char *pos;
321 kv_t *kv = NULL;
322 section_t *found = NULL;
323
324 if (section == NULL)
325 {
326 return NULL;
327 }
328
329 pos = strchr(key, '.');
330 if (pos)
331 {
332 *pos = '\0';
333 pos++;
334
335 if (!print_key(buf, len, start, key, args))
336 {
337 return NULL;
338 }
339 if (section->sections->find_first(section->sections,
340 (linked_list_match_t)section_find,
341 (void**)&found, buf) != SUCCESS)
342 {
343 if (!ensure)
344 {
345 return NULL;
346 }
347 found = section_create(buf);
348 section->sections->insert_last(section->sections, found);
349 }
350 return find_value_buffered(found, start, pos, args, buf, len,
351 ensure);
352 }
353 else
354 {
355 if (!print_key(buf, len, start, key, args))
356 {
357 return NULL;
358 }
359 if (section->kv->find_first(section->kv, (linked_list_match_t)kv_find,
360 (void**)&kv, buf) != SUCCESS)
361 {
362 if (ensure)
363 {
364 kv = kv_create(buf, NULL);
365 section->kv->insert_last(section->kv, kv);
366 }
367 }
368 }
369 return kv;
370 }
371
372 /**
373 * Find the string value for a key (thread-safe).
374 */
375 static char *find_value(private_settings_t *this, section_t *section,
376 char *key, va_list args)
377 {
378 char buf[128], keybuf[512], *value = NULL;
379 kv_t *kv;
380
381 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
382 {
383 return NULL;
384 }
385 this->lock->read_lock(this->lock);
386 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
387 FALSE);
388 if (kv)
389 {
390 value = kv->value;
391 }
392 this->lock->unlock(this->lock);
393 return value;
394 }
395
396 /**
397 * Set a value to a copy of the given string (thread-safe).
398 */
399 static void set_value(private_settings_t *this, section_t *section,
400 char *key, va_list args, char *value)
401 {
402 char buf[128], keybuf[512];
403 kv_t *kv;
404
405 if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
406 {
407 return;
408 }
409 this->lock->write_lock(this->lock);
410 kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
411 TRUE);
412 if (kv)
413 {
414 if (!value)
415 {
416 kv->value = NULL;
417 }
418 else if (kv->value && (strlen(value) <= strlen(kv->value)))
419 { /* overwrite in-place, if possible */
420 strcpy(kv->value, value);
421 }
422 else
423 { /* otherwise clone the string and store it in the cache */
424 kv->value = strdup(value);
425 this->contents->insert_last(this->contents, kv->value);
426 }
427 }
428 this->lock->unlock(this->lock);
429 }
430
431 METHOD(settings_t, get_str, char*,
432 private_settings_t *this, char *key, char *def, ...)
433 {
434 char *value;
435 va_list args;
436
437 va_start(args, def);
438 value = find_value(this, this->top, key, args);
439 va_end(args);
440 if (value)
441 {
442 return value;
443 }
444 return def;
445 }
446
447 /**
448 * Described in header
449 */
450 inline bool settings_value_as_bool(char *value, bool def)
451 {
452 if (value)
453 {
454 if (strcaseeq(value, "1") ||
455 strcaseeq(value, "yes") ||
456 strcaseeq(value, "true") ||
457 strcaseeq(value, "enabled"))
458 {
459 return TRUE;
460 }
461 else if (strcaseeq(value, "0") ||
462 strcaseeq(value, "no") ||
463 strcaseeq(value, "false") ||
464 strcaseeq(value, "disabled"))
465 {
466 return FALSE;
467 }
468 }
469 return def;
470 }
471
472 METHOD(settings_t, get_bool, bool,
473 private_settings_t *this, char *key, bool def, ...)
474 {
475 char *value;
476 va_list args;
477
478 va_start(args, def);
479 value = find_value(this, this->top, key, args);
480 va_end(args);
481 return settings_value_as_bool(value, def);
482 }
483
484 /**
485 * Described in header
486 */
487 inline int settings_value_as_int(char *value, int def)
488 {
489 int intval;
490 if (value)
491 {
492 errno = 0;
493 intval = strtol(value, NULL, 10);
494 if (errno == 0)
495 {
496 return intval;
497 }
498 }
499 return def;
500 }
501
502 METHOD(settings_t, get_int, int,
503 private_settings_t *this, char *key, int def, ...)
504 {
505 char *value;
506 va_list args;
507
508 va_start(args, def);
509 value = find_value(this, this->top, key, args);
510 va_end(args);
511 return settings_value_as_int(value, def);
512 }
513
514 /**
515 * Described in header
516 */
517 inline double settings_value_as_double(char *value, double def)
518 {
519 double dval;
520 if (value)
521 {
522 errno = 0;
523 dval = strtod(value, NULL);
524 if (errno == 0)
525 {
526 return dval;
527 }
528 }
529 return def;
530 }
531
532 METHOD(settings_t, get_double, double,
533 private_settings_t *this, char *key, double def, ...)
534 {
535 char *value;
536 va_list args;
537
538 va_start(args, def);
539 value = find_value(this, this->top, key, args);
540 va_end(args);
541 return settings_value_as_double(value, def);
542 }
543
544 /**
545 * Described in header
546 */
547 inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
548 {
549 char *endptr;
550 u_int32_t timeval;
551 if (value)
552 {
553 errno = 0;
554 timeval = strtoul(value, &endptr, 10);
555 if (errno == 0)
556 {
557 switch (*endptr)
558 {
559 case 'd': /* time in days */
560 timeval *= 24 * 3600;
561 break;
562 case 'h': /* time in hours */
563 timeval *= 3600;
564 break;
565 case 'm': /* time in minutes */
566 timeval *= 60;
567 break;
568 case 's': /* time in seconds */
569 default:
570 break;
571 }
572 return timeval;
573 }
574 }
575 return def;
576 }
577
578 METHOD(settings_t, get_time, u_int32_t,
579 private_settings_t *this, char *key, u_int32_t def, ...)
580 {
581 char *value;
582 va_list args;
583
584 va_start(args, def);
585 value = find_value(this, this->top, key, args);
586 va_end(args);
587 return settings_value_as_time(value, def);
588 }
589
590 METHOD(settings_t, set_str, void,
591 private_settings_t *this, char *key, char *value, ...)
592 {
593 va_list args;
594 va_start(args, value);
595 set_value(this, this->top, key, args, value);
596 va_end(args);
597 }
598
599 METHOD(settings_t, set_bool, void,
600 private_settings_t *this, char *key, bool value, ...)
601 {
602 va_list args;
603 va_start(args, value);
604 set_value(this, this->top, key, args, value ? "1" : "0");
605 va_end(args);
606 }
607
608 METHOD(settings_t, set_int, void,
609 private_settings_t *this, char *key, int value, ...)
610 {
611 char val[16];
612 va_list args;
613 va_start(args, value);
614 if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
615 {
616 set_value(this, this->top, key, args, val);
617 }
618 va_end(args);
619 }
620
621 METHOD(settings_t, set_double, void,
622 private_settings_t *this, char *key, double value, ...)
623 {
624 char val[64];
625 va_list args;
626 va_start(args, value);
627 if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
628 {
629 set_value(this, this->top, key, args, val);
630 }
631 va_end(args);
632 }
633
634 METHOD(settings_t, set_time, void,
635 private_settings_t *this, char *key, u_int32_t value, ...)
636 {
637 char val[16];
638 va_list args;
639 va_start(args, value);
640 if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
641 {
642 set_value(this, this->top, key, args, val);
643 }
644 va_end(args);
645 }
646
647 /**
648 * Enumerate section names, not sections
649 */
650 static bool section_filter(void *null, section_t **in, char **out)
651 {
652 *out = (*in)->name;
653 return TRUE;
654 }
655
656 METHOD(settings_t, create_section_enumerator, enumerator_t*,
657 private_settings_t *this, char *key, ...)
658 {
659 section_t *section;
660 va_list args;
661
662 va_start(args, key);
663 section = find_section(this, this->top, key, args);
664 va_end(args);
665
666 if (!section)
667 {
668 return enumerator_create_empty();
669 }
670 this->lock->read_lock(this->lock);
671 return enumerator_create_filter(
672 section->sections->create_enumerator(section->sections),
673 (void*)section_filter, this->lock, (void*)this->lock->unlock);
674 }
675
676 /**
677 * Enumerate key and values, not kv_t entries
678 */
679 static bool kv_filter(void *null, kv_t **in, char **key,
680 void *none, char **value)
681 {
682 *key = (*in)->key;
683 *value = (*in)->value;
684 return TRUE;
685 }
686
687 METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
688 private_settings_t *this, char *key, ...)
689 {
690 section_t *section;
691 va_list args;
692
693 va_start(args, key);
694 section = find_section(this, this->top, key, args);
695 va_end(args);
696
697 if (!section)
698 {
699 return enumerator_create_empty();
700 }
701 this->lock->read_lock(this->lock);
702 return enumerator_create_filter(
703 section->kv->create_enumerator(section->kv),
704 (void*)kv_filter, this->lock, (void*)this->lock->unlock);
705 }
706
707 /**
708 * parse text, truncate "skip" chars, delimited by term respecting brackets.
709 *
710 * Chars in "skip" are truncated at the beginning and the end of the resulting
711 * token. "term" contains a list of characters to read up to (first match),
712 * while "br" contains bracket counterparts found in "term" to skip.
713 */
714 static char parse(char **text, char *skip, char *term, char *br, char **token)
715 {
716 char *best = NULL;
717 char best_term = '\0';
718
719 /* skip leading chars */
720 while (strchr(skip, **text))
721 {
722 (*text)++;
723 if (!**text)
724 {
725 return 0;
726 }
727 }
728 /* mark begin of subtext */
729 *token = *text;
730 while (*term)
731 {
732 char *pos = *text;
733 int level = 1;
734
735 /* find terminator */
736 while (*pos)
737 {
738 if (*pos == *term)
739 {
740 level--;
741 }
742 else if (br && *pos == *br)
743 {
744 level++;
745 }
746 if (level == 0)
747 {
748 if (best == NULL || best > pos)
749 {
750 best = pos;
751 best_term = *term;
752 }
753 break;
754 }
755 pos++;
756 }
757 /* try next terminator */
758 term++;
759 if (br)
760 {
761 br++;
762 }
763 }
764 if (best)
765 {
766 /* update input */
767 *text = best;
768 /* null trailing bytes */
769 do
770 {
771 *best = '\0';
772 best--;
773 }
774 while (best >= *token && strchr(skip, *best));
775 /* return found terminator */
776 return best_term;
777 }
778 return 0;
779 }
780
781 /**
782 * Check if "text" starts with "pattern".
783 * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
784 * is modified to point to the character right after "pattern".
785 */
786 static bool starts_with(char **text, char *skip, char *pattern)
787 {
788 char *pos = *text;
789 int len = strlen(pattern);
790 while (strchr(skip, *pos))
791 {
792 pos++;
793 if (!*pos)
794 {
795 return FALSE;
796 }
797 }
798 if (strlen(pos) < len || !strneq(pos, pattern, len))
799 {
800 return FALSE;
801 }
802 *text = pos + len;
803 return TRUE;
804 }
805
806 /**
807 * Check if what follows in "text" is an include statement.
808 * If this function returns TRUE, "text" will point to the character right after
809 * the include pattern, which is returned in "pattern".
810 */
811 static bool parse_include(char **text, char **pattern)
812 {
813 char *pos = *text;
814 if (!starts_with(&pos, "\n\t ", "include"))
815 {
816 return FALSE;
817 }
818 if (starts_with(&pos, "\t ", "="))
819 { /* ignore "include = value" */
820 return FALSE;
821 }
822 *text = pos;
823 return parse(text, "\t ", "\n", NULL, pattern) != 0;
824 }
825
826 /**
827 * Forward declaration.
828 */
829 static bool parse_files(linked_list_t *contents, char *file, int level,
830 char *pattern, section_t *section);
831
832 /**
833 * Parse a section
834 */
835 static bool parse_section(linked_list_t *contents, char *file, int level,
836 char **text, section_t *section)
837 {
838 bool finished = FALSE;
839 char *key, *value, *inner;
840
841 while (!finished)
842 {
843 if (parse_include(text, &value))
844 {
845 if (!parse_files(contents, file, level, value, section))
846 {
847 DBG1(DBG_LIB, "failed to include '%s'", value);
848 return FALSE;
849 }
850 continue;
851 }
852 switch (parse(text, "\t\n ", "{=#", NULL, &key))
853 {
854 case '{':
855 if (parse(text, "\t ", "}", "{", &inner))
856 {
857 section_t *sub;
858 if (!strlen(key))
859 {
860 DBG1(DBG_LIB, "skipping section without name in '%s'",
861 section->name);
862 continue;
863 }
864 if (section->sections->find_first(section->sections,
865 (linked_list_match_t)section_find,
866 (void**)&sub, key) != SUCCESS)
867 {
868 sub = section_create(key);
869 if (parse_section(contents, file, level, &inner, sub))
870 {
871 section->sections->insert_last(section->sections,
872 sub);
873 continue;
874 }
875 section_destroy(sub);
876 }
877 else
878 { /* extend the existing section */
879 if (parse_section(contents, file, level, &inner, sub))
880 {
881 continue;
882 }
883 }
884 DBG1(DBG_LIB, "parsing subsection '%s' failed", key);
885 break;
886 }
887 DBG1(DBG_LIB, "matching '}' not found near %s", *text);
888 break;
889 case '=':
890 if (parse(text, "\t ", "\n", NULL, &value))
891 {
892 kv_t *kv;
893 if (!strlen(key))
894 {
895 DBG1(DBG_LIB, "skipping value without key in '%s'",
896 section->name);
897 continue;
898 }
899 if (section->kv->find_first(section->kv,
900 (linked_list_match_t)kv_find,
901 (void**)&kv, key) != SUCCESS)
902 {
903 kv = kv_create(key, value);
904 section->kv->insert_last(section->kv, kv);
905 }
906 else
907 { /* replace with the most recently read value */
908 kv->value = value;
909 }
910 continue;
911 }
912 DBG1(DBG_LIB, "parsing value failed near %s", *text);
913 break;
914 case '#':
915 parse(text, "", "\n", NULL, &value);
916 continue;
917 default:
918 finished = TRUE;
919 continue;
920 }
921 return FALSE;
922 }
923 return TRUE;
924 }
925
926 /**
927 * Parse a file and add the settings to the given section.
928 */
929 static bool parse_file(linked_list_t *contents, char *file, int level,
930 section_t *section)
931 {
932 bool success;
933 char *text, *pos;
934 struct stat st;
935 FILE *fd;
936 int len;
937
938 DBG2(DBG_LIB, "loading config file '%s'", file);
939 if (stat(file, &st) == -1)
940 {
941 if (errno == ENOENT)
942 {
943 DBG2(DBG_LIB, "'%s' does not exist, ignored", file);
944 return TRUE;
945 }
946 DBG1(DBG_LIB, "failed to stat '%s': %s", file, strerror(errno));
947 return FALSE;
948 }
949 else if (!S_ISREG(st.st_mode))
950 {
951 DBG1(DBG_LIB, "'%s' is not a regular file", file);
952 return FALSE;
953 }
954 fd = fopen(file, "r");
955 if (fd == NULL)
956 {
957 DBG1(DBG_LIB, "'%s' is not readable", file);
958 return FALSE;
959 }
960 fseek(fd, 0, SEEK_END);
961 len = ftell(fd);
962 rewind(fd);
963 text = malloc(len + 1);
964 text[len] = '\0';
965 if (fread(text, 1, len, fd) != len)
966 {
967 free(text);
968 return FALSE;
969 }
970 fclose(fd);
971
972 pos = text;
973 success = parse_section(contents, file, level, &pos, section);
974 if (!success)
975 {
976 free(text);
977 }
978 else
979 {
980 contents->insert_last(contents, text);
981 }
982 return success;
983 }
984
985 /**
986 * Load the files matching "pattern", which is resolved with glob(3), if
987 * available.
988 * If the pattern is relative, the directory of "file" is used as base.
989 */
990 static bool parse_files(linked_list_t *contents, char *file, int level,
991 char *pattern, section_t *section)
992 {
993 bool success = TRUE;
994 char pat[PATH_MAX];
995
996 if (level > MAX_INCLUSION_LEVEL)
997 {
998 DBG1(DBG_LIB, "maximum level of %d includes reached, ignored",
999 MAX_INCLUSION_LEVEL);
1000 return TRUE;
1001 }
1002
1003 if (!strlen(pattern))
1004 {
1005 DBG2(DBG_LIB, "empty include pattern, ignored");
1006 return TRUE;
1007 }
1008
1009 if (!file || pattern[0] == '/')
1010 { /* absolute path */
1011 if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
1012 {
1013 DBG1(DBG_LIB, "include pattern too long, ignored");
1014 return TRUE;
1015 }
1016 }
1017 else
1018 { /* base relative paths to the directory of the current file */
1019 char *dir = strdup(file);
1020 dir = dirname(dir);
1021 if (snprintf(pat, sizeof(pat), "%s/%s", dir, pattern) >= sizeof(pat))
1022 {
1023 DBG1(DBG_LIB, "include pattern too long, ignored");
1024 free(dir);
1025 return TRUE;
1026 }
1027 free(dir);
1028 }
1029 #ifdef HAVE_GLOB_H
1030 {
1031 int status;
1032 glob_t buf;
1033
1034 status = glob(pat, GLOB_ERR, NULL, &buf);
1035 if (status == GLOB_NOMATCH)
1036 {
1037 DBG2(DBG_LIB, "no files found matching '%s', ignored", pat);
1038 }
1039 else if (status != 0)
1040 {
1041 DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat);
1042 success = FALSE;
1043 }
1044 else
1045 {
1046 char **expanded;
1047 for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
1048 {
1049 success &= parse_file(contents, *expanded, level + 1, section);
1050 if (!success)
1051 {
1052 break;
1053 }
1054 }
1055 }
1056 globfree(&buf);
1057 }
1058 #else /* HAVE_GLOB_H */
1059 /* if glob(3) is not available, try to load pattern directly */
1060 success = parse_file(contents, pat, level + 1, section);
1061 #endif /* HAVE_GLOB_H */
1062 return success;
1063 }
1064
1065 /**
1066 * Recursivly extends "base" with "extension".
1067 */
1068 static void section_extend(section_t *base, section_t *extension)
1069 {
1070 enumerator_t *enumerator;
1071 section_t *sec;
1072 kv_t *kv;
1073
1074 enumerator = extension->sections->create_enumerator(extension->sections);
1075 while (enumerator->enumerate(enumerator, (void**)&sec))
1076 {
1077 section_t *found;
1078 if (base->sections->find_first(base->sections,
1079 (linked_list_match_t)section_find, (void**)&found,
1080 sec->name) == SUCCESS)
1081 {
1082 section_extend(found, sec);
1083 }
1084 else
1085 {
1086 extension->sections->remove_at(extension->sections, enumerator);
1087 base->sections->insert_last(base->sections, sec);
1088 }
1089 }
1090 enumerator->destroy(enumerator);
1091
1092 enumerator = extension->kv->create_enumerator(extension->kv);
1093 while (enumerator->enumerate(enumerator, (void**)&kv))
1094 {
1095 kv_t *found;
1096 if (base->kv->find_first(base->kv, (linked_list_match_t)kv_find,
1097 (void**)&found, kv->key) == SUCCESS)
1098 {
1099 found->value = kv->value;
1100 }
1101 else
1102 {
1103 extension->kv->remove_at(extension->kv, enumerator);
1104 base->kv->insert_last(base->kv, kv);
1105 }
1106 }
1107 enumerator->destroy(enumerator);
1108 }
1109
1110 /**
1111 * Load settings from files matching the given file pattern.
1112 * All sections and values are added relative to "parent".
1113 * All files (even included ones) have to be loaded successfully.
1114 */
1115 static bool load_files_internal(private_settings_t *this, section_t *parent,
1116 char *pattern, bool merge)
1117 {
1118 char *text;
1119 linked_list_t *contents = linked_list_create();
1120 section_t *section = section_create(NULL);
1121
1122 if (pattern == NULL)
1123 {
1124 pattern = STRONGSWAN_CONF;
1125 }
1126
1127 if (!parse_files(contents, NULL, 0, pattern, section))
1128 {
1129 contents->destroy_function(contents, (void*)free);
1130 section_destroy(section);
1131 return FALSE;
1132 }
1133
1134 this->lock->write_lock(this->lock);
1135 if (!merge)
1136 {
1137 section_purge(parent);
1138 }
1139 /* extend parent section */
1140 section_extend(parent, section);
1141 /* move contents of loaded files to main store */
1142 while (contents->remove_first(contents, (void**)&text) == SUCCESS)
1143 {
1144 this->contents->insert_last(this->contents, text);
1145 }
1146 this->lock->unlock(this->lock);
1147
1148 section_destroy(section);
1149 contents->destroy(contents);
1150 return TRUE;
1151 }
1152
1153 METHOD(settings_t, load_files, bool,
1154 private_settings_t *this, char *pattern, bool merge)
1155 {
1156 return load_files_internal(this, this->top, pattern, merge);
1157 }
1158
1159 METHOD(settings_t, load_files_section, bool,
1160 private_settings_t *this, char *pattern, bool merge, char *key, ...)
1161 {
1162 section_t *section;
1163 va_list args;
1164
1165 va_start(args, key);
1166 section = ensure_section(this, this->top, key, args);
1167 va_end(args);
1168
1169 if (!section)
1170 {
1171 return FALSE;
1172 }
1173 return load_files_internal(this, section, pattern, merge);
1174 }
1175
1176 METHOD(settings_t, destroy, void,
1177 private_settings_t *this)
1178 {
1179 section_destroy(this->top);
1180 this->contents->destroy_function(this->contents, (void*)free);
1181 this->lock->destroy(this->lock);
1182 free(this);
1183 }
1184
1185 /*
1186 * see header file
1187 */
1188 settings_t *settings_create(char *file)
1189 {
1190 private_settings_t *this;
1191
1192 INIT(this,
1193 .public = {
1194 .get_str = _get_str,
1195 .get_int = _get_int,
1196 .get_double = _get_double,
1197 .get_time = _get_time,
1198 .get_bool = _get_bool,
1199 .set_str = _set_str,
1200 .set_int = _set_int,
1201 .set_double = _set_double,
1202 .set_time = _set_time,
1203 .set_bool = _set_bool,
1204 .create_section_enumerator = _create_section_enumerator,
1205 .create_key_value_enumerator = _create_key_value_enumerator,
1206 .load_files = _load_files,
1207 .load_files_section = _load_files_section,
1208 .destroy = _destroy,
1209 },
1210 .top = section_create(NULL),
1211 .contents = linked_list_create(),
1212 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1213 );
1214
1215 load_files(this, file, FALSE);
1216
1217 return &this->public;
1218 }
1219