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