config-parser.c revision 36175032e12e7dfe67f92ee7c2065fdc6865aefd
e8058322725ba050014777ee2484f7e833ab1e3aLukas Slebodnik/* Copyright (c) 2005-2011 Dovecot authors, see the included COPYING file */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "lib.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "array.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "str.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "hash.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "strescape.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "istream.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "module-dir.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "settings-parser.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "service-settings.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "master-service.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "master-service-settings.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "all-settings.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "old-set-parser.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "config-request.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "config-parser-private.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <stdlib.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <unistd.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <fcntl.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <time.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#ifdef HAVE_GLOB_H
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter# include <glob.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#endif
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#ifndef GLOB_BRACE
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter# define GLOB_BRACE 0
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#endif
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#define DNS_LOOKUP_TIMEOUT_SECS 30
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#define DNS_LOOKUP_WARN_SECS 5
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic const enum settings_parser_flags settings_parser_flags =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS |
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter SETTINGS_PARSER_FLAG_TRACK_CHANGES;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstruct config_module_parser *config_module_parsers;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstruct config_filter_context *config_filter;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstruct module *modules;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Waltervoid (*hook_config_parser_begin)(struct config_parser_context *ctx);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic const char *info_type_name_find(const struct setting_parser_info *info)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int i;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (i = 0; info->defines[i].key != NULL; i++) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (info->defines[i].offset == info->type_offset)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return info->defines[i].key;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_panic("setting parser: Invalid type_offset value");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return NULL;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic int config_add_type(struct setting_parser_context *parser,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *line, const char *section_name)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const struct setting_parser_info *info;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *p;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter string_t *str;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter int ret;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter info = settings_parse_get_prev_info(parser);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (info == NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* section inside strlist */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (info->type_offset == (size_t)-1)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str = t_str_new(256);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p = strchr(line, '=');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_n(str, line, p-line);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(str, SETTINGS_SEPARATOR);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, p+1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (info != NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(str, SETTINGS_SEPARATOR);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, info_type_name_find(info));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(str, '=');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, section_name);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = settings_parse_line(parser, str_c(str));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_assert(ret > 0);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic bool
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterconfig_parser_is_in_localremote(struct config_section_stack *section)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const struct config_filter *filter = &section->filter;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return filter->local_name != NULL || filter->local_bits > 0 ||
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter filter->remote_bits > 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterint config_apply_line(struct config_parser_context *ctx, const char *key,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *line, const char *section_name)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct config_module_parser *l;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter bool found = FALSE;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int ret;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter for (l = ctx->cur_section->parsers; l->root != NULL; l++) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ret = settings_parse_line(l->parser, line);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (ret > 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter found = TRUE;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* FIXME: remove once auth does support these. */
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (strcmp(l->root->module_name, "auth") == 0 &&
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter config_parser_is_in_localremote(ctx->cur_section)) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = p_strconcat(ctx->pool,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter "Auth settings not supported inside local/remote blocks: ",
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter key, NULL);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (section_name != NULL) {
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter if (config_add_type(l->parser, line, section_name) < 0) {
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter ctx->error = "Section not allowed here";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter } else if (ret < 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = settings_parser_get_error(l->parser);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (!found) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = p_strconcat(ctx->pool, "Unknown setting: ",
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter key, NULL);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic const char *
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterfix_relative_path(const char *path, struct input_stack *input)
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter{
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter const char *p;
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter if (*path == '/')
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter return path;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p = strrchr(input->path, '/');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (p == NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return path;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic struct config_module_parser *
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterconfig_module_parsers_init(pool_t pool)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_module_parser *dest;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter unsigned int i, count;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter for (count = 0; all_roots[count] != NULL; count++) ;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter dest = p_new(pool, struct config_module_parser, count + 1);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter for (i = 0; i < count; i++) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter dest[i].root = all_roots[i];
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter dest[i].parser = settings_parser_init(pool, all_roots[i],
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter settings_parser_flags);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return dest;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterconfig_add_new_parser(struct config_parser_context *ctx)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_section_stack *cur_section = ctx->cur_section;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_filter_parser *parser;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter parser = p_new(ctx->pool, struct config_filter_parser, 1);
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter parser->filter = cur_section->filter;
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter if (ctx->cur_input->linenum == 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter parser->file_and_line =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p_strdup(ctx->pool, ctx->cur_input->path);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter parser->file_and_line =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p_strdup_printf(ctx->pool, "%s:%d",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->cur_input->path,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->cur_input->linenum);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter parser->parsers = cur_section->prev == NULL ? ctx->root_parsers :
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter config_module_parsers_init(ctx->pool);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter array_append(&ctx->all_parsers, &parser, 1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter cur_section->parsers = parser->parsers;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic struct config_section_stack *
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekconfig_add_new_section(struct config_parser_context *ctx)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek struct config_section_stack *section;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek section = p_new(ctx->pool, struct config_section_stack, 1);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek section->prev = ctx->cur_section;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek section->filter = ctx->cur_section->filter;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek section->parsers = ctx->cur_section->parsers;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter section->open_path = p_strdup(ctx->pool, ctx->cur_input->path);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter section->open_linenum = ctx->cur_input->linenum;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return section;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic struct config_filter_parser *
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterconfig_filter_parser_find(struct config_parser_context *ctx,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const struct config_filter *filter)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_filter_parser *const *parsers;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter array_foreach(&ctx->all_parsers, parsers) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_filter_parser *parser = *parsers;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (config_filters_equal(&parser->filter, filter))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return parser;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return NULL;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterint config_parse_net(const char *value, struct ip_addr *ip_r,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter unsigned int *bits_r, const char **error_r)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct ip_addr *ips;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter const char *p;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter unsigned int ip_count, bits, max_bits;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter time_t t1, t2;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int ret;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (net_parse_range(value, ip_r, bits_r) == 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter p = strchr(value, '/');
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (p != NULL) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter value = t_strdup_until(value, p);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter p++;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter t1 = time(NULL);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter alarm(DNS_LOOKUP_TIMEOUT_SECS);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ret = net_gethostbyname(value, &ips, &ip_count);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter alarm(0);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter t2 = time(NULL);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (ret != 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *error_r = t_strdup_printf("gethostbyname(%s) failed: %s",
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter value, net_gethosterror(ret));
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *ip_r = ips[0];
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (t2 - t1 >= DNS_LOOKUP_WARN_SECS) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_warning("gethostbyname(%s) took %d seconds",
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter value, (int)(t2-t1));
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter max_bits = IPADDR_IS_V4(&ips[0]) ? 32 : 128;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (p == NULL || str_to_uint(p, &bits) < 0 || bits > max_bits)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *bits_r = max_bits;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter else
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *bits_r = bits;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic bool
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterconfig_filter_add_new_filter(struct config_parser_context *ctx,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter const char *key, const char *value)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct config_filter *filter = &ctx->cur_section->filter;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct config_filter *parent = &ctx->cur_section->prev->filter;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct config_filter_parser *parser;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter const char *error;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (strcmp(key, "protocol") == 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (parent->service != NULL)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = "protocol must not be under protocol";
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter else
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter filter->service = p_strdup(ctx->pool, value);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter } else if (strcmp(key, "local") == 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (parent->remote_bits > 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = "local must not be under remote";
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter else if (parent->service != NULL)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = "local must not be under protocol";
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter else if (parent->local_name != NULL)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = "local must not be under local_name";
66277b21179d95f6e96abed01a20ccbccf27ce99Pavel Březina else if (config_parse_net(value, &filter->local_net,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter &filter->local_bits, &error) < 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = p_strdup(ctx->pool, error);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter else if (parent->local_bits > filter->local_bits ||
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter (parent->local_bits > 0 &&
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter !net_is_in_network(&filter->local_net,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter &parent->local_net,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter parent->local_bits)))
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->error = "local not a subset of parent local";
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek else
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek filter->local_host = p_strdup(ctx->pool, value);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek } else if (strcmp(key, "local_name") == 0) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek if (parent->remote_bits > 0)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->error = "local_name must not be under remote";
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek else if (parent->service != NULL)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->error = "local_name must not be under protocol";
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek else
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek filter->local_name = p_strdup(ctx->pool, value);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek } else if (strcmp(key, "remote") == 0) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek if (parent->service != NULL)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->error = "remote must not be under protocol";
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek else if (config_parse_net(value, &filter->remote_net,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek &filter->remote_bits, &error) < 0)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->error = p_strdup(ctx->pool, error);
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter else if (parent->remote_bits > filter->remote_bits ||
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter (parent->remote_bits > 0 &&
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek !net_is_in_network(&filter->remote_net,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek &parent->remote_net,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek parent->remote_bits)))
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ctx->error = "remote not a subset of parent remote";
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek else
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek filter->remote_host = p_strdup(ctx->pool, value);
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter } else {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek return FALSE;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter parser = config_filter_parser_find(ctx, filter);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (parser != NULL)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ctx->cur_section->parsers = parser->parsers;
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter else
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter config_add_new_parser(ctx);
66277b21179d95f6e96abed01a20ccbccf27ce99Pavel Březina return TRUE;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walterstatic int
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walterconfig_filter_parser_check(struct config_parser_context *ctx,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek const struct config_module_parser *p,
58229439447d5617913a5a2e173b78105c694842Pavel Březina const char **error_r)
58229439447d5617913a5a2e173b78105c694842Pavel Březina{
5de968e80ade1c02d1907834dcff95e9fc9ad10aJakub Hrozek for (; p->root != NULL; p++) {
5de968e80ade1c02d1907834dcff95e9fc9ad10aJakub Hrozek /* skip checking settings we don't care about */
58229439447d5617913a5a2e173b78105c694842Pavel Březina if (*ctx->module != '\0' &&
58229439447d5617913a5a2e173b78105c694842Pavel Březina !config_module_want_parser(ctx->root_parsers,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ctx->module, p->root))
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek continue;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek settings_parse_var_skip(p->parser);
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter if (!settings_parser_check(p->parser, ctx->pool, error_r))
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter return -1;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek return 0;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek}
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozekstatic const char *
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozekget_str_setting(struct config_filter_parser *parser, const char *key,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek const char *default_value)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek{
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek struct config_module_parser *module_parser;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek const char *const *set_value;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek enum setting_type set_type;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek module_parser = parser->parsers;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek for (; module_parser->parser != NULL; module_parser++) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek set_value = settings_parse_get_value(module_parser->parser,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek key, &set_type);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek if (set_value != NULL &&
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek settings_parse_is_changed(module_parser->parser, key)) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek i_assert(set_type == SET_STR || set_type == SET_ENUM);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek return *set_value;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek return default_value;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek}
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozekstatic int
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozekconfig_all_parsers_check(struct config_parser_context *ctx,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek struct config_filter_context *new_filter,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek const char **error_r)
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek{
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek struct config_filter_parser *const *parsers;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek struct config_module_parser *tmp_parsers;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek struct master_service_settings_output output;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek unsigned int i, count;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek const char *ssl_set, *global_ssl_set;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek pool_t tmp_pool;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek bool ssl_warned = FALSE;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek int ret = 0;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
66277b21179d95f6e96abed01a20ccbccf27ce99Pavel Březina if (ctx->cur_section->prev != NULL) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek *error_r = t_strdup_printf(
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek "Missing '}' (section started at %s:%u)",
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->cur_section->open_path,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ctx->cur_section->open_linenum);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek return -1;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek tmp_pool = pool_alloconly_create("config parsers check", 1024*64);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek parsers = array_get(&ctx->all_parsers, &count);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek i_assert(count > 0 && parsers[count-1] == NULL);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek count--;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek global_ssl_set = get_str_setting(parsers[0], "ssl", "");
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek for (i = 0; i < count && ret == 0; i++) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek if (config_filter_parsers_get(new_filter, tmp_pool, "",
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek &parsers[i]->filter,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek &tmp_parsers, &output,
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek error_r) < 0) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ret = -1;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek break;
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ssl_set = get_str_setting(parsers[i], "ssl", global_ssl_set);
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek if (strcmp(ssl_set, "no") != 0 &&
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek strcmp(global_ssl_set, "no") == 0 && !ssl_warned) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek i_warning("SSL is disabled because global ssl=no, "
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek "ignoring ssl=%s for subsection", ssl_set);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ssl_warned = TRUE;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ret = config_filter_parser_check(ctx, tmp_parsers, error_r);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter config_filter_parsers_free(tmp_parsers);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter p_clear(tmp_pool);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter pool_unref(&tmp_pool);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return ret;
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic int
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstr_append_file(string_t *str, const char *key, const char *path,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter const char **error_r)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter unsigned char buf[1024];
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int fd;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ssize_t ret;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek fd = open(path, O_RDONLY);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (fd == -1) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek *error_r = t_strdup_printf("%s: Can't open file %s: %m",
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek key, path);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek return -1;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek while ((ret = read(fd, buf, sizeof(buf))) > 0)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str_append_n(str, buf, ret);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (ret < 0) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek *error_r = t_strdup_printf("%s: read(%s) failed: %m",
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek key, path);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)close(fd);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek return ret < 0 ? -1 : 0;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic int settings_add_include(struct config_parser_context *ctx, const char *path,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek bool ignore_errors, const char **error_r)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter struct input_stack *tmp, *new_input;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int fd;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter for (tmp = ctx->cur_input; tmp != NULL; tmp = tmp->prev) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (strcmp(tmp->path, path) == 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter break;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (tmp != NULL) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *error_r = t_strdup_printf("Recursive include file: %s", path);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if ((fd = open(path, O_RDONLY)) == -1) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (ignore_errors)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *error_r = t_strdup_printf("Couldn't open include file %s: %m",
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter path);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter new_input = p_new(ctx->pool, struct input_stack, 1);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter new_input->prev = ctx->cur_input;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter new_input->path = p_strdup(ctx->pool, path);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter new_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter i_stream_set_return_partial_line(new_input->input, TRUE);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter ctx->cur_input = new_input;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic int
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Waltersettings_include(struct config_parser_context *ctx, const char *pattern,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter bool ignore_errors)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *error;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#ifdef HAVE_GLOB
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter glob_t globbers;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter unsigned int i;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case 0:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case GLOB_NOSPACE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = "glob() failed: Not enough memory";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case GLOB_ABORTED:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = "glob() failed: Read error";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter case GLOB_NOMATCH:
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (ignore_errors)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = "No matches";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter default:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = "glob() failed: Unknown error";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* iterate throuth the different files matching the globbing */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (i = globbers.gl_pathc; i > 0; i--) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (settings_add_include(ctx, globbers.gl_pathv[i-1],
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ignore_errors, &error) < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strdup(ctx->pool, error);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter globfree(&globbers);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter#else
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (settings_add_include(ctx, pattern, ignore_errors, &error) < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strdup(ctx->pool, error);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#endif
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic enum config_line_type
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterconfig_parse_line(struct config_parser_context *ctx,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter char *line, string_t *full_line,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char **key_r, const char **value_r)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *key;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int len;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter char *p;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *key_r = NULL;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *value_r = NULL;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* @UNSAFE: line is modified */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* skip whitespace */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (IS_WHITE(*line))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter line++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* ignore comments or empty lines */
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (*line == '#' || *line == '\0')
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return CONFIG_LINE_TYPE_SKIP;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* strip away comments. pretty kludgy way really.. */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (p = line; *p != '\0'; p++) {
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter if (*p == '\'' || *p == '"') {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter char quote = *p;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (p++; *p != quote && *p != '\0'; p++) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*p == '\\' && p[1] != '\0')
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*p == '\0')
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else if (*p == '#') {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (!IS_WHITE(p[-1])) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_warning("Configuration file %s line %u: "
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek "Ambiguous '#' character in line, treating it as comment. "
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek "Add a space before it to remove this warning.",
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ctx->cur_input->path,
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ctx->cur_input->linenum);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek *p = '\0';
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* remove whitespace from end of line */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter len = strlen(line);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (IS_WHITE(line[len-1]))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter len--;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter line[len] = '\0';
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (len > 0 && line[len-1] == '\\') {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* continues in next line */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter len--;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (IS_WHITE(line[len-1]))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter len--;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_n(full_line, line, len);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(full_line, ' ');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return CONFIG_LINE_TYPE_SKIP;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (str_len(full_line) > 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(full_line, line);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter line = str_c_modifiable(full_line);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* a) key = value
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek b) section_type [section_name] {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek c) } */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter key = line;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter line++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (IS_WHITE(*line)) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *line++ = '\0';
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (IS_WHITE(*line)) line++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *key_r = key;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *value_r = line;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (strcmp(key, "!include") == 0)
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter return CONFIG_LINE_TYPE_INCLUDE;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (strcmp(key, "!include_try") == 0)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return CONFIG_LINE_TYPE_INCLUDE_TRY;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (*line == '=') {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* a) */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *line++ = '\0';
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (IS_WHITE(*line)) line++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*line == '<') {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *value_r = line + 1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return CONFIG_LINE_TYPE_KEYFILE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*line == '$') {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *value_r = line + 1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return CONFIG_LINE_TYPE_KEYVARIABLE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter len = strlen(line);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (len > 0 &&
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek ((*line == '"' && line[len-1] == '"') ||
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek (*line == '\'' && line[len-1] == '\''))) {
4f7f714e118e95896fac5239c7a8b529c39a4758Jakub Hrozek line[len-1] = '\0';
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter line = str_unescape(line+1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *value_r = line;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek return CONFIG_LINE_TYPE_KEYVALUE;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (strcmp(key, "}") == 0 && *line == '\0')
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return CONFIG_LINE_TYPE_SECTION_END;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* b) + errors */
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter line[-1] = '\0';
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (*line == '{')
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter *value_r = "";
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter else {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter /* get section name */
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter *value_r = line;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter while (!IS_WHITE(*line) && *line != '\0')
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter line++;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (*line != '\0') {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter *line++ = '\0';
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter while (IS_WHITE(*line))
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek line++;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (*line != '{') {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter *value_r = "Expecting '='";
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter return CONFIG_LINE_TYPE_ERROR;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter }
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter }
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter if (line[1] != '\0') {
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter *value_r = "Garbage after '{'";
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter return CONFIG_LINE_TYPE_ERROR;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter }
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter return CONFIG_LINE_TYPE_SECTION_BEGIN;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter}
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Walterstatic int config_parse_finish(struct config_parser_context *ctx, const char **error_r)
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_filter_context *new_filter;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *error;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter int ret;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter new_filter = config_filter_init(ctx->pool);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter (void)array_append_space(&ctx->all_parsers);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter config_filter_add_all(new_filter, array_idx(&ctx->all_parsers, 0));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if ((ret = config_all_parsers_check(ctx, new_filter, &error)) < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *error_r = t_strdup_printf("Error in configuration file %s: %s",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->path, error);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter }
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter if (config_filter != NULL)
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter config_filter_deinit(&config_filter);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter config_module_parsers = ctx->root_parsers;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter config_filter = new_filter;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter return ret;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter}
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Walterstatic const void *
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walterconfig_get_value(struct config_section_stack *section, const char *key,
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter bool expand_parent, enum setting_type *type_r)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter struct config_module_parser *l;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter const void *value;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter for (l = section->parsers; l->root != NULL; l++) {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter value = settings_parse_get_value(l->parser, key, type_r);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (value != NULL) {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (!expand_parent || section->prev == NULL ||
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter settings_parse_is_changed(l->parser, key))
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return value;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* not changed by this parser. maybe parent has. */
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter return config_get_value(section->prev,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter key, TRUE, type_r);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter }
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter }
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter return NULL;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walterstatic bool
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterconfig_require_key(struct config_parser_context *ctx, const char *key)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter struct config_module_parser *l;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*ctx->module == '\0')
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return TRUE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (l = ctx->cur_section->parsers; l->root != NULL; l++) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (config_module_want_parser(ctx->root_parsers,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->module, l->root) &&
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter settings_parse_is_valid_key(l->parser, key))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return TRUE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return FALSE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic int config_write_value(struct config_parser_context *ctx,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter enum config_line_type type,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *key, const char *value)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter string_t *str = ctx->str;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const void *var_name, *var_value, *p;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter enum setting_type var_type;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *error;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter bool dump, expand_parent;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter switch (type) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYVALUE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYFILE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!ctx->expand_values) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(str, '<');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!config_require_key(ctx, key)) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* don't even try to open the file */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else if (str_append_file(str, key, value, &error) < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* file reading failed */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strdup(ctx->pool, error);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYVARIABLE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* expand_parent=TRUE for "key = $key stuff".
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter we'll always expand it so that doveconf -n can give
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter usable output */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p = strchr(value, ' ');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (p == NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_name = value;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter else
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_name = t_strdup_until(value, p);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter expand_parent = strcmp(key, var_name) == 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!ctx->expand_values && !expand_parent) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(str, '$');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_value = config_get_value(ctx->cur_section, var_name,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter expand_parent, &var_type);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (var_value == NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strconcat(ctx->pool,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "Unknown variable: $",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_name, NULL);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!config_export_type(str, var_value, NULL,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_type, TRUE, &dump)) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strconcat(ctx->pool,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "Invalid variable: $",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter var_name, NULL);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (p != NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(str, p);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter default:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_unreached();
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Waltervoid config_parser_apply_line(struct config_parser_context *ctx,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter enum config_line_type type,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *key, const char *value)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *section_name;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_truncate(ctx->str, ctx->pathlen);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter switch (type) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_SKIP:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_ERROR:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = p_strdup(ctx->pool, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYVALUE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYFILE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_KEYVARIABLE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(ctx->str, key);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ctx->str, '=');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (config_write_value(ctx, type, key, value) < 0)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter (void)config_apply_line(ctx, key, str_c(ctx->str), NULL);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_SECTION_BEGIN:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->cur_section = config_add_new_section(ctx);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->cur_section->pathlen = ctx->pathlen;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (config_filter_add_new_filter(ctx, key, value)) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* new filter */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* new config section */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (*value == '\0') {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* no section name, use a counter */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter section_name = dec2str(ctx->section_counter++);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter section_name = settings_section_escape(value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(ctx->str, key);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->pathlen = str_len(ctx->str);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ctx->str, '=');
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(ctx->str, section_name);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (config_apply_line(ctx, key, str_c(ctx->str), value) < 0)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_truncate(ctx->str, ctx->pathlen);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ctx->str, SETTINGS_SEPARATOR);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append(ctx->str, section_name);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_append_c(ctx->str, SETTINGS_SEPARATOR);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->pathlen = str_len(ctx->str);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_SECTION_END:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (ctx->cur_section->prev == NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->error = "Unexpected '}'";
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->pathlen = ctx->cur_section->pathlen;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx->cur_section = ctx->cur_section->prev;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_INCLUDE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case CONFIG_LINE_TYPE_INCLUDE_TRY:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter (void)settings_include(ctx, fix_relative_path(value, ctx->cur_input),
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter type == CONFIG_LINE_TYPE_INCLUDE_TRY);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterint config_parse_file(const char *path, bool expand_values, const char *module,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char **error_r)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct input_stack root;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct config_parser_context ctx;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int i, count;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *key, *value;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter string_t *full_line;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter enum config_line_type type;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter char *line;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int fd, ret = 0;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter bool handled;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fd = open(path, O_RDONLY);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (fd < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *error_r = t_strdup_printf("open(%s) failed: %m", path);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter memset(&ctx, 0, sizeof(ctx));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.pool = pool_alloconly_create("config file parser", 1024*256);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.path = path;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (count = 0; all_roots[count] != NULL; count++) ;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.root_parsers =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p_new(ctx.pool, struct config_module_parser, count+1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (i = 0; i < count; i++) {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter ctx.root_parsers[i].root = all_roots[i];
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter ctx.root_parsers[i].parser =
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter settings_parser_init(ctx.pool, all_roots[i],
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter settings_parser_flags);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter memset(&root, 0, sizeof(root));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter root.path = path;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.cur_input = &root;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.expand_values = expand_values;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.module = module;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter p_array_init(&ctx.all_parsers, ctx.pool, 128);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.cur_section = p_new(ctx.pool, struct config_section_stack, 1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter config_add_new_parser(&ctx);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.str = str_new(ctx.pool, 256);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter full_line = str_new(default_pool, 512);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter old_settings_init(&ctx);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (hook_config_parser_begin != NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter hook_config_parser_begin(&ctx);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterprevfile:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.cur_input->linenum++;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter type = config_parse_line(&ctx, line, full_line,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter &key, &value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter str_truncate(ctx.str, ctx.pathlen);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter T_BEGIN {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter handled = old_settings_handle(&ctx, type, key, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!handled)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter config_parser_apply_line(&ctx, type, key, value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } T_END;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (ctx.error != NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter *error_r = t_strdup_printf(
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "Error in configuration file %s line %d: %s",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.cur_input->path, ctx.cur_input->linenum,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ctx.error);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = -2;
break;
}
str_truncate(full_line, 0);
}
i_stream_destroy(&ctx.cur_input->input);
ctx.cur_input = ctx.cur_input->prev;
if (line == NULL && ctx.cur_input != NULL)
goto prevfile;
str_free(&full_line);
if (ret == 0)
ret = config_parse_finish(&ctx, error_r);
return ret < 0 ? ret : 1;
}
void config_parse_load_modules(void)
{
struct module_dir_load_settings mod_set;
struct module *m;
const struct setting_parser_info **roots;
ARRAY_DEFINE(new_roots, const struct setting_parser_info *);
ARRAY_TYPE(service_settings) new_services;
struct service_settings *const *services, *service_set;
unsigned int i, count;
memset(&mod_set, 0, sizeof(mod_set));
mod_set.version = master_service_get_version_string(master_service);
modules = module_dir_load(CONFIG_MODULE_DIR, NULL, &mod_set);
module_dir_init(modules);
i_array_init(&new_roots, 64);
i_array_init(&new_services, 64);
for (m = modules; m != NULL; m = m->next) {
roots = module_get_symbol_quiet(m,
t_strdup_printf("%s_set_roots", m->name));
if (roots != NULL) {
for (i = 0; roots[i] != NULL; i++)
array_append(&new_roots, &roots[i], 1);
}
service_set = module_get_symbol_quiet(m,
t_strdup_printf("%s_service_settings", m->name));
if (service_set != NULL)
array_append(&new_services, &service_set, 1);
}
if (array_count(&new_roots) > 0) {
/* modules added new settings. add the defaults and start
using the new list. */
for (i = 0; all_roots[i] != NULL; i++)
array_append(&new_roots, &all_roots[i], 1);
(void)array_append_space(&new_roots);
all_roots = array_idx(&new_roots, 0);
}
if (array_count(&new_services) > 0) {
/* module added new services. update the defaults. */
services = array_get(default_services, &count);
for (i = 0; i < count; i++)
array_append(&new_services, &services[i], 1);
*default_services = new_services;
}
}
static bool parsers_are_connected(const struct setting_parser_info *root,
const struct setting_parser_info *info)
{
const struct setting_parser_info *p;
const struct setting_parser_info *const *dep;
/* we're trying to find info or its parents from root's dependencies. */
for (p = info; p != NULL; p = p->parent) {
if (p == root)
return TRUE;
}
if (root->dependencies != NULL) {
for (dep = root->dependencies; *dep != NULL; dep++) {
if (parsers_are_connected(*dep, info))
return TRUE;
}
}
return FALSE;
}
bool config_module_want_parser(struct config_module_parser *parsers,
const char *module,
const struct setting_parser_info *root)
{
struct config_module_parser *l;
if (strcmp(root->module_name, module) == 0)
return TRUE;
if (root == &master_service_setting_parser_info) {
/* everyone wants master service settings */
return TRUE;
}
for (l = parsers; l->root != NULL; l++) {
if (strcmp(l->root->module_name, module) != 0)
continue;
/* see if we can find a way to get from the original parser
to this parser */
if (parsers_are_connected(l->root, root))
return TRUE;
}
return FALSE;
}