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