Mercurial > hg > octave-kai > gnulib-hg
annotate lib/setenv.c @ 4156:99ea86c79f44
Make it possibly to simply write: #include <alloca.h>.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Fri, 10 Jan 2003 21:06:49 +0000 |
parents | d064e5107035 |
children | e58a1c05a6ba |
rev | line source |
---|---|
4156
99ea86c79f44
Make it possibly to simply write: #include <alloca.h>.
Bruno Haible <bruno@clisp.org>
parents:
4080
diff
changeset
|
1 /* Copyright (C) 1992,1995-1999,2000-2003 Free Software Foundation, Inc. |
4080 | 2 This file is part of the GNU C Library. |
574 | 3 |
4080 | 4 The GNU C Library is free software; you can redistribute it and/or |
5 modify it under the terms of the GNU Library General Public License as | |
6 published by the Free Software Foundation; either version 2 of the | |
7 License, or (at your option) any later version. | |
574 | 8 |
4080 | 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 Library General Public License for more details. | |
574 | 13 |
4080 | 14 You should have received a copy of the GNU Library General Public |
15 License along with the GNU C Library; see the file COPYING.LIB. If not, | |
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 Boston, MA 02111-1307, USA. */ | |
574 | 18 |
4080 | 19 #if HAVE_CONFIG_H |
653 | 20 # include <config.h> |
574 | 21 #endif |
22 | |
4156
99ea86c79f44
Make it possibly to simply write: #include <alloca.h>.
Bruno Haible <bruno@clisp.org>
parents:
4080
diff
changeset
|
23 #include <alloca.h> |
4080 | 24 |
574 | 25 #include <errno.h> |
4080 | 26 #if !_LIBC |
27 # if !defined errno && !defined HAVE_ERRNO_DECL | |
28 extern int errno; | |
29 # endif | |
30 # define __set_errno(ev) ((errno) = (ev)) | |
31 #endif | |
574 | 32 |
33 #if _LIBC || HAVE_STDLIB_H | |
653 | 34 # include <stdlib.h> |
574 | 35 #endif |
36 #if _LIBC || HAVE_STRING_H | |
653 | 37 # include <string.h> |
574 | 38 #endif |
39 #if _LIBC || HAVE_UNISTD_H | |
653 | 40 # include <unistd.h> |
574 | 41 #endif |
42 | |
4080 | 43 /* For those losing systems which don't have 'alloca' we have to add |
44 some additional code emulating it. */ | |
45 #if _LIBC || HAVE_ALLOCA | |
46 # define freea(p) /* nothing */ | |
47 #else | |
48 # define alloca(n) malloc (n) | |
49 # define freea(p) free (p) | |
50 #endif | |
51 | |
52 #if !_LIBC | |
2718 | 53 # define __environ environ |
4080 | 54 # ifndef HAVE_ENVIRON_DECL |
55 extern char **environ; | |
56 # endif | |
57 #endif | |
58 | |
59 #if _LIBC | |
60 /* This lock protects against simultaneous modifications of `environ'. */ | |
61 # include <bits/libc-lock.h> | |
62 __libc_lock_define_initialized (static, envlock) | |
63 # define LOCK __libc_lock_lock (envlock) | |
64 # define UNLOCK __libc_lock_unlock (envlock) | |
65 #else | |
66 # define LOCK | |
67 # define UNLOCK | |
68 #endif | |
69 | |
70 /* In the GNU C library we must keep the namespace clean. */ | |
71 #ifdef _LIBC | |
72 # define setenv __setenv | |
73 # define clearenv __clearenv | |
74 # define tfind __tfind | |
75 # define tsearch __tsearch | |
574 | 76 #endif |
77 | |
4080 | 78 /* In the GNU C library implementation we try to be more clever and |
79 allow arbitrarily many changes of the environment given that the used | |
80 values are from a small set. Outside glibc this will eat up all | |
81 memory after a while. */ | |
82 #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ | |
83 && defined __GNUC__) | |
84 # define USE_TSEARCH 1 | |
85 # include <search.h> | |
86 typedef int (*compar_fn_t) (const void *, const void *); | |
87 | |
88 /* This is a pointer to the root of the search tree with the known | |
89 values. */ | |
90 static void *known_values; | |
91 | |
92 # define KNOWN_VALUE(Str) \ | |
93 ({ \ | |
94 void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ | |
95 value != NULL ? *(char **) value : NULL; \ | |
96 }) | |
97 # define STORE_VALUE(Str) \ | |
98 tsearch (Str, &known_values, (compar_fn_t) strcmp) | |
99 | |
100 #else | |
101 # undef USE_TSEARCH | |
102 | |
103 # define KNOWN_VALUE(Str) NULL | |
104 # define STORE_VALUE(Str) do { } while (0) | |
105 | |
106 #endif | |
107 | |
108 | |
109 /* If this variable is not a null pointer we allocated the current | |
110 environment. */ | |
111 static char **last_environ; | |
112 | |
113 | |
114 /* This function is used by `setenv' and `putenv'. The difference between | |
115 the two functions is that for the former must create a new string which | |
116 is then placed in the environment, while the argument of `putenv' | |
117 must be used directly. This is all complicated by the fact that we try | |
118 to reuse values once generated for a `setenv' call since we can never | |
119 free the strings. */ | |
574 | 120 int |
4080 | 121 __add_to_environ (const char *name, const char *value, const char *combined, |
122 int replace) | |
574 | 123 { |
124 register char **ep; | |
125 register size_t size; | |
126 const size_t namelen = strlen (name); | |
4080 | 127 const size_t vallen = value != NULL ? strlen (value) + 1 : 0; |
128 | |
129 LOCK; | |
130 | |
131 /* We have to get the pointer now that we have the lock and not earlier | |
132 since another thread might have created a new environment. */ | |
133 ep = __environ; | |
574 | 134 |
135 size = 0; | |
4080 | 136 if (ep != NULL) |
137 { | |
138 for (; *ep != NULL; ++ep) | |
139 if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') | |
140 break; | |
141 else | |
142 ++size; | |
143 } | |
574 | 144 |
4080 | 145 if (ep == NULL || *ep == NULL) |
574 | 146 { |
147 char **new_environ; | |
4080 | 148 #ifdef USE_TSEARCH |
149 char *new_value; | |
150 #endif | |
574 | 151 |
4080 | 152 /* We allocated this space; we can extend it. */ |
153 new_environ = | |
154 (char **) (last_environ == NULL | |
155 ? malloc ((size + 2) * sizeof (char *)) | |
156 : realloc (last_environ, (size + 2) * sizeof (char *))); | |
574 | 157 if (new_environ == NULL) |
4080 | 158 { |
159 UNLOCK; | |
160 return -1; | |
161 } | |
162 | |
163 /* If the whole entry is given add it. */ | |
164 if (combined != NULL) | |
165 /* We must not add the string to the search tree since it belongs | |
166 to the user. */ | |
167 new_environ[size] = (char *) combined; | |
168 else | |
169 { | |
170 /* See whether the value is already known. */ | |
171 #ifdef USE_TSEARCH | |
172 new_value = (char *) alloca (namelen + 1 + vallen); | |
173 # ifdef _LIBC | |
174 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), | |
175 value, vallen); | |
176 # else | |
177 memcpy (new_value, name, namelen); | |
178 new_value[namelen] = '='; | |
179 memcpy (&new_value[namelen + 1], value, vallen); | |
180 # endif | |
574 | 181 |
4080 | 182 new_environ[size] = KNOWN_VALUE (new_value); |
183 if (new_environ[size] == NULL) | |
184 #endif | |
185 { | |
186 new_environ[size] = (char *) malloc (namelen + 1 + vallen); | |
187 if (new_environ[size] == NULL) | |
188 { | |
189 #ifdef USE_TSEARCH | |
190 freea (new_value); | |
191 #endif | |
192 __set_errno (ENOMEM); | |
193 UNLOCK; | |
194 return -1; | |
195 } | |
196 | |
197 #ifdef USE_TSEARCH | |
198 memcpy (new_environ[size], new_value, namelen + 1 + vallen); | |
199 #else | |
200 memcpy (new_environ[size], name, namelen); | |
201 new_environ[size][namelen] = '='; | |
202 memcpy (&new_environ[size][namelen + 1], value, vallen); | |
203 #endif | |
204 /* And save the value now. We cannot do this when we remove | |
205 the string since then we cannot decide whether it is a | |
206 user string or not. */ | |
207 STORE_VALUE (new_environ[size]); | |
208 } | |
209 #ifdef USE_TSEARCH | |
210 freea (new_value); | |
211 #endif | |
574 | 212 } |
213 | |
214 if (__environ != last_environ) | |
215 memcpy ((char *) new_environ, (char *) __environ, | |
216 size * sizeof (char *)); | |
217 | |
218 new_environ[size + 1] = NULL; | |
219 | |
220 last_environ = __environ = new_environ; | |
221 } | |
222 else if (replace) | |
223 { | |
4080 | 224 char *np; |
225 | |
226 /* Use the user string if given. */ | |
227 if (combined != NULL) | |
228 np = (char *) combined; | |
229 else | |
574 | 230 { |
4080 | 231 #ifdef USE_TSEARCH |
232 char *new_value = alloca (namelen + 1 + vallen); | |
233 # ifdef _LIBC | |
234 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), | |
235 value, vallen); | |
236 # else | |
237 memcpy (new_value, name, namelen); | |
238 new_value[namelen] = '='; | |
239 memcpy (&new_value[namelen + 1], value, vallen); | |
240 # endif | |
241 | |
242 np = KNOWN_VALUE (new_value); | |
243 if (np == NULL) | |
244 #endif | |
245 { | |
246 np = malloc (namelen + 1 + vallen); | |
247 if (np == NULL) | |
248 { | |
249 #ifdef USE_TSEARCH | |
250 freea (new_value); | |
251 #endif | |
252 UNLOCK; | |
253 return -1; | |
254 } | |
255 | |
256 #ifdef USE_TSEARCH | |
257 memcpy (np, new_value, namelen + 1 + vallen); | |
258 #else | |
259 memcpy (np, name, namelen); | |
260 np[namelen] = '='; | |
261 memcpy (&np[namelen + 1], value, vallen); | |
262 #endif | |
263 /* And remember the value. */ | |
264 STORE_VALUE (np); | |
265 } | |
266 #ifdef USE_TSEARCH | |
267 freea (new_value); | |
268 #endif | |
574 | 269 } |
4080 | 270 |
271 *ep = np; | |
574 | 272 } |
273 | |
4080 | 274 UNLOCK; |
275 | |
574 | 276 return 0; |
277 } | |
278 | |
4080 | 279 int |
280 setenv (const char *name, const char *value, int replace) | |
281 { | |
282 return __add_to_environ (name, value, NULL, replace); | |
283 } | |
284 | |
285 /* The `clearenv' was planned to be added to POSIX.1 but probably | |
286 never made it. Nevertheless the POSIX.9 standard (POSIX bindings | |
287 for Fortran 77) requires this function. */ | |
288 int | |
289 clearenv () | |
574 | 290 { |
4080 | 291 LOCK; |
292 | |
293 if (__environ == last_environ && __environ != NULL) | |
294 { | |
295 /* We allocated this environment so we can free it. */ | |
296 free (__environ); | |
297 last_environ = NULL; | |
298 } | |
299 | |
300 /* Clear the environment pointer removes the whole environment. */ | |
301 __environ = NULL; | |
574 | 302 |
4080 | 303 UNLOCK; |
304 | |
305 return 0; | |
574 | 306 } |
4080 | 307 |
308 #ifdef _LIBC | |
309 static void | |
310 free_mem (void) | |
311 { | |
312 /* Remove all traces. */ | |
313 clearenv (); | |
314 | |
315 /* Now remove the search tree. */ | |
316 __tdestroy (known_values, free); | |
317 known_values = NULL; | |
318 } | |
319 text_set_element (__libc_subfreeres, free_mem); | |
320 | |
321 | |
322 # undef setenv | |
323 # undef clearenv | |
324 weak_alias (__setenv, setenv) | |
325 weak_alias (__clearenv, clearenv) | |
326 #endif |