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 <egg...@cs.ucla.edu> + 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