Bash-4.3 patch 27
[platform/upstream/bash.git] / variables.c
1 /* variables.c -- Functions for hacking shell variables. */
2
3 /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
7    Bash is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    Bash is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #include "posixstat.h"
25 #include "posixtime.h"
26
27 #if defined (__QNX__)
28 #  if defined (__QNXNTO__)
29 #    include <sys/netmgr.h>
30 #  else
31 #    include <sys/vc.h>
32 #  endif /* !__QNXNTO__ */
33 #endif /* __QNX__ */
34
35 #if defined (HAVE_UNISTD_H)
36 #  include <unistd.h>
37 #endif
38
39 #include <stdio.h>
40 #include "chartypes.h"
41 #if defined (HAVE_PWD_H)
42 #  include <pwd.h>
43 #endif
44 #include "bashansi.h"
45 #include "bashintl.h"
46
47 #define NEED_XTRACE_SET_DECL
48
49 #include "shell.h"
50 #include "flags.h"
51 #include "execute_cmd.h"
52 #include "findcmd.h"
53 #include "mailcheck.h"
54 #include "input.h"
55 #include "hashcmd.h"
56 #include "pathexp.h"
57 #include "alias.h"
58 #include "jobs.h"
59
60 #include "version.h"
61
62 #include "builtins/getopt.h"
63 #include "builtins/common.h"
64 #include "builtins/builtext.h"
65
66 #if defined (READLINE)
67 #  include "bashline.h"
68 #  include <readline/readline.h>
69 #else
70 #  include <tilde/tilde.h>
71 #endif
72
73 #if defined (HISTORY)
74 #  include "bashhist.h"
75 #  include <readline/history.h>
76 #endif /* HISTORY */
77
78 #if defined (PROGRAMMABLE_COMPLETION)
79 #  include "pcomplete.h"
80 #endif
81
82 #define TEMPENV_HASH_BUCKETS    4       /* must be power of two */
83
84 #define ifsname(s)      ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
85
86 #define BASHFUNC_PREFIX         "BASH_FUNC_"
87 #define BASHFUNC_PREFLEN        10      /* == strlen(BASHFUNC_PREFIX */
88 #define BASHFUNC_SUFFIX         "%%"
89 #define BASHFUNC_SUFFLEN        2       /* == strlen(BASHFUNC_SUFFIX) */
90
91 extern char **environ;
92
93 /* Variables used here and defined in other files. */
94 extern int posixly_correct;
95 extern int line_number, line_number_base;
96 extern int subshell_environment, indirection_level, subshell_level;
97 extern int build_version, patch_level;
98 extern int expanding_redir;
99 extern int last_command_exit_value;
100 extern char *dist_version, *release_status;
101 extern char *shell_name;
102 extern char *primary_prompt, *secondary_prompt;
103 extern char *current_host_name;
104 extern sh_builtin_func_t *this_shell_builtin;
105 extern SHELL_VAR *this_shell_function;
106 extern char *the_printed_command_except_trap;
107 extern char *this_command_name;
108 extern char *command_execution_string;
109 extern time_t shell_start_time;
110 extern int assigning_in_environment;
111 extern int executing_builtin;
112 extern int funcnest_max;
113
114 #if defined (READLINE)
115 extern int no_line_editing;
116 extern int perform_hostname_completion;
117 #endif
118
119 /* The list of shell variables that the user has created at the global
120    scope, or that came from the environment. */
121 VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
122
123 /* The current list of shell variables, including function scopes */
124 VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
125
126 /* The list of shell functions that the user has created, or that came from
127    the environment. */
128 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
129
130 #if defined (DEBUGGER)
131 /* The table of shell function definitions that the user defined or that
132    came from the environment. */
133 HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
134 #endif
135
136 /* The current variable context.  This is really a count of how deep into
137    executing functions we are. */
138 int variable_context = 0;
139
140 /* The set of shell assignments which are made only in the environment
141    for a single command. */
142 HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
143
144 /* Set to non-zero if an assignment error occurs while putting variables
145    into the temporary environment. */
146 int tempenv_assign_error;
147
148 /* Some funky variables which are known about specially.  Here is where
149    "$*", "$1", and all the cruft is kept. */
150 char *dollar_vars[10];
151 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
152
153 /* The value of $$. */
154 pid_t dollar_dollar_pid;
155
156 /* Non-zero means that we have to remake EXPORT_ENV. */
157 int array_needs_making = 1;
158
159 /* The number of times BASH has been executed.  This is set
160    by initialize_variables (). */
161 int shell_level = 0;
162
163 /* An array which is passed to commands as their environment.  It is
164    manufactured from the union of the initial environment and the
165    shell variables that are marked for export. */
166 char **export_env = (char **)NULL;
167 static int export_env_index;
168 static int export_env_size;
169
170 #if defined (READLINE)
171 static int winsize_assignment;          /* currently assigning to LINES or COLUMNS */
172 #endif
173
174 static HASH_TABLE *last_table_searched; /* hash_lookup sets this */
175
176 /* Some forward declarations. */
177 static void create_variable_tables __P((void));
178
179 static void set_machine_vars __P((void));
180 static void set_home_var __P((void));
181 static void set_shell_var __P((void));
182 static char *get_bash_name __P((void));
183 static void initialize_shell_level __P((void));
184 static void uidset __P((void));
185 #if defined (ARRAY_VARS)
186 static void make_vers_array __P((void));
187 #endif
188
189 static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
190 #if defined (ARRAY_VARS)
191 static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
192 #endif
193 static SHELL_VAR *get_self __P((SHELL_VAR *));
194
195 #if defined (ARRAY_VARS)
196 static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
197 static SHELL_VAR *init_dynamic_assoc_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
198 #endif
199
200 static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *));
201 static SHELL_VAR *get_seconds __P((SHELL_VAR *));
202 static SHELL_VAR *init_seconds_var __P((void));
203
204 static int brand __P((void));
205 static void sbrand __P((unsigned long));                /* set bash random number generator. */
206 static void seedrand __P((void));                       /* seed generator randomly */
207 static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *));
208 static SHELL_VAR *get_random __P((SHELL_VAR *));
209
210 static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *));
211 static SHELL_VAR *get_lineno __P((SHELL_VAR *));
212
213 static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t, char *));
214 static SHELL_VAR *get_subshell __P((SHELL_VAR *));
215
216 static SHELL_VAR *get_bashpid __P((SHELL_VAR *));
217
218 #if defined (HISTORY)
219 static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
220 #endif
221
222 #if defined (READLINE)
223 static SHELL_VAR *get_comp_wordbreaks __P((SHELL_VAR *));
224 static SHELL_VAR *assign_comp_wordbreaks __P((SHELL_VAR *, char *, arrayind_t, char *));
225 #endif
226
227 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
228 static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t, char *));
229 static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
230 #endif
231
232 #if defined (ARRAY_VARS)
233 static SHELL_VAR *get_groupset __P((SHELL_VAR *));
234
235 static SHELL_VAR *build_hashcmd __P((SHELL_VAR *));
236 static SHELL_VAR *get_hashcmd __P((SHELL_VAR *));
237 static SHELL_VAR *assign_hashcmd __P((SHELL_VAR *,  char *, arrayind_t, char *));
238 #  if defined (ALIAS)
239 static SHELL_VAR *build_aliasvar __P((SHELL_VAR *));
240 static SHELL_VAR *get_aliasvar __P((SHELL_VAR *));
241 static SHELL_VAR *assign_aliasvar __P((SHELL_VAR *,  char *, arrayind_t, char *));
242 #  endif
243 #endif
244
245 static SHELL_VAR *get_funcname __P((SHELL_VAR *));
246 static SHELL_VAR *init_funcname_var __P((void));
247
248 static void initialize_dynamic_variables __P((void));
249
250 static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
251 static SHELL_VAR *new_shell_variable __P((const char *));
252 static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
253 static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
254
255 static void dispose_variable_value __P((SHELL_VAR *));
256 static void free_variable_hash_data __P((PTR_T));
257
258 static VARLIST *vlist_alloc __P((int));
259 static VARLIST *vlist_realloc __P((VARLIST *, int));
260 static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
261
262 static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
263
264 static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
265
266 static SHELL_VAR **vapply __P((sh_var_map_func_t *));
267 static SHELL_VAR **fapply __P((sh_var_map_func_t *));
268
269 static int visible_var __P((SHELL_VAR *));
270 static int visible_and_exported __P((SHELL_VAR *));
271 static int export_environment_candidate __P((SHELL_VAR *));
272 static int local_and_exported __P((SHELL_VAR *));
273 static int variable_in_context __P((SHELL_VAR *));
274 #if defined (ARRAY_VARS)
275 static int visible_array_vars __P((SHELL_VAR *));
276 #endif
277
278 static SHELL_VAR *find_nameref_at_context __P((SHELL_VAR *, VAR_CONTEXT *));
279 static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
280 static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
281
282 static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
283 static void push_temp_var __P((PTR_T));
284 static void propagate_temp_var __P((PTR_T));
285 static void dispose_temporary_env __P((sh_free_func_t *));     
286
287 static inline char *mk_env_string __P((const char *, const char *, int));
288 static char **make_env_array_from_var_list __P((SHELL_VAR **));
289 static char **make_var_export_array __P((VAR_CONTEXT *));
290 static char **make_func_export_array __P((void));
291 static void add_temp_array_to_env __P((char **, int, int));
292
293 static int n_shell_variables __P((void));
294 static int set_context __P((SHELL_VAR *));
295
296 static void push_func_var __P((PTR_T));
297 static void push_exported_var __P((PTR_T));
298
299 static inline int find_special_var __P((const char *));
300
301 static void
302 create_variable_tables ()
303 {
304   if (shell_variables == 0)
305     {
306       shell_variables = global_variables = new_var_context ((char *)NULL, 0);
307       shell_variables->scope = 0;
308       shell_variables->table = hash_create (0);
309     }
310
311   if (shell_functions == 0)
312     shell_functions = hash_create (0);
313
314 #if defined (DEBUGGER)
315   if (shell_function_defs == 0)
316     shell_function_defs = hash_create (0);
317 #endif
318 }
319
320 /* Initialize the shell variables from the current environment.
321    If PRIVMODE is nonzero, don't import functions from ENV or
322    parse $SHELLOPTS. */
323 void
324 initialize_shell_variables (env, privmode)
325      char **env;
326      int privmode;
327 {
328   char *name, *string, *temp_string;
329   int c, char_index, string_index, string_length, ro;
330   SHELL_VAR *temp_var;
331
332   create_variable_tables ();
333
334   for (string_index = 0; string = env[string_index++]; )
335     {
336       char_index = 0;
337       name = string;
338       while ((c = *string++) && c != '=')
339         ;
340       if (string[-1] == '=')
341         char_index = string - name - 1;
342
343       /* If there are weird things in the environment, like `=xxx' or a
344          string without an `=', just skip them. */
345       if (char_index == 0)
346         continue;
347
348       /* ASSERT(name[char_index] == '=') */
349       name[char_index] = '\0';
350       /* Now, name = env variable name, string = env variable value, and
351          char_index == strlen (name) */
352
353       temp_var = (SHELL_VAR *)NULL;
354
355       /* If exported function, define it now.  Don't import functions from
356          the environment in privileged mode. */
357       if (privmode == 0 && read_but_dont_execute == 0 && 
358           STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) &&
359           STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) &&
360           STREQN ("() {", string, 4))
361         {
362           size_t namelen;
363           char *tname;          /* desired imported function name */
364
365           namelen = char_index - BASHFUNC_PREFLEN - BASHFUNC_SUFFLEN;
366
367           tname = name + BASHFUNC_PREFLEN;      /* start of func name */
368           tname[namelen] = '\0';                /* now tname == func name */
369
370           string_length = strlen (string);
371           temp_string = (char *)xmalloc (namelen + string_length + 2);
372
373           memcpy (temp_string, tname, namelen);
374           temp_string[namelen] = ' ';
375           memcpy (temp_string + namelen + 1, string, string_length + 1);
376
377           /* Don't import function names that are invalid identifiers from the
378              environment, though we still allow them to be defined as shell
379              variables. */
380           if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname)))
381             parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
382
383           if (temp_var = find_function (tname))
384             {
385               VSETATTR (temp_var, (att_exported|att_imported));
386               array_needs_making = 1;
387             }
388           else
389             {
390               if (temp_var = bind_variable (name, string, 0))
391                 {
392                   VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
393                   array_needs_making = 1;
394                 }
395               last_command_exit_value = 1;
396               report_error (_("error importing function definition for `%s'"), tname);
397             }
398
399           /* Restore original suffix */
400           tname[namelen] = BASHFUNC_SUFFIX[0];
401         }
402 #if defined (ARRAY_VARS)
403 #  if ARRAY_EXPORT
404       /* Array variables may not yet be exported. */
405       else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
406         {
407           string_length = 1;
408           temp_string = extract_array_assignment_list (string, &string_length);
409           temp_var = assign_array_from_string (name, temp_string);
410           FREE (temp_string);
411           VSETATTR (temp_var, (att_exported | att_imported));
412           array_needs_making = 1;
413         }
414 #  endif /* ARRAY_EXPORT */
415 #endif
416 #if 0
417       else if (legal_identifier (name))
418 #else
419       else
420 #endif
421         {
422           ro = 0;
423           if (posixly_correct && STREQ (name, "SHELLOPTS"))
424             {
425               temp_var = find_variable ("SHELLOPTS");
426               ro = temp_var && readonly_p (temp_var);
427               if (temp_var)
428                 VUNSETATTR (temp_var, att_readonly);
429             }
430           temp_var = bind_variable (name, string, 0);
431           if (temp_var)
432             {
433               if (legal_identifier (name))
434                 VSETATTR (temp_var, (att_exported | att_imported));
435               else
436                 VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
437               if (ro)
438                 VSETATTR (temp_var, att_readonly);
439               array_needs_making = 1;
440             }
441         }
442
443       name[char_index] = '=';
444       /* temp_var can be NULL if it was an exported function with a syntax
445          error (a different bug, but it still shouldn't dump core). */
446       if (temp_var && function_p (temp_var) == 0)       /* XXX not yet */
447         {
448           CACHE_IMPORTSTR (temp_var, name);
449         }
450     }
451
452   set_pwd ();
453
454   /* Set up initial value of $_ */
455   temp_var = set_if_not ("_", dollar_vars[0]);
456
457   /* Remember this pid. */
458   dollar_dollar_pid = getpid ();
459
460   /* Now make our own defaults in case the vars that we think are
461      important are missing. */
462   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
463 #if 0
464   set_auto_export (temp_var);   /* XXX */
465 #endif
466
467   temp_var = set_if_not ("TERM", "dumb");
468 #if 0
469   set_auto_export (temp_var);   /* XXX */
470 #endif
471
472 #if defined (__QNX__)
473   /* set node id -- don't import it from the environment */
474   {
475     char node_name[22];
476 #  if defined (__QNXNTO__)
477     netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
478 #  else
479     qnx_nidtostr (getnid (), node_name, sizeof (node_name));
480 #  endif
481     temp_var = bind_variable ("NODE", node_name, 0);
482     set_auto_export (temp_var);
483   }
484 #endif
485
486   /* set up the prompts. */
487   if (interactive_shell)
488     {
489 #if defined (PROMPT_STRING_DECODE)
490       set_if_not ("PS1", primary_prompt);
491 #else
492       if (current_user.uid == -1)
493         get_current_user_info ();
494       set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
495 #endif
496       set_if_not ("PS2", secondary_prompt);
497     }
498   set_if_not ("PS4", "+ ");
499
500   /* Don't allow IFS to be imported from the environment. */
501   temp_var = bind_variable ("IFS", " \t\n", 0);
502   setifs (temp_var);
503
504   /* Magic machine types.  Pretty convenient. */
505   set_machine_vars ();
506
507   /* Default MAILCHECK for interactive shells.  Defer the creation of a
508      default MAILPATH until the startup files are read, because MAIL
509      names a mail file if MAILPATH is not set, and we should provide a
510      default only if neither is set. */
511   if (interactive_shell)
512     {
513       temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
514       VSETATTR (temp_var, att_integer);
515     }
516
517   /* Do some things with shell level. */
518   initialize_shell_level ();
519
520   set_ppid ();
521
522   /* Initialize the `getopts' stuff. */
523   temp_var = bind_variable ("OPTIND", "1", 0);
524   VSETATTR (temp_var, att_integer);
525   getopts_reset (0);
526   bind_variable ("OPTERR", "1", 0);
527   sh_opterr = 1;
528
529   if (login_shell == 1 && posixly_correct == 0)
530     set_home_var ();
531
532   /* Get the full pathname to THIS shell, and set the BASH variable
533      to it. */
534   name = get_bash_name ();
535   temp_var = bind_variable ("BASH", name, 0);
536   free (name);
537
538   /* Make the exported environment variable SHELL be the user's login
539      shell.  Note that the `tset' command looks at this variable
540      to determine what style of commands to output; if it ends in "csh",
541      then C-shell commands are output, else Bourne shell commands. */
542   set_shell_var ();
543
544   /* Make a variable called BASH_VERSION which contains the version info. */
545   bind_variable ("BASH_VERSION", shell_version_string (), 0);
546 #if defined (ARRAY_VARS)
547   make_vers_array ();
548 #endif
549
550   if (command_execution_string)
551     bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
552
553   /* Find out if we're supposed to be in Posix.2 mode via an
554      environment variable. */
555   temp_var = find_variable ("POSIXLY_CORRECT");
556   if (!temp_var)
557     temp_var = find_variable ("POSIX_PEDANTIC");
558   if (temp_var && imported_p (temp_var))
559     sv_strict_posix (temp_var->name);
560
561 #if defined (HISTORY)
562   /* Set history variables to defaults, and then do whatever we would
563      do if the variable had just been set.  Do this only in the case
564      that we are remembering commands on the history list. */
565   if (remember_on_history)
566     {
567       name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
568
569       set_if_not ("HISTFILE", name);
570       free (name);
571     }
572 #endif /* HISTORY */
573
574   /* Seed the random number generator. */
575   seedrand ();
576
577   /* Handle some "special" variables that we may have inherited from a
578      parent shell. */
579   if (interactive_shell)
580     {
581       temp_var = find_variable ("IGNOREEOF");
582       if (!temp_var)
583         temp_var = find_variable ("ignoreeof");
584       if (temp_var && imported_p (temp_var))
585         sv_ignoreeof (temp_var->name);
586     }
587
588 #if defined (HISTORY)
589   if (interactive_shell && remember_on_history)
590     {
591       sv_history_control ("HISTCONTROL");
592       sv_histignore ("HISTIGNORE");
593       sv_histtimefmt ("HISTTIMEFORMAT");
594     }
595 #endif /* HISTORY */
596
597 #if defined (READLINE) && defined (STRICT_POSIX)
598   /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
599      -DSTRICT_POSIX */
600   if (interactive_shell && posixly_correct && no_line_editing == 0)
601     rl_prefer_env_winsize = 1;
602 #endif /* READLINE && STRICT_POSIX */
603
604      /*
605       * 24 October 2001
606       *
607       * I'm tired of the arguing and bug reports.  Bash now leaves SSH_CLIENT
608       * and SSH2_CLIENT alone.  I'm going to rely on the shell_level check in
609       * isnetconn() to avoid running the startup files more often than wanted.
610       * That will, of course, only work if the user's login shell is bash, so
611       * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
612       * in config-top.h.
613       */
614 #if 0
615   temp_var = find_variable ("SSH_CLIENT");
616   if (temp_var && imported_p (temp_var))
617     {
618       VUNSETATTR (temp_var, att_exported);
619       array_needs_making = 1;
620     }
621   temp_var = find_variable ("SSH2_CLIENT");
622   if (temp_var && imported_p (temp_var))
623     {
624       VUNSETATTR (temp_var, att_exported);
625       array_needs_making = 1;
626     }
627 #endif
628
629   /* Get the user's real and effective user ids. */
630   uidset ();
631
632   temp_var = find_variable ("BASH_XTRACEFD");
633   if (temp_var && imported_p (temp_var))
634     sv_xtracefd (temp_var->name);
635
636   /* Initialize the dynamic variables, and seed their values. */
637   initialize_dynamic_variables ();
638 }
639
640 /* **************************************************************** */
641 /*                                                                  */
642 /*           Setting values for special shell variables             */
643 /*                                                                  */
644 /* **************************************************************** */
645
646 static void
647 set_machine_vars ()
648 {
649   SHELL_VAR *temp_var;
650
651   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
652   temp_var = set_if_not ("OSTYPE", OSTYPE);
653   temp_var = set_if_not ("MACHTYPE", MACHTYPE);
654
655   temp_var = set_if_not ("HOSTNAME", current_host_name);
656 }
657
658 /* Set $HOME to the information in the password file if we didn't get
659    it from the environment. */
660
661 /* This function is not static so the tilde and readline libraries can
662    use it. */
663 char *
664 sh_get_home_dir ()
665 {
666   if (current_user.home_dir == 0)
667     get_current_user_info ();
668   return current_user.home_dir;
669 }
670
671 static void
672 set_home_var ()
673 {
674   SHELL_VAR *temp_var;
675
676   temp_var = find_variable ("HOME");
677   if (temp_var == 0)
678     temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
679 #if 0
680   VSETATTR (temp_var, att_exported);
681 #endif
682 }
683
684 /* Set $SHELL to the user's login shell if it is not already set.  Call
685    get_current_user_info if we haven't already fetched the shell. */
686 static void
687 set_shell_var ()
688 {
689   SHELL_VAR *temp_var;
690
691   temp_var = find_variable ("SHELL");
692   if (temp_var == 0)
693     {
694       if (current_user.shell == 0)
695         get_current_user_info ();
696       temp_var = bind_variable ("SHELL", current_user.shell, 0);
697     }
698 #if 0
699   VSETATTR (temp_var, att_exported);
700 #endif
701 }
702
703 static char *
704 get_bash_name ()
705 {
706   char *name;
707
708   if ((login_shell == 1) && RELPATH(shell_name))
709     {
710       if (current_user.shell == 0)
711         get_current_user_info ();
712       name = savestring (current_user.shell);
713     }
714   else if (ABSPATH(shell_name))
715     name = savestring (shell_name);
716   else if (shell_name[0] == '.' && shell_name[1] == '/')
717     {
718       /* Fast path for common case. */
719       char *cdir;
720       int len;
721
722       cdir = get_string_value ("PWD");
723       if (cdir)
724         {
725           len = strlen (cdir);
726           name = (char *)xmalloc (len + strlen (shell_name) + 1);
727           strcpy (name, cdir);
728           strcpy (name + len, shell_name + 1);
729         }
730       else
731         name = savestring (shell_name);
732     }
733   else
734     {
735       char *tname;
736       int s;
737
738       tname = find_user_command (shell_name);
739
740       if (tname == 0)
741         {
742           /* Try the current directory.  If there is not an executable
743              there, just punt and use the login shell. */
744           s = file_status (shell_name);
745           if (s & FS_EXECABLE)
746             {
747               tname = make_absolute (shell_name, get_string_value ("PWD"));
748               if (*shell_name == '.')
749                 {
750                   name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
751                   if (name == 0)
752                     name = tname;
753                   else
754                     free (tname);
755                 }
756              else
757                 name = tname;
758             }
759           else
760             {
761               if (current_user.shell == 0)
762                 get_current_user_info ();
763               name = savestring (current_user.shell);
764             }
765         }
766       else
767         {
768           name = full_pathname (tname);
769           free (tname);
770         }
771     }
772
773   return (name);
774 }
775
776 void
777 adjust_shell_level (change)
778      int change;
779 {
780   char new_level[5], *old_SHLVL;
781   intmax_t old_level;
782   SHELL_VAR *temp_var;
783
784   old_SHLVL = get_string_value ("SHLVL");
785   if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
786     old_level = 0;
787
788   shell_level = old_level + change;
789   if (shell_level < 0)
790     shell_level = 0;
791   else if (shell_level > 1000)
792     {
793       internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
794       shell_level = 1;
795     }
796
797   /* We don't need the full generality of itos here. */
798   if (shell_level < 10)
799     {
800       new_level[0] = shell_level + '0';
801       new_level[1] = '\0';
802     }
803   else if (shell_level < 100)
804     {
805       new_level[0] = (shell_level / 10) + '0';
806       new_level[1] = (shell_level % 10) + '0';
807       new_level[2] = '\0';
808     }
809   else if (shell_level < 1000)
810     {
811       new_level[0] = (shell_level / 100) + '0';
812       old_level = shell_level % 100;
813       new_level[1] = (old_level / 10) + '0';
814       new_level[2] = (old_level % 10) + '0';
815       new_level[3] = '\0';
816     }
817
818   temp_var = bind_variable ("SHLVL", new_level, 0);
819   set_auto_export (temp_var);
820 }
821
822 static void
823 initialize_shell_level ()
824 {
825   adjust_shell_level (1);
826 }
827
828 /* If we got PWD from the environment, update our idea of the current
829    working directory.  In any case, make sure that PWD exists before
830    checking it.  It is possible for getcwd () to fail on shell startup,
831    and in that case, PWD would be undefined.  If this is an interactive
832    login shell, see if $HOME is the current working directory, and if
833    that's not the same string as $PWD, set PWD=$HOME. */
834
835 void
836 set_pwd ()
837 {
838   SHELL_VAR *temp_var, *home_var;
839   char *temp_string, *home_string;
840
841   home_var = find_variable ("HOME");
842   home_string = home_var ? value_cell (home_var) : (char *)NULL;
843
844   temp_var = find_variable ("PWD");
845   if (temp_var && imported_p (temp_var) &&
846       (temp_string = value_cell (temp_var)) &&
847       same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
848     set_working_directory (temp_string);
849   else if (home_string && interactive_shell && login_shell &&
850            same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
851     {
852       set_working_directory (home_string);
853       temp_var = bind_variable ("PWD", home_string, 0);
854       set_auto_export (temp_var);
855     }
856   else
857     {
858       temp_string = get_working_directory ("shell-init");
859       if (temp_string)
860         {
861           temp_var = bind_variable ("PWD", temp_string, 0);
862           set_auto_export (temp_var);
863           free (temp_string);
864         }
865     }
866
867   /* According to the Single Unix Specification, v2, $OLDPWD is an
868      `environment variable' and therefore should be auto-exported.
869      Make a dummy invisible variable for OLDPWD, and mark it as exported. */
870   temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
871   VSETATTR (temp_var, (att_exported | att_invisible));
872 }
873
874 /* Make a variable $PPID, which holds the pid of the shell's parent.  */
875 void
876 set_ppid ()
877 {
878   char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
879   SHELL_VAR *temp_var;
880
881   name = inttostr (getppid (), namebuf, sizeof(namebuf));
882   temp_var = find_variable ("PPID");
883   if (temp_var)
884     VUNSETATTR (temp_var, (att_readonly | att_exported));
885   temp_var = bind_variable ("PPID", name, 0);
886   VSETATTR (temp_var, (att_readonly | att_integer));
887 }
888
889 static void
890 uidset ()
891 {
892   char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
893   register SHELL_VAR *v;
894
895   b = inttostr (current_user.uid, buff, sizeof (buff));
896   v = find_variable ("UID");
897   if (v == 0)
898     {
899       v = bind_variable ("UID", b, 0);
900       VSETATTR (v, (att_readonly | att_integer));
901     }
902
903   if (current_user.euid != current_user.uid)
904     b = inttostr (current_user.euid, buff, sizeof (buff));
905
906   v = find_variable ("EUID");
907   if (v == 0)
908     {
909       v = bind_variable ("EUID", b, 0);
910       VSETATTR (v, (att_readonly | att_integer));
911     }
912 }
913
914 #if defined (ARRAY_VARS)
915 static void
916 make_vers_array ()
917 {
918   SHELL_VAR *vv;
919   ARRAY *av;
920   char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
921
922   unbind_variable ("BASH_VERSINFO");
923
924   vv = make_new_array_variable ("BASH_VERSINFO");
925   av = array_cell (vv);
926   strcpy (d, dist_version);
927   s = strchr (d, '.');
928   if (s)
929     *s++ = '\0';
930   array_insert (av, 0, d);
931   array_insert (av, 1, s);
932   s = inttostr (patch_level, b, sizeof (b));
933   array_insert (av, 2, s);
934   s = inttostr (build_version, b, sizeof (b));
935   array_insert (av, 3, s);
936   array_insert (av, 4, release_status);
937   array_insert (av, 5, MACHTYPE);
938
939   VSETATTR (vv, att_readonly);
940 }
941 #endif /* ARRAY_VARS */
942
943 /* Set the environment variables $LINES and $COLUMNS in response to
944    a window size change. */
945 void
946 sh_set_lines_and_columns (lines, cols)
947      int lines, cols;
948 {
949   char val[INT_STRLEN_BOUND(int) + 1], *v;
950
951 #if defined (READLINE)
952   /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
953   if (winsize_assignment)
954     return;
955 #endif
956
957   v = inttostr (lines, val, sizeof (val));
958   bind_variable ("LINES", v, 0);
959
960   v = inttostr (cols, val, sizeof (val));
961   bind_variable ("COLUMNS", v, 0);
962 }
963
964 /* **************************************************************** */
965 /*                                                                  */
966 /*                 Printing variables and values                    */
967 /*                                                                  */
968 /* **************************************************************** */
969
970 /* Print LIST (a list of shell variables) to stdout in such a way that
971    they can be read back in. */
972 void
973 print_var_list (list)
974      register SHELL_VAR **list;
975 {
976   register int i;
977   register SHELL_VAR *var;
978
979   for (i = 0; list && (var = list[i]); i++)
980     if (invisible_p (var) == 0)
981       print_assignment (var);
982 }
983
984 /* Print LIST (a list of shell functions) to stdout in such a way that
985    they can be read back in. */
986 void
987 print_func_list (list)
988      register SHELL_VAR **list;
989 {
990   register int i;
991   register SHELL_VAR *var;
992
993   for (i = 0; list && (var = list[i]); i++)
994     {
995       printf ("%s ", var->name);
996       print_var_function (var);
997       printf ("\n");
998     }
999 }
1000       
1001 /* Print the value of a single SHELL_VAR.  No newline is
1002    output, but the variable is printed in such a way that
1003    it can be read back in. */
1004 void
1005 print_assignment (var)
1006      SHELL_VAR *var;
1007 {
1008   if (var_isset (var) == 0)
1009     return;
1010
1011   if (function_p (var))
1012     {
1013       printf ("%s", var->name);
1014       print_var_function (var);
1015       printf ("\n");
1016     }
1017 #if defined (ARRAY_VARS)
1018   else if (array_p (var))
1019     print_array_assignment (var, 0);
1020   else if (assoc_p (var))
1021     print_assoc_assignment (var, 0);
1022 #endif /* ARRAY_VARS */
1023   else
1024     {
1025       printf ("%s=", var->name);
1026       print_var_value (var, 1);
1027       printf ("\n");
1028     }
1029 }
1030
1031 /* Print the value cell of VAR, a shell variable.  Do not print
1032    the name, nor leading/trailing newline.  If QUOTE is non-zero,
1033    and the value contains shell metacharacters, quote the value
1034    in such a way that it can be read back in. */
1035 void
1036 print_var_value (var, quote)
1037      SHELL_VAR *var;
1038      int quote;
1039 {
1040   char *t;
1041
1042   if (var_isset (var) == 0)
1043     return;
1044
1045   if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
1046     {
1047       t = ansic_quote (value_cell (var), 0, (int *)0);
1048       printf ("%s", t);
1049       free (t);
1050     }
1051   else if (quote && sh_contains_shell_metas (value_cell (var)))
1052     {
1053       t = sh_single_quote (value_cell (var));
1054       printf ("%s", t);
1055       free (t);
1056     }
1057   else
1058     printf ("%s", value_cell (var));
1059 }
1060
1061 /* Print the function cell of VAR, a shell variable.  Do not
1062    print the name, nor leading/trailing newline. */
1063 void
1064 print_var_function (var)
1065      SHELL_VAR *var;
1066 {
1067   char *x;
1068
1069   if (function_p (var) && var_isset (var))
1070     {
1071       x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
1072       printf ("%s", x);
1073     }
1074 }
1075
1076 /* **************************************************************** */
1077 /*                                                                  */
1078 /*                      Dynamic Variables                           */
1079 /*                                                                  */
1080 /* **************************************************************** */
1081
1082 /* DYNAMIC VARIABLES
1083
1084    These are variables whose values are generated anew each time they are
1085    referenced.  These are implemented using a pair of function pointers
1086    in the struct variable: assign_func, which is called from bind_variable
1087    and, if arrays are compiled into the shell, some of the functions in
1088    arrayfunc.c, and dynamic_value, which is called from find_variable.
1089
1090    assign_func is called from bind_variable_internal, if
1091    bind_variable_internal discovers that the variable being assigned to
1092    has such a function.  The function is called as
1093         SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
1094    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
1095    is usually ENTRY (self).  IND is an index for an array variable, and
1096    unused otherwise.
1097
1098    dynamic_value is called from find_variable_internal to return a `new'
1099    value for the specified dynamic varible.  If this function is NULL,
1100    the variable is treated as a `normal' shell variable.  If it is not,
1101    however, then this function is called like this:
1102         tempvar = (*(var->dynamic_value)) (var);
1103
1104    Sometimes `tempvar' will replace the value of `var'.  Other times, the
1105    shell will simply use the string value.  Pretty object-oriented, huh?
1106
1107    Be warned, though: if you `unset' a special variable, it loses its
1108    special meaning, even if you subsequently set it.
1109
1110    The special assignment code would probably have been better put in
1111    subst.c: do_assignment_internal, in the same style as
1112    stupidly_hack_special_variables, but I wanted the changes as
1113    localized as possible.  */
1114
1115 #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1116   do \
1117     { \
1118       v = bind_variable (var, (val), 0); \
1119       v->dynamic_value = gfunc; \
1120       v->assign_func = afunc; \
1121     } \
1122   while (0)
1123
1124 #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1125   do \
1126     { \
1127       v = make_new_array_variable (var); \
1128       v->dynamic_value = gfunc; \
1129       v->assign_func = afunc; \
1130     } \
1131   while (0)
1132
1133 #define INIT_DYNAMIC_ASSOC_VAR(var, gfunc, afunc) \
1134   do \
1135     { \
1136       v = make_new_assoc_variable (var); \
1137       v->dynamic_value = gfunc; \
1138       v->assign_func = afunc; \
1139     } \
1140   while (0)
1141
1142 static SHELL_VAR *
1143 null_assign (self, value, unused, key)
1144      SHELL_VAR *self;
1145      char *value;
1146      arrayind_t unused;
1147      char *key;
1148 {
1149   return (self);
1150 }
1151
1152 #if defined (ARRAY_VARS)
1153 static SHELL_VAR *
1154 null_array_assign (self, value, ind, key)
1155      SHELL_VAR *self;
1156      char *value;
1157      arrayind_t ind;
1158      char *key;
1159 {
1160   return (self);
1161 }
1162 #endif
1163
1164 /* Degenerate `dynamic_value' function; just returns what's passed without
1165    manipulation. */
1166 static SHELL_VAR *
1167 get_self (self)
1168      SHELL_VAR *self;
1169 {
1170   return (self);
1171 }
1172
1173 #if defined (ARRAY_VARS)
1174 /* A generic dynamic array variable initializer.  Initialize array variable
1175    NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1176 static SHELL_VAR *
1177 init_dynamic_array_var (name, getfunc, setfunc, attrs)
1178      char *name;
1179      sh_var_value_func_t *getfunc;
1180      sh_var_assign_func_t *setfunc;
1181      int attrs;
1182 {
1183   SHELL_VAR *v;
1184
1185   v = find_variable (name);
1186   if (v)
1187     return (v);
1188   INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1189   if (attrs)
1190     VSETATTR (v, attrs);
1191   return v;
1192 }
1193
1194 static SHELL_VAR *
1195 init_dynamic_assoc_var (name, getfunc, setfunc, attrs)
1196      char *name;
1197      sh_var_value_func_t *getfunc;
1198      sh_var_assign_func_t *setfunc;
1199      int attrs;
1200 {
1201   SHELL_VAR *v;
1202
1203   v = find_variable (name);
1204   if (v)
1205     return (v);
1206   INIT_DYNAMIC_ASSOC_VAR (name, getfunc, setfunc);
1207   if (attrs)
1208     VSETATTR (v, attrs);
1209   return v;
1210 }
1211 #endif
1212
1213 /* The value of $SECONDS.  This is the number of seconds since shell
1214    invocation, or, the number of seconds since the last assignment + the
1215    value of the last assignment. */
1216 static intmax_t seconds_value_assigned;
1217
1218 static SHELL_VAR *
1219 assign_seconds (self, value, unused, key)
1220      SHELL_VAR *self;
1221      char *value;
1222      arrayind_t unused;
1223      char *key;
1224 {
1225   if (legal_number (value, &seconds_value_assigned) == 0)
1226     seconds_value_assigned = 0;
1227   shell_start_time = NOW;
1228   return (self);
1229 }
1230
1231 static SHELL_VAR *
1232 get_seconds (var)
1233      SHELL_VAR *var;
1234 {
1235   time_t time_since_start;
1236   char *p;
1237
1238   time_since_start = NOW - shell_start_time;
1239   p = itos(seconds_value_assigned + time_since_start);
1240
1241   FREE (value_cell (var));
1242
1243   VSETATTR (var, att_integer);
1244   var_setvalue (var, p);
1245   return (var);
1246 }
1247
1248 static SHELL_VAR *
1249 init_seconds_var ()
1250 {
1251   SHELL_VAR *v;
1252
1253   v = find_variable ("SECONDS");
1254   if (v)
1255     {
1256       if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1257         seconds_value_assigned = 0;
1258     }
1259   INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
1260   return v;      
1261 }
1262      
1263 /* The random number seed.  You can change this by setting RANDOM. */
1264 static unsigned long rseed = 1;
1265 static int last_random_value;
1266 static int seeded_subshell = 0;
1267
1268 /* A linear congruential random number generator based on the example
1269    one in the ANSI C standard.  This one isn't very good, but a more
1270    complicated one is overkill. */
1271
1272 /* Returns a pseudo-random number between 0 and 32767. */
1273 static int
1274 brand ()
1275 {
1276   /* From "Random number generators: good ones are hard to find",
1277      Park and Miller, Communications of the ACM, vol. 31, no. 10,
1278      October 1988, p. 1195. filtered through FreeBSD */
1279   long h, l;
1280
1281   /* Can't seed with 0. */
1282   if (rseed == 0)
1283     rseed = 123459876;
1284   h = rseed / 127773;
1285   l = rseed % 127773;
1286   rseed = 16807 * l - 2836 * h;
1287 #if 0
1288   if (rseed < 0)
1289     rseed += 0x7fffffff;
1290 #endif
1291   return ((unsigned int)(rseed & 32767));       /* was % 32768 */
1292 }
1293
1294 /* Set the random number generator seed to SEED. */
1295 static void
1296 sbrand (seed)
1297      unsigned long seed;
1298 {
1299   rseed = seed;
1300   last_random_value = 0;
1301 }
1302
1303 static void
1304 seedrand ()
1305 {
1306   struct timeval tv;
1307
1308   gettimeofday (&tv, NULL);
1309   sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ());
1310 }
1311
1312 static SHELL_VAR *
1313 assign_random (self, value, unused, key)
1314      SHELL_VAR *self;
1315      char *value;
1316      arrayind_t unused;
1317      char *key;
1318 {
1319   sbrand (strtoul (value, (char **)NULL, 10));
1320   if (subshell_environment)
1321     seeded_subshell = getpid ();
1322   return (self);
1323 }
1324
1325 int
1326 get_random_number ()
1327 {
1328   int rv, pid;
1329
1330   /* Reset for command and process substitution. */
1331   pid = getpid ();
1332   if (subshell_environment && seeded_subshell != pid)
1333     {
1334       seedrand ();
1335       seeded_subshell = pid;
1336     }
1337
1338   do
1339     rv = brand ();
1340   while (rv == last_random_value);
1341   return rv;
1342 }
1343
1344 static SHELL_VAR *
1345 get_random (var)
1346      SHELL_VAR *var;
1347 {
1348   int rv;
1349   char *p;
1350
1351   rv = get_random_number ();
1352   last_random_value = rv;
1353   p = itos (rv);
1354
1355   FREE (value_cell (var));
1356
1357   VSETATTR (var, att_integer);
1358   var_setvalue (var, p);
1359   return (var);
1360 }
1361
1362 static SHELL_VAR *
1363 assign_lineno (var, value, unused, key)
1364      SHELL_VAR *var;
1365      char *value;
1366      arrayind_t unused;
1367      char *key;
1368 {
1369   intmax_t new_value;
1370
1371   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1372     new_value = 0;
1373   line_number = line_number_base = new_value;
1374   return var;
1375 }
1376
1377 /* Function which returns the current line number. */
1378 static SHELL_VAR *
1379 get_lineno (var)
1380      SHELL_VAR *var;
1381 {
1382   char *p;
1383   int ln;
1384
1385   ln = executing_line_number ();
1386   p = itos (ln);
1387   FREE (value_cell (var));
1388   var_setvalue (var, p);
1389   return (var);
1390 }
1391
1392 static SHELL_VAR *
1393 assign_subshell (var, value, unused, key)
1394      SHELL_VAR *var;
1395      char *value;
1396      arrayind_t unused;
1397      char *key;
1398 {
1399   intmax_t new_value;
1400
1401   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1402     new_value = 0;
1403   subshell_level = new_value;
1404   return var;
1405 }
1406
1407 static SHELL_VAR *
1408 get_subshell (var)
1409      SHELL_VAR *var;
1410 {
1411   char *p;
1412
1413   p = itos (subshell_level);
1414   FREE (value_cell (var));
1415   var_setvalue (var, p);
1416   return (var);
1417 }
1418
1419 static SHELL_VAR *
1420 get_bashpid (var)
1421      SHELL_VAR *var;
1422 {
1423   int pid;
1424   char *p;
1425
1426   pid = getpid ();
1427   p = itos (pid);
1428
1429   FREE (value_cell (var));
1430   VSETATTR (var, att_integer|att_readonly);
1431   var_setvalue (var, p);
1432   return (var);
1433 }
1434
1435 static SHELL_VAR *
1436 get_bash_command (var)
1437      SHELL_VAR *var;
1438 {
1439   char *p;
1440
1441   if (the_printed_command_except_trap)
1442     p = savestring (the_printed_command_except_trap);
1443   else
1444     {
1445       p = (char *)xmalloc (1);
1446       p[0] = '\0';
1447     }
1448   FREE (value_cell (var));
1449   var_setvalue (var, p);
1450   return (var);
1451 }
1452
1453 #if defined (HISTORY)
1454 static SHELL_VAR *
1455 get_histcmd (var)
1456      SHELL_VAR *var;
1457 {
1458   char *p;
1459
1460   p = itos (history_number ());
1461   FREE (value_cell (var));
1462   var_setvalue (var, p);
1463   return (var);
1464 }
1465 #endif
1466
1467 #if defined (READLINE)
1468 /* When this function returns, VAR->value points to malloced memory. */
1469 static SHELL_VAR *
1470 get_comp_wordbreaks (var)
1471      SHELL_VAR *var;
1472 {
1473   /* If we don't have anything yet, assign a default value. */
1474   if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1475     enable_hostname_completion (perform_hostname_completion);
1476
1477   FREE (value_cell (var));
1478   var_setvalue (var, savestring (rl_completer_word_break_characters));
1479
1480   return (var);
1481 }
1482
1483 /* When this function returns, rl_completer_word_break_characters points to
1484    malloced memory. */
1485 static SHELL_VAR *
1486 assign_comp_wordbreaks (self, value, unused, key)
1487      SHELL_VAR *self;
1488      char *value;
1489      arrayind_t unused;
1490      char *key;
1491 {
1492   if (rl_completer_word_break_characters &&
1493       rl_completer_word_break_characters != rl_basic_word_break_characters)
1494     free (rl_completer_word_break_characters);
1495
1496   rl_completer_word_break_characters = savestring (value);
1497   return self;
1498 }
1499 #endif /* READLINE */
1500
1501 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1502 static SHELL_VAR *
1503 assign_dirstack (self, value, ind, key)
1504      SHELL_VAR *self;
1505      char *value;
1506      arrayind_t ind;
1507      char *key;
1508 {
1509   set_dirstack_element (ind, 1, value);
1510   return self;
1511 }
1512
1513 static SHELL_VAR *
1514 get_dirstack (self)
1515      SHELL_VAR *self;
1516 {
1517   ARRAY *a;
1518   WORD_LIST *l;
1519
1520   l = get_directory_stack (0);
1521   a = array_from_word_list (l);
1522   array_dispose (array_cell (self));
1523   dispose_words (l);
1524   var_setarray (self, a);
1525   return self;
1526 }
1527 #endif /* PUSHD AND POPD && ARRAY_VARS */
1528
1529 #if defined (ARRAY_VARS)
1530 /* We don't want to initialize the group set with a call to getgroups()
1531    unless we're asked to, but we only want to do it once. */
1532 static SHELL_VAR *
1533 get_groupset (self)
1534      SHELL_VAR *self;
1535 {
1536   register int i;
1537   int ng;
1538   ARRAY *a;
1539   static char **group_set = (char **)NULL;
1540
1541   if (group_set == 0)
1542     {
1543       group_set = get_group_list (&ng);
1544       a = array_cell (self);
1545       for (i = 0; i < ng; i++)
1546         array_insert (a, i, group_set[i]);
1547     }
1548   return (self);
1549 }
1550
1551 static SHELL_VAR *
1552 build_hashcmd (self)
1553      SHELL_VAR *self;
1554 {
1555   HASH_TABLE *h;
1556   int i;
1557   char *k, *v;
1558   BUCKET_CONTENTS *item;
1559
1560   h = assoc_cell (self);
1561   if (h)
1562     assoc_dispose (h);
1563
1564   if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
1565     {
1566       var_setvalue (self, (char *)NULL);
1567       return self;
1568     }
1569
1570   h = assoc_create (hashed_filenames->nbuckets);
1571   for (i = 0; i < hashed_filenames->nbuckets; i++)
1572     {
1573       for (item = hash_items (i, hashed_filenames); item; item = item->next)
1574         {
1575           k = savestring (item->key);
1576           v = pathdata(item)->path;
1577           assoc_insert (h, k, v);
1578         }
1579     }
1580
1581   var_setvalue (self, (char *)h);
1582   return self;
1583 }
1584
1585 static SHELL_VAR *
1586 get_hashcmd (self)
1587      SHELL_VAR *self;
1588 {
1589   build_hashcmd (self);
1590   return (self);
1591 }
1592
1593 static SHELL_VAR *
1594 assign_hashcmd (self, value, ind, key)
1595      SHELL_VAR *self;
1596      char *value;
1597      arrayind_t ind;
1598      char *key;
1599 {
1600   phash_insert (key, value, 0, 0);
1601   return (build_hashcmd (self));
1602 }
1603
1604 #if defined (ALIAS)
1605 static SHELL_VAR *
1606 build_aliasvar (self)
1607      SHELL_VAR *self;
1608 {
1609   HASH_TABLE *h;
1610   int i;
1611   char *k, *v;
1612   BUCKET_CONTENTS *item;
1613
1614   h = assoc_cell (self);
1615   if (h)
1616     assoc_dispose (h);
1617
1618   if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
1619     {
1620       var_setvalue (self, (char *)NULL);
1621       return self;
1622     }
1623
1624   h = assoc_create (aliases->nbuckets);
1625   for (i = 0; i < aliases->nbuckets; i++)
1626     {
1627       for (item = hash_items (i, aliases); item; item = item->next)
1628         {
1629           k = savestring (item->key);
1630           v = ((alias_t *)(item->data))->value;
1631           assoc_insert (h, k, v);
1632         }
1633     }
1634
1635   var_setvalue (self, (char *)h);
1636   return self;
1637 }
1638
1639 static SHELL_VAR *
1640 get_aliasvar (self)
1641      SHELL_VAR *self;
1642 {
1643   build_aliasvar (self);
1644   return (self);
1645 }
1646
1647 static SHELL_VAR *
1648 assign_aliasvar (self, value, ind, key)
1649      SHELL_VAR *self;
1650      char *value;
1651      arrayind_t ind;
1652      char *key;
1653 {
1654   add_alias (key, value);
1655   return (build_aliasvar (self));
1656 }
1657 #endif /* ALIAS */
1658
1659 #endif /* ARRAY_VARS */
1660
1661 /* If ARRAY_VARS is not defined, this just returns the name of any
1662    currently-executing function.  If we have arrays, it's a call stack. */
1663 static SHELL_VAR *
1664 get_funcname (self)
1665      SHELL_VAR *self;
1666 {
1667 #if ! defined (ARRAY_VARS)
1668   char *t;
1669   if (variable_context && this_shell_function)
1670     {
1671       FREE (value_cell (self));
1672       t = savestring (this_shell_function->name);
1673       var_setvalue (self, t);
1674     }
1675 #endif
1676   return (self);
1677 }
1678
1679 void
1680 make_funcname_visible (on_or_off)
1681      int on_or_off;
1682 {
1683   SHELL_VAR *v;
1684
1685   v = find_variable ("FUNCNAME");
1686   if (v == 0 || v->dynamic_value == 0)
1687     return;
1688
1689   if (on_or_off)
1690     VUNSETATTR (v, att_invisible);
1691   else
1692     VSETATTR (v, att_invisible);
1693 }
1694
1695 static SHELL_VAR *
1696 init_funcname_var ()
1697 {
1698   SHELL_VAR *v;
1699
1700   v = find_variable ("FUNCNAME");
1701   if (v)
1702     return v;
1703 #if defined (ARRAY_VARS)
1704   INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1705 #else
1706   INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1707 #endif
1708   VSETATTR (v, att_invisible|att_noassign);
1709   return v;
1710 }
1711
1712 static void
1713 initialize_dynamic_variables ()
1714 {
1715   SHELL_VAR *v;
1716
1717   v = init_seconds_var ();
1718
1719   INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1720   INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1721
1722   INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1723   VSETATTR (v, att_integer);
1724   INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1725   VSETATTR (v, att_integer);
1726
1727   INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
1728   VSETATTR (v, att_integer|att_readonly);
1729
1730 #if defined (HISTORY)
1731   INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
1732   VSETATTR (v, att_integer);
1733 #endif
1734
1735 #if defined (READLINE)
1736   INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1737 #endif
1738
1739 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1740   v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
1741 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1742
1743 #if defined (ARRAY_VARS)
1744   v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1745
1746 #  if defined (DEBUGGER)
1747   v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
1748   v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
1749 #  endif /* DEBUGGER */
1750   v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
1751   v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
1752
1753   v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree);
1754 #  if defined (ALIAS)
1755   v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree);
1756 #  endif
1757 #endif
1758
1759   v = init_funcname_var ();
1760 }
1761
1762 /* **************************************************************** */
1763 /*                                                                  */
1764 /*              Retrieving variables and values                     */
1765 /*                                                                  */
1766 /* **************************************************************** */
1767
1768 /* How to get a pointer to the shell variable or function named NAME.
1769    HASHED_VARS is a pointer to the hash table containing the list
1770    of interest (either variables or functions). */
1771
1772 static SHELL_VAR *
1773 hash_lookup (name, hashed_vars)
1774      const char *name;
1775      HASH_TABLE *hashed_vars;
1776 {
1777   BUCKET_CONTENTS *bucket;
1778
1779   bucket = hash_search (name, hashed_vars, 0);
1780   /* If we find the name in HASHED_VARS, set LAST_TABLE_SEARCHED to that
1781      table. */
1782   if (bucket)
1783     last_table_searched = hashed_vars;
1784   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1785 }
1786
1787 SHELL_VAR *
1788 var_lookup (name, vcontext)
1789      const char *name;
1790      VAR_CONTEXT *vcontext;
1791 {
1792   VAR_CONTEXT *vc;
1793   SHELL_VAR *v;
1794
1795   v = (SHELL_VAR *)NULL;
1796   for (vc = vcontext; vc; vc = vc->down)
1797     if (v = hash_lookup (name, vc->table))
1798       break;
1799
1800   return v;
1801 }
1802
1803 /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
1804    then also search the temporarily built list of exported variables.
1805    The lookup order is:
1806         temporary_env
1807         shell_variables list
1808 */
1809
1810 SHELL_VAR *
1811 find_variable_internal (name, force_tempenv)
1812      const char *name;
1813      int force_tempenv;
1814 {
1815   SHELL_VAR *var;
1816   int search_tempenv;
1817   VAR_CONTEXT *vc;
1818
1819   var = (SHELL_VAR *)NULL;
1820
1821   /* If explicitly requested, first look in the temporary environment for
1822      the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
1823      to get the `exported' value of $foo.  This happens if we are executing
1824      a function or builtin, or if we are looking up a variable in a
1825      "subshell environment". */
1826   search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1827
1828   if (search_tempenv && temporary_env)          
1829     var = hash_lookup (name, temporary_env);
1830
1831   vc = shell_variables;
1832 #if 0
1833 if (search_tempenv == 0 && /* (subshell_environment & SUBSHELL_COMSUB) && */
1834     expanding_redir &&
1835     (this_shell_builtin == eval_builtin || this_shell_builtin == command_builtin))
1836   {
1837   itrace("find_variable_internal: search_tempenv == 0: skipping VC_BLTNENV");
1838   while (vc && (vc->flags & VC_BLTNENV))
1839     vc = vc->down;
1840   if (vc == 0)
1841     vc = shell_variables;
1842   }
1843 #endif
1844
1845   if (var == 0)
1846     var = var_lookup (name, vc);
1847
1848   if (var == 0)
1849     return ((SHELL_VAR *)NULL);
1850
1851   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1852 }
1853
1854 /* Look up and resolve the chain of nameref variables starting at V all the
1855    way to NULL or non-nameref. */
1856 SHELL_VAR *
1857 find_variable_nameref (v)
1858      SHELL_VAR *v;
1859 {
1860   int level;
1861   char *newname;
1862   SHELL_VAR *orig, *oldv;
1863
1864   level = 0;
1865   orig = v;
1866   while (v && nameref_p (v))
1867     {
1868       level++;
1869       if (level > NAMEREF_MAX)
1870         return ((SHELL_VAR *)0);        /* error message here? */
1871       newname = nameref_cell (v);
1872       if (newname == 0 || *newname == '\0')
1873         return ((SHELL_VAR *)0);
1874       oldv = v;
1875       v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
1876       if (v == orig || v == oldv)
1877         {
1878           internal_warning (_("%s: circular name reference"), orig->name);
1879           return ((SHELL_VAR *)0);
1880         }
1881     }
1882   return v;
1883 }
1884
1885 /* Resolve the chain of nameref variables for NAME.  XXX - could change later */
1886 SHELL_VAR *
1887 find_variable_last_nameref (name)
1888      const char *name;
1889 {
1890   SHELL_VAR *v, *nv;
1891   char *newname;
1892   int level;
1893
1894   nv = v = find_variable_noref (name);
1895   level = 0;
1896   while (v && nameref_p (v))
1897     {
1898       level++;
1899       if (level > NAMEREF_MAX)
1900         return ((SHELL_VAR *)0);        /* error message here? */
1901       newname = nameref_cell (v);
1902       if (newname == 0 || *newname == '\0')
1903         return ((SHELL_VAR *)0);
1904       nv = v;
1905       v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
1906     }
1907   return nv;
1908 }
1909
1910 /* Resolve the chain of nameref variables for NAME.  XXX - could change later */
1911 SHELL_VAR *
1912 find_global_variable_last_nameref (name)
1913      const char *name;
1914 {
1915   SHELL_VAR *v, *nv;
1916   char *newname;
1917   int level;
1918
1919   nv = v = find_global_variable_noref (name);
1920   level = 0;
1921   while (v && nameref_p (v))
1922     {
1923       level++;
1924       if (level > NAMEREF_MAX)
1925         return ((SHELL_VAR *)0);        /* error message here? */
1926       newname = nameref_cell (v);
1927       if (newname == 0 || *newname == '\0')
1928         return ((SHELL_VAR *)0);
1929       nv = v;
1930       v = find_global_variable_noref (newname);
1931     }
1932   return nv;
1933 }
1934
1935 static SHELL_VAR *
1936 find_nameref_at_context (v, vc)
1937      SHELL_VAR *v;
1938      VAR_CONTEXT *vc;
1939 {
1940   SHELL_VAR *nv, *nv2;
1941   VAR_CONTEXT *nvc;
1942   char *newname;
1943   int level;
1944
1945   nv = v;
1946   level = 1;
1947   while (nv && nameref_p (nv))
1948     {
1949       level++;
1950       if (level > NAMEREF_MAX)
1951         return ((SHELL_VAR *)NULL);
1952       newname = nameref_cell (nv);
1953       if (newname == 0 || *newname == '\0')
1954         return ((SHELL_VAR *)NULL);      
1955       nv2 = hash_lookup (newname, vc->table);
1956       if (nv2 == 0)
1957         break;
1958       nv = nv2;
1959     }
1960   return nv;
1961 }
1962
1963 /* Do nameref resolution from the VC, which is the local context for some
1964    function or builtin, `up' the chain to the global variables context.  If
1965    NVCP is not NULL, return the variable context where we finally ended the
1966    nameref resolution (so the bind_variable_internal can use the correct
1967    variable context and hash table). */
1968 static SHELL_VAR *
1969 find_variable_nameref_context (v, vc, nvcp)
1970      SHELL_VAR *v;
1971      VAR_CONTEXT *vc;
1972      VAR_CONTEXT **nvcp;
1973 {
1974   SHELL_VAR *nv, *nv2;
1975   VAR_CONTEXT *nvc;
1976
1977   /* Look starting at the current context all the way `up' */
1978   for (nv = v, nvc = vc; nvc; nvc = nvc->down)
1979     {
1980       nv2 = find_nameref_at_context (nv, nvc);
1981       if (nv2 == 0)
1982         continue;
1983       nv = nv2;
1984       if (*nvcp)
1985         *nvcp = nvc;
1986       if (nameref_p (nv) == 0)
1987         break;
1988     }
1989   return (nameref_p (nv) ? (SHELL_VAR *)NULL : nv);
1990 }
1991
1992 /* Do nameref resolution from the VC, which is the local context for some
1993    function or builtin, `up' the chain to the global variables context.  If
1994    NVCP is not NULL, return the variable context where we finally ended the
1995    nameref resolution (so the bind_variable_internal can use the correct
1996    variable context and hash table). */
1997 static SHELL_VAR *
1998 find_variable_last_nameref_context (v, vc, nvcp)
1999      SHELL_VAR *v;
2000      VAR_CONTEXT *vc;
2001      VAR_CONTEXT **nvcp;
2002 {
2003   SHELL_VAR *nv, *nv2;
2004   VAR_CONTEXT *nvc;
2005
2006   /* Look starting at the current context all the way `up' */
2007   for (nv = v, nvc = vc; nvc; nvc = nvc->down)
2008     {
2009       nv2 = find_nameref_at_context (nv, nvc);
2010       if (nv2 == 0)
2011         continue;
2012       nv = nv2;
2013       if (*nvcp)
2014         *nvcp = nvc;
2015     }
2016   return (nameref_p (nv) ? nv : (SHELL_VAR *)NULL);
2017 }
2018
2019 /* Find a variable, forcing a search of the temporary environment first */
2020 SHELL_VAR *
2021 find_variable_tempenv (name)
2022      const char *name;
2023 {
2024   SHELL_VAR *var;
2025
2026   var = find_variable_internal (name, 1);
2027   if (var && nameref_p (var))
2028     var = find_variable_nameref (var);
2029   return (var);
2030 }
2031
2032 /* Find a variable, not forcing a search of the temporary environment first */
2033 SHELL_VAR *
2034 find_variable_notempenv (name)
2035      const char *name;
2036 {
2037   SHELL_VAR *var;
2038
2039   var = find_variable_internal (name, 0);
2040   if (var && nameref_p (var))
2041     var = find_variable_nameref (var);
2042   return (var);
2043 }
2044
2045 SHELL_VAR *
2046 find_global_variable (name)
2047      const char *name;
2048 {
2049   SHELL_VAR *var;
2050
2051   var = var_lookup (name, global_variables);
2052   if (var && nameref_p (var))
2053     var = find_variable_nameref (var);
2054
2055   if (var == 0)
2056     return ((SHELL_VAR *)NULL);
2057
2058   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2059 }
2060
2061 SHELL_VAR *
2062 find_global_variable_noref (name)
2063      const char *name;
2064 {
2065   SHELL_VAR *var;
2066
2067   var = var_lookup (name, global_variables);
2068
2069   if (var == 0)
2070     return ((SHELL_VAR *)NULL);
2071
2072   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2073 }
2074
2075 SHELL_VAR *
2076 find_shell_variable (name)
2077      const char *name;
2078 {
2079   SHELL_VAR *var;
2080
2081   var = var_lookup (name, shell_variables);
2082   if (var && nameref_p (var))
2083     var = find_variable_nameref (var);
2084
2085   if (var == 0)
2086     return ((SHELL_VAR *)NULL);
2087
2088   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2089 }
2090
2091 /* Look up the variable entry named NAME.  Returns the entry or NULL. */
2092 SHELL_VAR *
2093 find_variable (name)
2094      const char *name;
2095 {
2096   SHELL_VAR *v;
2097
2098   last_table_searched = 0;
2099   v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
2100   if (v && nameref_p (v))
2101     v = find_variable_nameref (v);
2102   return v;
2103 }
2104
2105 SHELL_VAR *
2106 find_variable_noref (name)
2107      const char *name;
2108 {
2109   SHELL_VAR *v;
2110
2111   v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
2112   return v;
2113 }
2114
2115 /* Look up the function entry whose name matches STRING.
2116    Returns the entry or NULL. */
2117 SHELL_VAR *
2118 find_function (name)
2119      const char *name;
2120 {
2121   return (hash_lookup (name, shell_functions));
2122 }
2123
2124 /* Find the function definition for the shell function named NAME.  Returns
2125    the entry or NULL. */
2126 FUNCTION_DEF *
2127 find_function_def (name)
2128      const char *name;
2129 {
2130 #if defined (DEBUGGER)
2131   return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
2132 #else
2133   return ((FUNCTION_DEF *)0);
2134 #endif
2135 }
2136
2137 /* Return the value of VAR.  VAR is assumed to have been the result of a
2138    lookup without any subscript, if arrays are compiled into the shell. */
2139 char *
2140 get_variable_value (var)
2141      SHELL_VAR *var;
2142 {
2143   if (var == 0)
2144     return ((char *)NULL);
2145 #if defined (ARRAY_VARS)
2146   else if (array_p (var))
2147     return (array_reference (array_cell (var), 0));
2148   else if (assoc_p (var))
2149     return (assoc_reference (assoc_cell (var), "0"));
2150 #endif
2151   else
2152     return (value_cell (var));
2153 }
2154
2155 /* Return the string value of a variable.  Return NULL if the variable
2156    doesn't exist.  Don't cons a new string.  This is a potential memory
2157    leak if the variable is found in the temporary environment.  Since
2158    functions and variables have separate name spaces, returns NULL if
2159    var_name is a shell function only. */
2160 char *
2161 get_string_value (var_name)
2162      const char *var_name;
2163 {
2164   SHELL_VAR *var;
2165
2166   var = find_variable (var_name);
2167   return ((var) ? get_variable_value (var) : (char *)NULL);
2168 }
2169
2170 /* This is present for use by the tilde and readline libraries. */
2171 char *
2172 sh_get_env_value (v)
2173      const char *v;
2174 {
2175   return get_string_value (v);
2176 }
2177
2178 /* **************************************************************** */
2179 /*                                                                  */
2180 /*                Creating and setting variables                    */
2181 /*                                                                  */
2182 /* **************************************************************** */
2183
2184 /* Set NAME to VALUE if NAME has no value. */
2185 SHELL_VAR *
2186 set_if_not (name, value)
2187      char *name, *value;
2188 {
2189   SHELL_VAR *v;
2190
2191   if (shell_variables == 0)
2192     create_variable_tables ();
2193
2194   v = find_variable (name);
2195   if (v == 0)
2196     v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
2197   return (v);
2198 }
2199
2200 /* Create a local variable referenced by NAME. */
2201 SHELL_VAR *
2202 make_local_variable (name)
2203      const char *name;
2204 {
2205   SHELL_VAR *new_var, *old_var;
2206   VAR_CONTEXT *vc;
2207   int was_tmpvar;
2208   char *tmp_value;
2209
2210   /* local foo; local foo;  is a no-op. */
2211   old_var = find_variable (name);
2212   if (old_var && local_p (old_var) && old_var->context == variable_context)
2213     return (old_var);
2214
2215   was_tmpvar = old_var && tempvar_p (old_var);
2216   /* If we're making a local variable in a shell function, the temporary env
2217      has already been merged into the function's variable context stack.  We
2218      can assume that a temporary var in the same context appears in the same
2219      VAR_CONTEXT and can safely be returned without creating a new variable
2220      (which results in duplicate names in the same VAR_CONTEXT->table */
2221   /* We can't just test tmpvar_p because variables in the temporary env given
2222      to a shell function appear in the function's local variable VAR_CONTEXT
2223      but retain their tempvar attribute.  We want temporary variables that are
2224      found in temporary_env, hence the test for last_table_searched, which is
2225      set in hash_lookup and only (so far) checked here. */
2226   if (was_tmpvar && old_var->context == variable_context && last_table_searched != temporary_env)
2227     {
2228       VUNSETATTR (old_var, att_invisible);
2229       return (old_var);
2230     }
2231   if (was_tmpvar)
2232     tmp_value = value_cell (old_var);
2233
2234   for (vc = shell_variables; vc; vc = vc->down)
2235     if (vc_isfuncenv (vc) && vc->scope == variable_context)
2236       break;
2237
2238   if (vc == 0)
2239     {
2240       internal_error (_("make_local_variable: no function context at current scope"));
2241       return ((SHELL_VAR *)NULL);
2242     }
2243   else if (vc->table == 0)
2244     vc->table = hash_create (TEMPENV_HASH_BUCKETS);
2245
2246   /* Since this is called only from the local/declare/typeset code, we can
2247      call builtin_error here without worry (of course, it will also work
2248      for anything that sets this_command_name).  Variables with the `noassign'
2249      attribute may not be made local.  The test against old_var's context
2250      level is to disallow local copies of readonly global variables (since I
2251      believe that this could be a security hole).  Readonly copies of calling
2252      function local variables are OK. */
2253   if (old_var && (noassign_p (old_var) ||
2254                  (readonly_p (old_var) && old_var->context == 0)))
2255     {
2256       if (readonly_p (old_var))
2257         sh_readonly (name);
2258       else if (noassign_p (old_var))
2259         builtin_error (_("%s: variable may not be assigned value"), name);
2260 #if 0
2261       /* Let noassign variables through with a warning */
2262       if (readonly_p (old_var))
2263 #endif
2264         return ((SHELL_VAR *)NULL);
2265     }
2266
2267   if (old_var == 0)
2268     new_var = make_new_variable (name, vc->table);
2269   else
2270     {
2271       new_var = make_new_variable (name, vc->table);
2272
2273       /* If we found this variable in one of the temporary environments,
2274          inherit its value.  Watch to see if this causes problems with
2275          things like `x=4 local x'. XXX - see above for temporary env
2276          variables with the same context level as variable_context */
2277       /* XXX - we should only do this if the variable is not an array. */
2278       if (was_tmpvar)
2279         var_setvalue (new_var, savestring (tmp_value));
2280
2281       new_var->attributes = exported_p (old_var) ? att_exported : 0;
2282     }
2283
2284   vc->flags |= VC_HASLOCAL;
2285
2286   new_var->context = variable_context;
2287   VSETATTR (new_var, att_local);
2288
2289   if (ifsname (name))
2290     setifs (new_var);
2291
2292   if (was_tmpvar == 0)
2293     VSETATTR (new_var, att_invisible);  /* XXX */
2294   return (new_var);
2295 }
2296
2297 /* Create a new shell variable with name NAME. */
2298 static SHELL_VAR *
2299 new_shell_variable (name)
2300      const char *name;
2301 {
2302   SHELL_VAR *entry;
2303
2304   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2305
2306   entry->name = savestring (name);
2307   var_setvalue (entry, (char *)NULL);
2308   CLEAR_EXPORTSTR (entry);
2309
2310   entry->dynamic_value = (sh_var_value_func_t *)NULL;
2311   entry->assign_func = (sh_var_assign_func_t *)NULL;
2312
2313   entry->attributes = 0;
2314
2315   /* Always assume variables are to be made at toplevel!
2316      make_local_variable has the responsibility of changing the
2317      variable context. */
2318   entry->context = 0;
2319
2320   return (entry);
2321 }
2322
2323 /* Create a new shell variable with name NAME and add it to the hash table
2324    TABLE. */
2325 static SHELL_VAR *
2326 make_new_variable (name, table)
2327      const char *name;
2328      HASH_TABLE *table;
2329 {
2330   SHELL_VAR *entry;
2331   BUCKET_CONTENTS *elt;
2332
2333   entry = new_shell_variable (name);
2334
2335   /* Make sure we have a shell_variables hash table to add to. */
2336   if (shell_variables == 0)
2337     create_variable_tables ();
2338
2339   elt = hash_insert (savestring (name), table, HASH_NOSRCH);
2340   elt->data = (PTR_T)entry;
2341
2342   return entry;
2343 }
2344
2345 #if defined (ARRAY_VARS)
2346 SHELL_VAR *
2347 make_new_array_variable (name)
2348      char *name;
2349 {
2350   SHELL_VAR *entry;
2351   ARRAY *array;
2352
2353   entry = make_new_variable (name, global_variables->table);
2354   array = array_create ();
2355
2356   var_setarray (entry, array);
2357   VSETATTR (entry, att_array);
2358   return entry;
2359 }
2360
2361 SHELL_VAR *
2362 make_local_array_variable (name, assoc_ok)
2363      char *name;
2364      int assoc_ok;
2365 {
2366   SHELL_VAR *var;
2367   ARRAY *array;
2368
2369   var = make_local_variable (name);
2370   if (var == 0 || array_p (var) || (assoc_ok && assoc_p (var)))
2371     return var;
2372
2373   array = array_create ();
2374
2375   dispose_variable_value (var);
2376   var_setarray (var, array);
2377   VSETATTR (var, att_array);
2378   return var;
2379 }
2380
2381 SHELL_VAR *
2382 make_new_assoc_variable (name)
2383      char *name;
2384 {
2385   SHELL_VAR *entry;
2386   HASH_TABLE *hash;
2387
2388   entry = make_new_variable (name, global_variables->table);
2389   hash = assoc_create (0);
2390
2391   var_setassoc (entry, hash);
2392   VSETATTR (entry, att_assoc);
2393   return entry;
2394 }
2395
2396 SHELL_VAR *
2397 make_local_assoc_variable (name)
2398      char *name;
2399 {
2400   SHELL_VAR *var;
2401   HASH_TABLE *hash;
2402
2403   var = make_local_variable (name);
2404   if (var == 0 || assoc_p (var))
2405     return var;
2406
2407   dispose_variable_value (var);
2408   hash = assoc_create (0);
2409
2410   var_setassoc (var, hash);
2411   VSETATTR (var, att_assoc);
2412   return var;
2413 }
2414 #endif
2415
2416 char *
2417 make_variable_value (var, value, flags)
2418      SHELL_VAR *var;
2419      char *value;
2420      int flags;
2421 {
2422   char *retval, *oval;
2423   intmax_t lval, rval;
2424   int expok, olen, op;
2425
2426   /* If this variable has had its type set to integer (via `declare -i'),
2427      then do expression evaluation on it and store the result.  The
2428      functions in expr.c (evalexp()) and bind_int_variable() are responsible
2429      for turning off the integer flag if they don't want further
2430      evaluation done. */
2431   if (integer_p (var))
2432     {
2433       if (flags & ASS_APPEND)
2434         {
2435           oval = value_cell (var);
2436           lval = evalexp (oval, &expok);        /* ksh93 seems to do this */
2437           if (expok == 0)
2438             {
2439               top_level_cleanup ();
2440               jump_to_top_level (DISCARD);
2441             }
2442         }
2443       rval = evalexp (value, &expok);
2444       if (expok == 0)
2445         {
2446           top_level_cleanup ();
2447           jump_to_top_level (DISCARD);
2448         }
2449       /* This can be fooled if the variable's value changes while evaluating
2450          `rval'.  We can change it if we move the evaluation of lval to here. */
2451       if (flags & ASS_APPEND)
2452         rval += lval;
2453       retval = itos (rval);
2454     }
2455 #if defined (CASEMOD_ATTRS)
2456   else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var))
2457     {
2458       if (flags & ASS_APPEND)
2459         {
2460           oval = get_variable_value (var);
2461           if (oval == 0)        /* paranoia */
2462             oval = "";
2463           olen = STRLEN (oval);
2464           retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2465           strcpy (retval, oval);
2466           if (value)
2467             strcpy (retval+olen, value);
2468         }
2469       else if (*value)
2470         retval = savestring (value);
2471       else
2472         {
2473           retval = (char *)xmalloc (1);
2474           retval[0] = '\0';
2475         }
2476       op = capcase_p (var) ? CASE_CAPITALIZE
2477                          : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER);
2478       oval = sh_modcase (retval, (char *)0, op);
2479       free (retval);
2480       retval = oval;
2481     }
2482 #endif /* CASEMOD_ATTRS */
2483   else if (value)
2484     {
2485       if (flags & ASS_APPEND)
2486         {
2487           oval = get_variable_value (var);
2488           if (oval == 0)        /* paranoia */
2489             oval = "";
2490           olen = STRLEN (oval);
2491           retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2492           strcpy (retval, oval);
2493           if (value)
2494             strcpy (retval+olen, value);
2495         }
2496       else if (*value)
2497         retval = savestring (value);
2498       else
2499         {
2500           retval = (char *)xmalloc (1);
2501           retval[0] = '\0';
2502         }
2503     }
2504   else
2505     retval = (char *)NULL;
2506
2507   return retval;
2508 }
2509
2510 /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
2511    temporary environment (but usually is not). */
2512 static SHELL_VAR *
2513 bind_variable_internal (name, value, table, hflags, aflags)
2514      const char *name;
2515      char *value;
2516      HASH_TABLE *table;
2517      int hflags, aflags;
2518 {
2519   char *newval;
2520   SHELL_VAR *entry;
2521
2522   entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
2523   /* Follow the nameref chain here if this is the global variables table */
2524   if (entry && nameref_p (entry) && (invisible_p (entry) == 0) && table == global_variables->table)
2525     {
2526       entry = find_global_variable (entry->name);
2527       /* Let's see if we have a nameref referencing a variable that hasn't yet
2528          been created. */
2529       if (entry == 0)
2530         entry = find_variable_last_nameref (name);      /* XXX */
2531       if (entry == 0)                                   /* just in case */
2532         return (entry);
2533     }
2534
2535   /* The first clause handles `declare -n ref; ref=x;' */
2536   if (entry && invisible_p (entry) && nameref_p (entry))
2537     goto assign_value;
2538   else if (entry && nameref_p (entry))
2539     {
2540       newval = nameref_cell (entry);
2541 #if defined (ARRAY_VARS)
2542       /* declare -n foo=x[2] */
2543       if (valid_array_reference (newval))
2544         /* XXX - should it be aflags? */
2545         entry = assign_array_element (newval, make_variable_value (entry, value, 0), aflags);
2546       else
2547 #endif
2548       {
2549       entry = make_new_variable (newval, table);
2550       var_setvalue (entry, make_variable_value (entry, value, 0));
2551       }
2552     }
2553   else if (entry == 0)
2554     {
2555       entry = make_new_variable (name, table);
2556       var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
2557     }
2558   else if (entry->assign_func)  /* array vars have assign functions now */
2559     {
2560       INVALIDATE_EXPORTSTR (entry);
2561       newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
2562       if (assoc_p (entry))
2563         entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0"));
2564       else if (array_p (entry))
2565         entry = (*(entry->assign_func)) (entry, newval, 0, 0);
2566       else
2567         entry = (*(entry->assign_func)) (entry, newval, -1, 0);
2568       if (newval != value)
2569         free (newval);
2570       return (entry);
2571     }
2572   else
2573     {
2574 assign_value:
2575       if (readonly_p (entry) || noassign_p (entry))
2576         {
2577           if (readonly_p (entry))
2578             err_readonly (name);
2579           return (entry);
2580         }
2581
2582       /* Variables which are bound are visible. */
2583       VUNSETATTR (entry, att_invisible);
2584
2585 #if defined (ARRAY_VARS)
2586       if (assoc_p (entry) || array_p (entry))
2587         newval = make_array_variable_value (entry, 0, "0", value, aflags);
2588       else
2589 #endif
2590
2591       newval = make_variable_value (entry, value, aflags);      /* XXX */
2592
2593       /* Invalidate any cached export string */
2594       INVALIDATE_EXPORTSTR (entry);
2595
2596 #if defined (ARRAY_VARS)
2597       /* XXX -- this bears looking at again -- XXX */
2598       /* If an existing array variable x is being assigned to with x=b or
2599          `read x' or something of that nature, silently convert it to
2600          x[0]=b or `read x[0]'. */
2601       if (assoc_p (entry))
2602         {
2603           assoc_insert (assoc_cell (entry), savestring ("0"), newval);
2604           free (newval);
2605         }
2606       else if (array_p (entry))
2607         {
2608           array_insert (array_cell (entry), 0, newval);
2609           free (newval);
2610         }
2611       else
2612 #endif
2613         {
2614           FREE (value_cell (entry));
2615           var_setvalue (entry, newval);
2616         }
2617     }
2618
2619   if (mark_modified_vars)
2620     VSETATTR (entry, att_exported);
2621
2622   if (exported_p (entry))
2623     array_needs_making = 1;
2624
2625   return (entry);
2626 }
2627         
2628 /* Bind a variable NAME to VALUE.  This conses up the name
2629    and value strings.  If we have a temporary environment, we bind there
2630    first, then we bind into shell_variables. */
2631
2632 SHELL_VAR *
2633 bind_variable (name, value, flags)
2634      const char *name;
2635      char *value;
2636      int flags;
2637 {
2638   SHELL_VAR *v, *nv;
2639   VAR_CONTEXT *vc, *nvc;
2640   int level;
2641
2642   if (shell_variables == 0)
2643     create_variable_tables ();
2644
2645   /* If we have a temporary environment, look there first for the variable,
2646      and, if found, modify the value there before modifying it in the
2647      shell_variables table.  This allows sourced scripts to modify values
2648      given to them in a temporary environment while modifying the variable
2649      value that the caller sees. */
2650   if (temporary_env)
2651     bind_tempenv_variable (name, value);
2652
2653   /* XXX -- handle local variables here. */
2654   for (vc = shell_variables; vc; vc = vc->down)
2655     {
2656       if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
2657         {
2658           v = hash_lookup (name, vc->table);
2659           nvc = vc;
2660           if (v && nameref_p (v))
2661             {
2662               nv = find_variable_nameref_context (v, vc, &nvc);
2663               if (nv == 0)
2664                 {
2665                   nv = find_variable_last_nameref_context (v, vc, &nvc);
2666                   if (nv && nameref_p (nv))
2667                     {
2668                       /* If this nameref variable doesn't have a value yet,
2669                          set the value.  Otherwise, assign using the value as
2670                          normal. */
2671                       if (nameref_cell (nv) == 0)
2672                         return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
2673                       return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
2674                     }
2675                   else
2676                     v = nv;
2677                 }
2678               else
2679                 v = nv;
2680             }
2681           if (v)
2682             return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
2683         }
2684     }
2685   /* bind_variable_internal will handle nameref resolution in this case */
2686   return (bind_variable_internal (name, value, global_variables->table, 0, flags));
2687 }
2688
2689 SHELL_VAR *
2690 bind_global_variable (name, value, flags)
2691      const char *name;
2692      char *value;
2693      int flags;
2694 {
2695   SHELL_VAR *v, *nv;
2696   VAR_CONTEXT *vc, *nvc;
2697   int level;
2698
2699   if (shell_variables == 0)
2700     create_variable_tables ();
2701
2702   /* bind_variable_internal will handle nameref resolution in this case */
2703   return (bind_variable_internal (name, value, global_variables->table, 0, flags));
2704 }
2705
2706 /* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
2707    value, variables are no longer invisible.  This is a duplicate of part
2708    of the internals of bind_variable.  If the variable is exported, or
2709    all modified variables should be exported, mark the variable for export
2710    and note that the export environment needs to be recreated. */
2711 SHELL_VAR *
2712 bind_variable_value (var, value, aflags)
2713      SHELL_VAR *var;
2714      char *value;
2715      int aflags;
2716 {
2717   char *t;
2718   int invis;
2719
2720   invis = invisible_p (var);
2721   VUNSETATTR (var, att_invisible);
2722
2723   if (var->assign_func)
2724     {
2725       /* If we're appending, we need the old value, so use
2726          make_variable_value */
2727       t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
2728       (*(var->assign_func)) (var, t, -1, 0);
2729       if (t != value && t)
2730         free (t);      
2731     }
2732   else
2733     {
2734       t = make_variable_value (var, value, aflags);
2735 #if defined (ARRAY_VARS)
2736       if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || (legal_identifier (t) == 0 && valid_array_reference (t) == 0)))
2737 #else
2738       if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || legal_identifier (t) == 0))
2739 #endif
2740         {
2741           free (t);
2742           if (invis)
2743             VSETATTR (var, att_invisible);      /* XXX */
2744           return ((SHELL_VAR *)NULL);
2745         }
2746       FREE (value_cell (var));
2747       var_setvalue (var, t);
2748     }
2749
2750   INVALIDATE_EXPORTSTR (var);
2751
2752   if (mark_modified_vars)
2753     VSETATTR (var, att_exported);
2754
2755   if (exported_p (var))
2756     array_needs_making = 1;
2757
2758   return (var);
2759 }
2760
2761 /* Bind/create a shell variable with the name LHS to the RHS.
2762    This creates or modifies a variable such that it is an integer.
2763
2764    This used to be in expr.c, but it is here so that all of the
2765    variable binding stuff is localized.  Since we don't want any
2766    recursive evaluation from bind_variable() (possible without this code,
2767    since bind_variable() calls the evaluator for variables with the integer
2768    attribute set), we temporarily turn off the integer attribute for each
2769    variable we set here, then turn it back on after binding as necessary. */
2770
2771 SHELL_VAR *
2772 bind_int_variable (lhs, rhs)
2773      char *lhs, *rhs;
2774 {
2775   register SHELL_VAR *v;
2776   int isint, isarr, implicitarray;
2777
2778   isint = isarr = implicitarray = 0;
2779 #if defined (ARRAY_VARS)
2780   if (valid_array_reference (lhs))
2781     {
2782       isarr = 1;
2783       v = array_variable_part (lhs, (char **)0, (int *)0);
2784     }
2785   else
2786 #endif
2787     v = find_variable (lhs);
2788
2789   if (v)
2790     {
2791       isint = integer_p (v);
2792       VUNSETATTR (v, att_integer);
2793 #if defined (ARRAY_VARS)
2794       if (array_p (v) && isarr == 0)
2795         implicitarray = 1;
2796 #endif
2797     }
2798
2799 #if defined (ARRAY_VARS)
2800   if (isarr)
2801     v = assign_array_element (lhs, rhs, 0);
2802   else if (implicitarray)
2803     v = bind_array_variable (lhs, 0, rhs, 0);
2804   else
2805 #endif
2806     v = bind_variable (lhs, rhs, 0);
2807
2808   if (v && isint)
2809     VSETATTR (v, att_integer);
2810
2811   VUNSETATTR (v, att_invisible);
2812
2813   return (v);
2814 }
2815
2816 SHELL_VAR *
2817 bind_var_to_int (var, val)
2818      char *var;
2819      intmax_t val;
2820 {
2821   char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
2822
2823   p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
2824   return (bind_int_variable (var, p));
2825 }
2826
2827 /* Do a function binding to a variable.  You pass the name and
2828    the command to bind to.  This conses the name and command. */
2829 SHELL_VAR *
2830 bind_function (name, value)
2831      const char *name;
2832      COMMAND *value;
2833 {
2834   SHELL_VAR *entry;
2835
2836   entry = find_function (name);
2837   if (entry == 0)
2838     {
2839       BUCKET_CONTENTS *elt;
2840
2841       elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2842       entry = new_shell_variable (name);
2843       elt->data = (PTR_T)entry;
2844     }
2845   else
2846     INVALIDATE_EXPORTSTR (entry);
2847
2848   if (var_isset (entry))
2849     dispose_command (function_cell (entry));
2850
2851   if (value)
2852     var_setfunc (entry, copy_command (value));
2853   else
2854     var_setfunc (entry, 0);
2855
2856   VSETATTR (entry, att_function);
2857
2858   if (mark_modified_vars)
2859     VSETATTR (entry, att_exported);
2860
2861   VUNSETATTR (entry, att_invisible);            /* Just to be sure */
2862
2863   if (exported_p (entry))
2864     array_needs_making = 1;
2865
2866 #if defined (PROGRAMMABLE_COMPLETION)
2867   set_itemlist_dirty (&it_functions);
2868 #endif
2869
2870   return (entry);
2871 }
2872
2873 #if defined (DEBUGGER)
2874 /* Bind a function definition, which includes source file and line number
2875    information in addition to the command, into the FUNCTION_DEF hash table.*/
2876 void
2877 bind_function_def (name, value)
2878      const char *name;
2879      FUNCTION_DEF *value;
2880 {
2881   FUNCTION_DEF *entry;
2882   BUCKET_CONTENTS *elt;
2883   COMMAND *cmd;
2884
2885   entry = find_function_def (name);
2886   if (entry)
2887     {
2888       dispose_function_def_contents (entry);
2889       entry = copy_function_def_contents (value, entry);
2890     }
2891   else
2892     {
2893       cmd = value->command;
2894       value->command = 0;
2895       entry = copy_function_def (value);
2896       value->command = cmd;
2897
2898       elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2899       elt->data = (PTR_T *)entry;
2900     }
2901 }
2902 #endif /* DEBUGGER */
2903
2904 /* Add STRING, which is of the form foo=bar, to the temporary environment
2905    HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
2906    responsible for moving the main temporary env to one of the other
2907    temporary environments.  The expansion code in subst.c calls this. */
2908 int
2909 assign_in_env (word, flags)
2910      WORD_DESC *word;
2911      int flags;
2912 {
2913   int offset, aflags;
2914   char *name, *temp, *value;
2915   SHELL_VAR *var;
2916   const char *string;
2917
2918   string = word->word;
2919
2920   aflags = 0;
2921   offset = assignment (string, 0);
2922   name = savestring (string);
2923   value = (char *)NULL;
2924
2925   if (name[offset] == '=')
2926     {
2927       name[offset] = 0;
2928
2929       /* don't ignore the `+' when assigning temporary environment */
2930       if (name[offset - 1] == '+')
2931         {
2932           name[offset - 1] = '\0';
2933           aflags |= ASS_APPEND;
2934         }
2935
2936       var = find_variable (name);
2937       if (var && (readonly_p (var) || noassign_p (var)))
2938         {
2939           if (readonly_p (var))
2940             err_readonly (name);
2941           free (name);
2942           return (0);
2943         }
2944
2945       temp = name + offset + 1;
2946       value = expand_assignment_string_to_string (temp, 0);
2947
2948       if (var && (aflags & ASS_APPEND))
2949         {
2950           temp = make_variable_value (var, value, aflags);
2951           FREE (value);
2952           value = temp;
2953         }
2954     }
2955
2956   if (temporary_env == 0)
2957     temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2958
2959   var = hash_lookup (name, temporary_env);
2960   if (var == 0)
2961     var = make_new_variable (name, temporary_env);
2962   else
2963     FREE (value_cell (var));
2964
2965   if (value == 0)
2966     {
2967       value = (char *)xmalloc (1);      /* like do_assignment_internal */
2968       value[0] = '\0';
2969     }
2970
2971   var_setvalue (var, value);
2972   var->attributes |= (att_exported|att_tempvar);
2973   var->context = variable_context;      /* XXX */
2974
2975   INVALIDATE_EXPORTSTR (var);
2976   var->exportstr = mk_env_string (name, value, 0);
2977
2978   array_needs_making = 1;
2979
2980   if (flags)
2981     stupidly_hack_special_variables (name);
2982
2983   if (echo_command_at_execute)
2984     /* The Korn shell prints the `+ ' in front of assignment statements,
2985         so we do too. */
2986     xtrace_print_assignment (name, value, 0, 1);
2987
2988   free (name);
2989   return 1;
2990 }
2991
2992 /* **************************************************************** */
2993 /*                                                                  */
2994 /*                      Copying variables                           */
2995 /*                                                                  */
2996 /* **************************************************************** */
2997
2998 #ifdef INCLUDE_UNUSED
2999 /* Copy VAR to a new data structure and return that structure. */
3000 SHELL_VAR *
3001 copy_variable (var)
3002      SHELL_VAR *var;
3003 {
3004   SHELL_VAR *copy = (SHELL_VAR *)NULL;
3005
3006   if (var)
3007     {
3008       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
3009
3010       copy->attributes = var->attributes;
3011       copy->name = savestring (var->name);
3012
3013       if (function_p (var))
3014         var_setfunc (copy, copy_command (function_cell (var)));
3015 #if defined (ARRAY_VARS)
3016       else if (array_p (var))
3017         var_setarray (copy, array_copy (array_cell (var)));
3018       else if (assoc_p (var))
3019         var_setassoc (copy, assoc_copy (assoc_cell (var)));
3020 #endif
3021       else if (nameref_cell (var))      /* XXX - nameref */
3022         var_setref (copy, savestring (nameref_cell (var)));
3023       else if (value_cell (var))        /* XXX - nameref */
3024         var_setvalue (copy, savestring (value_cell (var)));
3025       else
3026         var_setvalue (copy, (char *)NULL);
3027
3028       copy->dynamic_value = var->dynamic_value;
3029       copy->assign_func = var->assign_func;
3030
3031       copy->exportstr = COPY_EXPORTSTR (var);
3032
3033       copy->context = var->context;
3034     }
3035   return (copy);
3036 }
3037 #endif
3038
3039 /* **************************************************************** */
3040 /*                                                                  */
3041 /*                Deleting and unsetting variables                  */
3042 /*                                                                  */
3043 /* **************************************************************** */
3044
3045 /* Dispose of the information attached to VAR. */
3046 static void
3047 dispose_variable_value (var)
3048      SHELL_VAR *var;
3049 {
3050   if (function_p (var))
3051     dispose_command (function_cell (var));
3052 #if defined (ARRAY_VARS)
3053   else if (array_p (var))
3054     array_dispose (array_cell (var));
3055   else if (assoc_p (var))
3056     assoc_dispose (assoc_cell (var));
3057 #endif
3058   else if (nameref_p (var))
3059     FREE (nameref_cell (var));
3060   else
3061     FREE (value_cell (var));
3062 }
3063
3064 void
3065 dispose_variable (var)
3066      SHELL_VAR *var;
3067 {
3068   if (var == 0)
3069     return;
3070
3071   if (nofree_p (var) == 0)
3072     dispose_variable_value (var);
3073
3074   FREE_EXPORTSTR (var);
3075
3076   free (var->name);
3077
3078   if (exported_p (var))
3079     array_needs_making = 1;
3080
3081   free (var);
3082 }
3083
3084 /* Unset the shell variable referenced by NAME.  Unsetting a nameref variable
3085    unsets the variable it resolves to but leaves the nameref alone. */
3086 int
3087 unbind_variable (name)
3088      const char *name;
3089 {
3090   SHELL_VAR *v, *nv;
3091   int r;
3092
3093   v = var_lookup (name, shell_variables);
3094   nv = (v && nameref_p (v)) ? find_variable_nameref (v) : (SHELL_VAR *)NULL;
3095
3096   r = nv ? makunbound (nv->name, shell_variables) : makunbound (name, shell_variables);
3097   return r;
3098 }
3099
3100 /* Unbind NAME, where NAME is assumed to be a nameref variable */
3101 int
3102 unbind_nameref (name)
3103      const char *name;
3104 {
3105   SHELL_VAR *v;
3106
3107   v = var_lookup (name, shell_variables);
3108   if (v && nameref_p (v))
3109     return makunbound (name, shell_variables);
3110   return 0;
3111 }
3112
3113 /* Unset the shell function named NAME. */
3114 int
3115 unbind_func (name)
3116      const char *name;
3117 {
3118   BUCKET_CONTENTS *elt;
3119   SHELL_VAR *func;
3120
3121   elt = hash_remove (name, shell_functions, 0);
3122
3123   if (elt == 0)
3124     return -1;
3125
3126 #if defined (PROGRAMMABLE_COMPLETION)
3127   set_itemlist_dirty (&it_functions);
3128 #endif
3129
3130   func = (SHELL_VAR *)elt->data;
3131   if (func)
3132     {
3133       if (exported_p (func))
3134         array_needs_making++;
3135       dispose_variable (func);
3136     }
3137
3138   free (elt->key);
3139   free (elt);
3140
3141   return 0;  
3142 }
3143
3144 #if defined (DEBUGGER)
3145 int
3146 unbind_function_def (name)
3147      const char *name;
3148 {
3149   BUCKET_CONTENTS *elt;
3150   FUNCTION_DEF *funcdef;
3151
3152   elt = hash_remove (name, shell_function_defs, 0);
3153
3154   if (elt == 0)
3155     return -1;
3156
3157   funcdef = (FUNCTION_DEF *)elt->data;
3158   if (funcdef)
3159     dispose_function_def (funcdef);
3160
3161   free (elt->key);
3162   free (elt);
3163
3164   return 0;  
3165 }
3166 #endif /* DEBUGGER */
3167
3168 int
3169 delete_var (name, vc)
3170      const char *name;
3171      VAR_CONTEXT *vc;
3172 {
3173   BUCKET_CONTENTS *elt;
3174   SHELL_VAR *old_var;
3175   VAR_CONTEXT *v;
3176
3177   for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
3178     if (elt = hash_remove (name, v->table, 0))
3179       break;
3180
3181   if (elt == 0)
3182     return (-1);
3183
3184   old_var = (SHELL_VAR *)elt->data;
3185   free (elt->key);
3186   free (elt);
3187
3188   dispose_variable (old_var);
3189   return (0);
3190 }
3191
3192 /* Make the variable associated with NAME go away.  HASH_LIST is the
3193    hash table from which this variable should be deleted (either
3194    shell_variables or shell_functions).
3195    Returns non-zero if the variable couldn't be found. */
3196 int
3197 makunbound (name, vc)
3198      const char *name;
3199      VAR_CONTEXT *vc;
3200 {
3201   BUCKET_CONTENTS *elt, *new_elt;
3202   SHELL_VAR *old_var;
3203   VAR_CONTEXT *v;
3204   char *t;
3205
3206   for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
3207     if (elt = hash_remove (name, v->table, 0))
3208       break;
3209
3210   if (elt == 0)
3211     return (-1);
3212
3213   old_var = (SHELL_VAR *)elt->data;
3214
3215   if (old_var && exported_p (old_var))
3216     array_needs_making++;
3217
3218   /* If we're unsetting a local variable and we're still executing inside
3219      the function, just mark the variable as invisible.  The function
3220      eventually called by pop_var_context() will clean it up later.  This
3221      must be done so that if the variable is subsequently assigned a new
3222      value inside the function, the `local' attribute is still present.
3223      We also need to add it back into the correct hash table. */
3224   if (old_var && local_p (old_var) && variable_context == old_var->context)
3225     {
3226       if (nofree_p (old_var))
3227         var_setvalue (old_var, (char *)NULL);
3228 #if defined (ARRAY_VARS)
3229       else if (array_p (old_var))
3230         array_dispose (array_cell (old_var));
3231       else if (assoc_p (old_var))
3232         assoc_dispose (assoc_cell (old_var));
3233 #endif
3234       else if (nameref_p (old_var))
3235         FREE (nameref_cell (old_var));
3236       else
3237         FREE (value_cell (old_var));
3238       /* Reset the attributes.  Preserve the export attribute if the variable
3239          came from a temporary environment.  Make sure it stays local, and
3240          make it invisible. */ 
3241       old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
3242       VSETATTR (old_var, att_local);
3243       VSETATTR (old_var, att_invisible);
3244       var_setvalue (old_var, (char *)NULL);
3245       INVALIDATE_EXPORTSTR (old_var);
3246
3247       new_elt = hash_insert (savestring (old_var->name), v->table, 0);
3248       new_elt->data = (PTR_T)old_var;
3249       stupidly_hack_special_variables (old_var->name);
3250
3251       free (elt->key);
3252       free (elt);
3253       return (0);
3254     }
3255
3256   /* Have to save a copy of name here, because it might refer to
3257      old_var->name.  If so, stupidly_hack_special_variables will
3258      reference freed memory. */
3259   t = savestring (name);
3260
3261   free (elt->key);
3262   free (elt);
3263
3264   dispose_variable (old_var);
3265   stupidly_hack_special_variables (t);
3266   free (t);
3267
3268   return (0);
3269 }
3270
3271 /* Get rid of all of the variables in the current context. */
3272 void
3273 kill_all_local_variables ()
3274 {
3275   VAR_CONTEXT *vc;
3276
3277   for (vc = shell_variables; vc; vc = vc->down)
3278     if (vc_isfuncenv (vc) && vc->scope == variable_context)
3279       break;
3280   if (vc == 0)
3281     return;             /* XXX */
3282
3283   if (vc->table && vc_haslocals (vc))
3284     {
3285       delete_all_variables (vc->table);
3286       hash_dispose (vc->table);
3287     }
3288   vc->table = (HASH_TABLE *)NULL;
3289 }
3290
3291 static void
3292 free_variable_hash_data (data)
3293      PTR_T data;
3294 {
3295   SHELL_VAR *var;
3296
3297   var = (SHELL_VAR *)data;
3298   dispose_variable (var);
3299 }
3300
3301 /* Delete the entire contents of the hash table. */
3302 void
3303 delete_all_variables (hashed_vars)
3304      HASH_TABLE *hashed_vars;
3305 {
3306   hash_flush (hashed_vars, free_variable_hash_data);
3307 }
3308
3309 /* **************************************************************** */
3310 /*                                                                  */
3311 /*                   Setting variable attributes                    */
3312 /*                                                                  */
3313 /* **************************************************************** */
3314
3315 #define FIND_OR_MAKE_VARIABLE(name, entry) \
3316   do \
3317     { \
3318       entry = find_variable (name); \
3319       if (!entry) \
3320         { \
3321           entry = bind_variable (name, "", 0); \
3322           if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \
3323         } \
3324     } \
3325   while (0)
3326
3327 /* Make the variable associated with NAME be readonly.
3328    If NAME does not exist yet, create it. */
3329 void
3330 set_var_read_only (name)
3331      char *name;
3332 {
3333   SHELL_VAR *entry;
3334
3335   FIND_OR_MAKE_VARIABLE (name, entry);
3336   VSETATTR (entry, att_readonly);
3337 }
3338
3339 #ifdef INCLUDE_UNUSED
3340 /* Make the function associated with NAME be readonly.
3341    If NAME does not exist, we just punt, like auto_export code below. */
3342 void
3343 set_func_read_only (name)
3344      const char *name;
3345 {
3346   SHELL_VAR *entry;
3347
3348   entry = find_function (name);
3349   if (entry)
3350     VSETATTR (entry, att_readonly);
3351 }
3352
3353 /* Make the variable associated with NAME be auto-exported.
3354    If NAME does not exist yet, create it. */
3355 void
3356 set_var_auto_export (name)
3357      char *name;
3358 {
3359   SHELL_VAR *entry;
3360
3361   FIND_OR_MAKE_VARIABLE (name, entry);
3362   set_auto_export (entry);
3363 }
3364
3365 /* Make the function associated with NAME be auto-exported. */
3366 void
3367 set_func_auto_export (name)
3368      const char *name;
3369 {
3370   SHELL_VAR *entry;
3371
3372   entry = find_function (name);
3373   if (entry)
3374     set_auto_export (entry);
3375 }
3376 #endif
3377
3378 /* **************************************************************** */
3379 /*                                                                  */
3380 /*                   Creating lists of variables                    */
3381 /*                                                                  */
3382 /* **************************************************************** */
3383
3384 static VARLIST *
3385 vlist_alloc (nentries)
3386      int nentries;
3387 {
3388   VARLIST  *vlist;
3389
3390   vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
3391   vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
3392   vlist->list_size = nentries;
3393   vlist->list_len = 0;
3394   vlist->list[0] = (SHELL_VAR *)NULL;
3395
3396   return vlist;
3397 }
3398
3399 static VARLIST *
3400 vlist_realloc (vlist, n)
3401      VARLIST *vlist;
3402      int n;
3403 {
3404   if (vlist == 0)
3405     return (vlist = vlist_alloc (n));
3406   if (n > vlist->list_size)
3407     {
3408       vlist->list_size = n;
3409       vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
3410     }
3411   return vlist;
3412 }
3413
3414 static void
3415 vlist_add (vlist, var, flags)
3416      VARLIST *vlist;
3417      SHELL_VAR *var;
3418      int flags;
3419 {
3420   register int i;
3421
3422   for (i = 0; i < vlist->list_len; i++)
3423     if (STREQ (var->name, vlist->list[i]->name))
3424       break;
3425   if (i < vlist->list_len)
3426     return;
3427
3428   if (i >= vlist->list_size)
3429     vlist = vlist_realloc (vlist, vlist->list_size + 16);
3430
3431   vlist->list[vlist->list_len++] = var;
3432   vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
3433 }
3434
3435 /* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
3436    variables for which FUNCTION returns a non-zero value.  A NULL value
3437    for FUNCTION means to use all variables. */
3438 SHELL_VAR **
3439 map_over (function, vc)
3440      sh_var_map_func_t *function;
3441      VAR_CONTEXT *vc;
3442 {
3443   VAR_CONTEXT *v;
3444   VARLIST *vlist;
3445   SHELL_VAR **ret;
3446   int nentries;
3447
3448   for (nentries = 0, v = vc; v; v = v->down)
3449     nentries += HASH_ENTRIES (v->table);
3450
3451   if (nentries == 0)
3452     return (SHELL_VAR **)NULL;
3453
3454   vlist = vlist_alloc (nentries);
3455
3456   for (v = vc; v; v = v->down)
3457     flatten (v->table, function, vlist, 0);
3458
3459   ret = vlist->list;
3460   free (vlist);
3461   return ret;
3462 }
3463
3464 SHELL_VAR **
3465 map_over_funcs (function)
3466      sh_var_map_func_t *function;
3467 {
3468   VARLIST *vlist;
3469   SHELL_VAR **ret;
3470
3471   if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
3472     return ((SHELL_VAR **)NULL);
3473
3474   vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
3475
3476   flatten (shell_functions, function, vlist, 0);
3477
3478   ret = vlist->list;
3479   free (vlist);
3480   return ret;
3481 }
3482
3483 /* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
3484    elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved
3485    for future use.  Only unique names are added to VLIST.  If FUNC is
3486    NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is
3487    NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST
3488    and FUNC are both NULL, nothing happens. */
3489 static void
3490 flatten (var_hash_table, func, vlist, flags)
3491      HASH_TABLE *var_hash_table;
3492      sh_var_map_func_t *func;
3493      VARLIST *vlist;
3494      int flags;
3495 {
3496   register int i;
3497   register BUCKET_CONTENTS *tlist;
3498   int r;
3499   SHELL_VAR *var;
3500
3501   if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
3502     return;
3503
3504   for (i = 0; i < var_hash_table->nbuckets; i++)
3505     {
3506       for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
3507         {
3508           var = (SHELL_VAR *)tlist->data;
3509
3510           r = func ? (*func) (var) : 1;
3511           if (r && vlist)
3512             vlist_add (vlist, var, flags);
3513         }
3514     }
3515 }
3516
3517 void
3518 sort_variables (array)
3519      SHELL_VAR **array;
3520 {
3521   qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
3522 }
3523
3524 static int
3525 qsort_var_comp (var1, var2)
3526      SHELL_VAR **var1, **var2;
3527 {
3528   int result;
3529
3530   if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
3531     result = strcmp ((*var1)->name, (*var2)->name);
3532
3533   return (result);
3534 }
3535
3536 /* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
3537    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
3538 static SHELL_VAR **
3539 vapply (func)
3540      sh_var_map_func_t *func;
3541 {
3542   SHELL_VAR **list;
3543
3544   list = map_over (func, shell_variables);
3545   if (list /* && posixly_correct */)
3546     sort_variables (list);
3547   return (list);
3548 }
3549
3550 /* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
3551    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
3552 static SHELL_VAR **
3553 fapply (func)
3554      sh_var_map_func_t *func;
3555 {
3556   SHELL_VAR **list;
3557
3558   list = map_over_funcs (func);
3559   if (list /* && posixly_correct */)
3560     sort_variables (list);
3561   return (list);
3562 }
3563
3564 /* Create a NULL terminated array of all the shell variables. */
3565 SHELL_VAR **
3566 all_shell_variables ()
3567 {
3568   return (vapply ((sh_var_map_func_t *)NULL));
3569 }
3570
3571 /* Create a NULL terminated array of all the shell functions. */
3572 SHELL_VAR **
3573 all_shell_functions ()
3574 {
3575   return (fapply ((sh_var_map_func_t *)NULL));
3576 }
3577
3578 static int
3579 visible_var (var)
3580      SHELL_VAR *var;
3581 {
3582   return (invisible_p (var) == 0);
3583 }
3584
3585 SHELL_VAR **
3586 all_visible_functions ()
3587 {
3588   return (fapply (visible_var));
3589 }
3590
3591 SHELL_VAR **
3592 all_visible_variables ()
3593 {
3594   return (vapply (visible_var));
3595 }
3596
3597 /* Return non-zero if the variable VAR is visible and exported.  Array
3598    variables cannot be exported. */
3599 static int
3600 visible_and_exported (var)
3601      SHELL_VAR *var;
3602 {
3603   return (invisible_p (var) == 0 && exported_p (var));
3604 }
3605
3606 /* Candidate variables for the export environment are either valid variables
3607    with the export attribute or invalid variables inherited from the initial
3608    environment and simply passed through. */
3609 static int
3610 export_environment_candidate (var)
3611      SHELL_VAR *var;
3612 {
3613   return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
3614 }
3615
3616 /* Return non-zero if VAR is a local variable in the current context and
3617    is exported. */
3618 static int
3619 local_and_exported (var)
3620      SHELL_VAR *var;
3621 {
3622   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
3623 }
3624
3625 SHELL_VAR **
3626 all_exported_variables ()
3627 {
3628   return (vapply (visible_and_exported));
3629 }
3630
3631 SHELL_VAR **
3632 local_exported_variables ()
3633 {
3634   return (vapply (local_and_exported));
3635 }
3636
3637 static int
3638 variable_in_context (var)
3639      SHELL_VAR *var;
3640 {
3641   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
3642 }
3643
3644 SHELL_VAR **
3645 all_local_variables ()
3646 {
3647   VARLIST *vlist;
3648   SHELL_VAR **ret;
3649   VAR_CONTEXT *vc;
3650
3651   vc = shell_variables;
3652   for (vc = shell_variables; vc; vc = vc->down)
3653     if (vc_isfuncenv (vc) && vc->scope == variable_context)
3654       break;
3655
3656   if (vc == 0)
3657     {
3658       internal_error (_("all_local_variables: no function context at current scope"));
3659       return (SHELL_VAR **)NULL;
3660     }
3661   if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
3662     return (SHELL_VAR **)NULL;
3663     
3664   vlist = vlist_alloc (HASH_ENTRIES (vc->table));
3665
3666   flatten (vc->table, variable_in_context, vlist, 0);
3667
3668   ret = vlist->list;
3669   free (vlist);
3670   if (ret)
3671     sort_variables (ret);
3672   return ret;
3673 }
3674
3675 #if defined (ARRAY_VARS)
3676 /* Return non-zero if the variable VAR is visible and an array. */
3677 static int
3678 visible_array_vars (var)
3679      SHELL_VAR *var;
3680 {
3681   return (invisible_p (var) == 0 && array_p (var));
3682 }
3683
3684 SHELL_VAR **
3685 all_array_variables ()
3686 {
3687   return (vapply (visible_array_vars));
3688 }
3689 #endif /* ARRAY_VARS */
3690
3691 char **
3692 all_variables_matching_prefix (prefix)
3693      const char *prefix;
3694 {
3695   SHELL_VAR **varlist;
3696   char **rlist;
3697   int vind, rind, plen;
3698
3699   plen = STRLEN (prefix);
3700   varlist = all_visible_variables ();
3701   for (vind = 0; varlist && varlist[vind]; vind++)
3702     ;
3703   if (varlist == 0 || vind == 0)
3704     return ((char **)NULL);
3705   rlist = strvec_create (vind + 1);
3706   for (vind = rind = 0; varlist[vind]; vind++)
3707     {
3708       if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
3709         rlist[rind++] = savestring (varlist[vind]->name);
3710     }
3711   rlist[rind] = (char *)0;
3712   free (varlist);
3713
3714   return rlist;
3715 }
3716
3717 /* **************************************************************** */
3718 /*                                                                  */
3719 /*               Managing temporary variable scopes                 */
3720 /*                                                                  */
3721 /* **************************************************************** */
3722
3723 /* Make variable NAME have VALUE in the temporary environment. */
3724 static SHELL_VAR *
3725 bind_tempenv_variable (name, value)
3726      const char *name;
3727      char *value;
3728 {
3729   SHELL_VAR *var;
3730
3731   var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
3732
3733   if (var)
3734     {
3735       FREE (value_cell (var));
3736       var_setvalue (var, savestring (value));
3737       INVALIDATE_EXPORTSTR (var);
3738     }
3739
3740   return (var);
3741 }
3742
3743 /* Find a variable in the temporary environment that is named NAME.
3744    Return the SHELL_VAR *, or NULL if not found. */
3745 SHELL_VAR *
3746 find_tempenv_variable (name)
3747      const char *name;
3748 {
3749   return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
3750 }
3751
3752 char **tempvar_list;
3753 int tvlist_ind;
3754
3755 /* Push the variable described by (SHELL_VAR *)DATA down to the next
3756    variable context from the temporary environment. */
3757 static void
3758 push_temp_var (data)
3759      PTR_T data;
3760 {
3761   SHELL_VAR *var, *v;
3762   HASH_TABLE *binding_table;
3763
3764   var = (SHELL_VAR *)data;
3765
3766   binding_table = shell_variables->table;
3767   if (binding_table == 0)
3768     {
3769       if (shell_variables == global_variables)
3770         /* shouldn't happen */
3771         binding_table = shell_variables->table = global_variables->table = hash_create (0);
3772       else
3773         binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
3774     }
3775
3776   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
3777
3778   /* XXX - should we set the context here?  It shouldn't matter because of how
3779      assign_in_env works, but might want to check. */
3780   if (binding_table == global_variables->table)         /* XXX */
3781     var->attributes &= ~(att_tempvar|att_propagate);
3782   else
3783     {
3784       var->attributes |= att_propagate;
3785       if  (binding_table == shell_variables->table)
3786         shell_variables->flags |= VC_HASTMPVAR;
3787     }
3788   v->attributes |= var->attributes;
3789
3790   if (find_special_var (var->name) >= 0)
3791     tempvar_list[tvlist_ind++] = savestring (var->name);
3792
3793   dispose_variable (var);
3794 }
3795
3796 static void
3797 propagate_temp_var (data)
3798      PTR_T data;
3799 {
3800   SHELL_VAR *var;
3801
3802   var = (SHELL_VAR *)data;
3803   if (tempvar_p (var) && (var->attributes & att_propagate))
3804     push_temp_var (data);
3805   else
3806     {
3807       if (find_special_var (var->name) >= 0)
3808         tempvar_list[tvlist_ind++] = savestring (var->name);
3809       dispose_variable (var);
3810     }
3811 }
3812
3813 /* Free the storage used in the hash table for temporary
3814    environment variables.  PUSHF is a function to be called
3815    to free each hash table entry.  It takes care of pushing variables
3816    to previous scopes if appropriate.  PUSHF stores names of variables
3817    that require special handling (e.g., IFS) on tempvar_list, so this
3818    function can call stupidly_hack_special_variables on all the
3819    variables in the list when the temporary hash table is destroyed. */
3820 static void
3821 dispose_temporary_env (pushf)
3822      sh_free_func_t *pushf;
3823 {
3824   int i;
3825
3826   tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
3827   tempvar_list[tvlist_ind = 0] = 0;
3828     
3829   hash_flush (temporary_env, pushf);
3830   hash_dispose (temporary_env);
3831   temporary_env = (HASH_TABLE *)NULL;
3832
3833   tempvar_list[tvlist_ind] = 0;
3834
3835   array_needs_making = 1;
3836
3837 #if 0
3838   sv_ifs ("IFS");               /* XXX here for now -- check setifs in assign_in_env */  
3839 #endif
3840   for (i = 0; i < tvlist_ind; i++)
3841     stupidly_hack_special_variables (tempvar_list[i]);
3842
3843   strvec_dispose (tempvar_list);
3844   tempvar_list = 0;
3845   tvlist_ind = 0;
3846 }
3847
3848 void
3849 dispose_used_env_vars ()
3850 {
3851   if (temporary_env)
3852     {
3853       dispose_temporary_env (propagate_temp_var);
3854       maybe_make_export_env ();
3855     }
3856 }
3857
3858 /* Take all of the shell variables in the temporary environment HASH_TABLE
3859    and make shell variables from them at the current variable context. */
3860 void
3861 merge_temporary_env ()
3862 {
3863   if (temporary_env)
3864     dispose_temporary_env (push_temp_var);
3865 }
3866
3867 /* **************************************************************** */
3868 /*                                                                  */
3869 /*           Creating and manipulating the environment              */
3870 /*                                                                  */
3871 /* **************************************************************** */
3872
3873 static inline char *
3874 mk_env_string (name, value, isfunc)
3875      const char *name, *value;
3876      int isfunc;
3877 {
3878   size_t name_len, value_len;
3879   char  *p, *q;
3880
3881   name_len = strlen (name);
3882   value_len = STRLEN (value);
3883
3884   /* If we are exporting a shell function, construct the encoded function
3885      name. */
3886   if (isfunc && value)
3887     {
3888       p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2);
3889       q = p;
3890       memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN);
3891       q += BASHFUNC_PREFLEN;
3892       memcpy (q, name, name_len);
3893       q += name_len;
3894       memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN);
3895       q += BASHFUNC_SUFFLEN;
3896     }
3897   else
3898     {
3899       p = (char *)xmalloc (2 + name_len + value_len);
3900       memcpy (p, name, name_len);
3901       q = p + name_len;
3902     }
3903
3904   q[0] = '=';
3905   if (value && *value)
3906     memcpy (q + 1, value, value_len + 1);
3907   else
3908     q[1] = '\0';
3909
3910   return (p);
3911 }
3912
3913 #ifdef DEBUG
3914 /* Debugging */
3915 static int
3916 valid_exportstr (v)
3917      SHELL_VAR *v;
3918 {
3919   char *s;
3920
3921   s = v->exportstr;
3922   if (s == 0)
3923     {
3924       internal_error (_("%s has null exportstr"), v->name);
3925       return (0);
3926     }
3927   if (legal_variable_starter ((unsigned char)*s) == 0)
3928     {
3929       internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3930       return (0);
3931     }
3932   for (s = v->exportstr + 1; s && *s; s++)
3933     {
3934       if (*s == '=')
3935         break;
3936       if (legal_variable_char ((unsigned char)*s) == 0)
3937         {
3938           internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3939           return (0);
3940         }
3941     }
3942   if (*s != '=')
3943     {
3944       internal_error (_("no `=' in exportstr for %s"), v->name);
3945       return (0);
3946     }
3947   return (1);
3948 }
3949 #endif
3950
3951 static char **
3952 make_env_array_from_var_list (vars)
3953      SHELL_VAR **vars;
3954 {
3955   register int i, list_index;
3956   register SHELL_VAR *var;
3957   char **list, *value;
3958
3959   list = strvec_create ((1 + strvec_len ((char **)vars)));
3960
3961 #define USE_EXPORTSTR (value == var->exportstr)
3962
3963   for (i = 0, list_index = 0; var = vars[i]; i++)
3964     {
3965 #if defined (__CYGWIN__)
3966       /* We don't use the exportstr stuff on Cygwin at all. */
3967       INVALIDATE_EXPORTSTR (var);
3968 #endif
3969       if (var->exportstr)
3970         value = var->exportstr;
3971       else if (function_p (var))
3972         value = named_function_string ((char *)NULL, function_cell (var), 0);
3973 #if defined (ARRAY_VARS)
3974       else if (array_p (var))
3975 #  if ARRAY_EXPORT
3976         value = array_to_assignment_string (array_cell (var));
3977 #  else
3978         continue;       /* XXX array vars cannot yet be exported */
3979 #  endif /* ARRAY_EXPORT */
3980       else if (assoc_p (var))
3981 #  if 0
3982         value = assoc_to_assignment_string (assoc_cell (var));
3983 #  else
3984         continue;       /* XXX associative array vars cannot yet be exported */
3985 #  endif
3986 #endif
3987       else
3988         value = value_cell (var);
3989
3990       if (value)
3991         {
3992           /* Gee, I'd like to get away with not using savestring() if we're
3993              using the cached exportstr... */
3994           list[list_index] = USE_EXPORTSTR ? savestring (value)
3995                                            : mk_env_string (var->name, value, function_p (var));
3996
3997           if (USE_EXPORTSTR == 0)
3998             SAVE_EXPORTSTR (var, list[list_index]);
3999
4000           list_index++;
4001 #undef USE_EXPORTSTR
4002
4003 #if 0   /* not yet */
4004 #if defined (ARRAY_VARS)
4005           if (array_p (var) || assoc_p (var))
4006             free (value);
4007 #endif
4008 #endif
4009         }
4010     }
4011
4012   list[list_index] = (char *)NULL;
4013   return (list);
4014 }
4015
4016 /* Make an array of assignment statements from the hash table
4017    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
4018    variables are eligible. */
4019 static char **
4020 make_var_export_array (vcxt)
4021      VAR_CONTEXT *vcxt;
4022 {
4023   char **list;
4024   SHELL_VAR **vars;
4025
4026 #if 0
4027   vars = map_over (visible_and_exported, vcxt);
4028 #else
4029   vars = map_over (export_environment_candidate, vcxt);
4030 #endif
4031
4032   if (vars == 0)
4033     return (char **)NULL;
4034
4035   list = make_env_array_from_var_list (vars);
4036
4037   free (vars);
4038   return (list);
4039 }
4040
4041 static char **
4042 make_func_export_array ()
4043 {
4044   char **list;
4045   SHELL_VAR **vars;
4046
4047   vars = map_over_funcs (visible_and_exported);
4048   if (vars == 0)
4049     return (char **)NULL;
4050
4051   list = make_env_array_from_var_list (vars);
4052
4053   free (vars);
4054   return (list);
4055 }
4056
4057 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
4058 #define add_to_export_env(envstr,do_alloc) \
4059 do \
4060   { \
4061     if (export_env_index >= (export_env_size - 1)) \
4062       { \
4063         export_env_size += 16; \
4064         export_env = strvec_resize (export_env, export_env_size); \
4065         environ = export_env; \
4066       } \
4067     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
4068     export_env[export_env_index] = (char *)NULL; \
4069   } while (0)
4070
4071 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
4072    array with the same left-hand side.  Return the new EXPORT_ENV. */
4073 char **
4074 add_or_supercede_exported_var (assign, do_alloc)
4075      char *assign;
4076      int do_alloc;
4077 {
4078   register int i;
4079   int equal_offset;
4080
4081   equal_offset = assignment (assign, 0);
4082   if (equal_offset == 0)
4083     return (export_env);
4084
4085   /* If this is a function, then only supersede the function definition.
4086      We do this by including the `=() {' in the comparison, like
4087      initialize_shell_variables does. */
4088   if (assign[equal_offset + 1] == '(' &&
4089      strncmp (assign + equal_offset + 2, ") {", 3) == 0)                /* } */
4090     equal_offset += 4;
4091
4092   for (i = 0; i < export_env_index; i++)
4093     {
4094       if (STREQN (assign, export_env[i], equal_offset + 1))
4095         {
4096           free (export_env[i]);
4097           export_env[i] = do_alloc ? savestring (assign) : assign;
4098           return (export_env);
4099         }
4100     }
4101   add_to_export_env (assign, do_alloc);
4102   return (export_env);
4103 }
4104
4105 static void
4106 add_temp_array_to_env (temp_array, do_alloc, do_supercede)
4107      char **temp_array;
4108      int do_alloc, do_supercede;
4109 {
4110   register int i;
4111
4112   if (temp_array == 0)
4113     return;
4114
4115   for (i = 0; temp_array[i]; i++)
4116     {
4117       if (do_supercede)
4118         export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
4119       else
4120         add_to_export_env (temp_array[i], do_alloc);
4121     }
4122
4123   free (temp_array);
4124 }
4125
4126 /* Make the environment array for the command about to be executed, if the
4127    array needs making.  Otherwise, do nothing.  If a shell action could
4128    change the array that commands receive for their environment, then the
4129    code should `array_needs_making++'.
4130
4131    The order to add to the array is:
4132         temporary_env
4133         list of var contexts whose head is shell_variables
4134         shell_functions
4135
4136   This is the shell variable lookup order.  We add only new variable
4137   names at each step, which allows local variables and variables in
4138   the temporary environments to shadow variables in the global (or
4139   any previous) scope.
4140 */
4141
4142 static int
4143 n_shell_variables ()
4144 {
4145   VAR_CONTEXT *vc;
4146   int n;
4147
4148   for (n = 0, vc = shell_variables; vc; vc = vc->down)
4149     n += HASH_ENTRIES (vc->table);
4150   return n;
4151 }
4152
4153 int
4154 chkexport (name)
4155      char *name;
4156 {
4157   SHELL_VAR *v;
4158
4159   v = find_variable (name);
4160   if (v && exported_p (v))
4161     {
4162       array_needs_making = 1;
4163       maybe_make_export_env ();
4164       return 1;
4165     }
4166   return 0;
4167 }
4168
4169 void
4170 maybe_make_export_env ()
4171 {
4172   register char **temp_array;
4173   int new_size;
4174   VAR_CONTEXT *tcxt;
4175
4176   if (array_needs_making)
4177     {
4178       if (export_env)
4179         strvec_flush (export_env);
4180
4181       /* Make a guess based on how many shell variables and functions we
4182          have.  Since there will always be array variables, and array
4183          variables are not (yet) exported, this will always be big enough
4184          for the exported variables and functions. */
4185       new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
4186                  HASH_ENTRIES (temporary_env);
4187       if (new_size > export_env_size)
4188         {
4189           export_env_size = new_size;
4190           export_env = strvec_resize (export_env, export_env_size);
4191           environ = export_env;
4192         }
4193       export_env[export_env_index = 0] = (char *)NULL;
4194
4195       /* Make a dummy variable context from the temporary_env, stick it on
4196          the front of shell_variables, call make_var_export_array on the
4197          whole thing to flatten it, and convert the list of SHELL_VAR *s
4198          to the form needed by the environment. */
4199       if (temporary_env)
4200         {
4201           tcxt = new_var_context ((char *)NULL, 0);
4202           tcxt->table = temporary_env;
4203           tcxt->down = shell_variables;
4204         }
4205       else
4206         tcxt = shell_variables;
4207       
4208       temp_array = make_var_export_array (tcxt);
4209       if (temp_array)
4210         add_temp_array_to_env (temp_array, 0, 0);
4211
4212       if (tcxt != shell_variables)
4213         free (tcxt);
4214
4215 #if defined (RESTRICTED_SHELL)
4216       /* Restricted shells may not export shell functions. */
4217       temp_array = restricted ? (char **)0 : make_func_export_array ();
4218 #else
4219       temp_array = make_func_export_array ();
4220 #endif
4221       if (temp_array)
4222         add_temp_array_to_env (temp_array, 0, 0);
4223
4224       array_needs_making = 0;
4225     }
4226 }
4227
4228 /* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
4229    we will need to remake the exported environment every time we
4230    change directories.  `_' is always put into the environment for
4231    every external command, so without special treatment it will always
4232    cause the environment to be remade.
4233
4234    If there is no other reason to make the exported environment, we can
4235    just update the variables in place and mark the exported environment
4236    as no longer needing a remake. */
4237 void
4238 update_export_env_inplace (env_prefix, preflen, value)
4239      char *env_prefix;
4240      int preflen;
4241      char *value;
4242 {
4243   char *evar;
4244
4245   evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
4246   strcpy (evar, env_prefix);
4247   if (value)
4248     strcpy (evar + preflen, value);
4249   export_env = add_or_supercede_exported_var (evar, 0);
4250 }
4251
4252 /* We always put _ in the environment as the name of this command. */
4253 void
4254 put_command_name_into_env (command_name)
4255      char *command_name;
4256 {
4257   update_export_env_inplace ("_=", 2, command_name);
4258 }
4259
4260 /* **************************************************************** */
4261 /*                                                                  */
4262 /*                    Managing variable contexts                    */
4263 /*                                                                  */
4264 /* **************************************************************** */
4265
4266 /* Allocate and return a new variable context with NAME and FLAGS.
4267    NAME can be NULL. */
4268
4269 VAR_CONTEXT *
4270 new_var_context (name, flags)
4271      char *name;
4272      int flags;
4273 {
4274   VAR_CONTEXT *vc;
4275
4276   vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
4277   vc->name = name ? savestring (name) : (char *)NULL;
4278   vc->scope = variable_context;
4279   vc->flags = flags;
4280
4281   vc->up = vc->down = (VAR_CONTEXT *)NULL;
4282   vc->table = (HASH_TABLE *)NULL;
4283
4284   return vc;
4285 }
4286
4287 /* Free a variable context and its data, including the hash table.  Dispose
4288    all of the variables. */
4289 void
4290 dispose_var_context (vc)
4291      VAR_CONTEXT *vc;
4292 {
4293   FREE (vc->name);
4294
4295   if (vc->table)
4296     {
4297       delete_all_variables (vc->table);
4298       hash_dispose (vc->table);
4299     }
4300
4301   free (vc);
4302 }
4303
4304 /* Set VAR's scope level to the current variable context. */
4305 static int
4306 set_context (var)
4307      SHELL_VAR *var;
4308 {
4309   return (var->context = variable_context);
4310 }
4311
4312 /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
4313    temporary variables, and push it onto shell_variables.  This is
4314    for shell functions. */
4315 VAR_CONTEXT *
4316 push_var_context (name, flags, tempvars)
4317      char *name;
4318      int flags;
4319      HASH_TABLE *tempvars;
4320 {
4321   VAR_CONTEXT *vc;
4322
4323   vc = new_var_context (name, flags);
4324   vc->table = tempvars;
4325   if (tempvars)
4326     {
4327       /* Have to do this because the temp environment was created before
4328          variable_context was incremented. */
4329       flatten (tempvars, set_context, (VARLIST *)NULL, 0);
4330       vc->flags |= VC_HASTMPVAR;
4331     }
4332   vc->down = shell_variables;
4333   shell_variables->up = vc;
4334
4335   return (shell_variables = vc);
4336 }
4337
4338 static void
4339 push_func_var (data)
4340      PTR_T data;
4341 {
4342   SHELL_VAR *var, *v;
4343
4344   var = (SHELL_VAR *)data;
4345
4346   if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
4347     {
4348       /* Make sure we have a hash table to store the variable in while it is
4349          being propagated down to the global variables table.  Create one if
4350          we have to */
4351       if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
4352         shell_variables->table = hash_create (0);
4353       /* XXX - should we set v->context here? */
4354       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
4355       if (shell_variables == global_variables)
4356         var->attributes &= ~(att_tempvar|att_propagate);
4357       else
4358         shell_variables->flags |= VC_HASTMPVAR;
4359       v->attributes |= var->attributes;
4360     }
4361   else
4362     stupidly_hack_special_variables (var->name);        /* XXX */
4363
4364   dispose_variable (var);
4365 }
4366
4367 /* Pop the top context off of VCXT and dispose of it, returning the rest of
4368    the stack. */
4369 void
4370 pop_var_context ()
4371 {
4372   VAR_CONTEXT *ret, *vcxt;
4373
4374   vcxt = shell_variables;
4375   if (vc_isfuncenv (vcxt) == 0)
4376     {
4377       internal_error (_("pop_var_context: head of shell_variables not a function context"));
4378       return;
4379     }
4380
4381   if (ret = vcxt->down)
4382     {
4383       ret->up = (VAR_CONTEXT *)NULL;
4384       shell_variables = ret;
4385       if (vcxt->table)
4386         hash_flush (vcxt->table, push_func_var);
4387       dispose_var_context (vcxt);
4388     }
4389   else
4390     internal_error (_("pop_var_context: no global_variables context"));
4391 }
4392
4393 /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
4394    all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
4395 void
4396 delete_all_contexts (vcxt)
4397      VAR_CONTEXT *vcxt;
4398 {
4399   VAR_CONTEXT *v, *t;
4400
4401   for (v = vcxt; v != global_variables; v = t)
4402     {
4403       t = v->down;
4404       dispose_var_context (v);
4405     }    
4406
4407   delete_all_variables (global_variables->table);
4408   shell_variables = global_variables;
4409 }
4410
4411 /* **************************************************************** */
4412 /*                                                                  */
4413 /*         Pushing and Popping temporary variable scopes            */
4414 /*                                                                  */
4415 /* **************************************************************** */
4416
4417 VAR_CONTEXT *
4418 push_scope (flags, tmpvars)
4419      int flags;
4420      HASH_TABLE *tmpvars;
4421 {
4422   return (push_var_context ((char *)NULL, flags, tmpvars));
4423 }
4424
4425 static void
4426 push_exported_var (data)
4427      PTR_T data;
4428 {
4429   SHELL_VAR *var, *v;
4430
4431   var = (SHELL_VAR *)data;
4432
4433   /* If a temp var had its export attribute set, or it's marked to be
4434      propagated, bind it in the previous scope before disposing it. */
4435   /* XXX - This isn't exactly right, because all tempenv variables have the
4436     export attribute set. */
4437 #if 0
4438   if (exported_p (var) || (var->attributes & att_propagate))
4439 #else
4440   if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
4441 #endif
4442     {
4443       var->attributes &= ~att_tempvar;          /* XXX */
4444       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
4445       if (shell_variables == global_variables)
4446         var->attributes &= ~att_propagate;
4447       v->attributes |= var->attributes;
4448     }
4449   else
4450     stupidly_hack_special_variables (var->name);        /* XXX */
4451
4452   dispose_variable (var);
4453 }
4454
4455 void
4456 pop_scope (is_special)
4457      int is_special;
4458 {
4459   VAR_CONTEXT *vcxt, *ret;
4460
4461   vcxt = shell_variables;
4462   if (vc_istempscope (vcxt) == 0)
4463     {
4464       internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
4465       return;
4466     }
4467
4468   ret = vcxt->down;
4469   if (ret)
4470     ret->up = (VAR_CONTEXT *)NULL;
4471
4472   shell_variables = ret;
4473
4474   /* Now we can take care of merging variables in VCXT into set of scopes
4475      whose head is RET (shell_variables). */
4476   FREE (vcxt->name);
4477   if (vcxt->table)
4478     {
4479       if (is_special)
4480         hash_flush (vcxt->table, push_func_var);
4481       else
4482         hash_flush (vcxt->table, push_exported_var);
4483       hash_dispose (vcxt->table);
4484     }
4485   free (vcxt);
4486
4487   sv_ifs ("IFS");       /* XXX here for now */
4488 }
4489
4490 /* **************************************************************** */
4491 /*                                                                  */
4492 /*               Pushing and Popping function contexts              */
4493 /*                                                                  */
4494 /* **************************************************************** */
4495
4496 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
4497 static int dollar_arg_stack_slots;
4498 static int dollar_arg_stack_index;
4499
4500 /* XXX - we might want to consider pushing and popping the `getopts' state
4501    when we modify the positional parameters. */
4502 void
4503 push_context (name, is_subshell, tempvars)
4504      char *name;        /* function name */
4505      int is_subshell;
4506      HASH_TABLE *tempvars;
4507 {
4508   if (is_subshell == 0)
4509     push_dollar_vars ();
4510   variable_context++;
4511   push_var_context (name, VC_FUNCENV, tempvars);
4512 }
4513
4514 /* Only called when subshell == 0, so we don't need to check, and can
4515    unconditionally pop the dollar vars off the stack. */
4516 void
4517 pop_context ()
4518 {
4519   pop_dollar_vars ();
4520   variable_context--;
4521   pop_var_context ();
4522
4523   sv_ifs ("IFS");               /* XXX here for now */
4524 }
4525
4526 /* Save the existing positional parameters on a stack. */
4527 void
4528 push_dollar_vars ()
4529 {
4530   if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
4531     {
4532       dollar_arg_stack = (WORD_LIST **)
4533         xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
4534                   * sizeof (WORD_LIST *));
4535     }
4536   dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
4537   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
4538 }
4539
4540 /* Restore the positional parameters from our stack. */
4541 void
4542 pop_dollar_vars ()
4543 {
4544   if (!dollar_arg_stack || dollar_arg_stack_index == 0)
4545     return;
4546
4547   remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
4548   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
4549   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
4550   set_dollar_vars_unchanged ();
4551 }
4552
4553 void
4554 dispose_saved_dollar_vars ()
4555 {
4556   if (!dollar_arg_stack || dollar_arg_stack_index == 0)
4557     return;
4558
4559   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
4560   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
4561 }
4562
4563 /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
4564
4565 void
4566 push_args (list)
4567      WORD_LIST *list;
4568 {
4569 #if defined (ARRAY_VARS) && defined (DEBUGGER)
4570   SHELL_VAR *bash_argv_v, *bash_argc_v;
4571   ARRAY *bash_argv_a, *bash_argc_a;
4572   WORD_LIST *l;
4573   arrayind_t i;
4574   char *t;
4575
4576   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
4577   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
4578
4579   for (l = list, i = 0; l; l = l->next, i++)
4580     array_push (bash_argv_a, l->word->word);
4581
4582   t = itos (i);
4583   array_push (bash_argc_a, t);
4584   free (t);
4585 #endif /* ARRAY_VARS && DEBUGGER */
4586 }
4587
4588 /* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
4589    array and use that value as the count of elements to remove from
4590    BASH_ARGV. */
4591 void
4592 pop_args ()
4593 {
4594 #if defined (ARRAY_VARS) && defined (DEBUGGER)
4595   SHELL_VAR *bash_argv_v, *bash_argc_v;
4596   ARRAY *bash_argv_a, *bash_argc_a;
4597   ARRAY_ELEMENT *ce;
4598   intmax_t i;
4599
4600   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
4601   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
4602
4603   ce = array_shift (bash_argc_a, 1, 0);
4604   if (ce == 0 || legal_number (element_value (ce), &i) == 0)
4605     i = 0;
4606
4607   for ( ; i > 0; i--)
4608     array_pop (bash_argv_a);
4609   array_dispose_element (ce);
4610 #endif /* ARRAY_VARS && DEBUGGER */
4611 }
4612
4613 /*************************************************
4614  *                                               *
4615  *      Functions to manage special variables    *
4616  *                                               *
4617  *************************************************/
4618
4619 /* Extern declarations for variables this code has to manage. */
4620 extern int eof_encountered, eof_encountered_limit, ignoreeof;
4621
4622 #if defined (READLINE)
4623 extern int hostname_list_initialized;
4624 #endif
4625
4626 /* An alist of name.function for each special variable.  Most of the
4627    functions don't do much, and in fact, this would be faster with a
4628    switch statement, but by the end of this file, I am sick of switch
4629    statements. */
4630
4631 #define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
4632
4633 /* This table will be sorted with qsort() the first time it's accessed. */
4634 struct name_and_function {
4635   char *name;
4636   sh_sv_func_t *function;
4637 };
4638
4639 static struct name_and_function special_vars[] = {
4640   { "BASH_COMPAT", sv_shcompat },
4641   { "BASH_XTRACEFD", sv_xtracefd },
4642
4643 #if defined (JOB_CONTROL)
4644   { "CHILD_MAX", sv_childmax },
4645 #endif
4646
4647 #if defined (READLINE)
4648 #  if defined (STRICT_POSIX)
4649   { "COLUMNS", sv_winsize },
4650 #  endif
4651   { "COMP_WORDBREAKS", sv_comp_wordbreaks },
4652 #endif
4653
4654   { "FUNCNEST", sv_funcnest },
4655
4656   { "GLOBIGNORE", sv_globignore },
4657
4658 #if defined (HISTORY)
4659   { "HISTCONTROL", sv_history_control },
4660   { "HISTFILESIZE", sv_histsize },
4661   { "HISTIGNORE", sv_histignore },
4662   { "HISTSIZE", sv_histsize },
4663   { "HISTTIMEFORMAT", sv_histtimefmt },
4664 #endif
4665
4666 #if defined (__CYGWIN__)
4667   { "HOME", sv_home },
4668 #endif
4669
4670 #if defined (READLINE)
4671   { "HOSTFILE", sv_hostfile },
4672 #endif
4673
4674   { "IFS", sv_ifs },
4675   { "IGNOREEOF", sv_ignoreeof },
4676
4677   { "LANG", sv_locale },
4678   { "LC_ALL", sv_locale },
4679   { "LC_COLLATE", sv_locale },
4680   { "LC_CTYPE", sv_locale },
4681   { "LC_MESSAGES", sv_locale },
4682   { "LC_NUMERIC", sv_locale },
4683   { "LC_TIME", sv_locale },
4684
4685 #if defined (READLINE) && defined (STRICT_POSIX)
4686   { "LINES", sv_winsize },
4687 #endif
4688
4689   { "MAIL", sv_mail },
4690   { "MAILCHECK", sv_mail },
4691   { "MAILPATH", sv_mail },
4692
4693   { "OPTERR", sv_opterr },
4694   { "OPTIND", sv_optind },
4695
4696   { "PATH", sv_path },
4697   { "POSIXLY_CORRECT", sv_strict_posix },
4698
4699 #if defined (READLINE)
4700   { "TERM", sv_terminal },
4701   { "TERMCAP", sv_terminal },
4702   { "TERMINFO", sv_terminal },
4703 #endif /* READLINE */
4704
4705   { "TEXTDOMAIN", sv_locale },
4706   { "TEXTDOMAINDIR", sv_locale },
4707
4708 #if defined (HAVE_TZSET)
4709   { "TZ", sv_tz },
4710 #endif
4711
4712 #if defined (HISTORY) && defined (BANG_HISTORY)
4713   { "histchars", sv_histchars },
4714 #endif /* HISTORY && BANG_HISTORY */
4715
4716   { "ignoreeof", sv_ignoreeof },
4717
4718   { (char *)0, (sh_sv_func_t *)0 }
4719 };
4720
4721 #define N_SPECIAL_VARS  (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
4722
4723 static int
4724 sv_compare (sv1, sv2)
4725      struct name_and_function *sv1, *sv2;
4726 {
4727   int r;
4728
4729   if ((r = sv1->name[0] - sv2->name[0]) == 0)
4730     r = strcmp (sv1->name, sv2->name);
4731   return r;
4732 }
4733
4734 static inline int
4735 find_special_var (name)
4736      const char *name;
4737 {
4738   register int i, r;
4739
4740   for (i = 0; special_vars[i].name; i++)
4741     {
4742       r = special_vars[i].name[0] - name[0];
4743       if (r == 0)
4744         r = strcmp (special_vars[i].name, name);
4745       if (r == 0)
4746         return i;
4747       else if (r > 0)
4748         /* Can't match any of rest of elements in sorted list.  Take this out
4749            if it causes problems in certain environments. */
4750         break;
4751     }
4752   return -1;
4753 }
4754
4755 /* The variable in NAME has just had its state changed.  Check to see if it
4756    is one of the special ones where something special happens. */
4757 void
4758 stupidly_hack_special_variables (name)
4759      char *name;
4760 {
4761   static int sv_sorted = 0;
4762   int i;
4763
4764   if (sv_sorted == 0)   /* shouldn't need, but it's fairly cheap. */
4765     {
4766       qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
4767                 (QSFUNC *)sv_compare);
4768       sv_sorted = 1;
4769     }
4770
4771   i = find_special_var (name);
4772   if (i != -1)
4773     (*(special_vars[i].function)) (name);
4774 }
4775
4776 /* Special variables that need hooks to be run when they are unset as part
4777    of shell reinitialization should have their sv_ functions run here. */
4778 void
4779 reinit_special_variables ()
4780 {
4781 #if defined (READLINE)
4782   sv_comp_wordbreaks ("COMP_WORDBREAKS");
4783 #endif
4784   sv_globignore ("GLOBIGNORE");
4785   sv_opterr ("OPTERR");
4786 }
4787
4788 void
4789 sv_ifs (name)
4790      char *name;
4791 {
4792   SHELL_VAR *v;
4793
4794   v = find_variable ("IFS");
4795   setifs (v);
4796 }
4797
4798 /* What to do just after the PATH variable has changed. */
4799 void
4800 sv_path (name)
4801      char *name;
4802 {
4803   /* hash -r */
4804   phash_flush ();
4805 }
4806
4807 /* What to do just after one of the MAILxxxx variables has changed.  NAME
4808    is the name of the variable.  This is called with NAME set to one of
4809    MAIL, MAILCHECK, or MAILPATH.  */
4810 void
4811 sv_mail (name)
4812      char *name;
4813 {
4814   /* If the time interval for checking the files has changed, then
4815      reset the mail timer.  Otherwise, one of the pathname vars
4816      to the users mailbox has changed, so rebuild the array of
4817      filenames. */
4818   if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
4819     reset_mail_timer ();
4820   else
4821     {
4822       free_mail_files ();
4823       remember_mail_dates ();
4824     }
4825 }
4826
4827 void
4828 sv_funcnest (name)
4829      char *name;
4830 {
4831   SHELL_VAR *v;
4832   intmax_t num;
4833
4834   v = find_variable (name);
4835   if (v == 0)
4836     funcnest_max = 0;
4837   else if (legal_number (value_cell (v), &num) == 0)
4838     funcnest_max = 0;
4839   else
4840     funcnest_max = num;
4841 }
4842
4843 /* What to do when GLOBIGNORE changes. */
4844 void
4845 sv_globignore (name)
4846      char *name;
4847 {
4848   if (privileged_mode == 0)
4849     setup_glob_ignore (name);
4850 }
4851
4852 #if defined (READLINE)
4853 void
4854 sv_comp_wordbreaks (name)
4855      char *name;
4856 {
4857   SHELL_VAR *sv;
4858
4859   sv = find_variable (name);
4860   if (sv == 0)
4861     reset_completer_word_break_chars ();
4862 }
4863
4864 /* What to do just after one of the TERMxxx variables has changed.
4865    If we are an interactive shell, then try to reset the terminal
4866    information in readline. */
4867 void
4868 sv_terminal (name)
4869      char *name;
4870 {
4871   if (interactive_shell && no_line_editing == 0)
4872     rl_reset_terminal (get_string_value ("TERM"));
4873 }
4874
4875 void
4876 sv_hostfile (name)
4877      char *name;
4878 {
4879   SHELL_VAR *v;
4880
4881   v = find_variable (name);
4882   if (v == 0)
4883     clear_hostname_list ();
4884   else
4885     hostname_list_initialized = 0;
4886 }
4887
4888 #if defined (STRICT_POSIX)
4889 /* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
4890    found in the initial environment) to override the terminal size reported by
4891    the kernel. */
4892 void
4893 sv_winsize (name)
4894      char *name;
4895 {
4896   SHELL_VAR *v;
4897   intmax_t xd;
4898   int d;
4899
4900   if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
4901     return;
4902
4903   v = find_variable (name);
4904   if (v == 0 || var_isnull (v))
4905     rl_reset_screen_size ();
4906   else
4907     {
4908       if (legal_number (value_cell (v), &xd) == 0)
4909         return;
4910       winsize_assignment = 1;
4911       d = xd;                   /* truncate */
4912       if (name[0] == 'L')       /* LINES */
4913         rl_set_screen_size (d, -1);
4914       else                      /* COLUMNS */
4915         rl_set_screen_size (-1, d);
4916       winsize_assignment = 0;
4917     }
4918 }
4919 #endif /* STRICT_POSIX */
4920 #endif /* READLINE */
4921
4922 /* Update the value of HOME in the export environment so tilde expansion will
4923    work on cygwin. */
4924 #if defined (__CYGWIN__)
4925 sv_home (name)
4926      char *name;
4927 {
4928   array_needs_making = 1;
4929   maybe_make_export_env ();
4930 }
4931 #endif
4932
4933 #if defined (HISTORY)
4934 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
4935    If there is a value for this HISTSIZE (and it is numeric), then stifle
4936    the history.  Otherwise, if there is NO value for this variable,
4937    unstifle the history.  If name is HISTFILESIZE, and its value is
4938    numeric, truncate the history file to hold no more than that many
4939    lines. */
4940 void
4941 sv_histsize (name)
4942      char *name;
4943 {
4944   char *temp;
4945   intmax_t num;
4946   int hmax;
4947
4948   temp = get_string_value (name);
4949
4950   if (temp && *temp)
4951     {
4952       if (legal_number (temp, &num))
4953         {
4954           hmax = num;
4955           if (hmax < 0 && name[4] == 'S')
4956             unstifle_history ();        /* unstifle history if HISTSIZE < 0 */
4957           else if (name[4] == 'S')
4958             {
4959               stifle_history (hmax);
4960               hmax = where_history ();
4961               if (history_lines_this_session > hmax)
4962                 history_lines_this_session = hmax;
4963             }
4964           else if (hmax >= 0)   /* truncate HISTFILE if HISTFILESIZE >= 0 */
4965             {
4966               history_truncate_file (get_string_value ("HISTFILE"), hmax);
4967               if (hmax <= history_lines_in_file)
4968                 history_lines_in_file = hmax;
4969             }
4970         }
4971     }
4972   else if (name[4] == 'S')
4973     unstifle_history ();
4974 }
4975
4976 /* What to do after the HISTIGNORE variable changes. */
4977 void
4978 sv_histignore (name)
4979      char *name;
4980 {
4981   setup_history_ignore (name);
4982 }
4983
4984 /* What to do after the HISTCONTROL variable changes. */
4985 void
4986 sv_history_control (name)
4987      char *name;
4988 {
4989   char *temp;
4990   char *val;
4991   int tptr;
4992
4993   history_control = 0;
4994   temp = get_string_value (name);
4995
4996   if (temp == 0 || *temp == 0)
4997     return;
4998
4999   tptr = 0;
5000   while (val = extract_colon_unit (temp, &tptr))
5001     {
5002       if (STREQ (val, "ignorespace"))
5003         history_control |= HC_IGNSPACE;
5004       else if (STREQ (val, "ignoredups"))
5005         history_control |= HC_IGNDUPS;
5006       else if (STREQ (val, "ignoreboth"))
5007         history_control |= HC_IGNBOTH;
5008       else if (STREQ (val, "erasedups"))
5009         history_control |= HC_ERASEDUPS;
5010
5011       free (val);
5012     }
5013 }
5014
5015 #if defined (BANG_HISTORY)
5016 /* Setting/unsetting of the history expansion character. */
5017 void
5018 sv_histchars (name)
5019      char *name;
5020 {
5021   char *temp;
5022
5023   temp = get_string_value (name);
5024   if (temp)
5025     {
5026       history_expansion_char = *temp;
5027       if (temp[0] && temp[1])
5028         {
5029           history_subst_char = temp[1];
5030           if (temp[2])
5031               history_comment_char = temp[2];
5032         }
5033     }
5034   else
5035     {
5036       history_expansion_char = '!';
5037       history_subst_char = '^';
5038       history_comment_char = '#';
5039     }
5040 }
5041 #endif /* BANG_HISTORY */
5042
5043 void
5044 sv_histtimefmt (name)
5045      char *name;
5046 {
5047   SHELL_VAR *v;
5048
5049   if (v = find_variable (name))
5050     {
5051       if (history_comment_char == 0)
5052         history_comment_char = '#';
5053     }
5054   history_write_timestamps = (v != 0);
5055 }
5056 #endif /* HISTORY */
5057
5058 #if defined (HAVE_TZSET)
5059 void
5060 sv_tz (name)
5061      char *name;
5062 {
5063   if (chkexport (name))
5064     tzset ();
5065 }
5066 #endif
5067
5068 /* If the variable exists, then the value of it can be the number
5069    of times we actually ignore the EOF.  The default is small,
5070    (smaller than csh, anyway). */
5071 void
5072 sv_ignoreeof (name)
5073      char *name;
5074 {
5075   SHELL_VAR *tmp_var;
5076   char *temp;
5077
5078   eof_encountered = 0;
5079
5080   tmp_var = find_variable (name);
5081   ignoreeof = tmp_var != 0;
5082   temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
5083   if (temp)
5084     eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
5085   set_shellopts ();     /* make sure `ignoreeof' is/is not in $SHELLOPTS */
5086 }
5087
5088 void
5089 sv_optind (name)
5090      char *name;
5091 {
5092   char *tt;
5093   int s;
5094
5095   tt = get_string_value ("OPTIND");
5096   if (tt && *tt)
5097     {
5098       s = atoi (tt);
5099
5100       /* According to POSIX, setting OPTIND=1 resets the internal state
5101          of getopt (). */
5102       if (s < 0 || s == 1)
5103         s = 0;
5104     }
5105   else
5106     s = 0;
5107   getopts_reset (s);
5108 }
5109
5110 void
5111 sv_opterr (name)
5112      char *name;
5113 {
5114   char *tt;
5115
5116   tt = get_string_value ("OPTERR");
5117   sh_opterr = (tt && *tt) ? atoi (tt) : 1;
5118 }
5119
5120 void
5121 sv_strict_posix (name)
5122      char *name;
5123 {
5124   SET_INT_VAR (name, posixly_correct);
5125   posix_initialize (posixly_correct);
5126 #if defined (READLINE)
5127   if (interactive_shell)
5128     posix_readline_initialize (posixly_correct);
5129 #endif /* READLINE */
5130   set_shellopts ();     /* make sure `posix' is/is not in $SHELLOPTS */
5131 }
5132
5133 void
5134 sv_locale (name)
5135      char *name;
5136 {
5137   char *v;
5138   int r;
5139
5140   v = get_string_value (name);
5141   if (name[0] == 'L' && name[1] == 'A') /* LANG */
5142     r = set_lang (name, v);
5143   else
5144     r = set_locale_var (name, v);               /* LC_*, TEXTDOMAIN* */
5145
5146 #if 1
5147   if (r == 0 && posixly_correct)
5148     last_command_exit_value = 1;
5149 #endif
5150 }
5151
5152 #if defined (ARRAY_VARS)
5153 void
5154 set_pipestatus_array (ps, nproc)
5155      int *ps;
5156      int nproc;
5157 {
5158   SHELL_VAR *v;
5159   ARRAY *a;
5160   ARRAY_ELEMENT *ae;
5161   register int i;
5162   char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
5163
5164   v = find_variable ("PIPESTATUS");
5165   if (v == 0)
5166     v = make_new_array_variable ("PIPESTATUS");
5167   if (array_p (v) == 0)
5168     return;             /* Do nothing if not an array variable. */
5169   a = array_cell (v);
5170
5171   if (a == 0 || array_num_elements (a) == 0)
5172     {
5173       for (i = 0; i < nproc; i++)       /* was ps[i] != -1, not i < nproc */
5174         {
5175           t = inttostr (ps[i], tbuf, sizeof (tbuf));
5176           array_insert (a, i, t);
5177         }
5178       return;
5179     }
5180
5181   /* Fast case */
5182   if (array_num_elements (a) == nproc && nproc == 1)
5183     {
5184       ae = element_forw (a->head);
5185       free (element_value (ae));
5186       ae->value = itos (ps[0]);
5187     }
5188   else if (array_num_elements (a) <= nproc)
5189     {
5190       /* modify in array_num_elements members in place, then add */
5191       ae = a->head;
5192       for (i = 0; i < array_num_elements (a); i++)
5193         {
5194           ae = element_forw (ae);
5195           free (element_value (ae));
5196           ae->value = itos (ps[i]);
5197         }
5198       /* add any more */
5199       for ( ; i < nproc; i++)
5200         {
5201           t = inttostr (ps[i], tbuf, sizeof (tbuf));
5202           array_insert (a, i, t);
5203         }
5204     }
5205   else
5206     {
5207       /* deleting elements.  it's faster to rebuild the array. */         
5208       array_flush (a);
5209       for (i = 0; ps[i] != -1; i++)
5210         {
5211           t = inttostr (ps[i], tbuf, sizeof (tbuf));
5212           array_insert (a, i, t);
5213         }
5214     }
5215 }
5216
5217 ARRAY *
5218 save_pipestatus_array ()
5219 {
5220   SHELL_VAR *v;
5221   ARRAY *a, *a2;
5222
5223   v = find_variable ("PIPESTATUS");
5224   if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
5225     return ((ARRAY *)NULL);
5226     
5227   a = array_cell (v);
5228   a2 = array_copy (array_cell (v));
5229
5230   return a2;
5231 }
5232
5233 void
5234 restore_pipestatus_array (a)
5235      ARRAY *a;
5236 {
5237   SHELL_VAR *v;
5238   ARRAY *a2;
5239
5240   v = find_variable ("PIPESTATUS");
5241   /* XXX - should we still assign even if existing value is NULL? */
5242   if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
5243     return;
5244
5245   a2 = array_cell (v);
5246   var_setarray (v, a); 
5247
5248   array_dispose (a2);
5249 }
5250 #endif
5251
5252 void
5253 set_pipestatus_from_exit (s)
5254      int s;
5255 {
5256 #if defined (ARRAY_VARS)
5257   static int v[2] = { 0, -1 };
5258
5259   v[0] = s;
5260   set_pipestatus_array (v, 1);
5261 #endif
5262 }
5263
5264 void
5265 sv_xtracefd (name)
5266      char *name;
5267 {
5268   SHELL_VAR *v;
5269   char *t, *e;
5270   int fd;
5271   FILE *fp;
5272
5273   v = find_variable (name);
5274   if (v == 0)
5275     {
5276       xtrace_reset ();
5277       return;
5278     }
5279
5280   t = value_cell (v);
5281   if (t == 0 || *t == 0)
5282     xtrace_reset ();
5283   else
5284     {
5285       fd = (int)strtol (t, &e, 10);
5286       if (e != t && *e == '\0' && sh_validfd (fd))
5287         {
5288           fp = fdopen (fd, "w");
5289           if (fp == 0)
5290             internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
5291           else
5292             xtrace_set (fd, fp);
5293         }
5294       else
5295         internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
5296     }
5297 }
5298
5299 #define MIN_COMPAT_LEVEL 31
5300
5301 void
5302 sv_shcompat (name)
5303      char *name;
5304 {
5305   SHELL_VAR *v;
5306   char *val;
5307   int tens, ones, compatval;
5308
5309   v = find_variable (name);
5310   if (v == 0)
5311     {
5312       shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
5313       set_compatibility_opts ();
5314       return;
5315     }
5316   val = value_cell (v);
5317   if (val == 0 || *val == '\0')
5318     {
5319       shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
5320       set_compatibility_opts ();
5321       return;
5322     }
5323   /* Handle decimal-like compatibility version specifications: 4.2 */
5324   if (isdigit (val[0]) && val[1] == '.' && isdigit (val[2]) && val[3] == 0)
5325     {
5326       tens = val[0] - '0';
5327       ones = val[2] - '0';
5328       compatval = tens*10 + ones;
5329     }
5330   /* Handle integer-like compatibility version specifications: 42 */
5331   else if (isdigit (val[0]) && isdigit (val[1]) && val[2] == 0)
5332     {
5333       tens = val[0] - '0';
5334       ones = val[1] - '0';
5335       compatval = tens*10 + ones;
5336     }
5337   else
5338     {
5339 compat_error:
5340       internal_error (_("%s: %s: compatibility value out of range"), name, val);
5341       shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
5342       set_compatibility_opts ();
5343       return;
5344     }
5345
5346   if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL)
5347     goto compat_error;
5348
5349   shell_compatibility_level = compatval;
5350   set_compatibility_opts ();
5351 }
5352
5353 #if defined (JOB_CONTROL)
5354 void
5355 sv_childmax (name)
5356      char *name;
5357 {
5358   char *tt;
5359   int s;
5360
5361   tt = get_string_value (name);
5362   s = (tt && *tt) ? atoi (tt) : 0;
5363   set_maxchild (s);
5364 }
5365 #endif