dovecot-2.0: config: If value contains <file, the setting value ...

dovecot at dovecot.org dovecot at dovecot.org
Thu May 14 02:52:43 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/39c2db5f1fcc
changeset: 9274:39c2db5f1fcc
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 13 19:51:34 2009 -0400
description:
config: If value contains <file, the setting value is read from the given file.

diffstat:

7 files changed, 83 insertions(+), 47 deletions(-)
src/config/config-connection.c     |    7 +++
src/config/config-parser.c         |   45 ++++++++++++++++++++---
src/config/config-parser.h         |    2 -
src/config/doveconf.c              |    2 -
src/config/main.c                  |    2 -
src/lib-settings/settings-parser.c |   69 +++++++++++++++---------------------
src/lib-settings/settings-parser.h |    3 +

diffs (235 lines):

diff -r 1d7965092e0e -r 39c2db5f1fcc src/config/config-connection.c
--- a/src/config/config-connection.c	Wed May 13 17:51:16 2009 -0400
+++ b/src/config/config-connection.c	Wed May 13 19:51:34 2009 -0400
@@ -4,6 +4,7 @@
 #include "llist.h"
 #include "istream.h"
 #include "ostream.h"
+#include "settings-parser.h"
 #include "config-request.h"
 #include "config-connection.h"
 
@@ -46,9 +47,15 @@ config_request_output(const char *key, c
 		      bool list ATTR_UNUSED, void *context)
 {
 	struct ostream *output = context;
+	const char *p;
 
 	o_stream_send_str(output, key);
 	o_stream_send_str(output, "=");
+	while ((p = strchr(value, '\n')) != NULL) {
+		o_stream_send(output, value, p-value);
+		o_stream_send(output, SETTING_STREAM_LF_CHAR, 1);
+		value = p+1;
+	}
 	o_stream_send_str(output, value);
 	o_stream_send_str(output, "\n");
 }
diff -r 1d7965092e0e -r 39c2db5f1fcc src/config/config-parser.c
--- a/src/config/config-parser.c	Wed May 13 17:51:16 2009 -0400
+++ b/src/config/config-parser.c	Wed May 13 19:51:34 2009 -0400
@@ -242,7 +242,30 @@ config_all_parsers_check(struct parser_c
 		config_filter_parser_list_check(ctx, parsers[i]);
 }
 
