1 /* xputenv.c: set an environment variable without return. */
2
3 /* Copyright 1993-98, 2008, 2009 Karl Berry.
4 Copyright 2003-05 Olaf Weber.
5
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.
10
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.
15
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/>. */
18
19
20 #include <kpathsea/config.h>
21 #include <kpathsea/types.h>
22
23 #ifdef WIN32
24 #include <stdlib.h>
25 #else
26 #if !HAVE_DECL_PUTENV
27 extern int putenv (char* entry);
28 #endif
29 #endif /* not WIN32 */
30
31 /*
32 * We have different arguments from the "standard" function. A separate
33 * var and value tends to be much more practical.
34 *
35 * The standards for putenv are clear: put the passed string into the
36 * environment, and if you alter that string, the environment changes.
37 * Of course various implementations are broken in a number of ways,
38 * which include making copies of the passed string, and more.
39 */
40 void
kpathsea_xputenv(kpathsea kpse,const char * var,const char * value)41 kpathsea_xputenv(kpathsea kpse, const char *var, const char *value)
42 {
43 char *cur_item;
44 char *old_item;
45 char *new_item;
46 size_t var_lim;
47 int cur_loc;
48
49 /* kpse_debug2(KPSE_DEBUG_VARS, "kpse_putenv($%s,%s)", var, value); */
50
51 old_item = NULL;
52 cur_item = concat3(var, "=", value);
53 /* Include '=' in length. */
54 var_lim = strlen(var) + 1;
55
56 /* Have we stored something for this value already? */
57 for (cur_loc = 0; cur_loc != kpse->saved_count; ++cur_loc) {
58 if (strncmp(kpse->saved_env[cur_loc], cur_item, var_lim) == 0) {
59 /* Get the old value. We need this is case another part
60 * of the program didn't use us to change the environment.
61 */
62 old_item = getenv(var);
63 break;
64 }
65 }
66
67 if (old_item && strcmp(old_item, cur_item+var_lim) == 0) {
68 /* Set same value as is in environment, don't bother to set. */
69 free(cur_item);
70 return;
71 } else {
72 /* We set a different value. */
73 if (putenv(cur_item) < 0)
74 LIB_FATAL1("putenv(%s)", cur_item);
75 /* Get the new string. */
76 new_item = getenv(var);
77 if (new_item != cur_item+var_lim) {
78 /* Our new string isn't used, don't keep it around. */
79 free(cur_item);
80 return;
81 }
82 }
83
84 /* If we get here, it means getenv() returned a reference to cur_item.
85 So we save cur_item, and free the old string we also owned. */
86 if (cur_loc == kpse->saved_count) {
87 /* No old string. */
88 kpse->saved_count++;
89 XRETALLOC(kpse->saved_env, kpse->saved_count, char *);
90 } else {
91 /* We owned the old string. */
92 free(kpse->saved_env[cur_loc]);
93 }
94 kpse->saved_env[cur_loc] = cur_item;
95
96 return;
97 }
98
99 /* A special case for setting a variable to a numeric value
100 (specifically, KPATHSEA_DPI). We don't need to dynamically allocate
101 and free the string for the number, since it's saved as part of the
102 environment value. */
103
104 void
kpathsea_xputenv_int(kpathsea kpse,const_string var_name,int num)105 kpathsea_xputenv_int (kpathsea kpse, const_string var_name, int num)
106 {
107 char str[MAX_INT_LENGTH];
108 sprintf (str, "%d", num);
109
110 kpathsea_xputenv (kpse, var_name, str);
111 }
112
113 #if defined (KPSE_COMPAT_API)
114 void
xputenv(const char * var,const char * value)115 xputenv (const char *var, const char *value)
116 {
117 kpathsea_xputenv (kpse_def, var, value);
118 }
119
120 void
xputenv_int(const_string var_name,int num)121 xputenv_int (const_string var_name, int num)
122 {
123 kpathsea_xputenv_int(kpse_def, var_name, num);
124 }
125 #endif
126