]> Savannah Git Hosting - gnulib.git/commitdiff
unsetenv: On native Windows, don't modify _environ directly.
authorBruno Haible <bruno@clisp.org>
Wed, 5 Jun 2024 23:21:28 +0000 (01:21 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 6 Jun 2024 23:29:43 +0000 (01:29 +0200)
* m4/setenv.m4 (gl_PREREQ_UNSETENV): Check for _putenv.
* lib/unsetenv.c (unsetenv): Add native Windows handling, from
lib/putenv.c.
* modules/unsetenv (Depends-on): Add free-posix, malloc-posix.
* m4/putenv.m4 (gl_FUNC_PUTENV): Use AC_CHECK_DECLS_ONCE.
* lib/putenv.c (_unsetenv): Moved to lib/unsetenv.c.
(putenv): Invoke unsetenv instead of _unsetenv.
* modules/putenv (Depends-on): Add unsetenv.

ChangeLog
lib/putenv.c
lib/unsetenv.c
m4/putenv.m4
m4/setenv.m4
modules/putenv
modules/unsetenv

index 8005d2856bef35280c9cd93e69741e283853e7ef..1e7e4ecfc1d94f85bc826f2305c73474c3ff4503 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2024-06-05  Bruno Haible  <bruno@clisp.org>
+
+       unsetenv: On native Windows, don't modify _environ directly.
+       * m4/setenv.m4 (gl_PREREQ_UNSETENV): Check for _putenv.
+       * lib/unsetenv.c (unsetenv): Add native Windows handling, from
+       lib/putenv.c.
+       * modules/unsetenv (Depends-on): Add free-posix, malloc-posix.
+       * m4/putenv.m4 (gl_FUNC_PUTENV): Use AC_CHECK_DECLS_ONCE.
+       * lib/putenv.c (_unsetenv): Moved to lib/unsetenv.c.
+       (putenv): Invoke unsetenv instead of _unsetenv.
+       * modules/putenv (Depends-on): Add unsetenv.
+
 2024-06-05  Bruno Haible  <bruno@clisp.org>
 
        putenv: Don't crash upon out-of-memory.
index 1d70717e0f7f9456b5b6bc12c47ed0603a330d1c..d3084c9e6077d59f48a6dba86499539a14f77608 100644 (file)
@@ -64,71 +64,6 @@ __libc_lock_define_initialized (static, envlock)
 # define SetEnvironmentVariable SetEnvironmentVariableA
 #endif
 
-static int
-_unsetenv (const char *name)
-{
-  size_t len;
-
-  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  len = strlen (name);
-
-#if HAVE_DECL__PUTENV /* native Windows */
-  /* The Microsoft documentation
-     <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-wputenv>
-     says:
-       "Don't change an environment entry directly: instead,
-        use _putenv or _wputenv to change it."
-     Note: Microsoft's _putenv updates not only the contents of _environ but
-     also the contents of _wenviron, so that both are in kept in sync.
-
-     The way to remove an environment variable is to pass to _putenv a string
-     of the form "NAME=".  (NB: This is a different convention than with glibc
-     putenv, which expects a string of the form "NAME"!)  */
-  {
-    int putenv_result;
-    char *name_ = malloc (len + 2);
-    if (name_ == NULL)
-      return -1;
-    memcpy (name_, name, len);
-    name_[len] = '=';
-    name_[len + 1] = 0;
-    putenv_result = _putenv (name_);
-    /* In this particular case it is OK to free() the argument passed to
-       _putenv.  */
-    free (name_);
-    return putenv_result;
-  }
-#else
-
-  LOCK;
-
-  char **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;
-#endif
-}
-
-
 /* Put STRING, which is of the form "NAME=VALUE", in the environment.
    If STRING contains no '=', then remove STRING from the environment.  */
 int
@@ -140,7 +75,7 @@ putenv (char *string)
   if (name_end == NULL)
     {
       /* Remove the variable from the environment.  */
-      return _unsetenv (string);
+      return unsetenv (string);
     }
 
 #if HAVE_DECL__PUTENV /* native Windows */
index e5489490f74b6ad2b27b559bf1d1cc5272154eae..5e989968c1e987c1b3fdea28d21a2899e35c031b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995-2002, 2005-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995-2002, 2005-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    This file is free software: you can redistribute it and/or modify
@@ -57,7 +57,6 @@ int
 unsetenv (const char *name)
 {
   size_t len;
-  char **ep;
 
   if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
     {
@@ -67,9 +66,37 @@ unsetenv (const char *name)
 
   len = strlen (name);
 
+#if HAVE_DECL__PUTENV /* native Windows */
+  /* The Microsoft documentation
+     <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-wputenv>
+     says:
+       "Don't change an environment entry directly: instead,
+        use _putenv or _wputenv to change it."
+     Note: Microsoft's _putenv updates not only the contents of _environ but
+     also the contents of _wenviron, so that both are in kept in sync.
+
+     The way to remove an environment variable is to pass to _putenv a string
+     of the form "NAME=".  (NB: This is a different convention than with glibc
+     putenv, which expects a string of the form "NAME"!)  */
+  {
+    int putenv_result;
+    char *name_ = malloc (len + 2);
+    if (name_ == NULL)
+      return -1;
+    memcpy (name_, name, len);
+    name_[len] = '=';
+    name_[len + 1] = 0;
+    putenv_result = _putenv (name_);
+    /* In this particular case it is OK to free() the argument passed to
+       _putenv.  */
+    free (name_);
+    return putenv_result;
+  }
+#else
+
   LOCK;
 
-  ep = __environ;
+  char **ep = __environ;
   while (*ep != NULL)
     if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
       {
@@ -87,6 +114,7 @@ unsetenv (const char *name)
   UNLOCK;
 
   return 0;
+#endif
 }
 
 #ifdef _LIBC
index d37a60213fcc062581e9f3e68772e5164ab37541..388d00ea8cf2e42871942a8bea636c4ae3eba1a2 100644 (file)
@@ -1,5 +1,5 @@
-# putenv.m4 serial 26
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# putenv.m4 serial 26.1
+dnl Copyright (C) 2002-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -60,5 +60,5 @@ AC_DEFUN([gl_FUNC_PUTENV],
 # Prerequisites of lib/putenv.c.
 AC_DEFUN([gl_PREREQ_PUTENV],
 [
-  AC_CHECK_DECLS([_putenv])
+  AC_CHECK_DECLS_ONCE([_putenv])
 ])
index a30523d6a337709a1c165433a3532060b1e823da..c31a5837d6f55019d0ace01b8caa1a7ba273317a 100644 (file)
@@ -1,5 +1,5 @@
-# setenv.m4 serial 33
-dnl Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+# setenv.m4 serial 34
+dnl Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -162,4 +162,5 @@ AC_DEFUN([gl_PREREQ_UNSETENV],
 [
   AC_REQUIRE([gl_ENVIRON])
   AC_CHECK_HEADERS_ONCE([unistd.h])
+  AC_CHECK_DECLS_ONCE([_putenv])
 ])
index a5a7c8d795c73d8377dfc6128efe4f15360c0378..d644d3ff26bb44c92f25f3b8791fb5a8e9c60781 100644 (file)
@@ -10,6 +10,7 @@ stdlib
 environ         [test $REPLACE_PUTENV = 1]
 free-posix      [test $REPLACE_PUTENV = 1]
 malloc-posix    [test $REPLACE_PUTENV = 1]
+unsetenv        [test $REPLACE_PUTENV = 1]
 
 configure.ac:
 gl_FUNC_PUTENV
index 0e603a5b7611d56206ce090b261a8adcb695e687..302d97081437332bff5a44fdf2ede09eb12dc8f4 100644 (file)
@@ -9,6 +9,8 @@ Depends-on:
 stdlib
 unistd          [test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1]
 environ         [test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1]
+free-posix      [test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1]
+malloc-posix    [test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1]
 
 configure.ac:
 gl_FUNC_UNSETENV