Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 29 Jul 1999 20:40:05 +0000 (20:40 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 29 Jul 1999 20:40:05 +0000 (20:40 +0000)
* 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.

ChangeLog
include/stdlib.h
sysdeps/generic/putenv.c
sysdeps/generic/setenv.c

index 2208c60..61b75f3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index c15d364..187c458 100644 (file)
@@ -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
 
index 3fcd5f9..75fafad 100644 (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.
 
    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);
index a5818d0..fc58e9b 100644 (file)
    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;
     }