author | Jon Tibble <meths@btinternet.com> |
Thu, 09 Dec 2010 22:32:39 +0100 | |
changeset 13255 | 4afa820d78b9 |
parent 13105 | 48f2dbca79a2 |
permissions | -rw-r--r-- |
0 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
3864 | 5 |
* Common Development and Distribution License (the "License"). |
6 |
* You may not use this file except in compliance with the License. |
|
0 | 7 |
* |
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
3864 | 21 |
|
0 | 22 |
/* |
13105
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
23 |
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 24 |
*/ |
25 |
||
26 |
/* Copyright (c) 1988 AT&T */ |
|
27 |
/* All Rights Reserved */ |
|
28 |
||
6812 | 29 |
#pragma weak _putenv = putenv |
0 | 30 |
|
6812 | 31 |
#include "lint.h" |
0 | 32 |
#include <mtlib.h> |
33 |
#include <sys/types.h> |
|
34 |
#include <thread.h> |
|
35 |
#include <synch.h> |
|
36 |
#include <stdlib.h> |
|
37 |
#include <errno.h> |
|
38 |
#include <string.h> |
|
39 |
#include <atomic.h> |
|
40 |
||
41 |
#define MIN_ENV_SIZE 128 |
|
42 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
43 |
extern const char **_environ; |
0 | 44 |
extern void clean_env(); |
45 |
||
46 |
/* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
47 |
* For performance and consistency reasons we expand the _environ list using |
0 | 48 |
* the trusted "power of two, drop it on the floor" method. This allows for |
49 |
* a lockless, single pass implementation of getenv(), yet the memory leak |
|
50 |
* is bounded - in normal circumstances total wastage is never greater than |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
51 |
* 3x the space needed to hold any _environ list. |
0 | 52 |
* |
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
53 |
* The only abnormal circumstance is if an application modifies the _environ |
0 | 54 |
* list pointer directly. Such an application does not conform to POSIX.1 |
55 |
* 2001. However, we also care about standards which did not foresee this |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
56 |
* issue. For this reason we keep a working copy of our notion of _environ in |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
57 |
* my_environ. If, when we are called upon to modify _environ, we ever detect |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
58 |
* a mismatch between _environ and my_environ we discard all our assumptions |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
59 |
* concerning the location and size of the _environ list. As an additional |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
60 |
* precaution we only ever update _environ once we have finished manipulating |
0 | 61 |
* our working copy. |
62 |
* |
|
63 |
* The setenv() API is inherently leaky but we are completely at the mercy |
|
64 |
* of the application. |
|
65 |
* |
|
66 |
* To pacify leak detectors we chain all allocations which are at risk of |
|
67 |
* being leaked in either of the above two scenarios. chunk_list must only |
|
68 |
* be updated under the protection of update_lock. |
|
69 |
* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
70 |
* Although we don't allocate the original _environ list it is likely that |
0 | 71 |
* we will leak this too. Accordingly, we create a reference in initenv(). |
72 |
* However, we can't be held responsible for such leaks in abnormal (see |
|
73 |
* above) circumstances. |
|
74 |
*/ |
|
75 |
||
76 |
typedef struct chunk { |
|
77 |
struct chunk *next; |
|
78 |
} chunk_t; |
|
79 |
||
80 |
static mutex_t update_lock = DEFAULTMUTEX; |
|
81 |
static const char **orig_environ = NULL; |
|
82 |
static const char **my_environ = NULL; |
|
83 |
static const char **environ_base = NULL; |
|
84 |
static int environ_size = 0; |
|
85 |
static int environ_gen = 0; |
|
86 |
static int initenv_done = 0; |
|
87 |
static chunk_t *chunk_list = NULL; |
|
88 |
||
89 |
/* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
90 |
* Compute the size an _environ list including the terminating NULL entry. |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
91 |
* This is the only way we have to determine the size of an _environ list |
0 | 92 |
* we didn't allocate. |
93 |
*/ |
|
94 |
static int |
|
95 |
envsize(const char **e) |
|
96 |
{ |
|
97 |
int size; |
|
98 |
||
99 |
if (e == NULL) |
|
100 |
return (0); |
|
101 |
||
102 |
for (size = 1; *e != NULL; e++) |
|
103 |
size++; |
|
104 |
||
105 |
return (size); |
|
106 |
} |
|
107 |
||
108 |
/* |
|
109 |
* Initialization for the following scenarios: |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
110 |
* 1. The very first time we reference the _environ list we must call in the |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
111 |
* NLSPATH janitor, make a reference to the original _environ list to keep |
0 | 112 |
* leak detectors happy, initialize my_environ and environ_base, and then |
113 |
* compute environ_size. |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
114 |
* 2. Whenever we detect that someone else has hijacked _environ (something |
0 | 115 |
* very abnormal) we need to reinitialize my_environ and environ_base, |
116 |
* and then recompute environ_size. |
|
117 |
* |
|
118 |
* The local globals my_environ, environ_base and environ_size may be used |
|
119 |
* by others only if initenv_done is true and only under the protection of |
|
120 |
* update_lock. However, our callers, who must NOT be holding update_lock, |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
121 |
* may safely test initenv_done or my_environ against _environ just prior to |
0 | 122 |
* calling us because we test these again whilst holding update_lock. |
123 |
*/ |
|
124 |
static void |
|
125 |
initenv() |
|
126 |
{ |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
127 |
if ((my_environ != _environ) || !initenv_done) { |
3864 | 128 |
lmutex_lock(&update_lock); |
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
129 |
if ((my_environ != _environ) || !initenv_done) { |
3864 | 130 |
if (!initenv_done) { |
131 |
/* Call the NLSPATH janitor in. */ |
|
132 |
clean_env(); |
|
0 | 133 |
|
3864 | 134 |
/* Pacify leak detectors in normal operation. */ |
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
135 |
orig_environ = _environ; |
0 | 136 |
#ifdef __lint |
3864 | 137 |
my_environ = orig_environ; |
0 | 138 |
#endif |
3864 | 139 |
} |
0 | 140 |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
141 |
my_environ = _environ; |
3864 | 142 |
environ_base = my_environ; |
143 |
environ_size = envsize(environ_base); |
|
144 |
membar_producer(); |
|
0 | 145 |
initenv_done = 1; |
146 |
} |
|
3864 | 147 |
lmutex_unlock(&update_lock); |
0 | 148 |
} |
3864 | 149 |
membar_consumer(); |
0 | 150 |
} |
151 |
||
152 |
/* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
153 |
* Search an _environ list for a particular entry. If name_only is set, then |
0 | 154 |
* string must be the entry name only, and we return the value of the first |
155 |
* match. Otherwise, string must be of the form "name=value", and we return |
|
156 |
* the address of the first matching entry. |
|
157 |
*/ |
|
158 |
static const char ** |
|
159 |
findenv(const char **e, const char *string, int name_only, char **value) |
|
160 |
{ |
|
161 |
char target; |
|
162 |
const char *s1; |
|
163 |
const char *s2; |
|
164 |
||
165 |
*value = NULL; |
|
166 |
||
167 |
if (e == NULL) |
|
168 |
return (NULL); |
|
169 |
||
170 |
target = name_only ? '\0' : '='; |
|
171 |
||
172 |
for (; (s2 = *e) != NULL; e++) { |
|
173 |
s1 = string; |
|
174 |
||
175 |
/* Fast comparison for first char. */ |
|
176 |
if (*s1 != *s2) |
|
177 |
continue; |
|
178 |
||
179 |
/* Slow comparison for rest of string. */ |
|
180 |
while (*s1 == *s2 && *s2 != '=') { |
|
181 |
s1++; |
|
182 |
s2++; |
|
183 |
} |
|
184 |
||
185 |
if (*s1 == target && *s2 == '=') { |
|
186 |
*value = (char *)s2 + 1; |
|
187 |
return (e); |
|
188 |
} |
|
189 |
} |
|
190 |
return (NULL); |
|
191 |
} |
|
192 |
||
193 |
/* |
|
194 |
* Common code for putenv() and setenv(). We support the lockless getenv() |
|
195 |
* by inserting new entries at the bottom of the list, and by growing the |
|
196 |
* list using the trusted "power of two, drop it on the floor" method. We |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
197 |
* use a lock (update_lock) to protect all updates to the _environ list, but |
0 | 198 |
* we are obliged to release this lock whenever we call malloc() or free(). |
199 |
* A generation number (environ_gen) is bumped whenever names are added to, |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
200 |
* or removed from, the _environ list so that we can detect collisions with |
0 | 201 |
* other updaters. |
202 |
* |
|
203 |
* Return values |
|
204 |
* 0 : success |
|
205 |
* -1 : with errno set |
|
206 |
* -2 : an entry already existed and overwrite was zero |
|
207 |
*/ |
|
208 |
static int |
|
209 |
addtoenv(char *string, int overwrite) |
|
210 |
{ |
|
211 |
char *value; |
|
212 |
const char **p; |
|
213 |
chunk_t *new_chunk; |
|
214 |
const char **new_environ; |
|
215 |
const char **new_base; |
|
216 |
int new_size; |
|
217 |
int old_gen; |
|
218 |
||
3864 | 219 |
initenv(); |
0 | 220 |
|
221 |
lmutex_lock(&update_lock); |
|
222 |
||
223 |
for (;;) { |
|
224 |
/* |
|
225 |
* If the name already exists just overwrite the existing |
|
226 |
* entry -- except when we were called by setenv() without |
|
227 |
* the overwrite flag. |
|
228 |
*/ |
|
229 |
if ((p = findenv(my_environ, string, 0, &value)) != NULL) { |
|
230 |
if (overwrite) { |
|
231 |
/* |
|
232 |
* Replace the value in situ. No name was |
|
233 |
* added, so there is no need to bump the |
|
234 |
* generation number. |
|
235 |
*/ |
|
236 |
*p = string; |
|
237 |
lmutex_unlock(&update_lock); |
|
238 |
return (0); |
|
239 |
} else { |
|
240 |
/* No change. */ |
|
241 |
lmutex_unlock(&update_lock); |
|
242 |
return (-2); |
|
243 |
} |
|
244 |
} |
|
245 |
||
246 |
/* Try to insert the new entry at the bottom of the list. */ |
|
247 |
if (environ_base < my_environ) { |
|
248 |
/* |
|
249 |
* The new value must be visible before we decrement |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
250 |
* the _environ list pointer. |
0 | 251 |
*/ |
252 |
my_environ[-1] = string; |
|
253 |
membar_producer(); |
|
254 |
my_environ--; |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
255 |
_environ = my_environ; |
0 | 256 |
|
257 |
/* |
|
258 |
* We've added a name, so bump the generation number. |
|
259 |
*/ |
|
260 |
environ_gen++; |
|
261 |
||
262 |
lmutex_unlock(&update_lock); |
|
263 |
return (0); |
|
264 |
} |
|
265 |
||
266 |
/* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
267 |
* There is no room. Attempt to allocate a new _environ list |
0 | 268 |
* which is at least double the size of the current one. See |
269 |
* comment above concerning locking and malloc() etc. |
|
270 |
*/ |
|
271 |
new_size = environ_size * 2; |
|
272 |
if (new_size < MIN_ENV_SIZE) |
|
273 |
new_size = MIN_ENV_SIZE; |
|
274 |
||
275 |
old_gen = environ_gen; |
|
276 |
lmutex_unlock(&update_lock); |
|
277 |
||
278 |
new_chunk = malloc(sizeof (chunk_t) + |
|
279 |
new_size * sizeof (char *)); |
|
280 |
if (new_chunk == NULL) { |
|
281 |
errno = ENOMEM; |
|
282 |
return (-1); |
|
283 |
} |
|
284 |
||
285 |
lmutex_lock(&update_lock); |
|
286 |
||
287 |
/* |
|
288 |
* If no other thread added or removed names while the lock |
|
289 |
* was dropped, it is time to break out of this loop. |
|
290 |
*/ |
|
291 |
if (environ_gen == old_gen) |
|
292 |
break; |
|
293 |
||
294 |
/* |
|
295 |
* At least one name has been added or removed, so we need to |
|
296 |
* try again. It is very likely that we will find sufficient |
|
297 |
* space the next time around. |
|
298 |
*/ |
|
299 |
lmutex_unlock(&update_lock); |
|
300 |
free(new_chunk); |
|
301 |
lmutex_lock(&update_lock); |
|
302 |
} |
|
303 |
||
304 |
/* Add the new chunk to chunk_list to hide potential future leak. */ |
|
305 |
new_chunk->next = chunk_list; |
|
306 |
chunk_list = new_chunk; |
|
307 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
308 |
/* Copy the old _environ list into the top of the new _environ list. */ |
0 | 309 |
new_base = (const char **)(new_chunk + 1); |
310 |
new_environ = &new_base[(new_size - 1) - environ_size]; |
|
311 |
(void) memcpy(new_environ, my_environ, environ_size * sizeof (char *)); |
|
312 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
313 |
/* Insert the new entry at the bottom of the new _environ list. */ |
0 | 314 |
new_environ[-1] = string; |
315 |
new_environ--; |
|
316 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
317 |
/* Ensure that the new _environ list is visible to all. */ |
0 | 318 |
membar_producer(); |
319 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
320 |
/* Make the switch (dropping the old _environ list on the floor). */ |
0 | 321 |
environ_base = new_base; |
322 |
my_environ = new_environ; |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
323 |
_environ = my_environ; |
0 | 324 |
environ_size = new_size; |
325 |
||
326 |
/* We've added a name, so bump the generation number. */ |
|
327 |
environ_gen++; |
|
328 |
||
329 |
lmutex_unlock(&update_lock); |
|
330 |
return (0); |
|
331 |
} |
|
332 |
||
333 |
/* |
|
334 |
* All the work for putenv() is done in addtoenv(). |
|
335 |
*/ |
|
336 |
int |
|
337 |
putenv(char *string) |
|
338 |
{ |
|
339 |
return (addtoenv(string, 1)); |
|
340 |
} |
|
341 |
||
342 |
/* |
|
343 |
* setenv() is a little more complex than putenv() because we have to allocate |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
344 |
* and construct an _environ entry on behalf of the caller. The bulk of the |
0 | 345 |
* work is still done in addtoenv(). |
346 |
*/ |
|
347 |
||
348 |
int |
|
349 |
setenv(const char *envname, const char *envval, int overwrite) |
|
350 |
{ |
|
351 |
chunk_t *new_chunk; |
|
352 |
char *new_string; |
|
353 |
size_t name_len; |
|
354 |
size_t val_len; |
|
355 |
int res; |
|
356 |
||
357 |
if (envname == NULL || *envname == 0 || strchr(envname, '=') != NULL) { |
|
358 |
errno = EINVAL; |
|
359 |
return (-1); |
|
360 |
} |
|
361 |
||
362 |
name_len = strlen(envname); |
|
363 |
val_len = strlen(envval); |
|
364 |
||
365 |
new_chunk = malloc(sizeof (chunk_t) + name_len + val_len + 2); |
|
366 |
if (new_chunk == NULL) { |
|
367 |
errno = ENOMEM; |
|
368 |
return (-1); |
|
369 |
} |
|
370 |
new_string = (char *)(new_chunk + 1); |
|
371 |
||
372 |
(void) memcpy(new_string, envname, name_len); |
|
373 |
new_string[name_len] = '='; |
|
374 |
(void) memcpy(new_string + name_len + 1, envval, val_len); |
|
375 |
new_string[name_len + 1 + val_len] = 0; |
|
376 |
||
377 |
if ((res = addtoenv(new_string, overwrite)) < 0) { |
|
378 |
free(new_chunk); |
|
379 |
if (res == -2) { |
|
380 |
/* The name already existed, but not an error. */ |
|
381 |
return (0); |
|
382 |
} else { |
|
383 |
/* i.e. res == -1 which means only one thing. */ |
|
384 |
errno = ENOMEM; |
|
385 |
return (-1); |
|
386 |
} |
|
387 |
} |
|
388 |
||
389 |
/* Hide potential leak of new_string. */ |
|
390 |
lmutex_lock(&update_lock); |
|
391 |
new_chunk->next = chunk_list; |
|
392 |
chunk_list = new_chunk; |
|
393 |
lmutex_unlock(&update_lock); |
|
394 |
||
395 |
return (0); |
|
396 |
} |
|
397 |
||
398 |
/* |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
399 |
* unsetenv() is tricky because we need to compress the _environ list in a way |
0 | 400 |
* which supports a lockless getenv(). The approach here is to move the first |
401 |
* entry from the enrivon list into the space occupied by the entry to be |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
402 |
* deleted, and then to increment _environ. This has the added advantage of |
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
403 |
* making _any_ incremental linear search of the _environ list consistent (i.e. |
0 | 404 |
* we will not break any naughty apps which read the list without our help). |
405 |
*/ |
|
406 |
int |
|
407 |
unsetenv(const char *name) |
|
408 |
{ |
|
409 |
const char **p; |
|
410 |
char *value; |
|
411 |
||
412 |
if (name == NULL || *name == 0 || strchr(name, '=') != NULL) { |
|
413 |
errno = EINVAL; |
|
414 |
return (-1); |
|
415 |
} |
|
416 |
||
3864 | 417 |
initenv(); |
0 | 418 |
|
419 |
lmutex_lock(&update_lock); |
|
420 |
||
421 |
/* |
|
422 |
* Find the target, overwrite it with the first entry, increment the |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
423 |
* _environ pointer. |
0 | 424 |
*/ |
425 |
if ((p = findenv(my_environ, name, 1, &value)) != NULL) { |
|
426 |
/* Overwrite target with the first entry. */ |
|
427 |
*p = my_environ[0]; |
|
428 |
||
429 |
/* Ensure that the moved entry is visible to all. */ |
|
430 |
membar_producer(); |
|
431 |
||
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
432 |
/* Shrink the _environ list. */ |
0 | 433 |
my_environ++; |
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
434 |
_environ = my_environ; |
0 | 435 |
|
436 |
/* Make sure addtoenv() knows that we've removed a name. */ |
|
437 |
environ_gen++; |
|
438 |
} |
|
439 |
||
440 |
lmutex_unlock(&update_lock); |
|
441 |
return (0); |
|
442 |
} |
|
443 |
||
444 |
/* |
|
13105
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
445 |
* Dump entire environment. |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
446 |
*/ |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
447 |
int |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
448 |
clearenv(void) |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
449 |
{ |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
450 |
/* |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
451 |
* Just drop the entire environment list on the floor, as it |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
452 |
* would be non-trivial to try and free the used memory. |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
453 |
*/ |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
454 |
static const char *nullp = NULL; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
455 |
|
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
456 |
lmutex_lock(&update_lock); |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
457 |
_environ = &nullp; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
458 |
my_environ = NULL; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
459 |
environ_base = NULL; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
460 |
environ_size = 0; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
461 |
environ_gen++; |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
462 |
membar_producer(); |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
463 |
lmutex_unlock(&update_lock); |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
464 |
|
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
465 |
return (0); |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
466 |
} |
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
467 |
|
48f2dbca79a2
PSARC 2010/299 GNU/Linux/BSD compatibility functions
Roger A. Faulkner <Roger.Faulkner@Oracle.COM>
parents:
6879
diff
changeset
|
468 |
/* |
0 | 469 |
* At last, a lockless implementation of getenv()! |
470 |
*/ |
|
471 |
char * |
|
472 |
getenv(const char *name) |
|
473 |
{ |
|
474 |
char *value; |
|
475 |
||
3864 | 476 |
initenv(); |
0 | 477 |
|
6879
150dcecba680
6714179 libc synonym expunging in snv_92 was too aggressive, breaking pfinstall
raf
parents:
6812
diff
changeset
|
478 |
if (findenv(_environ, name, 1, &value) != NULL) |
0 | 479 |
return (value); |
480 |
||
481 |
return (NULL); |
|
482 |
} |