From 2478dbdfba7cf729ddee43a5a77bde8c25ccdede Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Tue, 1 Mar 2016 21:11:42 +0100 Subject: [PATCH] Make environment.c more portable --- src/src/environment.c | 39 +++++++++++++++++++++++++++++---------- src/src/readconf.c | 7 +++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/src/environment.c b/src/src/environment.c index aaa84f817..c41d19eba 100644 --- a/src/src/environment.c +++ b/src/src/environment.c @@ -9,6 +9,10 @@ #include "exim.h" +#ifndef environ +extern char **environ; +#endif + /* The cleanup_environment() function is used during the startup phase of the Exim process, right after reading the configurations main part, before any expansions take place. It retains the environment @@ -23,22 +27,37 @@ BOOL cleanup_environment() { if (!keep_environment || *keep_environment == '\0') - clearenv(); + { + /* From: https://github.com/dovecot/core/blob/master/src/lib/env-util.c#L55 + Try to clear the environment. + a) environ = NULL crashes on OS X. + b) *environ = NULL doesn't work on FreeBSD 7.0. + c) environ = emptyenv doesn't work on Haiku OS + d) environ = calloc() should work everywhere */ + + if (environ) *environ = NULL; + + } else if (Ustrcmp(keep_environment, "*") != 0) { uschar **p; if (environ) for (p = USS environ; *p; /* see below */) { - uschar *name = string_copyn(*p, US Ustrchr(*p, '=') - *p); - - if (OK != match_isinlist(name, CUSS &keep_environment, - 0, NULL, NULL, MCL_NOEXPAND, FALSE, NULL)) - if (unsetenv(CS name) < 0) return FALSE; - else /* nothing */; - else - p++; + /* It's considered broken if we do not find the '=', according to + Florian Weimer. For now we ignore such strings. unsetenv() would complain, + getenv() would complain. */ + uschar *eqp = Ustrchr(*p, '='); - store_reset(name); + if (eqp) + { + uschar *name = string_copyn(*p, eqp - *p); + if (OK != match_isinlist(name, CUSS &keep_environment, + 0, NULL, NULL, MCL_NOEXPAND, FALSE, NULL)) + if (unsetenv(CS name) < 0) return FALSE; + else p = USS environ; /* RESTART from the beginning */ + else p++; + store_reset(name); + } } } if (add_environment) diff --git a/src/src/readconf.c b/src/src/readconf.c index cf5f069e9..92160c8f2 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -15,6 +15,13 @@ static void fn_smtp_receive_timeout(const uschar * name, const uschar * str); static void save_config_line(const uschar* line); static void save_config_position(const uschar *file, int line); static void print_config(BOOL admin); +/* glibc seems to define environ as a macro, we can use this to check +it's existence. And, if we declare environ a 2nd time, it shouldn't +harm */ +#ifndef environ +extern char **environ; +#endif + #define CSTATE_STACK_SIZE 10 -- 2.30.2