Revert Jim's 2006-10-23 patch.
[gnulib.git] / lib / putenv.c
index 239981f..d904016 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991, 1994, 1997, 1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1994, 1997, 1998, 2000, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    NOTE: The canonical source of this file is maintained with the GNU C
    Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
 
 #include <stddef.h>
 
 /* Include errno.h *after* sys/types.h to work around header problems
    on AIX 3.2.5.  */
 #include <errno.h>
+#ifndef __set_errno
+# define __set_errno(ev) ((errno) = (ev))
+#endif
 
-/* Don't include stdlib.h because some (e.g., Solaris 2.7) declare putenv
+/* Don't include stdlib.h because some (e.g., Solaris 7) declare putenv
    with a non-const argument.  That would conflict with the declaration of
    rpl_putenv below (due to the #define putenv rpl_putenv from config.h).  */
 
-char *malloc ();
+void *malloc ();
 void free ();
 
-#if defined (__GNU_LIBRARY__) || defined (HAVE_STRING_H)
-# include <string.h>
-#endif
-#if defined (__GNU_LIBRARY__) || defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
+#include <string.h>
 
-#if !defined (__GNU_LIBRARY__) && !defined (HAVE_STRCHR)
-# define strchr index
-#endif
-#if !defined (__GNU_LIBRARY__) && !defined (HAVE_MEMCPY)
-# define memcpy(d,s,n) bcopy ((s), (d), (n))
-#endif
+#include <unistd.h>
 
 #if HAVE_GNU_LD
 # define environ __environ
@@ -54,12 +46,56 @@ void free ();
 extern char **environ;
 #endif
 
-#ifndef NULL
-# define NULL 0
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'.  */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK  __libc_lock_lock (envlock)
+# define UNLOCK        __libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
 #endif
 
+static int
+unsetenv (const char *name)
+{
+  size_t len;
+  char **ep;
+
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  len = strlen (name);
+
+  LOCK;
+
+  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;
+
+       do
+         dp[0] = dp[1];
+       while (*dp++);
+       /* Continue the loop in case NAME appears again.  */
+      }
+    else
+      ++ep;
+
+  UNLOCK;
+
+  return 0;
+}
+
 
-/* Put STRING, which is of the form "NAME=VALUE", in the environment.  */
+/* Put STRING, which is of the form "NAME=VALUE", in the environment.
+   If STRING contains no `=', then remove STRING from the environment.  */
 int
 rpl_putenv (const char *string)
 {
@@ -70,18 +106,7 @@ rpl_putenv (const char *string)
   if (name_end == NULL)
     {
       /* Remove the variable from the environment.  */
-      size = strlen (string);
-      for (ep = environ; *ep != NULL; ++ep)
-       if (!strncmp (*ep, string, size) && (*ep)[size] == '=')
-         {
-           while (ep[1] != NULL)
-             {
-               ep[0] = ep[1];
-               ++ep;
-             }
-           *ep = NULL;
-           return 0;
-         }
+      return unsetenv (string);
     }
 
   size = 0;
@@ -103,7 +128,7 @@ rpl_putenv (const char *string)
       new_environ[size] = (char *) string;
       new_environ[size + 1] = NULL;
       if (last_environ != NULL)
-       free ((void *) last_environ);
+       free (last_environ);
       last_environ = new_environ;
       environ = new_environ;
     }