No specific user configuration
[platform/upstream/bash.git] / lib / sh / getenv.c
1 /* getenv.c - get environment variable value from the shell's variable
2               list. */
3
4 /* Copyright (C) 1997-2002 Free Software Foundation, Inc.
5
6    This file is part of GNU Bash, the Bourne Again SHell.
7
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.
12
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.
17
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 */
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>
31 #include <errno.h>
32 #include <shell.h>
33
34 #ifndef errno
35 extern int errno;
36 #endif
37
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)
51      const char *name;
52 {
53   SHELL_VAR *var;
54
55   if (name == 0 || *name == '\0')
56     return ((char *)NULL);
57
58   var = find_tempenv_variable ((char *)name);
59   if (var)
60     {
61       FREE (last_tempenv_value);
62
63       last_tempenv_value = value_cell (var) ? savestring (value_cell (var)) : (char *)NULL;
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)
94      const char *name;
95 {
96   return (getenv (name));
97 }
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
118   offset = assignment (str, 0);
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? */
130   var = bind_variable (name, value, 0);
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;
172   v = (char *)value;    /* some compilers need explicit cast */
173   /* XXX - should we worry about readonly here? */
174   if (rewrite == 0)
175     var = find_variable (name);
176
177   if (var == 0)
178     var = bind_variable (name, v, 0);
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 }
233 #endif /* CAN_REDEFINE_GETENV */