Fix portability issues on *BSD and MacOS
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Tue, 1 Mar 2016 20:11:42 +0000 (21:11 +0100)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Wed, 2 Mar 2016 16:52:58 +0000 (17:52 +0100)
(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)

src/src/environment.c
src/src/functions.h
src/src/readconf.c
src/src/string.c
test/stderr/0002

index aaa84f8172a0c9c66cfec98b1444d87931867e6f..8542dc0d265970c3509352b3f86e95e192534f44 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "exim.h"
 
 
 #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
 /* 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')
 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 */)
     {
 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)
     }
   }
 if (add_environment)
index 8ddf848f2ab3f6c6e9667910b37902b576161db8..fe20b035bc7a88b8d375229ebbbff2536e9d24ca 100644 (file)
@@ -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 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 *);
 extern uschar *string_copy_dnsdomain(uschar *);
 extern uschar *string_copy_malloc(const uschar *);
 extern uschar *string_copylc(const uschar *);
index 9f6954cf0f964ac464e68e64576acda6e56c3c02..1de6bd72e4bbe997a1e840bb62bbba4620b79d59 100644 (file)
@@ -11,9 +11,12 @@ implementation of the conditional .ifdef etc. */
 
 #include "exim.h"
 
 
 #include "exim.h"
 
+extern char **environ;
+
 static void fn_smtp_receive_timeout(const uschar * name, const uschar * str);
 
 
 static void fn_smtp_receive_timeout(const uschar * name, const uschar * str);
 
 
+
 #define CSTATE_STACK_SIZE 10
 
 
 #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;
       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++)
         {
 
       for (p = USS environ; *p; p++)
         {
index b7e7db48796064bb0570e8baf16d88c689d48506..461dac56beda5edfdb133b6932b6bbc32756f2d2 100644 (file)
@@ -1712,9 +1712,9 @@ for -bP environment output, needs a function to compare two pointers to string
 pointers. Here it is. */
 
 int
 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 */
 
 }
 #endif /* COMPILE_UTILITY */
 
index c19ce9ce3519c9cf01594359faf874482cc8d033..d94e3686ac476b0eda2203e4508c44dea6694bac 100644 (file)
@@ -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")
 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
 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")
 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
 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")
 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
 configuration file is TESTSUITE/test-config
 admin user
 originator: uid=CALLER_UID gid=CALLER_GID login=CALLER name=CALLER_NAME