From: Heiko Schlittermann (HS12-RIPE) Date: Tue, 1 Mar 2016 20:11:42 +0000 (+0100) Subject: Fix portability issues on *BSD and MacOS X-Git-Tag: exim-4_86_2~1 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/dd90c19962a63fe966e17c75b4a36639302d1e67 Fix portability issues on *BSD and MacOS (cherry picked from commit 2478dbdfba7cf729ddee43a5a77bde8c25ccdede) (cherry picked from commit 84bbb4d8164aae21a8e5418250359637d8aabc29) (cherry picked from commit cdbe36e825ffdeb88da83148a866db0c9c2806e7) (cherry picked from commit de5ba17561e686e5a05c9cc88288c82b563987de) (cherry picked from commit 35a5627dc1afa9c40adc64d215821750d4932a52) --- diff --git a/src/src/environment.c b/src/src/environment.c index aaa84f817..8542dc0d2 100644 --- a/src/src/environment.c +++ b/src/src/environment.c @@ -9,6 +9,8 @@ #include "exim.h" +extern char **environ; + /* 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 +25,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/functions.h b/src/src/functions.h index 8ddf848f2..fe20b035b 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -409,7 +409,7 @@ extern uschar *string_append_listele(uschar *, uschar, const uschar *); extern uschar *string_append_listele_n(uschar *, uschar, const uschar *, unsigned); extern uschar *string_base62(unsigned long int); extern uschar *string_cat(uschar *, int *, int *, const uschar *, int); -extern int string_compare_by_pointer(const uschar **, const uschar **); +extern int string_compare_by_pointer(const void *, const void *); extern uschar *string_copy_dnsdomain(uschar *); extern uschar *string_copy_malloc(const uschar *); extern uschar *string_copylc(const uschar *); diff --git a/src/src/readconf.c b/src/src/readconf.c index 9f6954cf0..1de6bd72e 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -11,9 +11,12 @@ implementation of the conditional .ifdef etc. */ #include "exim.h" +extern char **environ; + static void fn_smtp_receive_timeout(const uschar * name, const uschar * str); + #define CSTATE_STACK_SIZE 10 @@ -2674,7 +2677,7 @@ if (type == NULL) size_t n; for (p = USS environ; *p; p++) ; n = p - USS environ; - qsort(environ, p - USS environ, sizeof(*p), (__compar_fn_t) string_compare_by_pointer); + qsort(environ, p - USS environ, sizeof(*p), string_compare_by_pointer); for (p = USS environ; *p; p++) { diff --git a/src/src/string.c b/src/src/string.c index b7e7db487..461dac56b 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -1712,9 +1712,9 @@ for -bP environment output, needs a function to compare two pointers to string pointers. Here it is. */ int -string_compare_by_pointer(const uschar **a, const uschar **b) +string_compare_by_pointer(const void *a, const void *b) { -return Ustrcmp(CUS *a, CUS *b); +return Ustrcmp(* CUSS a, * CUSS b); } #endif /* COMPILE_UTILITY */ diff --git a/test/stderr/0002 b/test/stderr/0002 index c19ce9ce3..d94e3686a 100644 --- a/test/stderr/0002 +++ b/test/stderr/0002 @@ -135,6 +135,10 @@ PWD in keep_environment? no (end of list) SHELL in keep_environment? no (end of list) TERM in keep_environment? no (end of list) USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") configuration file is TESTSUITE/test-config admin user changed uid/gid: privilege not needed @@ -199,6 +203,10 @@ PWD in keep_environment? no (end of list) SHELL in keep_environment? no (end of list) TERM in keep_environment? no (end of list) USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") configuration file is TESTSUITE/test-config admin user changed uid/gid: privilege not needed @@ -388,6 +396,10 @@ PWD in keep_environment? no (end of list) SHELL in keep_environment? no (end of list) TERM in keep_environment? no (end of list) USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") +USER in keep_environment? yes (matched "USER") configuration file is TESTSUITE/test-config admin user originator: uid=CALLER_UID gid=CALLER_GID login=CALLER name=CALLER_NAME