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