New module 'tanhf'.
[gnulib.git] / lib / putenv.c
index 5e9a863..3c33279 100644 (file)
@@ -1,11 +1,12 @@
-/* Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2011 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.
 
 
    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.
 
-   This program is free software; you can redistribute it and/or modify it
+   This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
+   Free Software Foundation; either version 3 of the License, or any
    later version.
 
    This program is distributed in the hope that it will be useful,
    later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
-#include <errno.h>
+#include <config.h>
 
 
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+/* Specification.  */
+#include <stdlib.h>
 
 
-/* Define-away any (possibly conflicting) prototype of putenv.
-   Many systems omit the `const' attribute on the argument.
-   Define-away only if it's not already defined (e.g. to rpl_putenv).  */
-#ifndef putenv
-# define putenv _sys_putenv
-#endif
+#include <stddef.h>
 
 
-#if defined (__GNU_LIBRARY__) || defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#endif
-#if defined (__GNU_LIBRARY__) || defined (HAVE_STRING_H)
-# include <string.h>
-#endif
-#if defined (__GNU_LIBRARY__) || defined (HAVE_UNISTD_H)
-# include <unistd.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
 
 #endif
 
-#ifndef putenv
-# undef putenv
-#endif
+#include <string.h>
+#include <unistd.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))
+#if _LIBC
+# if HAVE_GNU_LD
+# define environ __environ
+# else
+extern char **environ;
+# endif
 #endif
 
 #endif
 
-#if HAVE_GNU_LD
-# define environ __environ
+#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
 #else
-extern char **environ;
+# define LOCK
+# define UNLOCK
 #endif
 
 #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
 int
-putenv (string)
-     const char *string;
+putenv (char *string)
 {
   const char *const name_end = strchr (string, '=');
   register size_t size;
 {
   const char *const name_end = strchr (string, '=');
   register size_t size;
@@ -70,24 +102,13 @@ putenv (string)
   if (name_end == NULL)
     {
       /* Remove the variable from the environment.  */
   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;
   for (ep = environ; *ep != NULL; ++ep)
     if (!strncmp (*ep, string, name_end - string) &&
     }
 
   size = 0;
   for (ep = environ; *ep != NULL; ++ep)
     if (!strncmp (*ep, string, name_end - string) &&
-       (*ep)[name_end - string] == '=')
+        (*ep)[name_end - string] == '=')
       break;
     else
       ++size;
       break;
     else
       ++size;
@@ -97,18 +118,17 @@ putenv (string)
       static char **last_environ = NULL;
       char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
       if (new_environ == NULL)
       static char **last_environ = NULL;
       char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
       if (new_environ == NULL)
-       return -1;
+        return -1;
       (void) memcpy ((void *) new_environ, (void *) environ,
       (void) memcpy ((void *) new_environ, (void *) environ,
-                    size * sizeof (char *));
+                     size * sizeof (char *));
       new_environ[size] = (char *) string;
       new_environ[size + 1] = NULL;
       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;
     }
   else
       last_environ = new_environ;
       environ = new_environ;
     }
   else
-    *ep = (char *) string;
+    *ep = string;
 
   return 0;
 }
 
   return 0;
 }