bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 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"
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen#include "module-dir.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "settings-parser.h"
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen#include "service-settings.h"
01afde78e4ff6b4c75f75257a7972eca37114383Timo Sirainen#include "master-service.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "master-service-settings.h"
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen#include "master-service-ssl-settings.h"
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen#include "all-settings.h"
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen#include "old-set-parser.h"
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen#include "config-request.h"
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen#include "config-parser-private.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <unistd.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <fcntl.h>
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen#include <time.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
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen#define DNS_LOOKUP_TIMEOUT_SECS 30
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen#define DNS_LOOKUP_WARN_SECS 5
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo SirainenARRAY_DEFINE_TYPE(setting_parser_info_p, const struct setting_parser_info *);
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo 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;
73b8333f9a979efefe1db70f22c63edec5ad4466Timo Sirainenstruct module *modules;
0171540a6764f714b8b753ba209ec9a83c213d25Timo Sirainenvoid (*hook_config_parser_begin)(struct config_parser_context *ctx);
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainenint (*hook_config_parser_end)(struct config_parser_context *ctx,
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen const char **error_r);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainenstatic ARRAY_TYPE(service_settings) services_free_at_deinit = ARRAY_INIT;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainenstatic ARRAY_TYPE(setting_parser_info_p) roots_free_at_deinit = ARRAY_INIT;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo 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
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainenstatic int config_add_type(struct setting_parser_context *parser,
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo 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);
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen if (info == NULL) {
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen /* section inside strlist */
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen return -1;
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen }
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (info->type_offset == (size_t)-1)
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen return 0;
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);
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen if (info != NULL) {
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen str_append_c(str, SETTINGS_SEPARATOR);
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen str_append(str, info_type_name_find(info));
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen }
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
096e109f9f332bc758ca5e22ec64337379c5f231Timo Sirainen ret = settings_parse_keyvalue(parser, str_c(str), section_name);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen i_assert(ret > 0);
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen return 0;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen}
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainenstatic bool
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainenconfig_parser_is_in_localremote(struct config_section_stack *section)
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen{
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen const struct config_filter *filter = &section->filter;
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen return filter->local_name != NULL || filter->local_bits > 0 ||
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen filter->remote_bits > 0;
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen}
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainenstatic void
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainensection_stack_write(string_t *str, struct config_section_stack *section)
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen{
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen if (section == NULL)
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen return;
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen section_stack_write(str, section->prev);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen if (!section->is_filter && section->key != NULL)
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen str_printfa(str, "%s { ", section->key);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen}
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainenstatic const char *
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainenget_setting_full_path(struct config_parser_context *ctx, const char *key)
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen{
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen string_t *str = t_str_new(128);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen section_stack_write(str, ctx->cur_section);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen str_append(str, key);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen return str_c(str);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen}
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenint config_apply_line(struct config_parser_context *ctx, const char *key,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *line, const char *section_name)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen struct config_module_parser *l;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool found = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen int ret;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen for (l = ctx->cur_section->parsers; l->root != NULL; l++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = settings_parse_line(l->parser, line);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret > 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen found = TRUE;
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen /* FIXME: remove once auth does support these. */
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen if (strcmp(l->root->module_name, "auth") == 0 &&
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen config_parser_is_in_localremote(ctx->cur_section)) {
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen ctx->error = p_strconcat(ctx->pool,
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen "Auth settings not supported inside local/remote blocks: ",
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen key, NULL);
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen return -1;
33ef806e0d378a0b2326cd939714c9070502d1e5Timo Sirainen }
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen if (section_name != NULL) {
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen if (config_add_type(l->parser, line, section_name) < 0) {
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen ctx->error = "Section not allowed here";
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen return -1;
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen }
36175032e12e7dfe67f92ee7c2065fdc6865aefdTimo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen } else if (ret < 0) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = settings_parser_get_error(l->parser);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return -1;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (!found) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strconcat(ctx->pool, "Unknown setting: ",
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen get_setting_full_path(ctx, key), NULL);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return -1;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
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
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen for (count = 0; all_roots[count] != NULL; count++) ;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen dest = p_new(pool, struct config_module_parser, count + 1);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen for (i = 0; i < count; i++) {
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen dest[i].root = all_roots[i];
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen dest[i].parser = settings_parser_init(pool, all_roots[i],
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen settings_parser_flags);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen }
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen return dest;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic void
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_add_new_parser(struct config_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;
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen if (ctx->cur_input->linenum == 0) {
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen parser->file_and_line =
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen p_strdup(ctx->pool, ctx->cur_input->path);
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen } else {
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen parser->file_and_line =
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen p_strdup_printf(ctx->pool, "%s:%d",
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen ctx->cur_input->path,
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen ctx->cur_input->linenum);
04ce187ba9c7c98b4f3fbaa833a2dc929e4281b8Timo Sirainen }
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 *
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_add_new_section(struct config_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;
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen section->open_path = p_strdup(ctx->pool, ctx->cur_input->path);
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen section->open_linenum = ctx->cur_input->linenum;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return section;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstatic struct config_filter_parser *
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_filter_parser_find(struct config_parser_context *ctx,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const struct config_filter *filter)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_parser *const *parsers;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(&ctx->all_parsers, parsers) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen struct config_filter_parser *parser = *parsers;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (config_filters_equal(&parser->filter, filter))
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen return parser;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen }
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return NULL;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
de44e83f4b5e366e57e973b26f2eb0ad26984945Timo Sirainenint config_parse_net(const char *value, struct ip_addr *ip_r,
de44e83f4b5e366e57e973b26f2eb0ad26984945Timo Sirainen unsigned int *bits_r, const char **error_r)
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen{
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen struct ip_addr *ips;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen const char *p;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen unsigned int ip_count, bits, max_bits;
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen time_t t1, t2;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen int ret;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen if (net_parse_range(value, ip_r, bits_r) == 0)
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen return 0;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen p = strchr(value, '/');
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen if (p != NULL) {
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen value = t_strdup_until(value, p);
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen p++;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen }
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen t1 = time(NULL);
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen alarm(DNS_LOOKUP_TIMEOUT_SECS);
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen ret = net_gethostbyname(value, &ips, &ip_count);
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen alarm(0);
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen t2 = time(NULL);
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen if (ret != 0) {
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen *error_r = t_strdup_printf("gethostbyname(%s) failed: %s",
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen value, net_gethosterror(ret));
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen return -1;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen }
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen *ip_r = ips[0];
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen if (t2 - t1 >= DNS_LOOKUP_WARN_SECS) {
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen i_warning("gethostbyname(%s) took %d seconds",
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen value, (int)(t2-t1));
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen }
6a865d46c3704c7d9781f5f249d87796ec5d3591Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen max_bits = IPADDR_IS_V4(&ips[0]) ? 32 : 128;
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen if (p == NULL)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen *bits_r = max_bits;
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen else if (str_to_uint(p, &bits) == 0 && bits <= max_bits)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen *bits_r = bits;
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen else {
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen *error_r = t_strdup_printf("Invalid network mask: %s", p);
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen return -1;
059b4bb561737ce8e15620149140b122021929c9Timo Sirainen }
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen return 0;
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen}
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainenstatic bool
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_filter_add_new_filter(struct config_parser_context *ctx,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *key, const char *value)
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;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *error;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen if (strcmp(key, "protocol") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->service != NULL)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "Nested protocol { protocol { .. } } block not allowed";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen filter->service = p_strdup(ctx->pool, value);
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen } else if (strcmp(key, "local") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->remote_bits > 0)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "remote { local { .. } } not allowed (use local { remote { .. } } instead)";
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen else if (parent->service != NULL)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "protocol { local { .. } } not allowed (use local { protocol { .. } } instead)";
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen else if (parent->local_name != NULL)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "local_name { local { .. } } not allowed (use local { local_name { .. } } instead)";
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen else if (config_parse_net(value, &filter->local_net,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen &filter->local_bits, &error) < 0)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strdup(ctx->pool, error);
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)))
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "local net1 { local net2 { .. } } requires net2 to be inside net1";
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen else
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen filter->local_host = p_strdup(ctx->pool, value);
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen } else if (strcmp(key, "local_name") == 0) {
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (parent->remote_bits > 0)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "remote { local_name { .. } } not allowed (use local_name { remote { .. } } instead)";
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen else if (parent->service != NULL)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "protocol { local_name { .. } } not allowed (use local_name { protocol { .. } } instead)";
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen else
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen filter->local_name = p_strdup(ctx->pool, value);
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen } else if (strcmp(key, "remote") == 0) {
dbd93ca6319a01fdea82853e8b4bd4b226d796f0Timo Sirainen if (parent->service != NULL)
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "protocol { remote { .. } } not allowed (use remote { protocol { .. } } instead)";
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen else if (config_parse_net(value, &filter->remote_net,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen &filter->remote_bits, &error) < 0)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strdup(ctx->pool, error);
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)))
0df899feada1f406122d7658894c77eeb10225a3Timo Sirainen ctx->error = "remote net1 { remote net2 { .. } } requires net2 to be inside net1";
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen else
7c2b57939462fc2022d7e7f7aecd768ec1a8ba38Timo Sirainen filter->remote_host = p_strdup(ctx->pool, value);
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);
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen ctx->cur_section->is_filter = TRUE;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen return TRUE;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen}
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainenstatic int
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_filter_parser_check(struct config_parser_context *ctx,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const struct config_module_parser *p,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char **error_r)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen{
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen const char *error;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen char *error_dup = NULL;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen bool ok;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen for (; p->root != NULL; p++) {
e982ce57ae92ab7ac22496357219697676fab731Timo Sirainen /* skip checking settings we don't care about */
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (!config_module_want_parser(ctx->root_parsers,
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen ctx->modules, p->root))
e982ce57ae92ab7ac22496357219697676fab731Timo Sirainen continue;
e982ce57ae92ab7ac22496357219697676fab731Timo Sirainen
df6551ce47053de2c366f490bef60803207beaa4Timo Sirainen settings_parse_var_skip(p->parser);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen T_BEGIN {
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen ok = settings_parser_check(p->parser, ctx->pool, &error);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen if (!ok)
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen error_dup = i_strdup(error);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen } T_END;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen if (!ok) {
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen i_assert(error_dup != NULL);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen *error_r = t_strdup(error_dup);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen i_free(error_dup);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen return -1;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen }
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen }
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen return 0;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainenstatic const char *
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainenget_str_setting(struct config_filter_parser *parser, const char *key,
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen const char *default_value)
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen{
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen struct config_module_parser *module_parser;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen const char *const *set_value;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen enum setting_type set_type;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen module_parser = parser->parsers;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen for (; module_parser->parser != NULL; module_parser++) {
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen set_value = settings_parse_get_value(module_parser->parser,
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen key, &set_type);
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen if (set_value != NULL &&
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen settings_parse_is_changed(module_parser->parser, key)) {
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen i_assert(set_type == SET_STR || set_type == SET_ENUM);
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen return *set_value;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen }
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen }
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen return default_value;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen}
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainenstatic int
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_all_parsers_check(struct config_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;
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen struct config_module_parser *tmp_parsers;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output output;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen unsigned int i, count;
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen const char *ssl_set, *global_ssl_set;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen pool_t tmp_pool;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen bool ssl_warned = FALSE;
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen int ret = 0;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen if (ctx->cur_section->prev != NULL) {
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen *error_r = t_strdup_printf(
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen "Missing '}' (section started at %s:%u)",
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen ctx->cur_section->open_path,
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen ctx->cur_section->open_linenum);
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen return -1;
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen }
1618629fd55e914c8d2e28fc01b8264613f00a99Timo Sirainen
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen tmp_pool = pool_alloconly_create(MEMPOOL_GROWING"config parsers check", 1024*64);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen parsers = array_get(&ctx->all_parsers, &count);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen i_assert(count > 0 && parsers[count-1] == NULL);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen count--;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen global_ssl_set = get_str_setting(parsers[0], "ssl", "");
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen for (i = 0; i < count && ret == 0; i++) {
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (config_filter_parsers_get(new_filter, tmp_pool, NULL,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen &parsers[i]->filter,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen &tmp_parsers, &output,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen error_r) < 0) {
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen ret = -1;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen break;
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen }
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen ssl_set = get_str_setting(parsers[i], "ssl", global_ssl_set);
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen if (strcmp(ssl_set, "no") != 0 &&
f637b33bb82d56c0546eb08cefcbd7617d885232Timo Sirainen strcmp(global_ssl_set, "no") == 0 && !ssl_warned) {
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen i_warning("SSL is disabled because global ssl=no, "
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen "ignoring ssl=%s for subsection", ssl_set);
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen ssl_warned = TRUE;
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen }
6407c617c37ddf87a8d21745bc95d826c62200a4Timo Sirainen
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen ret = config_filter_parser_check(ctx, tmp_parsers, error_r);
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen config_filter_parsers_free(tmp_parsers);
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen p_clear(tmp_pool);
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen }
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen pool_unref(&tmp_pool);
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen return ret;
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
fbd671a3f51a5f92535923fcaf05fed1e5712ae4Timo Sirainen *error_r = NULL;
fbd671a3f51a5f92535923fcaf05fed1e5712ae4Timo 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 }
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return ret < 0 ? -1 : 0;
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen}
1b33e848e84e6f74aa0e3339c32fa96bc15102a2Timo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenstatic int settings_add_include(struct config_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
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen new_input = p_new(ctx->pool, struct input_stack, 1);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen new_input->prev = ctx->cur_input;
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen new_input->path = p_strdup(ctx->pool, path);
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen new_input->input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
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
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainensettings_include(struct config_parser_context *ctx, const char *pattern,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen bool ignore_errors)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen{
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *error;
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:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = "glob() failed: Not enough memory";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case GLOB_ABORTED:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = "glob() failed: Read error";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen case GLOB_NOMATCH:
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen if (ignore_errors)
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = "No matches";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen default:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = "glob() failed: Unknown error";
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* iterate through the different files matching the globbing */
460fc973318e28c32d53c5696a5835b56a9527a9Timo Sirainen for (i = globbers.gl_pathc; i > 0; i--) {
460fc973318e28c32d53c5696a5835b56a9527a9Timo Sirainen if (settings_add_include(ctx, globbers.gl_pathv[i-1],
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ignore_errors, &error) < 0) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strdup(ctx->pool, error);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return -1;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen }
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen globfree(&globbers);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#else
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (settings_add_include(ctx, pattern, ignore_errors, &error) < 0) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strdup(ctx->pool, error);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen return -1;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen return 0;
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen#endif
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen}
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenstatic enum config_line_type
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenconfig_parse_line(struct config_parser_context *ctx,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen char *line, string_t *full_line,
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen const char **key_r, const char **value_r)
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen{
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen const char *key;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t 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 == '#') {
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen if (!IS_WHITE(p[-1])) {
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen i_warning("Configuration file %s line %u: "
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen "Ambiguous '#' character in line, treating it as comment. "
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen "Add a space before it to remove this warning.",
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen ctx->cur_input->path,
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen ctx->cur_input->linenum);
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen }
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);
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang while (len >= 1) {
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang if(!IS_WHITE(line[len-1]))
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang break;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen len--;
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line[len] = '\0';
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang if (len >= 1 && line[len-1] == '\\') {
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen /* continues in next line */
c8154bfaf4f08f4b1b038ae4483ea703789c9be6Timo Sirainen len--;
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang while (len >= 1) {
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang if(!IS_WHITE(line[len-1]))
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang break;
c8154bfaf4f08f4b1b038ae4483ea703789c9be6Timo Sirainen len--;
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang }
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang if(len >= 1) {
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang str_append_n(full_line, line, len);
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang str_append_c(full_line, ' ');
b27a8a97319620c4a6d97f2f98a2f0f15669d8f9Baofeng Wang }
0fa40bfd73cedc311ff2e0ae90707836382bfc8cTimo Sirainen return CONFIG_LINE_TYPE_CONTINUE;
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
adc36a428ffc99c8befa88ce35b9cefbd7ed34ccTimo Sirainen if (*line == '<') {
626e3839784e63befc29386cbfc7e5760f5e71bfTimo Sirainen while (IS_WHITE(line[1])) line++;
adc36a428ffc99c8befa88ce35b9cefbd7ed34ccTimo Sirainen *value_r = line + 1;
adc36a428ffc99c8befa88ce35b9cefbd7ed34ccTimo Sirainen return CONFIG_LINE_TYPE_KEYFILE;
adc36a428ffc99c8befa88ce35b9cefbd7ed34ccTimo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen if (*line == '$') {
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen *value_r = line + 1;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen return CONFIG_LINE_TYPE_KEYVARIABLE;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
adc36a428ffc99c8befa88ce35b9cefbd7ed34ccTimo 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 */
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen if (*line != '"') {
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen *value_r = line;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen while (!IS_WHITE(*line) && *line != '\0')
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen line++;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen if (*line != '\0') {
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen *line++ = '\0';
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen while (IS_WHITE(*line))
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen line++;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen }
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen } else {
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen char *value = ++line;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen while (*line != '"' && *line != '\0')
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen line++;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen if (*line == '"') {
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen *line++ = '\0';
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen while (IS_WHITE(*line))
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen line++;
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen *value_r = str_unescape(value);
d477b279ecb46c3e38bb505eefc6fbd20056905eTimo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen if (*line != '{') {
f34e5fbfc053542595005c8dfa1c9fd4254de1dfPhil Carmody *value_r = "Expecting '{'";
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_ERROR;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
95dd5084fc409d5cf7aa1f129b3ec3a54008f09aTimo Sirainen }
95dd5084fc409d5cf7aa1f129b3ec3a54008f09aTimo Sirainen if (line[1] != '\0') {
95dd5084fc409d5cf7aa1f129b3ec3a54008f09aTimo Sirainen *value_r = "Garbage after '{'";
95dd5084fc409d5cf7aa1f129b3ec3a54008f09aTimo Sirainen return CONFIG_LINE_TYPE_ERROR;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return CONFIG_LINE_TYPE_SECTION_BEGIN;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen}
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenstatic int config_parse_finish(struct config_parser_context *ctx, const char **error_r)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen{
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen struct config_filter_context *new_filter;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen const char *error;
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen int ret = 0;
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen if (hook_config_parser_end != NULL)
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen ret = hook_config_parser_end(ctx, error_r);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen new_filter = config_filter_init(ctx->pool);
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen array_append_zero(&ctx->all_parsers);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen config_filter_add_all(new_filter, array_idx(&ctx->all_parsers, 0));
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen if (ret < 0)
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen ;
0df566822360dd8ca963864a51a8bd56054c3331Timo Sirainen else if (ctx->hide_errors)
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen ret = 0;
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen else if ((ret = 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 }
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;
4383941ed43d004f34f77334a06ad14e6a305607Timo Sirainen return ret;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen}
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainenstatic const void *
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainenconfig_get_value(struct config_section_stack *section, const char *key,
92a9ff5e799adf9bffb8831576d84eb84b8ef09aTimo Sirainen bool expand_parent, enum setting_type *type_r)
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen{
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen struct config_module_parser *l;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen const void *value;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen
92a9ff5e799adf9bffb8831576d84eb84b8ef09aTimo Sirainen for (l = section->parsers; l->root != NULL; l++) {
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen value = settings_parse_get_value(l->parser, key, type_r);
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen if (value != NULL) {
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen if (!expand_parent || section->prev == NULL ||
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen settings_parse_is_changed(l->parser, key))
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen return value;
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen /* not changed by this parser. maybe parent has. */
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen return config_get_value(section->prev,
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen key, TRUE, type_r);
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen return NULL;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen}
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainenstatic bool
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainenconfig_require_key(struct config_parser_context *ctx, const char *key)
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen{
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen struct config_module_parser *l;
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (ctx->modules == NULL)
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen return TRUE;
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen for (l = ctx->cur_section->parsers; l->root != NULL; l++) {
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen if (config_module_want_parser(ctx->root_parsers,
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen ctx->modules, l->root) &&
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen settings_parse_is_valid_key(l->parser, key))
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen return TRUE;
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen }
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen return FALSE;
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen}
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenstatic int config_write_value(struct config_parser_context *ctx,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen enum config_line_type type,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *key, const char *value)
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen{
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen string_t *str = ctx->str;
e84a09e48c179ff8fe9fe10b8a09c2f23f83fda9Timo Sirainen const void *var_name, *var_value, *p;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen enum setting_type var_type;
3fae65c7973bd0327191c2c4e9c9bcd48f24f59bTimo Sirainen const char *error, *path, *full_key;
92a9ff5e799adf9bffb8831576d84eb84b8ef09aTimo Sirainen bool dump, expand_parent;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen switch (type) {
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen case CONFIG_LINE_TYPE_KEYVALUE:
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen str_append(str, value);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen break;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen case CONFIG_LINE_TYPE_KEYFILE:
3fae65c7973bd0327191c2c4e9c9bcd48f24f59bTimo Sirainen full_key = t_strndup(str_data(ctx->str), str_len(str)-1);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen if (!ctx->expand_values) {
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen str_append_c(str, '<');
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen str_append(str, value);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen } else {
3fae65c7973bd0327191c2c4e9c9bcd48f24f59bTimo Sirainen if (!config_require_key(ctx, full_key)) {
098e1a7aef39722fd2d4b4e4535eb9e6aedd1ef2Timo Sirainen /* don't even try to open the file */
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen } else {
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen path = fix_relative_path(value, ctx->cur_input);
3fae65c7973bd0327191c2c4e9c9bcd48f24f59bTimo Sirainen if (str_append_file(str, full_key, path, &error) < 0) {
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen /* file reading failed */
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen ctx->error = p_strdup(ctx->pool, error);
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen return -1;
9e28e13ae8dc7cf7e9ff82d07392db8a6e941495Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen break;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen case CONFIG_LINE_TYPE_KEYVARIABLE:
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen /* expand_parent=TRUE for "key = $key stuff".
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen we'll always expand it so that doveconf -n can give
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen usable output */
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen p = strchr(value, ' ');
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen if (p == NULL)
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen var_name = value;
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen else
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen var_name = t_strdup_until(value, p);
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen expand_parent = strcmp(key, var_name) == 0;
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen
d581fe1755bcfc0f42020178376ec65e2f8ced4bTimo Sirainen if (!ctx->expand_values && !expand_parent) {
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen str_append_c(str, '$');
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen str_append(str, value);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen } else {
19ddb3a08a51e533a8f793b1d9beebd87c201d10Timo Sirainen var_value = config_get_value(ctx->cur_section, var_name,
92a9ff5e799adf9bffb8831576d84eb84b8ef09aTimo Sirainen expand_parent, &var_type);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen if (var_value == NULL) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strconcat(ctx->pool,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen "Unknown variable: $",
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen var_name, NULL);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen return -1;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen if (!config_export_type(str, var_value, NULL,
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen var_type, TRUE, &dump)) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strconcat(ctx->pool,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen "Invalid variable: $",
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen var_name, NULL);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen return -1;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
e84a09e48c179ff8fe9fe10b8a09c2f23f83fda9Timo Sirainen if (p != NULL)
e84a09e48c179ff8fe9fe10b8a09c2f23f83fda9Timo Sirainen str_append(str, p);
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen break;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen default:
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen i_unreached();
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen }
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen return 0;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen}
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen
87404eae4581d7ef834f490507503e59a500066eTimo Sirainenstatic void
87404eae4581d7ef834f490507503e59a500066eTimo Sirainenconfig_parser_check_warnings(struct config_parser_context *ctx, const char *key)
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen{
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen const char *path, *first_pos;
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen first_pos = hash_table_lookup(ctx->seen_settings, str_c(ctx->str));
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen if (ctx->cur_section->prev == NULL) {
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen /* changing a root setting. if we've already seen it inside
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen filters, log a warning. */
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen if (first_pos == NULL)
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen return;
cb445bd4e32a2aae17a97a87bd74f57caec25449Timo Sirainen i_warning("%s line %u: Global setting %s won't change the setting inside an earlier filter at %s "
cb445bd4e32a2aae17a97a87bd74f57caec25449Timo Sirainen "(if this is intentional, avoid this warning by moving the global setting before %s)",
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen ctx->cur_input->path, ctx->cur_input->linenum,
cb445bd4e32a2aae17a97a87bd74f57caec25449Timo Sirainen key, first_pos, first_pos);
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen return;
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen }
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen if (first_pos != NULL)
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen return;
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen first_pos = p_strdup_printf(ctx->pool, "%s line %u",
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen ctx->cur_input->path, ctx->cur_input->linenum);
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen path = p_strdup(ctx->pool, str_c(ctx->str));
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen hash_table_insert(ctx->seen_settings, path, first_pos);
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen}
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenvoid config_parser_apply_line(struct config_parser_context *ctx,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen enum config_line_type type,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *key, const char *value)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen{
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *section_name;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_truncate(ctx->str, ctx->pathlen);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen switch (type) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_SKIP:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
0fa40bfd73cedc311ff2e0ae90707836382bfc8cTimo Sirainen case CONFIG_LINE_TYPE_CONTINUE:
0fa40bfd73cedc311ff2e0ae90707836382bfc8cTimo Sirainen i_unreached();
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_ERROR:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = p_strdup(ctx->pool, value);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_KEYVALUE:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_KEYFILE:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_KEYVARIABLE:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append(ctx->str, key);
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen config_parser_check_warnings(ctx, key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append_c(ctx->str, '=');
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (config_write_value(ctx, type, key, value) < 0)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen (void)config_apply_line(ctx, key, str_c(ctx->str), NULL);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_SECTION_BEGIN:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->cur_section = config_add_new_section(ctx);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->cur_section->pathlen = ctx->pathlen;
e3d797bc851dc90fb88e68ae715c204d0f46e6ffTimo Sirainen ctx->cur_section->key = p_strdup(ctx->pool, key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (config_filter_add_new_filter(ctx, key, value)) {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* new filter */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* new config section */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (*value == '\0') {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen /* no section name, use a counter */
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen section_name = dec2str(ctx->section_counter++);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen } else {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen section_name = settings_section_escape(value);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append(ctx->str, key);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->pathlen = str_len(ctx->str);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append_c(ctx->str, '=');
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append(ctx->str, section_name);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (config_apply_line(ctx, key, str_c(ctx->str), value) < 0)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_truncate(ctx->str, ctx->pathlen);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append_c(ctx->str, SETTINGS_SEPARATOR);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append(ctx->str, section_name);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_append_c(ctx->str, SETTINGS_SEPARATOR);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->pathlen = str_len(ctx->str);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_SECTION_END:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ctx->cur_section->prev == NULL)
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->error = "Unexpected '}'";
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen else {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->pathlen = ctx->cur_section->pathlen;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx->cur_section = ctx->cur_section->prev;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_INCLUDE:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen case CONFIG_LINE_TYPE_INCLUDE_TRY:
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen (void)settings_include(ctx, fix_relative_path(value, ctx->cur_input),
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen type == CONFIG_LINE_TYPE_INCLUDE_TRY);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen break;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen}
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainenint config_parse_file(const char *path, bool expand_values,
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen const char *const *modules, const char **error_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen struct input_stack root;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen struct config_parser_context ctx;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned int i, count;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen const char *key, *value;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen string_t *full_line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen enum config_line_type type;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen char *line;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen int fd, ret = 0;
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen bool handled;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen if (path == NULL) {
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen path = "<defaults>";
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen fd = -1;
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen } else {
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen fd = open(path, O_RDONLY);
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen if (fd < 0) {
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen *error_r = t_strdup_printf("open(%s) failed: %m", path);
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen return 0;
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen }
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen }
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen ctx.pool = pool_alloconly_create(MEMPOOL_GROWING"config file parser", 1024*256);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.path = path;
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen ctx.hide_errors = fd == -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen for (count = 0; all_roots[count] != 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++) {
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen ctx.root_parsers[i].root = all_roots[i];
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen ctx.root_parsers[i].parser =
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen settings_parser_init(ctx.pool, all_roots[i],
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen settings_parser_flags);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen }
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&root);
d595049948579def2d82718dbce0a6b49a281402Timo Sirainen root.path = path;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input = &root;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen ctx.expand_values = expand_values;
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen ctx.modules = modules;
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen hash_table_create(&ctx.seen_settings, ctx.pool, 0, str_hash, strcmp);
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
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx.str = str_new(ctx.pool, 256);
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen full_line = str_new(default_pool, 512);
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen ctx.cur_input->input = fd != -1 ?
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen i_stream_create_fd_autoclose(&fd, (size_t)-1) :
c45852c0ee568ae95360002363f21a147bf6c7abTimo Sirainen i_stream_create_from_data("", 0);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen i_stream_set_return_partial_line(ctx.cur_input->input, TRUE);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen old_settings_init(&ctx);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen if (hook_config_parser_begin != NULL) T_BEGIN {
0171540a6764f714b8b753ba209ec9a83c213d25Timo Sirainen hook_config_parser_begin(&ctx);
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen } T_END;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen
d595049948579def2d82718dbce0a6b49a281402Timo Sirainenprevfile:
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ctx.cur_input->linenum++;
25e480bc781fdbcbee1d8b88ccdef163c0c63b0fTimo Sirainen type = config_parse_line(&ctx, line, full_line,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen &key, &value);
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen str_truncate(ctx.str, ctx.pathlen);
0fa40bfd73cedc311ff2e0ae90707836382bfc8cTimo Sirainen if (type == CONFIG_LINE_TYPE_CONTINUE)
0fa40bfd73cedc311ff2e0ae90707836382bfc8cTimo Sirainen continue;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen T_BEGIN {
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen handled = old_settings_handle(&ctx, type, key, value);
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen if (!handled)
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen config_parser_apply_line(&ctx, type, key, value);
d461a91e5eb2270e77f4276f0268ba1eede6a08dTimo Sirainen } T_END;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (ctx.error != 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,
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen ctx.error);
4383941ed43d004f34f77334a06ad14e6a305607Timo Sirainen ret = -2;
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
87404eae4581d7ef834f490507503e59a500066eTimo Sirainen hash_table_destroy(&ctx.seen_settings);
66d7dd2a37123a332f19bfa83ea58521f9853d01Timo Sirainen str_free(&full_line);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (ret == 0)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen ret = config_parse_finish(&ctx, error_r);
f41adea86b697c8d6970d6d992ac3eca199dfc07Timo Sirainen return ret < 0 ? ret : 1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainenvoid config_parse_load_modules(void)
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen{
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen struct module_dir_load_settings mod_set;
73b8333f9a979efefe1db70f22c63edec5ad4466Timo Sirainen struct module *m;
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen const struct setting_parser_info **roots;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen ARRAY_TYPE(setting_parser_info_p) new_roots;
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen ARRAY_TYPE(service_settings) new_services;
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen struct service_settings *const *services, *service_set;
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen unsigned int i, count;
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&mod_set);
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen mod_set.abi_version = DOVECOT_ABI_VERSION;
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen modules = module_dir_load(CONFIG_MODULE_DIR, NULL, &mod_set);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen module_dir_init(modules);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen i_array_init(&new_roots, 64);
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen i_array_init(&new_services, 64);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen for (m = modules; m != NULL; m = m->next) {
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen roots = module_get_symbol_quiet(m,
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen t_strdup_printf("%s_set_roots", m->name));
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen if (roots != NULL) {
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen for (i = 0; roots[i] != NULL; i++)
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen array_append(&new_roots, &roots[i], 1);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen }
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen services = module_get_symbol_quiet(m,
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen t_strdup_printf("%s_service_settings_array", m->name));
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen if (services != NULL) {
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen for (count = 0; services[count] != NULL; count++) ;
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen array_append(&new_services, services, count);
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen } else {
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen service_set = module_get_symbol_quiet(m,
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen t_strdup_printf("%s_service_settings", m->name));
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen if (service_set != NULL)
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen array_append(&new_services, &service_set, 1);
1ab2295a9258fe032bc9cb38909e902b40353282Timo Sirainen }
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen }
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen if (array_count(&new_roots) > 0) {
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen /* modules added new settings. add the defaults and start
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen using the new list. */
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen for (i = 0; all_roots[i] != NULL; i++)
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen array_append(&new_roots, &all_roots[i], 1);
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen array_append_zero(&new_roots);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen all_roots = array_idx(&new_roots, 0);
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen roots_free_at_deinit = new_roots;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen } else {
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen array_free(&new_roots);
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen }
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen if (array_count(&new_services) > 0) {
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen /* module added new services. update the defaults. */
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen services = array_get(default_services, &count);
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen for (i = 0; i < count; i++)
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen array_append(&new_services, &services[i], 1);
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen *default_services = new_services;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen services_free_at_deinit = new_services;
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen } else {
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen array_free(&new_services);
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen }
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen}
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainenstatic bool parsers_are_connected(const struct setting_parser_info *root,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct setting_parser_info *info)
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen{
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct setting_parser_info *p;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct setting_parser_info *const *dep;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen /* we're trying to find info or its parents from root's dependencies. */
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen for (p = info; p != NULL; p = p->parent) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen if (p == root)
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return TRUE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen if (root->dependencies != NULL) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen for (dep = root->dependencies; *dep != NULL; dep++) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen if (parsers_are_connected(*dep, info))
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return TRUE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return FALSE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen}
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainenbool config_module_want_parser(struct config_module_parser *parsers,
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen const char *const *modules,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct setting_parser_info *root)
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen{
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen struct config_module_parser *l;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (modules == NULL)
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return TRUE;
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (root == &master_service_setting_parser_info) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen /* everyone wants master service settings */
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return TRUE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
a402b3c01073c1b11fe3c83aae4e3bc5c7d40360Timo Sirainen for (l = parsers; l->root != NULL; l++) {
633a3da9d3e9a5befd3405f6651043a6bdd327cbTimo Sirainen if (!str_array_find(modules, l->root->module_name))
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen continue;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen /* see if we can find a way to get from the original parser
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen to this parser */
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen if (parsers_are_connected(l->root, root))
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return TRUE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen return FALSE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen}
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainenvoid config_parser_deinit(void)
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen{
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen if (array_is_created(&services_free_at_deinit))
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen array_free(&services_free_at_deinit);
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen if (array_is_created(&roots_free_at_deinit))
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen array_free(&roots_free_at_deinit);
6347bb65e93c27f1bf4330786447c9ab0cab4dbfTimo Sirainen}