Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/setenv.c @ 7302:8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
longer worry about uses that don't define HAVE_CONFIG_H.
* acl.c, alloca.c, argmatch.c, atexit.c, backupfile.c:
* basename.c, c-stack.c, c-strtod.c, calloc.c, canon-host.c:
* canonicalize.c, chdir-long.c, chdir-safer.c, chown.c:
* cloexec.c, close-stream.c, closeout.c, creat-safer.c:
* cycle-check.c, diacrit.c, dirchownmod.c, dirfd.c, dirname.c:
* dup-safer.c, dup2.c, error.c, euidaccess.c, exclude.c:
* exitfail.c, fchmodat.c, fchown-stub.c, fd-safer.c:
* file-type.c, fileblocks.c, filemode.c, filenamecat.c:
* fnmatch.c, fopen-safer.c, fprintftime.c, free.c, fsusage.c:
* ftruncate.c, fts-cycle.c, fts.c, full-write.c, gai_strerror.c:
* getcwd.c, getdate.y, getdomainname.c, getgroups.c:
* gethostname.c, gethrxtime.c, getloadavg.c, getlogin_r.c:
* getndelim2.c, getnline.c, getopt.c, getopt1.c, getpass.c:
* gettime.c, gettimeofday.c, getugroups.c, getusershell.c:
* glob.c, group-member.c, hard-locale.c, hash-pjw.c, hash.c:
* human.c, idcache.c, inet_ntop.c, inet_pton.c, inttostr.c:
* isdir.c, lchown.c, linebuffer.c, long-options.c, lstat.c:
* malloc.c, md5.c, memcasecmp.c, memchr.c, memcmp.c, memcoll.c:
* memcpy.c, memmove.c, memrchr.c, mkancesdirs.c, mkdir-p.c:
* mkdir.c, mkdirat.c, mkstemp-safer.c, mkstemp.c, modechange.c:
* mountlist.c, nanosleep.c, obstack.c, open-safer.c:
* openat-die.c, openat.c, pagealign_alloc.c, physmem.c:
* pipe-safer.c, posixtm.c, posixver.c, putenv.c, quote.c:
* quotearg.c, raise.c, readtokens.c, readtokens0.c, readutmp.c:
* realloc.c, regex.c, rename.c, rmdir.c, rpmatch.c, safe-read.c:
* same.c, save-cwd.c, savedir.c, setenv.c, settime.c, sha1.c:
* sig2str.c, snprintf.c, strdup.c, strerror.c, strftime.c:
* stripslash.c, strndup.c, strnlen.c, strpbrk.c, strtod.c:
* strtoimax.c, strtol.c, strverscmp.c, tempname.c, time_r.c:
* timegm.c, tmpfile-safer.c, unlinkdir.c, userspec.c, utime.c:
* utimecmp.c, utimens.c, version-etc-fsf.c, version-etc.c:
* xalloc-die.c, xgetcwd.c, xgethostname.c, xmalloc.c:
* xmemcoll.c, xnanosleep.c, xreadlink.c, xstrtod.c:
* xstrtoimax.c, xstrtol.c, xstrtoumax.c, yesno.c:
Likewise.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Wed, 13 Sep 2006 22:38:14 +0000 |
parents | 75561a6a4a30 |
children | 330dcd891960 |
rev | line source |
---|---|
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7074
diff
changeset
|
1 /* Copyright (C) 1992,1995-1999,2000-2003,2005,2006 Free Software Foundation, Inc. |
4080 | 2 This file is part of the GNU C Library. |
574 | 3 |
4440
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
4 This program is free software; you can redistribute it and/or modify |
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
5 it under the terms of the GNU General Public License as published by |
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
6 the Free Software Foundation; either version 2, or (at your option) |
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
7 any later version. |
574 | 8 |
4440
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
9 This program is distributed in the hope that it will be useful, |
4080 | 10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
4440
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
12 GNU General Public License for more details. |
574 | 13 |
4440
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
14 You should have received a copy of the GNU General Public License along |
e58a1c05a6ba
Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents:
4156
diff
changeset
|
15 with this program; if not, write to the Free Software Foundation, |
6711 | 16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ |
574 | 17 |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7074
diff
changeset
|
18 #if !_LIBC |
653 | 19 # include <config.h> |
574 | 20 #endif |
4156
99ea86c79f44
Make it possibly to simply write: #include <alloca.h>.
Bruno Haible <bruno@clisp.org>
parents:
4080
diff
changeset
|
21 #include <alloca.h> |
4080 | 22 |
574 | 23 #include <errno.h> |
5159 | 24 #ifndef __set_errno |
4080 | 25 # define __set_errno(ev) ((errno) = (ev)) |
26 #endif | |
574 | 27 |
4683
4452e4c45cc4
Assume ANSI C <string.h>, <stdlib.h>.
Bruno Haible <bruno@clisp.org>
parents:
4440
diff
changeset
|
28 #include <stdlib.h> |
4452e4c45cc4
Assume ANSI C <string.h>, <stdlib.h>.
Bruno Haible <bruno@clisp.org>
parents:
4440
diff
changeset
|
29 #include <string.h> |
7074
75561a6a4a30
setenv.c comes from gettext / libiconv again.
Bruno Haible <bruno@clisp.org>
parents:
6711
diff
changeset
|
30 #if _LIBC || HAVE_UNISTD_H |
75561a6a4a30
setenv.c comes from gettext / libiconv again.
Bruno Haible <bruno@clisp.org>
parents:
6711
diff
changeset
|
31 # include <unistd.h> |
75561a6a4a30
setenv.c comes from gettext / libiconv again.
Bruno Haible <bruno@clisp.org>
parents:
6711
diff
changeset
|
32 #endif |
574 | 33 |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
34 #if !_LIBC |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
35 # include "allocsa.h" |
4080 | 36 #endif |
37 | |
38 #if !_LIBC | |
2718 | 39 # define __environ environ |
4080 | 40 # ifndef HAVE_ENVIRON_DECL |
41 extern char **environ; | |
42 # endif | |
43 #endif | |
44 | |
45 #if _LIBC | |
46 /* This lock protects against simultaneous modifications of `environ'. */ | |
47 # include <bits/libc-lock.h> | |
48 __libc_lock_define_initialized (static, envlock) | |
49 # define LOCK __libc_lock_lock (envlock) | |
50 # define UNLOCK __libc_lock_unlock (envlock) | |
51 #else | |
52 # define LOCK | |
53 # define UNLOCK | |
54 #endif | |
55 | |
56 /* In the GNU C library we must keep the namespace clean. */ | |
57 #ifdef _LIBC | |
58 # define setenv __setenv | |
59 # define clearenv __clearenv | |
60 # define tfind __tfind | |
61 # define tsearch __tsearch | |
574 | 62 #endif |
63 | |
4080 | 64 /* In the GNU C library implementation we try to be more clever and |
65 allow arbitrarily many changes of the environment given that the used | |
66 values are from a small set. Outside glibc this will eat up all | |
67 memory after a while. */ | |
68 #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ | |
69 && defined __GNUC__) | |
70 # define USE_TSEARCH 1 | |
71 # include <search.h> | |
72 typedef int (*compar_fn_t) (const void *, const void *); | |
73 | |
74 /* This is a pointer to the root of the search tree with the known | |
75 values. */ | |
76 static void *known_values; | |
77 | |
78 # define KNOWN_VALUE(Str) \ | |
79 ({ \ | |
80 void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ | |
81 value != NULL ? *(char **) value : NULL; \ | |
82 }) | |
83 # define STORE_VALUE(Str) \ | |
84 tsearch (Str, &known_values, (compar_fn_t) strcmp) | |
85 | |
86 #else | |
87 # undef USE_TSEARCH | |
88 | |
89 # define KNOWN_VALUE(Str) NULL | |
90 # define STORE_VALUE(Str) do { } while (0) | |
91 | |
92 #endif | |
93 | |
94 | |
95 /* If this variable is not a null pointer we allocated the current | |
96 environment. */ | |
97 static char **last_environ; | |
98 | |
99 | |
100 /* This function is used by `setenv' and `putenv'. The difference between | |
101 the two functions is that for the former must create a new string which | |
102 is then placed in the environment, while the argument of `putenv' | |
103 must be used directly. This is all complicated by the fact that we try | |
104 to reuse values once generated for a `setenv' call since we can never | |
105 free the strings. */ | |
574 | 106 int |
4080 | 107 __add_to_environ (const char *name, const char *value, const char *combined, |
108 int replace) | |
574 | 109 { |
110 register char **ep; | |
111 register size_t size; | |
112 const size_t namelen = strlen (name); | |
4080 | 113 const size_t vallen = value != NULL ? strlen (value) + 1 : 0; |
114 | |
115 LOCK; | |
116 | |
117 /* We have to get the pointer now that we have the lock and not earlier | |
118 since another thread might have created a new environment. */ | |
119 ep = __environ; | |
574 | 120 |
121 size = 0; | |
4080 | 122 if (ep != NULL) |
123 { | |
124 for (; *ep != NULL; ++ep) | |
125 if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') | |
126 break; | |
127 else | |
128 ++size; | |
129 } | |
574 | 130 |
4080 | 131 if (ep == NULL || *ep == NULL) |
574 | 132 { |
133 char **new_environ; | |
4080 | 134 #ifdef USE_TSEARCH |
135 char *new_value; | |
136 #endif | |
574 | 137 |
4080 | 138 /* We allocated this space; we can extend it. */ |
139 new_environ = | |
140 (char **) (last_environ == NULL | |
141 ? malloc ((size + 2) * sizeof (char *)) | |
142 : realloc (last_environ, (size + 2) * sizeof (char *))); | |
574 | 143 if (new_environ == NULL) |
4080 | 144 { |
145 UNLOCK; | |
146 return -1; | |
147 } | |
148 | |
149 /* If the whole entry is given add it. */ | |
150 if (combined != NULL) | |
151 /* We must not add the string to the search tree since it belongs | |
152 to the user. */ | |
153 new_environ[size] = (char *) combined; | |
154 else | |
155 { | |
156 /* See whether the value is already known. */ | |
157 #ifdef USE_TSEARCH | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
158 # ifdef _LIBC |
4080 | 159 new_value = (char *) alloca (namelen + 1 + vallen); |
160 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), | |
161 value, vallen); | |
162 # else | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
163 new_value = (char *) allocsa (namelen + 1 + vallen); |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
164 if (new_value == NULL) |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
165 { |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
166 __set_errno (ENOMEM); |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
167 UNLOCK; |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
168 return -1; |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
169 } |
4080 | 170 memcpy (new_value, name, namelen); |
171 new_value[namelen] = '='; | |
172 memcpy (&new_value[namelen + 1], value, vallen); | |
173 # endif | |
574 | 174 |
4080 | 175 new_environ[size] = KNOWN_VALUE (new_value); |
176 if (new_environ[size] == NULL) | |
177 #endif | |
178 { | |
179 new_environ[size] = (char *) malloc (namelen + 1 + vallen); | |
180 if (new_environ[size] == NULL) | |
181 { | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
182 #if defined USE_TSEARCH && !defined _LIBC |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
183 freesa (new_value); |
4080 | 184 #endif |
185 __set_errno (ENOMEM); | |
186 UNLOCK; | |
187 return -1; | |
188 } | |
189 | |
190 #ifdef USE_TSEARCH | |
191 memcpy (new_environ[size], new_value, namelen + 1 + vallen); | |
192 #else | |
193 memcpy (new_environ[size], name, namelen); | |
194 new_environ[size][namelen] = '='; | |
195 memcpy (&new_environ[size][namelen + 1], value, vallen); | |
196 #endif | |
197 /* And save the value now. We cannot do this when we remove | |
198 the string since then we cannot decide whether it is a | |
199 user string or not. */ | |
200 STORE_VALUE (new_environ[size]); | |
201 } | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
202 #if defined USE_TSEARCH && !defined _LIBC |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
203 freesa (new_value); |
4080 | 204 #endif |
574 | 205 } |
206 | |
207 if (__environ != last_environ) | |
208 memcpy ((char *) new_environ, (char *) __environ, | |
209 size * sizeof (char *)); | |
210 | |
211 new_environ[size + 1] = NULL; | |
212 | |
213 last_environ = __environ = new_environ; | |
214 } | |
215 else if (replace) | |
216 { | |
4080 | 217 char *np; |
218 | |
219 /* Use the user string if given. */ | |
220 if (combined != NULL) | |
221 np = (char *) combined; | |
222 else | |
574 | 223 { |
4080 | 224 #ifdef USE_TSEARCH |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
225 char *new_value; |
4080 | 226 # ifdef _LIBC |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
227 new_value = alloca (namelen + 1 + vallen); |
4080 | 228 __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), |
229 value, vallen); | |
230 # else | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
231 new_value = allocsa (namelen + 1 + vallen); |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
232 if (new_value == NULL) |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
233 { |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
234 __set_errno (ENOMEM); |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
235 UNLOCK; |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
236 return -1; |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
237 } |
4080 | 238 memcpy (new_value, name, namelen); |
239 new_value[namelen] = '='; | |
240 memcpy (&new_value[namelen + 1], value, vallen); | |
241 # endif | |
242 | |
243 np = KNOWN_VALUE (new_value); | |
244 if (np == NULL) | |
245 #endif | |
246 { | |
247 np = malloc (namelen + 1 + vallen); | |
248 if (np == NULL) | |
249 { | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
250 #if defined USE_TSEARCH && !defined _LIBC |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
251 freesa (new_value); |
4080 | 252 #endif |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
253 __set_errno (ENOMEM); |
4080 | 254 UNLOCK; |
255 return -1; | |
256 } | |
257 | |
258 #ifdef USE_TSEARCH | |
259 memcpy (np, new_value, namelen + 1 + vallen); | |
260 #else | |
261 memcpy (np, name, namelen); | |
262 np[namelen] = '='; | |
263 memcpy (&np[namelen + 1], value, vallen); | |
264 #endif | |
265 /* And remember the value. */ | |
266 STORE_VALUE (np); | |
267 } | |
4929
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
268 #if defined USE_TSEARCH && !defined _LIBC |
4192ff0fff14
Use allocsa instead of alloca.
Bruno Haible <bruno@clisp.org>
parents:
4691
diff
changeset
|
269 freesa (new_value); |
4080 | 270 #endif |
574 | 271 } |
4080 | 272 |
273 *ep = np; | |
574 | 274 } |
275 | |
4080 | 276 UNLOCK; |
277 | |
574 | 278 return 0; |
279 } | |
280 | |
4080 | 281 int |
282 setenv (const char *name, const char *value, int replace) | |
283 { | |
284 return __add_to_environ (name, value, NULL, replace); | |
285 } | |
286 | |
287 /* The `clearenv' was planned to be added to POSIX.1 but probably | |
288 never made it. Nevertheless the POSIX.9 standard (POSIX bindings | |
289 for Fortran 77) requires this function. */ | |
290 int | |
4691 | 291 clearenv (void) |
574 | 292 { |
4080 | 293 LOCK; |
294 | |
295 if (__environ == last_environ && __environ != NULL) | |
296 { | |
297 /* We allocated this environment so we can free it. */ | |
298 free (__environ); | |
299 last_environ = NULL; | |
300 } | |
301 | |
302 /* Clear the environment pointer removes the whole environment. */ | |
303 __environ = NULL; | |
574 | 304 |
4080 | 305 UNLOCK; |
306 | |
307 return 0; | |
574 | 308 } |
4080 | 309 |
310 #ifdef _LIBC | |
311 static void | |
312 free_mem (void) | |
313 { | |
314 /* Remove all traces. */ | |
315 clearenv (); | |
316 | |
317 /* Now remove the search tree. */ | |
318 __tdestroy (known_values, free); | |
319 known_values = NULL; | |
320 } | |
321 text_set_element (__libc_subfreeres, free_mem); | |
322 | |
323 | |
324 # undef setenv | |
325 # undef clearenv | |
326 weak_alias (__setenv, setenv) | |
327 weak_alias (__clearenv, clearenv) | |
328 #endif |