2 * Copyright (C) 2010 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
24 #include <sys/types.h>
30 #endif /* HAVE_GLOB_H */
35 #include "utils/linked_list.h"
36 #include "threading/rwlock.h"
38 #define MAX_INCLUSION_LEVEL 10
40 typedef struct private_settings_t private_settings_t
;
41 typedef struct section_t section_t
;
42 typedef struct kv_t kv_t
;
45 * private data of settings
47 struct private_settings_t
{
60 * contents of loaded files and in-memory settings (char*)
62 linked_list_t
*contents
;
65 * lock to safely access the settings
71 * section containing subsections and key value pairs
81 * subsections, as section_t
83 linked_list_t
*sections
;
86 * key value pairs, as kv_t
97 * key string, relative
108 * create a key/value pair
110 static kv_t
*kv_create(char *key
, char *value
)
121 * destroy a key/value pair
123 static void kv_destroy(kv_t
*this)
130 * create a section with the given name
132 static section_t
*section_create(char *name
)
136 .name
= strdupnull(name
),
137 .sections
= linked_list_create(),
138 .kv
= linked_list_create(),
146 static void section_destroy(section_t
*this)
148 this->kv
->destroy_function(this->kv
, (void*)kv_destroy
);
149 this->sections
->destroy_function(this->sections
, (void*)section_destroy
);
155 * Purge contents of a section
157 static void section_purge(section_t
*this)
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();
166 * callback to find a section by name
168 static bool section_find(section_t
*this, char *name
)
170 return streq(this->name
, name
);
174 * callback to find a kv pair by key
176 static bool kv_find(kv_t
*this, char *key
)
178 return streq(this->key
, key
);
182 * Print a format key, but consume already processed arguments
184 static bool print_key(char *buf
, int len
, char *start
, char *key
, va_list args
)
193 pos
= strchr(start
, '%');
196 start
+= strlen(start
) + 1;
209 va_arg(copy
, enum_name_t
*);
215 DBG1(DBG_CFG
, "settings with %%%c not supported!", *pos
);
224 res
= vsnprintf(buf
, len
, key
, copy
) < len
;
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.
233 static section_t
*find_section_buffered(section_t
*section
,
234 char *start
, char *key
, va_list args
, char *buf
, int len
,
238 section_t
*found
= NULL
;
244 pos
= strchr(key
, '.');
250 if (!print_key(buf
, len
, start
, key
, args
))
254 if (section
->sections
->find_first(section
->sections
,
255 (linked_list_match_t
)section_find
,
256 (void**)&found
, buf
) != SUCCESS
)
260 found
= section_create(buf
);
261 section
->sections
->insert_last(section
->sections
, found
);
266 return find_section_buffered(found
, start
, pos
, args
, buf
, len
, ensure
);
272 * Find a section by a given key (thread-safe).
274 static section_t
*find_section(private_settings_t
*this, section_t
*section
,
275 char *key
, va_list args
)
277 char buf
[128], keybuf
[512];
280 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
284 this->lock
->read_lock(this->lock
);
285 found
= find_section_buffered(section
, keybuf
, keybuf
, args
, buf
,
287 this->lock
->unlock(this->lock
);
292 * Ensure that the section with the given key exists (thread-safe).
294 static section_t
*ensure_section(private_settings_t
*this, section_t
*section
,
295 char *key
, va_list args
)
297 char buf
[128], keybuf
[512];
300 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
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
,
308 this->lock
->unlock(this->lock
);
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
317 static kv_t
*find_value_buffered(section_t
*section
, char *start
, char *key
,
318 va_list args
, char *buf
, int len
, bool ensure
)
322 section_t
*found
= NULL
;
329 pos
= strchr(key
, '.');
335 if (!print_key(buf
, len
, start
, key
, args
))
339 if (section
->sections
->find_first(section
->sections
,
340 (linked_list_match_t
)section_find
,
341 (void**)&found
, buf
) != SUCCESS
)
347 found
= section_create(buf
);
348 section
->sections
->insert_last(section
->sections
, found
);
350 return find_value_buffered(found
, start
, pos
, args
, buf
, len
,
355 if (!print_key(buf
, len
, start
, key
, args
))
359 if (section
->kv
->find_first(section
->kv
, (linked_list_match_t
)kv_find
,
360 (void**)&kv
, buf
) != SUCCESS
)
364 kv
= kv_create(buf
, NULL
);
365 section
->kv
->insert_last(section
->kv
, kv
);
373 * Find the string value for a key (thread-safe).
375 static char *find_value(private_settings_t
*this, section_t
*section
,
376 char *key
, va_list args
)
378 char buf
[128], keybuf
[512], *value
= NULL
;
381 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
385 this->lock
->read_lock(this->lock
);
386 kv
= find_value_buffered(section
, keybuf
, keybuf
, args
, buf
, sizeof(buf
),
392 this->lock
->unlock(this->lock
);
397 * Set a value to a copy of the given string (thread-safe).
399 static void set_value(private_settings_t
*this, section_t
*section
,
400 char *key
, va_list args
, char *value
)
402 char buf
[128], keybuf
[512];
405 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
409 this->lock
->write_lock(this->lock
);
410 kv
= find_value_buffered(section
, keybuf
, keybuf
, args
, buf
, sizeof(buf
),
418 else if (kv
->value
&& (strlen(value
) <= strlen(kv
->value
)))
419 { /* overwrite in-place, if possible */
420 strcpy(kv
->value
, value
);
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
);
428 this->lock
->unlock(this->lock
);
431 METHOD(settings_t
, get_str
, char*,
432 private_settings_t
*this, char *key
, char *def
, ...)
438 value
= find_value(this, this->top
, key
, args
);
447 METHOD(settings_t
, alloc_str
, char*,
448 private_settings_t
*this, char *key
, char *def
, ...)
454 /* additional lock to savely strdup */
455 this->lock
->read_lock(this->lock
);
456 value
= strdupnull(find_value(this, this->top
, key
, args
) ?: def
);
457 this->lock
->unlock(this->lock
);
463 * Described in header
465 inline bool settings_value_as_bool(char *value
, bool def
)
469 if (strcaseeq(value
, "1") ||
470 strcaseeq(value
, "yes") ||
471 strcaseeq(value
, "true") ||
472 strcaseeq(value
, "enabled"))
476 else if (strcaseeq(value
, "0") ||
477 strcaseeq(value
, "no") ||
478 strcaseeq(value
, "false") ||
479 strcaseeq(value
, "disabled"))
487 METHOD(settings_t
, get_bool
, bool,
488 private_settings_t
*this, char *key
, bool def
, ...)
494 value
= find_value(this, this->top
, key
, args
);
496 return settings_value_as_bool(value
, def
);
500 * Described in header
502 inline int settings_value_as_int(char *value
, int def
)
508 intval
= strtol(value
, NULL
, 10);
517 METHOD(settings_t
, get_int
, int,
518 private_settings_t
*this, char *key
, int def
, ...)
524 value
= find_value(this, this->top
, key
, args
);
526 return settings_value_as_int(value
, def
);
530 * Described in header
532 inline double settings_value_as_double(char *value
, double def
)
538 dval
= strtod(value
, NULL
);
547 METHOD(settings_t
, get_double
, double,
548 private_settings_t
*this, char *key
, double def
, ...)
554 value
= find_value(this, this->top
, key
, args
);
556 return settings_value_as_double(value
, def
);
560 * Described in header
562 inline u_int32_t
settings_value_as_time(char *value
, u_int32_t def
)
569 timeval
= strtoul(value
, &endptr
, 10);
574 case 'd': /* time in days */
575 timeval
*= 24 * 3600;
577 case 'h': /* time in hours */
580 case 'm': /* time in minutes */
583 case 's': /* time in seconds */
593 METHOD(settings_t
, get_time
, u_int32_t
,
594 private_settings_t
*this, char *key
, u_int32_t def
, ...)
600 value
= find_value(this, this->top
, key
, args
);
602 return settings_value_as_time(value
, def
);
605 METHOD(settings_t
, set_str
, void,
606 private_settings_t
*this, char *key
, char *value
, ...)
609 va_start(args
, value
);
610 set_value(this, this->top
, key
, args
, value
);
614 METHOD(settings_t
, set_bool
, void,
615 private_settings_t
*this, char *key
, bool value
, ...)
618 va_start(args
, value
);
619 set_value(this, this->top
, key
, args
, value
? "1" : "0");
623 METHOD(settings_t
, set_int
, void,
624 private_settings_t
*this, char *key
, int value
, ...)
628 va_start(args
, value
);
629 if (snprintf(val
, sizeof(val
), "%d", value
) < sizeof(val
))
631 set_value(this, this->top
, key
, args
, val
);
636 METHOD(settings_t
, set_double
, void,
637 private_settings_t
*this, char *key
, double value
, ...)
641 va_start(args
, value
);
642 if (snprintf(val
, sizeof(val
), "%f", value
) < sizeof(val
))
644 set_value(this, this->top
, key
, args
, val
);
649 METHOD(settings_t
, set_time
, void,
650 private_settings_t
*this, char *key
, u_int32_t value
, ...)
654 va_start(args
, value
);
655 if (snprintf(val
, sizeof(val
), "%u", value
) < sizeof(val
))
657 set_value(this, this->top
, key
, args
, val
);
663 * Enumerate section names, not sections
665 static bool section_filter(void *null
, section_t
**in
, char **out
)
671 METHOD(settings_t
, create_section_enumerator
, enumerator_t
*,
672 private_settings_t
*this, char *key
, ...)
678 section
= find_section(this, this->top
, key
, args
);
683 return enumerator_create_empty();
685 this->lock
->read_lock(this->lock
);
686 return enumerator_create_filter(
687 section
->sections
->create_enumerator(section
->sections
),
688 (void*)section_filter
, this->lock
, (void*)this->lock
->unlock
);
692 * Enumerate key and values, not kv_t entries
694 static bool kv_filter(void *null
, kv_t
**in
, char **key
,
695 void *none
, char **value
)
698 *value
= (*in
)->value
;
702 METHOD(settings_t
, create_key_value_enumerator
, enumerator_t
*,
703 private_settings_t
*this, char *key
, ...)
709 section
= find_section(this, this->top
, key
, args
);
714 return enumerator_create_empty();
716 this->lock
->read_lock(this->lock
);
717 return enumerator_create_filter(
718 section
->kv
->create_enumerator(section
->kv
),
719 (void*)kv_filter
, this->lock
, (void*)this->lock
->unlock
);
723 * parse text, truncate "skip" chars, delimited by term respecting brackets.
725 * Chars in "skip" are truncated at the beginning and the end of the resulting
726 * token. "term" contains a list of characters to read up to (first match),
727 * while "br" contains bracket counterparts found in "term" to skip.
729 static char parse(char **text
, char *skip
, char *term
, char *br
, char **token
)
732 char best_term
= '\0';
734 /* skip leading chars */
735 while (strchr(skip
, **text
))
743 /* mark begin of subtext */
750 /* find terminator */
757 else if (br
&& *pos
== *br
)
763 if (best
== NULL
|| best
> pos
)
772 /* try next terminator */
783 /* null trailing bytes */
789 while (best
>= *token
&& strchr(skip
, *best
));
790 /* return found terminator */
797 * Check if "text" starts with "pattern".
798 * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
799 * is modified to point to the character right after "pattern".
801 static bool starts_with(char **text
, char *skip
, char *pattern
)
804 int len
= strlen(pattern
);
805 while (strchr(skip
, *pos
))
813 if (strlen(pos
) < len
|| !strneq(pos
, pattern
, len
))
822 * Check if what follows in "text" is an include statement.
823 * If this function returns TRUE, "text" will point to the character right after
824 * the include pattern, which is returned in "pattern".
826 static bool parse_include(char **text
, char **pattern
)
829 if (!starts_with(&pos
, "\n\t ", "include"))
833 if (starts_with(&pos
, "\t ", "="))
834 { /* ignore "include = value" */
838 return parse(text
, "\t ", "\n", NULL
, pattern
) != 0;
842 * Forward declaration.
844 static bool parse_files(linked_list_t
*contents
, char *file
, int level
,
845 char *pattern
, section_t
*section
);
850 static bool parse_section(linked_list_t
*contents
, char *file
, int level
,
851 char **text
, section_t
*section
)
853 bool finished
= FALSE
;
854 char *key
, *value
, *inner
;
858 if (parse_include(text
, &value
))
860 if (!parse_files(contents
, file
, level
, value
, section
))
862 DBG1(DBG_LIB
, "failed to include '%s'", value
);
867 switch (parse(text
, "\t\n ", "{=#", NULL
, &key
))
870 if (parse(text
, "\t ", "}", "{", &inner
))
875 DBG1(DBG_LIB
, "skipping section without name in '%s'",
879 if (section
->sections
->find_first(section
->sections
,
880 (linked_list_match_t
)section_find
,
881 (void**)&sub
, key
) != SUCCESS
)
883 sub
= section_create(key
);
884 if (parse_section(contents
, file
, level
, &inner
, sub
))
886 section
->sections
->insert_last(section
->sections
,
890 section_destroy(sub
);
893 { /* extend the existing section */
894 if (parse_section(contents
, file
, level
, &inner
, sub
))
899 DBG1(DBG_LIB
, "parsing subsection '%s' failed", key
);
902 DBG1(DBG_LIB
, "matching '}' not found near %s", *text
);
905 if (parse(text
, "\t ", "\n", NULL
, &value
))
910 DBG1(DBG_LIB
, "skipping value without key in '%s'",
914 if (section
->kv
->find_first(section
->kv
,
915 (linked_list_match_t
)kv_find
,
916 (void**)&kv
, key
) != SUCCESS
)
918 kv
= kv_create(key
, value
);
919 section
->kv
->insert_last(section
->kv
, kv
);
922 { /* replace with the most recently read value */
927 DBG1(DBG_LIB
, "parsing value failed near %s", *text
);
930 parse(text
, "", "\n", NULL
, &value
);
942 * Parse a file and add the settings to the given section.
944 static bool parse_file(linked_list_t
*contents
, char *file
, int level
,
953 DBG2(DBG_LIB
, "loading config file '%s'", file
);
954 if (stat(file
, &st
) == -1)
958 DBG2(DBG_LIB
, "'%s' does not exist, ignored", file
);
961 DBG1(DBG_LIB
, "failed to stat '%s': %s", file
, strerror(errno
));
964 else if (!S_ISREG(st
.st_mode
))
966 DBG1(DBG_LIB
, "'%s' is not a regular file", file
);
969 fd
= fopen(file
, "r");
972 DBG1(DBG_LIB
, "'%s' is not readable", file
);
975 fseek(fd
, 0, SEEK_END
);
978 text
= malloc(len
+ 1);
980 if (fread(text
, 1, len
, fd
) != len
)
988 success
= parse_section(contents
, file
, level
, &pos
, section
);
995 contents
->insert_last(contents
, text
);
1001 * Load the files matching "pattern", which is resolved with glob(3), if
1003 * If the pattern is relative, the directory of "file" is used as base.
1005 static bool parse_files(linked_list_t
*contents
, char *file
, int level
,
1006 char *pattern
, section_t
*section
)
1008 bool success
= TRUE
;
1011 if (level
> MAX_INCLUSION_LEVEL
)
1013 DBG1(DBG_LIB
, "maximum level of %d includes reached, ignored",
1014 MAX_INCLUSION_LEVEL
);
1018 if (!strlen(pattern
))
1020 DBG2(DBG_LIB
, "empty include pattern, ignored");
1024 if (!file
|| pattern
[0] == '/')
1025 { /* absolute path */
1026 if (snprintf(pat
, sizeof(pat
), "%s", pattern
) >= sizeof(pat
))
1028 DBG1(DBG_LIB
, "include pattern too long, ignored");
1033 { /* base relative paths to the directory of the current file */
1034 char *dir
= strdup(file
);
1036 if (snprintf(pat
, sizeof(pat
), "%s/%s", dir
, pattern
) >= sizeof(pat
))
1038 DBG1(DBG_LIB
, "include pattern too long, ignored");
1049 status
= glob(pat
, GLOB_ERR
, NULL
, &buf
);
1050 if (status
== GLOB_NOMATCH
)
1052 DBG2(DBG_LIB
, "no files found matching '%s', ignored", pat
);
1054 else if (status
!= 0)
1056 DBG1(DBG_LIB
, "expanding file pattern '%s' failed", pat
);
1062 for (expanded
= buf
.gl_pathv
; *expanded
!= NULL
; expanded
++)
1064 success
&= parse_file(contents
, *expanded
, level
+ 1, section
);
1073 #else /* HAVE_GLOB_H */
1074 /* if glob(3) is not available, try to load pattern directly */
1075 success
= parse_file(contents
, pat
, level
+ 1, section
);
1076 #endif /* HAVE_GLOB_H */
1081 * Recursivly extends "base" with "extension".
1083 static void section_extend(section_t
*base
, section_t
*extension
)
1085 enumerator_t
*enumerator
;
1089 enumerator
= extension
->sections
->create_enumerator(extension
->sections
);
1090 while (enumerator
->enumerate(enumerator
, (void**)&sec
))
1093 if (base
->sections
->find_first(base
->sections
,
1094 (linked_list_match_t
)section_find
, (void**)&found
,
1095 sec
->name
) == SUCCESS
)
1097 section_extend(found
, sec
);
1101 extension
->sections
->remove_at(extension
->sections
, enumerator
);
1102 base
->sections
->insert_last(base
->sections
, sec
);
1105 enumerator
->destroy(enumerator
);
1107 enumerator
= extension
->kv
->create_enumerator(extension
->kv
);
1108 while (enumerator
->enumerate(enumerator
, (void**)&kv
))
1111 if (base
->kv
->find_first(base
->kv
, (linked_list_match_t
)kv_find
,
1112 (void**)&found
, kv
->key
) == SUCCESS
)
1114 found
->value
= kv
->value
;
1118 extension
->kv
->remove_at(extension
->kv
, enumerator
);
1119 base
->kv
->insert_last(base
->kv
, kv
);
1122 enumerator
->destroy(enumerator
);
1126 * Load settings from files matching the given file pattern.
1127 * All sections and values are added relative to "parent".
1128 * All files (even included ones) have to be loaded successfully.
1130 static bool load_files_internal(private_settings_t
*this, section_t
*parent
,
1131 char *pattern
, bool merge
)
1134 linked_list_t
*contents
= linked_list_create();
1135 section_t
*section
= section_create(NULL
);
1137 if (pattern
== NULL
)
1139 pattern
= STRONGSWAN_CONF
;
1142 if (!parse_files(contents
, NULL
, 0, pattern
, section
))
1144 contents
->destroy_function(contents
, (void*)free
);
1145 section_destroy(section
);
1149 this->lock
->write_lock(this->lock
);
1152 section_purge(parent
);
1154 /* extend parent section */
1155 section_extend(parent
, section
);
1156 /* move contents of loaded files to main store */
1157 while (contents
->remove_first(contents
, (void**)&text
) == SUCCESS
)
1159 this->contents
->insert_last(this->contents
, text
);
1161 this->lock
->unlock(this->lock
);
1163 section_destroy(section
);
1164 contents
->destroy(contents
);
1168 METHOD(settings_t
, load_files
, bool,
1169 private_settings_t
*this, char *pattern
, bool merge
)
1171 return load_files_internal(this, this->top
, pattern
, merge
);
1174 METHOD(settings_t
, load_files_section
, bool,
1175 private_settings_t
*this, char *pattern
, bool merge
, char *key
, ...)
1180 va_start(args
, key
);
1181 section
= ensure_section(this, this->top
, key
, args
);
1188 return load_files_internal(this, section
, pattern
, merge
);
1191 METHOD(settings_t
, destroy
, void,
1192 private_settings_t
*this)
1194 section_destroy(this->top
);
1195 this->contents
->destroy_function(this->contents
, (void*)free
);
1196 this->lock
->destroy(this->lock
);
1203 settings_t
*settings_create(char *file
)
1205 private_settings_t
*this;
1209 .get_str
= _get_str
,
1210 .alloc_str
= _alloc_str
,
1211 .get_int
= _get_int
,
1212 .get_double
= _get_double
,
1213 .get_time
= _get_time
,
1214 .get_bool
= _get_bool
,
1215 .set_str
= _set_str
,
1216 .set_int
= _set_int
,
1217 .set_double
= _set_double
,
1218 .set_time
= _set_time
,
1219 .set_bool
= _set_bool
,
1220 .create_section_enumerator
= _create_section_enumerator
,
1221 .create_key_value_enumerator
= _create_key_value_enumerator
,
1222 .load_files
= _load_files
,
1223 .load_files_section
= _load_files_section
,
1224 .destroy
= _destroy
,
1226 .top
= section_create(NULL
),
1227 .contents
= linked_list_create(),
1228 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
1231 load_files(this, file
, FALSE
);
1233 return &this->public;