Imported from ../bash-2.05.tar.gz.
This commit is contained in:
438
variables.c
438
variables.c
@@ -99,7 +99,7 @@ char **function_env = (char **)NULL;
|
||||
|
||||
/* The array of shell assignments which are made only in the environment
|
||||
for the execution of a shell builtin command which may cause more than
|
||||
one command to be executed (e.g., "source"). */
|
||||
one command to be executed (e.g., "eval" or "source"). */
|
||||
char **builtin_env = (char **)NULL;
|
||||
|
||||
/* Some funky variables which are known about specially. Here is where
|
||||
@@ -137,6 +137,7 @@ static void initialize_dynamic_variables ();
|
||||
static void make_vers_array ();
|
||||
static void sbrand (); /* set bash random number generator. */
|
||||
static int qsort_var_comp ();
|
||||
static SHELL_VAR *bind_tempenv_variable ();
|
||||
|
||||
/* Make VAR be auto-exported. VAR is a pointer to a SHELL_VAR. */
|
||||
#define set_auto_export(var) \
|
||||
@@ -167,17 +168,17 @@ initialize_shell_variables (env, privmode)
|
||||
while ((c = *string++) && c != '=')
|
||||
;
|
||||
if (string[-1] == '=')
|
||||
char_index = string - name - 1;
|
||||
char_index = string - name - 1;
|
||||
|
||||
/* If there are weird things in the environment, like `=xxx' or a
|
||||
string without an `=', just skip them. */
|
||||
if (char_index == 0)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
/* ASSERT(name[char_index] == '=') */
|
||||
name[char_index] = '\0';
|
||||
/* Now, name = env variable name, string = env variable value, and
|
||||
char_index == strlen (name) */
|
||||
char_index == strlen (name) */
|
||||
|
||||
/* If exported function, define it now. */
|
||||
if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
|
||||
@@ -231,38 +232,14 @@ initialize_shell_variables (env, privmode)
|
||||
|
||||
name[char_index] = '=';
|
||||
/* temp_var can be NULL if it was an exported function with a syntax
|
||||
error (a different bug, but it still shouldn't dump core). */
|
||||
error (a different bug, but it still shouldn't dump core). */
|
||||
if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
|
||||
{
|
||||
CACHE_IMPORTSTR (temp_var, name);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got PWD from the environment, update our idea of the current
|
||||
working directory. In any case, make sure that PWD exists before
|
||||
checking it. It is possible for getcwd () to fail on shell startup,
|
||||
and in that case, PWD would be undefined. */
|
||||
temp_var = find_variable ("PWD");
|
||||
if (temp_var && imported_p (temp_var) &&
|
||||
(temp_string = value_cell (temp_var)) &&
|
||||
same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
|
||||
set_working_directory (temp_string);
|
||||
else
|
||||
{
|
||||
temp_string = get_working_directory ("shell-init");
|
||||
if (temp_string)
|
||||
{
|
||||
temp_var = bind_variable ("PWD", temp_string);
|
||||
set_auto_export (temp_var);
|
||||
free (temp_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* According to the Single Unix Specification, v2, $OLDPWD is an
|
||||
`environment variable' and therefore should be auto-exported.
|
||||
Make a dummy invisible variable for OLDPWD, and mark it as exported. */
|
||||
temp_var = bind_variable ("OLDPWD", (char *)NULL);
|
||||
VSETATTR (temp_var, (att_exported | att_invisible));
|
||||
set_pwd ();
|
||||
|
||||
/* Set up initial value of $_ */
|
||||
temp_var = bind_variable ("_", dollar_vars[0]);
|
||||
@@ -306,13 +283,14 @@ initialize_shell_variables (env, privmode)
|
||||
temp_var = bind_variable ("IFS", " \t\n");
|
||||
|
||||
/* Magic machine types. Pretty convenient. */
|
||||
temp_var = bind_variable ("HOSTTYPE", HOSTTYPE);
|
||||
temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
|
||||
set_auto_export (temp_var);
|
||||
temp_var = bind_variable ("OSTYPE", OSTYPE);
|
||||
temp_var = set_if_not ("OSTYPE", OSTYPE);
|
||||
set_auto_export (temp_var);
|
||||
temp_var = bind_variable ("MACHTYPE", MACHTYPE);
|
||||
temp_var = set_if_not ("MACHTYPE", MACHTYPE);
|
||||
set_auto_export (temp_var);
|
||||
temp_var = bind_variable ("HOSTNAME", current_host_name);
|
||||
|
||||
temp_var = set_if_not ("HOSTNAME", current_host_name);
|
||||
set_auto_export (temp_var);
|
||||
|
||||
/* Default MAILCHECK for interactive shells. Defer the creation of a
|
||||
@@ -401,6 +379,12 @@ initialize_shell_variables (env, privmode)
|
||||
#endif /* HISTORY */
|
||||
|
||||
temp_var = find_variable ("SSH_CLIENT");
|
||||
if (temp_var && imported_p (temp_var))
|
||||
{
|
||||
VUNSETATTR (temp_var, att_exported);
|
||||
array_needs_making = 1;
|
||||
}
|
||||
temp_var = find_variable ("SSH2_CLIENT");
|
||||
if (temp_var && imported_p (temp_var))
|
||||
{
|
||||
VUNSETATTR (temp_var, att_exported);
|
||||
@@ -420,7 +404,7 @@ initialize_shell_variables (env, privmode)
|
||||
/* This function is not static so the tilde and readline libraries can
|
||||
use it. */
|
||||
char *
|
||||
get_home_dir ()
|
||||
sh_get_home_dir ()
|
||||
{
|
||||
if (current_user.home_dir == 0)
|
||||
get_current_user_info ();
|
||||
@@ -434,7 +418,7 @@ set_home_var ()
|
||||
|
||||
temp_var = find_variable ("HOME");
|
||||
if (temp_var == 0)
|
||||
temp_var = bind_variable ("HOME", get_home_dir ());
|
||||
temp_var = bind_variable ("HOME", sh_get_home_dir ());
|
||||
VSETATTR (temp_var, att_exported);
|
||||
}
|
||||
|
||||
@@ -460,13 +444,13 @@ get_bash_name ()
|
||||
{
|
||||
char *name;
|
||||
|
||||
if ((login_shell == 1) && (*shell_name != '/'))
|
||||
if ((login_shell == 1) && RELPATH(shell_name))
|
||||
{
|
||||
if (current_user.shell == 0)
|
||||
get_current_user_info ();
|
||||
get_current_user_info ();
|
||||
name = savestring (current_user.shell);
|
||||
}
|
||||
else if (*shell_name == '/')
|
||||
else if (ABSPATH(shell_name))
|
||||
name = savestring (shell_name);
|
||||
else if (shell_name[0] == '.' && shell_name[1] == '/')
|
||||
{
|
||||
@@ -475,10 +459,15 @@ get_bash_name ()
|
||||
int len;
|
||||
|
||||
cdir = get_string_value ("PWD");
|
||||
len = strlen (cdir);
|
||||
name = xmalloc (len + strlen (shell_name) + 1);
|
||||
strcpy (name, cdir);
|
||||
strcpy (name + len, shell_name + 1);
|
||||
if (cdir)
|
||||
{
|
||||
len = strlen (cdir);
|
||||
name = xmalloc (len + strlen (shell_name) + 1);
|
||||
strcpy (name, cdir);
|
||||
strcpy (name + len, shell_name + 1);
|
||||
}
|
||||
else
|
||||
name = savestring (shell_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -497,7 +486,7 @@ get_bash_name ()
|
||||
tname = make_absolute (shell_name, get_string_value ("PWD"));
|
||||
if (*shell_name == '.')
|
||||
{
|
||||
name = canonicalize_pathname (tname);
|
||||
name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
if (name == 0)
|
||||
name = tname;
|
||||
else
|
||||
@@ -574,6 +563,52 @@ initialize_shell_level ()
|
||||
adjust_shell_level (1);
|
||||
}
|
||||
|
||||
/* If we got PWD from the environment, update our idea of the current
|
||||
working directory. In any case, make sure that PWD exists before
|
||||
checking it. It is possible for getcwd () to fail on shell startup,
|
||||
and in that case, PWD would be undefined. If this is an interactive
|
||||
login shell, see if $HOME is the current working directory, and if
|
||||
that's not the same string as $PWD, set PWD=$HOME. */
|
||||
|
||||
void
|
||||
set_pwd ()
|
||||
{
|
||||
SHELL_VAR *temp_var, *home_var;
|
||||
char *temp_string, *home_string;
|
||||
|
||||
home_var = find_variable ("HOME");
|
||||
home_string = home_var ? value_cell (home_var) : (char *)NULL;
|
||||
|
||||
temp_var = find_variable ("PWD");
|
||||
if (temp_var && imported_p (temp_var) &&
|
||||
(temp_string = value_cell (temp_var)) &&
|
||||
same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
|
||||
set_working_directory (temp_string);
|
||||
else if (home_string && interactive_shell && login_shell &&
|
||||
same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
|
||||
{
|
||||
set_working_directory (home_string);
|
||||
temp_var = bind_variable ("PWD", home_string);
|
||||
set_auto_export (temp_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_string = get_working_directory ("shell-init");
|
||||
if (temp_string)
|
||||
{
|
||||
temp_var = bind_variable ("PWD", temp_string);
|
||||
set_auto_export (temp_var);
|
||||
free (temp_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* According to the Single Unix Specification, v2, $OLDPWD is an
|
||||
`environment variable' and therefore should be auto-exported.
|
||||
Make a dummy invisible variable for OLDPWD, and mark it as exported. */
|
||||
temp_var = bind_variable ("OLDPWD", (char *)NULL);
|
||||
VSETATTR (temp_var, (att_exported | att_invisible));
|
||||
}
|
||||
|
||||
/* Make a variable $PPID, which holds the pid of the shell's parent. */
|
||||
void
|
||||
set_ppid ()
|
||||
@@ -597,21 +632,21 @@ uidset ()
|
||||
|
||||
b = inttostr (current_user.uid, buff, sizeof (buff));
|
||||
v = find_variable ("UID");
|
||||
if (v)
|
||||
VUNSETATTR (v, att_readonly);
|
||||
|
||||
v = bind_variable ("UID", b);
|
||||
VSETATTR (v, (att_readonly | att_integer));
|
||||
if (v == 0)
|
||||
{
|
||||
v = bind_variable ("UID", b);
|
||||
VSETATTR (v, (att_readonly | att_integer));
|
||||
}
|
||||
|
||||
if (current_user.euid != current_user.uid)
|
||||
b = inttostr (current_user.euid, buff, sizeof (buff));
|
||||
|
||||
v = find_variable ("EUID");
|
||||
if (v)
|
||||
VUNSETATTR (v, att_readonly);
|
||||
|
||||
v = bind_variable ("EUID", b);
|
||||
VSETATTR (v, (att_readonly | att_integer));
|
||||
if (v == 0)
|
||||
{
|
||||
v = bind_variable ("EUID", b);
|
||||
VSETATTR (v, (att_readonly | att_integer));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -646,7 +681,7 @@ make_vers_array ()
|
||||
/* Set the environment variables $LINES and $COLUMNS in response to
|
||||
a window size change. */
|
||||
void
|
||||
set_lines_and_columns (lines, cols)
|
||||
sh_set_lines_and_columns (lines, cols)
|
||||
int lines, cols;
|
||||
{
|
||||
char val[32], *v;
|
||||
@@ -754,7 +789,8 @@ all_shell_functions ()
|
||||
return (all_vars (shell_functions));
|
||||
}
|
||||
|
||||
/* Print VARS to stdout in such a way that they can be read back in. */
|
||||
/* Print LIST (a list of shell variables) to stdout in such a way that
|
||||
they can be read back in. */
|
||||
void
|
||||
print_var_list (list)
|
||||
register SHELL_VAR **list;
|
||||
@@ -767,6 +803,23 @@ print_var_list (list)
|
||||
print_assignment (var);
|
||||
}
|
||||
|
||||
/* Print LIST (a list of shell functions) to stdout in such a way that
|
||||
they can be read back in. */
|
||||
void
|
||||
print_func_list (list)
|
||||
register SHELL_VAR **list;
|
||||
{
|
||||
register int i;
|
||||
register SHELL_VAR *var;
|
||||
|
||||
for (i = 0; list && (var = list[i]); i++)
|
||||
{
|
||||
printf ("%s ", var->name);
|
||||
print_var_function (var);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (NOTDEF)
|
||||
/* Print LIST (a linked list of shell variables) to stdout
|
||||
by printing the names, without the values. Used to support the
|
||||
@@ -793,7 +846,7 @@ print_assignment (var)
|
||||
{
|
||||
if (function_p (var) && var->value)
|
||||
{
|
||||
printf ("%s=", var->name);
|
||||
printf ("%s", var->name);
|
||||
print_var_function (var);
|
||||
printf ("\n");
|
||||
}
|
||||
@@ -822,9 +875,13 @@ print_var_value (var, quote)
|
||||
|
||||
if (var->value)
|
||||
{
|
||||
if (quote && contains_shell_metas (var->value))
|
||||
if (quote && sh_contains_shell_metas (var->value))
|
||||
{
|
||||
t = single_quote (var->value);
|
||||
#if 0
|
||||
t = sh_single_quote (var->value);
|
||||
#else
|
||||
t = ansic_quote (var->value, 0, (int *)0);
|
||||
#endif
|
||||
printf ("%s", t);
|
||||
free (t);
|
||||
}
|
||||
@@ -868,7 +925,7 @@ print_array_assignment (var, quoted)
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Dynamic Variable Extension */
|
||||
/* Dynamic Variable Extension */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
@@ -988,12 +1045,10 @@ assign_random (self, value)
|
||||
return (self);
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
get_random (var)
|
||||
SHELL_VAR *var;
|
||||
int
|
||||
get_random_number ()
|
||||
{
|
||||
int rv;
|
||||
char *p;
|
||||
|
||||
/* Reset for command and process substitution. */
|
||||
if (subshell_environment)
|
||||
@@ -1002,7 +1057,17 @@ get_random (var)
|
||||
do
|
||||
rv = brand ();
|
||||
while (rv == (int)last_random_value);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
get_random (var)
|
||||
SHELL_VAR *var;
|
||||
{
|
||||
int rv;
|
||||
char *p;
|
||||
|
||||
rv = get_random_number ();
|
||||
last_random_value = rv;
|
||||
p = itos ((int)rv);
|
||||
|
||||
@@ -1164,10 +1229,11 @@ initialize_dynamic_variables ()
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign);
|
||||
VSETATTR (v, att_noassign);
|
||||
#endif
|
||||
|
||||
INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
|
||||
VSETATTR (v, att_invisible);
|
||||
VSETATTR (v, att_invisible|att_noassign);
|
||||
}
|
||||
|
||||
/* How to get a pointer to the shell variable or function named NAME.
|
||||
@@ -1191,7 +1257,9 @@ find_variable_internal (name, search_tempenv)
|
||||
char *name;
|
||||
int search_tempenv;
|
||||
{
|
||||
SHELL_VAR *var = (SHELL_VAR *)NULL;
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = (SHELL_VAR *)NULL;
|
||||
|
||||
/* If explicitly requested, first look in the temporary environment for
|
||||
the variable. This allows constructs such as "foo=x eval 'echo $foo'"
|
||||
@@ -1235,11 +1303,11 @@ find_function (name)
|
||||
in the temporary environment. */
|
||||
char *
|
||||
get_string_value (var_name)
|
||||
char *var_name;
|
||||
const char *var_name;
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_variable (var_name);
|
||||
var = find_variable ((char *)var_name); /* XXX fix later */
|
||||
|
||||
if (!var)
|
||||
return (char *)NULL;
|
||||
@@ -1253,8 +1321,8 @@ get_string_value (var_name)
|
||||
|
||||
/* This is present for use by the tilde and readline libraries. */
|
||||
char *
|
||||
get_env_value (v)
|
||||
char *v;
|
||||
sh_get_env_value (v)
|
||||
const char *v;
|
||||
{
|
||||
return get_string_value (v);
|
||||
}
|
||||
@@ -1266,6 +1334,7 @@ make_local_variable (name)
|
||||
{
|
||||
SHELL_VAR *new_var, *old_var;
|
||||
BUCKET_CONTENTS *elt;
|
||||
int old_var_context;
|
||||
|
||||
/* local foo; local foo; is a no-op. */
|
||||
old_var = find_variable (name);
|
||||
@@ -1274,10 +1343,16 @@ make_local_variable (name)
|
||||
|
||||
/* Since this is called only from the local/declare/typeset code, we can
|
||||
call builtin_error here without worry (of course, it will also work
|
||||
for anything that sets this_command_name). */
|
||||
if (old_var && readonly_p (old_var))
|
||||
for anything that sets this_command_name). Variables with the `noassign'
|
||||
attribute may not be made local. The test against old_var's context
|
||||
level is to disallow local copies of readonly global variables (since I
|
||||
believe that this could be a security hole). Readonly copies of calling
|
||||
function local variables are OK. */
|
||||
if (old_var && (noassign_p (old_var) ||
|
||||
(readonly_p (old_var) && old_var->context == 0)))
|
||||
{
|
||||
builtin_error ("%s: readonly variable");
|
||||
if (readonly_p (old_var))
|
||||
builtin_error ("%s: readonly variable");
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
@@ -1378,6 +1453,10 @@ make_new_variable (name)
|
||||
entry->context = 0;
|
||||
entry->prev_context = (SHELL_VAR *)NULL;
|
||||
|
||||
/* Make sure we have a shell_variables hash table to add to. */
|
||||
if (shell_variables == 0)
|
||||
shell_variables = make_hash_table (0);
|
||||
|
||||
elt = add_hash_item (savestring (name), shell_variables);
|
||||
elt->data = (char *)entry;
|
||||
|
||||
@@ -1444,8 +1523,28 @@ bind_variable (name, value)
|
||||
char *name, *value;
|
||||
{
|
||||
char *newval;
|
||||
SHELL_VAR *entry;
|
||||
SHELL_VAR *entry, *tempenv_entry;
|
||||
int found_in_tempenv;
|
||||
|
||||
entry = (SHELL_VAR *)0;
|
||||
found_in_tempenv = 0;
|
||||
|
||||
/* If we have a temporary environment, look there first for the variable,
|
||||
and, if found, modify the value there before modifying it in the
|
||||
shell_variables table. This allows sourced scripts to modify values
|
||||
given to them in a temporary environment while modifying the variable
|
||||
value that the caller sees. */
|
||||
if (temporary_env || builtin_env || function_env)
|
||||
{
|
||||
tempenv_entry = find_tempenv_variable (name);
|
||||
if (tempenv_entry)
|
||||
{
|
||||
dispose_variable (tempenv_entry);
|
||||
tempenv_entry = bind_tempenv_variable (name, value);
|
||||
dispose_variable (tempenv_entry);
|
||||
}
|
||||
}
|
||||
|
||||
entry = var_lookup (name, shell_variables);
|
||||
|
||||
if (entry == 0)
|
||||
@@ -1453,20 +1552,17 @@ bind_variable (name, value)
|
||||
entry = make_new_variable (name);
|
||||
entry->value = make_variable_value (entry, value);
|
||||
}
|
||||
#if defined (ARRAY_VARS)
|
||||
else if (entry->assign_func && array_p (entry) == 0)
|
||||
#else
|
||||
else if (entry->assign_func)
|
||||
#endif
|
||||
else if (entry->assign_func) /* array vars have assign functions now */
|
||||
{
|
||||
INVALIDATE_EXPORTSTR (entry);
|
||||
return ((*(entry->assign_func)) (entry, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readonly_p (entry))
|
||||
if (readonly_p (entry) || noassign_p (entry))
|
||||
{
|
||||
report_error ("%s: readonly variable", name);
|
||||
if (readonly_p (entry))
|
||||
report_error ("%s: readonly variable", name);
|
||||
return (entry);
|
||||
}
|
||||
|
||||
@@ -1614,9 +1710,10 @@ bind_array_variable (name, ind, value)
|
||||
|
||||
if (entry == (SHELL_VAR *) 0)
|
||||
entry = make_new_array_variable (name);
|
||||
else if (readonly_p (entry))
|
||||
else if (readonly_p (entry) || noassign_p (entry))
|
||||
{
|
||||
report_error ("%s: readonly variable", name);
|
||||
if (readonly_p (entry))
|
||||
report_error ("%s: readonly variable", name);
|
||||
return (entry);
|
||||
}
|
||||
else if (array_p (entry) == 0)
|
||||
@@ -1644,9 +1741,10 @@ assign_array_from_string (name, value)
|
||||
var = find_variable (name);
|
||||
if (var == 0)
|
||||
var = make_new_array_variable (name);
|
||||
else if (readonly_p (var))
|
||||
else if (readonly_p (var) || noassign_p (var))
|
||||
{
|
||||
report_error ("%s: readonly variable", name);
|
||||
if (readonly_p (var))
|
||||
report_error ("%s: readonly variable", name);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
else if (array_p (var) == 0)
|
||||
@@ -1729,7 +1827,7 @@ assign_array_var_from_string (var, value)
|
||||
ni = 1;
|
||||
val = extract_array_assignment_list (value, &ni);
|
||||
if (val == 0)
|
||||
return var;
|
||||
return var;
|
||||
}
|
||||
else
|
||||
val = value;
|
||||
@@ -1810,7 +1908,7 @@ assign_array_var_from_string (var, value)
|
||||
}
|
||||
|
||||
if (integer_p (var))
|
||||
this_command_name = (char *)NULL; /* no command name for errors */
|
||||
this_command_name = (char *)NULL; /* no command name for errors */
|
||||
nval = make_variable_value (var, val);
|
||||
if (var->assign_func)
|
||||
(*var->assign_func) (var, ind, nval);
|
||||
@@ -2394,7 +2492,7 @@ all_variables_matching_prefix (prefix)
|
||||
for (vind = rind = 0; varlist[vind]; vind++)
|
||||
{
|
||||
if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
|
||||
rlist[rind++] = savestring (varlist[vind]->name);
|
||||
rlist[rind++] = savestring (varlist[vind]->name);
|
||||
}
|
||||
rlist[rind] = (char *)0;
|
||||
free (varlist);
|
||||
@@ -2437,7 +2535,7 @@ valid_exportstr (v)
|
||||
for (s = v->exportstr + 1; s && *s; s++)
|
||||
{
|
||||
if (*s == '=')
|
||||
break;
|
||||
break;
|
||||
if (legal_variable_char (*s) == 0)
|
||||
{
|
||||
internal_error ("invalid character %d in exportstr for %s", *s, v->name);
|
||||
@@ -2475,25 +2573,12 @@ make_var_array (hashed_vars)
|
||||
|
||||
for (i = 0, list_index = 0; var = vars[i]; i++)
|
||||
{
|
||||
if (var->exportstr)
|
||||
{
|
||||
#if defined(__CYGWIN__) || defined (__CYGWIN32__)
|
||||
INVALIDATE_EXPORTSTR (var);
|
||||
value = value_cell (var);
|
||||
#else
|
||||
/* XXX -- this test can go away in the next release, to be replaced
|
||||
by a simple `value = var->exportstr;', when the exportstr code
|
||||
is better-tested. Until then, don't do it for cygwin at all,
|
||||
since that system has some weird environment variables. */
|
||||
if (valid_exportstr (var))
|
||||
value = var->exportstr;
|
||||
else
|
||||
{
|
||||
INVALIDATE_EXPORTSTR (var);
|
||||
value = value_cell (var);
|
||||
}
|
||||
#if defined (__CYGWIN__)
|
||||
/* We don't use the exportstr stuff on Cygwin at all. */
|
||||
INVALIDATE_EXPORTSTR (var);
|
||||
#endif
|
||||
}
|
||||
if (var->exportstr)
|
||||
value = var->exportstr;
|
||||
else if (function_p (var))
|
||||
value = named_function_string ((char *)NULL, function_cell (var), 0);
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -2556,12 +2641,14 @@ assign_in_env (string)
|
||||
name[offset] = 0;
|
||||
|
||||
var = find_variable (name);
|
||||
if (var && readonly_p (var))
|
||||
if (var && (readonly_p (var) || noassign_p (var)))
|
||||
{
|
||||
report_error ("%s: readonly variable", name);
|
||||
if (readonly_p (var))
|
||||
report_error ("%s: readonly variable", name);
|
||||
free (name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
temp = name + offset + 1;
|
||||
temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
|
||||
|
||||
@@ -2603,6 +2690,68 @@ assign_in_env (string)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a SHELL_VAR from a `name=value' string as in the environment, taking
|
||||
the variable name, the environment string, and an index into the string
|
||||
which is the offset of the `=' (the char before the value begins). */
|
||||
static SHELL_VAR *
|
||||
shell_var_from_env_string (name, env_string, l)
|
||||
char *name, *env_string;
|
||||
int l;
|
||||
{
|
||||
SHELL_VAR *temp;
|
||||
char *w;
|
||||
|
||||
/* This is a potential memory leak. The code should really save
|
||||
the created variables in some auxiliary data structure, which
|
||||
can be disposed of at the appropriate time. */
|
||||
temp = new_shell_variable (name);
|
||||
w = env_string + l + 1;
|
||||
|
||||
temp->value = *w ? savestring (w) : (char *)NULL;
|
||||
|
||||
temp->attributes = att_exported|att_tempvar;
|
||||
temp->context = 0;
|
||||
temp->prev_context = (SHELL_VAR *)NULL;
|
||||
|
||||
temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
|
||||
CLEAR_EXPORTSTR (temp);
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
/* Bind NAME to VALUE in ARRAY, an array of strings in the same format as the
|
||||
environment array (i.e, name=value). If NAME is present, change the value,
|
||||
cons up a new SHELL_VAR and return it. Otherwise return (SHELL_VAR *)NULL. */
|
||||
|
||||
static SHELL_VAR *
|
||||
bind_name_in_env_array (name, value, array)
|
||||
char *name, *value;
|
||||
char **array;
|
||||
{
|
||||
register int i, l;
|
||||
char *new_env_string, *w;
|
||||
SHELL_VAR *temp;
|
||||
|
||||
if (array == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
|
||||
for (i = 0, l = strlen (name); array[i]; i++)
|
||||
{
|
||||
if (STREQN (array[i], name, l) && array[i][l] == '=')
|
||||
{
|
||||
new_env_string = mk_env_string (name, value);
|
||||
|
||||
temp = shell_var_from_env_string (name, new_env_string, l);
|
||||
|
||||
free (array[i]);
|
||||
array[i] = new_env_string;
|
||||
|
||||
return (temp);
|
||||
}
|
||||
}
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
/* Search for NAME in ARRAY, an array of strings in the same format as the
|
||||
environment array (i.e, name=value). If NAME is present, make a new
|
||||
variable and return it. Otherwise, return NULL. */
|
||||
@@ -2612,6 +2761,7 @@ find_name_in_env_array (name, array)
|
||||
char **array;
|
||||
{
|
||||
register int i, l;
|
||||
SHELL_VAR *temp;
|
||||
|
||||
if (array == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
@@ -2620,30 +2770,50 @@ find_name_in_env_array (name, array)
|
||||
{
|
||||
if (STREQN (array[i], name, l) && array[i][l] == '=')
|
||||
{
|
||||
SHELL_VAR *temp;
|
||||
char *w;
|
||||
|
||||
/* This is a potential memory leak. The code should really save
|
||||
the created variables in some auxiliary data structure, which
|
||||
can be disposed of at the appropriate time. */
|
||||
temp = new_shell_variable (name);
|
||||
w = array[i] + l + 1;
|
||||
|
||||
temp->value = *w ? savestring (w) : (char *)NULL;
|
||||
|
||||
temp->attributes = att_exported|att_tempvar;
|
||||
temp->context = 0;
|
||||
temp->prev_context = (SHELL_VAR *)NULL;
|
||||
|
||||
temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
|
||||
CLEAR_EXPORTSTR (temp);
|
||||
|
||||
temp = shell_var_from_env_string (name, array[i], l);
|
||||
return (temp);
|
||||
}
|
||||
}
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
#define FIND_AND_BIND_IN_ENV_ARRAY(N, V, A) \
|
||||
do \
|
||||
{ \
|
||||
var = find_name_in_env_array (N, A); \
|
||||
if (var) \
|
||||
{ \
|
||||
dispose_variable (var); \
|
||||
var = bind_name_in_env_array (N, V, A); \
|
||||
return (var); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Make variable NAME have VALUE in one of the temporary environments. */
|
||||
static SHELL_VAR *
|
||||
bind_tempenv_variable (name, value)
|
||||
char *name, *value;
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = (SHELL_VAR *)NULL;
|
||||
|
||||
if (temporary_env)
|
||||
FIND_AND_BIND_IN_ENV_ARRAY (name, value, temporary_env);
|
||||
|
||||
/* We don't check this_shell_builtin because the command that needs the
|
||||
value from builtin_env may be a disk command run inside a script run
|
||||
with `.' and a temporary env. */
|
||||
if (builtin_env)
|
||||
FIND_AND_BIND_IN_ENV_ARRAY (name, value, builtin_env);
|
||||
|
||||
if (variable_context && function_env)
|
||||
FIND_AND_BIND_IN_ENV_ARRAY (name, value, function_env);
|
||||
|
||||
return (SHELL_VAR *)NULL;
|
||||
}
|
||||
|
||||
/* Find a variable in the temporary environment that is named NAME.
|
||||
The temporary environment can be either the environment provided
|
||||
to a simple command, or the environment provided to a shell function.
|
||||
@@ -2747,6 +2917,12 @@ merge_builtin_env ()
|
||||
merge_env_array (builtin_env);
|
||||
}
|
||||
|
||||
void
|
||||
merge_function_env ()
|
||||
{
|
||||
merge_env_array (function_env);
|
||||
}
|
||||
|
||||
int
|
||||
any_temporary_variables ()
|
||||
{
|
||||
@@ -2825,7 +3001,7 @@ maybe_make_export_env ()
|
||||
if (new_size > export_env_size)
|
||||
{
|
||||
export_env_size = new_size;
|
||||
export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
|
||||
export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
|
||||
}
|
||||
export_env[export_env_index = 0] = (char *)NULL;
|
||||
|
||||
@@ -2849,6 +3025,10 @@ maybe_make_export_env ()
|
||||
for (i = 0; function_env[i]; i++)
|
||||
export_env = add_or_supercede_exported_var (function_env[i], 1);
|
||||
|
||||
if (builtin_env)
|
||||
for (i = 0; builtin_env[i]; i++)
|
||||
export_env = add_or_supercede_exported_var (builtin_env[i], 1);
|
||||
|
||||
if (temporary_env)
|
||||
for (i = 0; temporary_env[i]; i++)
|
||||
export_env = add_or_supercede_exported_var (temporary_env[i], 1);
|
||||
@@ -3124,7 +3304,7 @@ sv_histsize (name)
|
||||
if (temp && *temp)
|
||||
{
|
||||
if (legal_number (temp, &num))
|
||||
{
|
||||
{
|
||||
if (name[4] == 'S')
|
||||
{
|
||||
stifle_history (num);
|
||||
|
||||
Reference in New Issue
Block a user