1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-06-15 06:41:47 +03:00
* 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.
This commit is contained in:
Ulrich Drepper
1999-07-29 20:40:05 +00:00
parent a827898574
commit de4a40d07f
4 changed files with 96 additions and 73 deletions

View File

@ -1,5 +1,15 @@
1999-07-29 Ulrich Drepper <drepper@cygnus.com> 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. * sysdeps/i386/bits/string.h (__memset_cc): Fix typo in last patch.
* nis/nss_nis/nis-initgroups.c (_nss_nis_initgroups): Correct size * nis/nss_nis/nis-initgroups.c (_nss_nis_initgroups): Correct size

View File

@ -46,6 +46,9 @@ extern char *__canonicalize_file_name __P ((__const char *__name));
extern char *__realpath __P ((__const char *__name, char *__resolved)); extern char *__realpath __P ((__const char *__name, char *__resolved));
extern int __ptsname_r __P ((int __fd, char *__buf, size_t __buflen)); extern int __ptsname_r __P ((int __fd, char *__buf, size_t __buflen));
extern int __getpt __P ((void)); extern int __getpt __P ((void));
extern int __add_to_environ (const char *name, const char *value,
const char *combines, int replace);
#endif #endif
#undef __Need_M_And_C #undef __Need_M_And_C

View File

@ -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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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); memcpy (name, string, name_end - string);
name[name_end - string] = '\0'; name[name_end - string] = '\0';
#endif #endif
return __setenv (name, name_end + 1, 1); return __add_to_environ (name, NULL, string, 1);
} }
__unsetenv (string); __unsetenv (string);

View File

@ -16,23 +16,6 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ 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 #if HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
@ -117,16 +100,23 @@ static void *known_values;
static char **last_environ; 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 int
setenv (name, value, replace) __add_to_environ (name, value, combined, replace)
const char *name; const char *name;
const char *value; const char *value;
const char *combined;
int replace; int replace;
{ {
register char **ep; register char **ep;
register size_t size; register size_t size;
const size_t namelen = strlen (name); const size_t namelen = strlen (name);
const size_t vallen = strlen (value) + 1; const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
LOCK; LOCK;
@ -156,37 +146,49 @@ setenv (name, value, replace)
return -1; 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 #ifdef USE_TSEARCH
new_value = alloca (namelen + 1 + vallen); new_value = (char *) alloca (namelen + 1 + vallen);
# ifdef _LIBC # ifdef _LIBC
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen); value, vallen);
# else # else
memcpy (new_value, name, namelen); memcpy (new_value, name, namelen);
new_value[namelen] = '='; new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen); memcpy (&new_value[namelen + 1], value, vallen);
# endif # endif
new_environ[size] = KNOWN_VALUE (new_value); new_environ[size] = KNOWN_VALUE (new_value);
if (new_environ[size] == NULL)
#endif
{
new_environ[size] = malloc (namelen + 1 + vallen);
if (new_environ[size] == NULL) if (new_environ[size] == NULL)
#endif
{ {
__set_errno (ENOMEM); new_environ[size] = (char *) malloc (namelen + 1 + vallen);
UNLOCK; if (new_environ[size] == NULL)
return -1; {
} __set_errno (ENOMEM);
UNLOCK;
return -1;
}
#ifdef USE_TSEARCH #ifdef USE_TSEARCH
memcpy (new_environ[size], new_value, namelen + 1 + vallen); memcpy (new_environ[size], new_value, namelen + 1 + vallen);
#else #else
memcpy (new_environ[size], name, namelen); memcpy (new_environ[size], name, namelen);
new_environ[size][namelen] = '='; new_environ[size][namelen] = '=';
memcpy (&new_environ[size][namelen + 1], value, vallen); memcpy (&new_environ[size][namelen + 1], value, vallen);
#endif #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) if (__environ != last_environ)
@ -199,43 +201,47 @@ setenv (name, value, replace)
} }
else if (replace) else if (replace)
{ {
char *new_value;
char *np; 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 #ifdef USE_TSEARCH
new_value = alloca (namelen + 1 + vallen); char *new_value = alloca (namelen + 1 + vallen);
# ifdef _LIBC # ifdef _LIBC
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
value, vallen); value, vallen);
# else # else
memcpy (new_value, name, namelen); memcpy (new_value, name, namelen);
new_value[namelen] = '='; new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen); memcpy (&new_value[namelen + 1], value, vallen);
# endif # endif
np = KNOWN_VALUE (new_value); np = KNOWN_VALUE (new_value);
if (np == NULL)
#endif
{
np = malloc (namelen + 1 + vallen);
if (np == NULL) if (np == NULL)
#endif
{ {
UNLOCK; np = malloc (namelen + 1 + vallen);
return -1; if (np == NULL)
} {
UNLOCK;
return -1;
}
#ifdef USE_TSEARCH #ifdef USE_TSEARCH
memcpy (np, new_value, namelen + 1 + vallen); memcpy (np, new_value, namelen + 1 + vallen);
#else #else
memcpy (np, name, namelen); memcpy (np, name, namelen);
np[namelen] = '='; np[namelen] = '=';
memcpy (&np[namelen + 1], value, vallen); memcpy (&np[namelen + 1], value, vallen);
#endif #endif
/* And remember the value. */
STORE_VALUE (np);
}
} }
/* Keep the old value around. */
STORE_VALUE (*ep);
*ep = np; *ep = np;
} }
@ -244,6 +250,15 @@ setenv (name, value, replace)
return 0; return 0;
} }
int
setenv (name, value, replace)
const char *name;
const char *value;
int replace;
{
return __add_to_environ (name, value, NULL, replace);
}
void void
unsetenv (name) unsetenv (name)
const char *name; const char *name;
@ -253,20 +268,20 @@ unsetenv (name)
LOCK; LOCK;
for (ep = __environ; *ep != NULL; ++ep) ep = __environ;
while (*ep != NULL)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=') if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{ {
/* Found it. Remove this pointer by moving later ones back. */ /* Found it. Remove this pointer by moving later ones back. */
char **dp = ep; char **dp = ep;
/* Store the value so that we can reuse it later. */
STORE_VALUE (*ep);
do do
dp[0] = dp[1]; dp[0] = dp[1];
while (*dp++); while (*dp++);
/* Continue the loop in case NAME appears again. */ /* Continue the loop in case NAME appears again. */
} }
else
++ep;
UNLOCK; UNLOCK;
} }
@ -281,12 +296,7 @@ clearenv ()
if (__environ == last_environ && __environ != NULL) if (__environ == last_environ && __environ != NULL)
{ {
/* We allocated this environment so we can free it. Store all the /* We allocated this environment so we can free it. */
strings. */
char **ep = __environ;
while (*ep != NULL)
STORE_VALUE (*ep++);
free (__environ); free (__environ);
last_environ = NULL; last_environ = NULL;
} }