dovecot-2.0: Added import_environment setting.

dovecot at dovecot.org dovecot at dovecot.org
Thu Feb 10 01:54:29 EET 2011


details:   http://hg.dovecot.org/dovecot-2.0/rev/cec7fa92ff48
changeset: 12591:cec7fa92ff48
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Feb 10 01:54:26 2011 +0200
description:
Added import_environment setting.
This also cleans up different places in code where TZ and other environments
are preserved. If it's not in the import_environment setting, it's not
preserved.

diffstat:

 src/doveadm/doveadm.c                    |   1 +
 src/lib-lda/smtp-client.c                |   2 +-
 src/lib-master/master-interface.h        |   4 ++
 src/lib-master/master-service-settings.c |  14 ++++++-
 src/lib-master/master-service-settings.h |   2 +
 src/lib-master/master-service.c          |  24 ++++-------
 src/lib-master/master-service.h          |   5 +-
 src/lib-storage/mail-storage-service.c   |   1 +
 src/master/main.c                        |  62 +++++++++++++++++--------------
 src/master/master-settings.c             |  15 +++++++
 src/master/master-settings.h             |   1 +
 src/master/service-process.c             |   6 +--
 src/master/service.c                     |   2 -
 src/master/service.h                     |   2 -
 14 files changed, 84 insertions(+), 57 deletions(-)

diffs (truncated from 358 to 300 lines):

diff -r 98f13cc1e649 -r cec7fa92ff48 src/doveadm/doveadm.c
--- a/src/doveadm/doveadm.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/doveadm/doveadm.c	Thu Feb 10 01:54:26 2011 +0200
@@ -234,6 +234,7 @@
 	memset(&input, 0, sizeof(input));
 	input.roots = set_roots;
 	input.module = "doveadm";
+	input.preserve_user = TRUE;
 	input.preserve_home = TRUE;
 	if (master_service_settings_read(master_service, &input,
 					 &output, &error) < 0)
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-lda/smtp-client.c
--- a/src/lib-lda/smtp-client.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-lda/smtp-client.c	Thu Feb 10 01:54:26 2011 +0200
@@ -51,7 +51,7 @@
 	if (dup2(fd, STDIN_FILENO) < 0)
 		i_fatal("dup2() failed: %m");
 
-	master_service_env_clean(TRUE);
+	master_service_env_clean();
 
 	execv_const(sendmail_path, argv);
 }
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-master/master-interface.h
--- a/src/lib-master/master-interface.h	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-master/master-interface.h	Thu Feb 10 01:54:26 2011 +0200
@@ -59,6 +59,10 @@
    if dovecot was started with -p parameter. */
 #define MASTER_SSL_KEY_PASSWORD_ENV "SSL_KEY_PASSWORD"
 
