summaryrefslogtreecommitdiffstats
path: root/gl/setenv.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
commitb0afb8fe0ff1d87165af9df61501197a06240dda (patch)
tree274ac6a96c53ef4c19ab4974ce24a06a233128c5 /gl/setenv.c
parent68fc05381ee5fa0aee1413118fbb3d81ca888b09 (diff)
downloadmonitoring-plugins-b0afb8fe0ff1d87165af9df61501197a06240dda.tar.gz
Sync with Gnulib stable-202507 code (a8ac9f9ce5)
Diffstat (limited to 'gl/setenv.c')
-rw-r--r--gl/setenv.c97
1 files changed, 93 insertions, 4 deletions
diff --git a/gl/setenv.c b/gl/setenv.c
index 9e2e9e2f..ef301d41 100644
--- a/gl/setenv.c
+++ b/gl/setenv.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 1992, 1995-2003, 2005-2024 Free Software Foundation, Inc. 1/* Copyright (C) 1992, 1995-2003, 2005-2025 Free Software Foundation, Inc.
2 This file is part of the GNU C Library. 2 This file is part of the GNU C Library.
3 3
4 This file is free software: you can redistribute it and/or modify 4 This file is free software: you can redistribute it and/or modify
@@ -38,11 +38,23 @@
38# include <unistd.h> 38# include <unistd.h>
39#endif 39#endif
40 40
41#if defined _WIN32 && ! defined __CYGWIN__
42# define WIN32_LEAN_AND_MEAN
43# include <windows.h>
44#endif
45
41#if !_LIBC 46#if !_LIBC
42# include "malloca.h" 47# include "malloca.h"
43#endif 48#endif
44 49
50#if defined _WIN32 && ! defined __CYGWIN__
51/* Don't assume that UNICODE is not defined. */
52# undef SetEnvironmentVariable
53# define SetEnvironmentVariable SetEnvironmentVariableA
54#endif
55
45#if _LIBC || !HAVE_SETENV 56#if _LIBC || !HAVE_SETENV
57#if !HAVE_DECL__PUTENV
46 58
47#if !_LIBC 59#if !_LIBC
48# define __environ environ 60# define __environ environ
@@ -215,8 +227,7 @@ __add_to_environ (const char *name, const char *value, const char *combined,
215 } 227 }
216 228
217 if (__environ != last_environ) 229 if (__environ != last_environ)
218 memcpy ((char *) new_environ, (char *) __environ, 230 memcpy (new_environ, __environ, size * sizeof (char *));
219 size * sizeof (char *));
220 231
221 new_environ[size + 1] = NULL; 232 new_environ[size + 1] = NULL;
222 233
@@ -343,6 +354,84 @@ weak_alias (__setenv, setenv)
343weak_alias (__clearenv, clearenv) 354weak_alias (__clearenv, clearenv)
344#endif 355#endif
345 356
357#else /* HAVE_DECL__PUTENV */
358/* Native Windows */
359
360int
361setenv (const char *name, const char *value, int replace)
362{
363 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
364 {
365 errno = EINVAL;
366 return -1;
367 }
368
369 /* The Microsoft documentation
370 <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-wputenv>
371 says:
372 "Don't change an environment entry directly: instead,
373 use _putenv or _wputenv to change it."
374 Note: Microsoft's _putenv updates not only the contents of _environ but
375 also the contents of _wenviron, so that both are in kept in sync. */
376 const char *existing_value = getenv (name);
377 if (existing_value != NULL)
378 {
379 if (replace)
380 {
381 if (strcmp (existing_value, value) == 0)
382 /* No need to allocate memory. */
383 return 0;
384 }
385 else
386 /* Keep the existing value. */
387 return 0;
388 }
389 /* Allocate a new environment entry in the heap. */
390 /* _putenv ("NAME=") unsets NAME, so if VALUE is the empty string, invoke
391 _putenv ("NAME= ") and fix up the result afterwards. */
392 const char *value_ = (value[0] == '\0' ? " " : value);
393 size_t name_len = strlen (name);
394 size_t value_len = strlen (value_);
395 char *string = (char *) malloc (name_len + 1 + value_len + 1);
396 if (string == NULL)
397 return -1;
398 memcpy (string, name, name_len);
399 string[name_len] = '=';
400 memcpy (&string[name_len + 1], value_, value_len + 1);
401 /* Use _putenv. */
402 if (_putenv (string) < 0)
403 return -1;
404 if (value[0] == '\0')
405 {
406 /* Fix up the result. */
407 char *new_value = getenv (name);
408 if (new_value != NULL && new_value[0] == ' ' && new_value[1] == '\0')
409 new_value[0] = '\0';
410# if defined _WIN32 && ! defined __CYGWIN__
411 /* _putenv propagated "NAME= " into the subprocess environment;
412 fix that by calling SetEnvironmentVariable directly. */
413 /* Documentation:
414 <https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setenvironmentvariable> */
415 if (!SetEnvironmentVariable (name, ""))
416 {
417 switch (GetLastError ())
418 {
419 case ERROR_NOT_ENOUGH_MEMORY:
420 case ERROR_OUTOFMEMORY:
421 errno = ENOMEM;
422 break;
423 default:
424 errno = EINVAL;
425 break;
426 }
427 return -1;
428 }
429# endif
430 }
431 return 0;
432}
433
434#endif /* HAVE_DECL__PUTENV */
346#endif /* _LIBC || !HAVE_SETENV */ 435#endif /* _LIBC || !HAVE_SETENV */
347 436
348/* The rest of this file is called into use when replacing an existing 437/* The rest of this file is called into use when replacing an existing
@@ -360,7 +449,7 @@ int
360rpl_setenv (const char *name, const char *value, int replace) 449rpl_setenv (const char *name, const char *value, int replace)
361{ 450{
362 int result; 451 int result;
363 if (!name || !*name || strchr (name, '=')) 452 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
364 { 453 {
365 errno = EINVAL; 454 errno = EINVAL;
366 return -1; 455 return -1;