diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | include/stdlib.h | 3 | ||||
-rw-r--r-- | sysdeps/generic/putenv.c | 4 | ||||
-rw-r--r-- | sysdeps/generic/setenv.c | 152 |
4 files changed, 96 insertions, 73 deletions
@@ -1,5 +1,15 @@ 1999-07-29 Ulrich Drepper <drepper@cygnus.com> + * sysdeps/generic/setenv.c: Move setenv code in new function + __add_to_environ. Add new parameter specifying already + constructed string for the environment. + (setenv): Call __add_to_environ with new parameter set to NULL. + (unsetenv): Really test all elements for duplicated name. Missed those + cases where the two are following each other. + * sysdeps/generic/putenv.c: Use __add_to_environ instead of setenv. + * include/stdlib.h: Add prototype of __add_to_environ. + * stdlib/tst-environ.c: New file. + * sysdeps/i386/bits/string.h (__memset_cc): Fix typo in last patch. * nis/nss_nis/nis-initgroups.c (_nss_nis_initgroups): Correct size diff --git a/include/stdlib.h b/include/stdlib.h index c15d364..187c458 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -46,6 +46,9 @@ extern char *__canonicalize_file_name __P ((__const char *__name)); extern char *__realpath __P ((__const char *__name, char *__resolved)); extern int __ptsname_r __P ((int __fd, char *__buf, size_t __buflen)); extern int __getpt __P ((void)); + +extern int __add_to_environ (const char *name, const char *value, + const char *combines, int replace); #endif #undef __Need_M_And_C diff --git a/sysdeps/generic/putenv.c b/sysdeps/generic/putenv.c index 3fcd5f9..75fafad 100644 --- a/sysdeps/generic/putenv.c +++ b/sysdeps/generic/putenv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 94, 95, 96, 97, 98 Free Software Foundation, Inc. +/* Copyright (C) 1991, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -64,7 +64,7 @@ putenv (string) memcpy (name, string, name_end - string); name[name_end - string] = '\0'; #endif - return __setenv (name, name_end + 1, 1); + return __add_to_environ (name, NULL, string, 1); } __unsetenv (string); diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c index a5818d0..fc58e9b 100644 --- a/sysdeps/generic/setenv.c +++ b/sysdeps/generic/setenv.c @@ -16,23 +16,6 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Issues: - - 1. putenv must not use setenv since the string provided by the user - must be used, not a copy - - 2. a common function should determine the place where to insert the - new entry and if necessary take care of extending the array - - 3. It must be kept track of whether an entry was inserted via putenv - or setenv. In the former case the entry must not be put into - the search tree since removing it could mean it will not be - available anymore (e.g., when allocated on the stack) - - To handle this an array parallel to the __environ array must specify - whether the entry was added via putenv or not -*/ - #if HAVE_CONFIG_H # include <config.h> #endif @@ -117,16 +100,23 @@ static void *known_values; static char **last_environ; +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. */ int -setenv (name, value, replace) +__add_to_environ (name, value, combined, replace) const char *name; const char *value; + const char *combined; int replace; { register char **ep; register size_t size; const size_t namelen = strlen (name); - const size_t vallen = strlen (value) + 1; + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; LOCK; @@ -156,37 +146,49 @@ setenv (name, value, replace) return -1; } - /* See whether the value is already known. */ + /* If the whole entry is given add it. */ + if (combined != NULL) + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + else + { + /* See whether the value is already known. */ #ifdef USE_TSEARCH - new_value = alloca (namelen + 1 + vallen); + new_value = (char *) alloca (namelen + 1 + vallen); # ifdef _LIBC - __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), - value, vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); # else - memcpy (new_value, name, namelen); - new_value[namelen] = '='; - memcpy (&new_value[namelen + 1], value, vallen); + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); # endif - new_environ[size] = KNOWN_VALUE (new_value); - if (new_environ[size] == NULL) -#endif - { - new_environ[size] = malloc (namelen + 1 + vallen); + new_environ[size] = KNOWN_VALUE (new_value); if (new_environ[size] == NULL) +#endif { - __set_errno (ENOMEM); - UNLOCK; - return -1; - } + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (new_environ[size] == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } #ifdef USE_TSEARCH - memcpy (new_environ[size], new_value, namelen + 1 + vallen); + memcpy (new_environ[size], new_value, namelen + 1 + vallen); #else - memcpy (new_environ[size], name, namelen); - new_environ[size][namelen] = '='; - memcpy (&new_environ[size][namelen + 1], value, vallen); + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); #endif + /* And save the value now. We cannot do this when we remove + the string since then we cannot decide whether it is a + user string or not. */ + STORE_VALUE (new_environ[size]); + } } if (__environ != last_environ) @@ -199,43 +201,47 @@ setenv (name, value, replace) } else if (replace) { - char *new_value; char *np; - /* The existing string is too short; malloc a new one. */ + /* Use the user string if given. */ + if (combined != NULL) + np = (char *) combined; + else + { #ifdef USE_TSEARCH - new_value = alloca (namelen + 1 + vallen); + char *new_value = alloca (namelen + 1 + vallen); # ifdef _LIBC - __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), - value, vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); # else - memcpy (new_value, name, namelen); - new_value[namelen] = '='; - memcpy (&new_value[namelen + 1], value, vallen); + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); # endif - np = KNOWN_VALUE (new_value); - if (np == NULL) -#endif - { - np = malloc (namelen + 1 + vallen); + np = KNOWN_VALUE (new_value); if (np == NULL) +#endif { - UNLOCK; - return -1; - } + np = malloc (namelen + 1 + vallen); + if (np == NULL) + { + UNLOCK; + return -1; + } #ifdef USE_TSEARCH - memcpy (np, new_value, namelen + 1 + vallen); + memcpy (np, new_value, namelen + 1 + vallen); #else - memcpy (np, name, namelen); - np[namelen] = '='; - memcpy (&np[namelen + 1], value, vallen); + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); #endif + /* And remember the value. */ + STORE_VALUE (np); + } } - /* Keep the old value around. */ - STORE_VALUE (*ep); *ep = np; } @@ -244,6 +250,15 @@ setenv (name, value, replace) return 0; } +int +setenv (name, value, replace) + const char *name; + const char *value; + int replace; +{ + return __add_to_environ (name, value, NULL, replace); +} + void unsetenv (name) const char *name; @@ -253,20 +268,20 @@ unsetenv (name) LOCK; - for (ep = __environ; *ep != NULL; ++ep) + ep = __environ; + while (*ep != NULL) if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { /* Found it. Remove this pointer by moving later ones back. */ char **dp = ep; - /* Store the value so that we can reuse it later. */ - STORE_VALUE (*ep); - do dp[0] = dp[1]; while (*dp++); /* Continue the loop in case NAME appears again. */ } + else + ++ep; UNLOCK; } @@ -281,12 +296,7 @@ clearenv () if (__environ == last_environ && __environ != NULL) { - /* We allocated this environment so we can free it. Store all the - strings. */ - char **ep = __environ; - while (*ep != NULL) - STORE_VALUE (*ep++); - + /* We allocated this environment so we can free it. */ free (__environ); last_environ = NULL; } |