setenv.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* Copyright (C) 1992, 1995, 1996, 1997, 2002, 2011 Free Software Foundation,
  2. Inc.
  3. This file based on setenv.c in the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If not,
  14. write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
  15. Boston, MA 02110-1301, USA. */
  16. /*
  17. @deftypefn Supplemental int setenv (const char *@var{name}, @
  18. const char *@var{value}, int @var{overwrite})
  19. @deftypefnx Supplemental void unsetenv (const char *@var{name})
  20. @code{setenv} adds @var{name} to the environment with value
  21. @var{value}. If the name was already present in the environment,
  22. the new value will be stored only if @var{overwrite} is nonzero.
  23. The companion @code{unsetenv} function removes @var{name} from the
  24. environment. This implementation is not safe for multithreaded code.
  25. @end deftypefn
  26. */
  27. #if HAVE_CONFIG_H
  28. # include <config.h>
  29. #endif
  30. #define setenv libiberty_setenv
  31. #define unsetenv libiberty_unsetenv
  32. #include "ansidecl.h"
  33. #include <sys/types.h> /* For `size_t' */
  34. #include <stdio.h> /* For `NULL' */
  35. #include <errno.h>
  36. #if !defined(errno) && !defined(HAVE_ERRNO_DECL)
  37. extern int errno;
  38. #endif
  39. #define __set_errno(ev) ((errno) = (ev))
  40. #if HAVE_STDLIB_H
  41. # include <stdlib.h>
  42. #endif
  43. #if HAVE_STRING_H
  44. # include <string.h>
  45. #endif
  46. #if HAVE_UNISTD_H
  47. # include <unistd.h>
  48. #endif
  49. #define __environ environ
  50. #ifndef HAVE_ENVIRON_DECL
  51. extern char **environ;
  52. #endif
  53. #undef setenv
  54. #undef unsetenv
  55. /* LOCK and UNLOCK are defined as no-ops. This makes the libiberty
  56. * implementation MT-Unsafe. */
  57. #define LOCK
  58. #define UNLOCK
  59. /* Below this point, it's verbatim code from the glibc-2.0 implementation */
  60. /* If this variable is not a null pointer we allocated the current
  61. environment. */
  62. static char **last_environ;
  63. int
  64. setenv (const char *name, const char *value, int replace)
  65. {
  66. register char **ep = 0;
  67. register size_t size;
  68. const size_t namelen = strlen (name);
  69. const size_t vallen = strlen (value) + 1;
  70. LOCK;
  71. size = 0;
  72. if (__environ != NULL)
  73. {
  74. for (ep = __environ; *ep != NULL; ++ep)
  75. if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
  76. break;
  77. else
  78. ++size;
  79. }
  80. if (__environ == NULL || *ep == NULL)
  81. {
  82. char **new_environ;
  83. if (__environ == last_environ && __environ != NULL)
  84. /* We allocated this space; we can extend it. */
  85. new_environ = (char **) realloc (last_environ,
  86. (size + 2) * sizeof (char *));
  87. else
  88. new_environ = (char **) malloc ((size + 2) * sizeof (char *));
  89. if (new_environ == NULL)
  90. {
  91. UNLOCK;
  92. return -1;
  93. }
  94. new_environ[size] = (char *) malloc (namelen + 1 + vallen);
  95. if (new_environ[size] == NULL)
  96. {
  97. free ((char *) new_environ);
  98. __set_errno (ENOMEM);
  99. UNLOCK;
  100. return -1;
  101. }
  102. if (__environ != last_environ)
  103. memcpy ((char *) new_environ, (char *) __environ,
  104. size * sizeof (char *));
  105. memcpy (new_environ[size], name, namelen);
  106. new_environ[size][namelen] = '=';
  107. memcpy (&new_environ[size][namelen + 1], value, vallen);
  108. new_environ[size + 1] = NULL;
  109. last_environ = __environ = new_environ;
  110. }
  111. else if (replace)
  112. {
  113. size_t len = strlen (*ep);
  114. if (len + 1 < namelen + 1 + vallen)
  115. {
  116. /* The existing string is too short; malloc a new one. */
  117. char *new_string = (char *) malloc (namelen + 1 + vallen);
  118. if (new_string == NULL)
  119. {
  120. UNLOCK;
  121. return -1;
  122. }
  123. *ep = new_string;
  124. }
  125. memcpy (*ep, name, namelen);
  126. (*ep)[namelen] = '=';
  127. memcpy (&(*ep)[namelen + 1], value, vallen);
  128. }
  129. UNLOCK;
  130. return 0;
  131. }
  132. void
  133. unsetenv (const char *name)
  134. {
  135. const size_t len = strlen (name);
  136. char **ep;
  137. LOCK;
  138. for (ep = __environ; *ep; ++ep)
  139. if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
  140. {
  141. /* Found it. Remove this pointer by moving later ones back. */
  142. char **dp = ep;
  143. do
  144. dp[0] = dp[1];
  145. while (*dp++);
  146. /* Continue the loop in case NAME appears again. */
  147. }
  148. UNLOCK;
  149. }