2 * Copyright (C) 2010-2014 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 */
34 #include "collections/linked_list.h"
35 #include "threading/rwlock.h"
36 #include "utils/debug.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
= memchr(pos
, '%', key
- pos
);
208 va_arg(copy
, enum_name_t
*);
214 DBG1(DBG_CFG
, "settings with %%%c not supported!", *pos
);
219 res
= vsnprintf(buf
, len
, key
, copy
) < len
;
225 * Find a section by a given key, using buffered key, reusable buffer.
226 * If "ensure" is TRUE, the sections are created if they don't exist.
228 static section_t
*find_section_buffered(section_t
*section
,
229 char *start
, char *key
, va_list args
, char *buf
, int len
,
233 section_t
*found
= NULL
;
239 pos
= strchr(key
, '.');
245 if (!print_key(buf
, len
, start
, key
, args
))
253 else if (section
->sections
->find_first(section
->sections
,
254 (linked_list_match_t
)section_find
,
255 (void**)&found
, buf
) != SUCCESS
)
259 found
= section_create(buf
);
260 section
->sections
->insert_last(section
->sections
, found
);
265 return find_section_buffered(found
, start
, pos
, args
, buf
, len
, ensure
);
271 * Find a section by a given key (thread-safe).
273 static section_t
*find_section(private_settings_t
*this, section_t
*section
,
274 char *key
, va_list args
)
276 char buf
[128], keybuf
[512];
279 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
283 this->lock
->read_lock(this->lock
);
284 found
= find_section_buffered(section
, keybuf
, keybuf
, args
, buf
,
286 this->lock
->unlock(this->lock
);
291 * Ensure that the section with the given key exists (thread-safe).
293 static section_t
*ensure_section(private_settings_t
*this, section_t
*section
,
294 char *key
, va_list args
)
296 char buf
[128], keybuf
[512];
299 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
303 /* we might have to change the tree */
304 this->lock
->write_lock(this->lock
);
305 found
= find_section_buffered(section
, keybuf
, keybuf
, args
, buf
,
307 this->lock
->unlock(this->lock
);
312 * Find the key/value pair for a key, using buffered key, reusable buffer
313 * If "ensure" is TRUE, the sections (and key/value pair) are created if they
316 static kv_t
*find_value_buffered(section_t
*section
, char *start
, char *key
,
317 va_list args
, char *buf
, int len
, bool ensure
)
321 section_t
*found
= NULL
;
328 pos
= strchr(key
, '.');
334 if (!print_key(buf
, len
, start
, key
, args
))
342 else if (section
->sections
->find_first(section
->sections
,
343 (linked_list_match_t
)section_find
,
344 (void**)&found
, buf
) != SUCCESS
)
350 found
= section_create(buf
);
351 section
->sections
->insert_last(section
->sections
, found
);
353 return find_value_buffered(found
, start
, pos
, args
, buf
, len
,
358 if (!print_key(buf
, len
, start
, key
, args
))
362 if (section
->kv
->find_first(section
->kv
, (linked_list_match_t
)kv_find
,
363 (void**)&kv
, buf
) != SUCCESS
)
367 kv
= kv_create(buf
, NULL
);
368 section
->kv
->insert_last(section
->kv
, kv
);
376 * Find the string value for a key (thread-safe).
378 static char *find_value(private_settings_t
*this, section_t
*section
,
379 char *key
, va_list args
)
381 char buf
[128], keybuf
[512], *value
= NULL
;
384 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
388 this->lock
->read_lock(this->lock
);
389 kv
= find_value_buffered(section
, keybuf
, keybuf
, args
, buf
, sizeof(buf
),
395 this->lock
->unlock(this->lock
);
400 * Set a value to a copy of the given string (thread-safe).
402 static void set_value(private_settings_t
*this, section_t
*section
,
403 char *key
, va_list args
, char *value
)
405 char buf
[128], keybuf
[512];
408 if (snprintf(keybuf
, sizeof(keybuf
), "%s", key
) >= sizeof(keybuf
))
412 this->lock
->write_lock(this->lock
);
413 kv
= find_value_buffered(section
, keybuf
, keybuf
, args
, buf
, sizeof(buf
),
421 else if (kv
->value
&& (strlen(value
) <= strlen(kv
->value
)))
422 { /* overwrite in-place, if possible */
423 strcpy(kv
->value
, value
);
426 { /* otherwise clone the string and store it in the cache */
427 kv
->value
= strdup(value
);
428 this->contents
->insert_last(this->contents
, kv
->value
);
431 this->lock
->unlock(this->lock
);
434 METHOD(settings_t
, get_str
, char*,
435 private_settings_t
*this, char *key
, char *def
, ...)
441 value
= find_value(this, this->top
, key
, args
);
451 * Described in header
453 inline bool settings_value_as_bool(char *value
, bool def
)
457 if (strcaseeq(value
, "1") ||
458 strcaseeq(value
, "yes") ||
459 strcaseeq(value
, "true") ||
460 strcaseeq(value
, "enabled"))
464 else if (strcaseeq(value
, "0") ||
465 strcaseeq(value
, "no") ||
466 strcaseeq(value
, "false") ||
467 strcaseeq(value
, "disabled"))
475 METHOD(settings_t
, get_bool
, bool,
476 private_settings_t
*this, char *key
, bool def
, ...)
482 value
= find_value(this, this->top
, key
, args
);
484 return settings_value_as_bool(value
, def
);
488 * Described in header
490 inline int settings_value_as_int(char *value
, int def
)
496 intval
= strtol(value
, NULL
, 10);
505 METHOD(settings_t
, get_int
, int,
506 private_settings_t
*this, char *key
, int def
, ...)
512 value
= find_value(this, this->top
, key
, args
);
514 return settings_value_as_int(value
, def
);
518 * Described in header
520 inline double settings_value_as_double(char *value
, double def
)
526 dval
= strtod(value
, NULL
);
535 METHOD(settings_t
, get_double
, double,
536 private_settings_t
*this, char *key
, double def
, ...)
542 value
= find_value(this, this->top
, key
, args
);
544 return settings_value_as_double(value
, def
);
548 * Described in header
550 inline u_int32_t
settings_value_as_time(char *value
, u_int32_t def
)
557 timeval
= strtoul(value
, &endptr
, 10);
562 case 'd': /* time in days */
563 timeval
*= 24 * 3600;
565 case 'h': /* time in hours */
568 case 'm': /* time in minutes */
571 case 's': /* time in seconds */
581 METHOD(settings_t
, get_time
, u_int32_t
,
582 private_settings_t
*this, char *key
, u_int32_t def
, ...)
588 value
= find_value(this, this->top
, key
, args
);
590 return settings_value_as_time(value
, def
);
593 METHOD(settings_t
, set_str
, void,
594 private_settings_t
*this, char *key
, char *value
, ...)
597 va_start(args
, value
);
598 set_value(this, this->top
, key
, args
, value
);
602 METHOD(settings_t
, set_bool
, void,
603 private_settings_t
*this, char *key
, bool value
, ...)
606 va_start(args
, value
);
607 set_value(this, this->top
, key
, args
, value ?
"1" : "0");
611 METHOD(settings_t
, set_int
, void,
612 private_settings_t
*this, char *key
, int value
, ...)
616 va_start(args
, value
);
617 if (snprintf(val
, sizeof(val
), "%d", value
) < sizeof(val
))
619 set_value(this, this->top
, key
, args
, val
);
624 METHOD(settings_t
, set_double
, void,
625 private_settings_t
*this, char *key
, double value
, ...)
629 va_start(args
, value
);
630 if (snprintf(val
, sizeof(val
), "%f", value
) < sizeof(val
))
632 set_value(this, this->top
, key
, args
, val
);
637 METHOD(settings_t
, set_time
, void,
638 private_settings_t
*this, char *key
, u_int32_t value
, ...)
642 va_start(args
, value
);
643 if (snprintf(val
, sizeof(val
), "%u", value
) < sizeof(val
))
645 set_value(this, this->top
, key
, args
, val
);
650 METHOD(settings_t
, set_default_str
, bool,
651 private_settings_t
*this, char *key
, char *value
, ...)
656 va_start(args
, value
);
657 old
= find_value(this, this->top
, key
, args
);
662 va_start(args
, value
);
663 set_value(this, this->top
, key
, args
, value
);
671 * Enumerate section names, not sections
673 static bool section_filter(void *null
, section_t
**in
, char **out
)
679 METHOD(settings_t
, create_section_enumerator
, enumerator_t
*,
680 private_settings_t
*this, char *key
, ...)
686 section
= find_section(this, this->top
, key
, args
);
691 return enumerator_create_empty();
693 this->lock
->read_lock(this->lock
);
694 return enumerator_create_filter(
695 section
->sections
->create_enumerator(section
->sections
),
696 (void*)section_filter
, this->lock
, (void*)this->lock
->unlock
);
700 * Enumerate key and values, not kv_t entries
702 static bool kv_filter(void *null
, kv_t
**in
, char **key
,
703 void *none
, char **value
)
706 *value
= (*in
)->value
;
710 METHOD(settings_t
, create_key_value_enumerator
, enumerator_t
*,
711 private_settings_t
*this, char *key
, ...)
717 section
= find_section(this, this->top
, key
, args
);
722 return enumerator_create_empty();
724 this->lock
->read_lock(this->lock
);
725 return enumerator_create_filter(
726 section
->kv
->create_enumerator(section
->kv
),
727 (void*)kv_filter
, this->lock
, (void*)this->lock
->unlock
);
731 * parse text, truncate "skip" chars, delimited by term respecting brackets.
733 * Chars in "skip" are truncated at the beginning and the end of the resulting
734 * token. "term" contains a list of characters to read up to (first match),
735 * while "br" contains bracket counterparts found in "term" to skip.
737 static char parse(char **text
, char *skip
, char *term
, char *br
, char **token
)
740 char best_term
= '\0';
742 /* skip leading chars */
743 while (strchr(skip
, **text
))
751 /* mark begin of subtext */
758 /* find terminator */
765 else if (br
&& *pos
== *br
)
771 if (best
== NULL
|| best
> pos
)
780 /* try next terminator */
791 /* null trailing bytes */
797 while (best
>= *token
&& strchr(skip
, *best
));
798 /* return found terminator */
805 * Check if "text" starts with "pattern".
806 * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
807 * is modified to point to the character right after "pattern".
809 static bool starts_with(char **text
, char *skip
, char *pattern
)
812 int len
= strlen(pattern
);
813 while (strchr(skip
, *pos
))
821 if (strlen(pos
) < len
|| !strneq(pos
, pattern
, len
))
830 * Check if what follows in "text" is an include statement.
831 * If this function returns TRUE, "text" will point to the character right after
832 * the include pattern, which is returned in "pattern".
834 static bool parse_include(char **text
, char **pattern
)
837 if (!starts_with(&pos
, "\n\t ", "include"))
841 if (starts_with(&pos
, "\t ", "="))
842 { /* ignore "include = value" */
846 return parse(text
, "\t ", "\n", NULL
, pattern
) != 0;
850 * Forward declaration.
852 static bool parse_files(linked_list_t
*contents
, char *file
, int level
,
853 char *pattern
, section_t
*section
);
858 static bool parse_section(linked_list_t
*contents
, char *file
, int level
,
859 char **text
, section_t
*section
)
861 bool finished
= FALSE
;
862 char *key
, *value
, *inner
;
866 if (parse_include(text
, &value
))
868 if (!parse_files(contents
, file
, level
, value
, section
))
870 DBG1(DBG_LIB
, "failed to include '%s'", value
);
875 switch (parse(text
, "\t\n ", "{=#", NULL
, &key
))
878 if (parse(text
, "\t ", "}", "{", &inner
))
883 DBG1(DBG_LIB
, "skipping section without name in '%s'",
887 if (section
->sections
->find_first(section
->sections
,
888 (linked_list_match_t
)section_find
,
889 (void**)&sub
, key
) != SUCCESS
)
891 sub
= section_create(key
);
892 if (parse_section(contents
, file
, level
, &inner
, sub
))
894 section
->sections
->insert_last(section
->sections
,
898 section_destroy(sub
);
901 { /* extend the existing section */
902 if (parse_section(contents
, file
, level
, &inner
, sub
))
907 DBG1(DBG_LIB
, "parsing subsection '%s' failed", key
);
910 DBG1(DBG_LIB
, "matching '}' not found near %s", *text
);
913 if (parse(text
, "\t ", "\n", NULL
, &value
))
918 DBG1(DBG_LIB
, "skipping value without key in '%s'",
922 if (section
->kv
->find_first(section
->kv
,
923 (linked_list_match_t
)kv_find
,
924 (void**)&kv
, key
) != SUCCESS
)
926 kv
= kv_create(key
, value
);
927 section
->kv
->insert_last(section
->kv
, kv
);
930 { /* replace with the most recently read value */
935 DBG1(DBG_LIB
, "parsing value failed near %s", *text
);
938 parse(text
, "", "\n", NULL
, &value
);
950 * Parse a file and add the settings to the given section.
952 static bool parse_file(linked_list_t
*contents
, char *file
, int level
,
961 DBG2(DBG_LIB
, "loading config file '%s'", file
);
962 if (stat(file
, &st
) == -1)
966 DBG2(DBG_LIB
, "'%s' does not exist, ignored", file
);
969 DBG1(DBG_LIB
, "failed to stat '%s': %s", file
, strerror(errno
));
972 else if (!S_ISREG(st
.st_mode
))
974 DBG1(DBG_LIB
, "'%s' is not a regular file", file
);
977 fd
= fopen(file
, "r");
980 DBG1(DBG_LIB
, "'%s' is not readable", file
);
983 fseek(fd
, 0, SEEK_END
);
986 text
= malloc(len
+ 1);
988 if (fread(text
, 1, len
, fd
) != len
)
997 success
= parse_section(contents
, file
, level
, &pos
, section
);
1004 contents
->insert_last(contents
, text
);
1010 * Load the files matching "pattern", which is resolved with glob(3), if
1012 * If the pattern is relative, the directory of "file" is used as base.
1014 static bool parse_files(linked_list_t
*contents
, char *file
, int level
,
1015 char *pattern
, section_t
*section
)
1017 bool success
= TRUE
;
1020 if (level
> MAX_INCLUSION_LEVEL
)
1022 DBG1(DBG_LIB
, "maximum level of %d includes reached, ignored",
1023 MAX_INCLUSION_LEVEL
);
1027 if (!strlen(pattern
))
1029 DBG2(DBG_LIB
, "empty include pattern, ignored");
1033 if (!file
|| pattern
[0] == '/')
1034 { /* absolute path */
1035 if (snprintf(pat
, sizeof(pat
), "%s", pattern
) >= sizeof(pat
))
1037 DBG1(DBG_LIB
, "include pattern too long, ignored");
1042 { /* base relative paths to the directory of the current file */
1043 char *dir
= strdup(file
);
1045 if (snprintf(pat
, sizeof(pat
), "%s/%s", dir
, pattern
) >= sizeof(pat
))
1047 DBG1(DBG_LIB
, "include pattern too long, ignored");
1058 status
= glob(pat
, GLOB_ERR
, NULL
, &buf
);
1059 if (status
== GLOB_NOMATCH
)
1061 DBG2(DBG_LIB
, "no files found matching '%s', ignored", pat
);
1063 else if (status
!= 0)
1065 DBG1(DBG_LIB
, "expanding file pattern '%s' failed", pat
);
1071 for (expanded
= buf
.gl_pathv
; *expanded
!= NULL
; expanded
++)
1073 success
&= parse_file(contents
, *expanded
, level
+ 1, section
);
1082 #else /* HAVE_GLOB_H */
1083 /* if glob(3) is not available, try to load pattern directly */
1084 success
= parse_file(contents
, pat
, level
+ 1, section
);
1085 #endif /* HAVE_GLOB_H */
1090 * Recursivly extends "base" with "extension".
1092 static void section_extend(section_t
*base
, section_t
*extension
)
1094 enumerator_t
*enumerator
;
1098 enumerator
= extension
->sections
->create_enumerator(extension
->sections
);
1099 while (enumerator
->enumerate(enumerator
, (void**)&sec
))
1102 if (base
->sections
->find_first(base
->sections
,
1103 (linked_list_match_t
)section_find
, (void**)&found
,
1104 sec
->name
) == SUCCESS
)
1106 section_extend(found
, sec
);
1110 extension
->sections
->remove_at(extension
->sections
, enumerator
);
1111 base
->sections
->insert_last(base
->sections
, sec
);
1114 enumerator
->destroy(enumerator
);
1116 enumerator
= extension
->kv
->create_enumerator(extension
->kv
);
1117 while (enumerator
->enumerate(enumerator
, (void**)&kv
))
1120 if (base
->kv
->find_first(base
->kv
, (linked_list_match_t
)kv_find
,
1121 (void**)&found
, kv
->key
) == SUCCESS
)
1123 found
->value
= kv
->value
;
1127 extension
->kv
->remove_at(extension
->kv
, enumerator
);
1128 base
->kv
->insert_last(base
->kv
, kv
);
1131 enumerator
->destroy(enumerator
);
1135 * Load settings from files matching the given file pattern.
1136 * All sections and values are added relative to "parent".
1137 * All files (even included ones) have to be loaded successfully.
1139 static bool load_files_internal(private_settings_t
*this, section_t
*parent
,
1140 char *pattern
, bool merge
)
1143 linked_list_t
*contents
;
1146 if (pattern
== NULL
)
1148 #ifdef STRONGSWAN_CONF
1149 pattern
= STRONGSWAN_CONF
;
1155 contents
= linked_list_create();
1156 section
= section_create(NULL
);
1158 if (!parse_files(contents
, NULL
, 0, pattern
, section
))
1160 contents
->destroy_function(contents
, (void*)free
);
1161 section_destroy(section
);
1165 this->lock
->write_lock(this->lock
);
1168 section_purge(parent
);
1170 /* extend parent section */
1171 section_extend(parent
, section
);
1172 /* move contents of loaded files to main store */
1173 while (contents
->remove_first(contents
, (void**)&text
) == SUCCESS
)
1175 this->contents
->insert_last(this->contents
, text
);
1177 this->lock
->unlock(this->lock
);
1179 section_destroy(section
);
1180 contents
->destroy(contents
);
1184 METHOD(settings_t
, load_files
, bool,
1185 private_settings_t
*this, char *pattern
, bool merge
)
1187 return load_files_internal(this, this->top
, pattern
, merge
);
1190 METHOD(settings_t
, load_files_section
, bool,
1191 private_settings_t
*this, char *pattern
, bool merge
, char *key
, ...)
1196 va_start(args
, key
);
1197 section
= ensure_section(this, this->top
, key
, args
);
1204 return load_files_internal(this, section
, pattern
, merge
);
1207 METHOD(settings_t
, destroy
, void,
1208 private_settings_t
*this)
1210 section_destroy(this->top
);
1211 this->contents
->destroy_function(this->contents
, (void*)free
);
1212 this->lock
->destroy(this->lock
);
1219 settings_t
*settings_create(char *file
)
1221 private_settings_t
*this;
1225 .get_str
= _get_str
,
1226 .get_int
= _get_int
,
1227 .get_double
= _get_double
,
1228 .get_time
= _get_time
,
1229 .get_bool
= _get_bool
,
1230 .set_str
= _set_str
,
1231 .set_int
= _set_int
,
1232 .set_double
= _set_double
,
1233 .set_time
= _set_time
,
1234 .set_bool
= _set_bool
,
1235 .set_default_str
= _set_default_str
,
1236 .create_section_enumerator
= _create_section_enumerator
,
1237 .create_key_value_enumerator
= _create_key_value_enumerator
,
1238 .load_files
= _load_files
,
1239 .load_files_section
= _load_files_section
,
1240 .destroy
= _destroy
,
1242 .top
= section_create(NULL
),
1243 .contents
= linked_list_create(),
1244 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
1247 load_files(this, file
, FALSE
);
1249 return &this->public;