Coverage Report

Created: 2026-01-10 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib/env-util.c
Line
Count
Source
1
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "env-util.h"
6
7
#ifdef __APPLE__
8
#  include <crt_externs.h>
9
#endif
10
11
struct env_backup {
12
  pool_t pool;
13
  const char **strings;
14
};
15
16
void env_put(const char *name, const char *value)
17
0
{
18
0
  i_assert(strchr(name, '=') == NULL);
19
20
0
  if (setenv(name, value, 1) != 0)
21
0
    i_fatal("setenv(%s, %s) failed: %m", name, value);
22
0
}
23
24
void env_put_array(const char *const *envs)
25
0
{
26
0
  for (unsigned int i = 0; envs[i] != NULL; i++) {
27
0
    const char *value = strchr(envs[i], '=');
28
0
    i_assert(value != NULL);
29
0
    T_BEGIN {
30
0
      const char *name = t_strdup_until(envs[i], value++);
31
0
      env_put(name, value);
32
0
    } T_END;
33
0
  }
34
0
}
35
36
void env_remove(const char *name)
37
0
{
38
0
  if (unsetenv(name) < 0)
39
0
    i_fatal("unsetenv(%s) failed: %m", name);
40
0
}
41
42
void env_clean(void)
43
0
{
44
0
#ifdef HAVE_CLEARENV
45
0
  if (clearenv() < 0)
46
0
    i_fatal("clearenv() failed");
47
#else
48
  char ***environ_p = env_get_environ_p();
49
50
  /* Try to clear the environment.
51
52
     a) environ = NULL crashes on OS X.
53
     b) *environ = NULL doesn't work on FreeBSD 7.0.
54
     c) environ = emptyenv doesn't work on Haiku OS
55
     d) environ = calloc() should work everywhere
56
  */
57
  *environ_p = calloc(1, sizeof(**environ_p));
58
#endif
59
0
}
60
61
static void env_clean_except_real(const char *const preserve_envs[])
62
0
{
63
0
  ARRAY_TYPE(const_string) copy;
64
0
  const char *value, *const *envp;
65
0
  unsigned int i, count;
66
67
0
  t_array_init(&copy, 16);
68
0
  for (i = 0; preserve_envs[i] != NULL; i++) {
69
0
    const char *key = preserve_envs[i];
70
71
0
    value = getenv(key);
72
0
    if (value != NULL) {
73
0
      key = t_strdup(key);
74
0
      value = t_strdup(value);
75
0
      array_push_back(&copy, &key);
76
0
      array_push_back(&copy, &value);
77
0
    }
78
0
  }
79
80
  /* Note that if the original environment was set with env_put(), the
81
     environment strings will be invalid after env_clean(). That's why
82
     we t_strdup() them above. */
83
0
  env_clean();
84
85
0
  envp = array_get(&copy, &count);
86
0
  for (i = 0; i < count; i += 2)
87
0
    env_put(envp[i], envp[i+1]);
88
0
}
89
90
void env_clean_except(const char *const preserve_envs[])
91
0
{
92
0
  T_BEGIN {
93
0
    env_clean_except_real(preserve_envs);
94
0
  } T_END;
95
0
}
96
97
struct env_backup *env_backup_save(void)
98
0
{
99
0
  char **environ = *env_get_environ_p();
100
0
  struct env_backup *env;
101
0
  unsigned int i, count;
102
0
  pool_t pool;
103
104
0
  i_assert(environ != NULL);
105
106
0
  for (count = 0; environ[count] != NULL; count++) ;
107
108
0
  pool = pool_alloconly_create("saved environment", 4096);
109
0
  env = p_new(pool, struct env_backup, 1);
110
0
  env->pool = pool;
111
0
  env->strings = p_new(pool, const char *, count + 1);
112
0
  for (i = 0; i < count; i++)
113
0
    env->strings[i] = p_strdup(pool, environ[i]);
114
0
  return env;
115
0
}
116
117
void env_backup_restore(struct env_backup *env)
118
0
{
119
0
  env_clean();
120
0
  env_put_array(env->strings);
121
0
}
122
123
void env_backup_free(struct env_backup **_env)
124
0
{
125
0
  struct env_backup *env = *_env;
126
127
0
  *_env = NULL;
128
0
  pool_unref(&env->pool);
129
0
}
130
131
char ***env_get_environ_p(void)
132
0
{
133
#ifdef __APPLE__
134
  return _NSGetEnviron();
135
#else
136
0
  extern char **environ;
137
138
0
  return &environ;
139
0
#endif
140
0
}