dovecot-1.2: dovecot.conf: Added support for !include globs.

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 27 03:59:49 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/1aec43edab2d
changeset: 9255:1aec43edab2d
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jul 26 20:58:52 2009 -0400
description:
dovecot.conf: Added support for !include globs.
Based on patch by Thomas Guthmann.

diffstat:

3 files changed, 89 insertions(+), 27 deletions(-)
configure.in                |    4 -
dovecot-example.conf        |    5 ++
src/lib-settings/settings.c |  107 ++++++++++++++++++++++++++++++++-----------

diffs (178 lines):

diff -r d6fcb6d050ba -r 1aec43edab2d configure.in
--- a/configure.in	Sun Jul 26 20:13:18 2009 -0400
+++ b/configure.in	Sun Jul 26 20:58:52 2009 -0400
@@ -304,7 +304,7 @@ AC_CHECK_HEADERS(strings.h stdint.h unis
   sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h jfs/quota.h sys/fs/quota_common.h \
   mntent.h sys/mnttab.h sys/event.h sys/time.h sys/mkdev.h linux/dqblk_xfs.h \
   xfs/xqm.h execinfo.h ucontext.h malloc_np.h sys/utsname.h sys/vmount.h \
-  sys/utsname.h)
+  sys/utsname.h glob.h)
 
 dnl * gcc specific options
 if test "x$ac_cv_c_compiler_gnu" = "xyes"; then
@@ -363,7 +363,7 @@ AC_CHECK_FUNCS(fcntl flock lockf inet_at
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
 	       strtoull strtoll strtouq strtoq \
 	       setpriority quotactl getmntent kqueue kevent backtrace_symbols \
-	       walkcontext dirfd clearenv malloc_usable_size)
+	       walkcontext dirfd clearenv malloc_usable_size glob)
 
 AC_CHECK_LIB(rt, clock_gettime, [
   AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function)
diff -r d6fcb6d050ba -r 1aec43edab2d dovecot-example.conf
--- a/dovecot-example.conf	Sun Jul 26 20:13:18 2009 -0400
+++ b/dovecot-example.conf	Sun Jul 26 20:58:52 2009 -0400
@@ -1208,3 +1208,8 @@ plugin {
   # size and vsize are available only for expunge and copy events.
   #mail_log_fields = uid box msgid size
 }
+
+# Config files can also be included:
+#!include = /etc/dovecot/conf.d/*.conf
+# Optional configurations, don't give an error if it's not found:
+#!include_try = /etc/dovecot/extra.conf
diff -r d6fcb6d050ba -r 1aec43edab2d src/lib-settings/settings.c
--- a/src/lib-settings/settings.c	Sun Jul 26 20:13:18 2009 -0400
+++ b/src/lib-settings/settings.c	Sun Jul 26 20:58:52 2009 -0400
@@ -8,6 +8,9 @@
 
 #include <stdio.h>
 #include <fcntl.h>
+#ifdef HAVE_GLOB_H
+#  include <glob.h>
+#endif
 
 #define SECTION_ERRORMSG "%s (section changed in %s at line %d)"
 
@@ -85,6 +88,79 @@ fix_relative_path(const char *path, stru
 	return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
 }
 
+static int settings_add_include(const char *path, struct input_stack **inputp,
+				bool ignore_errors, const char **error_r)
+{
+	struct input_stack *tmp, *new_input;
+	int fd;
+
+	for (tmp = *inputp; tmp != NULL; tmp = tmp->prev) {
+		if (strcmp(tmp->path, path) == 0)
+			break;
+	}
+	if (tmp != NULL) {
+		*error_r = t_strdup_printf("Recursive include file: %s", path);
+		return -1;
+	}
+
+	if ((fd = open(path, O_RDONLY)) == -1) {
+		if (ignore_errors)
+			return 0;
+
+		*error_r = t_strdup_printf("Couldn't open include file %s: %m",
+					   path);
+		return -1;
+	}
+
+	new_input = t_new(struct input_stack, 1);
+	new_input->prev = *inputp;
+	new_input->path = t_strdup(path);
+	new_input->input = i_stream_create_fd(fd, 2048, TRUE);
+	i_stream_set_return_partial_line(new_input->input, TRUE);
+	*inputp = new_input;
+	return 0;
+}
+
+static int
+settings_include(const char *pattern, struct input_stack **inputp,
+		 bool ignore_errors, const char **error_r)
+{
+#ifdef HAVE_GLOB
+	glob_t globbers;
+	unsigned int i;
+
+	switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
+	case 0:
+		break;
+	case GLOB_NOSPACE:
+		*error_r = "glob() failed: Not enough memory";
+		return -1;
+	case GLOB_ABORTED:
+		*error_r = "glob() failed: Read error";
+		return -1;
+	case GLOB_NOMATCH:
+		if (ignore_errors)
+			return 0;
+		*error_r = "No matches";
+		return -1;
+	default:
+		*error_r = "glob() failed: Unknown error";
+		return -1;
+	}
+
+	/* iterate throuth the different files matching the globbing */
+	for (i = 0; i < globbers.gl_pathc; i++) {
+		if (settings_add_include(globbers.gl_pathv[i], inputp,
+					 ignore_errors, error_r) < 0)
+			return -1;
+	}
+	globfree(&globbers);
+	return 0;
+#else
+	return settings_add_include(pattern, inputp, ignore_errors, error_r);
+#endif
+}
+
 #define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
 
 static bool
@@ -93,7 +169,7 @@ settings_read_real(const char *path, con
 		   settings_section_callback_t *sect_callback, void *context)
 {
 	/* pretty horrible code, but v2.0 will have this rewritten anyway.. */
-	struct input_stack root, *input, *new_input;
+	struct input_stack root, *input;
 	const char *errormsg, *next_section, *name, *last_section_path = NULL;
 	char *line, *key, *p, quote;
 	string_t *full_line;
@@ -120,7 +196,6 @@ settings_read_real(const char *path, con
 
 	full_line = t_str_new(512);
 	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:
@@ -183,29 +258,11 @@ prevfile:
 
 		if (strcmp(key, "!include_try") == 0 ||
 		    strcmp(key, "!include") == 0) {
-			struct input_stack *tmp;
-			const char *path;
-
-			path = fix_relative_path(line, input);
-			for (tmp = input; tmp != NULL; tmp = tmp->prev) {
-				if (strcmp(tmp->path, path) == 0)
-					break;
-			}
-			if (tmp != NULL) {
-				errormsg = "Recursive include";
-			} else if ((fd = open(path, O_RDONLY)) != -1) {
-				new_input = t_new(struct input_stack, 1);
-				new_input->prev = input;
-				new_input->path = t_strdup(path);
-				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);
-				}
-			}
+			if (settings_include(fix_relative_path(line, input),
+					     &input,
+					     strcmp(key, "!include_try") == 0,
+					     &errormsg) == 0)
+				goto prevfile;
 		} else if (*line == '=') {
 			/* a) */
 			*line++ = '\0';


More information about the dovecot-cvs mailing list