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
This commit is contained in:
parent
a4837536e2
commit
89bd9d3685
5 changed files with 94 additions and 19 deletions
|
@ -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)
|
||||
|
|
94
lib/putenv.c
94
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -48,3 +48,9 @@ AC_DEFUN([gl_FUNC_PUTENV],
|
|||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
# Prerequisites of lib/putenv.c.
|
||||
AC_DEFUN([gl_PREREQ_PUTENV],
|
||||
[
|
||||
AC_CHECK_FUNCS([_putenv])
|
||||
])
|
||||
|
|
Loading…
Add table
Reference in a new issue