1
0
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:
Bruno Haible
2024-06-06 01:21:28 +02:00
parent adb76c7542
commit 43433e89de
7 changed files with 50 additions and 71 deletions

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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

View File

@@ -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])
])

View File

@@ -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])
])

View File

@@ -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

View File

@@ -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