config-parser.c revision 3872c943f81f4440d54f2ac4657d3dfd31978600
a11689fe3fbb3bca11b9cb4ae5faf27db96401ccTimo Sirainen/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "array.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "str.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "hash.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "strescape.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "istream.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "settings-parser.h"
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen#include "all-settings.h"
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen#include "config-filter.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "config-parser.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <unistd.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <fcntl.h>
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#ifdef HAVE_GLOB_H
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen# include <glob.h>
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#endif
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen#ifndef GLOB_BRACE
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen# define GLOB_BRACE 0
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen#endif
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstruct config_section_stack {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_section_stack *prev;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen struct config_filter filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen /* module_name=NULL-terminated list of parsers */
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_module_parser *parsers;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen unsigned int pathlen;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen};
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
d595049948579def2d82718dbce0a6b49a281402Timo Sirainenstruct input_stack {
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen struct input_stack *prev;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen struct istream *input;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen const char *path;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen unsigned int linenum;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen};
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainenstruct parser_context {
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen pool_t pool;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen const char *path;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ARRAY_DEFINE(all_parsers, struct config_filter_parser *);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen struct config_module_parser *root_parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_section_stack *cur_section;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen struct input_stack *cur_input;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen struct config_filter_context *filter;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen};
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic const enum settings_parser_flags settings_parser_flags =
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS |
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen SETTINGS_PARSER_FLAG_TRACK_CHANGES;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainenstruct config_module_parser *config_module_parsers;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainenstruct config_filter_context *config_filter;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainenstatic const char *info_type_name_find(const struct setting_parser_info *info)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen{
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen unsigned int i;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen for (i = 0; info->defines[i].key != NULL; i++) {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (info->defines[i].offset == info->type_offset)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return info->defines[i].key;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen }
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen i_panic("setting parser: Invalid type_offset value");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return NULL;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen}
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainenstatic void config_add_type(struct setting_parser_context *parser,
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen const char *line, const char *section_name)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen{
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen const struct setting_parser_info *info;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen const char *p;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen string_t *str;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen int ret;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen info = settings_parse_get_prev_info(parser);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (info->type_offset == (size_t)-1)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str = t_str_new(256);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen p = strchr(line, '=');
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append_n(str, line, p-line);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append(str, p+1);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append(str, info_type_name_find(info));
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append_c(str, '=');
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen str_append(str, section_name);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen ret = settings_parse_line(parser, str_c(str));
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen i_assert(ret > 0);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen}
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenstatic int
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_apply_line(struct parser_context *ctx, const char *key,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char *line, const char *section_name,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char **error_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen struct config_module_parser *l;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool found = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen int ret;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen for (l = ctx->cur_section->parsers; l->module_name != NULL; l++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = settings_parse_line(l->parser, line);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret > 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen found = TRUE;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (section_name != NULL)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen config_add_type(l->parser, line, section_name);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen } else if (ret < 0) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *error_r = settings_parser_get_error(l->parser);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return -1;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (!found) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *error_r = t_strconcat("Unknown setting: ", key, NULL);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return -1;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *error_r = NULL;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return 0;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainenstatic const char *
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainenfix_relative_path(const char *path, struct input_stack *input)
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen{
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen const char *p;
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen if (*path == '/')
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen return path;
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen p = strrchr(input->path, '/');
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen if (p == NULL)
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen return path;
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen}
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainenstatic struct config_module_parser *
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_module_parsers_init(pool_t pool)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen struct config_module_parser *dest;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen unsigned int i, count;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen for (count = 0; all_roots[count].module_name != NULL; count++) ;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen dest = p_new(pool, struct config_module_parser, count + 1);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen for (i = 0; i < count; i++) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen dest[i].module_name = all_roots[i].module_name;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen dest[i].root = all_roots[i].root;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen dest[i].parser = settings_parser_init(pool, all_roots[i].root,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen settings_parser_flags);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen }
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen return dest;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic void
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainenconfig_add_new_parser(struct parser_context *ctx)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_section_stack *cur_section = ctx->cur_section;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_parser *parser;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen parser = p_new(ctx->pool, struct config_filter_parser, 1);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen parser->filter = cur_section->filter;
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen parser->file_and_line =
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen p_strdup_printf(ctx->pool, "%s:%d",
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen ctx->cur_input->path, ctx->cur_input->linenum);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen parser->parsers = cur_section->prev == NULL ? ctx->root_parsers :
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_module_parsers_init(ctx->pool);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen array_append(&ctx->all_parsers, &parser, 1);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen cur_section->parsers = parser->parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic struct config_section_stack *
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_add_new_section(struct parser_context *ctx)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_section_stack *section;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen section = p_new(ctx->pool, struct config_section_stack, 1);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen section->prev = ctx->cur_section;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen section->filter = ctx->cur_section->filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen section->parsers = ctx->cur_section->parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return section;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic struct config_filter_parser *
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_filter_parser_find(struct parser_context *ctx,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const struct config_filter *filter)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_parser *const *parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen unsigned int i, count;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen parsers = array_get(&ctx->all_parsers, &count);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen for (i = 0; i < count; i++) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_filters_equal(&parsers[i]->filter, filter))
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return parsers[i];
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen }
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return NULL;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainenstatic bool
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_filter_add_new_filter(struct parser_context *ctx,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen const char *key, const char *value,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen const char **error_r)
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter *filter = &ctx->cur_section->filter;
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen struct config_filter *parent = &ctx->cur_section->prev->filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_parser *parser;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen if (strcmp(key, "protocol") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->service != NULL)
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "protocol must not be under protocol";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen filter->service = p_strdup(ctx->pool, value);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen } else if (strcmp(key, "local_ip") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->remote_bits > 0)
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "local_ip must not be under remote_ip";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (parent->service != NULL)
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "local_ip must not be under protocol";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (net_parse_range(value, &filter->local_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen &filter->local_bits) < 0)
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen *error_r = "Invalid network mask";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (parent->local_bits > filter->local_bits ||
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen (parent->local_bits > 0 &&
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen !net_is_in_network(&filter->local_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen &parent->local_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen parent->local_bits)))
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "local_ip not a subset of parent local_ip";
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen } else if (strcmp(key, "remote_ip") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->service != NULL)
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "remote_ip must not be under protocol";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (net_parse_range(value, &filter->remote_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen &filter->remote_bits) < 0)
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen *error_r = "Invalid network mask";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (parent->remote_bits > filter->remote_bits ||
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen (parent->remote_bits > 0 &&
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen !net_is_in_network(&filter->remote_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen &parent->remote_net,
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen parent->remote_bits)))
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen *error_r = "remote_ip not a subset of parent remote_ip";
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen } else {
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen return FALSE;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen }
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen parser = config_filter_parser_find(ctx, filter);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (parser != NULL)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ctx->cur_section->parsers = parser->parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen else
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_add_new_parser(ctx);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen return TRUE;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen}
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainenstatic int
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_filter_parser_check(struct parser_context *ctx,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const struct config_module_parser *p,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char **error_r)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen for (; p->module_name != NULL; p++) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (!settings_parser_check(p->parser, ctx->pool, error_r))
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen return -1;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen }
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen return 0;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainenstatic int
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenconfig_all_parsers_check(struct parser_context *ctx,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_context *new_filter,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char **error_r)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_parser *const *parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const struct config_module_parser *tmp_parsers;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen unsigned int i, count;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen pool_t tmp_pool;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
3872c943f81f4440d54f2ac4657d3dfd31978600Timo Sirainen tmp_pool = pool_alloconly_create("config parsers check", 1024*32);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen parsers = array_get(&ctx->all_parsers, &count);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen i_assert(count > 0 && parsers[count-1] == NULL);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen count--;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen for (i = 0; i < count; i++) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen p_clear(tmp_pool);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_filter_get_parsers(new_filter, tmp_pool,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen &parsers[i]->filter,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen &tmp_parsers, error_r) < 0)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen break;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_filter_parser_check(ctx, tmp_parsers, error_r) < 0)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen break;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen }
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return i == count ? 0 : -1;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenstatic int
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainenstr_append_file(string_t *str, const char *key, const char *path,
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen const char **error_r)
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen{
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen unsigned char buf[1024];
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen int fd;
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen ssize_t ret;
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen fd = open(path, O_RDONLY);
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen if (fd == -1) {
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen *error_r = t_strdup_printf("%s: Can't open file %s: %m",
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen key, path);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return -1;
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen }
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen while ((ret = read(fd, buf, sizeof(buf))) > 0)
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen str_append_n(str, buf, ret);
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen if (ret < 0) {
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen *error_r = t_strdup_printf("%s: read(%s) failed: %m",
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen key, path);
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen }
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen (void)close(fd);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return ret < 0 ? -1 : 0;
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen}
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainenstatic int settings_add_include(struct parser_context *ctx, const char *path,
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen bool ignore_errors, const char **error_r)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen{
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen struct input_stack *tmp, *new_input;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen int fd;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen for (tmp = ctx->cur_input; tmp != NULL; tmp = tmp->prev) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (strcmp(tmp->path, path) == 0)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen break;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (tmp != NULL) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = t_strdup_printf("Recursive include file: %s", path);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if ((fd = open(path, O_RDONLY)) == -1) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (ignore_errors)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = t_strdup_printf("Couldn't open include file %s: %m",
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen path);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen new_input = t_new(struct input_stack, 1);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen new_input->prev = ctx->cur_input;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen new_input->path = t_strdup(path);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen new_input->input = i_stream_create_fd(fd, 2048, TRUE);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen i_stream_set_return_partial_line(new_input->input, TRUE);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen ctx->cur_input = new_input;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen}
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainenstatic int
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainensettings_include(struct parser_context *ctx, const char *pattern,
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen bool ignore_errors, const char **error_r)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen{
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#ifdef HAVE_GLOB
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen glob_t globbers;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen unsigned int i;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case 0:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen break;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case GLOB_NOSPACE:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = "glob() failed: Not enough memory";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case GLOB_ABORTED:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = "glob() failed: Read error";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case GLOB_NOMATCH:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (ignore_errors)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = "No matches";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen default:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen *error_r = "glob() failed: Unknown error";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen /* iterate throuth the different files matching the globbing */
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen for (i = 0; i < globbers.gl_pathc; i++) {
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (settings_add_include(ctx, globbers.gl_pathv[i],
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen ignore_errors, error_r) < 0)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen globfree(&globbers);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#else
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return settings_add_include(ctx, pattern, ignore_errors, error_r);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#endif
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen}
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenenum config_line_type {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_SKIP,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_ERROR,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_KEYVALUE,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_SECTION_BEGIN,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_SECTION_END,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_INCLUDE,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen CONFIG_LINE_TYPE_INCLUDE_TRY
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen};
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenstatic enum config_line_type
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenconfig_parse_line(char *line, string_t *full_line, const char **key_r,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen const char **value_r)
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen{
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen const char *key;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen unsigned int len;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen char *p;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *key_r = NULL;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *value_r = NULL;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* @UNSAFE: line is modified */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* skip whitespace */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (IS_WHITE(*line))
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* ignore comments or empty lines */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line == '#' || *line == '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_SKIP;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* strip away comments. pretty kludgy way really.. */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen for (p = line; *p != '\0'; p++) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*p == '\'' || *p == '"') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen char quote = *p;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen for (p++; *p != quote && *p != '\0'; p++) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*p == '\\' && p[1] != '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen p++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*p == '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen } else if (*p == '#') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *p = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* remove whitespace from end of line */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen len = strlen(line);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (IS_WHITE(line[len-1]))
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen len--;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line[len] = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (len > 0 && line[len-1] == '\\') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* continues in next line */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line[len-1] = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen str_append(full_line, line);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_SKIP;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (str_len(full_line) > 0) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen str_append(full_line, line);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line = str_c_modifiable(full_line);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* a) key = value
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen b) section_type [section_name] {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen c) } */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen key = line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (IS_WHITE(*line)) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *line++ = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (IS_WHITE(*line)) line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *key_r = key;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *value_r = line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (strcmp(key, "!include") == 0)
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_INCLUDE;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (strcmp(key, "!include_try") == 0)
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_INCLUDE_TRY;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line == '=') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* a) */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *line++ = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (IS_WHITE(*line)) line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen len = strlen(line);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (len > 0 &&
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen ((*line == '"' && line[len-1] == '"') ||
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen (*line == '\'' && line[len-1] == '\''))) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line[len-1] = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line = str_unescape(line+1);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *value_r = line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_KEYVALUE;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (strcmp(key, "}") == 0 && *line == '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_SECTION_END;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* b) + errors */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line[-1] = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line == '{')
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen *value_r = "";
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen else {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* get section name */
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen *value_r = line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (!IS_WHITE(*line) && *line != '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line != '\0') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *line++ = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen while (IS_WHITE(*line))
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line != '{') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen *value_r = "Expecting '='";
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_ERROR;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen if (line[1] != '\0') {
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen *value_r = "Garbage after '{'";
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen return CONFIG_LINE_TYPE_ERROR;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_SECTION_BEGIN;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen}
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic int config_parse_finish(struct parser_context *ctx, const char **error_r)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_context *new_filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char *error;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen new_filter = config_filter_init(ctx->pool);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen (void)array_append_space(&ctx->all_parsers);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_filter_add_all(new_filter, array_idx(&ctx->all_parsers, 0));
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_all_parsers_check(ctx, new_filter, &error) < 0) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen *error_r = t_strdup_printf("Error in configuration file %s: %s",
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ctx->path, error);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return -1;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen }
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_filter != NULL)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_filter_deinit(&config_filter);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_module_parsers = ctx->root_parsers;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_filter = new_filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return 0;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen}
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainenint config_parse_file(const char *path, bool expand_files,
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen const char **error_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen struct input_stack root;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen struct parser_context ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int pathlen = 0;
2024157e8de36edd31f5fd72f5ea7364a0955fa7Timo Sirainen unsigned int i, count, counter = 0, cur_counter;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen const char *errormsg, *key, *value;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen string_t *str, *full_line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen enum config_line_type type;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen char *line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen int fd, ret = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen fd = open(path, O_RDONLY);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen if (fd < 0) {
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen *error_r = t_strdup_printf("open(%s) failed: %m", path);
863f2bc9983c33221f5936421fc9c06caf21639aTimo Sirainen return 0;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen }
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen memset(&ctx, 0, sizeof(ctx));
ebded144e74a668973ec9ba6e7e169d4e6dc766cTimo Sirainen ctx.pool = pool_alloconly_create("config file parser", 1024*64);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.path = path;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen for (count = 0; all_roots[count].module_name != NULL; count++) ;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ctx.root_parsers =
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen p_new(ctx.pool, struct config_module_parser, count+1);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen for (i = 0; i < count; i++) {
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ctx.root_parsers[i].module_name = all_roots[i].module_name;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ctx.root_parsers[i].root = all_roots[i].root;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ctx.root_parsers[i].parser =
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen settings_parser_init(ctx.pool, all_roots[i].root,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen settings_parser_flags);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen }
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen memset(&root, 0, sizeof(root));
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen root.path = path;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input = &root;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen p_array_init(&ctx.all_parsers, ctx.pool, 128);
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen ctx.cur_section = p_new(ctx.pool, struct config_section_stack, 1);
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen config_add_new_parser(&ctx);
13be7f7215efe02d020e9d823772861df98b82bdTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str = t_str_new(256);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen full_line = t_str_new(512);
9e1211fd8b7a12b1a4e4c2b7714164e504f127d0Timo Sirainen errormsg = NULL;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input->input = i_stream_create_fd(fd, (size_t)-1, TRUE);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
d595049948579def2d82718dbce0a6b49a281402Timo Sirainenprevfile:
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input->linenum++;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen type = config_parse_line(line, full_line,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen &key, &value);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen switch (type) {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_SKIP:
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_ERROR:
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen errormsg = value;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_KEYVALUE:
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_truncate(str, pathlen);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_append(str, key);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_append_c(str, '=');
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*value != '<' || !expand_files)
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen str_append(str, value);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen else if (str_append_file(str, key, value+1, &errormsg) < 0) {
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen /* file reading failed */
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen (void)config_apply_line(&ctx, key, str_c(str), NULL, &errormsg);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_SECTION_BEGIN:
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ctx.cur_section = config_add_new_section(&ctx);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ctx.cur_section->pathlen = pathlen;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (config_filter_add_new_filter(&ctx, key, value,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen &errormsg)) {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen /* new filter */
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen /* new config section */
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_truncate(str, pathlen);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_append(str, key);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen pathlen = str_len(str);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen cur_counter = counter++;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_append_c(str, '=');
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_printfa(str, "%u", cur_counter);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen if (config_apply_line(&ctx, key, str_c(str), value, &errormsg) < 0)
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen break;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_truncate(str, pathlen);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_printfa(str, "%u", cur_counter);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen pathlen = str_len(str);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_SECTION_END:
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (ctx.cur_section->prev == NULL)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen errormsg = "Unexpected '}'";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else {
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen pathlen = ctx.cur_section->pathlen;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ctx.cur_section = ctx.cur_section->prev;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_INCLUDE:
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen case CONFIG_LINE_TYPE_INCLUDE_TRY:
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen (void)settings_include(&ctx, fix_relative_path(value, ctx.cur_input),
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen type == CONFIG_LINE_TYPE_INCLUDE_TRY,
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen &errormsg);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (errormsg != NULL) {
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen *error_r = t_strdup_printf(
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen "Error in configuration file %s line %d: %s",
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input->path, ctx.cur_input->linenum,
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen errormsg);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ret = -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_truncate(full_line, 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen i_stream_destroy(&ctx.cur_input->input);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input = ctx.cur_input->prev;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen if (line == NULL && ctx.cur_input != NULL)
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen goto prevfile;
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (ret == 0)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ret = config_parse_finish(&ctx, error_r);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen if (ret < 0) {
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen pool_unref(&ctx.pool);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen return -1;
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen }
863f2bc9983c33221f5936421fc9c06caf21639aTimo Sirainen return 1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}