* 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 (Depends-on): Add unsetenv.
+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 (Depends-on): Add unsetenv.
+
2024-06-05 Bruno Haible <bruno@clisp.org>
putenv: Don't crash upon out-of-memory.
# 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
if (name_end == NULL)
{
/* Remove the variable from the environment. */
- return _unsetenv (string);
+ return unsetenv (string);
}
#if HAVE_DECL__PUTENV /* native Windows */
-/* Copyright (C) 1992, 1995-2002, 2005-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995-2002, 2005-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
unsetenv (const char *name)
{
size_t len;
- char **ep;
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
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] == '=')
{
UNLOCK;
return 0;
+#endif
}
#ifdef _LIBC
-# putenv.m4 serial 26
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# putenv.m4 serial 26.1
+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,
dnl with or without modifications, as long as this notice is preserved.
# Prerequisites of lib/putenv.c.
AC_DEFUN([gl_PREREQ_PUTENV],
[
- AC_CHECK_DECLS([_putenv])
+ AC_CHECK_DECLS_ONCE([_putenv])
])
-# setenv.m4 serial 33
-dnl Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+# setenv.m4 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,
dnl with or without modifications, as long as this notice is preserved.
[
AC_REQUIRE([gl_ENVIRON])
AC_CHECK_HEADERS_ONCE([unistd.h])
+ AC_CHECK_DECLS_ONCE([_putenv])
])
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
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