Imported from ../bash-3.0.tar.gz.
[platform/upstream/bash.git] / variables.c
1 /* variables.c -- Functions for hacking shell variables. */
2
3 /* Copyright (C) 1987-2004 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 it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Bash; see the file COPYING.  If not, write to the Free
19    Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #include "posixstat.h"
25 #include "posixtime.h"
26
27 #if defined (qnx)
28 #  include <sys/vc.h>
29 #endif
30
31 #if defined (HAVE_UNISTD_H)
32 #  include <unistd.h>
33 #endif
34
35 #include <stdio.h>
36 #include "chartypes.h"
37 #include <pwd.h>
38 #include "bashansi.h"
39 #include "bashintl.h"
40
41 #include "shell.h"
42 #include "flags.h"
43 #include "execute_cmd.h"
44 #include "findcmd.h"
45 #include "mailcheck.h"
46 #include "input.h"
47 #include "hashcmd.h"
48 #include "pathexp.h"
49
50 #include "builtins/getopt.h"
51 #include "builtins/common.h"
52
53 #if defined (READLINE)
54 #  include "bashline.h"
55 #  include <readline/readline.h>
56 #else
57 #  include <tilde/tilde.h>
58 #endif
59
60 #if defined (HISTORY)
61 #  include "bashhist.h"
62 #  include <readline/history.h>
63 #endif /* HISTORY */
64
65 #if defined (PROGRAMMABLE_COMPLETION)
66 #  include "pcomplete.h"
67 #endif
68
69 #define TEMPENV_HASH_BUCKETS    4       /* must be power of two */
70
71 #define ifsname(s)      ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
72
73 /* Variables used here and defined in other files. */
74 extern int posixly_correct;
75 extern int line_number;
76 extern int subshell_environment, indirection_level, subshell_level;
77 extern int build_version, patch_level;
78 extern int expanding_redir;
79 extern char *dist_version, *release_status;
80 extern char *shell_name;
81 extern char *primary_prompt, *secondary_prompt;
82 extern char *current_host_name;
83 extern sh_builtin_func_t *this_shell_builtin;
84 extern SHELL_VAR *this_shell_function;
85 extern char *the_printed_command_except_trap;
86 extern char *this_command_name;
87 extern char *command_execution_string;
88 extern time_t shell_start_time;
89
90 #if defined (READLINE)
91 extern int perform_hostname_completion;
92 #endif
93
94 /* The list of shell variables that the user has created at the global
95    scope, or that came from the environment. */
96 VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
97
98 /* The current list of shell variables, including function scopes */
99 VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
100
101 /* The list of shell functions that the user has created, or that came from
102    the environment. */
103 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
104
105 #if defined (DEBUGGER)
106 /* The table of shell function definitions that the user defined or that
107    came from the environment. */
108 HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
109 #endif
110
111 /* The current variable context.  This is really a count of how deep into
112    executing functions we are. */
113 int variable_context = 0;
114
115 /* The set of shell assignments which are made only in the environment
116    for a single command. */
117 HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
118
119 /* Set to non-zero if an assignment error occurs while putting variables
120    into the temporary environment. */
121 int tempenv_assign_error;
122
123 /* Some funky variables which are known about specially.  Here is where
124    "$*", "$1", and all the cruft is kept. */
125 char *dollar_vars[10];
126 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
127
128 /* The value of $$. */
129 pid_t dollar_dollar_pid;
130
131 /* An array which is passed to commands as their environment.  It is
132    manufactured from the union of the initial environment and the
133    shell variables that are marked for export. */
134 char **export_env = (char **)NULL;
135 static int export_env_index;
136 static int export_env_size;
137
138 /* Non-zero means that we have to remake EXPORT_ENV. */
139 int array_needs_making = 1;
140
141 /* The number of times BASH has been executed.  This is set
142    by initialize_variables (). */
143 int shell_level = 0;
144
145 /* Some forward declarations. */
146 static void set_machine_vars __P((void));
147 static void set_home_var __P((void));
148 static void set_shell_var __P((void));
149 static char *get_bash_name __P((void));
150 static void initialize_shell_level __P((void));
151 static void uidset __P((void));
152 #if defined (ARRAY_VARS)
153 static void make_vers_array __P((void));
154 #endif
155
156 static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
157 #if defined (ARRAY_VARS)
158 static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
159 #endif
160 static SHELL_VAR *get_self __P((SHELL_VAR *));
161
162 #if defined (ARRAY_VARS)
163 static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
164 #endif
165
166 static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
167 static SHELL_VAR *get_seconds __P((SHELL_VAR *));
168 static SHELL_VAR *init_seconds_var __P((void));
169
170 static int brand __P((void));
171 static void sbrand __P((unsigned long));                /* set bash random number generator. */
172 static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
173 static SHELL_VAR *get_random __P((SHELL_VAR *));
174
175 static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
176 static SHELL_VAR *get_lineno __P((SHELL_VAR *));
177
178 static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
179 static SHELL_VAR *get_subshell __P((SHELL_VAR *));
180
181 #if defined (HISTORY)
182 static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
183 #endif
184
185 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
186 static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
187 static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
188 #endif
189
190 #if defined (ARRAY_VARS)
191 static SHELL_VAR *get_groupset __P((SHELL_VAR *));
192 #endif
193
194 static SHELL_VAR *get_funcname __P((SHELL_VAR *));
195 static SHELL_VAR *init_funcname_var __P((void));
196
197 static void initialize_dynamic_variables __P((void));
198
199 static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
200 static SHELL_VAR *new_shell_variable __P((const char *));
201 static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
202 static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int));
203
204 static void free_variable_hash_data __P((PTR_T));
205
206 static VARLIST *vlist_alloc __P((int));
207 static VARLIST *vlist_realloc __P((VARLIST *, int));
208 static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
209
210 static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
211
212 static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
213
214 static SHELL_VAR **vapply __P((sh_var_map_func_t *));
215 static SHELL_VAR **fapply __P((sh_var_map_func_t *));
216
217 static int visible_var __P((SHELL_VAR *));
218 static int visible_and_exported __P((SHELL_VAR *));
219 static int local_and_exported __P((SHELL_VAR *));
220 static int variable_in_context __P((SHELL_VAR *));
221 #if defined (ARRAY_VARS)
222 static int visible_array_vars __P((SHELL_VAR *));
223 #endif
224
225 static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
226 static void push_temp_var __P((PTR_T));
227 static void propagate_temp_var __P((PTR_T));
228 static void dispose_temporary_env __P((sh_free_func_t *));     
229
230 static inline char *mk_env_string __P((const char *, const char *));
231 static char **make_env_array_from_var_list __P((SHELL_VAR **));
232 static char **make_var_export_array __P((VAR_CONTEXT *));
233 static char **make_func_export_array __P((void));
234 static void add_temp_array_to_env __P((char **, int, int));
235
236 static int n_shell_variables __P((void));
237 static int set_context __P((SHELL_VAR *));
238
239 static void push_func_var __P((PTR_T));
240 static void push_exported_var __P((PTR_T));
241
242 static inline int find_special_var __P((const char *));
243                
244 /* Initialize the shell variables from the current environment.
245    If PRIVMODE is nonzero, don't import functions from ENV or
246    parse $SHELLOPTS. */
247 void
248 initialize_shell_variables (env, privmode)
249      char **env;
250      int privmode;
251 {
252   char *name, *string, *temp_string;
253   int c, char_index, string_index, string_length;
254   SHELL_VAR *temp_var;
255
256   if (shell_variables == 0)
257     {
258       shell_variables = global_variables = new_var_context ((char *)NULL, 0);
259       shell_variables->scope = 0;
260       shell_variables->table = hash_create (0);
261     }
262
263   if (shell_functions == 0)
264     shell_functions = hash_create (0);
265
266 #if defined (DEBUGGER)
267   if (shell_function_defs == 0)
268     shell_function_defs = hash_create (0);
269 #endif
270
271   for (string_index = 0; string = env[string_index++]; )
272     {
273       char_index = 0;
274       name = string;
275       while ((c = *string++) && c != '=')
276         ;
277       if (string[-1] == '=')
278         char_index = string - name - 1;
279
280       /* If there are weird things in the environment, like `=xxx' or a
281          string without an `=', just skip them. */
282       if (char_index == 0)
283         continue;
284
285       /* ASSERT(name[char_index] == '=') */
286       name[char_index] = '\0';
287       /* Now, name = env variable name, string = env variable value, and
288          char_index == strlen (name) */
289
290       /* If exported function, define it now.  Don't import functions from
291          the environment in privileged mode. */
292       if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
293         {
294           string_length = strlen (string);
295           temp_string = (char *)xmalloc (3 + string_length + char_index);
296
297           strcpy (temp_string, name);
298           temp_string[char_index] = ' ';
299           strcpy (temp_string + char_index + 1, string);
300
301           parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
302
303           /* Ancient backwards compatibility.  Old versions of bash exported
304              functions like name()=() {...} */
305           if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
306             name[char_index - 2] = '\0';
307
308           if (temp_var = find_function (name))
309             {
310               VSETATTR (temp_var, (att_exported|att_imported));
311               array_needs_making = 1;
312             }
313           else
314             report_error (_("error importing function definition for `%s'"), name);
315
316           /* ( */
317           if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
318             name[char_index - 2] = '(';         /* ) */
319         }
320 #if defined (ARRAY_VARS)
321 #  if 0
322       /* Array variables may not yet be exported. */
323       else if (*string == '(' && string[1] == '[' && xstrchr (string, ')'))
324         {
325           string_length = 1;
326           temp_string = extract_array_assignment_list (string, &string_length);
327           temp_var = assign_array_from_string (name, temp_string);
328           FREE (temp_string);
329           VSETATTR (temp_var, (att_exported | att_imported));
330           array_needs_making = 1;
331         }
332 #  endif
333 #endif
334       else
335         {
336           temp_var = bind_variable (name, string);
337           VSETATTR (temp_var, (att_exported | att_imported));
338           array_needs_making = 1;
339         }
340
341       name[char_index] = '=';
342       /* temp_var can be NULL if it was an exported function with a syntax
343          error (a different bug, but it still shouldn't dump core). */
344       if (temp_var && function_p (temp_var) == 0)       /* XXX not yet */
345         {
346           CACHE_IMPORTSTR (temp_var, name);
347         }
348     }
349
350   set_pwd ();
351
352   /* Set up initial value of $_ */
353   temp_var = bind_variable ("_", dollar_vars[0]);
354
355   /* Remember this pid. */
356   dollar_dollar_pid = getpid ();
357
358   /* Now make our own defaults in case the vars that we think are
359      important are missing. */
360   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
361 #if 0
362   set_auto_export (temp_var);   /* XXX */
363 #endif
364
365   temp_var = set_if_not ("TERM", "dumb");
366 #if 0
367   set_auto_export (temp_var);   /* XXX */
368 #endif
369
370 #if defined (qnx)
371   /* set node id -- don't import it from the environment */
372   {
373     char node_name[22];
374     qnx_nidtostr (getnid (), node_name, sizeof (node_name));
375     temp_var = bind_variable ("NODE", node_name);
376     set_auto_export (temp_var);
377   }
378 #endif
379
380   /* set up the prompts. */
381   if (interactive_shell)
382     {
383 #if defined (PROMPT_STRING_DECODE)
384       set_if_not ("PS1", primary_prompt);
385 #else
386       if (current_user.uid == -1)
387         get_current_user_info ();
388       set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
389 #endif
390       set_if_not ("PS2", secondary_prompt);
391     }
392   set_if_not ("PS4", "+ ");
393
394   /* Don't allow IFS to be imported from the environment. */
395   temp_var = bind_variable ("IFS", " \t\n");
396   setifs (temp_var);
397
398   /* Magic machine types.  Pretty convenient. */
399   set_machine_vars ();
400
401   /* Default MAILCHECK for interactive shells.  Defer the creation of a
402      default MAILPATH until the startup files are read, because MAIL
403      names a mail file if MAILPATH is not set, and we should provide a
404      default only if neither is set. */
405   if (interactive_shell)
406     set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
407
408   /* Do some things with shell level. */
409   initialize_shell_level ();
410
411   set_ppid ();
412
413   /* Initialize the `getopts' stuff. */
414   bind_variable ("OPTIND", "1");
415   getopts_reset (0);
416   bind_variable ("OPTERR", "1");
417   sh_opterr = 1;
418
419   if (login_shell == 1)
420     set_home_var ();
421
422   /* Get the full pathname to THIS shell, and set the BASH variable
423      to it. */
424   name = get_bash_name ();
425   temp_var = bind_variable ("BASH", name);
426   free (name);
427
428   /* Make the exported environment variable SHELL be the user's login
429      shell.  Note that the `tset' command looks at this variable
430      to determine what style of commands to output; if it ends in "csh",
431      then C-shell commands are output, else Bourne shell commands. */
432   set_shell_var ();
433
434   /* Make a variable called BASH_VERSION which contains the version info. */
435   bind_variable ("BASH_VERSION", shell_version_string ());
436 #if defined (ARRAY_VARS)
437   make_vers_array ();
438 #endif
439
440   if (command_execution_string)
441     bind_variable ("BASH_EXECUTION_STRING", command_execution_string);
442
443   /* Find out if we're supposed to be in Posix.2 mode via an
444      environment variable. */
445   temp_var = find_variable ("POSIXLY_CORRECT");
446   if (!temp_var)
447     temp_var = find_variable ("POSIX_PEDANTIC");
448   if (temp_var && imported_p (temp_var))
449     sv_strict_posix (temp_var->name);
450
451 #if defined (HISTORY)
452   /* Set history variables to defaults, and then do whatever we would
453      do if the variable had just been set.  Do this only in the case
454      that we are remembering commands on the history list. */
455   if (remember_on_history)
456     {
457       name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
458
459       set_if_not ("HISTFILE", name);
460       free (name);
461
462       set_if_not ("HISTSIZE", "500");
463       sv_histsize ("HISTSIZE");
464     }
465 #endif /* HISTORY */
466
467   /* Seed the random number generator. */
468   sbrand (dollar_dollar_pid + shell_start_time);
469
470   /* Handle some "special" variables that we may have inherited from a
471      parent shell. */
472   if (interactive_shell)
473     {
474       temp_var = find_variable ("IGNOREEOF");
475       if (!temp_var)
476         temp_var = find_variable ("ignoreeof");
477       if (temp_var && imported_p (temp_var))
478         sv_ignoreeof (temp_var->name);
479     }
480
481 #if defined (HISTORY)
482   if (interactive_shell && remember_on_history)
483     {
484       sv_history_control ("HISTCONTROL");
485       sv_histignore ("HISTIGNORE");
486     }
487 #endif /* HISTORY */
488
489      /*
490       * 24 October 2001
491       *
492       * I'm tired of the arguing and bug reports.  Bash now leaves SSH_CLIENT
493       * and SSH2_CLIENT alone.  I'm going to rely on the shell_level check in
494       * isnetconn() to avoid running the startup files more often than wanted.
495       * That will, of course, only work if the user's login shell is bash, so
496       * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
497       * in config-top.h.
498       */
499 #if 0
500   temp_var = find_variable ("SSH_CLIENT");
501   if (temp_var && imported_p (temp_var))
502     {
503       VUNSETATTR (temp_var, att_exported);
504       array_needs_making = 1;
505     }
506   temp_var = find_variable ("SSH2_CLIENT");
507   if (temp_var && imported_p (temp_var))
508     {
509       VUNSETATTR (temp_var, att_exported);
510       array_needs_making = 1;
511     }
512 #endif
513
514   /* Get the user's real and effective user ids. */
515   uidset ();
516
517   /* Initialize the dynamic variables, and seed their values. */
518   initialize_dynamic_variables ();
519 }
520
521 /* **************************************************************** */
522 /*                                                                  */
523 /*           Setting values for special shell variables             */
524 /*                                                                  */
525 /* **************************************************************** */
526
527 static void
528 set_machine_vars ()
529 {
530   SHELL_VAR *temp_var;
531
532   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
533   temp_var = set_if_not ("OSTYPE", OSTYPE);
534   temp_var = set_if_not ("MACHTYPE", MACHTYPE);
535
536   temp_var = set_if_not ("HOSTNAME", current_host_name);
537 }
538
539 /* Set $HOME to the information in the password file if we didn't get
540    it from the environment. */
541
542 /* This function is not static so the tilde and readline libraries can
543    use it. */
544 char *
545 sh_get_home_dir ()
546 {
547   if (current_user.home_dir == 0)
548     get_current_user_info ();
549   return current_user.home_dir;
550 }
551
552 static void
553 set_home_var ()
554 {
555   SHELL_VAR *temp_var;
556
557   temp_var = find_variable ("HOME");
558   if (temp_var == 0)
559     temp_var = bind_variable ("HOME", sh_get_home_dir ());
560 #if 0
561   VSETATTR (temp_var, att_exported);
562 #endif
563 }
564
565 /* Set $SHELL to the user's login shell if it is not already set.  Call
566    get_current_user_info if we haven't already fetched the shell. */
567 static void
568 set_shell_var ()
569 {
570   SHELL_VAR *temp_var;
571
572   temp_var = find_variable ("SHELL");
573   if (temp_var == 0)
574     {
575       if (current_user.shell == 0)
576         get_current_user_info ();
577       temp_var = bind_variable ("SHELL", current_user.shell);
578     }
579 #if 0
580   VSETATTR (temp_var, att_exported);
581 #endif
582 }
583
584 static char *
585 get_bash_name ()
586 {
587   char *name;
588
589   if ((login_shell == 1) && RELPATH(shell_name))
590     {
591       if (current_user.shell == 0)
592         get_current_user_info ();
593       name = savestring (current_user.shell);
594     }
595   else if (ABSPATH(shell_name))
596     name = savestring (shell_name);
597   else if (shell_name[0] == '.' && shell_name[1] == '/')
598     {
599       /* Fast path for common case. */
600       char *cdir;
601       int len;
602
603       cdir = get_string_value ("PWD");
604       if (cdir)
605         {
606           len = strlen (cdir);
607           name = (char *)xmalloc (len + strlen (shell_name) + 1);
608           strcpy (name, cdir);
609           strcpy (name + len, shell_name + 1);
610         }
611       else
612         name = savestring (shell_name);
613     }
614   else
615     {
616       char *tname;
617       int s;
618
619       tname = find_user_command (shell_name);
620
621       if (tname == 0)
622         {
623           /* Try the current directory.  If there is not an executable
624              there, just punt and use the login shell. */
625           s = file_status (shell_name);
626           if (s & FS_EXECABLE)
627             {
628               tname = make_absolute (shell_name, get_string_value ("PWD"));
629               if (*shell_name == '.')
630                 {
631                   name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
632                   if (name == 0)
633                     name = tname;
634                   else
635                     free (tname);
636                 }
637              else
638                 name = tname;
639             }
640           else
641             {
642               if (current_user.shell == 0)
643                 get_current_user_info ();
644               name = savestring (current_user.shell);
645             }
646         }
647       else
648         {
649           name = full_pathname (tname);
650           free (tname);
651         }
652     }
653
654   return (name);
655 }
656
657 void
658 adjust_shell_level (change)
659      int change;
660 {
661   char new_level[5], *old_SHLVL;
662   intmax_t old_level;
663   SHELL_VAR *temp_var;
664
665   old_SHLVL = get_string_value ("SHLVL");
666   if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
667     old_level = 0;
668
669   shell_level = old_level + change;
670   if (shell_level < 0)
671     shell_level = 0;
672   else if (shell_level > 1000)
673     {
674       internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
675       shell_level = 1;
676     }
677
678   /* We don't need the full generality of itos here. */
679   if (shell_level < 10)
680     {
681       new_level[0] = shell_level + '0';
682       new_level[1] = '\0';
683     }
684   else if (shell_level < 100)
685     {
686       new_level[0] = (shell_level / 10) + '0';
687       new_level[1] = (shell_level % 10) + '0';
688       new_level[2] = '\0';
689     }
690   else if (shell_level < 1000)
691     {
692       new_level[0] = (shell_level / 100) + '0';
693       old_level = shell_level % 100;
694       new_level[1] = (old_level / 10) + '0';
695       new_level[2] = (old_level % 10) + '0';
696       new_level[3] = '\0';
697     }
698
699   temp_var = bind_variable ("SHLVL", new_level);
700   set_auto_export (temp_var);
701 }
702
703 static void
704 initialize_shell_level ()
705 {
706   adjust_shell_level (1);
707 }
708
709 /* If we got PWD from the environment, update our idea of the current
710    working directory.  In any case, make sure that PWD exists before
711    checking it.  It is possible for getcwd () to fail on shell startup,
712    and in that case, PWD would be undefined.  If this is an interactive
713    login shell, see if $HOME is the current working directory, and if
714    that's not the same string as $PWD, set PWD=$HOME. */
715
716 void
717 set_pwd ()
718 {
719   SHELL_VAR *temp_var, *home_var;
720   char *temp_string, *home_string;
721
722   home_var = find_variable ("HOME");
723   home_string = home_var ? value_cell (home_var) : (char *)NULL;
724
725   temp_var = find_variable ("PWD");
726   if (temp_var && imported_p (temp_var) &&
727       (temp_string = value_cell (temp_var)) &&
728       same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
729     set_working_directory (temp_string);
730   else if (home_string && interactive_shell && login_shell &&
731            same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
732     {
733       set_working_directory (home_string);
734       temp_var = bind_variable ("PWD", home_string);
735       set_auto_export (temp_var);
736     }
737   else
738     {
739       temp_string = get_working_directory ("shell-init");
740       if (temp_string)
741         {
742           temp_var = bind_variable ("PWD", temp_string);
743           set_auto_export (temp_var);
744           free (temp_string);
745         }
746     }
747
748   /* According to the Single Unix Specification, v2, $OLDPWD is an
749      `environment variable' and therefore should be auto-exported.
750      Make a dummy invisible variable for OLDPWD, and mark it as exported. */
751   temp_var = bind_variable ("OLDPWD", (char *)NULL);
752   VSETATTR (temp_var, (att_exported | att_invisible));
753 }
754
755 /* Make a variable $PPID, which holds the pid of the shell's parent.  */
756 void
757 set_ppid ()
758 {
759   char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
760   SHELL_VAR *temp_var;
761
762   name = inttostr (getppid (), namebuf, sizeof(namebuf));
763   temp_var = find_variable ("PPID");
764   if (temp_var)
765     VUNSETATTR (temp_var, (att_readonly | att_exported));
766   temp_var = bind_variable ("PPID", name);
767   VSETATTR (temp_var, (att_readonly | att_integer));
768 }
769
770 static void
771 uidset ()
772 {
773   char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
774   register SHELL_VAR *v;
775
776   b = inttostr (current_user.uid, buff, sizeof (buff));
777   v = find_variable ("UID");
778   if (v == 0)
779     {
780       v = bind_variable ("UID", b);
781       VSETATTR (v, (att_readonly | att_integer));
782     }
783
784   if (current_user.euid != current_user.uid)
785     b = inttostr (current_user.euid, buff, sizeof (buff));
786
787   v = find_variable ("EUID");
788   if (v == 0)
789     {
790       v = bind_variable ("EUID", b);
791       VSETATTR (v, (att_readonly | att_integer));
792     }
793 }
794
795 #if defined (ARRAY_VARS)
796 static void
797 make_vers_array ()
798 {
799   SHELL_VAR *vv;
800   ARRAY *av;
801   char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
802
803   unbind_variable ("BASH_VERSINFO");
804
805   vv = make_new_array_variable ("BASH_VERSINFO");
806   av = array_cell (vv);
807   strcpy (d, dist_version);
808   s = xstrchr (d, '.');
809   if (s)
810     *s++ = '\0';
811   array_insert (av, 0, d);
812   array_insert (av, 1, s);
813   s = inttostr (patch_level, b, sizeof (b));
814   array_insert (av, 2, s);
815   s = inttostr (build_version, b, sizeof (b));
816   array_insert (av, 3, s);
817   array_insert (av, 4, release_status);
818   array_insert (av, 5, MACHTYPE);
819
820   VSETATTR (vv, att_readonly);
821 }
822 #endif /* ARRAY_VARS */
823
824 /* Set the environment variables $LINES and $COLUMNS in response to
825    a window size change. */
826 void
827 sh_set_lines_and_columns (lines, cols)
828      int lines, cols;
829 {
830   char val[INT_STRLEN_BOUND(int) + 1], *v;
831
832   v = inttostr (lines, val, sizeof (val));
833   bind_variable ("LINES", v);
834
835   v = inttostr (cols, val, sizeof (val));
836   bind_variable ("COLUMNS", v);
837 }
838
839 /* **************************************************************** */
840 /*                                                                  */
841 /*                 Printing variables and values                    */
842 /*                                                                  */
843 /* **************************************************************** */
844
845 /* Print LIST (a list of shell variables) to stdout in such a way that
846    they can be read back in. */
847 void
848 print_var_list (list)
849      register SHELL_VAR **list;
850 {
851   register int i;
852   register SHELL_VAR *var;
853
854   for (i = 0; list && (var = list[i]); i++)
855     if (invisible_p (var) == 0)
856       print_assignment (var);
857 }
858
859 /* Print LIST (a list of shell functions) to stdout in such a way that
860    they can be read back in. */
861 void
862 print_func_list (list)
863      register SHELL_VAR **list;
864 {
865   register int i;
866   register SHELL_VAR *var;
867
868   for (i = 0; list && (var = list[i]); i++)
869     {
870       printf ("%s ", var->name);
871       print_var_function (var);
872       printf ("\n");
873     }
874 }
875       
876 /* Print the value of a single SHELL_VAR.  No newline is
877    output, but the variable is printed in such a way that
878    it can be read back in. */
879 void
880 print_assignment (var)
881      SHELL_VAR *var;
882 {
883   if (var_isset (var) == 0)
884     return;
885
886   if (function_p (var))
887     {
888       printf ("%s", var->name);
889       print_var_function (var);
890       printf ("\n");
891     }
892 #if defined (ARRAY_VARS)
893   else if (array_p (var))
894     print_array_assignment (var, 0);
895 #endif /* ARRAY_VARS */
896   else
897     {
898       printf ("%s=", var->name);
899       print_var_value (var, 1);
900       printf ("\n");
901     }
902 }
903
904 /* Print the value cell of VAR, a shell variable.  Do not print
905    the name, nor leading/trailing newline.  If QUOTE is non-zero,
906    and the value contains shell metacharacters, quote the value
907    in such a way that it can be read back in. */
908 void
909 print_var_value (var, quote)
910      SHELL_VAR *var;
911      int quote;
912 {
913   char *t;
914
915   if (var_isset (var) == 0)
916     return;
917
918   if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
919     {
920       t = ansic_quote (value_cell (var), 0, (int *)0);
921       printf ("%s", t);
922       free (t);
923     }
924   else if (quote && sh_contains_shell_metas (value_cell (var)))
925     {
926       t = sh_single_quote (value_cell (var));
927       printf ("%s", t);
928       free (t);
929     }
930   else
931     printf ("%s", value_cell (var));
932 }
933
934 /* Print the function cell of VAR, a shell variable.  Do not
935    print the name, nor leading/trailing newline. */
936 void
937 print_var_function (var)
938      SHELL_VAR *var;
939 {
940   if (function_p (var) && var_isset (var))
941     printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
942 }
943
944 /* **************************************************************** */
945 /*                                                                  */
946 /*                      Dynamic Variables                           */
947 /*                                                                  */
948 /* **************************************************************** */
949
950 /* DYNAMIC VARIABLES
951
952    These are variables whose values are generated anew each time they are
953    referenced.  These are implemented using a pair of function pointers
954    in the struct variable: assign_func, which is called from bind_variable
955    and, if arrays are compiled into the shell, some of the functions in
956    arrayfunc.c, and dynamic_value, which is called from find_variable.
957
958    assign_func is called from bind_variable_internal, if
959    bind_variable_internal discovers that the variable being assigned to
960    has such a function.  The function is called as
961         SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
962    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
963    is usually ENTRY (self).  IND is an index for an array variable, and
964    unused otherwise.
965
966    dynamic_value is called from find_variable_internal to return a `new'
967    value for the specified dynamic varible.  If this function is NULL,
968    the variable is treated as a `normal' shell variable.  If it is not,
969    however, then this function is called like this:
970         tempvar = (*(var->dynamic_value)) (var);
971
972    Sometimes `tempvar' will replace the value of `var'.  Other times, the
973    shell will simply use the string value.  Pretty object-oriented, huh?
974
975    Be warned, though: if you `unset' a special variable, it loses its
976    special meaning, even if you subsequently set it.
977
978    The special assignment code would probably have been better put in
979    subst.c: do_assignment_internal, in the same style as
980    stupidly_hack_special_variables, but I wanted the changes as
981    localized as possible.  */
982
983 #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
984   do \
985     { \
986       v = bind_variable (var, (val)); \
987       v->dynamic_value = gfunc; \
988       v->assign_func = afunc; \
989     } \
990   while (0)
991
992 #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
993   do \
994     { \
995       v = make_new_array_variable (var); \
996       v->dynamic_value = gfunc; \
997       v->assign_func = afunc; \
998     } \
999   while (0)
1000
1001 static SHELL_VAR *
1002 null_assign (self, value, unused)
1003      SHELL_VAR *self;
1004      char *value;
1005      arrayind_t unused;
1006 {
1007   return (self);
1008 }
1009
1010 #if defined (ARRAY_VARS)
1011 static SHELL_VAR *
1012 null_array_assign (self, value, ind)
1013      SHELL_VAR *self;
1014      char *value;
1015      arrayind_t ind;
1016 {
1017   return (self);
1018 }
1019 #endif
1020
1021 /* Degenerate `dynamic_value' function; just returns what's passed without
1022    manipulation. */
1023 static SHELL_VAR *
1024 get_self (self)
1025      SHELL_VAR *self;
1026 {
1027   return (self);
1028 }
1029
1030 #if defined (ARRAY_VARS)
1031 /* A generic dynamic array variable initializer.  Intialize array variable
1032    NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1033 static SHELL_VAR *
1034 init_dynamic_array_var (name, getfunc, setfunc, attrs)
1035      char *name;
1036      sh_var_value_func_t *getfunc;
1037      sh_var_assign_func_t *setfunc;
1038      int attrs;
1039 {
1040   SHELL_VAR *v;
1041
1042   v = find_variable (name);
1043   if (v)
1044     return (v);
1045   INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1046   if (attrs)
1047     VSETATTR (v, attrs);
1048   return v;
1049 }
1050 #endif
1051
1052
1053 /* The value of $SECONDS.  This is the number of seconds since shell
1054    invocation, or, the number of seconds since the last assignment + the
1055    value of the last assignment. */
1056 static intmax_t seconds_value_assigned;
1057
1058 static SHELL_VAR *
1059 assign_seconds (self, value, unused)
1060      SHELL_VAR *self;
1061      char *value;
1062      arrayind_t unused;
1063 {
1064   if (legal_number (value, &seconds_value_assigned) == 0)
1065     seconds_value_assigned = 0;
1066   shell_start_time = NOW;
1067   return (self);
1068 }
1069
1070 static SHELL_VAR *
1071 get_seconds (var)
1072      SHELL_VAR *var;
1073 {
1074   time_t time_since_start;
1075   char *p;
1076
1077   time_since_start = NOW - shell_start_time;
1078   p = itos(seconds_value_assigned + time_since_start);
1079
1080   FREE (value_cell (var));
1081
1082   VSETATTR (var, att_integer);
1083   var_setvalue (var, p);
1084   return (var);
1085 }
1086
1087 static SHELL_VAR *
1088 init_seconds_var ()
1089 {
1090   SHELL_VAR *v;
1091
1092   v = find_variable ("SECONDS");
1093   if (v)
1094     {
1095       if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1096         seconds_value_assigned = 0;
1097     }
1098   INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
1099   return v;      
1100 }
1101      
1102 /* The random number seed.  You can change this by setting RANDOM. */
1103 static unsigned long rseed = 1;
1104 static int last_random_value;
1105
1106 /* A linear congruential random number generator based on the example
1107    one in the ANSI C standard.  This one isn't very good, but a more
1108    complicated one is overkill. */
1109
1110 /* Returns a pseudo-random number between 0 and 32767. */
1111 static int
1112 brand ()
1113 {
1114   rseed = rseed * 1103515245 + 12345;
1115   return ((unsigned int)((rseed >> 16) & 32767));       /* was % 32768 */
1116 }
1117
1118 /* Set the random number generator seed to SEED. */
1119 static void
1120 sbrand (seed)
1121      unsigned long seed;
1122 {
1123   rseed = seed;
1124   last_random_value = 0;
1125 }
1126
1127 static SHELL_VAR *
1128 assign_random (self, value, unused)
1129      SHELL_VAR *self;
1130      char *value;
1131      arrayind_t unused;
1132 {
1133   sbrand (strtoul (value, (char **)NULL, 10));
1134   return (self);
1135 }
1136
1137 int
1138 get_random_number ()
1139 {
1140   int rv;
1141
1142   /* Reset for command and process substitution. */
1143   if (subshell_environment)
1144     sbrand (rseed + getpid() + NOW);
1145
1146   do
1147     rv = brand ();
1148   while (rv == last_random_value);
1149   return rv;
1150 }
1151
1152 static SHELL_VAR *
1153 get_random (var)
1154      SHELL_VAR *var;
1155 {
1156   int rv;
1157   char *p;
1158
1159   rv = get_random_number ();
1160   last_random_value = rv;
1161   p = itos (rv);
1162
1163   FREE (value_cell (var));
1164
1165   VSETATTR (var, att_integer);
1166   var_setvalue (var, p);
1167   return (var);
1168 }
1169
1170 static SHELL_VAR *
1171 assign_lineno (var, value, unused)
1172      SHELL_VAR *var;
1173      char *value;
1174      arrayind_t unused;
1175 {
1176   intmax_t new_value;
1177
1178   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1179     new_value = 0;
1180   line_number = new_value;
1181   return var;
1182 }
1183
1184 /* Function which returns the current line number. */
1185 static SHELL_VAR *
1186 get_lineno (var)
1187      SHELL_VAR *var;
1188 {
1189   char *p;
1190   int ln;
1191
1192   ln = executing_line_number ();
1193   p = itos (ln);
1194   FREE (value_cell (var));
1195   var_setvalue (var, p);
1196   return (var);
1197 }
1198
1199 static SHELL_VAR *
1200 assign_subshell (var, value, unused)
1201      SHELL_VAR *var;
1202      char *value;
1203      arrayind_t unused;
1204 {
1205   intmax_t new_value;
1206
1207   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1208     new_value = 0;
1209   subshell_level = new_value;
1210   return var;
1211 }
1212
1213 static SHELL_VAR *
1214 get_subshell (var)
1215      SHELL_VAR *var;
1216 {
1217   char *p;
1218
1219   p = itos (subshell_level);
1220   FREE (value_cell (var));
1221   var_setvalue (var, p);
1222   return (var);
1223 }
1224
1225 static SHELL_VAR *
1226 get_bash_command (var)
1227      SHELL_VAR *var;
1228 {
1229   char *p;
1230
1231   p = savestring (the_printed_command_except_trap);
1232   FREE (value_cell (var));
1233   var_setvalue (var, p);
1234   return (var);
1235 }
1236
1237 #if defined (HISTORY)
1238 static SHELL_VAR *
1239 get_histcmd (var)
1240      SHELL_VAR *var;
1241 {
1242   char *p;
1243
1244   p = itos (history_number ());
1245   FREE (value_cell (var));
1246   var_setvalue (var, p);
1247   return (var);
1248 }
1249 #endif
1250
1251 #if defined (READLINE)
1252 /* When this function returns, VAR->value points to malloced memory. */
1253 static SHELL_VAR *
1254 get_comp_wordbreaks (var)
1255      SHELL_VAR *var;
1256 {
1257   char *p;
1258
1259   /* If we don't have anything yet, assign a default value. */
1260   if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1261     enable_hostname_completion (perform_hostname_completion);
1262
1263 #if 0
1264   FREE (value_cell (var));
1265   p = savestring (rl_completer_word_break_characters);
1266   
1267   var_setvalue (var, p);
1268 #else
1269   var_setvalue (var, rl_completer_word_break_characters);
1270 #endif
1271
1272   return (var);
1273 }
1274
1275 /* When this function returns, rl_completer_word_break_characters points to
1276    malloced memory. */
1277 static SHELL_VAR *
1278 assign_comp_wordbreaks (self, value, unused)
1279      SHELL_VAR *self;
1280      char *value;
1281      arrayind_t unused;
1282 {
1283   if (rl_completer_word_break_characters &&
1284       rl_completer_word_break_characters != rl_basic_word_break_characters)
1285     free (rl_completer_word_break_characters);
1286
1287   rl_completer_word_break_characters = savestring (value);
1288   return self;
1289 }
1290 #endif /* READLINE */
1291
1292 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1293 static SHELL_VAR *
1294 assign_dirstack (self, value, ind)
1295      SHELL_VAR *self;
1296      char *value;
1297      arrayind_t ind;
1298 {
1299   set_dirstack_element (ind, 1, value);
1300   return self;
1301 }
1302
1303 static SHELL_VAR *
1304 get_dirstack (self)
1305      SHELL_VAR *self;
1306 {
1307   ARRAY *a;
1308   WORD_LIST *l;
1309
1310   l = get_directory_stack ();
1311   a = array_from_word_list (l);
1312   array_dispose (array_cell (self));
1313   dispose_words (l);
1314   var_setarray (self, a);
1315   return self;
1316 }
1317 #endif /* PUSHD AND POPD && ARRAY_VARS */
1318
1319 #if defined (ARRAY_VARS)
1320 /* We don't want to initialize the group set with a call to getgroups()
1321    unless we're asked to, but we only want to do it once. */
1322 static SHELL_VAR *
1323 get_groupset (self)
1324      SHELL_VAR *self;
1325 {
1326   register int i;
1327   int ng;
1328   ARRAY *a;
1329   static char **group_set = (char **)NULL;
1330
1331   if (group_set == 0)
1332     {
1333       group_set = get_group_list (&ng);
1334       a = array_cell (self);
1335       for (i = 0; i < ng; i++)
1336         array_insert (a, i, group_set[i]);
1337     }
1338   return (self);
1339 }
1340 #endif /* ARRAY_VARS */
1341
1342 /* If ARRAY_VARS is not defined, this just returns the name of any
1343    currently-executing function.  If we have arrays, it's a call stack. */
1344 static SHELL_VAR *
1345 get_funcname (self)
1346      SHELL_VAR *self;
1347 {
1348 #if ! defined (ARRAY_VARS)
1349   char *t;
1350   if (variable_context && this_shell_function)
1351     {
1352       FREE (value_cell (self));
1353       t = savestring (this_shell_function->name);
1354       var_setvalue (self, t);
1355     }
1356 #endif
1357   return (self);
1358 }
1359
1360 void
1361 make_funcname_visible (on_or_off)
1362      int on_or_off;
1363 {
1364   SHELL_VAR *v;
1365
1366   v = find_variable ("FUNCNAME");
1367   if (v == 0 || v->dynamic_value == 0)
1368     return;
1369
1370   if (on_or_off)
1371     VUNSETATTR (v, att_invisible);
1372   else
1373     VSETATTR (v, att_invisible);
1374 }
1375
1376 static SHELL_VAR *
1377 init_funcname_var ()
1378 {
1379   SHELL_VAR *v;
1380
1381   v = find_variable ("FUNCNAME");
1382   if (v)
1383     return v;
1384 #if defined (ARRAY_VARS)
1385   INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1386 #else
1387   INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1388 #endif
1389   VSETATTR (v, att_invisible|att_noassign);
1390   return v;
1391 }
1392
1393 static void
1394 initialize_dynamic_variables ()
1395 {
1396   SHELL_VAR *v;
1397
1398   v = init_seconds_var ();
1399
1400   INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1401   INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1402
1403   INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1404   INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1405
1406 #if defined (HISTORY)
1407   INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
1408 #endif
1409
1410 #if defined (READLINE)
1411   INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1412 #endif
1413
1414 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1415   v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
1416 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1417
1418 #if defined (ARRAY_VARS)
1419   v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1420
1421 #  if defined (DEBUGGER)
1422   v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, (att_invisible|att_noassign));
1423   v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, (att_invisible|att_noassign));
1424 #  endif /* DEBUGGER */
1425   v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, (att_invisible|att_noassign));
1426   v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, (att_invisible|att_noassign));
1427 #endif
1428
1429   v = init_funcname_var ();
1430 }
1431
1432 /* **************************************************************** */
1433 /*                                                                  */
1434 /*              Retrieving variables and values                     */
1435 /*                                                                  */
1436 /* **************************************************************** */
1437
1438 /* How to get a pointer to the shell variable or function named NAME.
1439    HASHED_VARS is a pointer to the hash table containing the list
1440    of interest (either variables or functions). */
1441
1442 static SHELL_VAR *
1443 hash_lookup (name, hashed_vars)
1444      const char *name;
1445      HASH_TABLE *hashed_vars;
1446 {
1447   BUCKET_CONTENTS *bucket;
1448
1449   bucket = hash_search (name, hashed_vars, 0);
1450   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1451 }
1452
1453 SHELL_VAR *
1454 var_lookup (name, vcontext)
1455      const char *name;
1456      VAR_CONTEXT *vcontext;
1457 {
1458   VAR_CONTEXT *vc;
1459   SHELL_VAR *v;
1460
1461   v = (SHELL_VAR *)NULL;
1462   for (vc = vcontext; vc; vc = vc->down)
1463     if (v = hash_lookup (name, vc->table))
1464       break;
1465
1466   return v;
1467 }
1468
1469 /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
1470    then also search the temporarily built list of exported variables.
1471    The lookup order is:
1472         temporary_env
1473         shell_variables list
1474 */
1475
1476 SHELL_VAR *
1477 find_variable_internal (name, force_tempenv)
1478      const char *name;
1479      int force_tempenv;
1480 {
1481   SHELL_VAR *var;
1482   int search_tempenv;
1483
1484   var = (SHELL_VAR *)NULL;
1485
1486   /* If explicitly requested, first look in the temporary environment for
1487      the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
1488      to get the `exported' value of $foo.  This happens if we are executing
1489      a function or builtin, or if we are looking up a variable in a
1490      "subshell environment". */
1491   search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1492
1493   if (search_tempenv && temporary_env)          
1494     var = hash_lookup (name, temporary_env);
1495
1496   if (var == 0)
1497     var = var_lookup (name, shell_variables);
1498
1499   if (var == 0)
1500     return ((SHELL_VAR *)NULL);
1501
1502   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1503 }
1504
1505 /* Look up the variable entry named NAME.  Returns the entry or NULL. */
1506 SHELL_VAR *
1507 find_variable (name)
1508      const char *name;
1509 {
1510   return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
1511 }
1512
1513 /* Look up the function entry whose name matches STRING.
1514    Returns the entry or NULL. */
1515 SHELL_VAR *
1516 find_function (name)
1517      const char *name;
1518 {
1519   return (hash_lookup (name, shell_functions));
1520 }
1521
1522 /* Find the function definition for the shell function named NAME.  Returns
1523    the entry or NULL. */
1524 FUNCTION_DEF *
1525 find_function_def (name)
1526      const char *name;
1527 {
1528   return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
1529 }
1530
1531 /* Return the value of VAR.  VAR is assumed to have been the result of a
1532    lookup without any subscript, if arrays are compiled into the shell. */
1533 char *
1534 get_variable_value (var)
1535      SHELL_VAR *var;
1536 {
1537   if (var == 0)
1538     return ((char *)NULL);
1539 #if defined (ARRAY_VARS)
1540   else if (array_p (var))
1541     return (array_reference (array_cell (var), 0));
1542 #endif
1543   else
1544     return (value_cell (var));
1545 }
1546
1547 /* Return the string value of a variable.  Return NULL if the variable
1548    doesn't exist.  Don't cons a new string.  This is a potential memory
1549    leak if the variable is found in the temporary environment.  Since
1550    functions and variables have separate name spaces, returns NULL if
1551    var_name is a shell function only. */
1552 char *
1553 get_string_value (var_name)
1554      const char *var_name;
1555 {
1556   SHELL_VAR *var;
1557
1558   var = find_variable (var_name);
1559   return ((var) ? get_variable_value (var) : (char *)NULL);
1560 }
1561
1562 /* This is present for use by the tilde and readline libraries. */
1563 char *
1564 sh_get_env_value (v)
1565      const char *v;
1566 {
1567   return get_string_value (v);
1568 }
1569
1570 /* **************************************************************** */
1571 /*                                                                  */
1572 /*                Creating and setting variables                    */
1573 /*                                                                  */
1574 /* **************************************************************** */
1575
1576 /* Set NAME to VALUE if NAME has no value. */
1577 SHELL_VAR *
1578 set_if_not (name, value)
1579      char *name, *value;
1580 {
1581   SHELL_VAR *v;
1582
1583   v = find_variable (name);
1584   if (v == 0)
1585     v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH);
1586   return (v);
1587 }
1588
1589 /* Create a local variable referenced by NAME. */
1590 SHELL_VAR *
1591 make_local_variable (name)
1592      const char *name;
1593 {
1594   SHELL_VAR *new_var, *old_var;
1595   VAR_CONTEXT *vc;
1596   int was_tmpvar;
1597   char *tmp_value;
1598
1599   /* local foo; local foo;  is a no-op. */
1600   old_var = find_variable (name);
1601   if (old_var && local_p (old_var) && old_var->context == variable_context)
1602     return (old_var);
1603
1604   was_tmpvar = old_var && tempvar_p (old_var);
1605   if (was_tmpvar)
1606     tmp_value = value_cell (old_var);
1607
1608   for (vc = shell_variables; vc; vc = vc->down)
1609     if (vc_isfuncenv (vc) && vc->scope == variable_context)
1610       break;
1611
1612   if (vc == 0)
1613     {
1614       internal_error (_("make_local_variable: no function context at current scope"));
1615       return ((SHELL_VAR *)NULL);
1616     }
1617   else if (vc->table == 0)
1618     vc->table = hash_create (TEMPENV_HASH_BUCKETS);
1619
1620   /* Since this is called only from the local/declare/typeset code, we can
1621      call builtin_error here without worry (of course, it will also work
1622      for anything that sets this_command_name).  Variables with the `noassign'
1623      attribute may not be made local.  The test against old_var's context
1624      level is to disallow local copies of readonly global variables (since I
1625      believe that this could be a security hole).  Readonly copies of calling
1626      function local variables are OK. */
1627   if (old_var && (noassign_p (old_var) ||
1628                  (readonly_p (old_var) && old_var->context == 0)))
1629     {
1630       if (readonly_p (old_var))
1631         sh_readonly (name);
1632       return ((SHELL_VAR *)NULL);
1633     }
1634
1635   if (old_var == 0)
1636     new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH);
1637   else
1638     {
1639       new_var = make_new_variable (name, vc->table);
1640
1641       /* If we found this variable in one of the temporary environments,
1642          inherit its value.  Watch to see if this causes problems with
1643          things like `x=4 local x'. */
1644       if (was_tmpvar)
1645         var_setvalue (new_var, savestring (tmp_value));
1646
1647       new_var->attributes = exported_p (old_var) ? att_exported : 0;
1648     }
1649
1650   vc->flags |= VC_HASLOCAL;
1651
1652   new_var->context = variable_context;
1653   VSETATTR (new_var, att_local);
1654
1655   if (ifsname (name))
1656     setifs (new_var);
1657
1658   return (new_var);
1659 }
1660
1661 #if defined (ARRAY_VARS)
1662 SHELL_VAR *
1663 make_local_array_variable (name)
1664      char *name;
1665 {
1666   SHELL_VAR *var;
1667   ARRAY *array;
1668
1669   var = make_local_variable (name);
1670   if (var == 0 || array_p (var))
1671     return var;
1672
1673   array = array_create ();
1674
1675   FREE (value_cell(var));
1676   var_setarray (var, array);
1677   VSETATTR (var, att_array);
1678   return var;
1679 }
1680 #endif /* ARRAY_VARS */
1681
1682 /* Create a new shell variable with name NAME. */
1683 static SHELL_VAR *
1684 new_shell_variable (name)
1685      const char *name;
1686 {
1687   SHELL_VAR *entry;
1688
1689   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1690
1691   entry->name = savestring (name);
1692   var_setvalue (entry, (char *)NULL);
1693   CLEAR_EXPORTSTR (entry);
1694
1695   entry->dynamic_value = (sh_var_value_func_t *)NULL;
1696   entry->assign_func = (sh_var_assign_func_t *)NULL;
1697
1698   entry->attributes = 0;
1699
1700   /* Always assume variables are to be made at toplevel!
1701      make_local_variable has the responsibilty of changing the
1702      variable context. */
1703   entry->context = 0;
1704
1705   return (entry);
1706 }
1707
1708 /* Create a new shell variable with name NAME and add it to the hash table
1709    TABLE. */
1710 static SHELL_VAR *
1711 make_new_variable (name, table)
1712      const char *name;
1713      HASH_TABLE *table;
1714 {
1715   SHELL_VAR *entry;
1716   BUCKET_CONTENTS *elt;
1717
1718   entry = new_shell_variable (name);
1719
1720   /* Make sure we have a shell_variables hash table to add to. */
1721   if (shell_variables == 0)
1722     {
1723       shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1724       shell_variables->scope = 0;
1725       shell_variables->table = hash_create (0);
1726     }
1727
1728   elt = hash_insert (savestring (name), table, HASH_NOSRCH);
1729   elt->data = (PTR_T)entry;
1730
1731   return entry;
1732 }
1733
1734 #if defined (ARRAY_VARS)
1735 SHELL_VAR *
1736 make_new_array_variable (name)
1737      char *name;
1738 {
1739   SHELL_VAR *entry;
1740   ARRAY *array;
1741
1742   entry = make_new_variable (name, global_variables->table);
1743   array = array_create ();
1744   var_setarray (entry, array);
1745   VSETATTR (entry, att_array);
1746   return entry;
1747 }
1748 #endif
1749
1750 char *
1751 make_variable_value (var, value)
1752      SHELL_VAR *var;
1753      char *value;
1754 {
1755   char *retval;
1756   intmax_t lval;
1757   int expok;
1758
1759   /* If this variable has had its type set to integer (via `declare -i'),
1760      then do expression evaluation on it and store the result.  The
1761      functions in expr.c (evalexp()) and bind_int_variable() are responsible
1762      for turning off the integer flag if they don't want further
1763      evaluation done. */
1764   if (integer_p (var))
1765     {
1766       lval = evalexp (value, &expok);
1767       if (expok == 0)
1768         jump_to_top_level (DISCARD);
1769       retval = itos (lval);
1770     }
1771   else if (value)
1772     {
1773       if (*value)
1774         retval = savestring (value);
1775       else
1776         {
1777           retval = (char *)xmalloc (1);
1778           retval[0] = '\0';
1779         }
1780     }
1781   else
1782     retval = (char *)NULL;
1783
1784   return retval;
1785 }
1786
1787 /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
1788    temporary environment (but usually is not). */
1789 static SHELL_VAR *
1790 bind_variable_internal (name, value, table, hflags)
1791      const char *name;
1792      char *value;
1793      HASH_TABLE *table;
1794      int hflags;
1795 {
1796   char *newval;
1797   SHELL_VAR *entry;
1798
1799   entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
1800
1801   if (entry == 0)
1802     {
1803       entry = make_new_variable (name, table);
1804       var_setvalue (entry, make_variable_value (entry, value));
1805     }
1806   else if (entry->assign_func)  /* array vars have assign functions now */
1807     {
1808       INVALIDATE_EXPORTSTR (entry);
1809       return ((*(entry->assign_func)) (entry, value, -1));
1810     }
1811   else
1812     {
1813       if (readonly_p (entry) || noassign_p (entry))
1814         {
1815           if (readonly_p (entry))
1816             err_readonly (name);
1817           return (entry);
1818         }
1819
1820       /* Variables which are bound are visible. */
1821       VUNSETATTR (entry, att_invisible);
1822
1823       newval = make_variable_value (entry, value);
1824
1825       /* Invalidate any cached export string */
1826       INVALIDATE_EXPORTSTR (entry);
1827
1828 #if defined (ARRAY_VARS)
1829       /* XXX -- this bears looking at again -- XXX */
1830       /* If an existing array variable x is being assigned to with x=b or
1831          `read x' or something of that nature, silently convert it to
1832          x[0]=b or `read x[0]'. */
1833       if (array_p (entry))
1834         {
1835           array_insert (array_cell (entry), 0, newval);
1836           free (newval);
1837         }
1838       else
1839 #endif
1840         {
1841           FREE (value_cell (entry));
1842           var_setvalue (entry, newval);
1843         }
1844     }
1845
1846   if (mark_modified_vars)
1847     VSETATTR (entry, att_exported);
1848
1849   if (exported_p (entry))
1850     array_needs_making = 1;
1851
1852   return (entry);
1853 }
1854         
1855 /* Bind a variable NAME to VALUE.  This conses up the name
1856    and value strings.  If we have a temporary environment, we bind there
1857    first, then we bind into shell_variables. */
1858
1859 SHELL_VAR *
1860 bind_variable (name, value)
1861      const char *name;
1862      char *value;
1863 {
1864   SHELL_VAR *v;
1865   VAR_CONTEXT *vc;
1866
1867   if (shell_variables == 0)
1868     {
1869       shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1870       shell_variables->scope = 0;
1871       shell_variables->table = hash_create (0);
1872     }
1873
1874   /* If we have a temporary environment, look there first for the variable,
1875      and, if found, modify the value there before modifying it in the
1876      shell_variables table.  This allows sourced scripts to modify values
1877      given to them in a temporary environment while modifying the variable
1878      value that the caller sees. */
1879   if (temporary_env)
1880     bind_tempenv_variable (name, value);
1881
1882   /* XXX -- handle local variables here. */
1883   for (vc = shell_variables; vc; vc = vc->down)
1884     {
1885       if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
1886         {
1887           v = hash_lookup (name, vc->table);
1888           if (v)
1889             return (bind_variable_internal (name, value, vc->table, 0));
1890         }
1891     }
1892   return (bind_variable_internal (name, value, global_variables->table, 0));
1893 }
1894
1895 /* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
1896    value, variables are no longer invisible.  This is a duplicate of part
1897    of the internals of bind_variable.  If the variable is exported, or
1898    all modified variables should be exported, mark the variable for export
1899    and note that the export environment needs to be recreated. */
1900 SHELL_VAR *
1901 bind_variable_value (var, value)
1902      SHELL_VAR *var;
1903      char *value;
1904 {
1905   char *t;
1906
1907   VUNSETATTR (var, att_invisible);
1908
1909   t = make_variable_value (var, value);
1910   FREE (value_cell (var));
1911   var_setvalue (var, t);
1912
1913   INVALIDATE_EXPORTSTR (var);
1914
1915   if (mark_modified_vars)
1916     VSETATTR (var, att_exported);
1917
1918   if (exported_p (var))
1919     array_needs_making = 1;
1920
1921   return (var);
1922 }
1923
1924 /* Bind/create a shell variable with the name LHS to the RHS.
1925    This creates or modifies a variable such that it is an integer.
1926
1927    This used to be in expr.c, but it is here so that all of the
1928    variable binding stuff is localized.  Since we don't want any
1929    recursive evaluation from bind_variable() (possible without this code,
1930    since bind_variable() calls the evaluator for variables with the integer
1931    attribute set), we temporarily turn off the integer attribute for each
1932    variable we set here, then turn it back on after binding as necessary. */
1933
1934 SHELL_VAR *
1935 bind_int_variable (lhs, rhs)
1936      char *lhs, *rhs;
1937 {
1938   register SHELL_VAR *v;
1939   char *t;
1940   int isint, isarr;
1941
1942   isint = isarr = 0;
1943 #if defined (ARRAY_VARS)
1944 #  if 0
1945   if (t = xstrchr (lhs, '['))   /*]*/
1946 #  else
1947   if (valid_array_reference (lhs))
1948 #  endif
1949     {
1950       isarr = 1;
1951       v = array_variable_part (lhs, (char **)0, (int *)0);
1952     }
1953   else
1954 #endif
1955     v = find_variable (lhs);
1956
1957   if (v)
1958     {
1959       isint = integer_p (v);
1960       VUNSETATTR (v, att_integer);
1961     }
1962
1963 #if defined (ARRAY_VARS)
1964   if (isarr)
1965     v = assign_array_element (lhs, rhs);
1966   else
1967 #endif
1968     v = bind_variable (lhs, rhs);
1969
1970   if (isint)
1971     VSETATTR (v, att_integer);
1972
1973   return (v);
1974 }
1975
1976 SHELL_VAR *
1977 bind_var_to_int (var, val)
1978      char *var;
1979      intmax_t val;
1980 {
1981   char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
1982
1983   p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
1984   return (bind_int_variable (var, p));
1985 }
1986
1987 /* Do a function binding to a variable.  You pass the name and
1988    the command to bind to.  This conses the name and command. */
1989 SHELL_VAR *
1990 bind_function (name, value)
1991      const char *name;
1992      COMMAND *value;
1993 {
1994   SHELL_VAR *entry;
1995
1996   entry = find_function (name);
1997   if (entry == 0)
1998     {
1999       BUCKET_CONTENTS *elt;
2000
2001       elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2002       entry = new_shell_variable (name);
2003       elt->data = (PTR_T)entry;
2004     }
2005   else
2006     INVALIDATE_EXPORTSTR (entry);
2007
2008   if (var_isset (entry))
2009     dispose_command (function_cell (entry));
2010
2011   if (value)
2012     var_setfunc (entry, copy_command (value));
2013   else
2014     var_setfunc (entry, 0);
2015
2016   VSETATTR (entry, att_function);
2017
2018   if (mark_modified_vars)
2019     VSETATTR (entry, att_exported);
2020
2021   VUNSETATTR (entry, att_invisible);            /* Just to be sure */
2022
2023   if (exported_p (entry))
2024     array_needs_making = 1;
2025
2026 #if defined (PROGRAMMABLE_COMPLETION)
2027   set_itemlist_dirty (&it_functions);
2028 #endif
2029
2030   return (entry);
2031 }
2032
2033 /* Bind a function definition, which includes source file and line number
2034    information in addition to the command, into the FUNCTION_DEF hash table.*/
2035 void
2036 bind_function_def (name, value)
2037      const char *name;
2038      FUNCTION_DEF *value;
2039 {
2040   FUNCTION_DEF *entry;
2041   BUCKET_CONTENTS *elt;
2042   COMMAND *cmd;
2043
2044   entry = find_function_def (name);
2045   if (entry)
2046     {
2047       dispose_function_def_contents (entry);
2048       entry = copy_function_def_contents (value, entry);
2049     }
2050   else
2051     {
2052       cmd = value->command;
2053       value->command = 0;
2054       entry = copy_function_def (value);
2055       value->command = cmd;
2056
2057       elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2058       elt->data = (PTR_T *)entry;
2059     }
2060 }
2061
2062 /* Add STRING, which is of the form foo=bar, to the temporary environment
2063    HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
2064    responsible for moving the main temporary env to one of the other
2065    temporary environments.  The expansion code in subst.c calls this. */
2066 int
2067 assign_in_env (string)
2068      const char *string;
2069 {
2070   int offset;
2071   char *name, *temp, *value;
2072   SHELL_VAR *var;
2073
2074   offset = assignment (string, 0);
2075   name = savestring (string);
2076   value = (char *)NULL;
2077
2078   if (name[offset] == '=')
2079     {
2080       name[offset] = 0;
2081
2082       var = find_variable (name);
2083       if (var && (readonly_p (var) || noassign_p (var)))
2084         {
2085           if (readonly_p (var))
2086             err_readonly (name);
2087           free (name);
2088           return (0);
2089         }
2090
2091       temp = name + offset + 1;
2092       temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
2093
2094       value = expand_string_unsplit_to_string (temp, 0);
2095       free (temp);
2096     }
2097
2098   if (temporary_env == 0)
2099     temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2100
2101   var = hash_lookup (name, temporary_env);
2102   if (var == 0)
2103     var = make_new_variable (name, temporary_env);
2104   else
2105     FREE (value_cell (var));
2106
2107   if (value == 0)
2108     {
2109       value = (char *)xmalloc (1);      /* like do_assignment_internal */
2110       value[0] = '\0';
2111     }
2112
2113   var_setvalue (var, value);
2114   var->attributes |= (att_exported|att_tempvar);
2115   var->context = variable_context;      /* XXX */
2116
2117   INVALIDATE_EXPORTSTR (var);
2118   var->exportstr = mk_env_string (name, value);
2119
2120   array_needs_making = 1;
2121
2122   if (ifsname (name))
2123     setifs (var);
2124
2125   if (echo_command_at_execute)
2126     /* The Korn shell prints the `+ ' in front of assignment statements,
2127         so we do too. */
2128     xtrace_print_assignment (name, value, 0, 1);
2129
2130   free (name);
2131   return 1;
2132 }
2133
2134 /* **************************************************************** */
2135 /*                                                                  */
2136 /*                      Copying variables                           */
2137 /*                                                                  */
2138 /* **************************************************************** */
2139
2140 #ifdef INCLUDE_UNUSED
2141 /* Copy VAR to a new data structure and return that structure. */
2142 SHELL_VAR *
2143 copy_variable (var)
2144      SHELL_VAR *var;
2145 {
2146   SHELL_VAR *copy = (SHELL_VAR *)NULL;
2147
2148   if (var)
2149     {
2150       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2151
2152       copy->attributes = var->attributes;
2153       copy->name = savestring (var->name);
2154
2155       if (function_p (var))
2156         var_setfunc (copy, copy_command (function_cell (var)));
2157 #if defined (ARRAY_VARS)
2158       else if (array_p (var))
2159         var_setarray (copy, dup_array (array_cell (var)));
2160 #endif
2161       else if (value_cell (var))
2162         var_setvalue (copy, savestring (value_cell (var)));
2163       else
2164         var_setvalue (copy, (char *)NULL);
2165
2166       copy->dynamic_value = var->dynamic_value;
2167       copy->assign_func = var->assign_func;
2168
2169       copy->exportstr = COPY_EXPORTSTR (var);
2170
2171       copy->context = var->context;
2172     }
2173   return (copy);
2174 }
2175 #endif
2176
2177 /* **************************************************************** */
2178 /*                                                                  */
2179 /*                Deleting and unsetting variables                  */
2180 /*                                                                  */
2181 /* **************************************************************** */
2182
2183 /* Dispose of the information attached to VAR. */
2184 void
2185 dispose_variable (var)
2186      SHELL_VAR *var;
2187 {
2188   if (var == 0)
2189     return;
2190
2191   if (function_p (var))
2192     dispose_command (function_cell (var));
2193 #if defined (ARRAY_VARS)
2194   else if (array_p (var))
2195     array_dispose (array_cell (var));
2196 #endif
2197   else
2198     FREE (value_cell (var));
2199
2200   FREE_EXPORTSTR (var);
2201
2202   free (var->name);
2203
2204   if (exported_p (var))
2205     array_needs_making = 1;
2206
2207   free (var);
2208 }
2209
2210 /* Unset the shell variable referenced by NAME. */
2211 int
2212 unbind_variable (name)
2213      const char *name;
2214 {
2215   return makunbound (name, shell_variables);
2216 }
2217
2218 /* Unset the shell function named NAME. */
2219 int
2220 unbind_func (name)
2221      const char *name;
2222 {
2223   BUCKET_CONTENTS *elt;
2224   SHELL_VAR *func;
2225
2226   elt = hash_remove (name, shell_functions, 0);
2227
2228   if (elt == 0)
2229     return -1;
2230
2231 #if defined (PROGRAMMABLE_COMPLETION)
2232   set_itemlist_dirty (&it_functions);
2233 #endif
2234
2235   func = (SHELL_VAR *)elt->data;
2236   if (func)
2237     {
2238       if (exported_p (func))
2239         array_needs_making++;
2240       dispose_variable (func);
2241     }
2242
2243   free (elt->key);
2244   free (elt);
2245
2246   return 0;  
2247 }
2248
2249 int
2250 unbind_function_def (name)
2251      const char *name;
2252 {
2253   BUCKET_CONTENTS *elt;
2254   FUNCTION_DEF *funcdef;
2255
2256   elt = hash_remove (name, shell_function_defs, 0);
2257
2258   if (elt == 0)
2259     return -1;
2260
2261   funcdef = (FUNCTION_DEF *)elt->data;
2262   if (funcdef)
2263     dispose_function_def (funcdef);
2264
2265   free (elt->key);
2266   free (elt);
2267
2268   return 0;  
2269 }
2270
2271 /* Make the variable associated with NAME go away.  HASH_LIST is the
2272    hash table from which this variable should be deleted (either
2273    shell_variables or shell_functions).
2274    Returns non-zero if the variable couldn't be found. */
2275 int
2276 makunbound (name, vc)
2277      const char *name;
2278      VAR_CONTEXT *vc;
2279 {
2280   BUCKET_CONTENTS *elt, *new_elt;
2281   SHELL_VAR *old_var;
2282   VAR_CONTEXT *v;
2283   char *t;
2284
2285   for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2286     if (elt = hash_remove (name, v->table, 0))
2287       break;
2288
2289   if (elt == 0)
2290     return (-1);
2291
2292   old_var = (SHELL_VAR *)elt->data;
2293
2294   if (old_var && exported_p (old_var))
2295     array_needs_making++;
2296
2297   /* If we're unsetting a local variable and we're still executing inside
2298      the function, just mark the variable as invisible.  The function
2299      eventually called by pop_var_context() will clean it up later.  This
2300      must be done so that if the variable is subsequently assigned a new
2301      value inside the function, the `local' attribute is still present.
2302      We also need to add it back into the correct hash table. */
2303   if (old_var && local_p (old_var) && variable_context == old_var->context)
2304     {
2305       /* Reset the attributes.  Preserve the export attribute if the variable
2306          came from a temporary environment.  Make sure it stays local, and
2307          make it invisible. */ 
2308       old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
2309       VSETATTR (old_var, att_local);
2310       VSETATTR (old_var, att_invisible);
2311       FREE (value_cell (old_var));
2312       var_setvalue (old_var, (char *)NULL);
2313       INVALIDATE_EXPORTSTR (old_var);
2314
2315       new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2316       new_elt->data = (PTR_T)old_var;
2317       stupidly_hack_special_variables (old_var->name);
2318
2319       free (elt->key);
2320       free (elt);
2321       return (0);
2322     }
2323
2324   /* Have to save a copy of name here, because it might refer to
2325      old_var->name.  If so, stupidly_hack_special_variables will
2326      reference freed memory. */
2327   t = savestring (name);
2328
2329   free (elt->key);
2330   free (elt);
2331
2332   dispose_variable (old_var);
2333   stupidly_hack_special_variables (t);
2334   free (t);
2335
2336   return (0);
2337 }
2338
2339 /* Get rid of all of the variables in the current context. */
2340 void
2341 kill_all_local_variables ()
2342 {
2343   VAR_CONTEXT *vc;
2344
2345   for (vc = shell_variables; vc; vc = vc->down)
2346     if (vc_isfuncenv (vc) && vc->scope == variable_context)
2347       break;
2348   if (vc == 0)
2349     return;             /* XXX */
2350
2351   if (vc->table && vc_haslocals (vc))
2352     {
2353       delete_all_variables (vc->table);
2354       hash_dispose (vc->table);
2355     }
2356   vc->table = (HASH_TABLE *)NULL;
2357 }
2358
2359 static void
2360 free_variable_hash_data (data)
2361      PTR_T data;
2362 {
2363   SHELL_VAR *var;
2364
2365   var = (SHELL_VAR *)data;
2366   dispose_variable (var);
2367 }
2368
2369 /* Delete the entire contents of the hash table. */
2370 void
2371 delete_all_variables (hashed_vars)
2372      HASH_TABLE *hashed_vars;
2373 {
2374   hash_flush (hashed_vars, free_variable_hash_data);
2375 }
2376
2377 /* **************************************************************** */
2378 /*                                                                  */
2379 /*                   Setting variable attributes                    */
2380 /*                                                                  */
2381 /* **************************************************************** */
2382
2383 #define FIND_OR_MAKE_VARIABLE(name, entry) \
2384   do \
2385     { \
2386       entry = find_variable (name); \
2387       if (!entry) \
2388         { \
2389           entry = bind_variable (name, ""); \
2390           if (!no_invisible_vars) entry->attributes |= att_invisible; \
2391         } \
2392     } \
2393   while (0)
2394
2395 /* Make the variable associated with NAME be readonly.
2396    If NAME does not exist yet, create it. */
2397 void
2398 set_var_read_only (name)
2399      char *name;
2400 {
2401   SHELL_VAR *entry;
2402
2403   FIND_OR_MAKE_VARIABLE (name, entry);
2404   VSETATTR (entry, att_readonly);
2405 }
2406
2407 #ifdef INCLUDE_UNUSED
2408 /* Make the function associated with NAME be readonly.
2409    If NAME does not exist, we just punt, like auto_export code below. */
2410 void
2411 set_func_read_only (name)
2412      const char *name;
2413 {
2414   SHELL_VAR *entry;
2415
2416   entry = find_function (name);
2417   if (entry)
2418     VSETATTR (entry, att_readonly);
2419 }
2420
2421 /* Make the variable associated with NAME be auto-exported.
2422    If NAME does not exist yet, create it. */
2423 void
2424 set_var_auto_export (name)
2425      char *name;
2426 {
2427   SHELL_VAR *entry;
2428
2429   FIND_OR_MAKE_VARIABLE (name, entry);
2430   set_auto_export (entry);
2431 }
2432
2433 /* Make the function associated with NAME be auto-exported. */
2434 void
2435 set_func_auto_export (name)
2436      const char *name;
2437 {
2438   SHELL_VAR *entry;
2439
2440   entry = find_function (name);
2441   if (entry)
2442     set_auto_export (entry);
2443 }
2444 #endif
2445
2446 /* **************************************************************** */
2447 /*                                                                  */
2448 /*                   Creating lists of variables                    */
2449 /*                                                                  */
2450 /* **************************************************************** */
2451
2452 static VARLIST *
2453 vlist_alloc (nentries)
2454      int nentries;
2455 {
2456   VARLIST  *vlist;
2457
2458   vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2459   vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2460   vlist->list_size = nentries;
2461   vlist->list_len = 0;
2462   vlist->list[0] = (SHELL_VAR *)NULL;
2463
2464   return vlist;
2465 }
2466
2467 static VARLIST *
2468 vlist_realloc (vlist, n)
2469      VARLIST *vlist;
2470      int n;
2471 {
2472   if (vlist == 0)
2473     return (vlist = vlist_alloc (n));
2474   if (n > vlist->list_size)
2475     {
2476       vlist->list_size = n;
2477       vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2478     }
2479   return vlist;
2480 }
2481
2482 static void
2483 vlist_add (vlist, var, flags)
2484      VARLIST *vlist;
2485      SHELL_VAR *var;
2486      int flags;
2487 {
2488   register int i;
2489
2490   for (i = 0; i < vlist->list_len; i++)
2491     if (STREQ (var->name, vlist->list[i]->name))
2492       break;
2493   if (i < vlist->list_len)
2494     return;
2495
2496   if (i >= vlist->list_size)
2497     vlist = vlist_realloc (vlist, vlist->list_size + 16);
2498
2499   vlist->list[vlist->list_len++] = var;
2500   vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2501 }
2502
2503 /* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
2504    variables for which FUNCTION returns a non-zero value.  A NULL value
2505    for FUNCTION means to use all variables. */
2506 SHELL_VAR **
2507 map_over (function, vc)
2508      sh_var_map_func_t *function;
2509      VAR_CONTEXT *vc;
2510 {
2511   VAR_CONTEXT *v;
2512   VARLIST *vlist;
2513   SHELL_VAR **ret;
2514   int nentries;
2515
2516   for (nentries = 0, v = vc; v; v = v->down)
2517     nentries += HASH_ENTRIES (v->table);
2518
2519   if (nentries == 0)
2520     return (SHELL_VAR **)NULL;
2521
2522   vlist = vlist_alloc (nentries);
2523
2524   for (v = vc; v; v = v->down)
2525     flatten (v->table, function, vlist, 0);
2526
2527   ret = vlist->list;
2528   free (vlist);
2529   return ret;
2530 }
2531
2532 SHELL_VAR **
2533 map_over_funcs (function)
2534      sh_var_map_func_t *function;
2535 {
2536   VARLIST *vlist;
2537   SHELL_VAR **ret;
2538
2539   if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2540     return ((SHELL_VAR **)NULL);
2541
2542   vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2543
2544   flatten (shell_functions, function, vlist, 0);
2545
2546   ret = vlist->list;
2547   free (vlist);
2548   return ret;
2549 }
2550
2551 /* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2552    elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved
2553    for future use.  Only unique names are added to VLIST.  If FUNC is
2554    NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is
2555    NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST
2556    and FUNC are both NULL, nothing happens. */
2557 static void
2558 flatten (var_hash_table, func, vlist, flags)
2559      HASH_TABLE *var_hash_table;
2560      sh_var_map_func_t *func;
2561      VARLIST *vlist;
2562      int flags;
2563 {
2564   register int i;
2565   register BUCKET_CONTENTS *tlist;
2566   int r;
2567   SHELL_VAR *var;
2568
2569   if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
2570     return;
2571
2572   for (i = 0; i < var_hash_table->nbuckets; i++)
2573     {
2574       for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
2575         {
2576           var = (SHELL_VAR *)tlist->data;
2577
2578           r = func ? (*func) (var) : 1;
2579           if (r && vlist)
2580             vlist_add (vlist, var, flags);
2581         }
2582     }
2583 }
2584
2585 void
2586 sort_variables (array)
2587      SHELL_VAR **array;
2588 {
2589   qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
2590 }
2591
2592 static int
2593 qsort_var_comp (var1, var2)
2594      SHELL_VAR **var1, **var2;
2595 {
2596   int result;
2597
2598   if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
2599     result = strcmp ((*var1)->name, (*var2)->name);
2600
2601   return (result);
2602 }
2603
2604 /* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
2605    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
2606 static SHELL_VAR **
2607 vapply (func)
2608      sh_var_map_func_t *func;
2609 {
2610   SHELL_VAR **list;
2611
2612   list = map_over (func, shell_variables);
2613   if (list /* && posixly_correct */)
2614     sort_variables (list);
2615   return (list);
2616 }
2617
2618 /* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
2619    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
2620 static SHELL_VAR **
2621 fapply (func)
2622      sh_var_map_func_t *func;
2623 {
2624   SHELL_VAR **list;
2625
2626   list = map_over_funcs (func);
2627   if (list /* && posixly_correct */)
2628     sort_variables (list);
2629   return (list);
2630 }
2631
2632 /* Create a NULL terminated array of all the shell variables. */
2633 SHELL_VAR **
2634 all_shell_variables ()
2635 {
2636   return (vapply ((sh_var_map_func_t *)NULL));
2637 }
2638
2639 /* Create a NULL terminated array of all the shell functions. */
2640 SHELL_VAR **
2641 all_shell_functions ()
2642 {
2643   return (fapply ((sh_var_map_func_t *)NULL));
2644 }
2645
2646 static int
2647 visible_var (var)
2648      SHELL_VAR *var;
2649 {
2650   return (invisible_p (var) == 0);
2651 }
2652
2653 SHELL_VAR **
2654 all_visible_functions ()
2655 {
2656   return (fapply (visible_var));
2657 }
2658
2659 SHELL_VAR **
2660 all_visible_variables ()
2661 {
2662   return (vapply (visible_var));
2663 }
2664
2665 /* Return non-zero if the variable VAR is visible and exported.  Array
2666    variables cannot be exported. */
2667 static int
2668 visible_and_exported (var)
2669      SHELL_VAR *var;
2670 {
2671   return (invisible_p (var) == 0 && exported_p (var));
2672 }
2673
2674 /* Return non-zero if VAR is a local variable in the current context and
2675    is exported. */
2676 static int
2677 local_and_exported (var)
2678      SHELL_VAR *var;
2679 {
2680   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
2681 }
2682
2683 SHELL_VAR **
2684 all_exported_variables ()
2685 {
2686   return (vapply (visible_and_exported));
2687 }
2688
2689 SHELL_VAR **
2690 local_exported_variables ()
2691 {
2692   return (vapply (local_and_exported));
2693 }
2694
2695 static int
2696 variable_in_context (var)
2697      SHELL_VAR *var;
2698 {
2699   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
2700 }
2701
2702 SHELL_VAR **
2703 all_local_variables ()
2704 {
2705   VARLIST *vlist;
2706   SHELL_VAR **ret;
2707   VAR_CONTEXT *vc;
2708
2709   vc = shell_variables;
2710   for (vc = shell_variables; vc; vc = vc->down)
2711     if (vc_isfuncenv (vc) && vc->scope == variable_context)
2712       break;
2713
2714   if (vc == 0)
2715     {
2716       internal_error (_("all_local_variables: no function context at current scope"));
2717       return (SHELL_VAR **)NULL;
2718     }
2719   if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
2720     return (SHELL_VAR **)NULL;
2721     
2722   vlist = vlist_alloc (HASH_ENTRIES (vc->table));
2723
2724   flatten (vc->table, variable_in_context, vlist, 0);
2725
2726   ret = vlist->list;
2727   free (vlist);
2728   if (ret)
2729     sort_variables (ret);
2730   return ret;
2731 }
2732
2733 #if defined (ARRAY_VARS)
2734 /* Return non-zero if the variable VAR is visible and an array. */
2735 static int
2736 visible_array_vars (var)
2737      SHELL_VAR *var;
2738 {
2739   return (invisible_p (var) == 0 && array_p (var));
2740 }
2741
2742 SHELL_VAR **
2743 all_array_variables ()
2744 {
2745   return (vapply (visible_array_vars));
2746 }
2747 #endif /* ARRAY_VARS */
2748
2749 char **
2750 all_variables_matching_prefix (prefix)
2751      const char *prefix;
2752 {
2753   SHELL_VAR **varlist;
2754   char **rlist;
2755   int vind, rind, plen;
2756
2757   plen = STRLEN (prefix);
2758   varlist = all_visible_variables ();
2759   for (vind = 0; varlist && varlist[vind]; vind++)
2760     ;
2761   if (varlist == 0 || vind == 0)
2762     return ((char **)NULL);
2763   rlist = strvec_create (vind + 1);
2764   for (vind = rind = 0; varlist[vind]; vind++)
2765     {
2766       if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
2767         rlist[rind++] = savestring (varlist[vind]->name);
2768     }
2769   rlist[rind] = (char *)0;
2770   free (varlist);
2771
2772   return rlist;
2773 }
2774
2775 /* **************************************************************** */
2776 /*                                                                  */
2777 /*               Managing temporary variable scopes                 */
2778 /*                                                                  */
2779 /* **************************************************************** */
2780
2781 /* Make variable NAME have VALUE in the temporary environment. */
2782 static SHELL_VAR *
2783 bind_tempenv_variable (name, value)
2784      const char *name;
2785      char *value;
2786 {
2787   SHELL_VAR *var;
2788
2789   var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
2790
2791   if (var)
2792     {
2793       FREE (value_cell (var));
2794       var_setvalue (var, savestring (value));
2795       INVALIDATE_EXPORTSTR (var);
2796     }
2797
2798   return (var);
2799 }
2800
2801 /* Find a variable in the temporary environment that is named NAME.
2802    Return the SHELL_VAR *, or NULL if not found. */
2803 SHELL_VAR *
2804 find_tempenv_variable (name)
2805      const char *name;
2806 {
2807   return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
2808 }
2809
2810 /* Push the variable described by (SHELL_VAR *)DATA down to the next
2811    variable context from the temporary environment. */
2812 static void
2813 push_temp_var (data)
2814      PTR_T data;
2815 {
2816   SHELL_VAR *var, *v;
2817   HASH_TABLE *binding_table;
2818
2819   var = (SHELL_VAR *)data;
2820
2821   binding_table = shell_variables->table;
2822   if (binding_table == 0)
2823     {
2824       if (shell_variables == global_variables)
2825         /* shouldn't happen */
2826         binding_table = shell_variables->table = global_variables->table = hash_create (0);
2827       else
2828         binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
2829     }
2830
2831   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0);
2832
2833   /* XXX - should we set the context here?  It shouldn't matter because of how
2834      assign_in_env works, but might want to check. */
2835   if (binding_table == global_variables->table)         /* XXX */
2836     var->attributes &= ~(att_tempvar|att_propagate);
2837   else
2838     {
2839       var->attributes |= att_propagate;
2840       if  (binding_table == shell_variables->table)
2841         shell_variables->flags |= VC_HASTMPVAR;
2842     }
2843   v->attributes |= var->attributes;
2844
2845   dispose_variable (var);
2846 }
2847
2848 static void
2849 propagate_temp_var (data)
2850      PTR_T data;
2851 {
2852   SHELL_VAR *var;
2853
2854   var = (SHELL_VAR *)data;
2855   if (tempvar_p (var) && (var->attributes & att_propagate))
2856     push_temp_var (data);
2857   else
2858     dispose_variable (var);
2859 }
2860
2861 /* Free the storage used in the hash table for temporary
2862    environment variables.  PUSHF is a function to be called
2863    to free each hash table entry.  It takes care of pushing variables
2864    to previous scopes if appropriate. */
2865 static void
2866 dispose_temporary_env (pushf)
2867      sh_free_func_t *pushf;
2868 {
2869   hash_flush (temporary_env, pushf);
2870   hash_dispose (temporary_env);
2871   temporary_env  = (HASH_TABLE *)NULL;
2872
2873   array_needs_making = 1;
2874
2875   sv_ifs ("IFS");               /* XXX here for now */
2876 }
2877
2878 void
2879 dispose_used_env_vars ()
2880 {
2881   if (temporary_env)
2882     dispose_temporary_env (propagate_temp_var);
2883 }
2884
2885 /* Take all of the shell variables in the temporary environment HASH_TABLE
2886    and make shell variables from them at the current variable context. */
2887 void
2888 merge_temporary_env ()
2889 {
2890   if (temporary_env)
2891     dispose_temporary_env (push_temp_var);
2892 }
2893
2894 /* **************************************************************** */
2895 /*                                                                  */
2896 /*           Creating and manipulating the environment              */
2897 /*                                                                  */
2898 /* **************************************************************** */
2899
2900 static inline char *
2901 mk_env_string (name, value)
2902      const char *name, *value;
2903 {
2904   int name_len, value_len;
2905   char  *p;
2906
2907   name_len = strlen (name);
2908   value_len = STRLEN (value);
2909   p = (char *)xmalloc (2 + name_len + value_len);
2910   strcpy (p, name);
2911   p[name_len] = '=';
2912   if (value && *value)
2913     strcpy (p + name_len + 1, value);
2914   else
2915     p[name_len + 1] = '\0';
2916   return (p);
2917 }
2918
2919 #ifdef DEBUG
2920 /* Debugging */
2921 static int
2922 valid_exportstr (v)
2923      SHELL_VAR *v;
2924 {
2925   char *s;
2926
2927   s = v->exportstr;
2928   if (legal_variable_starter ((unsigned char)*s) == 0)
2929     {
2930       internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
2931       return (0);
2932     }
2933   for (s = v->exportstr + 1; s && *s; s++)
2934     {
2935       if (*s == '=')
2936         break;
2937       if (legal_variable_char ((unsigned char)*s) == 0)
2938         {
2939           internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
2940           return (0);
2941         }
2942     }
2943   if (*s != '=')
2944     {
2945       internal_error (_("no `=' in exportstr for %s"), v->name);
2946       return (0);
2947     }
2948   return (1);
2949 }
2950 #endif
2951
2952 static char **
2953 make_env_array_from_var_list (vars)
2954      SHELL_VAR **vars;
2955 {
2956   register int i, list_index;
2957   register SHELL_VAR *var;
2958   char **list, *value;
2959
2960   list = strvec_create ((1 + strvec_len ((char **)vars)));
2961
2962 #define USE_EXPORTSTR (value == var->exportstr)
2963
2964   for (i = 0, list_index = 0; var = vars[i]; i++)
2965     {
2966 #if defined (__CYGWIN__)
2967       /* We don't use the exportstr stuff on Cygwin at all. */
2968       INVALIDATE_EXPORTSTR (var);
2969 #endif
2970       if (var->exportstr)
2971         value = var->exportstr;
2972       else if (function_p (var))
2973         value = named_function_string ((char *)NULL, function_cell (var), 0);
2974 #if defined (ARRAY_VARS)
2975       else if (array_p (var))
2976 #  if 0
2977         value = array_to_assignment_string (array_cell (var));
2978 #  else
2979         continue;       /* XXX array vars cannot yet be exported */
2980 #  endif
2981 #endif
2982       else
2983         value = value_cell (var);
2984
2985       if (value)
2986         {
2987           /* Gee, I'd like to get away with not using savestring() if we're
2988              using the cached exportstr... */
2989           list[list_index] = USE_EXPORTSTR ? savestring (value)
2990                                            : mk_env_string (var->name, value);
2991
2992           if (USE_EXPORTSTR == 0)
2993             SAVE_EXPORTSTR (var, list[list_index]);
2994
2995           list_index++;
2996 #undef USE_EXPORTSTR
2997
2998 #if 0   /* not yet */
2999 #if defined (ARRAY_VARS)
3000           if (array_p (var))
3001             free (value);
3002 #endif
3003 #endif
3004         }
3005     }
3006
3007   list[list_index] = (char *)NULL;
3008   return (list);
3009 }
3010
3011 /* Make an array of assignment statements from the hash table
3012    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
3013    variables are eligible. */
3014 static char **
3015 make_var_export_array (vcxt)
3016      VAR_CONTEXT *vcxt;
3017 {
3018   char **list;
3019   SHELL_VAR **vars;
3020
3021   vars = map_over (visible_and_exported, vcxt);
3022
3023   if (vars == 0)
3024     return (char **)NULL;
3025
3026   list = make_env_array_from_var_list (vars);
3027
3028   free (vars);
3029   return (list);
3030 }
3031
3032 static char **
3033 make_func_export_array ()
3034 {
3035   char **list;
3036   SHELL_VAR **vars;
3037
3038   vars = map_over_funcs (visible_and_exported);
3039   if (vars == 0)
3040     return (char **)NULL;
3041
3042   list = make_env_array_from_var_list (vars);
3043
3044   free (vars);
3045   return (list);
3046 }
3047
3048 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3049 #define add_to_export_env(envstr,do_alloc) \
3050 do \
3051   { \
3052     if (export_env_index >= (export_env_size - 1)) \
3053       { \
3054         export_env_size += 16; \
3055         export_env = strvec_resize (export_env, export_env_size); \
3056       } \
3057     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3058     export_env[export_env_index] = (char *)NULL; \
3059   } while (0)
3060
3061 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3062    array with the same left-hand side.  Return the new EXPORT_ENV. */
3063 char **
3064 add_or_supercede_exported_var (assign, do_alloc)
3065      char *assign;
3066      int do_alloc;
3067 {
3068   register int i;
3069   int equal_offset;
3070
3071   equal_offset = assignment (assign, 0);
3072   if (equal_offset == 0)
3073     return (export_env);
3074
3075   /* If this is a function, then only supersede the function definition.
3076      We do this by including the `=() {' in the comparison, like
3077      initialize_shell_variables does. */
3078   if (assign[equal_offset + 1] == '(' &&
3079      strncmp (assign + equal_offset + 2, ") {", 3) == 0)                /* } */
3080     equal_offset += 4;
3081
3082   for (i = 0; i < export_env_index; i++)
3083     {
3084       if (STREQN (assign, export_env[i], equal_offset + 1))
3085         {
3086           free (export_env[i]);
3087           export_env[i] = do_alloc ? savestring (assign) : assign;
3088           return (export_env);
3089         }
3090     }
3091   add_to_export_env (assign, do_alloc);
3092   return (export_env);
3093 }
3094
3095 static void
3096 add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3097      char **temp_array;
3098      int do_alloc, do_supercede;
3099 {
3100   register int i;
3101
3102   if (temp_array == 0)
3103     return;
3104
3105   for (i = 0; temp_array[i]; i++)
3106     {
3107       if (do_supercede)
3108         export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3109       else
3110         add_to_export_env (temp_array[i], do_alloc);
3111     }
3112
3113   free (temp_array);
3114 }
3115
3116 /* Make the environment array for the command about to be executed, if the
3117    array needs making.  Otherwise, do nothing.  If a shell action could
3118    change the array that commands receive for their environment, then the
3119    code should `array_needs_making++'.
3120
3121    The order to add to the array is:
3122         temporary_env
3123         list of var contexts whose head is shell_variables
3124         shell_functions
3125
3126   This is the shell variable lookup order.  We add only new variable
3127   names at each step, which allows local variables and variables in
3128   the temporary environments to shadow variables in the global (or
3129   any previous) scope.
3130 */
3131
3132 static int
3133 n_shell_variables ()
3134 {
3135   VAR_CONTEXT *vc;
3136   int n;
3137
3138   for (n = 0, vc = shell_variables; vc; vc = vc->down)
3139     n += HASH_ENTRIES (vc->table);
3140   return n;
3141 }
3142
3143 void
3144 maybe_make_export_env ()
3145 {
3146   register char **temp_array;
3147   int new_size;
3148   VAR_CONTEXT *tcxt;
3149
3150   if (array_needs_making)
3151     {
3152       if (export_env)
3153         strvec_flush (export_env);
3154
3155       /* Make a guess based on how many shell variables and functions we
3156          have.  Since there will always be array variables, and array
3157          variables are not (yet) exported, this will always be big enough
3158          for the exported variables and functions. */
3159       new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3160                  HASH_ENTRIES (temporary_env);
3161       if (new_size > export_env_size)
3162         {
3163           export_env_size = new_size;
3164           export_env = strvec_resize (export_env, export_env_size);
3165         }
3166       export_env[export_env_index = 0] = (char *)NULL;
3167
3168       /* Make a dummy variable context from the  temporary_env, stick it on
3169          the front of shell_variables, call make_var_export_array on the
3170          whole thing to flatten it, and convert the list of SHELL_VAR *s
3171          to the form needed by the environment. */
3172       if (temporary_env)
3173         {
3174           tcxt = new_var_context ((char *)NULL, 0);
3175           tcxt->table = temporary_env;
3176           tcxt->down = shell_variables;
3177         }
3178       else
3179         tcxt = shell_variables;
3180       
3181       temp_array = make_var_export_array (tcxt);
3182       if (temp_array)
3183         add_temp_array_to_env (temp_array, 0, 0);
3184
3185       if (tcxt != shell_variables)
3186         free (tcxt);
3187
3188 #if defined (RESTRICTED_SHELL)
3189       /* Restricted shells may not export shell functions. */
3190       temp_array = restricted ? (char **)0 : make_func_export_array ();
3191 #else
3192       temp_array = make_func_export_array ();
3193 #endif
3194       if (temp_array)
3195         add_temp_array_to_env (temp_array, 0, 0);
3196
3197       array_needs_making = 0;
3198     }
3199 }
3200
3201 /* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
3202    we will need to remake the exported environment every time we
3203    change directories.  `_' is always put into the environment for
3204    every external command, so without special treatment it will always
3205    cause the environment to be remade.
3206
3207    If there is no other reason to make the exported environment, we can
3208    just update the variables in place and mark the exported environment
3209    as no longer needing a remake. */
3210 void
3211 update_export_env_inplace (env_prefix, preflen, value)
3212      char *env_prefix;
3213      int preflen;
3214      char *value;
3215 {
3216   char *evar;
3217
3218   evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
3219   strcpy (evar, env_prefix);
3220   if (value)
3221     strcpy (evar + preflen, value);
3222   export_env = add_or_supercede_exported_var (evar, 0);
3223 }
3224
3225 /* We always put _ in the environment as the name of this command. */
3226 void
3227 put_command_name_into_env (command_name)
3228      char *command_name;
3229 {
3230   update_export_env_inplace ("_=", 2, command_name);
3231 }
3232
3233 #if 0   /* UNUSED -- it caused too many problems */
3234 void
3235 put_gnu_argv_flags_into_env (pid, flags_string)
3236      intmax_t pid;
3237      char *flags_string;
3238 {
3239   char *dummy, *pbuf;
3240   int l, fl;
3241
3242   pbuf = itos (pid);
3243   l = strlen (pbuf);
3244
3245   fl = strlen (flags_string);
3246
3247   dummy = (char *)xmalloc (l + fl + 30);
3248   dummy[0] = '_';
3249   strcpy (dummy + 1, pbuf);
3250   strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3251   dummy[l + 27] = '=';
3252   strcpy (dummy + l + 28, flags_string);
3253
3254   free (pbuf);
3255
3256   export_env = add_or_supercede_exported_var (dummy, 0);
3257 }
3258 #endif
3259
3260 /* **************************************************************** */
3261 /*                                                                  */
3262 /*                    Managing variable contexts                    */
3263 /*                                                                  */
3264 /* **************************************************************** */
3265
3266 /* Allocate and return a new variable context with NAME and FLAGS.
3267    NAME can be NULL. */
3268
3269 VAR_CONTEXT *
3270 new_var_context (name, flags)
3271      char *name;
3272      int flags;
3273 {
3274   VAR_CONTEXT *vc;
3275
3276   vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3277   vc->name = name ? savestring (name) : (char *)NULL;
3278   vc->scope = variable_context;
3279   vc->flags = flags;
3280
3281   vc->up = vc->down = (VAR_CONTEXT *)NULL;
3282   vc->table = (HASH_TABLE *)NULL;
3283
3284   return vc;
3285 }
3286
3287 /* Free a variable context and its data, including the hash table.  Dispose
3288    all of the variables. */
3289 void
3290 dispose_var_context (vc)
3291      VAR_CONTEXT *vc;
3292 {
3293   FREE (vc->name);
3294
3295   if (vc->table)
3296     {
3297       delete_all_variables (vc->table);
3298       hash_dispose (vc->table);
3299     }
3300
3301   free (vc);
3302 }
3303
3304 /* Set VAR's scope level to the current variable context. */
3305 static int
3306 set_context (var)
3307      SHELL_VAR *var;
3308 {
3309   return (var->context = variable_context);
3310 }
3311
3312 /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3313    temporary variables, and push it onto shell_variables.  This is
3314    for shell functions. */
3315 VAR_CONTEXT *
3316 push_var_context (name, flags, tempvars)
3317      char *name;
3318      int flags;
3319      HASH_TABLE *tempvars;
3320 {
3321   VAR_CONTEXT *vc;
3322
3323   vc = new_var_context (name, flags);
3324   vc->table = tempvars;
3325   if (tempvars)
3326     {
3327       /* Have to do this because the temp environment was created before
3328          variable_context was incremented. */
3329       flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3330       vc->flags |= VC_HASTMPVAR;
3331     }
3332   vc->down = shell_variables;
3333   shell_variables->up = vc;
3334
3335   return (shell_variables = vc);
3336 }
3337
3338 static void
3339 push_func_var (data)
3340      PTR_T data;
3341 {
3342   SHELL_VAR *var, *v;
3343
3344   var = (SHELL_VAR *)data;
3345
3346   if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3347     {
3348       /* XXX - should we set v->context here? */
3349       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
3350       if (shell_variables == global_variables)
3351         var->attributes &= ~(att_tempvar|att_propagate);
3352       else
3353         shell_variables->flags |= VC_HASTMPVAR;
3354       v->attributes |= var->attributes;
3355     }
3356
3357   dispose_variable (var);
3358 }
3359
3360 /* Pop the top context off of VCXT and dispose of it, returning the rest of
3361    the stack. */
3362 void
3363 pop_var_context ()
3364 {
3365   VAR_CONTEXT *ret, *vcxt;
3366
3367   vcxt = shell_variables;
3368   if (vc_isfuncenv (vcxt) == 0)
3369     {
3370       internal_error (_("pop_var_context: head of shell_variables not a function context"));
3371       return;
3372     }
3373
3374   if (ret = vcxt->down)
3375     {
3376       ret->up = (VAR_CONTEXT *)NULL;
3377       shell_variables = ret;
3378       if (vcxt->table)
3379         hash_flush (vcxt->table, push_func_var);
3380       dispose_var_context (vcxt);
3381     }
3382   else
3383     internal_error (_("pop_var_context: no global_variables context"));
3384 }
3385
3386 /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3387    all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3388 void
3389 delete_all_contexts (vcxt)
3390      VAR_CONTEXT *vcxt;
3391 {
3392   VAR_CONTEXT *v, *t;
3393
3394   for (v = vcxt; v != global_variables; v = t)
3395     {
3396       t = v->down;
3397       dispose_var_context (v);
3398     }            
3399
3400   delete_all_variables (global_variables->table);
3401   shell_variables = global_variables;
3402 }
3403
3404 /* **************************************************************** */
3405 /*                                                                  */
3406 /*         Pushing and Popping temporary variable scopes            */
3407 /*                                                                  */
3408 /* **************************************************************** */
3409
3410 VAR_CONTEXT *
3411 push_scope (flags, tmpvars)
3412      int flags;
3413      HASH_TABLE *tmpvars;
3414 {
3415   return (push_var_context ((char *)NULL, flags, tmpvars));
3416 }
3417
3418 static void
3419 push_exported_var (data)
3420      PTR_T data;
3421 {
3422   SHELL_VAR *var, *v;
3423
3424   var = (SHELL_VAR *)data;
3425
3426   /* If a temp var had its export attribute set, or it's marked to be
3427      propagated, bind it in the previous scope before disposing it. */
3428   if (exported_p (var) || (var->attributes & att_propagate))
3429     {
3430       var->attributes &= ~att_tempvar;          /* XXX */
3431       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
3432       if (shell_variables == global_variables)
3433         var->attributes &= ~att_propagate;
3434       v->attributes |= var->attributes;
3435     }
3436
3437   dispose_variable (var);
3438 }
3439
3440 void
3441 pop_scope (is_special)
3442      int is_special;
3443 {
3444   VAR_CONTEXT *vcxt, *ret;
3445
3446   vcxt = shell_variables;
3447   if (vc_istempscope (vcxt) == 0)
3448     {
3449       internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
3450       return;
3451     }
3452
3453   ret = vcxt->down;
3454   if (ret)
3455     ret->up = (VAR_CONTEXT *)NULL;
3456
3457   shell_variables = ret;
3458
3459   /* Now we can take care of merging variables in VCXT into set of scopes
3460      whose head is RET (shell_variables). */
3461   FREE (vcxt->name);
3462   if (vcxt->table)
3463     {
3464       if (is_special)
3465         hash_flush (vcxt->table, push_func_var);
3466       else
3467         hash_flush (vcxt->table, push_exported_var);
3468       hash_dispose (vcxt->table);
3469     }
3470   free (vcxt);
3471
3472   sv_ifs ("IFS");       /* XXX here for now */
3473 }
3474
3475 /* **************************************************************** */
3476 /*                                                                  */
3477 /*               Pushing and Popping function contexts              */
3478 /*                                                                  */
3479 /* **************************************************************** */
3480
3481 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3482 static int dollar_arg_stack_slots;
3483 static int dollar_arg_stack_index;
3484
3485 /* XXX - we might want to consider pushing and popping the `getopts' state
3486    when we modify the positional parameters. */
3487 void
3488 push_context (name, is_subshell, tempvars)
3489      char *name;        /* function name */
3490      int is_subshell;
3491      HASH_TABLE *tempvars;
3492 {
3493   if (is_subshell == 0)
3494     push_dollar_vars ();
3495   variable_context++;
3496   push_var_context (name, VC_FUNCENV, tempvars);
3497 }
3498
3499 /* Only called when subshell == 0, so we don't need to check, and can
3500    unconditionally pop the dollar vars off the stack. */
3501 void
3502 pop_context ()
3503 {
3504   pop_dollar_vars ();
3505   variable_context--;
3506   pop_var_context ();
3507
3508   sv_ifs ("IFS");               /* XXX here for now */
3509 }
3510
3511 /* Save the existing positional parameters on a stack. */
3512 void
3513 push_dollar_vars ()
3514 {
3515   if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3516     {
3517       dollar_arg_stack = (WORD_LIST **)
3518         xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3519                   * sizeof (WORD_LIST **));
3520     }
3521   dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3522   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3523 }
3524
3525 /* Restore the positional parameters from our stack. */
3526 void
3527 pop_dollar_vars ()
3528 {
3529   if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3530     return;
3531
3532   remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
3533   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3534   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3535   set_dollar_vars_unchanged ();
3536 }
3537
3538 void
3539 dispose_saved_dollar_vars ()
3540 {
3541   if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3542     return;
3543
3544   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3545   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3546 }
3547
3548 /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
3549
3550 void
3551 push_args (list)
3552      WORD_LIST *list;
3553 {
3554 #if defined (ARRAY_VARS) && defined (DEBUGGER)
3555   SHELL_VAR *bash_argv_v, *bash_argc_v;
3556   ARRAY *bash_argv_a, *bash_argc_a;
3557   WORD_LIST *l;
3558   arrayind_t i;
3559   char *t;
3560
3561   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3562   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3563
3564   for (l = list, i = 0; l; l = l->next, i++)
3565     array_push (bash_argv_a, l->word->word);
3566
3567   t = itos (i);
3568   array_push (bash_argc_a, t);
3569   free (t);
3570 #endif /* ARRAY_VARS && DEBUGGER */
3571 }
3572
3573 /* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
3574    array and use that value as the count of elements to remove from
3575    BASH_ARGV. */
3576 void
3577 pop_args ()
3578 {
3579 #if defined (ARRAY_VARS) && defined (DEBUGGER)
3580   SHELL_VAR *bash_argv_v, *bash_argc_v;
3581   ARRAY *bash_argv_a, *bash_argc_a;
3582   ARRAY_ELEMENT *ce;
3583   intmax_t i;
3584
3585   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3586   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3587
3588   ce = array_shift (bash_argc_a, 1, 0);
3589   if (ce == 0 || legal_number (element_value (ce), &i) == 0)
3590     i = 0;
3591
3592   for ( ; i > 0; i--)
3593     array_pop (bash_argv_a);
3594   array_dispose_element (ce);
3595 #endif /* ARRAY_VARS && DEBUGGER */
3596 }
3597
3598 /*************************************************
3599  *                                               *
3600  *      Functions to manage special variables    *
3601  *                                               *
3602  *************************************************/
3603
3604 /* Extern declarations for variables this code has to manage. */
3605 extern int eof_encountered, eof_encountered_limit, ignoreeof;
3606
3607 #if defined (READLINE)
3608 extern int no_line_editing;
3609 extern int hostname_list_initialized;
3610 #endif
3611
3612 /* An alist of name.function for each special variable.  Most of the
3613    functions don't do much, and in fact, this would be faster with a
3614    switch statement, but by the end of this file, I am sick of switch
3615    statements. */
3616
3617 #define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
3618
3619 /* This table will be sorted with qsort() the first time it's accessed. */
3620 struct name_and_function {
3621   char *name;
3622   sh_sv_func_t *function;
3623 };
3624
3625 static struct name_and_function special_vars[] = {
3626   { "GLOBIGNORE", sv_globignore },
3627
3628 #if defined (HISTORY)
3629   { "HISTCONTROL", sv_history_control },
3630   { "HISTFILESIZE", sv_histsize },
3631   { "HISTIGNORE", sv_histignore },
3632   { "HISTSIZE", sv_histsize },
3633   { "HISTTIMEFORMAT", sv_histtimefmt },
3634 #endif
3635
3636 #if defined (READLINE)
3637   { "HOSTFILE", sv_hostfile },
3638 #endif
3639
3640   { "IFS", sv_ifs },
3641   { "IGNOREEOF", sv_ignoreeof },
3642
3643   { "LANG", sv_locale },
3644   { "LC_ALL", sv_locale },
3645   { "LC_COLLATE", sv_locale },
3646   { "LC_CTYPE", sv_locale },
3647   { "LC_MESSAGES", sv_locale },
3648   { "LC_NUMERIC", sv_locale },
3649
3650   { "MAIL", sv_mail },
3651   { "MAILCHECK", sv_mail },
3652   { "MAILPATH", sv_mail },
3653
3654   { "OPTERR", sv_opterr },
3655   { "OPTIND", sv_optind },
3656
3657   { "PATH", sv_path },
3658   { "POSIXLY_CORRECT", sv_strict_posix },
3659
3660 #if defined (READLINE)
3661   { "TERM", sv_terminal },
3662   { "TERMCAP", sv_terminal },
3663   { "TERMINFO", sv_terminal },
3664 #endif /* READLINE */
3665
3666   { "TEXTDOMAIN", sv_locale },
3667   { "TEXTDOMAINDIR", sv_locale },
3668
3669 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3670   { "TZ", sv_tz },
3671 #endif
3672
3673 #if defined (HISTORY) && defined (BANG_HISTORY)
3674   { "histchars", sv_histchars },
3675 #endif /* HISTORY && BANG_HISTORY */
3676
3677   { "ignoreeof", sv_ignoreeof },
3678
3679   { (char *)0, (sh_sv_func_t *)0 }
3680 };
3681
3682 #define N_SPECIAL_VARS  (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
3683
3684 static int
3685 sv_compare (sv1, sv2)
3686      struct name_and_function *sv1, *sv2;
3687 {
3688   int r;
3689
3690   if ((r = sv1->name[0] - sv2->name[0]) == 0)
3691     r = strcmp (sv1->name, sv2->name);
3692   return r;
3693 }
3694
3695 static inline int
3696 find_special_var (name)
3697      const char *name;
3698 {
3699   register int i, r;
3700
3701   for (i = 0; special_vars[i].name; i++)
3702     {
3703       r = special_vars[i].name[0] - name[0];
3704       if (r == 0)
3705         r = strcmp (special_vars[i].name, name);
3706       if (r == 0)
3707         return i;
3708       else if (r > 0)
3709         /* Can't match any of rest of elements in sorted list.  Take this out
3710            if it causes problems in certain environments. */
3711         break;
3712     }
3713   return -1;
3714 }
3715
3716 /* The variable in NAME has just had its state changed.  Check to see if it
3717    is one of the special ones where something special happens. */
3718 void
3719 stupidly_hack_special_variables (name)
3720      char *name;
3721 {
3722   static int sv_sorted = 0;
3723   int i;
3724
3725   if (sv_sorted == 0)   /* shouldn't need, but it's fairly cheap. */
3726     {
3727       qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
3728                 (QSFUNC *)sv_compare);
3729       sv_sorted = 1;
3730     }
3731
3732   i = find_special_var (name);
3733   if (i != -1)
3734     (*(special_vars[i].function)) (name);
3735 }
3736
3737 void
3738 sv_ifs (name)
3739      char *name;
3740 {
3741   SHELL_VAR *v;
3742
3743   v = find_variable ("IFS");
3744   setifs (v);
3745 }
3746
3747 /* What to do just after the PATH variable has changed. */
3748 void
3749 sv_path (name)
3750      char *name;
3751 {
3752   /* hash -r */
3753   phash_flush ();
3754 }
3755
3756 /* What to do just after one of the MAILxxxx variables has changed.  NAME
3757    is the name of the variable.  This is called with NAME set to one of
3758    MAIL, MAILCHECK, or MAILPATH.  */
3759 void
3760 sv_mail (name)
3761      char *name;
3762 {
3763   /* If the time interval for checking the files has changed, then
3764      reset the mail timer.  Otherwise, one of the pathname vars
3765      to the users mailbox has changed, so rebuild the array of
3766      filenames. */
3767   if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
3768     reset_mail_timer ();
3769   else
3770     {
3771       free_mail_files ();
3772       remember_mail_dates ();
3773     }
3774 }
3775
3776 /* What to do when GLOBIGNORE changes. */
3777 void
3778 sv_globignore (name)
3779      char *name;
3780 {
3781   setup_glob_ignore (name);
3782 }
3783
3784 #if defined (READLINE)
3785 /* What to do just after one of the TERMxxx variables has changed.
3786    If we are an interactive shell, then try to reset the terminal
3787    information in readline. */
3788 void
3789 sv_terminal (name)
3790      char *name;
3791 {
3792   if (interactive_shell && no_line_editing == 0)
3793     rl_reset_terminal (get_string_value ("TERM"));
3794 }
3795
3796 void
3797 sv_hostfile (name)
3798      char *name;
3799 {
3800   SHELL_VAR *v;
3801
3802   v = find_variable (name);
3803   if (v == 0)
3804     clear_hostname_list ();
3805   else
3806     hostname_list_initialized = 0;
3807 }
3808 #endif /* READLINE */
3809
3810 #if defined (HISTORY)
3811 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
3812    If there is a value for this HISTSIZE (and it is numeric), then stifle
3813    the history.  Otherwise, if there is NO value for this variable,
3814    unstifle the history.  If name is HISTFILESIZE, and its value is
3815    numeric, truncate the history file to hold no more than that many
3816    lines. */
3817 void
3818 sv_histsize (name)
3819      char *name;
3820 {
3821   char *temp;
3822   intmax_t num;
3823
3824   temp = get_string_value (name);
3825
3826   if (temp && *temp)
3827     {
3828       if (legal_number (temp, &num))
3829         {
3830           if (name[4] == 'S')
3831             {
3832               stifle_history (num);
3833               num = where_history ();
3834               if (history_lines_this_session > num)
3835                 history_lines_this_session = num;
3836             }
3837           else
3838             {
3839               history_truncate_file (get_string_value ("HISTFILE"), (int)num);
3840               if (num <= history_lines_in_file)
3841                 history_lines_in_file = num;
3842             }
3843         }
3844     }
3845   else if (name[4] == 'S')
3846     unstifle_history ();
3847 }
3848
3849 /* What to do after the HISTIGNORE variable changes. */
3850 void
3851 sv_histignore (name)
3852      char *name;
3853 {
3854   setup_history_ignore (name);
3855 }
3856
3857 /* What to do after the HISTCONTROL variable changes. */
3858 void
3859 sv_history_control (name)
3860      char *name;
3861 {
3862   char *temp;
3863   char *val;
3864   int tptr;
3865
3866   history_control = 0;
3867   temp = get_string_value (name);
3868
3869   if (temp == 0 || *temp == 0)
3870     return;
3871
3872   tptr = 0;
3873   while (val = extract_colon_unit (temp, &tptr))
3874     {
3875       if (STREQ (val, "ignorespace"))
3876         history_control |= HC_IGNSPACE;
3877       else if (STREQ (val, "ignoredups"))
3878         history_control |= HC_IGNDUPS;
3879       else if (STREQ (val, "ignoreboth"))
3880         history_control |= HC_IGNBOTH;
3881       else if (STREQ (val, "erasedups"))
3882         history_control |= HC_ERASEDUPS;
3883
3884       free (val);
3885     }
3886 }
3887
3888 #if defined (BANG_HISTORY)
3889 /* Setting/unsetting of the history expansion character. */
3890 void
3891 sv_histchars (name)
3892      char *name;
3893 {
3894   char *temp;
3895
3896   temp = get_string_value (name);
3897   if (temp)
3898     {
3899       history_expansion_char = *temp;
3900       if (temp[0] && temp[1])
3901         {
3902           history_subst_char = temp[1];
3903           if (temp[2])
3904               history_comment_char = temp[2];
3905         }
3906     }
3907   else
3908     {
3909       history_expansion_char = '!';
3910       history_subst_char = '^';
3911       history_comment_char = '#';
3912     }
3913 }
3914 #endif /* BANG_HISTORY */
3915
3916 void
3917 sv_histtimefmt (name)
3918      char *name;
3919 {
3920   SHELL_VAR *v;
3921
3922   v = find_variable (name);
3923   history_write_timestamps = (v != 0);
3924 }
3925 #endif /* HISTORY */
3926
3927 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3928 void
3929 sv_tz (name)
3930      char *name;
3931 {
3932   tzset ();
3933 }
3934 #endif
3935
3936 /* If the variable exists, then the value of it can be the number
3937    of times we actually ignore the EOF.  The default is small,
3938    (smaller than csh, anyway). */
3939 void
3940 sv_ignoreeof (name)
3941      char *name;
3942 {
3943   SHELL_VAR *tmp_var;
3944   char *temp;
3945
3946   eof_encountered = 0;
3947
3948   tmp_var = find_variable (name);
3949   ignoreeof = tmp_var != 0;
3950   temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
3951   if (temp)
3952     eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
3953   set_shellopts ();     /* make sure `ignoreeof' is/is not in $SHELLOPTS */
3954 }
3955
3956 void
3957 sv_optind (name)
3958      char *name;
3959 {
3960   char *tt;
3961   int s;
3962
3963   tt = get_string_value ("OPTIND");
3964   if (tt && *tt)
3965     {
3966       s = atoi (tt);
3967
3968       /* According to POSIX, setting OPTIND=1 resets the internal state
3969          of getopt (). */
3970       if (s < 0 || s == 1)
3971         s = 0;
3972     }
3973   else
3974     s = 0;
3975   getopts_reset (s);
3976 }
3977
3978 void
3979 sv_opterr (name)
3980      char *name;
3981 {
3982   char *tt;
3983
3984   tt = get_string_value ("OPTERR");
3985   sh_opterr = (tt && *tt) ? atoi (tt) : 1;
3986 }
3987
3988 void
3989 sv_strict_posix (name)
3990      char *name;
3991 {
3992   SET_INT_VAR (name, posixly_correct);
3993   posix_initialize (posixly_correct);
3994 #if defined (READLINE)
3995   if (interactive_shell)
3996     posix_readline_initialize (posixly_correct);
3997 #endif /* READLINE */
3998   set_shellopts ();     /* make sure `posix' is/is not in $SHELLOPTS */
3999 }
4000
4001 void
4002 sv_locale (name)
4003      char *name;
4004 {
4005   char *v;
4006
4007   v = get_string_value (name);
4008   if (name[0] == 'L' && name[1] == 'A') /* LANG */
4009     set_lang (name, v);
4010   else
4011     set_locale_var (name, v);           /* LC_*, TEXTDOMAIN* */
4012 }
4013
4014 #if defined (ARRAY_VARS)
4015 void
4016 set_pipestatus_array (ps, nproc)
4017      int *ps;
4018      int nproc;
4019 {
4020   SHELL_VAR *v;
4021   ARRAY *a;
4022   ARRAY_ELEMENT *ae;
4023   register int i;
4024   char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
4025
4026   v = find_variable ("PIPESTATUS");
4027   if (v == 0)
4028     v = make_new_array_variable ("PIPESTATUS");
4029   if (array_p (v) == 0)
4030     return;             /* Do nothing if not an array variable. */
4031   a = array_cell (v);
4032
4033   if (a == 0 || array_num_elements (a) == 0)
4034     {
4035       for (i = 0; i < nproc; i++)       /* was ps[i] != -1, not i < nproc */
4036         {
4037           t = inttostr (ps[i], tbuf, sizeof (tbuf));
4038           array_insert (a, i, t);
4039         }
4040       return;
4041     }
4042
4043   /* Fast case */
4044   if (array_num_elements (a) == nproc && nproc == 1)
4045     {
4046       ae = element_forw (a->head);
4047       free (element_value (ae));
4048       ae->value = itos (ps[0]);
4049     }
4050   else if (array_num_elements (a) <= nproc)
4051     {
4052       /* modify in array_num_elements members in place, then add */
4053       ae = a->head;
4054       for (i = 0; i < array_num_elements (a); i++)
4055         {
4056           ae = element_forw (ae);
4057           free (element_value (ae));
4058           ae->value = itos (ps[i]);
4059         }
4060       /* add any more */
4061       for ( ; i < nproc; i++)
4062         {
4063           t = inttostr (ps[i], tbuf, sizeof (tbuf));
4064           array_insert (a, i, t);
4065         }
4066     }
4067   else
4068     {
4069       /* deleting elements.  it's faster to rebuild the array. */         
4070       array_flush (a);
4071       for (i = 0; ps[i] != -1; i++)
4072         {
4073           t = inttostr (ps[i], tbuf, sizeof (tbuf));
4074           array_insert (a, i, t);
4075         }
4076     }
4077 }
4078 #endif
4079
4080 void
4081 set_pipestatus_from_exit (s)
4082      int s;
4083 {
4084 #if defined (ARRAY_VARS)
4085   static int v[2] = { 0, -1 };
4086
4087   v[0] = s;
4088   set_pipestatus_array (v, 1);
4089 #endif
4090 }