2 Configuration file handling on top of tini
4 Copyright (C) Amitay Isaacs 2017
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/locale.h"
25 #include "lib/util/dlinklist.h"
26 #include "lib/util/tini.h"
27 #include "lib/util/debug.h"
29 #include "common/conf.h"
47 struct conf_option *prev, *next;
53 struct conf_value default_value;
56 struct conf_value *value, *new_value;
57 union conf_pointer ptr;
58 bool temporary_modified;
62 struct conf_section *prev, *next;
65 conf_validate_section_fn validate;
66 struct conf_option *option;
71 struct conf_section *section;
75 bool validation_active;
79 * Functions related to conf_value
82 static int string_to_string(TALLOC_CTX *mem_ctx,
92 t = talloc_strdup(mem_ctx, str);
101 static int string_to_integer(const char *str, int *int_val)
110 t = strtol(str, &endptr, 0);
111 if (*str != '\0' || endptr == NULL) {
112 if (t < 0 || t > INT_MAX) {
123 static int string_to_boolean(const char *str, bool *bool_val)
125 if (strcasecmp(str, "true") == 0 || strcasecmp(str, "yes") == 0) {
130 if (strcasecmp(str, "false") == 0 || strcasecmp(str, "no") == 0) {
138 static int conf_value_from_string(TALLOC_CTX *mem_ctx,
140 struct conf_value *value)
144 switch (value->type) {
146 ret = string_to_string(mem_ctx, str, &value->data.string);
150 ret = string_to_integer(str, &value->data.integer);
154 ret = string_to_boolean(str, &value->data.boolean);
164 static bool conf_value_compare(struct conf_value *old, struct conf_value *new)
166 if (old == NULL || new == NULL) {
170 if (old->type != new->type) {
176 if (old->data.string == NULL && new->data.string == NULL) {
179 if (old->data.string != NULL && new->data.string != NULL) {
180 if (strcmp(old->data.string, new->data.string) == 0) {
187 if (old->data.integer == new->data.integer) {
193 if (old->data.boolean == new->data.boolean) {
202 static int conf_value_copy(TALLOC_CTX *mem_ctx,
203 struct conf_value *src,
204 struct conf_value *dst)
206 if (src->type != dst->type) {
212 if (dst->data.string != NULL) {
213 talloc_free(discard_const(dst->data.string));
215 if (src->data.string == NULL) {
216 dst->data.string = NULL;
218 dst->data.string = talloc_strdup(
219 mem_ctx, src->data.string);
220 if (dst->data.string == NULL) {
227 dst->data.integer = src->data.integer;
231 dst->data.boolean = src->data.boolean;
241 static void conf_value_dump(const char *key,
242 struct conf_value *value,
247 if ((value->type == CONF_STRING && value->data.string == NULL) ||
249 fprintf(fp, "\t# %s = ", key);
251 fprintf(fp, "\t%s = ", key);
254 switch (value->type) {
256 if (value->data.string != NULL) {
257 fprintf(fp, "%s", value->data.string);
262 fprintf(fp, "%d", value->data.integer);
266 fprintf(fp, "%s", (value->data.boolean ? "true" : "false"));
271 fprintf(fp, " # temporary");
278 * Functions related to conf_option
281 static struct conf_option *conf_option_find(struct conf_section *s,
284 struct conf_option *opt;
286 for (opt = s->option; opt != NULL; opt = opt->next) {
287 if (strcmp(opt->name, key) == 0) {
295 static void conf_option_set_ptr_value(struct conf_option *opt)
299 if (opt->ptr.string != NULL) {
300 *(opt->ptr.string) = opt->value->data.string;
305 if (opt->ptr.integer != NULL) {
306 *(opt->ptr.integer) = opt->value->data.integer;
311 if (opt->ptr.boolean != NULL) {
312 *(opt->ptr.boolean) = opt->value->data.boolean;
318 static void conf_option_default(struct conf_option *opt);
320 static int conf_option_add(struct conf_section *s,
324 struct conf_option **popt)
326 struct conf_option *opt;
328 opt = conf_option_find(s, key);
330 D_ERR("conf: option \"%s\" already exists\n", key);
334 opt = talloc_zero(s, struct conf_option);
339 opt->name = talloc_strdup(opt, key);
340 if (opt->name == NULL) {
346 opt->validate = validate;
348 DLIST_ADD_END(s->option, opt);
357 static int conf_option_set_default(struct conf_option *opt,
358 struct conf_value *default_value)
362 opt->default_value.type = opt->type;
364 ret = conf_value_copy(opt, default_value, &opt->default_value);
369 opt->default_set = true;
370 opt->temporary_modified = false;
375 static void conf_option_set_ptr(struct conf_option *opt,
376 union conf_pointer *ptr)
381 static bool conf_option_validate_string(struct conf_option *opt,
382 struct conf_value *value,
383 enum conf_update_mode mode)
385 conf_validate_string_option_fn validate =
386 (conf_validate_string_option_fn)opt->validate;
388 return validate(opt->name,
389 opt->value->data.string,
394 static bool conf_option_validate_integer(struct conf_option *opt,
395 struct conf_value *value,
396 enum conf_update_mode mode)
398 conf_validate_integer_option_fn validate =
399 (conf_validate_integer_option_fn)opt->validate;
401 return validate(opt->name,
402 opt->value->data.integer,
407 static bool conf_option_validate_boolean(struct conf_option *opt,
408 struct conf_value *value,
409 enum conf_update_mode mode)
411 conf_validate_boolean_option_fn validate =
412 (conf_validate_boolean_option_fn)opt->validate;
414 return validate(opt->name,
415 opt->value->data.boolean,
420 static bool conf_option_validate(struct conf_option *opt,
421 struct conf_value *value,
422 enum conf_update_mode mode)
426 if (opt->validate == NULL) {
432 ret = conf_option_validate_string(opt, value, mode);
436 ret = conf_option_validate_integer(opt, value, mode);
440 ret = conf_option_validate_boolean(opt, value, mode);
450 static bool conf_option_same_value(struct conf_option *opt,
451 struct conf_value *new_value)
453 return conf_value_compare(opt->value, new_value);
456 static int conf_option_new_value(struct conf_option *opt,
457 struct conf_value *new_value,
458 enum conf_update_mode mode)
463 if (opt->new_value != &opt->default_value) {
464 TALLOC_FREE(opt->new_value);
467 if (new_value == &opt->default_value) {
469 * This happens only during load/reload. Set the value to
470 * default value, so if the config option is dropped from
471 * config file, then it get's reset to default.
473 opt->new_value = &opt->default_value;
475 ok = conf_option_validate(opt, new_value, mode);
477 D_ERR("conf: validation for option \"%s\" failed\n",
482 opt->new_value = talloc_zero(opt, struct conf_value);
483 if (opt->new_value == NULL) {
487 opt->new_value->type = opt->value->type;
488 ret = conf_value_copy(opt, new_value, opt->new_value);
494 conf_option_set_ptr_value(opt);
496 if (new_value != &opt->default_value) {
497 if (mode == CONF_MODE_API) {
498 opt->temporary_modified = true;
500 opt->temporary_modified = false;
507 static int conf_option_new_default_value(struct conf_option *opt,
508 enum conf_update_mode mode)
510 return conf_option_new_value(opt, &opt->default_value, mode);
513 static void conf_option_default(struct conf_option *opt)
515 if (! opt->default_set) {
519 if (opt->value != &opt->default_value) {
520 TALLOC_FREE(opt->value);
523 opt->value = &opt->default_value;
524 conf_option_set_ptr_value(opt);
527 static void conf_option_reset(struct conf_option *opt)
529 if (opt->new_value != &opt->default_value) {
530 TALLOC_FREE(opt->new_value);
533 conf_option_set_ptr_value(opt);
536 static void conf_option_update(struct conf_option *opt)
538 if (opt->new_value == NULL) {
542 if (opt->value != &opt->default_value) {
543 TALLOC_FREE(opt->value);
546 opt->value = opt->new_value;
547 opt->new_value = NULL;
549 conf_option_set_ptr_value(opt);
552 static void conf_option_reset_temporary(struct conf_option *opt)
554 opt->temporary_modified = false;
557 static bool conf_option_is_default(struct conf_option *opt)
559 return (opt->value == &opt->default_value);
562 static void conf_option_dump(struct conf_option *opt, FILE *fp)
566 is_default = conf_option_is_default(opt);
568 conf_value_dump(opt->name,
571 opt->temporary_modified,
576 * Functions related to conf_section
579 static struct conf_section *conf_section_find(struct conf_context *conf,
582 struct conf_section *s;
584 for (s = conf->section; s != NULL; s = s->next) {
585 if (strcasecmp(s->name, section) == 0) {
593 static int conf_section_add(struct conf_context *conf,
595 conf_validate_section_fn validate)
597 struct conf_section *s;
599 s = conf_section_find(conf, section);
604 s = talloc_zero(conf, struct conf_section);
609 s->name = talloc_strdup(s, section);
610 if (s->name == NULL) {
615 s->validate = validate;
617 DLIST_ADD_END(conf->section, s);
621 static bool conf_section_validate(struct conf_context *conf,
622 struct conf_section *s,
623 enum conf_update_mode mode)
627 if (s->validate == NULL) {
631 ok = s->validate(conf, s->name, mode);
633 D_ERR("conf: validation for section [%s] failed\n", s->name);
639 static void conf_section_dump(struct conf_section *s, FILE *fp)
641 fprintf(fp, "[%s]\n", s->name);
645 * Functions related to conf_context
648 static void conf_all_default(struct conf_context *conf)
650 struct conf_section *s;
651 struct conf_option *opt;
653 for (s = conf->section; s != NULL; s = s->next) {
654 for (opt = s->option; opt != NULL; opt = opt->next) {
655 conf_option_default(opt);
660 static int conf_all_temporary_default(struct conf_context *conf,
661 enum conf_update_mode mode)
663 struct conf_section *s;
664 struct conf_option *opt;
667 for (s = conf->section; s != NULL; s = s->next) {
668 for (opt = s->option; opt != NULL; opt = opt->next) {
669 ret = conf_option_new_default_value(opt, mode);
679 static void conf_all_reset(struct conf_context *conf)
681 struct conf_section *s;
682 struct conf_option *opt;
684 for (s = conf->section; s != NULL; s = s->next) {
685 for (opt = s->option; opt != NULL; opt = opt->next) {
686 conf_option_reset(opt);
691 static void conf_all_update(struct conf_context *conf)
693 struct conf_section *s;
694 struct conf_option *opt;
696 for (s = conf->section; s != NULL; s = s->next) {
697 for (opt = s->option; opt != NULL; opt = opt->next) {
698 conf_option_update(opt);
699 conf_option_reset_temporary(opt);
708 int conf_init(TALLOC_CTX *mem_ctx, struct conf_context **result)
710 struct conf_context *conf;
712 conf = talloc_zero(mem_ctx, struct conf_context);
717 conf->define_failed = false;
723 void conf_define_section(struct conf_context *conf,
725 conf_validate_section_fn validate)
729 if (conf->define_failed) {
733 if (section == NULL) {
734 conf->define_failed = true;
738 ret = conf_section_add(conf, section, validate);
740 conf->define_failed = true;
745 static struct conf_option *conf_define(struct conf_context *conf,
749 conf_validate_string_option_fn validate)
751 struct conf_section *s;
752 struct conf_option *opt;
755 s = conf_section_find(conf, section);
757 D_ERR("conf: unknown section [%s]\n", section);
762 D_ERR("conf: option name null in section [%s]\n", section);
766 ret = conf_option_add(s, key, type, validate, &opt);
774 static void conf_define_post(struct conf_context *conf,
775 struct conf_option *opt,
776 struct conf_value *default_value)
780 ret = conf_option_set_default(opt, default_value);
782 conf->define_failed = true;
786 conf_option_default(opt);
789 void conf_define_string(struct conf_context *conf,
792 const char *default_str_val,
793 conf_validate_string_option_fn validate)
795 struct conf_option *opt;
796 struct conf_value default_value;
798 if (! conf_valid(conf)) {
802 opt = conf_define(conf, section, key, CONF_STRING, validate);
804 conf->define_failed = true;
808 default_value.type = CONF_STRING;
809 default_value.data.string = default_str_val;
811 conf_define_post(conf, opt, &default_value);
814 void conf_define_integer(struct conf_context *conf,
817 const int default_int_val,
818 conf_validate_integer_option_fn validate)
820 struct conf_option *opt;
821 struct conf_value default_value;
823 if (! conf_valid(conf)) {
827 opt = conf_define(conf, section, key, CONF_INTEGER, (void *)validate);
829 conf->define_failed = true;
833 default_value.type = CONF_INTEGER;
834 default_value.data.integer = default_int_val;
836 conf_define_post(conf, opt, &default_value);
840 void conf_define_boolean(struct conf_context *conf,
843 const bool default_bool_val,
844 conf_validate_boolean_option_fn validate)
846 struct conf_option *opt;
847 struct conf_value default_value;
849 if (! conf_valid(conf)) {
853 opt = conf_define(conf, section, key, CONF_BOOLEAN, (void *)validate);
855 conf->define_failed = true;
859 default_value.type = CONF_BOOLEAN;
860 default_value.data.boolean = default_bool_val;
862 conf_define_post(conf, opt, &default_value);
865 static struct conf_option *_conf_option(struct conf_context *conf,
869 struct conf_section *s;
870 struct conf_option *opt;
872 s = conf_section_find(conf, section);
877 opt = conf_option_find(s, key);
881 void conf_assign_string_pointer(struct conf_context *conf,
884 const char **str_ptr)
886 struct conf_option *opt;
887 union conf_pointer ptr;
889 opt = _conf_option(conf, section, key);
891 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
892 conf->define_failed = true;
896 if (opt->type != CONF_STRING) {
897 conf->define_failed = true;
901 ptr.string = str_ptr;
902 conf_option_set_ptr(opt, &ptr);
903 conf_option_set_ptr_value(opt);
906 void conf_assign_integer_pointer(struct conf_context *conf,
911 struct conf_option *opt;
912 union conf_pointer ptr;
914 opt = _conf_option(conf, section, key);
916 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
917 conf->define_failed = true;
921 if (opt->type != CONF_INTEGER) {
922 conf->define_failed = true;
926 ptr.integer = int_ptr;
927 conf_option_set_ptr(opt, &ptr);
928 conf_option_set_ptr_value(opt);
931 void conf_assign_boolean_pointer(struct conf_context *conf,
936 struct conf_option *opt;
937 union conf_pointer ptr;
939 opt = _conf_option(conf, section, key);
941 D_ERR("conf: unknown option [%s] -> \"%s\"\n", section, key);
942 conf->define_failed = true;
946 if (opt->type != CONF_BOOLEAN) {
947 conf->define_failed = true;
951 ptr.boolean = bool_ptr;
952 conf_option_set_ptr(opt, &ptr);
953 conf_option_set_ptr_value(opt);
956 bool conf_query(struct conf_context *conf,
959 enum conf_type *type)
961 struct conf_section *s;
962 struct conf_option *opt;
964 if (! conf_valid(conf)) {
968 s = conf_section_find(conf, section);
973 opt = conf_option_find(s, key);
984 bool conf_valid(struct conf_context *conf)
986 if (conf->define_failed) {
993 void conf_set_defaults(struct conf_context *conf)
995 conf_all_default(conf);
998 struct conf_load_state {
999 struct conf_context *conf;
1000 struct conf_section *s;
1001 enum conf_update_mode mode;
1005 static bool conf_load_section(const char *section, void *private_data);
1006 static bool conf_load_option(const char *name,
1007 const char *value_str,
1008 void *private_data);
1010 static int conf_load_internal(struct conf_context *conf)
1012 struct conf_load_state state;
1017 state = (struct conf_load_state) {
1019 .mode = (conf->reload ? CONF_MODE_RELOAD : CONF_MODE_LOAD),
1022 ret = conf_all_temporary_default(conf, state.mode);
1027 fp = fopen(conf->filename, "r");
1042 /* Process the last section */
1043 if (state.s != NULL) {
1044 ok = conf_section_validate(conf, state.s, state.mode);
1051 conf_all_update(conf);
1055 conf_all_reset(conf);
1059 static bool conf_load_section(const char *section, void *private_data)
1061 struct conf_load_state *state =
1062 (struct conf_load_state *)private_data;
1065 if (state->s != NULL) {
1066 ok = conf_section_validate(state->conf, state->s, state->mode);
1068 state->err = EINVAL;
1073 state->s = conf_section_find(state->conf, section);
1074 if (state->s == NULL) {
1075 if (state->conf->ignore_unknown) {
1076 D_DEBUG("conf: ignoring unknown section [%s]\n",
1079 D_ERR("conf: unknown section [%s]\n", section);
1080 state->err = EINVAL;
1088 static bool conf_load_option(const char *name,
1089 const char *value_str,
1092 struct conf_load_state *state =
1093 (struct conf_load_state *)private_data;
1094 struct conf_option *opt;
1095 TALLOC_CTX *tmp_ctx;
1096 struct conf_value value;
1100 if (state->s == NULL) {
1101 if (state->conf->ignore_unknown) {
1102 D_DEBUG("conf: ignoring unknown option \"%s\"\n",
1106 D_ERR("conf: unknown option \"%s\"\n", name);
1107 state->err = EINVAL;
1112 opt = conf_option_find(state->s, name);
1114 if (state->conf->ignore_unknown) {
1117 state->err = ENOENT;
1122 tmp_ctx = talloc_new(state->conf);
1123 if (tmp_ctx == NULL) {
1124 state->err = ENOMEM;
1128 value.type = opt->type;
1129 ret = conf_value_from_string(tmp_ctx, value_str, &value);
1131 talloc_free(tmp_ctx);
1136 ok = conf_option_same_value(opt, &value);
1141 ret = conf_option_new_value(opt, &value, state->mode);
1143 talloc_free(tmp_ctx);
1149 talloc_free(tmp_ctx);
1154 int conf_load(struct conf_context *conf,
1155 const char *filename,
1156 bool ignore_unknown)
1158 conf->filename = talloc_strdup(conf, filename);
1159 if (conf->filename == NULL) {
1163 conf->ignore_unknown = ignore_unknown;
1165 D_NOTICE("Reading config file %s\n", filename);
1167 return conf_load_internal(conf);
1170 int conf_reload(struct conf_context *conf)
1174 if (conf->filename == NULL) {
1178 D_NOTICE("Re-reading config file %s\n", conf->filename);
1180 conf->reload = true;
1181 ret = conf_load_internal(conf);
1182 conf->reload = false;
1187 static int conf_set(struct conf_context *conf,
1188 const char *section,
1190 struct conf_value *value)
1192 struct conf_section *s;
1193 struct conf_option *opt;
1197 s = conf_section_find(conf, section);
1202 opt = conf_option_find(s, key);
1207 if (opt->type != value->type) {
1211 ok = conf_option_same_value(opt, value);
1216 ret = conf_option_new_value(opt, value, CONF_MODE_API);
1218 conf_option_reset(opt);
1222 ok = conf_section_validate(conf, s, CONF_MODE_API);
1224 conf_option_reset(opt);
1228 conf_option_update(opt);
1232 int conf_set_string(struct conf_context *conf,
1233 const char *section,
1235 const char *str_val)
1237 struct conf_value value;
1239 value.type = CONF_STRING;
1240 value.data.string = str_val;
1242 return conf_set(conf, section, key, &value);
1245 int conf_set_integer(struct conf_context *conf,
1246 const char *section,
1250 struct conf_value value;
1252 value.type = CONF_INTEGER;
1253 value.data.integer = int_val;
1255 return conf_set(conf, section, key, &value);
1258 int conf_set_boolean(struct conf_context *conf,
1259 const char *section,
1263 struct conf_value value;
1265 value.type = CONF_BOOLEAN;
1266 value.data.boolean = bool_val;
1268 return conf_set(conf, section, key, &value);
1271 static int conf_get(struct conf_context *conf,
1272 const char *section,
1274 enum conf_type type,
1275 const struct conf_value **value,
1278 struct conf_section *s;
1279 struct conf_option *opt;
1281 s = conf_section_find(conf, section);
1286 opt = conf_option_find(s, key);
1291 if (opt->type != type) {
1295 *value = opt->value;
1296 if (is_default != NULL) {
1297 *is_default = conf_option_is_default(opt);
1303 int conf_get_string(struct conf_context *conf,
1304 const char *section,
1306 const char **str_val,
1309 const struct conf_value *value;
1312 ret = conf_get(conf, section, key, CONF_STRING, &value, is_default);
1317 *str_val = value->data.string;
1321 int conf_get_integer(struct conf_context *conf,
1322 const char *section,
1327 const struct conf_value *value;
1330 ret = conf_get(conf, section, key, CONF_INTEGER, &value, is_default);
1335 *int_val = value->data.integer;
1339 int conf_get_boolean(struct conf_context *conf,
1340 const char *section,
1345 const struct conf_value *value;
1348 ret = conf_get(conf, section, key, CONF_BOOLEAN, &value, is_default);
1353 *bool_val = value->data.boolean;
1357 void conf_dump(struct conf_context *conf, FILE *fp)
1359 struct conf_section *s;
1360 struct conf_option *opt;
1362 for (s = conf->section; s != NULL; s = s->next) {
1363 conf_section_dump(s, fp);
1364 for (opt = s->option; opt != NULL; opt = opt->next) {
1365 conf_option_dump(opt, fp);