setenv.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. #ifndef environ
  52. extern char **environ;
  53. #endif
  54. #endif
  55. #undef setenv
  56. #undef unsetenv
  57. /* LOCK and UNLOCK are defined as no-ops. This makes the libiberty
  58. * implementation MT-Unsafe. */
  59. #define LOCK
  60. #define UNLOCK
  61. /* Below this point, it's verbatim code from the glibc-2.0 implementation */
  62. /* If this variable is not a null pointer we allocated the current
  63. environment. */
  64. static char **last_environ;
  65. int
  66. setenv (const char *name, const char *value, int replace)
  67. {
  68. register char **ep = 0;
  69. register size_t size;
  70. const size_t namelen = strlen (name);
  71. const size_t vallen = strlen (value) + 1;
  72. LOCK;
  73. size = 0;
  74. if (__environ != NULL)
  75. {
  76. for (ep = __environ; *ep != NULL; ++ep)
  77. if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
  78. break;
  79. else
  80. ++size;
  81. }
  82. if (__environ == NULL || *ep == NULL)
  83. {
  84. char **new_environ;
  85. if (__environ == last_environ && __environ != NULL)
  86. /* We allocated this space; we can extend it. */
  87. new_environ = (char **) realloc (last_environ,
  88. (size + 2) * sizeof (char *));
  89. else
  90. new_environ = (char **) malloc ((size + 2) * sizeof (char *));
  91. if (new_environ == NULL)
  92. {
  93. UNLOCK;
  94. return -1;
  95. }
  96. new_environ[size] = (char *) malloc (namelen + 1 + vallen);
  97. if (new_environ[size] == NULL)
  98. {
  99. free ((char *) new_environ);
  100. __set_errno (ENOMEM);
  101. UNLOCK;
  102. return -1;
  103. }
  104. if (__environ != last_environ)
  105. memcpy ((char *) new_environ, (char *) __environ,
  106. size * sizeof (char *));
  107. memcpy (new_environ[size], name, namelen);
  108. new_environ[size][namelen] = '=';
  109. memcpy (&new_environ[size][namelen + 1], value, vallen);
  110. new_environ[size + 1] = NULL;
  111. last_environ = __environ = new_environ;
  112. }
  113. else if (replace)
  114. {
  115. size_t len = strlen (*ep);
  116. if (len + 1 < namelen + 1 + vallen)
  117. {
  118. /* The existing string is too short; malloc a new one. */
  119. char *new_string = (char *) malloc (namelen + 1 + vallen);
  120. if (new_string == NULL)
  121. {
  122. UNLOCK;
  123. return -1;
  124. }
  125. *ep = new_string;
  126. }
  127. memcpy (*ep, name, namelen);
  128. (*ep)[namelen] = '=';
  129. memcpy (&(*ep)[namelen + 1], value, vallen);
  130. }
  131. UNLOCK;
  132. return 0;
  133. }
  134. void
  135. unsetenv (const char *name)
  136. {
  137. const size_t len = strlen (name);
  138. char **ep;
  139. LOCK;
  140. for (ep = __environ; *ep; ++ep)
  141. if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
  142. {
  143. /* Found it. Remove this pointer by moving later ones back. */
  144. char **dp = ep;
  145. do
  146. dp[0] = dp[1];
  147. while (*dp++);
  148. /* Continue the loop in case NAME appears again. */
  149. }
  150. UNLOCK;
  151. }