/* getenv.c - get environment variable value from the shell's variable list. */ /* Copyright (C) 1997-2002 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. Bash is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Bash is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bash; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ #include #if defined (CAN_REDEFINE_GETENV) #if defined (HAVE_UNISTD_H) # include #endif #include #include #include #ifndef errno extern int errno; #endif extern char **environ; /* We supply our own version of getenv () because we want library routines to get the changed values of exported variables. */ /* The NeXT C library has getenv () defined and used in the same file. This screws our scheme. However, Bash will run on the NeXT using the C library getenv (), since right now the only environment variable that we care about is HOME, and that is already defined. */ static char *last_tempenv_value = (char *)NULL; char * getenv (name) const char *name; { SHELL_VAR *var; if (name == 0 || *name == '\0') return ((char *)NULL); var = find_tempenv_variable ((char *)name); if (var) { FREE (last_tempenv_value); last_tempenv_value = value_cell (var) ? savestring (value_cell (var)) : (char *)NULL; return (last_tempenv_value); } else if (shell_variables) { var = find_variable ((char *)name); if (var && exported_p (var)) return (value_cell (var)); } else { register int i, len; /* In some cases, s5r3 invokes getenv() before main(); BSD systems using gprof also exhibit this behavior. This means that shell_variables will be 0 when this is invoked. We look up the variable in the real environment in that case. */ for (i = 0, len = strlen (name); environ[i]; i++) { if ((STREQN (environ[i], name, len)) && (environ[i][len] == '=')) return (environ[i] + len + 1); } } return ((char *)NULL); } /* Some versions of Unix use _getenv instead. */ char * _getenv (name) const char *name; { return (getenv (name)); } /* SUSv3 says argument is a `char *'; BSD implementations disagree */ int putenv (str) #ifndef HAVE_STD_PUTENV const char *str; #else char *str; #endif { SHELL_VAR *var; char *name, *value; int offset; if (str == 0 || *str == '\0') { errno = EINVAL; return -1; } offset = assignment (str); if (str[offset] != '=') { errno = EINVAL; return -1; } name = savestring (str); name[offset] = 0; value = name + offset + 1; /* XXX - should we worry about readonly here? */ var = bind_variable (name, value); if (var == 0) { errno = EINVAL; return -1; } VUNSETATTR (var, att_invisible); VSETATTR (var, att_exported); return 0; } #if 0 int _putenv (name) #ifndef HAVE_STD_PUTENV const char *name; #else char *name; #endif { return putenv (name); } #endif int setenv (name, value, rewrite) char *name; char *value; int rewrite; { SHELL_VAR *var; char *v; if (name == 0 || *name == '\0' || strchr (name, '=') != 0) { errno = EINVAL; return -1; } var = 0; v = value; /* XXX - should we worry about readonly here? */ if (rewrite == 0) var = find_variable (name); if (var == 0) var = bind_variable (name, v); if (var == 0) return -1; VUNSETATTR (var, att_invisible); VSETATTR (var, att_exported); return 0; } #if 0 int _setenv (name, value, rewrite) char *name; char *value; int rewrite; { return setenv (name, value, rewrite); } #endif /* SUSv3 says unsetenv returns int; existing implementations (BSD) disagree. */ #ifdef HAVE_STD_UNSETENV #define UNSETENV_RETURN(N) return(N) #define UNSETENV_RETTYPE int #else #define UNSETENV_RETURN(N) return #define UNSETENV_RETTYPE void #endif UNSETENV_RETTYPE unsetenv (name) char *name; { if (name == 0 || *name == '\0' || strchr (name, '=') != 0) { errno = EINVAL; UNSETENV_RETURN(-1); } /* XXX - should we just remove the export attribute here? */ #if 1 unbind_variable (name); #else SHELL_VAR *v; v = find_variable (name); if (v) VUNSETATTR (v, att_exported); #endif UNSETENV_RETURN(0); } #endif /* CAN_REDEFINE_GETENV */