1 /* xputenv.c: set an environment variable without return. */
3 /* Copyright 1993-98, 2008 Karl Berry.
4 Copyright 2003-05 Olaf Weber.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; if not, see <http://www.gnu.org/licenses/>. */
20 #include <kpathsea/config.h>
25 /* Avoid implicit declaration warning. But since some systems do
26 declare it, don't use a prototype, for fear of conflicts. */
28 #endif /* not WIN32 */
30 /* These record the strings we've set and have to keep around.
31 * This function can be called many times during a run, and this
32 * allows us to reclaim memory we allocated.
34 static char **saved_env;
35 static int saved_count;
38 * We have different arguments from the "standard" function. A separate
39 * var and value tends to be much more practical.
41 * The standards for putenv are clear: put the passed string into the
42 * environment, and if you alter that string, the environment changes.
43 * Of course various implementations are broken in a number of ways,
44 * which include making copies of the passed string, and more.
47 xputenv(const char *var, const char *value)
55 /* kpse_debug2(KPSE_DEBUG_VARS, "kpse_putenv($%s,%s)", var, value); */
58 cur_item = concat3(var, "=", value);
59 /* Include '=' in length. */
60 var_lim = strlen(var) + 1;
62 /* Have we stored something for this value already? */
63 for (cur_loc = 0; cur_loc != saved_count; ++cur_loc) {
64 if (strncmp(saved_env[cur_loc], cur_item, var_lim) == 0) {
65 /* Get the old value. We need this is case another part
66 * of the program didn't use us to change the environment.
68 old_item = getenv(var);
73 if (old_item && strcmp(old_item, cur_item+var_lim) == 0) {
74 /* Set same value as is in environment, don't bother to set. */
78 /* We set a different value. */
79 if (putenv(cur_item) < 0)
80 FATAL1("putenv(%s)", cur_item);
81 /* Get the new string. */
82 new_item = getenv(var);
83 if (new_item != cur_item+var_lim) {
84 /* Our new string isn't used, don't keep it around. */
90 /* If we get here, it means getenv() returned a reference to cur_item.
91 * So we save cur_item, and free the old string we also owned.
93 if (cur_loc == saved_count) {
96 saved_env = XRETALLOC(saved_env, saved_count, char *);
98 /* We owned the old string. */
99 free(saved_env[cur_loc]);
101 saved_env[cur_loc] = cur_item;
106 /* A special case for setting a variable to a numeric value
107 (specifically, KPATHSEA_DPI). We don't need to dynamically allocate
108 and free the string for the number, since it's saved as part of the
109 environment value. */
112 xputenv_int P2C(const_string, var_name, int, num)
114 char str[MAX_INT_LENGTH];
115 sprintf (str, "%d", num);
117 xputenv (var_name, str);