setenv.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* Copyright (C) 1992, 1995-2003, 2005-2023 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #if !_LIBC
  14. /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
  15. optimizes away the name == NULL test below. */
  16. # define _GL_ARG_NONNULL(params)
  17. # define _GL_USE_STDLIB_ALLOC 1
  18. # include <config.h>
  19. #endif
  20. #include <alloca.h>
  21. /* Specification. */
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #ifndef __set_errno
  25. # define __set_errno(ev) ((errno) = (ev))
  26. #endif
  27. #include <string.h>
  28. #if _LIBC || HAVE_UNISTD_H
  29. # include <unistd.h>
  30. #endif
  31. #if !_LIBC
  32. # include "malloca.h"
  33. #endif
  34. #if _LIBC || !HAVE_SETENV
  35. #if !_LIBC
  36. # define __environ environ
  37. #endif
  38. #if _LIBC
  39. /* This lock protects against simultaneous modifications of 'environ'. */
  40. # include <bits/libc-lock.h>
  41. __libc_lock_define_initialized (static, envlock)
  42. # define LOCK __libc_lock_lock (envlock)
  43. # define UNLOCK __libc_lock_unlock (envlock)
  44. #else
  45. # define LOCK
  46. # define UNLOCK
  47. #endif
  48. /* In the GNU C library we must keep the namespace clean. */
  49. #ifdef _LIBC
  50. # define setenv __setenv
  51. # define clearenv __clearenv
  52. # define tfind __tfind
  53. # define tsearch __tsearch
  54. #endif
  55. /* In the GNU C library implementation we try to be more clever and
  56. allow arbitrarily many changes of the environment given that the used
  57. values are from a small set. Outside glibc this will eat up all
  58. memory after a while. */
  59. #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
  60. && (defined __GNUC__ || defined __clang__))
  61. # define USE_TSEARCH 1
  62. # include <search.h>
  63. typedef int (*compar_fn_t) (const void *, const void *);
  64. /* This is a pointer to the root of the search tree with the known
  65. values. */
  66. static void *known_values;
  67. # define KNOWN_VALUE(Str) \
  68. ({ \
  69. void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \
  70. value != NULL ? *(char **) value : NULL; \
  71. })
  72. # define STORE_VALUE(Str) \
  73. tsearch (Str, &known_values, (compar_fn_t) strcmp)
  74. #else
  75. # undef USE_TSEARCH
  76. # define KNOWN_VALUE(Str) NULL
  77. # define STORE_VALUE(Str) do { } while (0)
  78. #endif
  79. /* If this variable is not a null pointer we allocated the current
  80. environment. */
  81. static char **last_environ;
  82. /* This function is used by 'setenv' and 'putenv'. The difference between
  83. the two functions is that for the former must create a new string which
  84. is then placed in the environment, while the argument of 'putenv'
  85. must be used directly. This is all complicated by the fact that we try
  86. to reuse values once generated for a 'setenv' call since we can never
  87. free the strings. */
  88. int
  89. __add_to_environ (const char *name, const char *value, const char *combined,
  90. int replace)
  91. {
  92. char **ep;
  93. size_t size;
  94. const size_t namelen = strlen (name);
  95. const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
  96. LOCK;
  97. /* We have to get the pointer now that we have the lock and not earlier
  98. since another thread might have created a new environment. */
  99. ep = __environ;
  100. size = 0;
  101. if (ep != NULL)
  102. {
  103. for (; *ep != NULL; ++ep)
  104. if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
  105. break;
  106. else
  107. ++size;
  108. }
  109. if (ep == NULL || *ep == NULL)
  110. {
  111. char **new_environ;
  112. #ifdef USE_TSEARCH
  113. char *new_value;
  114. #endif
  115. /* We allocated this space; we can extend it. */
  116. new_environ =
  117. (char **) (last_environ == NULL
  118. ? malloc ((size + 2) * sizeof (char *))
  119. : realloc (last_environ, (size + 2) * sizeof (char *)));
  120. if (new_environ == NULL)
  121. {
  122. /* It's easier to set errno to ENOMEM than to rely on the
  123. 'malloc-posix' and 'realloc-posix' gnulib modules. */
  124. __set_errno (ENOMEM);
  125. UNLOCK;
  126. return -1;
  127. }
  128. /* If the whole entry is given add it. */
  129. if (combined != NULL)
  130. /* We must not add the string to the search tree since it belongs
  131. to the user. */
  132. new_environ[size] = (char *) combined;
  133. else
  134. {
  135. /* See whether the value is already known. */
  136. #ifdef USE_TSEARCH
  137. # ifdef _LIBC
  138. new_value = (char *) alloca (namelen + 1 + vallen);
  139. __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
  140. value, vallen);
  141. # else
  142. new_value = (char *) malloca (namelen + 1 + vallen);
  143. if (new_value == NULL)
  144. {
  145. __set_errno (ENOMEM);
  146. UNLOCK;
  147. return -1;
  148. }
  149. memcpy (new_value, name, namelen);
  150. new_value[namelen] = '=';
  151. memcpy (&new_value[namelen + 1], value, vallen);
  152. # endif
  153. new_environ[size] = KNOWN_VALUE (new_value);
  154. if (new_environ[size] == NULL)
  155. #endif
  156. {
  157. new_environ[size] = (char *) malloc (namelen + 1 + vallen);
  158. if (new_environ[size] == NULL)
  159. {
  160. #if defined USE_TSEARCH && !defined _LIBC
  161. freea (new_value);
  162. #endif
  163. __set_errno (ENOMEM);
  164. UNLOCK;
  165. return -1;
  166. }
  167. #ifdef USE_TSEARCH
  168. memcpy (new_environ[size], new_value, namelen + 1 + vallen);
  169. #else
  170. memcpy (new_environ[size], name, namelen);
  171. new_environ[size][namelen] = '=';
  172. memcpy (&new_environ[size][namelen + 1], value, vallen);
  173. #endif
  174. /* And save the value now. We cannot do this when we remove
  175. the string since then we cannot decide whether it is a
  176. user string or not. */
  177. STORE_VALUE (new_environ[size]);
  178. }
  179. #if defined USE_TSEARCH && !defined _LIBC
  180. freea (new_value);
  181. #endif
  182. }
  183. if (__environ != last_environ)
  184. memcpy ((char *) new_environ, (char *) __environ,
  185. size * sizeof (char *));
  186. new_environ[size + 1] = NULL;
  187. last_environ = __environ = new_environ;
  188. }
  189. else if (replace)
  190. {
  191. char *np;
  192. /* Use the user string if given. */
  193. if (combined != NULL)
  194. np = (char *) combined;
  195. else
  196. {
  197. #ifdef USE_TSEARCH
  198. char *new_value;
  199. # ifdef _LIBC
  200. new_value = alloca (namelen + 1 + vallen);
  201. __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
  202. value, vallen);
  203. # else
  204. new_value = malloca (namelen + 1 + vallen);
  205. if (new_value == NULL)
  206. {
  207. __set_errno (ENOMEM);
  208. UNLOCK;
  209. return -1;
  210. }
  211. memcpy (new_value, name, namelen);
  212. new_value[namelen] = '=';
  213. memcpy (&new_value[namelen + 1], value, vallen);
  214. # endif
  215. np = KNOWN_VALUE (new_value);
  216. if (np == NULL)
  217. #endif
  218. {
  219. np = (char *) malloc (namelen + 1 + vallen);
  220. if (np == NULL)
  221. {
  222. #if defined USE_TSEARCH && !defined _LIBC
  223. freea (new_value);
  224. #endif
  225. __set_errno (ENOMEM);
  226. UNLOCK;
  227. return -1;
  228. }
  229. #ifdef USE_TSEARCH
  230. memcpy (np, new_value, namelen + 1 + vallen);
  231. #else
  232. memcpy (np, name, namelen);
  233. np[namelen] = '=';
  234. memcpy (&np[namelen + 1], value, vallen);
  235. #endif
  236. /* And remember the value. */
  237. STORE_VALUE (np);
  238. }
  239. #if defined USE_TSEARCH && !defined _LIBC
  240. freea (new_value);
  241. #endif
  242. }
  243. *ep = np;
  244. }
  245. UNLOCK;
  246. return 0;
  247. }
  248. int
  249. setenv (const char *name, const char *value, int replace)
  250. {
  251. if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
  252. {
  253. __set_errno (EINVAL);
  254. return -1;
  255. }
  256. return __add_to_environ (name, value, NULL, replace);
  257. }
  258. /* The 'clearenv' was planned to be added to POSIX.1 but probably
  259. never made it. Nevertheless the POSIX.9 standard (POSIX bindings
  260. for Fortran 77) requires this function. */
  261. int
  262. clearenv (void)
  263. {
  264. LOCK;
  265. if (__environ == last_environ && __environ != NULL)
  266. {
  267. /* We allocated this environment so we can free it. */
  268. free (__environ);
  269. last_environ = NULL;
  270. }
  271. /* Clear the environment pointer removes the whole environment. */
  272. __environ = NULL;
  273. UNLOCK;
  274. return 0;
  275. }
  276. #ifdef _LIBC
  277. static void
  278. free_mem (void)
  279. {
  280. /* Remove all traces. */
  281. clearenv ();
  282. /* Now remove the search tree. */
  283. __tdestroy (known_values, free);
  284. known_values = NULL;
  285. }
  286. text_set_element (__libc_subfreeres, free_mem);
  287. # undef setenv
  288. # undef clearenv
  289. weak_alias (__setenv, setenv)
  290. weak_alias (__clearenv, clearenv)
  291. #endif
  292. #endif /* _LIBC || !HAVE_SETENV */
  293. /* The rest of this file is called into use when replacing an existing
  294. but buggy setenv. Known bugs include failure to diagnose invalid
  295. name, and consuming a leading '=' from value. */
  296. #if HAVE_SETENV
  297. # undef setenv
  298. # if !HAVE_DECL_SETENV
  299. extern int setenv (const char *, const char *, int);
  300. # endif
  301. # define STREQ(a, b) (strcmp (a, b) == 0)
  302. int
  303. rpl_setenv (const char *name, const char *value, int replace)
  304. {
  305. int result;
  306. if (!name || !*name || strchr (name, '='))
  307. {
  308. errno = EINVAL;
  309. return -1;
  310. }
  311. /* Call the real setenv even if replace is 0, in case implementation
  312. has underlying data to update, such as when environ changes. */
  313. result = setenv (name, value, replace);
  314. if (result == 0 && replace && *value == '=')
  315. {
  316. char *tmp = getenv (name);
  317. if (!STREQ (tmp, value))
  318. {
  319. int saved_errno;
  320. size_t len = strlen (value);
  321. tmp = malloca (len + 2);
  322. /* Since leading '=' is eaten, double it up. */
  323. *tmp = '=';
  324. memcpy (tmp + 1, value, len + 1);
  325. result = setenv (name, tmp, replace);
  326. saved_errno = errno;
  327. freea (tmp);
  328. errno = saved_errno;
  329. }
  330. }
  331. return result;
  332. }
  333. #endif /* HAVE_SETENV */