diff options
author | Jari Aalto <jari.aalto@cante.net> | 2000-03-17 21:46:59 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:53 +0000 |
commit | bb70624e964126b7ac4ff085ba163a9c35ffa18f (patch) | |
tree | ba2dd4add13ada94b1899c6d4aca80195b80b74b /variables.c | |
parent | b72432fdcc59300c6fe7c9d6c8a31ad3447933f5 (diff) | |
download | bash-bb70624e964126b7ac4ff085ba163a9c35ffa18f.tar.gz |
Imported from ../bash-2.04.tar.gz.
Diffstat (limited to 'variables.c')
-rw-r--r-- | variables.c | 543 |
1 files changed, 438 insertions, 105 deletions
diff --git a/variables.c b/variables.c index 8f4bb420..615aacd1 100644 --- a/variables.c +++ b/variables.c @@ -6,7 +6,7 @@ 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 1, or (at your option) + 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 @@ -16,7 +16,7 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #include "config.h" @@ -58,6 +58,10 @@ # include <readline/history.h> #endif /* HISTORY */ +#if defined (PROGRAMMABLE_COMPLETION) +# include "pcomplete.h" +#endif + /* Variables used here and defined in other files. */ extern int posixly_correct; extern int variable_context, line_number; @@ -69,6 +73,7 @@ extern char *shell_name; extern char *primary_prompt, *secondary_prompt; extern char *current_host_name; extern Function *this_shell_builtin; +extern SHELL_VAR *this_shell_function; extern char *this_command_name; extern time_t shell_start_time; @@ -175,17 +180,14 @@ initialize_shell_variables (env, privmode) char_index == strlen (name) */ /* If exported function, define it now. */ - if (privmode == 0 && STREQN ("() {", string, 4)) + if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4)) { string_length = strlen (string); temp_string = xmalloc (3 + string_length + char_index); -#if 1 + strcpy (temp_string, name); temp_string[char_index] = ' '; strcpy (temp_string + char_index + 1, string); -#else - sprintf (temp_string, "%s %s", name, string); -#endif parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST); @@ -196,14 +198,15 @@ initialize_shell_variables (env, privmode) if (temp_var = find_function (name)) { - temp_var->attributes |= (att_exported | att_imported); + VSETATTR (temp_var, (att_exported|att_imported)); array_needs_making = 1; } else report_error ("error importing function definition for `%s'", name); + /* ( */ if (name[char_index - 1] == ')' && name[char_index - 2] == '\0') - name[char_index - 2] = '('; + name[char_index - 2] = '('; /* ) */ } #if defined (ARRAY_VARS) # if 0 @@ -214,7 +217,7 @@ initialize_shell_variables (env, privmode) temp_string = extract_array_assignment_list (string, &string_length); temp_var = assign_array_from_string (name, temp_string); FREE (temp_string); - temp_var->attributes |= (att_exported | att_imported); + VSETATTR (temp_var, (att_exported | att_imported)); array_needs_making = 1; } # endif @@ -222,11 +225,17 @@ initialize_shell_variables (env, privmode) else { temp_var = bind_variable (name, string); - temp_var->attributes |= (att_exported | att_imported); + VSETATTR (temp_var, (att_exported | att_imported)); array_needs_making = 1; } 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). */ + 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 @@ -253,7 +262,7 @@ initialize_shell_variables (env, privmode) `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); - temp_var->attributes |= (att_exported | att_invisible); + VSETATTR (temp_var, (att_exported | att_invisible)); /* Set up initial value of $_ */ temp_var = bind_variable ("_", dollar_vars[0]); @@ -391,6 +400,13 @@ 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; + } + /* Get the user's real and effective user ids. */ uidset (); @@ -419,7 +435,7 @@ set_home_var () temp_var = find_variable ("HOME"); if (temp_var == 0) temp_var = bind_variable ("HOME", get_home_dir ()); - temp_var->attributes |= att_exported; + VSETATTR (temp_var, att_exported); } /* Set $SHELL to the user's login shell if it is not already set. Call @@ -436,7 +452,7 @@ set_shell_var () get_current_user_info (); temp_var = bind_variable ("SHELL", current_user.shell); } - temp_var->attributes |= att_exported; + VSETATTR (temp_var, att_exported); } static char * @@ -555,12 +571,6 @@ adjust_shell_level (change) static void initialize_shell_level () { -#if 0 - SHELL_VAR *temp_var; - - temp_var = set_if_not ("SHLVL", "0"); - set_auto_export (temp_var); -#endif adjust_shell_level (1); } @@ -574,9 +584,9 @@ set_ppid () name = inttostr ((int) getppid (), namebuf, sizeof(namebuf)); temp_var = find_variable ("PPID"); if (temp_var) - temp_var->attributes &= ~(att_readonly | att_exported); + VUNSETATTR (temp_var, (att_readonly | att_exported)); temp_var = bind_variable ("PPID", name); - temp_var->attributes |= (att_readonly | att_integer); + VSETATTR (temp_var, (att_readonly | att_integer)); } static void @@ -588,20 +598,20 @@ uidset () b = inttostr (current_user.uid, buff, sizeof (buff)); v = find_variable ("UID"); if (v) - v->attributes &= ~att_readonly; + VUNSETATTR (v, att_readonly); v = bind_variable ("UID", b); - v->attributes |= (att_readonly | att_integer); + 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) - v->attributes &= ~att_readonly; + VUNSETATTR (v, att_readonly); v = bind_variable ("EUID", b); - v->attributes |= (att_readonly | att_integer); + VSETATTR (v, (att_readonly | att_integer)); } #if defined (ARRAY_VARS) @@ -629,7 +639,7 @@ make_vers_array () array_add_element (av, 4, release_status); array_add_element (av, 5, MACHTYPE); - vv->attributes |= att_readonly; + VSETATTR (vv, att_readonly); } #endif /* ARRAY_VARS */ @@ -893,6 +903,25 @@ print_array_assignment (var, quoted) stupidly_hack_special_variables, but I wanted the changes as localized as possible. */ +static SHELL_VAR * +null_assign (self, value) + SHELL_VAR *self; + char *value; +{ + return (self); +} + +#if defined (ARRAY_VARS) +static SHELL_VAR * +null_array_assign (self, ind, value) + SHELL_VAR *self; + int ind; + char *value; +{ + return (self); +} +#endif + /* The value of $SECONDS. This is the number of seconds since shell invocation, or, the number of seconds since the last assignment + the value of the last assignment. */ @@ -920,7 +949,7 @@ get_seconds (var) FREE (var->value); - var->attributes |= att_integer; + VSETATTR (var, att_integer); var->value = p; return (var); } @@ -979,7 +1008,7 @@ get_random (var) FREE (var->value); - var->attributes |= att_integer; + VSETATTR (var, att_integer); var->value = p; return (var); } @@ -1071,42 +1100,74 @@ get_groupset (self) return (self); } #endif /* ARRAY_VARS */ - -static void -initialize_dynamic_variables () + +static SHELL_VAR * +get_funcname (self) + SHELL_VAR *self; +{ + if (variable_context && this_shell_function) + { + FREE (self->value); + self->value = savestring (this_shell_function->name); + } + return (self); +} + +void +make_funcname_visible (on_or_off) + int on_or_off; { SHELL_VAR *v; - v = bind_variable ("SECONDS", (char *)NULL); - v->dynamic_value = get_seconds; - v->assign_func = assign_seconds; + v = find_variable ("FUNCNAME"); + if (v == 0 || v->dynamic_value == 0) + return; + + if (on_or_off) + VUNSETATTR (v, att_invisible); + else + VSETATTR (v, att_invisible); +} + +#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \ + do \ + { \ + v = bind_variable (var, val); \ + v->dynamic_value = gfunc; \ + v->assign_func = afunc; \ + } while (0) + +#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \ + do \ + { \ + v = make_new_array_variable (var); \ + v->dynamic_value = gfunc; \ + v->assign_func = afunc; \ + } while (0) - v = bind_variable ("RANDOM", (char *)NULL); - v->dynamic_value = get_random; - v->assign_func = assign_random; +static void +initialize_dynamic_variables () +{ + SHELL_VAR *v; - v = bind_variable ("LINENO", (char *)NULL); - v->dynamic_value = get_lineno; - v->assign_func = assign_lineno; + INIT_DYNAMIC_VAR ("SECONDS", (char *)NULL, get_seconds, assign_seconds); + INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random); + INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno); #if defined (HISTORY) - v = bind_variable ("HISTCMD", (char *)NULL); - v->dynamic_value = get_histcmd; - v->assign_func = (DYNAMIC_FUNC *)NULL; + INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (DYNAMIC_FUNC *)NULL); #endif #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS) - v = make_new_array_variable ("DIRSTACK"); - v->dynamic_value = get_dirstack; - v->assign_func = assign_dirstack; + INIT_DYNAMIC_ARRAY_VAR ("DIRSTACK", get_dirstack, assign_dirstack); #endif /* PUSHD_AND_POPD && ARRAY_VARS */ #if defined (ARRAY_VARS) - v = make_new_array_variable ("GROUPS"); - v->dynamic_value = get_groupset; - v->assign_func = (DYNAMIC_FUNC *)NULL; - v->attributes |= att_readonly; + INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign); #endif + + INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign); + VSETATTR (v, att_invisible); } /* How to get a pointer to the shell variable or function named NAME. @@ -1211,6 +1272,15 @@ make_local_variable (name) if (old_var && old_var->context == variable_context) return (old_var); + /* 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)) + { + builtin_error ("%s: readonly variable"); + return ((SHELL_VAR *)NULL); + } + elt = remove_hash_item (name, shell_variables); if (elt) { @@ -1233,6 +1303,8 @@ make_local_variable (name) new_var->value = xmalloc (1); new_var->value[0] = '\0'; + CLEAR_EXPORTSTR (new_var); + new_var->dynamic_value = (DYNAMIC_FUNC *)NULL; new_var->assign_func = (DYNAMIC_FUNC *)NULL; @@ -1244,7 +1316,7 @@ make_local_variable (name) } new_var->context = variable_context; - new_var->attributes |= att_local; + VSETATTR (new_var, att_local); /* XXX */ if (variable_context >= local_variable_stack_size) @@ -1269,11 +1341,13 @@ make_local_array_variable (name) ARRAY *array; var = make_local_variable (name); + if (var == 0) + return var; array = new_array (); FREE (value_cell(var)); var->value = (char *)array; - var->attributes |= att_array; + VSETATTR (var, att_array); return var; } #endif /* ARRAY_VARS */ @@ -1293,6 +1367,7 @@ make_new_variable (name) entry->attributes = 0; entry->name = savestring (name); entry->value = (char *)NULL; + CLEAR_EXPORTSTR (entry); entry->dynamic_value = (DYNAMIC_FUNC *)NULL; entry->assign_func = (DYNAMIC_FUNC *)NULL; @@ -1320,7 +1395,7 @@ make_new_array_variable (name) entry = make_new_variable (name); array = new_array (); entry->value = (char *)array; - entry->attributes |= att_array; + VSETATTR (entry, att_array); return entry; } #endif @@ -1383,7 +1458,10 @@ bind_variable (name, value) #else else if (entry->assign_func) #endif - return ((*(entry->assign_func)) (entry, value)); + { + INVALIDATE_EXPORTSTR (entry); + return ((*(entry->assign_func)) (entry, value)); + } else { if (readonly_p (entry)) @@ -1393,10 +1471,13 @@ bind_variable (name, value) } /* Variables which are bound are visible. */ - entry->attributes &= ~att_invisible; + VUNSETATTR (entry, att_invisible); newval = make_variable_value (entry, value); + /* Invalidate any cached export string */ + INVALIDATE_EXPORTSTR (entry); + #if defined (ARRAY_VARS) /* XXX -- this bears looking at again -- XXX */ /* If an existing array variable x is being assigned to with x=b or @@ -1419,7 +1500,7 @@ bind_variable (name, value) } if (mark_modified_vars) - entry->attributes |= att_exported; + VSETATTR (entry, att_exported); if (exported_p (entry)) array_needs_making = 1; @@ -1427,6 +1508,67 @@ bind_variable (name, value) return (entry); } +/* Make VAR, a simple shell variable, have value VALUE. Once assigned a + value, variables are no longer invisible. This is a duplicate of part + of the internals of bind_variable. If the variable is exported, or + all modified variables should be exported, mark the variable for export + and note that the export environment needs to be recreated. */ +SHELL_VAR * +bind_variable_value (var, value) + SHELL_VAR *var; + char *value; +{ + char *t; + + VUNSETATTR (var, att_invisible); + + t = make_variable_value (var, value); + FREE (var->value); + var->value = t; + + INVALIDATE_EXPORTSTR (var); + + if (mark_modified_vars) + VSETATTR (var, att_exported); + + if (exported_p (var)) + array_needs_making = 1; + + return (var); +} + +/* Bind/create a shell variable with the name LHS to the RHS. + This creates or modifies a variable such that it is an integer. + + This used to be in expr.c, but it is here so that all of the + variable binding stuff is localized. Since we don't want any + recursive evaluation from bind_variable() (possible without this code, + since bind_variable() calls the evaluator for variables with the integer + attribute set), we temporarily turn off the integer attribute for each + variable we set here, then turn it back on after binding as necessary. */ + +SHELL_VAR * +bind_int_variable (lhs, rhs) + char *lhs, *rhs; +{ + register SHELL_VAR *v; + int isint; + + isint = 0; + v = find_variable (lhs); + if (v) + { + isint = integer_p (v); + VUNSETATTR (v, att_integer); + } + + v = bind_variable (lhs, rhs); + if (isint) + VSETATTR (v, att_integer); + + return (v); +} + #if defined (ARRAY_VARS) /* Convert a shell variable to an array variable. The original value is saved as array[0]. */ @@ -1440,10 +1582,14 @@ convert_var_to_array (var) oldval = value_cell (var); array = new_array (); array_add_element (array, 0, oldval); + FREE (value_cell (var)); var->value = (char *)array; - var->attributes |= att_array; - var->attributes &= ~att_invisible; + + INVALIDATE_EXPORTSTR (var); + + VSETATTR (var, att_array); + VUNSETATTR (var, att_invisible); return var; } @@ -1526,6 +1672,40 @@ assign_array_var_from_word_list (var, list) return var; } +/* For each word in a compound array assignment, if the word looks like + [ind]=value, quote the `[' and `]' before the `=' to protect them from + unwanted filename expansion. */ +static void +quote_array_assignment_chars (list) + WORD_LIST *list; +{ + char *s, *t, *nword; + int saw_eq; + WORD_LIST *l; + + for (l = list; l; l = l->next) + { + if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0') + continue; /* should not happen, but just in case... */ + /* Don't bother if it doesn't look like [ind]=value */ + if (l->word->word[0] != '[' || strchr (l->word->word, '=') == 0) /* ] */ + continue; + s = nword = xmalloc (strlen (l->word->word) * 2 + 1); + saw_eq = 0; + for (t = l->word->word; *t; ) + { + if (*t == '=') + saw_eq = 1; + if (saw_eq == 0 && (*t == '[' || *t == ']')) + *s++ = '\\'; + *s++ = *t++; + } + *s = '\0'; + free (l->word->word); + l->word->word = nword; + } +} + /* Perform a compound array assignment: VAR->name=( VALUE ). The VALUE has already had the parentheses stripped. */ SHELL_VAR * @@ -1559,13 +1739,15 @@ assign_array_var_from_string (var, value) /* First we split the string on whitespace, using the shell parser (ksh93 seems to do this). */ list = parse_string_to_word_list (val, "array assign"); + + /* If we're using [subscript]=value, we need to quote each [ and ] to + prevent unwanted filename expansion. */ + if (list) + quote_array_assignment_chars (list); + /* Now that we've split it, perform the shell expansions on each word in the list. */ -#if 0 - nlist = list ? expand_words_shellexp (list) : (WORD_LIST *)NULL; -#else nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL; -#endif dispose_words (list); @@ -1660,6 +1842,8 @@ dispose_variable (var) else FREE (value_cell (var)); + FREE_EXPORTSTR (var); + free (var->name); if (exported_p (var)) @@ -1756,6 +1940,11 @@ makunbound (name, hash_list) if (old_var && exported_p (old_var)) array_needs_making++; +#if defined (PROGRAMMABLE_COMPLETION) + if (hash_list == shell_functions) + set_itemlist_dirty (&it_functions); +#endif + /* If we're unsetting a local variable and we're still executing inside the function, just mark the variable as invisible. kill_all_local_variables will clean it up later. This must be done @@ -1764,7 +1953,8 @@ makunbound (name, hash_list) to add it back into the correct hash table. */ if (old_var && local_p (old_var) && variable_context == old_var->context) { - old_var->attributes |= att_invisible; + VSETATTR (old_var, att_invisible); + INVALIDATE_EXPORTSTR (old_var); new_elt = add_hash_item (savestring (old_var->name), hash_list); new_elt->data = (char *)old_var; stupidly_hack_special_variables (old_var->name); @@ -1852,7 +2042,7 @@ kill_all_local_variables () { for (i = 0; var = list[i]; i++) { - var->attributes &= ~att_local; + VUNSETATTR (var, att_local); makunbound (var->name, varlist); } free (list); @@ -1914,29 +2104,37 @@ bind_function (name, value) elt = add_hash_item (savestring (name), shell_functions); - elt->data = (char *)new_shell_variable (name); - entry = (SHELL_VAR *)elt->data; + entry = new_shell_variable (name); entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL; + CLEAR_EXPORTSTR (entry); /* Functions are always made at the top level. This allows a function to define another function (like autoload). */ entry->context = 0; + + elt->data = (char *)entry; } + INVALIDATE_EXPORTSTR (entry); + if (entry->value) dispose_command ((COMMAND *)entry->value); entry->value = value ? (char *)copy_command (value) : (char *)NULL; - entry->attributes |= att_function; + VSETATTR (entry, att_function); if (mark_modified_vars) - entry->attributes |= att_exported; + VSETATTR (entry, att_exported); - entry->attributes &= ~att_invisible; /* Just to be sure */ + VUNSETATTR (entry, att_invisible); /* Just to be sure */ if (exported_p (entry)) array_needs_making = 1; +#if defined (PROGRAMMABLE_COMPLETION) + set_itemlist_dirty (&it_functions); +#endif + return (entry); } @@ -1969,6 +2167,8 @@ copy_variable (var) copy->dynamic_value = var->dynamic_value; copy->assign_func = var->assign_func; + copy->exportstr = COPY_EXPORTSTR (var); + copy->context = var->context; /* Don't bother copying previous contexts along with this variable. */ @@ -1999,7 +2199,7 @@ set_var_read_only (name) SHELL_VAR *entry; FIND_OR_MAKE_VARIABLE (name, entry); - entry->attributes |= att_readonly; + VSETATTR (entry, att_readonly); } #ifdef INCLUDE_UNUSED @@ -2013,7 +2213,7 @@ set_func_read_only (name) entry = find_function (name); if (entry) - entry->attributes |= att_readonly; + VSETATTR (entry, att_readonly); } /* Make the variable associated with NAME be auto-exported. @@ -2102,8 +2302,6 @@ assignment (string) return (0); } -#ifdef READLINE - static int visible_var (var) SHELL_VAR *var; @@ -2126,19 +2324,17 @@ _visible_names (table) } SHELL_VAR ** -all_visible_variables () +all_visible_functions () { - return (_visible_names (shell_variables)); + return (_visible_names (shell_functions)); } SHELL_VAR ** -all_visible_functions () +all_visible_variables () { - return (_visible_names (shell_functions)); + return (_visible_names (shell_variables)); } -#endif /* READLINE */ - /* Return non-zero if the variable VAR is visible and exported. Array variables cannot be exported. */ static int @@ -2148,6 +2344,114 @@ visible_and_exported (var) return (invisible_p (var) == 0 && exported_p (var)); } +SHELL_VAR ** +all_exported_variables () +{ + SHELL_VAR **list; + + list = map_over (visible_and_exported, shell_variables); + if (list) + sort_variables (list); + return (list); +} + +#if defined (ARRAY_VARS) +/* Return non-zero if the variable VAR is visible and an array. */ +static int +visible_array_vars (var) + SHELL_VAR *var; +{ + return (invisible_p (var) == 0 && array_p (var)); +} + +SHELL_VAR ** +all_array_variables () +{ + SHELL_VAR **list; + + list = map_over (visible_array_vars, shell_variables); + if (list) + sort_variables (list); + return (list); +} +#endif /* ARRAY_VARS */ + +char ** +all_variables_matching_prefix (prefix) + char *prefix; +{ + SHELL_VAR **varlist; + char **rlist; + int vind, rind, plen; + + plen = STRLEN (prefix); + varlist = all_visible_variables (); + for (vind = 0; varlist && varlist[vind]; vind++) + ; + if (varlist == 0 || vind == 0) + return ((char **)NULL); + rlist = alloc_array (vind + 1); + for (vind = rind = 0; varlist[vind]; vind++) + { + if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen)) + rlist[rind++] = savestring (varlist[vind]->name); + } + rlist[rind] = (char *)0; + free (varlist); + + return rlist; +} + +static inline char * +mk_env_string (name, value) + char *name, *value; +{ + int name_len, value_len; + char *p; + + name_len = strlen (name); + value_len = STRLEN (value); + p = xmalloc (2 + name_len + value_len); + strcpy (p, name); + p[name_len] = '='; + if (value && *value) + strcpy (p + name_len + 1, value); + else + p[name_len + 1] = '\0'; + return (p); +} + +/* Debugging */ +static int +valid_exportstr (v) + SHELL_VAR *v; +{ + char *s; + + s = v->exportstr; + if (legal_variable_starter (*s) == 0) + { + internal_error ("invalid character %d in exportstr for %s", *s, v->name); + return (0); + } + for (s = v->exportstr + 1; s && *s; s++) + { + if (*s == '=') + break; + if (legal_variable_char (*s) == 0) + { + internal_error ("invalid character %d in exportstr for %s", *s, v->name); + return (0); + } + } + if (*s != '=') + { + internal_error ("no `=' in exportstr for %s", v->name); + return (0); + } + return (1); +} + /* Make an array of assignment statements from the hash table HASHED_VARS which contains SHELL_VARs. Only visible, exported variables are eligible. */ @@ -2165,11 +2469,32 @@ make_var_array (hashed_vars) if (vars == 0) return (char **)NULL; - list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *)); + list = alloc_array ((1 + array_len ((char **)vars))); + +#define USE_EXPORTSTR (value == var->exportstr) for (i = 0, list_index = 0; var = vars[i]; i++) { - if (function_p (var)) + 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); + } +#endif + } + else if (function_p (var)) value = named_function_string ((char *)NULL, function_cell (var), 0); #if defined (ARRAY_VARS) else if (array_p (var)) @@ -2184,20 +2509,24 @@ make_var_array (hashed_vars) if (value) { - int name_len, value_len; - char *p; - - name_len = strlen (var->name); - value_len = strlen (value); - p = list[list_index] = xmalloc (2 + name_len + value_len); - strcpy (p, var->name); - p[name_len] = '='; - strcpy (p + name_len + 1, value); + /* Gee, I'd like to get away with not using savestring() if we're + using the cached exportstr... */ + list[list_index] = USE_EXPORTSTR ? savestring (value) + : mk_env_string (var->name, value); + + if (USE_EXPORTSTR == 0 && function_p (var)) + { + SAVE_EXPORTSTR (var, list[list_index]); + } list_index++; +#undef USE_EXPORTSTR + +#if 0 /* not yet */ #if defined (ARRAY_VARS) if (array_p (var)) free (value); #endif +#endif } } @@ -2245,18 +2574,8 @@ assign_in_env (string) free (temp); } - nlen = strlen (name); - vlen = value ? strlen (value) : 0; - temp = xmalloc (2 + nlen + vlen); - strcpy (temp, name); - temp[nlen] = '='; - temp[nlen + 1] = '\0'; - if (value) - { - if (*value) - strcpy (temp + nlen + 1, value); - free (value); - } + temp = mk_env_string (name, value); + FREE (value); free (name); if (temporary_env == 0) @@ -2317,6 +2636,7 @@ find_name_in_env_array (name, array) temp->prev_context = (SHELL_VAR *)NULL; temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL; + CLEAR_EXPORTSTR (temp); return (temp); } @@ -2427,6 +2747,12 @@ merge_builtin_env () merge_env_array (builtin_env); } +int +any_temporary_variables () +{ + return (temporary_env || function_env); +} + /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */ #define add_to_export_env(envstr,do_alloc) \ do \ @@ -2495,7 +2821,7 @@ maybe_make_export_env () variables are not (yet) exported, this will always be big enough for the exported variables and functions, without any temporary or function environments. */ - new_size = shell_variables->nentries + shell_functions->nentries + 1; + new_size = HASH_ENTRIES (shell_variables) + HASH_ENTRIES (shell_functions) + 1; if (new_size > export_env_size) { export_env_size = new_size; @@ -2688,6 +3014,7 @@ struct name_and_function { { "LC_COLLATE", sv_locale }, { "LC_CTYPE", sv_locale }, { "LC_MESSAGES", sv_locale }, + { "LC_NUMERIC", sv_locale }, { "LANG", sv_locale }, #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) @@ -2768,7 +3095,13 @@ void sv_hostfile (name) char *name; { - hostname_list_initialized = 0; + SHELL_VAR *v; + + v = find_variable (name); + if (v == 0) + clear_hostname_list (); + else + hostname_list_initialized = 0; } #endif /* READLINE */ |