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 17:04:39 +0000 (18:04 +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)
(cherry picked from commit dd90c19962a63fe966e17c75b4a36639302d1e67)

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

index 673d2e609ba2195217585762f8b60e342d4946a6..3af82a673c5bed0bfd1f7e8f6fb41343c774a907 100644 (file)
@@ -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, USS &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, USS &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)
index 2115067d63f53cbb8367c19c8af9287b318309a4..68a65bafcd62cf2e04fd7130e4cd7c240b7cdb0f 100644 (file)
@@ -391,7 +391,7 @@ extern uschar *string_append(uschar *, int *, int *, int, ...);
 extern uschar *string_append_listele(uschar *, uschar, const uschar *);
 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(uschar *);
 extern uschar *string_copylc(const uschar *);
index 48674eca1bf275deab28d3cbcedf51ca6ee6ca27..4e7292db8a481d8e02b7a93386080406cb0b1f7a 100644 (file)
@@ -11,6 +11,9 @@ implementation of the conditional .ifdef etc. */
 
 #include "exim.h"
 
+extern char **environ;
+
+
 #define CSTATE_STACK_SIZE 10
 
 
@@ -2646,7 +2649,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++)
         {
index aeed6158f1212be1b27b4b35bce30b3251234e8c..d36548f8986587b27d78269a85a387863eaca617 100644 (file)
@@ -1641,9 +1641,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 */
 
index 437336a93612d9db846c24bba069e2a97314e89a..865fd9c041f428f919368c77779c623b518797d8 100644 (file)
@@ -138,6 +138,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
@@ -204,6 +208,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
@@ -393,6 +401,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