1 /* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, see <http://www.gnu.org/licenses/>.
18 modified for uClibc by Erik Andersen <andersen@codepoet.org>
28 #include <bits/uClibc_mutex.h>
29 __UCLIBC_MUTEX_STATIC(mylock
, PTHREAD_MUTEX_INITIALIZER
);
32 /* If this variable is not a null pointer we allocated the current
34 static char **last_environ
;
37 /* This function is used by `setenv' and `putenv'. The difference between
38 the two functions is that for the former must create a new string which
39 is then placed in the environment, while the argument of `putenv'
40 must be used directly. This is all complicated by the fact that we try
41 to reuse values once generated for a `setenv' call since we can never
42 free the strings. [in uclibc, we do not] */
43 static int __add_to_environ(const char *name
, const char *value
,
50 /* name may come from putenv() and thus may contain "=VAL" part */
51 const size_t namelen
= strchrnul(name
, '=') - name
;
54 __UCLIBC_MUTEX_LOCK(mylock
);
56 /* We have to get the pointer now that we have the lock and not earlier
57 since another thread might have created a new environment. */
63 if (!strncmp(*ep
, name
, namelen
) && (*ep
)[namelen
] == '=') {
74 /* Not found, add at the end */
76 /* We allocated this space; we can extend it. */
77 new_environ
= realloc(last_environ
, (size
+ 2) * sizeof(char *));
78 if (new_environ
== NULL
) {
79 /* __set_errno(ENOMEM); */
82 if (__environ
!= last_environ
) {
83 memcpy(new_environ
, __environ
, size
* sizeof(char *));
85 last_environ
= __environ
= new_environ
;
87 ep
= &new_environ
[size
];
88 /* Ensure env is NULL terminated in case malloc below fails */
93 var_val
= (char*) name
;
94 /* Build VAR=VAL if we called by setenv, not putenv. */
96 const size_t vallen
= strlen(value
) + 1;
98 var_val
= malloc(namelen
+ 1 + vallen
);
99 if (var_val
== NULL
) {
100 /* __set_errno(ENOMEM); */
103 memcpy(var_val
, name
, namelen
);
104 var_val
[namelen
] = '=';
105 memcpy(&var_val
[namelen
+ 1], value
, vallen
);
113 __UCLIBC_MUTEX_UNLOCK(mylock
);
117 int setenv(const char *name
, const char *value
, int replace
)
119 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
) {
124 /* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */
125 return __add_to_environ(name
, value
? value
: "", replace
);
127 libc_hidden_def(setenv
)
129 int unsetenv(const char *name
)
135 if (name
== NULL
|| *name
== '\0'
136 || *(eq
= strchrnul(name
, '=')) == '='
141 len
= eq
- name
; /* avoiding strlen this way */
143 __UCLIBC_MUTEX_LOCK(mylock
);
145 /* NB: clearenv(); unsetenv("foo"); should not segfault */
146 if (ep
) while (*ep
!= NULL
) {
147 if (!strncmp(*ep
, name
, len
) && (*ep
)[len
] == '=') {
148 /* Found it. Remove this pointer by moving later ones back. */
153 /* Continue the loop in case NAME appears again. */
158 __UCLIBC_MUTEX_UNLOCK(mylock
);
161 libc_hidden_def(unsetenv
)
163 /* The `clearenv' was planned to be added to POSIX.1 but probably
164 never made it. Nevertheless the POSIX.9 standard (POSIX bindings
165 for Fortran 77) requires this function. */
168 __UCLIBC_MUTEX_LOCK(mylock
);
169 /* If we allocated this environment we can free it.
170 * If we did not allocate this environment, it's NULL already
171 * and is safe to free(). */
174 /* Clearing environ removes the whole environment. */
176 __UCLIBC_MUTEX_UNLOCK(mylock
);
180 /* Put STRING, which is of the form "NAME=VALUE", in the environment. */
181 int putenv(char *string
)
183 if (strchr(string
, '=') != NULL
) {
184 return __add_to_environ(string
, NULL
, 1);
186 return unsetenv(string
);