GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: environ.c,v 1.20 2017/05/11 07:34:54 nicm Exp $ */ |
||
2 |
|||
3 |
/* |
||
4 |
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> |
||
5 |
* |
||
6 |
* Permission to use, copy, modify, and distribute this software for any |
||
7 |
* purpose with or without fee is hereby granted, provided that the above |
||
8 |
* copyright notice and this permission notice appear in all copies. |
||
9 |
* |
||
10 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||
11 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||
12 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||
13 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
14 |
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
||
15 |
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
||
16 |
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||
17 |
*/ |
||
18 |
|||
19 |
#include <sys/types.h> |
||
20 |
|||
21 |
#include <stdlib.h> |
||
22 |
#include <string.h> |
||
23 |
#include <unistd.h> |
||
24 |
|||
25 |
#include "tmux.h" |
||
26 |
|||
27 |
/* |
||
28 |
* Environment - manipulate a set of environment variables. |
||
29 |
*/ |
||
30 |
|||
31 |
RB_HEAD(environ, environ_entry); |
||
32 |
static int environ_cmp(struct environ_entry *, struct environ_entry *); |
||
33 |
✓✓✓✗ ✓✓✗✓ ✓✓✓✗ ✗✓✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✓✓✗ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✗✓✗ ✓✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓✗✓✓ ✓✓ |
5956 |
RB_GENERATE_STATIC(environ, environ_entry, entry, environ_cmp); |
34 |
|||
35 |
static int |
||
36 |
environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2) |
||
37 |
{ |
||
38 |
896 |
return (strcmp(envent1->name, envent2->name)); |
|
39 |
} |
||
40 |
|||
41 |
/* Initialise the environment. */ |
||
42 |
struct environ * |
||
43 |
environ_create(void) |
||
44 |
{ |
||
45 |
struct environ *env; |
||
46 |
|||
47 |
12 |
env = xcalloc(1, sizeof *env); |
|
48 |
6 |
RB_INIT(env); |
|
49 |
|||
50 |
6 |
return (env); |
|
51 |
} |
||
52 |
|||
53 |
/* Free an environment. */ |
||
54 |
void |
||
55 |
environ_free(struct environ *env) |
||
56 |
{ |
||
57 |
struct environ_entry *envent, *envent1; |
||
58 |
|||
59 |
✓✓✓✓ |
352 |
RB_FOREACH_SAFE(envent, environ, env, envent1) { |
60 |
82 |
RB_REMOVE(environ, env, envent); |
|
61 |
82 |
free(envent->name); |
|
62 |
82 |
free(envent->value); |
|
63 |
82 |
free(envent); |
|
64 |
} |
||
65 |
6 |
free(env); |
|
66 |
6 |
} |
|
67 |
|||
68 |
struct environ_entry * |
||
69 |
environ_first(struct environ *env) |
||
70 |
{ |
||
71 |
return (RB_MIN(environ, env)); |
||
72 |
} |
||
73 |
|||
74 |
struct environ_entry * |
||
75 |
environ_next(struct environ_entry *envent) |
||
76 |
{ |
||
77 |
return (RB_NEXT(environ, env, envent)); |
||
78 |
} |
||
79 |
|||
80 |
/* Copy one environment into another. */ |
||
81 |
void |
||
82 |
environ_copy(struct environ *srcenv, struct environ *dstenv) |
||
83 |
{ |
||
84 |
struct environ_entry *envent; |
||
85 |
|||
86 |
RB_FOREACH(envent, environ, srcenv) { |
||
87 |
if (envent->value == NULL) |
||
88 |
environ_clear(dstenv, envent->name); |
||
89 |
else |
||
90 |
environ_set(dstenv, envent->name, "%s", envent->value); |
||
91 |
} |
||
92 |
} |
||
93 |
|||
94 |
/* Find an environment variable. */ |
||
95 |
struct environ_entry * |
||
96 |
environ_find(struct environ *env, const char *name) |
||
97 |
{ |
||
98 |
164 |
struct environ_entry envent; |
|
99 |
|||
100 |
82 |
envent.name = (char *) name; |
|
101 |
164 |
return (RB_FIND(environ, env, &envent)); |
|
102 |
82 |
} |
|
103 |
|||
104 |
/* Set an environment variable. */ |
||
105 |
void |
||
106 |
environ_set(struct environ *env, const char *name, const char *fmt, ...) |
||
107 |
{ |
||
108 |
struct environ_entry *envent; |
||
109 |
164 |
va_list ap; |
|
110 |
|||
111 |
82 |
va_start(ap, fmt); |
|
112 |
✗✓ | 82 |
if ((envent = environ_find(env, name)) != NULL) { |
113 |
free(envent->value); |
||
114 |
xvasprintf(&envent->value, fmt, ap); |
||
115 |
} else { |
||
116 |
82 |
envent = xmalloc(sizeof *envent); |
|
117 |
82 |
envent->name = xstrdup(name); |
|
118 |
82 |
xvasprintf(&envent->value, fmt, ap); |
|
119 |
82 |
RB_INSERT(environ, env, envent); |
|
120 |
} |
||
121 |
82 |
va_end(ap); |
|
122 |
82 |
} |
|
123 |
|||
124 |
/* Clear an environment variable. */ |
||
125 |
void |
||
126 |
environ_clear(struct environ *env, const char *name) |
||
127 |
{ |
||
128 |
struct environ_entry *envent; |
||
129 |
|||
130 |
if ((envent = environ_find(env, name)) != NULL) { |
||
131 |
free(envent->value); |
||
132 |
envent->value = NULL; |
||
133 |
} else { |
||
134 |
envent = xmalloc(sizeof *envent); |
||
135 |
envent->name = xstrdup(name); |
||
136 |
envent->value = NULL; |
||
137 |
RB_INSERT(environ, env, envent); |
||
138 |
} |
||
139 |
} |
||
140 |
|||
141 |
/* Set an environment variable from a NAME=VALUE string. */ |
||
142 |
void |
||
143 |
environ_put(struct environ *env, const char *var) |
||
144 |
{ |
||
145 |
char *name, *value; |
||
146 |
|||
147 |
152 |
value = strchr(var, '='); |
|
148 |
✗✓ | 76 |
if (value == NULL) |
149 |
return; |
||
150 |
76 |
value++; |
|
151 |
|||
152 |
76 |
name = xstrdup(var); |
|
153 |
76 |
name[strcspn(name, "=")] = '\0'; |
|
154 |
|||
155 |
76 |
environ_set(env, name, "%s", value); |
|
156 |
76 |
free(name); |
|
157 |
152 |
} |
|
158 |
|||
159 |
/* Unset an environment variable. */ |
||
160 |
void |
||
161 |
environ_unset(struct environ *env, const char *name) |
||
162 |
{ |
||
163 |
struct environ_entry *envent; |
||
164 |
|||
165 |
if ((envent = environ_find(env, name)) == NULL) |
||
166 |
return; |
||
167 |
RB_REMOVE(environ, env, envent); |
||
168 |
free(envent->name); |
||
169 |
free(envent->value); |
||
170 |
free(envent); |
||
171 |
} |
||
172 |
|||
173 |
/* Copy variables from a destination into a source * environment. */ |
||
174 |
void |
||
175 |
environ_update(struct options *oo, struct environ *src, struct environ *dst) |
||
176 |
{ |
||
177 |
struct environ_entry *envent; |
||
178 |
struct options_entry *o; |
||
179 |
u_int size, idx; |
||
180 |
const char *value; |
||
181 |
|||
182 |
o = options_get(oo, "update-environment"); |
||
183 |
if (o == NULL || options_array_size(o, &size) == -1) |
||
184 |
return; |
||
185 |
for (idx = 0; idx < size; idx++) { |
||
186 |
value = options_array_get(o, idx); |
||
187 |
if (value == NULL) |
||
188 |
continue; |
||
189 |
if ((envent = environ_find(src, value)) == NULL) |
||
190 |
environ_clear(dst, value); |
||
191 |
else |
||
192 |
environ_set(dst, envent->name, "%s", envent->value); |
||
193 |
} |
||
194 |
} |
||
195 |
|||
196 |
/* Push environment into the real environment - use after fork(). */ |
||
197 |
void |
||
198 |
environ_push(struct environ *env) |
||
199 |
{ |
||
200 |
struct environ_entry *envent; |
||
201 |
|||
202 |
environ = xcalloc(1, sizeof *environ); |
||
203 |
RB_FOREACH(envent, environ, env) { |
||
204 |
if (envent->value != NULL && *envent->name != '\0') |
||
205 |
setenv(envent->name, envent->value, 1); |
||
206 |
} |
||
207 |
} |
||
208 |
|||
209 |
/* Log the environment. */ |
||
210 |
void |
||
211 |
environ_log(struct environ *env, const char *fmt, ...) |
||
212 |
{ |
||
213 |
struct environ_entry *envent; |
||
214 |
va_list ap; |
||
215 |
char *prefix; |
||
216 |
|||
217 |
va_start(ap, fmt); |
||
218 |
vasprintf(&prefix, fmt, ap); |
||
219 |
va_end(ap); |
||
220 |
|||
221 |
RB_FOREACH(envent, environ, env) { |
||
222 |
if (envent->value != NULL && *envent->name != '\0') { |
||
223 |
log_debug("%s%s=%s", prefix, envent->name, |
||
224 |
envent->value); |
||
225 |
} |
||
226 |
} |
||
227 |
|||
228 |
free(prefix); |
||
229 |
} |
||
230 |
|||
231 |
/* Create initial environment for new child. */ |
||
232 |
struct environ * |
||
233 |
environ_for_session(struct session *s, int no_TERM) |
||
234 |
{ |
||
235 |
struct environ *env; |
||
236 |
const char *value; |
||
237 |
int idx; |
||
238 |
|||
239 |
env = environ_create(); |
||
240 |
environ_copy(global_environ, env); |
||
241 |
if (s != NULL) |
||
242 |
environ_copy(s->environ, env); |
||
243 |
|||
244 |
if (!no_TERM) { |
||
245 |
value = options_get_string(global_options, "default-terminal"); |
||
246 |
environ_set(env, "TERM", "%s", value); |
||
247 |
} |
||
248 |
|||
249 |
if (s != NULL) |
||
250 |
idx = s->id; |
||
251 |
else |
||
252 |
idx = -1; |
||
253 |
environ_set(env, "TMUX", "%s,%ld,%d", socket_path, (long)getpid(), idx); |
||
254 |
|||
255 |
return (env); |
||
256 |
} |
Generated by: GCOVR (Version 3.3) |