+/* getenv(DOVECOT_PRESERVE_ENVS_ENV) returns a space separated list of
+   environments that should be preserved. */
+#define DOVECOT_PRESERVE_ENVS_ENV "DOVECOT_PRESERVE_ENVS"
+
 /* Write pipe to anvil. */
 #define MASTER_ANVIL_FD 3
 /* Anvil reads new log fds from this fd */
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-master/master-service-settings.c
--- a/src/lib-master/master-service-settings.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-master/master-service-settings.c	Thu Feb 10 01:54:26 2011 +0200
@@ -90,12 +90,22 @@
 			   const struct master_service_settings_input *input)
 {
 	const char **conf_argv, *binary_path = service->argv[0];
+	const char *home = NULL, *user = NULL;
 	unsigned int i, argv_max_count;
 
 	(void)t_binary_abspath(&binary_path);
 
-	if (!service->keep_environment)
-		master_service_env_clean(input->preserve_home);
+	if (!service->keep_environment && !input->preserve_environment) {
+		if (input->preserve_home)
+			home = getenv("HOME");
+		if (input->preserve_user)
+			user = getenv("USER");
+		master_service_env_clean();
+		if (home != NULL)
+			env_put(t_strconcat("HOME=", home, NULL));
+		if (user != NULL)
+			env_put(t_strconcat("USER=", user, NULL));
+	}
 	if (input->use_sysexits)
 		env_put("USE_SYSEXITS=1");
 
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-master/master-service-settings.h
--- a/src/lib-master/master-service-settings.h	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-master/master-service-settings.h	Thu Feb 10 01:54:26 2011 +0200
@@ -21,6 +21,8 @@
 struct master_service_settings_input {
 	const struct setting_parser_info *const *roots;
 	const char *config_path;
+	bool preserve_environment;
+	bool preserve_user;
 	bool preserve_home;
 	bool never_exec;
 	bool use_sysexits;
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-master/master-service.c
--- a/src/lib-master/master-service.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-master/master-service.c	Thu Feb 10 01:54:26 2011 +0200
@@ -391,22 +391,16 @@
 	master_status_update(service);
 }
 
-void master_service_env_clean(bool preserve_home)
+void master_service_env_clean(void)
 {
-	static const char *preserve_envs[] = {
-		"HOME", /* keep as the first element */
-		"USER",
-		"TZ",
-#ifdef DEBUG
-		"GDB",
-#endif
-#ifdef HAVE_SYSTEMD
-		"LISTEN_PID",
-		"LISTEN_FDS",
-#endif
-		NULL
-	};
-	env_clean_except(preserve_envs + (preserve_home ? 0 : 1));
+	const char *value = getenv(DOVECOT_PRESERVE_ENVS_ENV);
+
+	if (value == NULL || *value == '\0')
+		env_clean();
+	else T_BEGIN {
+		value = t_strconcat(value, " "DOVECOT_PRESERVE_ENVS_ENV, NULL);
+		env_clean_except(t_strsplit_spaces(value, " "));
+	} T_END;
 }
 
 void master_service_set_client_limit(struct master_service *service,
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-master/master-service.h
--- a/src/lib-master/master-service.h	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-master/master-service.h	Thu Feb 10 01:54:26 2011 +0200
@@ -59,8 +59,9 @@
    before calling this. */
 void master_service_init_finish(struct master_service *service);
 
-/* Clean environment from everything except TZ, USER and optionally HOME. */
-void master_service_env_clean(bool preserve_home);
+/* Clean environment from everything except the ones listed in
+   DOVECOT_PRESERVE_ENVS environment. */
+void master_service_env_clean(void);
 
 /* Initialize logging. */
 void master_service_init_log(struct master_service *service,
diff -r 98f13cc1e649 -r cec7fa92ff48 src/lib-storage/mail-storage-service.c
--- a/src/lib-storage/mail-storage-service.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/lib-storage/mail-storage-service.c	Thu Feb 10 01:54:26 2011 +0200
@@ -652,6 +652,7 @@
 
 	memset(&set_input, 0, sizeof(set_input));
 	set_input.roots = ctx->set_roots;
+	set_input.preserve_user = TRUE;
 	/* settings reader may exec doveconf, which is going to clear
 	   environment, and if we're not doing a userdb lookup we want to
 	   use $HOME */
diff -r 98f13cc1e649 -r cec7fa92ff48 src/master/main.c
--- a/src/master/main.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/master/main.c	Thu Feb 10 01:54:26 2011 +0200
@@ -48,7 +48,6 @@
 static char *pidfile_path;
 static failure_callback_t *orig_fatal_callback;
 static failure_callback_t *orig_error_callback;
-static const char *child_process_env[3]; /* @UNSAFE */
 
 static const struct setting_parser_info *set_roots[] = {
 	&master_setting_parser_info,
@@ -314,8 +313,7 @@
 	sets = master_service_settings_get_others(master_service);
 	set = sets[0];
 
-	if (services_create(set, child_process_env,
-			    &new_services, &error) < 0) {
+	if (services_create(set, &new_services, &error) < 0) {
 		/* new configuration is invalid, keep the old */
 		i_error("Config reload failed: %s", error);
 		return;
@@ -377,12 +375,39 @@
 	input.roots = set_roots;
 	input.module = "master";
 	input.parse_full_config = TRUE;
+	input.preserve_environment = TRUE;
 	if (master_service_settings_read(master_service, &input, &output,
 					 &error) < 0)
 		i_fatal("Error reading configuration: %s", error);
 	return master_service_settings_get_others(master_service)[0];
 }
 
+static void master_set_import_environment(const struct master_settings *set)
+{
+	const char *const *envs, *key, *value;
+	ARRAY_TYPE(const_string) keys;
+
+	if (*set->import_environment == '\0')
+		return;
+
+	t_array_init(&keys, 8);
+	envs = t_strsplit_spaces(set->import_environment, " ");
+	for (; *envs != NULL; envs++) {
+		value = strchr(*envs, '=');
+		if (value == NULL)
+			key = *envs;
+		else {
+			key = t_strdup_until(*envs, value);
+			env_put(*envs);
+		}
+		array_append(&keys, &key, 1);
+	}
+	(void)array_append_space(&keys);
+
+	value = t_strarray_join(array_idx(&keys, 0), " ");
+	env_put(t_strconcat(DOVECOT_PRESERVE_ENVS_ENV"=", value, NULL));
+}
+
 static void main_log_startup(void)
 {
 #define STARTUP_STRING PACKAGE_NAME" v"DOVECOT_VERSION_FULL" starting up"
@@ -598,18 +623,8 @@
 
 int main(int argc, char *argv[])
 {
-	static const char *preserve_envs[] = {
-		/* AIX depends on TZ to get the timezone correctly. */
-		"TZ",
-#ifdef HAVE_SYSTEMD
-		"LISTEN_PID",
-		"LISTEN_FDS",
-#endif
-		NULL
-	};
 	struct master_settings *set;
-	unsigned int child_process_env_idx = 0;
-	const char *error, *env_tz, *doveconf_arg = NULL;
+	const char *error, *doveconf_arg = NULL;
 	failure_callback_t *orig_info_callback, *orig_debug_callback;
 	bool foreground = FALSE, ask_key_pass = FALSE;
 	bool doubleopts[argc];
@@ -618,8 +633,6 @@
 #ifdef DEBUG
 	if (getenv("GDB") == NULL)
 		fd_debug_verify_leaks(3, 1024);
-	else
-		child_process_env[child_process_env_idx++] = "GDB=1";
 #endif
 	/* drop -- prefix from all --args. ugly, but the only way that it
 	   works with standard getopt() in all OSes.. */
@@ -740,23 +753,16 @@
 	master_settings_do_fixes(set);
 	fatal_log_check(set);
 
-	/* clean up the environment */
-	env_clean_except(preserve_envs);
-
-	env_tz = getenv("TZ");
-	if (env_tz != NULL) {
-		child_process_env[child_process_env_idx++] =
-			t_strconcat("TZ=", env_tz, NULL);
-	}
-	i_assert(child_process_env_idx <
-		 sizeof(child_process_env) / sizeof(child_process_env[0]));
-	child_process_env[child_process_env_idx] = NULL;
+	T_BEGIN {
+		master_set_import_environment(set);
+	} T_END;
+	master_service_env_clean();
 
 	/* create service structures from settings. if there are any errors in
 	   service configuration we'll catch it here. */
 	service_pids_init();
 	service_anvil_global_init();
-	if (services_create(set, child_process_env, &services, &error) < 0)
+	if (services_create(set, &services, &error) < 0)
 		i_fatal("%s", error);
 
 	services->config->config_file_path = get_full_config_path(services);
diff -r 98f13cc1e649 -r cec7fa92ff48 src/master/master-settings.c
--- a/src/master/master-settings.c	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/master/master-settings.c	Thu Feb 10 01:54:26 2011 +0200
@@ -170,6 +170,7 @@
 static const struct setting_define master_setting_defines[] = {
 	DEF(SET_STR, base_dir),
 	DEF(SET_STR, libexec_dir),
+	DEF(SET_STR, import_environment),
 	DEF(SET_STR, protocols),
 	DEF(SET_STR, listen),
 	DEF(SET_ENUM, ssl),
@@ -192,9 +193,23 @@
 	SETTING_DEFINE_LIST_END
 };
 
+/* <settings checks> */
+#ifdef HAVE_SYSTEMD
+#  define ENV_SYSTEMD " LISTEN_PID LISTEN_FDS"
+#else
+#  define ENV_SYSTEMD ""
+#endif
+#ifdef DEBUG
+#  define ENV_GDB " GDB"
+#else
+#  define ENV_GDB ""
+#endif
+/* </settings checks> */
+
 static const struct master_settings master_default_settings = {
 	.base_dir = PKG_RUNDIR,
 	.libexec_dir = PKG_LIBEXECDIR,
+	.import_environment = "TZ" ENV_SYSTEMD ENV_GDB,
 	.protocols = "imap pop3 lmtp",
 	.listen = "*, ::",
 	.ssl = "yes:no:required",
diff -r 98f13cc1e649 -r cec7fa92ff48 src/master/master-settings.h
--- a/src/master/master-settings.h	Thu Feb 10 00:45:51 2011 +0200
+++ b/src/master/master-settings.h	Thu Feb 10 01:54:26 2011 +0200
@@ -6,6 +6,7 @@
 struct master_settings {
 	const char *base_dir;
 	const char *libexec_dir;
+	const char *import_environment;


More information about the dovecot-cvs mailing list