dovecot-2.0: config: If master module requests configuration, re...

dovecot at dovecot.org dovecot at dovecot.org
Sat Aug 15 01:14:57 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/d7ccdbb58a03
changeset: 9793:d7ccdbb58a03
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Aug 14 18:13:35 2009 -0400
description:
config: If master module requests configuration, reread it before replying.
If new configuration is invalid, send an ERROR reply back.

diffstat:

9 files changed, 106 insertions(+), 47 deletions(-)
src/config/all-settings.h      |    8 ---
src/config/config-connection.c |   25 ++++++++---
src/config/config-filter.c     |    1 
src/config/config-filter.h     |    1 
src/config/config-parser.c     |   90 +++++++++++++++++++++++++++-------------
src/config/config-parser.h     |   12 ++++-
src/config/doveconf.c          |    4 +
src/config/main.c              |    6 ++
src/config/settings-get.pl     |    6 +-

diffs (truncated from 383 to 300 lines):

diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/all-settings.h
--- a/src/config/all-settings.h	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/all-settings.h	Fri Aug 14 18:13:35 2009 -0400
@@ -1,14 +1,10 @@
 #ifndef ALL_SETTINGS_H
 #define ALL_SETTINGS_H
 
-struct config_setting_parser_list {
+struct all_settings_root {
 	const char *module_name;
 	struct setting_parser_info *root;
-	struct setting_parser_context *parser;
-	void *settings;
 };
-ARRAY_DEFINE_TYPE(config_setting_parsers, struct config_setting_parser_list *);
-
-extern struct config_setting_parser_list config_setting_parsers[];
+extern const struct all_settings_root all_roots[];
 
 #endif
diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/config-connection.c
--- a/src/config/config-connection.c	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/config-connection.c	Fri Aug 14 18:13:35 2009 -0400
@@ -7,6 +7,7 @@
 #include "settings-parser.h"
 #include "master-service.h"
 #include "config-request.h"
+#include "config-parser.h"
 #include "config-connection.h"
 
 #include <stdlib.h>
@@ -61,11 +62,11 @@ config_request_output(const char *key, c
 	o_stream_send_str(output, "\n");
 }
 
-static void config_connection_request(struct config_connection *conn,
-				      const char *const *args)
+static int config_connection_request(struct config_connection *conn,
+				     const char *const *args)
 {
 	struct config_filter filter;
-	const char *module = "";
+	const char *path, *error, *module = "";
 
 	/* [<args>] */
 	memset(&filter, 0, sizeof(filter));
@@ -89,11 +90,23 @@ static void config_connection_request(st
 		}
 	}
 
+	if (strcmp(module, "master") == 0) {
+		/* master reads configuration only when reloading settings */
+		path = master_service_get_config_path(master_service);
+		if (config_parse_file(path, TRUE, &error) < 0) {
+			o_stream_send_str(conn->output,
+				t_strconcat("ERROR ", error, "\n", NULL));
+			config_connection_destroy(conn);
+			return -1;
+		}
+	}
+
 	o_stream_cork(conn->output);
 	config_request_handle(&filter, module, 0, config_request_output,
 			      conn->output);
 	o_stream_send_str(conn->output, "\n");
 	o_stream_uncork(conn->output);
+	return 0;
 }
 
 static void config_connection_input(void *context)
@@ -130,8 +143,10 @@ static void config_connection_input(void
 	while ((args = config_connection_next_line(conn)) != NULL) {
 		if (args[0] == NULL)
 			continue;
-		if (strcmp(args[0], "REQ") == 0)
-			config_connection_request(conn, args + 1);
+		if (strcmp(args[0], "REQ") == 0) {
+			if (config_connection_request(conn, args + 1) < 0)
+				break;
+		}
 	}
 }
 
diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/config-filter.c
--- a/src/config/config-filter.c	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/config-filter.c	Fri Aug 14 18:13:35 2009 -0400
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "config-parser.h"
 #include "config-filter.h"
 
 struct config_filter_context {
diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/config-filter.h
--- a/src/config/config-filter.h	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/config-filter.h	Fri Aug 14 18:13:35 2009 -0400
@@ -2,7 +2,6 @@
 #define CONFIG_FILTER_H
 
 #include "network.h"
-#include "all-settings.h"
 
 struct config_filter {
 	const char *service;
diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/config-parser.c
--- a/src/config/config-parser.c	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/config-parser.c	Fri Aug 14 18:13:35 2009 -0400
@@ -7,6 +7,7 @@
 #include "strescape.h"
 #include "istream.h"
 #include "settings-parser.h"
+#include "all-settings.h"
 #include "config-filter.h"
 #include "config-parser.h"
 
@@ -43,12 +44,14 @@ struct parser_context {
 	ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
 	/* parsers matching cur_filter */
 	ARRAY_TYPE(config_setting_parsers) cur_parsers;
+	struct config_setting_parser_list *root_parsers;
 	struct config_filter_stack *cur_filter;
 	struct input_stack *cur_input;
 
 	struct config_filter_context *filter;
 };
 
+struct config_setting_parser_list *config_setting_parsers;
 struct config_filter_context *config_filter;
 
 static const char *info_type_name_find(const struct setting_parser_info *info)
@@ -171,7 +174,7 @@ config_add_new_parser(struct parser_cont
 	cur_parsers = array_get(&ctx->cur_parsers, &count);
 	if (count == 0) {
 		/* first one */
-		parser->parser_list = config_setting_parsers;
+		parser->parser_list = ctx->root_parsers;
 	} else {
 		/* duplicate the first settings list */
 		parser->parser_list =
@@ -223,30 +226,38 @@ config_update_cur_parsers(struct parser_
 	return array_idx(&ctx->cur_parsers, 0);
 }
 
-static void
+static int
 config_filter_parser_list_check(struct parser_context *ctx,
-				struct config_filter_parser_list *parser)
+				struct config_filter_parser_list *parser,
+				const char **error_r)
 {
 	struct config_setting_parser_list *l = parser->parser_list;
 	const char *errormsg;
 
 	for (; l->module_name != NULL; l++) {
 		if (!settings_parser_check(l->parser, ctx->pool, &errormsg)) {
-			i_fatal("Error in configuration file %s: %s",
+			*error_r = t_strdup_printf(
+				"Error in configuration file %s: %s",
 				ctx->path, errormsg);
-		}
-	}
-}
-
-static void
-config_all_parsers_check(struct parser_context *ctx)
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int
+config_all_parsers_check(struct parser_context *ctx, const char **error_r)
 {
 	struct config_filter_parser_list *const *parsers;
 	unsigned int i, count;
 
 	parsers = array_get(&ctx->all_parsers, &count);
-	for (i = 0; i < count; i++)
-		config_filter_parser_list_check(ctx, parsers[i]);
+	for (i = 0; i < count; i++) {
+		if (config_filter_parser_list_check(ctx, parsers[i],
+						    error_r) < 0)
+			return -1;
+	}
+	return 0;
 }
 
 static void
@@ -345,37 +356,45 @@ settings_include(struct parser_context *
 #endif
 }
 
-void config_parse_file(const char *path, bool expand_files)
+int config_parse_file(const char *path, bool expand_files,
+		      const char **error_r)
 {
 	enum settings_parser_flags parser_flags =
                 SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
 	struct input_stack root;
 	ARRAY_TYPE(const_string) auth_defaults;
-	struct config_setting_parser_list *l, *const *parsers;
+	struct config_setting_parser_list *const *parsers;
 	struct parser_context ctx;
 	unsigned int pathlen = 0;
-	unsigned int counter = 0, auth_counter = 0, cur_counter;
+	unsigned int i, count, counter = 0, auth_counter = 0, cur_counter;
 	const char *errormsg, *name;
 	char *line, *key, *p;
-	int fd, ret;
+	int fd, ret = 0;
 	string_t *str, *full_line;
 	size_t len;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		*error_r = t_strdup_printf("open(%s) failed: %m", path);
+		return -1;
+	}
 
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.pool = pool_alloconly_create("config file parser", 1024*64);
 	ctx.path = path;
 
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		i_fatal("open(%s) failed: %m", path);
+	for (count = 0; all_roots[count].module_name != NULL; count++) ;
+	ctx.root_parsers =
+		p_new(ctx.pool, struct config_setting_parser_list, count+1);
+	for (i = 0; i < count; i++) {
+		ctx.root_parsers[i].module_name = all_roots[i].module_name;
+		ctx.root_parsers[i].root = all_roots[i].root;
+		ctx.root_parsers[i].parser =
+			settings_parser_init(ctx.pool, all_roots[i].root,
+					     parser_flags);
+	}
 
 	t_array_init(&auth_defaults, 32);
-
-	for (l = config_setting_parsers; l->module_name != NULL; l++) {
-		i_assert(l->parser == NULL);
-		l->parser = settings_parser_init(ctx.pool, l->root, parser_flags);
-	}
-
 	t_array_init(&ctx.cur_parsers, 128);
 	p_array_init(&ctx.all_parsers, ctx.pool, 128);
 	ctx.cur_filter = p_new(ctx.pool, struct config_filter_stack, 1);
@@ -454,7 +473,6 @@ prevfile:
 			while (IS_WHITE(*line)) line++;
 		}
 
-		ret = 1;
 		if (strcmp(key, "!include_try") == 0 ||
 		    strcmp(key, "!include") == 0) {
 			if (settings_include(&ctx, fix_relative_path(line, ctx.cur_input),
@@ -600,9 +618,11 @@ prevfile:
 		}
 
 		if (errormsg != NULL) {
-			i_fatal("Error in configuration file %s line %d: %s",
+			*error_r = t_strdup_printf(
+				"Error in configuration file %s line %d: %s",
 				ctx.cur_input->path, ctx.cur_input->linenum,
 				errormsg);
+			ret = -1;
 			break;
 		}
 		str_truncate(full_line, 0);
@@ -613,9 +633,21 @@ prevfile:
 	if (line == NULL && ctx.cur_input != NULL)
 		goto prevfile;
 
-	config_all_parsers_check(&ctx);
+	if (ret == 0) {
+		if (config_all_parsers_check(&ctx, error_r) < 0)
+			ret = -1;
+	}
+	if (ret < 0) {
+		pool_unref(&ctx.pool);
+		return -1;
+	}
+
+	if (config_filter != NULL)
+		config_filter_deinit(&config_filter);
+	config_setting_parsers = ctx.root_parsers;
 
 	(void)array_append_space(&ctx.all_parsers);
 	config_filter = config_filter_init(ctx.pool);
 	config_filter_add_all(config_filter, array_idx(&ctx.all_parsers, 0));
-}
+	return 0;
+}
diff -r 0287c38ba6bf -r d7ccdbb58a03 src/config/config-parser.h
--- a/src/config/config-parser.h	Fri Aug 14 17:36:27 2009 -0400
+++ b/src/config/config-parser.h	Fri Aug 14 18:13:35 2009 -0400
@@ -1,8 +1,18 @@
 #ifndef CONFIG_PARSER_H
 #define CONFIG_PARSER_H


More information about the dovecot-cvs mailing list