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 it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 2, or (at your option) any later 11 version. 12 13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 You should have received a copy of the GNU General Public License along 19 with Bash; see the file COPYING. If not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ 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 35extern int errno; 36#endif 37 38extern 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. */ 47static char *last_tempenv_value = (char *)NULL; 48 49char * 50getenv (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. */ 92char * 93_getenv (name) 94 const char *name; 95{ 96 return (getenv (name)); 97} 98 99/* SUSv3 says argument is a `char *'; BSD implementations disagree */ 100int 101putenv (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 144int 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 156int 157setenv (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 190int 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 210UNSETENV_RETTYPE 211unsetenv (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 */ 234