bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Win32] putenv modifications not inherited by child processed (Was:


From: Paul Eggert
Subject: Re: [Win32] putenv modifications not inherited by child processed (Was: Heap corruption in putenv)
Date: Mon, 18 Feb 2013 19:40:10 -0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130106 Thunderbird/17.0.2

Thanks, how about this change instead?
It's a bit more conservative about always using
_putenv and setting errno.  And it uses
WIN32_LEAN_AND_MEAN.

---
 ChangeLog    |  9 +++++++++
 lib/putenv.c | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 050ad4d..1f62845 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2013-02-18  Paul Eggert  <address@hidden>
 
+       putenv: port better to native Windows
+       * lib/putenv.c [(_WIN32 || __WIN32__) && ! __CYGWIN__]:
+       Define WIN32_LEAN_AND_MEAN and include <windows.h>.
+       (_unsetenv): Use _putenv if available.
+       (putenv): Temporarily set NAME=' ' rather than NAME='x' as that's
+       a bit less likely to cause damage.
+       (putenv) [(_WIN32 || __WIN32__) && ! __CYGWIN__]:
+       Fix the wrong value with SetEnvironmentVariable.
+
        extern-inline: avoid compilation error with HP-UX cc
        Reported by Richard Lloyd in
        <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
diff --git a/lib/putenv.c b/lib/putenv.c
index 0ec392f..8e6cb8a 100644
--- a/lib/putenv.c
+++ b/lib/putenv.c
@@ -34,6 +34,11 @@
 #include <string.h>
 #include <unistd.h>
 
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 #if _LIBC
 # if HAVE_GNU_LD
 #  define environ __environ
@@ -67,6 +72,20 @@ _unsetenv (const char *name)
 
   len = strlen (name);
 
+#if HAVE__PUTENV
+  {
+    char *name_ = malloc (len + 2);
+    memcpy (name_, name, len);
+    name_[len] = '=';
+    name_[len + 1] = 0;
+    putenv_result = _putenv (name_);
+    putenv_errno = errno;
+    free (name_);
+    __set_errno (putenv_errno);
+    return putenv_result;
+  }
+#else
+
   LOCK;
 
   ep = environ;
@@ -87,6 +106,7 @@ _unsetenv (const char *name)
   UNLOCK;
 
   return 0;
+#endif
 }
 
 
@@ -123,15 +143,15 @@ putenv (char *string)
         return _putenv (string);
       else
         {
-          /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME=x")
+          /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME= ")
              to allocate the environ vector and then replace the new
              entry with "NAME=".  */
           int putenv_result, putenv_errno;
-          char *name_x = malloc (name_end - string + sizeof "=x");
+          char *name_x = malloc (name_end - string + sizeof "= ");
           if (!name_x)
             return -1;
           memcpy (name_x, string, name_end - string + 1);
-          name_x[name_end - string + 1] = 'x';
+          name_x[name_end - string + 1] = ' ';
           name_x[name_end - string + 2] = 0;
           putenv_result = _putenv (name_x);
           putenv_errno = errno;
@@ -141,6 +161,16 @@ putenv (char *string)
                 *ep = string;
                 break;
               }
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+          if (putenv_result == 0)
+            {
+              /* _putenv propagated "NAME= " into the subprocess environment;
+                 fix that by calling SetEnvironmentVariable directly.  */
+              name_x[name_end - string] = 0;
+              putenv_result = SetEnvironmentVariable (name_x, "") ? 0 : -1;
+              putenv_errno = ENOMEM; /* ENOMEM is the only way to fail.  */
+            }
+# endif
           free (name_x);
           __set_errno (putenv_errno);
           return putenv_result;
-- 
1.7.11.7




reply via email to

[Prev in Thread] Current Thread [Next in Thread]