SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / environment.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) Heiko Schlittermann 2016
6  * hs@schlittermann.de
7  * See the file NOTICE for conditions of use and distribution.
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "exim.h"
12
13 extern char **environ;
14
15 /* The cleanup_environment() function is used during the startup phase
16 of the Exim process, right after reading the configurations main
17 part, before any expansions take place. It retains the environment
18 variables we trust (via the keep_environment option) and allows to
19 set additional variables (via add_environment).
20
21 Returns:    TRUE if successful
22             FALSE otherwise
23 */
24
25 BOOL
26 cleanup_environment()
27 {
28 int old_pool = store_pool;
29 store_pool = POOL_PERM;         /* Need perm memory for any created env vars */
30
31 if (!keep_environment || *keep_environment == '\0')
32   {
33   /* From: https://github.com/dovecot/core/blob/master/src/lib/env-util.c#L55
34   Try to clear the environment.
35   a) environ = NULL crashes on OS X.
36   b) *environ = NULL doesn't work on FreeBSD 7.0.
37   c) environ = emptyenv doesn't work on Haiku OS
38   d) environ = calloc() should work everywhere */
39
40   if (environ) *environ = NULL;
41
42   }
43 else if (Ustrcmp(keep_environment, "*") != 0)
44   {
45   rmark reset_point = store_mark();
46   if (environ) for (uschar ** p = USS environ; *p; /* see below */)
47     {
48     /* It's considered broken if we do not find the '=', according to
49     Florian Weimer. For now we ignore such strings. unsetenv() would complain,
50     getenv() would complain. */
51     uschar * eqp = Ustrchr(*p, '=');
52
53     if (eqp)
54       {
55       uschar * name = string_copyn(*p, eqp - *p);
56
57       if (OK != match_isinlist(name, CUSS &keep_environment,
58           0, NULL, NULL, MCL_NOEXPAND, FALSE, NULL))
59         if (os_unsetenv(name) < 0) return FALSE;
60         else p = USS environ; /* RESTART from the beginning */
61       else p++;
62       }
63     }
64   store_reset(reset_point);
65   }
66 if (add_environment)
67   {
68   uschar * p;
69   int sep = 0;
70   const uschar * envlist = add_environment;
71
72   while ((p = string_nextinlist(&envlist, &sep, NULL, 0)))
73     {
74     DEBUG(D_expand) debug_printf("adding %s\n", p);
75     putenv(CS p);
76     }
77   }
78 #ifndef DISABLE_TLS
79 tls_clean_env();
80 #endif
81
82 store_pool = old_pool;
83 return TRUE;
84 }