-void config_parse_file(const char *path)
+static void
+str_append_file(string_t *str, const char *key, const char *path,
+		const char **error_r)
+{
+	unsigned char buf[1024];
+	int fd;
+	ssize_t ret;
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		*error_r = t_strdup_printf("%s: Can't open file %s: %m",
+					   key, path);
+		return;
+	}
+	while ((ret = read(fd, buf, sizeof(buf))) > 0)
+		str_append_n(str, buf, ret);
+	if (ret < 0) {
+		*error_r = t_strdup_printf("%s: read(%s) failed: %m",
+					   key, path);
+	}
+	(void)close(fd);
+}
+
+void config_parse_file(const char *path, bool expand_files)
 {
 	enum settings_parser_flags parser_flags =
                 SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS;
@@ -394,15 +417,27 @@ prevfile:
 			str_truncate(str, pathlen);
 			str_append(str, key);
 			str_append_c(str, '=');
-			str_append(str, line);
-			if (pathlen == 0 &&
-			    strncmp(str_c(str), "auth_", 5) == 0) {
+
+			if (*line != '<' || !expand_files)
+				str_append(str, line);
+			else
+				str_append_file(str, key, line+1, &errormsg);
+
+			if (errormsg != NULL) {
+				/* file reading failed */
+			} else if (pathlen == 0 &&
+				   strncmp(str_c(str), "auth_", 5) == 0) {
 				/* verify that the setting is valid,
 				   but delay actually adding it */
 				const char *s = t_strdup(str_c(str) + 5);
 
 				str_truncate(str, 0);
-				str_printfa(str, "auth/0/%s=%s", key + 5, line);
+				str_printfa(str, "auth/0/%s=", key + 5);
+				if (*line != '<' || !expand_files)
+					str_append(str, line);
+				else
+					str_append_file(str, key, line+1, &errormsg);
+
 				errormsg = config_parse_line(parsers, key + 5, str_c(str), NULL);
 				array_append(&auth_defaults, &s, 1);
 			} else {
diff -r 1d7965092e0e -r 39c2db5f1fcc src/config/config-parser.h
--- a/src/config/config-parser.h	Wed May 13 17:51:16 2009 -0400
+++ b/src/config/config-parser.h	Wed May 13 19:51:34 2009 -0400
@@ -3,6 +3,6 @@
 
 extern struct config_filter_context *config_filter;
 
-void config_parse_file(const char *path);
+void config_parse_file(const char *path, bool expand_files);
 
 #endif
diff -r 1d7965092e0e -r 39c2db5f1fcc src/config/doveconf.c
--- a/src/config/doveconf.c	Wed May 13 17:51:16 2009 -0400
+++ b/src/config/doveconf.c	Wed May 13 19:51:34 2009 -0400
@@ -248,7 +248,7 @@ int main(int argc, char *argv[])
 	}
 	master_service_init_finish(service);
 
-	config_parse_file(config_path);
+	config_parse_file(config_path, FALSE);
 
 	if (exec_args == NULL) {
 		const char *info;
diff -r 1d7965092e0e -r 39c2db5f1fcc src/config/main.c
--- a/src/config/main.c	Wed May 13 17:51:16 2009 -0400
+++ b/src/config/main.c	Wed May 13 19:51:34 2009 -0400
@@ -30,7 +30,7 @@ int main(int argc, char *argv[])
 
 	master_service_init_log(service, "config: ", 0);
 	master_service_init_finish(service);
-	config_parse_file(master_service_get_config_path(service));
+	config_parse_file(master_service_get_config_path(service), TRUE);
 
 	master_service_run(service, client_connected);
 	config_connections_destroy_all();
diff -r 1d7965092e0e -r 39c2db5f1fcc src/lib-settings/settings-parser.c
--- a/src/lib-settings/settings-parser.c	Wed May 13 17:51:16 2009 -0400
+++ b/src/lib-settings/settings-parser.c	Wed May 13 19:51:34 2009 -0400
@@ -449,59 +449,50 @@ settings_parse_get_prev_info(struct sett
 	return ctx->prev_info;
 }
 
+static const char *settings_translate_lf(const char *value)
+{
+	char *dest, *p;
+
+	if (strchr(value, SETTING_STREAM_LF_CHAR[0]) == NULL)
+		return value;
+
+	dest = t_strdup_noconst(value);
+	for (p = dest; *p != '\0'; p++) {
+		if (*p == SETTING_STREAM_LF_CHAR[0])
+			*p = '\n';
+	}
+	return dest;
+}
+
 int settings_parse_stream(struct setting_parser_context *ctx,
 			  struct istream *input)
 {
 	const char *line;
-	string_t *full_line;
-	size_t len;
 	int ret = 1;
 
-	full_line = str_new(default_pool, 512);
 	while ((line = i_stream_next_line(input)) != NULL) {
 		if (*line == '\0') {
 			/* empty line finishes it */
 			ret = 0;
 			break;
 		}
-
 		ctx->linenum++;
-		while (IS_WHITE(*line == ' '))
-			line++;
-		if (*line == '\0' || *line == '#')
-			continue;
-
-		len = strlen(line);
-		while (len > 0 && IS_WHITE(line[len-1]))
-			len--;
-		if (line[len] == '\\') {
-			/* line continues */
-			str_append_n(full_line, line, len - 1);
-		} else {
-			/* full line */
-			if (str_len(full_line) > 0) {
-				str_append_n(full_line, line, len);
-				line = str_c(full_line);
-			}
-
+
+		T_BEGIN {
+			line = settings_translate_lf(line);
 			ret = settings_parse_line(ctx, line);
-			if (ret == 0 &&
-			    (ctx->flags &
-			     SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS) == 0)
-				ret = -1;
-
-			if (ret < 0) {
-				ctx->error = p_strdup_printf(ctx->parser_pool,
-							     "Line %u: %s",
-							     ctx->linenum,
-							     ctx->error);
-				ret = -1;
-				break;
-			}
-			str_truncate(full_line, 0);
-		}
-	}
-	str_free(&full_line);
+		} T_END;
+		if (ret == 0 && (ctx->flags &
+				 SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS) == 0)
+			ret = -1;
+
+		if (ret < 0) {
+			ctx->error = p_strdup_printf(ctx->parser_pool,
+				"Line %u: %s", ctx->linenum, ctx->error);
+			ret = -1;
+			break;
+		}
+	}
 	return ret;
 }
 
diff -r 1d7965092e0e -r 39c2db5f1fcc src/lib-settings/settings-parser.h
--- a/src/lib-settings/settings-parser.h	Wed May 13 17:51:16 2009 -0400
+++ b/src/lib-settings/settings-parser.h	Wed May 13 19:51:34 2009 -0400
@@ -12,6 +12,9 @@ struct var_expand_table;
    the initial '1' so it'll be easy to use them. */
 #define SETTING_STRVAR_UNEXPANDED "0"
 #define SETTING_STRVAR_EXPANDED "1"
+
+/* When parsing streams, this character is translated to LF. */
+#define SETTING_STREAM_LF_CHAR "\003"
 
 enum setting_type {
 	SET_INTERNAL, /* don't set this variable */


More information about the dovecot-cvs mailing list