]>
Commit | Line | Data |
---|---|---|
cce855bc JA |
1 | /* getenv.c - get environment variable value from the shell's variable |
2 | list. */ | |
3 | ||
7117c2d2 | 4 | /* Copyright (C) 1997-2002 Free Software Foundation, Inc. |
cce855bc JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
cce855bc | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
cce855bc | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
20 | */ | |
cce855bc JA |
21 | |
22 | #include <config.h> | |
23 | ||
24 | #if defined (CAN_REDEFINE_GETENV) | |
25 | ||
26 | #if defined (HAVE_UNISTD_H) | |
27 | # include <unistd.h> | |
28 | #endif | |
29 | ||
30 | #include <bashansi.h> | |
7117c2d2 | 31 | #include <errno.h> |
cce855bc JA |
32 | #include <shell.h> |
33 | ||
7117c2d2 JA |
34 | #ifndef errno |
35 | extern int errno; | |
36 | #endif | |
37 | ||
cce855bc JA |
38 | extern char **environ; |
39 | ||
40 | /* We supply our own version of getenv () because we want library | |
41 | routines to get the changed values of exported variables. */ | |
42 | ||
43 | /* The NeXT C library has getenv () defined and used in the same file. | |
44 | This screws our scheme. However, Bash will run on the NeXT using | |
45 | the C library getenv (), since right now the only environment variable | |
46 | that we care about is HOME, and that is already defined. */ | |
47 | static char *last_tempenv_value = (char *)NULL; | |
48 | ||
49 | char * | |
50 | getenv (name) | |
cce855bc | 51 | const char *name; |
cce855bc JA |
52 | { |
53 | SHELL_VAR *var; | |
54 | ||
7117c2d2 JA |
55 | if (name == 0 || *name == '\0') |
56 | return ((char *)NULL); | |
57 | ||
cce855bc JA |
58 | var = find_tempenv_variable ((char *)name); |
59 | if (var) | |
60 | { | |
61 | FREE (last_tempenv_value); | |
62 | ||
bb70624e | 63 | last_tempenv_value = value_cell (var) ? savestring (value_cell (var)) : (char *)NULL; |
cce855bc JA |
64 | return (last_tempenv_value); |
65 | } | |
66 | else if (shell_variables) | |
67 | { | |
68 | var = find_variable ((char *)name); | |
69 | if (var && exported_p (var)) | |
70 | return (value_cell (var)); | |
71 | } | |
72 | else | |
73 | { | |
74 | register int i, len; | |
75 | ||
76 | /* In some cases, s5r3 invokes getenv() before main(); BSD systems | |
77 | using gprof also exhibit this behavior. This means that | |
78 | shell_variables will be 0 when this is invoked. We look up the | |
79 | variable in the real environment in that case. */ | |
80 | ||
81 | for (i = 0, len = strlen (name); environ[i]; i++) | |
82 | { | |
83 | if ((STREQN (environ[i], name, len)) && (environ[i][len] == '=')) | |
84 | return (environ[i] + len + 1); | |
85 | } | |
86 | } | |
87 | ||
88 | return ((char *)NULL); | |
89 | } | |
90 | ||
91 | /* Some versions of Unix use _getenv instead. */ | |
92 | char * | |
93 | _getenv (name) | |
cce855bc | 94 | const char *name; |
cce855bc JA |
95 | { |
96 | return (getenv (name)); | |
97 | } | |
7117c2d2 JA |
98 | |
99 | /* SUSv3 says argument is a `char *'; BSD implementations disagree */ | |
100 | int | |
101 | putenv (str) | |
102 | #ifndef HAVE_STD_PUTENV | |
103 | const char *str; | |
104 | #else | |
105 | char *str; | |
106 | #endif | |
107 | { | |
108 | SHELL_VAR *var; | |
109 | char *name, *value; | |
110 | int offset; | |
111 | ||
112 | if (str == 0 || *str == '\0') | |
113 | { | |
114 | errno = EINVAL; | |
115 | return -1; | |
116 | } | |
117 | ||
b80f6443 | 118 | offset = assignment (str, 0); |
7117c2d2 JA |
119 | if (str[offset] != '=') |
120 | { | |
121 | errno = EINVAL; | |
122 | return -1; | |
123 | } | |
124 | name = savestring (str); | |
125 | name[offset] = 0; | |
126 | ||
127 | value = name + offset + 1; | |
128 | ||
129 | /* XXX - should we worry about readonly here? */ | |
95732b49 | 130 | var = bind_variable (name, value, 0); |
7117c2d2 JA |
131 | if (var == 0) |
132 | { | |
133 | errno = EINVAL; | |
134 | return -1; | |
135 | } | |
136 | ||
137 | VUNSETATTR (var, att_invisible); | |
138 | VSETATTR (var, att_exported); | |
139 | ||
140 | return 0; | |
141 | } | |
142 | ||
143 | #if 0 | |
144 | int | |
145 | _putenv (name) | |
146 | #ifndef HAVE_STD_PUTENV | |
147 | const char *name; | |
148 | #else | |
149 | char *name; | |
150 | #endif | |
151 | { | |
152 | return putenv (name); | |
153 | } | |
154 | #endif | |
155 | ||
156 | int | |
157 | setenv (name, value, rewrite) | |
158 | const char *name; | |
159 | const char *value; | |
160 | int rewrite; | |
161 | { | |
162 | SHELL_VAR *var; | |
163 | char *v; | |
164 | ||
165 | if (name == 0 || *name == '\0' || strchr (name, '=') != 0) | |
166 | { | |
167 | errno = EINVAL; | |
168 | return -1; | |
169 | } | |
170 | ||
171 | var = 0; | |
b80f6443 | 172 | v = (char *)value; /* some compilers need explicit cast */ |
7117c2d2 JA |
173 | /* XXX - should we worry about readonly here? */ |
174 | if (rewrite == 0) | |
175 | var = find_variable (name); | |
176 | ||
177 | if (var == 0) | |
95732b49 | 178 | var = bind_variable (name, v, 0); |
7117c2d2 JA |
179 | |
180 | if (var == 0) | |
181 | return -1; | |
182 | ||
183 | VUNSETATTR (var, att_invisible); | |
184 | VSETATTR (var, att_exported); | |
185 | ||
186 | return 0; | |
187 | } | |
188 | ||
189 | #if 0 | |
190 | int | |
191 | _setenv (name, value, rewrite) | |
192 | const char *name; | |
193 | const char *value; | |
194 | int rewrite; | |
195 | { | |
196 | return setenv (name, value, rewrite); | |
197 | } | |
198 | #endif | |
199 | ||
200 | /* SUSv3 says unsetenv returns int; existing implementations (BSD) disagree. */ | |
201 | ||
202 | #ifdef HAVE_STD_UNSETENV | |
203 | #define UNSETENV_RETURN(N) return(N) | |
204 | #define UNSETENV_RETTYPE int | |
205 | #else | |
206 | #define UNSETENV_RETURN(N) return | |
207 | #define UNSETENV_RETTYPE void | |
208 | #endif | |
209 | ||
210 | UNSETENV_RETTYPE | |
211 | unsetenv (name) | |
212 | const char *name; | |
213 | { | |
214 | if (name == 0 || *name == '\0' || strchr (name, '=') != 0) | |
215 | { | |
216 | errno = EINVAL; | |
217 | UNSETENV_RETURN(-1); | |
218 | } | |
219 | ||
220 | /* XXX - should we just remove the export attribute here? */ | |
221 | #if 1 | |
222 | unbind_variable (name); | |
223 | #else | |
224 | SHELL_VAR *v; | |
225 | ||
226 | v = find_variable (name); | |
227 | if (v) | |
228 | VUNSETATTR (v, att_exported); | |
229 | #endif | |
230 | ||
231 | UNSETENV_RETURN(0); | |
232 | } | |
cce855bc | 233 | #endif /* CAN_REDEFINE_GETENV */ |