summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2013-03-01 07:16:43 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2013-03-01 07:16:43 -0800
commit89bd9d36859503e25b767f97395870190f272bc1 (patch)
treeb42053badeb8e2274cc9f3a43b67ac800272aa37
parenta4837536e2ef918dacf687c134e690cbbe693487 (diff)
downloademacs-89bd9d36859503e25b767f97395870190f272bc1.tar.gz
Merge from gnulib.
2013-02-21 putenv: port better to native Windows 2013-02-18 extern-inline: avoid compilation error with HP-UX cc 2013-02-14 putenv: fix heap corruption with mixed putenv/_putenv
-rw-r--r--ChangeLog7
-rw-r--r--lib/putenv.c94
-rw-r--r--m4/extern-inline.m45
-rw-r--r--m4/gnulib-comp.m41
-rw-r--r--m4/putenv.m46
5 files changed, 94 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 7a2e7769eca..84d9987ccea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ Merge from gnulib, incorporating:
+ 2013-02-21 putenv: port better to native Windows
+ 2013-02-18 extern-inline: avoid compilation error with HP-UX cc
+ 2013-02-14 putenv: fix heap corruption with mixed putenv/_putenv
+
2013-02-28 Ken Brown <kbrown@cornell.edu>
* configure.ac (HAVE_DATA_START): Fix test. (Bug#13818)
diff --git a/lib/putenv.c b/lib/putenv.c
index 5f0fedaf9cc..ed666afc3bb 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,21 @@ _unsetenv (const char *name)
len = strlen (name);
+#if HAVE__PUTENV
+ {
+ int putenv_result, putenv_errno;
+ 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 +107,7 @@ _unsetenv (const char *name)
UNLOCK;
return 0;
+#endif
}
@@ -95,9 +116,8 @@ _unsetenv (const char *name)
int
putenv (char *string)
{
- const char *const name_end = strchr (string, '=');
- register size_t size;
- register char **ep;
+ const char *name_end = strchr (string, '=');
+ char **ep;
if (name_end == NULL)
{
@@ -105,30 +125,68 @@ putenv (char *string)
return _unsetenv (string);
}
- size = 0;
- for (ep = environ; *ep != NULL; ++ep)
- if (!strncmp (*ep, string, name_end - string) &&
- (*ep)[name_end - string] == '=')
+#if HAVE__PUTENV
+ /* Rely on _putenv to allocate the new environment. If other
+ parts of the application use _putenv, the !HAVE__PUTENV code
+ would fight over who owns the environ vector, causing a crash. */
+ if (name_end[1])
+ return _putenv (string);
+ else
+ {
+ /* _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 "= ");
+ if (!name_x)
+ return -1;
+ memcpy (name_x, string, name_end - string + 1);
+ name_x[name_end - string + 1] = ' ';
+ name_x[name_end - string + 2] = 0;
+ putenv_result = _putenv (name_x);
+ putenv_errno = errno;
+ for (ep = environ; *ep; ep++)
+ if (strcmp (*ep, name_x) == 0)
+ {
+ *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;
+ }
+#else
+ for (ep = environ; *ep; ep++)
+ if (strncmp (*ep, string, name_end - string) == 0
+ && (*ep)[name_end - string] == '=')
break;
- else
- ++size;
- if (*ep == NULL)
+ if (*ep)
+ *ep = string;
+ else
{
static char **last_environ = NULL;
- char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
- if (new_environ == NULL)
+ size_t size = ep - environ;
+ char **new_environ = malloc ((size + 2) * sizeof *new_environ);
+ if (! new_environ)
return -1;
- (void) memcpy ((void *) new_environ, (void *) environ,
- size * sizeof (char *));
- new_environ[size] = (char *) string;
- new_environ[size + 1] = NULL;
+ new_environ[0] = string;
+ memcpy (new_environ + 1, environ, (size + 1) * sizeof *new_environ);
free (last_environ);
last_environ = new_environ;
environ = new_environ;
}
- else
- *ep = string;
+#endif
return 0;
}
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
index 5880d4f4545..0152f29326b 100644
--- a/m4/extern-inline.m4
+++ b/m4/extern-inline.m4
@@ -18,13 +18,16 @@ AC_DEFUN([gl_EXTERN_INLINE],
_GL_INLINE_HEADER_END contains useful stuff to put
in the same include file, after uses of _GL_INLINE.
+ Suppress extern inline with HP-UX cc, as it appears to be broken; see
+ <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
+
Suppress the use of extern inline on Apple's platforms,
as Libc-825.25 (2012-09-19) is incompatible with it; see
<http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
Perhaps Apple will fix this some day. */
#if ((__GNUC__ \
? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
- : 199901L <= __STDC_VERSION__) \
+ : 199901L <= __STDC_VERSION__ && !defined __HP_cc) \
&& !defined __APPLE__)
# define _GL_INLINE inline
# define _GL_EXTERN_INLINE extern inline
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index a7987120c50..6c3012d827f 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -271,6 +271,7 @@ AC_DEFUN([gl_INIT],
gl_FUNC_PUTENV
if test $REPLACE_PUTENV = 1; then
AC_LIBOBJ([putenv])
+ gl_PREREQ_PUTENV
fi
gl_STDLIB_MODULE_INDICATOR([putenv])
gl_FUNC_READLINK
diff --git a/m4/putenv.m4 b/m4/putenv.m4
index 9de53527a73..03ed4f97dbe 100644
--- a/m4/putenv.m4
+++ b/m4/putenv.m4
@@ -48,3 +48,9 @@ AC_DEFUN([gl_FUNC_PUTENV],
;;
esac
])
+
+# Prerequisites of lib/putenv.c.
+AC_DEFUN([gl_PREREQ_PUTENV],
+[
+ AC_CHECK_FUNCS([_putenv])
+])