dovecot-1.2: Added !include and !include_try directives to confi...

dovecot at dovecot.org dovecot at dovecot.org
Wed Nov 19 19:37:30 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/e14aabe52d8e
changeset: 8451:e14aabe52d8e
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Nov 19 19:37:26 2008 +0200
description:
Added !include and !include_try directives to config file reader.

diffstat:

1 file changed, 59 insertions(+), 14 deletions(-)
src/lib-settings/settings.c |   73 ++++++++++++++++++++++++++++++++++---------

diffs (136 lines):

diff -r f532e962f05d -r e14aabe52d8e src/lib-settings/settings.c
--- a/src/lib-settings/settings.c	Wed Nov 19 19:10:26 2008 +0200
+++ b/src/lib-settings/settings.c	Wed Nov 19 19:37:26 2008 +0200
@@ -9,7 +9,15 @@
 #include <stdio.h>
 #include <fcntl.h>
 
-#define SECTION_ERRORMSG "%s (section changed at line %d)"
+#define SECTION_ERRORMSG "%s (section changed in %s at line %d)"
+
+struct input_stack {
+	struct input_stack *prev;
+
+	struct istream *input;
+	const char *path;
+	unsigned int linenum;
+};
 
 settings_section_callback_t *null_settings_section_callback = NULL;
 
@@ -69,12 +77,13 @@ settings_read_real(const char *path, con
 		   settings_callback_t *callback,
 		   settings_section_callback_t *sect_callback, void *context)
 {
-	struct istream *input;
-	const char *errormsg, *next_section, *name;
+	/* pretty horrible code, but v2.0 will have this rewritten anyway.. */
+	struct input_stack root, *input, *new_input;
+	const char *errormsg, *next_section, *name, *last_section_path = NULL;
 	char *line, *key, *p, quote;
 	string_t *full_line;
 	size_t len;
-	int fd, linenum, last_section_line = 0, skip, sections, root_section;
+	int fd, last_section_line = 0, skip, sections, root_section;
 
 	fd = open(path, O_RDONLY);
 	if (fd < 0) {
@@ -90,12 +99,18 @@ settings_read_real(const char *path, con
 		next_section = t_strcut(section, '/');
 	}
 
+	memset(&root, 0, sizeof(root));
+	root.path = path;
+	input = &root;
+
 	full_line = t_str_new(512);
-	linenum = 0; sections = 0; root_section = 0; errormsg = NULL;
-	input = i_stream_create_fd(fd, 2048, TRUE);
-	i_stream_set_return_partial_line(input, TRUE);
-	while ((line = i_stream_read_next_line(input)) != NULL) {
-		linenum++;
+	sections = 0; root_section = 0; errormsg = NULL;
+newfile:
+	input->input = i_stream_create_fd(fd, 2048, TRUE);
+	i_stream_set_return_partial_line(input->input, TRUE);
+prevfile:
+	while ((line = i_stream_read_next_line(input->input)) != NULL) {
+		input->linenum++;
 
 		/* @UNSAFE: line is modified */
 
@@ -151,7 +166,30 @@ settings_read_real(const char *path, con
 			while (IS_WHITE(*line)) line++;
 		}
 
-		if (*line == '=') {
+		if (strcmp(key, "!include_try") == 0 ||
+		    strcmp(key, "!include") == 0) {
+			struct input_stack *tmp;
+
+			for (tmp = input; tmp != NULL; tmp = tmp->prev) {
+				if (strcmp(tmp->path, line) == 0)
+					break;
+			}
+			if (tmp != NULL) {
+				errormsg = "Recursive include";
+			} else if ((fd = open(line, O_RDONLY)) != -1) {
+				new_input = t_new(struct input_stack, 1);
+				new_input->prev = input;
+				new_input->path = t_strdup(line);
+				input = new_input;
+				goto newfile;
+			} else {
+				/* failed, but ignore failures with include_try. */
+				if (strcmp(key, "!include") == 0) {
+					errormsg = t_strdup_printf(
+						"Couldn't open include file %s: %m", line);
+				}
+			}
+		} else if (*line == '=') {
 			/* a) */
 			*line++ = '\0';
 			while (IS_WHITE(*line)) line++;
@@ -215,10 +253,12 @@ settings_read_real(const char *path, con
 						errormsg = t_strdup_printf(
 							SECTION_ERRORMSG,
 							errormsg,
+							last_section_path,
 							last_section_line);
 					}
 				}
-				last_section_line = linenum;
+				last_section_path = input->path;
+				last_section_line = input->linenum;
 			}
 		} else {
 			/* c) */
@@ -237,20 +277,25 @@ settings_read_real(const char *path, con
 						break;
 					}
 				}
-				last_section_line = linenum;
+				last_section_path = input->path;
+				last_section_line = input->linenum;
 				sections--;
 			}
 		}
 
 		if (errormsg != NULL) {
 			i_error("Error in configuration file %s line %d: %s",
-				path, linenum, errormsg);
+				input->path, input->linenum, errormsg);
 			break;
 		}
 		str_truncate(full_line, 0);
 	}
 
-	i_stream_destroy(&input);
+	i_stream_destroy(&input->input);
+	input = input->prev;
+	if (line == NULL && input != NULL)
+		goto prevfile;
+
 	return errormsg == NULL;
 }
 


More information about the dovecot-cvs mailing list