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
);