mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2025-08-08 17:22:05 +03:00
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-gnu (Depends-on): Add unsetenv.
This commit is contained in:
12
ChangeLog
12
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-gnu (Depends-on): Add unsetenv.
|
||||
|
||||
2024-06-05 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
putenv: Don't crash upon out-of-memory.
|
||||
|
67
lib/putenv.c
67
lib/putenv.c
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# putenv.m4
|
||||
# serial 27
|
||||
# serial 28
|
||||
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,
|
||||
@@ -61,5 +61,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])
|
||||
])
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# setenv.m4
|
||||
# serial 33
|
||||
# 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,
|
||||
@@ -163,4 +163,5 @@ AC_DEFUN([gl_PREREQ_UNSETENV],
|
||||
[
|
||||
AC_REQUIRE([gl_ENVIRON])
|
||||
AC_CHECK_HEADERS_ONCE([unistd.h])
|
||||
AC_CHECK_DECLS_ONCE([_putenv])
|
||||
])
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user