config-parser.c revision ebded144e74a668973ec9ba6e7e169d4e6dc766c
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "lib.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "array.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "str.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "hash.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "strescape.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "istream.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "settings-parser.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "config-filter.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include "config-parser.h"
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include <unistd.h>
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#include <fcntl.h>
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistruct config_filter_stack {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_stack *prev;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi struct config_filter filter;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi unsigned int pathlen;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi};
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomistruct input_stack {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi struct input_stack *prev;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi struct istream *input;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int linenum;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi};
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomistruct parser_context {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi pool_t pool;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* parsers matching cur_filter */
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi ARRAY_TYPE(config_setting_parsers) cur_parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_stack *cur_filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct input_stack *cur_input;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_context *filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi};
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistruct config_filter_context *config_filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *info_type_name_find(const struct setting_parser_info *info)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; info->defines[i].key != NULL; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (info->defines[i].offset == info->type_offset)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return info->defines[i].key;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_panic("setting parser: Invalid type_offset value");
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return NULL;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void config_add_type(struct setting_parser_context *parser,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *line, const char *section_name)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const struct setting_parser_info *info;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi string_t *str;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi int ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi info = settings_parse_get_prev_info(parser);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (info->type_offset == (size_t)-1)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str = t_str_new(256);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p = strchr(line, '=');
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_n(str, line, p-line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_c(str, SETTINGS_SEPARATOR);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, p+1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_c(str, SETTINGS_SEPARATOR);
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi str_append(str, info_type_name_find(info));
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi str_append_c(str, '=');
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, section_name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ret = settings_parse_line(parser, str_c(str));
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(ret > 0);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_parsers_parse_line(struct config_setting_parser_list *parsers,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *key, const char *line,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *section_name)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *l;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi bool found = FALSE;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi int ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (l = parsers; l->module_name != NULL; l++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ret = settings_parse_line(l->parser, line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (ret > 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi found = TRUE;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (section_name != NULL)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_add_type(l->parser, line, section_name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (ret < 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return settings_parser_get_error(l->parser);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return found ? NULL : t_strconcat("Unknown setting: ", key, NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_parse_line(struct config_setting_parser_list *const *all_parsers,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *key, const char *line, const char *section_name)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (; *all_parsers != NULL; all_parsers++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ret = config_parsers_parse_line(*all_parsers, key, line,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi section_name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (ret != NULL)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return NULL;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic const char *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomifix_relative_path(const char *path, struct input_stack *input)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*path == '/')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p = strrchr(input->path, '/');
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (p == NULL)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic struct config_setting_parser_list *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_setting_parser_list_dup(pool_t pool,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const struct config_setting_parser_list *src)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *dest;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (count = 0; src[count].module_name != NULL; count++) ;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi dest = p_new(pool, struct config_setting_parser_list, count + 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi dest[i] = src[i];
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi dest[i].parser = settings_parser_dup(src[i].parser, pool);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return dest;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic struct config_filter_parser_list *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_add_new_parser(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_parser_list *parser;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *const *cur_parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parser = p_new(ctx->pool, struct config_filter_parser_list, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parser->filter = ctx->cur_filter->filter;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi cur_parsers = array_get(&ctx->cur_parsers, &count);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi if (count == 0) {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi /* first one */
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi parser->parser_list = config_setting_parsers;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* duplicate the first settings list */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parser->parser_list =
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_setting_parser_list_dup(ctx->pool,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi cur_parsers[0]);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi array_append(&ctx->all_parsers, &parser, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return parser;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void config_add_new_filter(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_stack *filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi filter = p_new(ctx->pool, struct config_filter_stack, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi filter->prev = ctx->cur_filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi filter->filter = ctx->cur_filter->filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx->cur_filter = filter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic struct config_setting_parser_list *const *
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_update_cur_parsers(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_parser_list *const *all_parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi bool full_found = FALSE;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi array_clear(&ctx->cur_parsers);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi all_parsers = array_get(&ctx->all_parsers, &count);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (!config_filter_match(&ctx->cur_filter->filter,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &all_parsers[i]->filter))
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi continue;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (config_filters_equal(&all_parsers[i]->filter,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &ctx->cur_filter->filter)) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi array_insert(&ctx->cur_parsers, 0,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &all_parsers[i]->parser_list, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi full_found = TRUE;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi array_append(&ctx->cur_parsers,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &all_parsers[i]->parser_list, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(full_found);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi (void)array_append_space(&ctx->cur_parsers);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return array_idx(&ctx->cur_parsers, 0);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_filter_parser_list_check(struct parser_context *ctx,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_parser_list *parser)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *l = parser->parser_list;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *errormsg;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (; l->module_name != NULL; l++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (!settings_parser_check(l->parser, ctx->pool, &errormsg)) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_fatal("Error in configuration file %s: %s",
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx->path, errormsg);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiconfig_all_parsers_check(struct parser_context *ctx)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_filter_parser_list *const *parsers;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int i, count;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parsers = array_get(&ctx->all_parsers, &count);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_filter_parser_list_check(ctx, parsers[i]);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistatic void
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomistr_append_file(string_t *str, const char *key, const char *path,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char **error_r)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned char buf[1024];
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi int fd;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ssize_t ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi fd = open(path, O_RDONLY);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (fd == -1) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *error_r = t_strdup_printf("%s: Can't open file %s: %m",
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi key, path);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi return;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while ((ret = read(fd, buf, sizeof(buf))) > 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_n(str, buf, ret);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (ret < 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *error_r = t_strdup_printf("%s: read(%s) failed: %m",
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi key, path);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi (void)close(fd);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi}
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomivoid config_parse_file(const char *path, bool expand_files)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi{
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi enum settings_parser_flags parser_flags =
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct input_stack root, *new_input;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ARRAY_TYPE(const_string) auth_defaults;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct config_setting_parser_list *l, *const *parsers;
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi struct parser_context ctx;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int pathlen = 0;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi unsigned int counter = 0, auth_counter = 0, cur_counter;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *errormsg, *name;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi char *line, *key, *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi int fd, ret;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi string_t *str, *full_line;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi size_t len;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi memset(&ctx, 0, sizeof(ctx));
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.pool = pool_alloconly_create("config file parser", 1024*64);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.path = path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi fd = open(path, O_RDONLY);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (fd < 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_fatal("open(%s) failed: %m", path);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi t_array_init(&auth_defaults, 32);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (l = config_setting_parsers; l->module_name != NULL; l++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(l->parser == NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi l->parser = settings_parser_init(ctx.pool, l->root, parser_flags);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi t_array_init(&ctx.cur_parsers, 128);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p_array_init(&ctx.all_parsers, ctx.pool, 128);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_filter = p_new(ctx.pool, struct config_filter_stack, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_add_new_parser(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parsers = config_update_cur_parsers(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, "0", "auth=0", NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(errormsg == NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, "name", "auth/0/name=default", NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(errormsg == NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi memset(&root, 0, sizeof(root));
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi root.path = path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_input = &root;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str = t_str_new(256);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi full_line = t_str_new(512);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = NULL;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuominewfile:
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomiprevfile:
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_input->linenum++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* @UNSAFE: line is modified */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* skip whitespace */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (IS_WHITE(*line))
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* ignore comments or empty lines */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line == '#' || *line == '\0')
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi continue;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* strip away comments. pretty kludgy way really.. */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (p = line; *p != '\0'; p++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*p == '\'' || *p == '"') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi char quote = *p;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (p++; *p != quote && *p != '\0'; p++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*p == '\\' && p[1] != '\0')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*p == '\0')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi break;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (*p == '#') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *p = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi break;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* remove whitespace from end of line */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi len = strlen(line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (IS_WHITE(line[len-1]))
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi len--;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line[len] = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (len > 0 && line[len-1] == '\\') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* continues in next line */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line[len-1] = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(full_line, line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi continue;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (str_len(full_line) > 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(full_line, line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line = str_c_modifiable(full_line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi /* a) key = value
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi b) section_type [section_name] {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi c) } */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi key = line;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (IS_WHITE(*line)) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *line++ = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (IS_WHITE(*line)) line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ret = 1;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "!include_try") == 0 ||
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi strcmp(key, "!include") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi struct input_stack *tmp;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *path;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi path = fix_relative_path(line, ctx.cur_input);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (tmp = ctx.cur_input; tmp != NULL; tmp = tmp->prev) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(tmp->path, path) == 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi break;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (tmp != NULL) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = "Recursive include";
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if ((fd = open(path, O_RDONLY)) != -1) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi new_input = t_new(struct input_stack, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi new_input->prev = ctx.cur_input;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi new_input->path = t_strdup(path);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_input = new_input;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi goto newfile;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* failed, but ignore failures with include_try. */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "!include") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = t_strdup_printf(
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi "Couldn't open include file %s: %m", line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (*line == '=') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* a) */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *line++ = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (IS_WHITE(*line)) line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi len = strlen(line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (len > 0 &&
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ((*line == '"' && line[len-1] == '"') ||
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi (*line == '\'' && line[len-1] == '\''))) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line[len-1] = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line = str_unescape(line+1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_truncate(str, pathlen);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, key);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_c(str, '=');
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line != '<' || !expand_files)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi else
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_file(str, key, line+1, &errormsg);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (errormsg != NULL) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* file reading failed */
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi } else if (pathlen == 0 &&
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi strncmp(str_c(str), "auth_", 5) == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* verify that the setting is valid,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi but delay actually adding it */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi const char *s = t_strdup(str_c(str) + 5);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_truncate(str, 0);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_printfa(str, "auth/0/%s=", key + 5);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line != '<' || !expand_files)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, line);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi else
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_file(str, key, line+1, &errormsg);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key + 5, str_c(str), NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi array_append(&auth_defaults, &s, 1);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key, str_c(str), NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (strcmp(key, "}") != 0 || *line != '\0') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* b) + errors */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line[-1] = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line == '{')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi name = "";
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi name = line;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (!IS_WHITE(*line) && *line != '\0')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line != '\0') {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi *line++ = '\0';
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi while (IS_WHITE(*line))
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi line++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (*line != '{')
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = "Expecting '='";
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_add_new_filter(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_filter->pathlen = pathlen;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "protocol") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi ctx.cur_filter->filter.service =
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p_strdup(ctx.pool, name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_add_new_parser(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi parsers = config_update_cur_parsers(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (strcmp(key, "local_ip") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (net_parse_range(name, &ctx.cur_filter->filter.local_net,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &ctx.cur_filter->filter.local_bits) < 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = "Invalid network mask";
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi config_add_new_parser(&ctx);
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi parsers = config_update_cur_parsers(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else if (strcmp(key, "remote_ip") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (net_parse_range(name, &ctx.cur_filter->filter.remote_net,
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi &ctx.cur_filter->filter.remote_bits) < 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = "Invalid network mask";
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi config_add_new_parser(&ctx);
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi parsers = config_update_cur_parsers(&ctx);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_truncate(str, pathlen);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, key);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi pathlen = str_len(str);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "auth") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi cur_counter = auth_counter++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (cur_counter == 0 && strcmp(name, "default") != 0)
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi cur_counter = auth_counter++;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi cur_counter = counter++;
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi str_append_c(str, '=');
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi str_printfa(str, "%u", cur_counter);
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi
03c6532fe7aa3ddae23c99ff6bec78d8dd2e8165Aki Tuomi if (cur_counter == 0 && strcmp(key, "auth") == 0) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi /* already added this */
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi } else {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, key, str_c(str), name);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_truncate(str, pathlen);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_c(str, SETTINGS_SEPARATOR);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_printfa(str, "%u", cur_counter);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append_c(str, SETTINGS_SEPARATOR);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi pathlen = str_len(str);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi if (strcmp(key, "auth") == 0 && errormsg == NULL) {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi /* add auth default settings */
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi const char *const *lines;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi unsigned int i, count;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi lines = array_get(&auth_defaults, &count);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi for (i = 0; i < count; i++) {
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_truncate(str, pathlen);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi p = strchr(lines[i], '=');
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi str_append(str, lines[i]);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi errormsg = config_parse_line(parsers, t_strdup_until(lines[i], p), str_c(str), NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi i_assert(errormsg == NULL);
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi } else {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi /* c) */
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi if (ctx.cur_filter->prev == NULL)
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi errormsg = "Unexpected '}'";
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi else {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi pathlen = ctx.cur_filter->pathlen;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi ctx.cur_filter = ctx.cur_filter->prev;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi parsers = config_update_cur_parsers(&ctx);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi if (errormsg != NULL) {
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi i_fatal("Error in configuration file %s line %d: %s",
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi ctx.cur_input->path, ctx.cur_input->linenum,
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi errormsg);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi break;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi str_truncate(full_line, 0);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi }
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi i_stream_destroy(&ctx.cur_input->input);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi ctx.cur_input = ctx.cur_input->prev;
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi if (line == NULL && ctx.cur_input != NULL)
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi goto prevfile;
4036c1ca99d2c517f68a5b67a419ae7fdfd45300Aki Tuomi
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi config_all_parsers_check(&ctx);
004be038dfe290f71e3d4a4b14d88673e8b55fb2Timo Sirainen
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi (void)array_append_space(&ctx.all_parsers);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi config_filter = config_filter_init(ctx.pool);
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi config_filter_add_all(config_filter, array_idx(&ctx.all_parsers, 0));
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi}
98bc2ecdbfd4f2f20c3a5e96ae445072fbe22223Aki Tuomi