config-parser.c revision 9f0f2de10e4ea0c99052bf4b2bef8179f2536228
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen#include "array.h"
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen#include "str.h"
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen#include "hash.h"
6dc4af35c045e10609b13fe80f9cf33f3a06c3ceTimo Sirainen#include "strescape.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream.h"
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen#include "settings-parser.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "all-settings.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "config-filter.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "config-parser.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <unistd.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <fcntl.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#ifdef HAVE_GLOB_H
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen# include <glob.h>
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen#endif
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#ifndef GLOB_BRACE
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen# define GLOB_BRACE 0
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#endif
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct config_section_stack {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct config_section_stack *prev;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainen struct config_filter filter;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* root=NULL-terminated list of parsers */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct config_module_parser *parsers;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int pathlen;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct input_stack {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct input_stack *prev;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen struct istream *input;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen const char *path;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unsigned int linenum;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen};
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct parser_context {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen pool_t pool;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const char *path;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ARRAY_DEFINE(all_parsers, struct config_filter_parser *);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct config_module_parser *root_parsers;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct config_section_stack *cur_section;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen struct input_stack *cur_input;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct config_filter_context *filter;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic const enum settings_parser_flags settings_parser_flags =
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS |
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen SETTINGS_PARSER_FLAG_TRACK_CHANGES;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct config_module_parser *config_module_parsers;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstruct config_filter_context *config_filter;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic const char *info_type_name_find(const struct setting_parser_info *info)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen{
9d6dec796909384293006e4289436579089d88d5Timo Sirainen unsigned int i;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen for (i = 0; info->defines[i].key != NULL; i++) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (info->defines[i].offset == info->type_offset)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return info->defines[i].key;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_panic("setting parser: Invalid type_offset value");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void config_add_type(struct setting_parser_context *parser,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *line, const char *section_name)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const struct setting_parser_info *info;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *p;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen string_t *str;
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainen int ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainen info = settings_parse_get_prev_info(parser);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (info->type_offset == (size_t)-1)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str = t_str_new(256);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen p = strchr(line, '=');
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append_n(str, line, p-line);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(str, p+1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, info_type_name_find(info));
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append_c(str, '=');
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append(str, section_name);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = settings_parse_line(parser, str_c(str));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_assert(ret > 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic int
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenconfig_apply_line(struct parser_context *ctx, const char *key,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *line, const char *section_name,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char **error_r)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct config_module_parser *l;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen bool found = FALSE;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (l = ctx->cur_section->parsers; l->root != NULL; l++) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = settings_parse_line(l->parser, line);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (ret > 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen found = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (section_name != NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen config_add_type(l->parser, line, section_name);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen } else if (ret < 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *error_r = settings_parser_get_error(l->parser);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (!found) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *error_r = t_strconcat("Unknown setting: ", key, NULL);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *error_r = NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic const char *
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainenfix_relative_path(const char *path, struct input_stack *input)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *p;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*path == '/')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return path;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen p = strrchr(input->path, '/');
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (p == NULL)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return path;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen}
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainenstatic struct config_module_parser *
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainenconfig_module_parsers_init(pool_t pool)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen{
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen struct config_module_parser *dest;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen unsigned int i, count;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (count = 0; all_roots[count] != NULL; count++) ;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen dest = p_new(pool, struct config_module_parser, count + 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (i = 0; i < count; i++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen dest[i].root = all_roots[i];
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen dest[i].parser = settings_parser_init(pool, all_roots[i],
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen settings_parser_flags);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return dest;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenconfig_add_new_parser(struct parser_context *ctx)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct config_section_stack *cur_section = ctx->cur_section;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct config_filter_parser *parser;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen parser = p_new(ctx->pool, struct config_filter_parser, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen parser->filter = cur_section->filter;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ctx->cur_input->linenum == 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen parser->file_and_line =
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen p_strdup(ctx->pool, ctx->cur_input->path);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen parser->file_and_line =
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen p_strdup_printf(ctx->pool, "%s:%d",
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen ctx->cur_input->path,
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen ctx->cur_input->linenum);
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen parser->parsers = cur_section->prev == NULL ? ctx->root_parsers :
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen config_module_parsers_init(ctx->pool);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen array_append(&ctx->all_parsers, &parser, 1);
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen cur_section->parsers = parser->parsers;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic struct config_section_stack *
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenconfig_add_new_section(struct parser_context *ctx)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct config_section_stack *section;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen section = p_new(ctx->pool, struct config_section_stack, 1);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen section->prev = ctx->cur_section;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen section->filter = ctx->cur_section->filter;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen section->parsers = ctx->cur_section->parsers;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return section;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic struct config_filter_parser *
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenconfig_filter_parser_find(struct parser_context *ctx,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const struct config_filter *filter)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct config_filter_parser *const *parsers;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned int i, count;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen parsers = array_get(&ctx->all_parsers, &count);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (i = 0; i < count; i++) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (config_filters_equal(&parsers[i]->filter, filter))
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return parsers[i];
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return NULL;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen}
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainenstatic bool
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainenconfig_filter_add_new_filter(struct parser_context *ctx,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen const char *key, const char *value,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char **error_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen struct config_filter *filter = &ctx->cur_section->filter;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen struct config_filter *parent = &ctx->cur_section->prev->filter;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen struct config_filter_parser *parser;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (strcmp(key, "protocol") == 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (parent->service != NULL)
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen *error_r = "protocol must not be under protocol";
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen else
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen filter->service = p_strdup(ctx->pool, value);
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen } else if (strcmp(key, "local_ip") == 0) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (parent->remote_bits > 0)
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen *error_r = "local_ip must not be under remote_ip";
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen else if (parent->service != NULL)
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen *error_r = "local_ip must not be under protocol";
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen else if (net_parse_range(value, &filter->local_net,
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen &filter->local_bits) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *error_r = "Invalid network mask";
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else if (parent->local_bits > filter->local_bits ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen (parent->local_bits > 0 &&
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen !net_is_in_network(&filter->local_net,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen &parent->local_net,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen parent->local_bits)))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *error_r = "local_ip not a subset of parent local_ip";
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else if (strcmp(key, "remote_ip") == 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (parent->service != NULL)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen *error_r = "remote_ip must not be under protocol";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen else if (net_parse_range(value, &filter->remote_net,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen &filter->remote_bits) < 0)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen *error_r = "Invalid network mask";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen else if (parent->remote_bits > filter->remote_bits ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen (parent->remote_bits > 0 &&
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen !net_is_in_network(&filter->remote_net,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen &parent->remote_net,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen parent->remote_bits)))
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen *error_r = "remote_ip not a subset of parent remote_ip";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen } else {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return FALSE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen parser = config_filter_parser_find(ctx, filter);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (parser != NULL)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ctx->cur_section->parsers = parser->parsers;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen else
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen config_add_new_parser(ctx);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return TRUE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenstatic int
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenconfig_filter_parser_check(struct parser_context *ctx,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen const struct config_module_parser *p,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen const char **error_r)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen{
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen for (; p->root != NULL; p++) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen settings_parse_var_skip(p->parser);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!settings_parser_check(p->parser, ctx->pool, error_r))
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return 0;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenconfig_all_parsers_check(struct parser_context *ctx,
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen struct config_filter_context *new_filter,
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen const char **error_r)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen{
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen struct config_filter_parser *const *parsers;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen struct config_module_parser *tmp_parsers;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unsigned int i, count;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen pool_t tmp_pool;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen int ret = 0;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen tmp_pool = pool_alloconly_create("config parsers check", 1024*32);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen parsers = array_get(&ctx->all_parsers, &count);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen i_assert(count > 0 && parsers[count-1] == NULL);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen count--;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen for (i = 0; i < count && ret == 0; i++) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (config_filter_parsers_get(new_filter, tmp_pool,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen &parsers[i]->filter,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen &tmp_parsers, error_r) < 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ret = -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ret = config_filter_parser_check(ctx, tmp_parsers, error_r);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen config_filter_parsers_free(tmp_parsers);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen p_clear(tmp_pool);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen pool_unref(&tmp_pool);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return ret;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen}
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenstatic int
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenstr_append_file(string_t *str, const char *key, const char *path,
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen const char **error_r)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen{
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen unsigned char buf[1024];
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen int fd;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ssize_t ret;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen fd = open(path, O_RDONLY);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (fd == -1) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen *error_r = t_strdup_printf("%s: Can't open file %s: %m",
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen key, path);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen while ((ret = read(fd, buf, sizeof(buf))) > 0)
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen str_append_n(str, buf, ret);
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen if (ret < 0) {
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen *error_r = t_strdup_printf("%s: read(%s) failed: %m",
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen key, path);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen (void)close(fd);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return ret < 0 ? -1 : 0;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainenstatic int settings_add_include(struct parser_context *ctx, const char *path,
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen bool ignore_errors, const char **error_r)
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen{
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen struct input_stack *tmp, *new_input;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen int fd;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen for (tmp = ctx->cur_input; tmp != NULL; tmp = tmp->prev) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (strcmp(tmp->path, path) == 0)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (tmp != NULL) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen *error_r = t_strdup_printf("Recursive include file: %s", path);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return -1;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if ((fd = open(path, O_RDONLY)) == -1) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (ignore_errors)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return 0;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen *error_r = t_strdup_printf("Couldn't open include file %s: %m",
d22301419109ed4a38351715e6760011421dadecTimo Sirainen path);
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen return -1;
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen }
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen new_input = t_new(struct input_stack, 1);
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen new_input->prev = ctx->cur_input;
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen new_input->path = t_strdup(path);
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen new_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen i_stream_set_return_partial_line(new_input->input, TRUE);
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen ctx->cur_input = new_input;
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen return 0;
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen}
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenstatic int
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainensettings_include(struct parser_context *ctx, const char *pattern,
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen bool ignore_errors, const char **error_r)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen{
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen#ifdef HAVE_GLOB
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen glob_t globbers;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen unsigned int i;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen case 0:
9d6dec796909384293006e4289436579089d88d5Timo Sirainen break;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen case GLOB_NOSPACE:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *error_r = "glob() failed: Not enough memory";
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen case GLOB_ABORTED:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *error_r = "glob() failed: Read error";
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen case GLOB_NOMATCH:
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (ignore_errors)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *error_r = "No matches";
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return -1;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen default:
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen *error_r = "glob() failed: Unknown error";
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return -1;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* iterate throuth the different files matching the globbing */
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen for (i = 0; i < globbers.gl_pathc; i++) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (settings_add_include(ctx, globbers.gl_pathv[i],
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen ignore_errors, error_r) < 0)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen globfree(&globbers);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#else
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return settings_add_include(ctx, pattern, ignore_errors, error_r);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen#endif
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenenum config_line_type {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen CONFIG_LINE_TYPE_SKIP,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen CONFIG_LINE_TYPE_ERROR,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen CONFIG_LINE_TYPE_KEYVALUE,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen CONFIG_LINE_TYPE_KEYFILE,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen CONFIG_LINE_TYPE_SECTION_BEGIN,
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen CONFIG_LINE_TYPE_SECTION_END,
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen CONFIG_LINE_TYPE_INCLUDE,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen CONFIG_LINE_TYPE_INCLUDE_TRY
d22301419109ed4a38351715e6760011421dadecTimo Sirainen};
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenstatic enum config_line_type
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenconfig_parse_line(struct parser_context *ctx, char *line, string_t *full_line,
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen const char **key_r, const char **value_r)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen{
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen const char *key;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unsigned int len;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen char *p;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen *key_r = NULL;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen *value_r = NULL;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* @UNSAFE: line is modified */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
9d6dec796909384293006e4289436579089d88d5Timo Sirainen /* skip whitespace */
9d6dec796909384293006e4289436579089d88d5Timo Sirainen while (IS_WHITE(*line))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen line++;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* ignore comments or empty lines */
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen if (*line == '#' || *line == '\0')
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return CONFIG_LINE_TYPE_SKIP;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* strip away comments. pretty kludgy way really.. */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen for (p = line; *p != '\0'; p++) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (*p == '\'' || *p == '"') {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen char quote = *p;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen for (p++; *p != quote && *p != '\0'; p++) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (*p == '\\' && p[1] != '\0')
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen p++;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
9d6dec796909384293006e4289436579089d88d5Timo Sirainen if (*p == '\0')
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen break;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen } else if (*p == '#') {
9d6dec796909384293006e4289436579089d88d5Timo Sirainen if (!IS_WHITE(p[-1])) {
9d6dec796909384293006e4289436579089d88d5Timo Sirainen i_warning("Configuration file %s line %u: "
9d6dec796909384293006e4289436579089d88d5Timo Sirainen "Ambiguous '#' character in line, treating it as comment. "
9d6dec796909384293006e4289436579089d88d5Timo Sirainen "Add a space before it to remove this warning.",
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen ctx->cur_input->path,
9d6dec796909384293006e4289436579089d88d5Timo Sirainen ctx->cur_input->linenum);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen }
9d6dec796909384293006e4289436579089d88d5Timo Sirainen *p = '\0';
9d6dec796909384293006e4289436579089d88d5Timo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* remove whitespace from end of line */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen len = strlen(line);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen while (IS_WHITE(line[len-1]))
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen len--;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen line[len] = '\0';
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (len > 0 && line[len-1] == '\\') {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* continues in next line */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen line[len-1] = '\0';
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(full_line, line);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return CONFIG_LINE_TYPE_SKIP;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (str_len(full_line) > 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(full_line, line);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen line = str_c_modifiable(full_line);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* a) key = value
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen b) section_type [section_name] {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen c) } */
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen key = line;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen line++;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (IS_WHITE(*line)) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *line++ = '\0';
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen while (IS_WHITE(*line)) line++;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *key_r = key;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *value_r = line;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (strcmp(key, "!include") == 0)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_INCLUDE;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (strcmp(key, "!include_try") == 0)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_INCLUDE_TRY;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (*line == '=') {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* a) */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen *line++ = '\0';
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen while (IS_WHITE(*line)) line++;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (*line == '<') {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *value_r = line + 1;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_KEYFILE;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen len = strlen(line);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (len > 0 &&
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen ((*line == '"' && line[len-1] == '"') ||
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen (*line == '\'' && line[len-1] == '\''))) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen line[len-1] = '\0';
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen line = str_unescape(line+1);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *value_r = line;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_KEYVALUE;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (strcmp(key, "}") == 0 && *line == '\0')
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return CONFIG_LINE_TYPE_SECTION_END;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen /* b) + errors */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen line[-1] = '\0';
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (*line == '{')
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *value_r = "";
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* get section name */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *value_r = line;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen while (!IS_WHITE(*line) && *line != '\0')
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen line++;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (*line != '\0') {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *line++ = '\0';
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen while (IS_WHITE(*line))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen line++;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (*line != '{') {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *value_r = "Expecting '='";
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_ERROR;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (line[1] != '\0') {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *value_r = "Garbage after '{'";
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_ERROR;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return CONFIG_LINE_TYPE_SECTION_BEGIN;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen}
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainenstatic int config_parse_finish(struct parser_context *ctx, const char **error_r)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen{
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen struct config_filter_context *new_filter;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen const char *error;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen new_filter = config_filter_init(ctx->pool);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen (void)array_append_space(&ctx->all_parsers);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen config_filter_add_all(new_filter, array_idx(&ctx->all_parsers, 0));
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (config_all_parsers_check(ctx, new_filter, &error) < 0) {
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen *error_r = t_strdup_printf("Error in configuration file %s: %s",
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen ctx->path, error);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return -1;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (config_filter != NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen config_filter_deinit(&config_filter);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen config_module_parsers = ctx->root_parsers;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen config_filter = new_filter;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen return 0;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenint config_parse_file(const char *path, bool expand_files,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char **error_r)
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen{
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen struct input_stack root;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen struct parser_context ctx;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen unsigned int pathlen = 0;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen unsigned int i, count, counter = 0;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen const char *errormsg, *key, *value, *section_name;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen string_t *str, *full_line;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen enum config_line_type type;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen char *line;
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen int fd, ret = 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen fd = open(path, O_RDONLY);
35077ff71c0082c1370d9c296abce3153f645958Timo Sirainen if (fd < 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *error_r = t_strdup_printf("open(%s) failed: %m", path);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen memset(&ctx, 0, sizeof(ctx));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx.pool = pool_alloconly_create("config file parser", 1024*64);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx.path = path;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen for (count = 0; all_roots[count] != NULL; count++) ;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx.root_parsers =
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_new(ctx.pool, struct config_module_parser, count+1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen for (i = 0; i < count; i++) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx.root_parsers[i].root = all_roots[i];
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx.root_parsers[i].parser =
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen settings_parser_init(ctx.pool, all_roots[i],
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen settings_parser_flags);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen memset(&root, 0, sizeof(root));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen root.path = path;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx.cur_input = &root;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_array_init(&ctx.all_parsers, ctx.pool, 128);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx.cur_section = p_new(ctx.pool, struct config_section_stack, 1);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen config_add_new_parser(&ctx);
7c27b0ab7213121ea43994499c04059413f6d0f2Timo Sirainen
7c27b0ab7213121ea43994499c04059413f6d0f2Timo Sirainen str = t_str_new(256);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen full_line = t_str_new(512);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen errormsg = NULL;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainenprevfile:
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen ctx.cur_input->linenum++;
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen type = config_parse_line(&ctx, line, full_line,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen &key, &value);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen switch (type) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen case CONFIG_LINE_TYPE_SKIP:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen case CONFIG_LINE_TYPE_ERROR:
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen errormsg = value;
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen break;
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen case CONFIG_LINE_TYPE_KEYVALUE:
88de8e8fb4ad86f59ac0c4d85f5a9103dfd3fcc0Timo Sirainen case CONFIG_LINE_TYPE_KEYFILE:
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_truncate(str, pathlen);
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen str_append(str, key);
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen str_append_c(str, '=');
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen if (type != CONFIG_LINE_TYPE_KEYFILE)
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen str_append(str, value);
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen else if (!expand_files) {
6797b2bb35596ec47d7f140eba79d4c686f370bcTimo Sirainen str_append_c(str, '<');
d22301419109ed4a38351715e6760011421dadecTimo Sirainen str_append(str, value);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else if (str_append_file(str, key, value, &errormsg) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* file reading failed */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
822b71c04ddd61cb08a0104f9e58f55334725e2aTimo Sirainen (void)config_apply_line(&ctx, key, str_c(str), NULL, &errormsg);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case CONFIG_LINE_TYPE_SECTION_BEGIN:
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx.cur_section = config_add_new_section(&ctx);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ctx.cur_section->pathlen = pathlen;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (config_filter_add_new_filter(&ctx, key, value,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen &errormsg)) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* new filter */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen break;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* new config section */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (*value == '\0') {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* no section name, use a counter */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen section_name = dec2str(counter++);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen section_name = settings_section_escape(value);
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_truncate(str, pathlen);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pathlen = str_len(str);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append_c(str, '=');
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append(str, section_name);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (config_apply_line(&ctx, key, str_c(str), value, &errormsg) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_truncate(str, pathlen);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(str, section_name);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen pathlen = str_len(str);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen case CONFIG_LINE_TYPE_SECTION_END:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ctx.cur_section->prev == NULL)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen errormsg = "Unexpected '}'";
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen pathlen = ctx.cur_section->pathlen;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ctx.cur_section = ctx.cur_section->prev;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen case CONFIG_LINE_TYPE_INCLUDE:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen case CONFIG_LINE_TYPE_INCLUDE_TRY:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen (void)settings_include(&ctx, fix_relative_path(value, ctx.cur_input),
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen type == CONFIG_LINE_TYPE_INCLUDE_TRY,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen &errormsg);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen if (errormsg != NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *error_r = t_strdup_printf(
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "Error in configuration file %s line %d: %s",
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx.cur_input->path, ctx.cur_input->linenum,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen errormsg);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ret = -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen }
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen str_truncate(full_line, 0);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_stream_destroy(&ctx.cur_input->input);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx.cur_input = ctx.cur_input->prev;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (line == NULL && ctx.cur_input != NULL)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen goto prevfile;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (ret == 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = config_parse_finish(&ctx, error_r);
c817e46049c4dc07f7bbc16f43f903ab7ea9ae7dTimo Sirainen if (ret < 0) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen pool_unref(&ctx.pool);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen