summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2016-03-01 21:11:42 +0100
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2016-03-01 23:42:00 +0100
commit2478dbdfba7cf729ddee43a5a77bde8c25ccdede (patch)
treebf27f2c5800f61bdffbe3d9f7bea294011293688
parent9677df8a76b314477c37b0fed7401dcfb1c268eb (diff)
Make environment.c more portable
-rw-r--r--src/src/environment.c39
-rw-r--r--src/src/readconf.c7
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