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
77extern char **environ;
78
79/* Variables used here and defined in other files. */
80extern int posixly_correct;
81extern int line_number;
82extern int subshell_environment, indirection_level, subshell_level;
83extern int build_version, patch_level;
84extern int expanding_redir;
85extern char *dist_version, *release_status;
86extern char *shell_name;
87extern char *primary_prompt, *secondary_prompt;
88extern char *current_host_name;
89extern sh_builtin_func_t *this_shell_builtin;
90extern SHELL_VAR *this_shell_function;
91extern char *the_printed_command_except_trap;
92extern char *this_command_name;
93extern char *command_execution_string;
94extern time_t shell_start_time;
95
96#if defined (READLINE)
97extern int no_line_editing;
98extern 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. */
103VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
104
105/* The current list of shell variables, including function scopes */
106VAR_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. */
110HASH_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. */
115HASH_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. */
120int variable_context = 0;
121
122/* The set of shell assignments which are made only in the environment
123   for a single command. */
124HASH_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. */
128int tempenv_assign_error;
129
130/* Some funky variables which are known about specially.  Here is where
131   "$*", "$1", and all the cruft is kept. */
132char *dollar_vars[10];
133WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
134
135/* The value of $$. */
136pid_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. */
141char **export_env = (char **)NULL;
142static int export_env_index;
143static int export_env_size;
144
145#if defined (READLINE)
146static int winsize_assignment;		/* currently assigning to LINES or COLUMNS */
147static int winsize_assigned;		/* assigned to LINES or COLUMNS */
148#endif
149
150/* Non-zero means that we have to remake EXPORT_ENV. */
151int array_needs_making = 1;
152
153/* The number of times BASH has been executed.  This is set
154   by initialize_variables (). */
155int shell_level = 0;
156
157/* Some forward declarations. */
158static void create_variable_tables __P((void));
159
160static void set_machine_vars __P((void));
161static void set_home_var __P((void));
162static void set_shell_var __P((void));
163static char *get_bash_name __P((void));
164static void initialize_shell_level __P((void));
165static void uidset __P((void));
166#if defined (ARRAY_VARS)
167static void make_vers_array __P((void));
168#endif
169
170static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
171#if defined (ARRAY_VARS)
172static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
173#endif
174static SHELL_VAR *get_self __P((SHELL_VAR *));
175
176#if defined (ARRAY_VARS)
177static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
178#endif
179
180static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
181static SHELL_VAR *get_seconds __P((SHELL_VAR *));
182static SHELL_VAR *init_seconds_var __P((void));
183
184static int brand __P((void));
185static void sbrand __P((unsigned long));		/* set bash random number generator. */
186static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
187static SHELL_VAR *get_random __P((SHELL_VAR *));
188
189static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
190static SHELL_VAR *get_lineno __P((SHELL_VAR *));
191
192static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
193static SHELL_VAR *get_subshell __P((SHELL_VAR *));
194
195#if defined (HISTORY)
196static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
197#endif
198
199#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
200static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
201static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
202#endif
203
204#if defined (ARRAY_VARS)
205static SHELL_VAR *get_groupset __P((SHELL_VAR *));
206#endif
207
208static SHELL_VAR *get_funcname __P((SHELL_VAR *));
209static SHELL_VAR *init_funcname_var __P((void));
210
211static void initialize_dynamic_variables __P((void));
212
213static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
214static SHELL_VAR *new_shell_variable __P((const char *));
215static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
216static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
217
218static void free_variable_hash_data __P((PTR_T));
219
220static VARLIST *vlist_alloc __P((int));
221static VARLIST *vlist_realloc __P((VARLIST *, int));
222static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
223
224static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
225
226static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
227
228static SHELL_VAR **vapply __P((sh_var_map_func_t *));
229static SHELL_VAR **fapply __P((sh_var_map_func_t *));
230
231static int visible_var __P((SHELL_VAR *));
232static int visible_and_exported __P((SHELL_VAR *));
233static int local_and_exported __P((SHELL_VAR *));
234static int variable_in_context __P((SHELL_VAR *));
235#if defined (ARRAY_VARS)
236static int visible_array_vars __P((SHELL_VAR *));
237#endif
238
239static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
240static void push_temp_var __P((PTR_T));
241static void propagate_temp_var __P((PTR_T));
242static void dispose_temporary_env __P((sh_free_func_t *));
243
244static inline char *mk_env_string __P((const char *, const char *));
245static char **make_env_array_from_var_list __P((SHELL_VAR **));
246static char **make_var_export_array __P((VAR_CONTEXT *));
247static char **make_func_export_array __P((void));
248static void add_temp_array_to_env __P((char **, int, int));
249
250static int n_shell_variables __P((void));
251static int set_context __P((SHELL_VAR *));
252
253static void push_func_var __P((PTR_T));
254static void push_exported_var __P((PTR_T));
255
256static inline int find_special_var __P((const char *));
257
258static void
259create_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. */
280void
281initialize_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
564static void
565set_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. */
581char *
582sh_get_home_dir ()
583{
584  if (current_user.home_dir == 0)
585    get_current_user_info ();
586  return current_user.home_dir;
587}
588
589static void
590set_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. */
604static void
605set_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
621static char *
622get_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
694void
695adjust_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
740static void
741initialize_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
753void
754set_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.  */
793void
794set_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
807static void
808uidset ()
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)
833static void
834make_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. */
863void
864sh_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. */
890void
891print_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. */
904void
905print_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. */
922void
923print_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. */
951void
952print_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. */
979void
980print_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
1044static SHELL_VAR *
1045null_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)
1054static SHELL_VAR *
1055null_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. */
1066static SHELL_VAR *
1067get_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. */
1076static SHELL_VAR *
1077init_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. */
1099static intmax_t seconds_value_assigned;
1100
1101static SHELL_VAR *
1102assign_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
1113static SHELL_VAR *
1114get_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
1130static SHELL_VAR *
1131init_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. */
1146static unsigned long rseed = 1;
1147static int last_random_value;
1148static 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. */
1155static int
1156brand ()
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. */
1163static void
1164sbrand (seed)
1165     unsigned long seed;
1166{
1167  rseed = seed;
1168  last_random_value = 0;
1169}
1170
1171static SHELL_VAR *
1172assign_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
1183int
1184get_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
1201static SHELL_VAR *
1202get_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
1219static SHELL_VAR *
1220assign_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. */
1234static SHELL_VAR *
1235get_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
1248static SHELL_VAR *
1249assign_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
1262static SHELL_VAR *
1263get_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
1274static SHELL_VAR *
1275get_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)
1294static SHELL_VAR *
1295get_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. */
1309static SHELL_VAR *
1310get_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. */
1324static SHELL_VAR *
1325assign_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)
1340static SHELL_VAR *
1341assign_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
1350static SHELL_VAR *
1351get_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. */
1369static SHELL_VAR *
1370get_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. */
1391static SHELL_VAR *
1392get_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
1407void
1408make_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
1423static SHELL_VAR *
1424init_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
1440static void
1441initialize_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
1492static SHELL_VAR *
1493hash_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
1503SHELL_VAR *
1504var_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
1526SHELL_VAR *
1527find_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. */
1556SHELL_VAR *
1557find_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. */
1565SHELL_VAR *
1566find_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. */
1574FUNCTION_DEF *
1575find_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. */
1583char *
1584get_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. */
1602char *
1603get_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. */
1613char *
1614sh_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. */
1627SHELL_VAR *
1628set_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. */
1643SHELL_VAR *
1644make_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)
1718SHELL_VAR *
1719make_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. */
1739static SHELL_VAR *
1740new_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. */
1766static SHELL_VAR *
1767make_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)
1787SHELL_VAR *
1788make_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
1802char *
1803make_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	    {
1825	      top_level_cleanup ();
1826	      jump_to_top_level (DISCARD);
1827	    }
1828	}
1829      rval = evalexp (value, &expok);
1830      if (expok == 0)
1831	{
1832	  top_level_cleanup ();
1833	  jump_to_top_level (DISCARD);
1834	}
1835      if (flags & ASS_APPEND)
1836	rval += lval;
1837      retval = itos (rval);
1838    }
1839  else if (value)
1840    {
1841      if (flags & ASS_APPEND)
1842	{
1843	  oval = get_variable_value (var);
1844	  if (oval == 0)	/* paranoia */
1845	    oval = "";
1846	  olen = STRLEN (oval);
1847	  retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
1848	  strcpy (retval, oval);
1849	  if (value)
1850	    strcpy (retval+olen, value);
1851	}
1852      else if (*value)
1853	retval = savestring (value);
1854      else
1855	{
1856	  retval = (char *)xmalloc (1);
1857	  retval[0] = '\0';
1858	}
1859    }
1860  else
1861    retval = (char *)NULL;
1862
1863  return retval;
1864}
1865
1866/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
1867   temporary environment (but usually is not). */
1868static SHELL_VAR *
1869bind_variable_internal (name, value, table, hflags, aflags)
1870     const char *name;
1871     char *value;
1872     HASH_TABLE *table;
1873     int hflags, aflags;
1874{
1875  char *newval;
1876  SHELL_VAR *entry;
1877
1878  entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
1879
1880  if (entry == 0)
1881    {
1882      entry = make_new_variable (name, table);
1883      var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
1884    }
1885  else if (entry->assign_func)	/* array vars have assign functions now */
1886    {
1887      INVALIDATE_EXPORTSTR (entry);
1888      newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
1889      entry = (*(entry->assign_func)) (entry, newval, -1);
1890      if (newval != value)
1891        free (newval);
1892      return (entry);
1893    }
1894  else
1895    {
1896      if (readonly_p (entry) || noassign_p (entry))
1897	{
1898	  if (readonly_p (entry))
1899	    err_readonly (name);
1900	  return (entry);
1901	}
1902
1903      /* Variables which are bound are visible. */
1904      VUNSETATTR (entry, att_invisible);
1905
1906      newval = make_variable_value (entry, value, aflags);	/* XXX */
1907
1908      /* Invalidate any cached export string */
1909      INVALIDATE_EXPORTSTR (entry);
1910
1911#if defined (ARRAY_VARS)
1912      /* XXX -- this bears looking at again -- XXX */
1913      /* If an existing array variable x is being assigned to with x=b or
1914	 `read x' or something of that nature, silently convert it to
1915	 x[0]=b or `read x[0]'. */
1916      if (array_p (entry))
1917	{
1918	  array_insert (array_cell (entry), 0, newval);
1919	  free (newval);
1920	}
1921      else
1922#endif
1923	{
1924	  FREE (value_cell (entry));
1925	  var_setvalue (entry, newval);
1926	}
1927    }
1928
1929  if (mark_modified_vars)
1930    VSETATTR (entry, att_exported);
1931
1932  if (exported_p (entry))
1933    array_needs_making = 1;
1934
1935  return (entry);
1936}
1937
1938/* Bind a variable NAME to VALUE.  This conses up the name
1939   and value strings.  If we have a temporary environment, we bind there
1940   first, then we bind into shell_variables. */
1941
1942SHELL_VAR *
1943bind_variable (name, value, flags)
1944     const char *name;
1945     char *value;
1946     int flags;
1947{
1948  SHELL_VAR *v;
1949  VAR_CONTEXT *vc;
1950
1951  if (shell_variables == 0)
1952    create_variable_tables ();
1953
1954  /* If we have a temporary environment, look there first for the variable,
1955     and, if found, modify the value there before modifying it in the
1956     shell_variables table.  This allows sourced scripts to modify values
1957     given to them in a temporary environment while modifying the variable
1958     value that the caller sees. */
1959  if (temporary_env)
1960    bind_tempenv_variable (name, value);
1961
1962  /* XXX -- handle local variables here. */
1963  for (vc = shell_variables; vc; vc = vc->down)
1964    {
1965      if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
1966        {
1967          v = hash_lookup (name, vc->table);
1968          if (v)
1969	    return (bind_variable_internal (name, value, vc->table, 0, flags));
1970        }
1971    }
1972  return (bind_variable_internal (name, value, global_variables->table, 0, flags));
1973}
1974
1975/* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
1976   value, variables are no longer invisible.  This is a duplicate of part
1977   of the internals of bind_variable.  If the variable is exported, or
1978   all modified variables should be exported, mark the variable for export
1979   and note that the export environment needs to be recreated. */
1980SHELL_VAR *
1981bind_variable_value (var, value, aflags)
1982     SHELL_VAR *var;
1983     char *value;
1984     int aflags;
1985{
1986  char *t;
1987
1988  VUNSETATTR (var, att_invisible);
1989
1990  if (var->assign_func)
1991    {
1992      /* If we're appending, we need the old value, so use
1993	 make_variable_value */
1994      t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
1995      (*(var->assign_func)) (var, t, -1);
1996      if (t != value && t)
1997	free (t);
1998    }
1999  else
2000    {
2001      t = make_variable_value (var, value, aflags);
2002      FREE (value_cell (var));
2003      var_setvalue (var, t);
2004    }
2005
2006  INVALIDATE_EXPORTSTR (var);
2007
2008  if (mark_modified_vars)
2009    VSETATTR (var, att_exported);
2010
2011  if (exported_p (var))
2012    array_needs_making = 1;
2013
2014  return (var);
2015}
2016
2017/* Bind/create a shell variable with the name LHS to the RHS.
2018   This creates or modifies a variable such that it is an integer.
2019
2020   This used to be in expr.c, but it is here so that all of the
2021   variable binding stuff is localized.  Since we don't want any
2022   recursive evaluation from bind_variable() (possible without this code,
2023   since bind_variable() calls the evaluator for variables with the integer
2024   attribute set), we temporarily turn off the integer attribute for each
2025   variable we set here, then turn it back on after binding as necessary. */
2026
2027SHELL_VAR *
2028bind_int_variable (lhs, rhs)
2029     char *lhs, *rhs;
2030{
2031  register SHELL_VAR *v;
2032  int isint, isarr;
2033
2034  isint = isarr = 0;
2035#if defined (ARRAY_VARS)
2036  if (valid_array_reference (lhs))
2037    {
2038      isarr = 1;
2039      v = array_variable_part (lhs, (char **)0, (int *)0);
2040    }
2041  else
2042#endif
2043    v = find_variable (lhs);
2044
2045  if (v)
2046    {
2047      isint = integer_p (v);
2048      VUNSETATTR (v, att_integer);
2049    }
2050
2051#if defined (ARRAY_VARS)
2052  if (isarr)
2053    v = assign_array_element (lhs, rhs, 0);
2054  else
2055#endif
2056    v = bind_variable (lhs, rhs, 0);
2057
2058  if (isint)
2059    VSETATTR (v, att_integer);
2060
2061  return (v);
2062}
2063
2064SHELL_VAR *
2065bind_var_to_int (var, val)
2066     char *var;
2067     intmax_t val;
2068{
2069  char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
2070
2071  p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
2072  return (bind_int_variable (var, p));
2073}
2074
2075/* Do a function binding to a variable.  You pass the name and
2076   the command to bind to.  This conses the name and command. */
2077SHELL_VAR *
2078bind_function (name, value)
2079     const char *name;
2080     COMMAND *value;
2081{
2082  SHELL_VAR *entry;
2083
2084  entry = find_function (name);
2085  if (entry == 0)
2086    {
2087      BUCKET_CONTENTS *elt;
2088
2089      elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2090      entry = new_shell_variable (name);
2091      elt->data = (PTR_T)entry;
2092    }
2093  else
2094    INVALIDATE_EXPORTSTR (entry);
2095
2096  if (var_isset (entry))
2097    dispose_command (function_cell (entry));
2098
2099  if (value)
2100    var_setfunc (entry, copy_command (value));
2101  else
2102    var_setfunc (entry, 0);
2103
2104  VSETATTR (entry, att_function);
2105
2106  if (mark_modified_vars)
2107    VSETATTR (entry, att_exported);
2108
2109  VUNSETATTR (entry, att_invisible);		/* Just to be sure */
2110
2111  if (exported_p (entry))
2112    array_needs_making = 1;
2113
2114#if defined (PROGRAMMABLE_COMPLETION)
2115  set_itemlist_dirty (&it_functions);
2116#endif
2117
2118  return (entry);
2119}
2120
2121/* Bind a function definition, which includes source file and line number
2122   information in addition to the command, into the FUNCTION_DEF hash table.*/
2123void
2124bind_function_def (name, value)
2125     const char *name;
2126     FUNCTION_DEF *value;
2127{
2128  FUNCTION_DEF *entry;
2129  BUCKET_CONTENTS *elt;
2130  COMMAND *cmd;
2131
2132  entry = find_function_def (name);
2133  if (entry)
2134    {
2135      dispose_function_def_contents (entry);
2136      entry = copy_function_def_contents (value, entry);
2137    }
2138  else
2139    {
2140      cmd = value->command;
2141      value->command = 0;
2142      entry = copy_function_def (value);
2143      value->command = cmd;
2144
2145      elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2146      elt->data = (PTR_T *)entry;
2147    }
2148}
2149
2150/* Add STRING, which is of the form foo=bar, to the temporary environment
2151   HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
2152   responsible for moving the main temporary env to one of the other
2153   temporary environments.  The expansion code in subst.c calls this. */
2154int
2155assign_in_env (word)
2156     WORD_DESC *word;
2157{
2158  int offset;
2159  char *name, *temp, *value;
2160  SHELL_VAR *var;
2161  const char *string;
2162
2163  string = word->word;
2164
2165  offset = assignment (string, 0);
2166  name = savestring (string);
2167  value = (char *)NULL;
2168
2169  if (name[offset] == '=')
2170    {
2171      name[offset] = 0;
2172
2173      /* ignore the `+' when assigning temporary environment */
2174      if (name[offset - 1] == '+')
2175	name[offset - 1] = '\0';
2176
2177      var = find_variable (name);
2178      if (var && (readonly_p (var) || noassign_p (var)))
2179	{
2180	  if (readonly_p (var))
2181	    err_readonly (name);
2182	  free (name);
2183  	  return (0);
2184	}
2185
2186      temp = name + offset + 1;
2187#if 0
2188      temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
2189      value = expand_string_unsplit_to_string (temp, 0);
2190      free (temp);
2191#else
2192      value = expand_assignment_string_to_string (temp, 0);
2193#endif
2194    }
2195
2196  if (temporary_env == 0)
2197    temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2198
2199  var = hash_lookup (name, temporary_env);
2200  if (var == 0)
2201    var = make_new_variable (name, temporary_env);
2202  else
2203    FREE (value_cell (var));
2204
2205  if (value == 0)
2206    {
2207      value = (char *)xmalloc (1);	/* like do_assignment_internal */
2208      value[0] = '\0';
2209    }
2210
2211  var_setvalue (var, value);
2212  var->attributes |= (att_exported|att_tempvar);
2213  var->context = variable_context;	/* XXX */
2214
2215  INVALIDATE_EXPORTSTR (var);
2216  var->exportstr = mk_env_string (name, value);
2217
2218  array_needs_making = 1;
2219
2220  if (ifsname (name))
2221    setifs (var);
2222
2223  if (echo_command_at_execute)
2224    /* The Korn shell prints the `+ ' in front of assignment statements,
2225	so we do too. */
2226    xtrace_print_assignment (name, value, 0, 1);
2227
2228  free (name);
2229  return 1;
2230}
2231
2232/* **************************************************************** */
2233/*								    */
2234/*			Copying variables			    */
2235/*								    */
2236/* **************************************************************** */
2237
2238#ifdef INCLUDE_UNUSED
2239/* Copy VAR to a new data structure and return that structure. */
2240SHELL_VAR *
2241copy_variable (var)
2242     SHELL_VAR *var;
2243{
2244  SHELL_VAR *copy = (SHELL_VAR *)NULL;
2245
2246  if (var)
2247    {
2248      copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2249
2250      copy->attributes = var->attributes;
2251      copy->name = savestring (var->name);
2252
2253      if (function_p (var))
2254	var_setfunc (copy, copy_command (function_cell (var)));
2255#if defined (ARRAY_VARS)
2256      else if (array_p (var))
2257	var_setarray (copy, dup_array (array_cell (var)));
2258#endif
2259      else if (value_cell (var))
2260	var_setvalue (copy, savestring (value_cell (var)));
2261      else
2262	var_setvalue (copy, (char *)NULL);
2263
2264      copy->dynamic_value = var->dynamic_value;
2265      copy->assign_func = var->assign_func;
2266
2267      copy->exportstr = COPY_EXPORTSTR (var);
2268
2269      copy->context = var->context;
2270    }
2271  return (copy);
2272}
2273#endif
2274
2275/* **************************************************************** */
2276/*								    */
2277/*		  Deleting and unsetting variables		    */
2278/*								    */
2279/* **************************************************************** */
2280
2281/* Dispose of the information attached to VAR. */
2282void
2283dispose_variable (var)
2284     SHELL_VAR *var;
2285{
2286  if (var == 0)
2287    return;
2288
2289  if (function_p (var))
2290    dispose_command (function_cell (var));
2291#if defined (ARRAY_VARS)
2292  else if (array_p (var))
2293    array_dispose (array_cell (var));
2294#endif
2295  else
2296    FREE (value_cell (var));
2297
2298  FREE_EXPORTSTR (var);
2299
2300  free (var->name);
2301
2302  if (exported_p (var))
2303    array_needs_making = 1;
2304
2305  free (var);
2306}
2307
2308/* Unset the shell variable referenced by NAME. */
2309int
2310unbind_variable (name)
2311     const char *name;
2312{
2313  return makunbound (name, shell_variables);
2314}
2315
2316/* Unset the shell function named NAME. */
2317int
2318unbind_func (name)
2319     const char *name;
2320{
2321  BUCKET_CONTENTS *elt;
2322  SHELL_VAR *func;
2323
2324  elt = hash_remove (name, shell_functions, 0);
2325
2326  if (elt == 0)
2327    return -1;
2328
2329#if defined (PROGRAMMABLE_COMPLETION)
2330  set_itemlist_dirty (&it_functions);
2331#endif
2332
2333  func = (SHELL_VAR *)elt->data;
2334  if (func)
2335    {
2336      if (exported_p (func))
2337	array_needs_making++;
2338      dispose_variable (func);
2339    }
2340
2341  free (elt->key);
2342  free (elt);
2343
2344  return 0;
2345}
2346
2347int
2348unbind_function_def (name)
2349     const char *name;
2350{
2351  BUCKET_CONTENTS *elt;
2352  FUNCTION_DEF *funcdef;
2353
2354  elt = hash_remove (name, shell_function_defs, 0);
2355
2356  if (elt == 0)
2357    return -1;
2358
2359  funcdef = (FUNCTION_DEF *)elt->data;
2360  if (funcdef)
2361    dispose_function_def (funcdef);
2362
2363  free (elt->key);
2364  free (elt);
2365
2366  return 0;
2367}
2368
2369/* Make the variable associated with NAME go away.  HASH_LIST is the
2370   hash table from which this variable should be deleted (either
2371   shell_variables or shell_functions).
2372   Returns non-zero if the variable couldn't be found. */
2373int
2374makunbound (name, vc)
2375     const char *name;
2376     VAR_CONTEXT *vc;
2377{
2378  BUCKET_CONTENTS *elt, *new_elt;
2379  SHELL_VAR *old_var;
2380  VAR_CONTEXT *v;
2381  char *t;
2382
2383  for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2384    if (elt = hash_remove (name, v->table, 0))
2385      break;
2386
2387  if (elt == 0)
2388    return (-1);
2389
2390  old_var = (SHELL_VAR *)elt->data;
2391
2392  if (old_var && exported_p (old_var))
2393    array_needs_making++;
2394
2395  /* If we're unsetting a local variable and we're still executing inside
2396     the function, just mark the variable as invisible.  The function
2397     eventually called by pop_var_context() will clean it up later.  This
2398     must be done so that if the variable is subsequently assigned a new
2399     value inside the function, the `local' attribute is still present.
2400     We also need to add it back into the correct hash table. */
2401  if (old_var && local_p (old_var) && variable_context == old_var->context)
2402    {
2403#if defined (ARRAY_VARS)
2404      if (array_p (old_var))
2405	array_dispose (array_cell (old_var));
2406      else
2407#endif
2408	FREE (value_cell (old_var));
2409      /* Reset the attributes.  Preserve the export attribute if the variable
2410         came from a temporary environment.  Make sure it stays local, and
2411         make it invisible. */
2412      old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
2413      VSETATTR (old_var, att_local);
2414      VSETATTR (old_var, att_invisible);
2415      var_setvalue (old_var, (char *)NULL);
2416      INVALIDATE_EXPORTSTR (old_var);
2417
2418      new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2419      new_elt->data = (PTR_T)old_var;
2420      stupidly_hack_special_variables (old_var->name);
2421
2422      free (elt->key);
2423      free (elt);
2424      return (0);
2425    }
2426
2427  /* Have to save a copy of name here, because it might refer to
2428     old_var->name.  If so, stupidly_hack_special_variables will
2429     reference freed memory. */
2430  t = savestring (name);
2431
2432  free (elt->key);
2433  free (elt);
2434
2435  dispose_variable (old_var);
2436  stupidly_hack_special_variables (t);
2437  free (t);
2438
2439  return (0);
2440}
2441
2442/* Get rid of all of the variables in the current context. */
2443void
2444kill_all_local_variables ()
2445{
2446  VAR_CONTEXT *vc;
2447
2448  for (vc = shell_variables; vc; vc = vc->down)
2449    if (vc_isfuncenv (vc) && vc->scope == variable_context)
2450      break;
2451  if (vc == 0)
2452    return;		/* XXX */
2453
2454  if (vc->table && vc_haslocals (vc))
2455    {
2456      delete_all_variables (vc->table);
2457      hash_dispose (vc->table);
2458    }
2459  vc->table = (HASH_TABLE *)NULL;
2460}
2461
2462static void
2463free_variable_hash_data (data)
2464     PTR_T data;
2465{
2466  SHELL_VAR *var;
2467
2468  var = (SHELL_VAR *)data;
2469  dispose_variable (var);
2470}
2471
2472/* Delete the entire contents of the hash table. */
2473void
2474delete_all_variables (hashed_vars)
2475     HASH_TABLE *hashed_vars;
2476{
2477  hash_flush (hashed_vars, free_variable_hash_data);
2478}
2479
2480/* **************************************************************** */
2481/*								    */
2482/*		     Setting variable attributes		    */
2483/*								    */
2484/* **************************************************************** */
2485
2486#define FIND_OR_MAKE_VARIABLE(name, entry) \
2487  do \
2488    { \
2489      entry = find_variable (name); \
2490      if (!entry) \
2491	{ \
2492	  entry = bind_variable (name, "", 0); \
2493	  if (!no_invisible_vars) entry->attributes |= att_invisible; \
2494	} \
2495    } \
2496  while (0)
2497
2498/* Make the variable associated with NAME be readonly.
2499   If NAME does not exist yet, create it. */
2500void
2501set_var_read_only (name)
2502     char *name;
2503{
2504  SHELL_VAR *entry;
2505
2506  FIND_OR_MAKE_VARIABLE (name, entry);
2507  VSETATTR (entry, att_readonly);
2508}
2509
2510#ifdef INCLUDE_UNUSED
2511/* Make the function associated with NAME be readonly.
2512   If NAME does not exist, we just punt, like auto_export code below. */
2513void
2514set_func_read_only (name)
2515     const char *name;
2516{
2517  SHELL_VAR *entry;
2518
2519  entry = find_function (name);
2520  if (entry)
2521    VSETATTR (entry, att_readonly);
2522}
2523
2524/* Make the variable associated with NAME be auto-exported.
2525   If NAME does not exist yet, create it. */
2526void
2527set_var_auto_export (name)
2528     char *name;
2529{
2530  SHELL_VAR *entry;
2531
2532  FIND_OR_MAKE_VARIABLE (name, entry);
2533  set_auto_export (entry);
2534}
2535
2536/* Make the function associated with NAME be auto-exported. */
2537void
2538set_func_auto_export (name)
2539     const char *name;
2540{
2541  SHELL_VAR *entry;
2542
2543  entry = find_function (name);
2544  if (entry)
2545    set_auto_export (entry);
2546}
2547#endif
2548
2549/* **************************************************************** */
2550/*								    */
2551/*		     Creating lists of variables		    */
2552/*								    */
2553/* **************************************************************** */
2554
2555static VARLIST *
2556vlist_alloc (nentries)
2557     int nentries;
2558{
2559  VARLIST  *vlist;
2560
2561  vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2562  vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2563  vlist->list_size = nentries;
2564  vlist->list_len = 0;
2565  vlist->list[0] = (SHELL_VAR *)NULL;
2566
2567  return vlist;
2568}
2569
2570static VARLIST *
2571vlist_realloc (vlist, n)
2572     VARLIST *vlist;
2573     int n;
2574{
2575  if (vlist == 0)
2576    return (vlist = vlist_alloc (n));
2577  if (n > vlist->list_size)
2578    {
2579      vlist->list_size = n;
2580      vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2581    }
2582  return vlist;
2583}
2584
2585static void
2586vlist_add (vlist, var, flags)
2587     VARLIST *vlist;
2588     SHELL_VAR *var;
2589     int flags;
2590{
2591  register int i;
2592
2593  for (i = 0; i < vlist->list_len; i++)
2594    if (STREQ (var->name, vlist->list[i]->name))
2595      break;
2596  if (i < vlist->list_len)
2597    return;
2598
2599  if (i >= vlist->list_size)
2600    vlist = vlist_realloc (vlist, vlist->list_size + 16);
2601
2602  vlist->list[vlist->list_len++] = var;
2603  vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2604}
2605
2606/* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
2607   variables for which FUNCTION returns a non-zero value.  A NULL value
2608   for FUNCTION means to use all variables. */
2609SHELL_VAR **
2610map_over (function, vc)
2611     sh_var_map_func_t *function;
2612     VAR_CONTEXT *vc;
2613{
2614  VAR_CONTEXT *v;
2615  VARLIST *vlist;
2616  SHELL_VAR **ret;
2617  int nentries;
2618
2619  for (nentries = 0, v = vc; v; v = v->down)
2620    nentries += HASH_ENTRIES (v->table);
2621
2622  if (nentries == 0)
2623    return (SHELL_VAR **)NULL;
2624
2625  vlist = vlist_alloc (nentries);
2626
2627  for (v = vc; v; v = v->down)
2628    flatten (v->table, function, vlist, 0);
2629
2630  ret = vlist->list;
2631  free (vlist);
2632  return ret;
2633}
2634
2635SHELL_VAR **
2636map_over_funcs (function)
2637     sh_var_map_func_t *function;
2638{
2639  VARLIST *vlist;
2640  SHELL_VAR **ret;
2641
2642  if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2643    return ((SHELL_VAR **)NULL);
2644
2645  vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2646
2647  flatten (shell_functions, function, vlist, 0);
2648
2649  ret = vlist->list;
2650  free (vlist);
2651  return ret;
2652}
2653
2654/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2655   elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved
2656   for future use.  Only unique names are added to VLIST.  If FUNC is
2657   NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is
2658   NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST
2659   and FUNC are both NULL, nothing happens. */
2660static void
2661flatten (var_hash_table, func, vlist, flags)
2662     HASH_TABLE *var_hash_table;
2663     sh_var_map_func_t *func;
2664     VARLIST *vlist;
2665     int flags;
2666{
2667  register int i;
2668  register BUCKET_CONTENTS *tlist;
2669  int r;
2670  SHELL_VAR *var;
2671
2672  if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
2673    return;
2674
2675  for (i = 0; i < var_hash_table->nbuckets; i++)
2676    {
2677      for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
2678	{
2679	  var = (SHELL_VAR *)tlist->data;
2680
2681	  r = func ? (*func) (var) : 1;
2682	  if (r && vlist)
2683	    vlist_add (vlist, var, flags);
2684	}
2685    }
2686}
2687
2688void
2689sort_variables (array)
2690     SHELL_VAR **array;
2691{
2692  qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
2693}
2694
2695static int
2696qsort_var_comp (var1, var2)
2697     SHELL_VAR **var1, **var2;
2698{
2699  int result;
2700
2701  if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
2702    result = strcmp ((*var1)->name, (*var2)->name);
2703
2704  return (result);
2705}
2706
2707/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
2708   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
2709static SHELL_VAR **
2710vapply (func)
2711     sh_var_map_func_t *func;
2712{
2713  SHELL_VAR **list;
2714
2715  list = map_over (func, shell_variables);
2716  if (list /* && posixly_correct */)
2717    sort_variables (list);
2718  return (list);
2719}
2720
2721/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
2722   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
2723static SHELL_VAR **
2724fapply (func)
2725     sh_var_map_func_t *func;
2726{
2727  SHELL_VAR **list;
2728
2729  list = map_over_funcs (func);
2730  if (list /* && posixly_correct */)
2731    sort_variables (list);
2732  return (list);
2733}
2734
2735/* Create a NULL terminated array of all the shell variables. */
2736SHELL_VAR **
2737all_shell_variables ()
2738{
2739  return (vapply ((sh_var_map_func_t *)NULL));
2740}
2741
2742/* Create a NULL terminated array of all the shell functions. */
2743SHELL_VAR **
2744all_shell_functions ()
2745{
2746  return (fapply ((sh_var_map_func_t *)NULL));
2747}
2748
2749static int
2750visible_var (var)
2751     SHELL_VAR *var;
2752{
2753  return (invisible_p (var) == 0);
2754}
2755
2756SHELL_VAR **
2757all_visible_functions ()
2758{
2759  return (fapply (visible_var));
2760}
2761
2762SHELL_VAR **
2763all_visible_variables ()
2764{
2765  return (vapply (visible_var));
2766}
2767
2768/* Return non-zero if the variable VAR is visible and exported.  Array
2769   variables cannot be exported. */
2770static int
2771visible_and_exported (var)
2772     SHELL_VAR *var;
2773{
2774  return (invisible_p (var) == 0 && exported_p (var));
2775}
2776
2777/* Return non-zero if VAR is a local variable in the current context and
2778   is exported. */
2779static int
2780local_and_exported (var)
2781     SHELL_VAR *var;
2782{
2783  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
2784}
2785
2786SHELL_VAR **
2787all_exported_variables ()
2788{
2789  return (vapply (visible_and_exported));
2790}
2791
2792SHELL_VAR **
2793local_exported_variables ()
2794{
2795  return (vapply (local_and_exported));
2796}
2797
2798static int
2799variable_in_context (var)
2800     SHELL_VAR *var;
2801{
2802  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
2803}
2804
2805SHELL_VAR **
2806all_local_variables ()
2807{
2808  VARLIST *vlist;
2809  SHELL_VAR **ret;
2810  VAR_CONTEXT *vc;
2811
2812  vc = shell_variables;
2813  for (vc = shell_variables; vc; vc = vc->down)
2814    if (vc_isfuncenv (vc) && vc->scope == variable_context)
2815      break;
2816
2817  if (vc == 0)
2818    {
2819      internal_error (_("all_local_variables: no function context at current scope"));
2820      return (SHELL_VAR **)NULL;
2821    }
2822  if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
2823    return (SHELL_VAR **)NULL;
2824
2825  vlist = vlist_alloc (HASH_ENTRIES (vc->table));
2826
2827  flatten (vc->table, variable_in_context, vlist, 0);
2828
2829  ret = vlist->list;
2830  free (vlist);
2831  if (ret)
2832    sort_variables (ret);
2833  return ret;
2834}
2835
2836#if defined (ARRAY_VARS)
2837/* Return non-zero if the variable VAR is visible and an array. */
2838static int
2839visible_array_vars (var)
2840     SHELL_VAR *var;
2841{
2842  return (invisible_p (var) == 0 && array_p (var));
2843}
2844
2845SHELL_VAR **
2846all_array_variables ()
2847{
2848  return (vapply (visible_array_vars));
2849}
2850#endif /* ARRAY_VARS */
2851
2852char **
2853all_variables_matching_prefix (prefix)
2854     const char *prefix;
2855{
2856  SHELL_VAR **varlist;
2857  char **rlist;
2858  int vind, rind, plen;
2859
2860  plen = STRLEN (prefix);
2861  varlist = all_visible_variables ();
2862  for (vind = 0; varlist && varlist[vind]; vind++)
2863    ;
2864  if (varlist == 0 || vind == 0)
2865    return ((char **)NULL);
2866  rlist = strvec_create (vind + 1);
2867  for (vind = rind = 0; varlist[vind]; vind++)
2868    {
2869      if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
2870	rlist[rind++] = savestring (varlist[vind]->name);
2871    }
2872  rlist[rind] = (char *)0;
2873  free (varlist);
2874
2875  return rlist;
2876}
2877
2878/* **************************************************************** */
2879/*								    */
2880/*		 Managing temporary variable scopes		    */
2881/*								    */
2882/* **************************************************************** */
2883
2884/* Make variable NAME have VALUE in the temporary environment. */
2885static SHELL_VAR *
2886bind_tempenv_variable (name, value)
2887     const char *name;
2888     char *value;
2889{
2890  SHELL_VAR *var;
2891
2892  var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
2893
2894  if (var)
2895    {
2896      FREE (value_cell (var));
2897      var_setvalue (var, savestring (value));
2898      INVALIDATE_EXPORTSTR (var);
2899    }
2900
2901  return (var);
2902}
2903
2904/* Find a variable in the temporary environment that is named NAME.
2905   Return the SHELL_VAR *, or NULL if not found. */
2906SHELL_VAR *
2907find_tempenv_variable (name)
2908     const char *name;
2909{
2910  return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
2911}
2912
2913/* Push the variable described by (SHELL_VAR *)DATA down to the next
2914   variable context from the temporary environment. */
2915static void
2916push_temp_var (data)
2917     PTR_T data;
2918{
2919  SHELL_VAR *var, *v;
2920  HASH_TABLE *binding_table;
2921
2922  var = (SHELL_VAR *)data;
2923
2924  binding_table = shell_variables->table;
2925  if (binding_table == 0)
2926    {
2927      if (shell_variables == global_variables)
2928	/* shouldn't happen */
2929	binding_table = shell_variables->table = global_variables->table = hash_create (0);
2930      else
2931	binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
2932    }
2933
2934  v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
2935
2936  /* XXX - should we set the context here?  It shouldn't matter because of how
2937     assign_in_env works, but might want to check. */
2938  if (binding_table == global_variables->table)		/* XXX */
2939    var->attributes &= ~(att_tempvar|att_propagate);
2940  else
2941    {
2942      var->attributes |= att_propagate;
2943      if  (binding_table == shell_variables->table)
2944	shell_variables->flags |= VC_HASTMPVAR;
2945    }
2946  v->attributes |= var->attributes;
2947
2948  dispose_variable (var);
2949}
2950
2951static void
2952propagate_temp_var (data)
2953     PTR_T data;
2954{
2955  SHELL_VAR *var;
2956
2957  var = (SHELL_VAR *)data;
2958  if (tempvar_p (var) && (var->attributes & att_propagate))
2959    push_temp_var (data);
2960  else
2961    dispose_variable (var);
2962}
2963
2964/* Free the storage used in the hash table for temporary
2965   environment variables.  PUSHF is a function to be called
2966   to free each hash table entry.  It takes care of pushing variables
2967   to previous scopes if appropriate. */
2968static void
2969dispose_temporary_env (pushf)
2970     sh_free_func_t *pushf;
2971{
2972  hash_flush (temporary_env, pushf);
2973  hash_dispose (temporary_env);
2974  temporary_env  = (HASH_TABLE *)NULL;
2975
2976  array_needs_making = 1;
2977
2978  sv_ifs ("IFS");		/* XXX here for now */
2979}
2980
2981void
2982dispose_used_env_vars ()
2983{
2984  if (temporary_env)
2985    {
2986      dispose_temporary_env (propagate_temp_var);
2987      maybe_make_export_env ();
2988    }
2989}
2990
2991/* Take all of the shell variables in the temporary environment HASH_TABLE
2992   and make shell variables from them at the current variable context. */
2993void
2994merge_temporary_env ()
2995{
2996  if (temporary_env)
2997    dispose_temporary_env (push_temp_var);
2998}
2999
3000/* **************************************************************** */
3001/*								    */
3002/*	     Creating and manipulating the environment		    */
3003/*								    */
3004/* **************************************************************** */
3005
3006static inline char *
3007mk_env_string (name, value)
3008     const char *name, *value;
3009{
3010  int name_len, value_len;
3011  char	*p;
3012
3013  name_len = strlen (name);
3014  value_len = STRLEN (value);
3015  p = (char *)xmalloc (2 + name_len + value_len);
3016  strcpy (p, name);
3017  p[name_len] = '=';
3018  if (value && *value)
3019    strcpy (p + name_len + 1, value);
3020  else
3021    p[name_len + 1] = '\0';
3022  return (p);
3023}
3024
3025#ifdef DEBUG
3026/* Debugging */
3027static int
3028valid_exportstr (v)
3029     SHELL_VAR *v;
3030{
3031  char *s;
3032
3033  s = v->exportstr;
3034  if (legal_variable_starter ((unsigned char)*s) == 0)
3035    {
3036      internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3037      return (0);
3038    }
3039  for (s = v->exportstr + 1; s && *s; s++)
3040    {
3041      if (*s == '=')
3042	break;
3043      if (legal_variable_char ((unsigned char)*s) == 0)
3044	{
3045	  internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3046	  return (0);
3047	}
3048    }
3049  if (*s != '=')
3050    {
3051      internal_error (_("no `=' in exportstr for %s"), v->name);
3052      return (0);
3053    }
3054  return (1);
3055}
3056#endif
3057
3058static char **
3059make_env_array_from_var_list (vars)
3060     SHELL_VAR **vars;
3061{
3062  register int i, list_index;
3063  register SHELL_VAR *var;
3064  char **list, *value;
3065
3066  list = strvec_create ((1 + strvec_len ((char **)vars)));
3067
3068#define USE_EXPORTSTR (value == var->exportstr)
3069
3070  for (i = 0, list_index = 0; var = vars[i]; i++)
3071    {
3072#if defined (__CYGWIN__)
3073      /* We don't use the exportstr stuff on Cygwin at all. */
3074      INVALIDATE_EXPORTSTR (var);
3075#endif
3076      if (var->exportstr)
3077	value = var->exportstr;
3078      else if (function_p (var))
3079	value = named_function_string ((char *)NULL, function_cell (var), 0);
3080#if defined (ARRAY_VARS)
3081      else if (array_p (var))
3082#  if 0
3083	value = array_to_assignment_string (array_cell (var));
3084#  else
3085	continue;	/* XXX array vars cannot yet be exported */
3086#  endif
3087#endif
3088      else
3089	value = value_cell (var);
3090
3091      if (value)
3092	{
3093	  /* Gee, I'd like to get away with not using savestring() if we're
3094	     using the cached exportstr... */
3095	  list[list_index] = USE_EXPORTSTR ? savestring (value)
3096					   : mk_env_string (var->name, value);
3097
3098	  if (USE_EXPORTSTR == 0)
3099	    SAVE_EXPORTSTR (var, list[list_index]);
3100
3101	  list_index++;
3102#undef USE_EXPORTSTR
3103
3104#if 0	/* not yet */
3105#if defined (ARRAY_VARS)
3106	  if (array_p (var))
3107	    free (value);
3108#endif
3109#endif
3110	}
3111    }
3112
3113  list[list_index] = (char *)NULL;
3114  return (list);
3115}
3116
3117/* Make an array of assignment statements from the hash table
3118   HASHED_VARS which contains SHELL_VARs.  Only visible, exported
3119   variables are eligible. */
3120static char **
3121make_var_export_array (vcxt)
3122     VAR_CONTEXT *vcxt;
3123{
3124  char **list;
3125  SHELL_VAR **vars;
3126
3127  vars = map_over (visible_and_exported, vcxt);
3128
3129  if (vars == 0)
3130    return (char **)NULL;
3131
3132  list = make_env_array_from_var_list (vars);
3133
3134  free (vars);
3135  return (list);
3136}
3137
3138static char **
3139make_func_export_array ()
3140{
3141  char **list;
3142  SHELL_VAR **vars;
3143
3144  vars = map_over_funcs (visible_and_exported);
3145  if (vars == 0)
3146    return (char **)NULL;
3147
3148  list = make_env_array_from_var_list (vars);
3149
3150  free (vars);
3151  return (list);
3152}
3153
3154/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3155#define add_to_export_env(envstr,do_alloc) \
3156do \
3157  { \
3158    if (export_env_index >= (export_env_size - 1)) \
3159      { \
3160	export_env_size += 16; \
3161	export_env = strvec_resize (export_env, export_env_size); \
3162	environ = export_env; \
3163      } \
3164    export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3165    export_env[export_env_index] = (char *)NULL; \
3166  } while (0)
3167
3168/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3169   array with the same left-hand side.  Return the new EXPORT_ENV. */
3170char **
3171add_or_supercede_exported_var (assign, do_alloc)
3172     char *assign;
3173     int do_alloc;
3174{
3175  register int i;
3176  int equal_offset;
3177
3178  equal_offset = assignment (assign, 0);
3179  if (equal_offset == 0)
3180    return (export_env);
3181
3182  /* If this is a function, then only supersede the function definition.
3183     We do this by including the `=() {' in the comparison, like
3184     initialize_shell_variables does. */
3185  if (assign[equal_offset + 1] == '(' &&
3186     strncmp (assign + equal_offset + 2, ") {", 3) == 0)		/* } */
3187    equal_offset += 4;
3188
3189  for (i = 0; i < export_env_index; i++)
3190    {
3191      if (STREQN (assign, export_env[i], equal_offset + 1))
3192	{
3193	  free (export_env[i]);
3194	  export_env[i] = do_alloc ? savestring (assign) : assign;
3195	  return (export_env);
3196	}
3197    }
3198  add_to_export_env (assign, do_alloc);
3199  return (export_env);
3200}
3201
3202static void
3203add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3204     char **temp_array;
3205     int do_alloc, do_supercede;
3206{
3207  register int i;
3208
3209  if (temp_array == 0)
3210    return;
3211
3212  for (i = 0; temp_array[i]; i++)
3213    {
3214      if (do_supercede)
3215	export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3216      else
3217	add_to_export_env (temp_array[i], do_alloc);
3218    }
3219
3220  free (temp_array);
3221}
3222
3223/* Make the environment array for the command about to be executed, if the
3224   array needs making.  Otherwise, do nothing.  If a shell action could
3225   change the array that commands receive for their environment, then the
3226   code should `array_needs_making++'.
3227
3228   The order to add to the array is:
3229   	temporary_env
3230   	list of var contexts whose head is shell_variables
3231  	shell_functions
3232
3233  This is the shell variable lookup order.  We add only new variable
3234  names at each step, which allows local variables and variables in
3235  the temporary environments to shadow variables in the global (or
3236  any previous) scope.
3237*/
3238
3239static int
3240n_shell_variables ()
3241{
3242  VAR_CONTEXT *vc;
3243  int n;
3244
3245  for (n = 0, vc = shell_variables; vc; vc = vc->down)
3246    n += HASH_ENTRIES (vc->table);
3247  return n;
3248}
3249
3250void
3251maybe_make_export_env ()
3252{
3253  register char **temp_array;
3254  int new_size;
3255  VAR_CONTEXT *tcxt;
3256
3257  if (array_needs_making)
3258    {
3259      if (export_env)
3260        strvec_flush (export_env);
3261
3262      /* Make a guess based on how many shell variables and functions we
3263	 have.  Since there will always be array variables, and array
3264	 variables are not (yet) exported, this will always be big enough
3265	 for the exported variables and functions. */
3266      new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3267		 HASH_ENTRIES (temporary_env);
3268      if (new_size > export_env_size)
3269	{
3270	  export_env_size = new_size;
3271	  export_env = strvec_resize (export_env, export_env_size);
3272	  environ = export_env;
3273	}
3274      export_env[export_env_index = 0] = (char *)NULL;
3275
3276      /* Make a dummy variable context from the  temporary_env, stick it on
3277         the front of shell_variables, call make_var_export_array on the
3278         whole thing to flatten it, and convert the list of SHELL_VAR *s
3279         to the form needed by the environment. */
3280      if (temporary_env)
3281        {
3282          tcxt = new_var_context ((char *)NULL, 0);
3283          tcxt->table = temporary_env;
3284          tcxt->down = shell_variables;
3285        }
3286      else
3287        tcxt = shell_variables;
3288
3289      temp_array = make_var_export_array (tcxt);
3290      if (temp_array)
3291	add_temp_array_to_env (temp_array, 0, 0);
3292
3293      if (tcxt != shell_variables)
3294        free (tcxt);
3295
3296#if defined (RESTRICTED_SHELL)
3297      /* Restricted shells may not export shell functions. */
3298      temp_array = restricted ? (char **)0 : make_func_export_array ();
3299#else
3300      temp_array = make_func_export_array ();
3301#endif
3302      if (temp_array)
3303	add_temp_array_to_env (temp_array, 0, 0);
3304
3305      array_needs_making = 0;
3306    }
3307}
3308
3309/* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
3310   we will need to remake the exported environment every time we
3311   change directories.  `_' is always put into the environment for
3312   every external command, so without special treatment it will always
3313   cause the environment to be remade.
3314
3315   If there is no other reason to make the exported environment, we can
3316   just update the variables in place and mark the exported environment
3317   as no longer needing a remake. */
3318void
3319update_export_env_inplace (env_prefix, preflen, value)
3320     char *env_prefix;
3321     int preflen;
3322     char *value;
3323{
3324  char *evar;
3325
3326  evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
3327  strcpy (evar, env_prefix);
3328  if (value)
3329    strcpy (evar + preflen, value);
3330  export_env = add_or_supercede_exported_var (evar, 0);
3331}
3332
3333/* We always put _ in the environment as the name of this command. */
3334void
3335put_command_name_into_env (command_name)
3336     char *command_name;
3337{
3338  update_export_env_inplace ("_=", 2, command_name);
3339}
3340
3341#if 0	/* UNUSED -- it caused too many problems */
3342void
3343put_gnu_argv_flags_into_env (pid, flags_string)
3344     intmax_t pid;
3345     char *flags_string;
3346{
3347  char *dummy, *pbuf;
3348  int l, fl;
3349
3350  pbuf = itos (pid);
3351  l = strlen (pbuf);
3352
3353  fl = strlen (flags_string);
3354
3355  dummy = (char *)xmalloc (l + fl + 30);
3356  dummy[0] = '_';
3357  strcpy (dummy + 1, pbuf);
3358  strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3359  dummy[l + 27] = '=';
3360  strcpy (dummy + l + 28, flags_string);
3361
3362  free (pbuf);
3363
3364  export_env = add_or_supercede_exported_var (dummy, 0);
3365}
3366#endif
3367
3368/* **************************************************************** */
3369/*								    */
3370/*		      Managing variable contexts		    */
3371/*								    */
3372/* **************************************************************** */
3373
3374/* Allocate and return a new variable context with NAME and FLAGS.
3375   NAME can be NULL. */
3376
3377VAR_CONTEXT *
3378new_var_context (name, flags)
3379     char *name;
3380     int flags;
3381{
3382  VAR_CONTEXT *vc;
3383
3384  vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3385  vc->name = name ? savestring (name) : (char *)NULL;
3386  vc->scope = variable_context;
3387  vc->flags = flags;
3388
3389  vc->up = vc->down = (VAR_CONTEXT *)NULL;
3390  vc->table = (HASH_TABLE *)NULL;
3391
3392  return vc;
3393}
3394
3395/* Free a variable context and its data, including the hash table.  Dispose
3396   all of the variables. */
3397void
3398dispose_var_context (vc)
3399     VAR_CONTEXT *vc;
3400{
3401  FREE (vc->name);
3402
3403  if (vc->table)
3404    {
3405      delete_all_variables (vc->table);
3406      hash_dispose (vc->table);
3407    }
3408
3409  free (vc);
3410}
3411
3412/* Set VAR's scope level to the current variable context. */
3413static int
3414set_context (var)
3415     SHELL_VAR *var;
3416{
3417  return (var->context = variable_context);
3418}
3419
3420/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3421   temporary variables, and push it onto shell_variables.  This is
3422   for shell functions. */
3423VAR_CONTEXT *
3424push_var_context (name, flags, tempvars)
3425     char *name;
3426     int flags;
3427     HASH_TABLE *tempvars;
3428{
3429  VAR_CONTEXT *vc;
3430
3431  vc = new_var_context (name, flags);
3432  vc->table = tempvars;
3433  if (tempvars)
3434    {
3435      /* Have to do this because the temp environment was created before
3436	 variable_context was incremented. */
3437      flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3438      vc->flags |= VC_HASTMPVAR;
3439    }
3440  vc->down = shell_variables;
3441  shell_variables->up = vc;
3442
3443  return (shell_variables = vc);
3444}
3445
3446static void
3447push_func_var (data)
3448     PTR_T data;
3449{
3450  SHELL_VAR *var, *v;
3451
3452  var = (SHELL_VAR *)data;
3453
3454  if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3455    {
3456      /* XXX - should we set v->context here? */
3457      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3458      if (shell_variables == global_variables)
3459	var->attributes &= ~(att_tempvar|att_propagate);
3460      else
3461	shell_variables->flags |= VC_HASTMPVAR;
3462      v->attributes |= var->attributes;
3463    }
3464  else
3465    stupidly_hack_special_variables (var->name);	/* XXX */
3466
3467  dispose_variable (var);
3468}
3469
3470/* Pop the top context off of VCXT and dispose of it, returning the rest of
3471   the stack. */
3472void
3473pop_var_context ()
3474{
3475  VAR_CONTEXT *ret, *vcxt;
3476
3477  vcxt = shell_variables;
3478  if (vc_isfuncenv (vcxt) == 0)
3479    {
3480      internal_error (_("pop_var_context: head of shell_variables not a function context"));
3481      return;
3482    }
3483
3484  if (ret = vcxt->down)
3485    {
3486      ret->up = (VAR_CONTEXT *)NULL;
3487      shell_variables = ret;
3488      if (vcxt->table)
3489	hash_flush (vcxt->table, push_func_var);
3490      dispose_var_context (vcxt);
3491    }
3492  else
3493    internal_error (_("pop_var_context: no global_variables context"));
3494}
3495
3496/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3497   all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3498void
3499delete_all_contexts (vcxt)
3500     VAR_CONTEXT *vcxt;
3501{
3502  VAR_CONTEXT *v, *t;
3503
3504  for (v = vcxt; v != global_variables; v = t)
3505    {
3506      t = v->down;
3507      dispose_var_context (v);
3508    }
3509
3510  delete_all_variables (global_variables->table);
3511  shell_variables = global_variables;
3512}
3513
3514/* **************************************************************** */
3515/*								    */
3516/*	   Pushing and Popping temporary variable scopes	    */
3517/*								    */
3518/* **************************************************************** */
3519
3520VAR_CONTEXT *
3521push_scope (flags, tmpvars)
3522     int flags;
3523     HASH_TABLE *tmpvars;
3524{
3525  return (push_var_context ((char *)NULL, flags, tmpvars));
3526}
3527
3528static void
3529push_exported_var (data)
3530     PTR_T data;
3531{
3532  SHELL_VAR *var, *v;
3533
3534  var = (SHELL_VAR *)data;
3535
3536  /* If a temp var had its export attribute set, or it's marked to be
3537     propagated, bind it in the previous scope before disposing it. */
3538  /* XXX - This isn't exactly right, because all tempenv variables have the
3539    export attribute set. */
3540#if 0
3541  if (exported_p (var) || (var->attributes & att_propagate))
3542#else
3543  if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
3544#endif
3545    {
3546      var->attributes &= ~att_tempvar;		/* XXX */
3547      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3548      if (shell_variables == global_variables)
3549	var->attributes &= ~att_propagate;
3550      v->attributes |= var->attributes;
3551    }
3552  else
3553    stupidly_hack_special_variables (var->name);	/* XXX */
3554
3555  dispose_variable (var);
3556}
3557
3558void
3559pop_scope (is_special)
3560     int is_special;
3561{
3562  VAR_CONTEXT *vcxt, *ret;
3563
3564  vcxt = shell_variables;
3565  if (vc_istempscope (vcxt) == 0)
3566    {
3567      internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
3568      return;
3569    }
3570
3571  ret = vcxt->down;
3572  if (ret)
3573    ret->up = (VAR_CONTEXT *)NULL;
3574
3575  shell_variables = ret;
3576
3577  /* Now we can take care of merging variables in VCXT into set of scopes
3578     whose head is RET (shell_variables). */
3579  FREE (vcxt->name);
3580  if (vcxt->table)
3581    {
3582      if (is_special)
3583	hash_flush (vcxt->table, push_func_var);
3584      else
3585	hash_flush (vcxt->table, push_exported_var);
3586      hash_dispose (vcxt->table);
3587    }
3588  free (vcxt);
3589
3590  sv_ifs ("IFS");	/* XXX here for now */
3591}
3592
3593/* **************************************************************** */
3594/*								    */
3595/*		 Pushing and Popping function contexts		    */
3596/*								    */
3597/* **************************************************************** */
3598
3599static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3600static int dollar_arg_stack_slots;
3601static int dollar_arg_stack_index;
3602
3603/* XXX - we might want to consider pushing and popping the `getopts' state
3604   when we modify the positional parameters. */
3605void
3606push_context (name, is_subshell, tempvars)
3607     char *name;	/* function name */
3608     int is_subshell;
3609     HASH_TABLE *tempvars;
3610{
3611  if (is_subshell == 0)
3612    push_dollar_vars ();
3613  variable_context++;
3614  push_var_context (name, VC_FUNCENV, tempvars);
3615}
3616
3617/* Only called when subshell == 0, so we don't need to check, and can
3618   unconditionally pop the dollar vars off the stack. */
3619void
3620pop_context ()
3621{
3622  pop_dollar_vars ();
3623  variable_context--;
3624  pop_var_context ();
3625
3626  sv_ifs ("IFS");		/* XXX here for now */
3627}
3628
3629/* Save the existing positional parameters on a stack. */
3630void
3631push_dollar_vars ()
3632{
3633  if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3634    {
3635      dollar_arg_stack = (WORD_LIST **)
3636	xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3637		  * sizeof (WORD_LIST **));
3638    }
3639  dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3640  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3641}
3642
3643/* Restore the positional parameters from our stack. */
3644void
3645pop_dollar_vars ()
3646{
3647  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3648    return;
3649
3650  remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
3651  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3652  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3653  set_dollar_vars_unchanged ();
3654}
3655
3656void
3657dispose_saved_dollar_vars ()
3658{
3659  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3660    return;
3661
3662  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3663  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3664}
3665
3666/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
3667
3668void
3669push_args (list)
3670     WORD_LIST *list;
3671{
3672#if defined (ARRAY_VARS) && defined (DEBUGGER)
3673  SHELL_VAR *bash_argv_v, *bash_argc_v;
3674  ARRAY *bash_argv_a, *bash_argc_a;
3675  WORD_LIST *l;
3676  arrayind_t i;
3677  char *t;
3678
3679  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3680  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3681
3682  for (l = list, i = 0; l; l = l->next, i++)
3683    array_push (bash_argv_a, l->word->word);
3684
3685  t = itos (i);
3686  array_push (bash_argc_a, t);
3687  free (t);
3688#endif /* ARRAY_VARS && DEBUGGER */
3689}
3690
3691/* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
3692   array and use that value as the count of elements to remove from
3693   BASH_ARGV. */
3694void
3695pop_args ()
3696{
3697#if defined (ARRAY_VARS) && defined (DEBUGGER)
3698  SHELL_VAR *bash_argv_v, *bash_argc_v;
3699  ARRAY *bash_argv_a, *bash_argc_a;
3700  ARRAY_ELEMENT *ce;
3701  intmax_t i;
3702
3703  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3704  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3705
3706  ce = array_shift (bash_argc_a, 1, 0);
3707  if (ce == 0 || legal_number (element_value (ce), &i) == 0)
3708    i = 0;
3709
3710  for ( ; i > 0; i--)
3711    array_pop (bash_argv_a);
3712  array_dispose_element (ce);
3713#endif /* ARRAY_VARS && DEBUGGER */
3714}
3715
3716/*************************************************
3717 *						 *
3718 *	Functions to manage special variables	 *
3719 *						 *
3720 *************************************************/
3721
3722/* Extern declarations for variables this code has to manage. */
3723extern int eof_encountered, eof_encountered_limit, ignoreeof;
3724
3725#if defined (READLINE)
3726extern int hostname_list_initialized;
3727#endif
3728
3729/* An alist of name.function for each special variable.  Most of the
3730   functions don't do much, and in fact, this would be faster with a
3731   switch statement, but by the end of this file, I am sick of switch
3732   statements. */
3733
3734#define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
3735
3736/* This table will be sorted with qsort() the first time it's accessed. */
3737struct name_and_function {
3738  char *name;
3739  sh_sv_func_t *function;
3740};
3741
3742static struct name_and_function special_vars[] = {
3743#if defined (READLINE)
3744#  if defined (STRICT_POSIX)
3745  { "COLUMNS", sv_winsize },
3746#  endif
3747  { "COMP_WORDBREAKS", sv_comp_wordbreaks },
3748#endif
3749
3750  { "GLOBIGNORE", sv_globignore },
3751
3752#if defined (HISTORY)
3753  { "HISTCONTROL", sv_history_control },
3754  { "HISTFILESIZE", sv_histsize },
3755  { "HISTIGNORE", sv_histignore },
3756  { "HISTSIZE", sv_histsize },
3757  { "HISTTIMEFORMAT", sv_histtimefmt },
3758#endif
3759
3760#if defined (__CYGWIN__)
3761  { "HOME", sv_home },
3762#endif
3763
3764#if defined (READLINE)
3765  { "HOSTFILE", sv_hostfile },
3766#endif
3767
3768  { "IFS", sv_ifs },
3769  { "IGNOREEOF", sv_ignoreeof },
3770
3771  { "LANG", sv_locale },
3772  { "LC_ALL", sv_locale },
3773  { "LC_COLLATE", sv_locale },
3774  { "LC_CTYPE", sv_locale },
3775  { "LC_MESSAGES", sv_locale },
3776  { "LC_NUMERIC", sv_locale },
3777  { "LC_TIME", sv_locale },
3778
3779#if defined (READLINE) && defined (STRICT_POSIX)
3780  { "LINES", sv_winsize },
3781#endif
3782
3783  { "MAIL", sv_mail },
3784  { "MAILCHECK", sv_mail },
3785  { "MAILPATH", sv_mail },
3786
3787  { "OPTERR", sv_opterr },
3788  { "OPTIND", sv_optind },
3789
3790  { "PATH", sv_path },
3791  { "POSIXLY_CORRECT", sv_strict_posix },
3792
3793#if defined (READLINE)
3794  { "TERM", sv_terminal },
3795  { "TERMCAP", sv_terminal },
3796  { "TERMINFO", sv_terminal },
3797#endif /* READLINE */
3798
3799  { "TEXTDOMAIN", sv_locale },
3800  { "TEXTDOMAINDIR", sv_locale },
3801
3802#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3803  { "TZ", sv_tz },
3804#endif
3805
3806#if defined (HISTORY) && defined (BANG_HISTORY)
3807  { "histchars", sv_histchars },
3808#endif /* HISTORY && BANG_HISTORY */
3809
3810  { "ignoreeof", sv_ignoreeof },
3811
3812  { (char *)0, (sh_sv_func_t *)0 }
3813};
3814
3815#define N_SPECIAL_VARS	(sizeof (special_vars) / sizeof (special_vars[0]) - 1)
3816
3817static int
3818sv_compare (sv1, sv2)
3819     struct name_and_function *sv1, *sv2;
3820{
3821  int r;
3822
3823  if ((r = sv1->name[0] - sv2->name[0]) == 0)
3824    r = strcmp (sv1->name, sv2->name);
3825  return r;
3826}
3827
3828static inline int
3829find_special_var (name)
3830     const char *name;
3831{
3832  register int i, r;
3833
3834  for (i = 0; special_vars[i].name; i++)
3835    {
3836      r = special_vars[i].name[0] - name[0];
3837      if (r == 0)
3838	r = strcmp (special_vars[i].name, name);
3839      if (r == 0)
3840	return i;
3841      else if (r > 0)
3842	/* Can't match any of rest of elements in sorted list.  Take this out
3843	   if it causes problems in certain environments. */
3844        break;
3845    }
3846  return -1;
3847}
3848
3849/* The variable in NAME has just had its state changed.  Check to see if it
3850   is one of the special ones where something special happens. */
3851void
3852stupidly_hack_special_variables (name)
3853     char *name;
3854{
3855  static int sv_sorted = 0;
3856  int i;
3857
3858  if (sv_sorted == 0)	/* shouldn't need, but it's fairly cheap. */
3859    {
3860      qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
3861		(QSFUNC *)sv_compare);
3862      sv_sorted = 1;
3863    }
3864
3865  i = find_special_var (name);
3866  if (i != -1)
3867    (*(special_vars[i].function)) (name);
3868}
3869
3870void
3871sv_ifs (name)
3872     char *name;
3873{
3874  SHELL_VAR *v;
3875
3876  v = find_variable ("IFS");
3877  setifs (v);
3878}
3879
3880/* What to do just after the PATH variable has changed. */
3881void
3882sv_path (name)
3883     char *name;
3884{
3885  /* hash -r */
3886  phash_flush ();
3887}
3888
3889/* What to do just after one of the MAILxxxx variables has changed.  NAME
3890   is the name of the variable.  This is called with NAME set to one of
3891   MAIL, MAILCHECK, or MAILPATH.  */
3892void
3893sv_mail (name)
3894     char *name;
3895{
3896  /* If the time interval for checking the files has changed, then
3897     reset the mail timer.  Otherwise, one of the pathname vars
3898     to the users mailbox has changed, so rebuild the array of
3899     filenames. */
3900  if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
3901    reset_mail_timer ();
3902  else
3903    {
3904      free_mail_files ();
3905      remember_mail_dates ();
3906    }
3907}
3908
3909/* What to do when GLOBIGNORE changes. */
3910void
3911sv_globignore (name)
3912     char *name;
3913{
3914  setup_glob_ignore (name);
3915}
3916
3917#if defined (READLINE)
3918void
3919sv_comp_wordbreaks (name)
3920     char *name;
3921{
3922  SHELL_VAR *sv;
3923
3924  sv = find_variable (name);
3925  if (sv == 0)
3926    rl_completer_word_break_characters = (char *)NULL;
3927}
3928
3929/* What to do just after one of the TERMxxx variables has changed.
3930   If we are an interactive shell, then try to reset the terminal
3931   information in readline. */
3932void
3933sv_terminal (name)
3934     char *name;
3935{
3936  if (interactive_shell && no_line_editing == 0)
3937    rl_reset_terminal (get_string_value ("TERM"));
3938}
3939
3940void
3941sv_hostfile (name)
3942     char *name;
3943{
3944  SHELL_VAR *v;
3945
3946  v = find_variable (name);
3947  if (v == 0)
3948    clear_hostname_list ();
3949  else
3950    hostname_list_initialized = 0;
3951}
3952
3953#if defined (STRICT_POSIX)
3954/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
3955   found in the initial environment) to override the terminal size reported by
3956   the kernel. */
3957void
3958sv_winsize (name)
3959     char *name;
3960{
3961  SHELL_VAR *v;
3962  intmax_t xd;
3963  int d;
3964
3965  if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
3966    return;
3967
3968  v = find_variable (name);
3969  if (v == 0 || var_isnull (v))
3970    rl_reset_screen_size ();
3971  else
3972    {
3973      if (legal_number (value_cell (v), &xd) == 0)
3974	return;
3975      winsize_assignment = winsize_assigned = 1;
3976      d = xd;			/* truncate */
3977      if (name[0] == 'L')	/* LINES */
3978	rl_set_screen_size (d, -1);
3979      else			/* COLUMNS */
3980	rl_set_screen_size (-1, d);
3981      winsize_assignment = 0;
3982    }
3983}
3984#endif /* STRICT_POSIX */
3985#endif /* READLINE */
3986
3987/* Update the value of HOME in the export environment so tilde expansion will
3988   work on cygwin. */
3989#if defined (__CYGWIN__)
3990sv_home (name)
3991     char *name;
3992{
3993  array_needs_making = 1;
3994  maybe_make_export_env ();
3995}
3996#endif
3997
3998#if defined (HISTORY)
3999/* What to do after the HISTSIZE or HISTFILESIZE variables change.
4000   If there is a value for this HISTSIZE (and it is numeric), then stifle
4001   the history.  Otherwise, if there is NO value for this variable,
4002   unstifle the history.  If name is HISTFILESIZE, and its value is
4003   numeric, truncate the history file to hold no more than that many
4004   lines. */
4005void
4006sv_histsize (name)
4007     char *name;
4008{
4009  char *temp;
4010  intmax_t num;
4011  int hmax;
4012
4013  temp = get_string_value (name);
4014
4015  if (temp && *temp)
4016    {
4017      if (legal_number (temp, &num))
4018	{
4019	  hmax = num;
4020	  if (name[4] == 'S')
4021	    {
4022	      stifle_history (hmax);
4023	      hmax = where_history ();
4024	      if (history_lines_this_session > hmax)
4025		history_lines_this_session = hmax;
4026	    }
4027	  else
4028	    {
4029	      history_truncate_file (get_string_value ("HISTFILE"), hmax);
4030	      if (hmax <= history_lines_in_file)
4031		history_lines_in_file = hmax;
4032	    }
4033	}
4034    }
4035  else if (name[4] == 'S')
4036    unstifle_history ();
4037}
4038
4039/* What to do after the HISTIGNORE variable changes. */
4040void
4041sv_histignore (name)
4042     char *name;
4043{
4044  setup_history_ignore (name);
4045}
4046
4047/* What to do after the HISTCONTROL variable changes. */
4048void
4049sv_history_control (name)
4050     char *name;
4051{
4052  char *temp;
4053  char *val;
4054  int tptr;
4055
4056  history_control = 0;
4057  temp = get_string_value (name);
4058
4059  if (temp == 0 || *temp == 0)
4060    return;
4061
4062  tptr = 0;
4063  while (val = extract_colon_unit (temp, &tptr))
4064    {
4065      if (STREQ (val, "ignorespace"))
4066	history_control |= HC_IGNSPACE;
4067      else if (STREQ (val, "ignoredups"))
4068	history_control |= HC_IGNDUPS;
4069      else if (STREQ (val, "ignoreboth"))
4070	history_control |= HC_IGNBOTH;
4071      else if (STREQ (val, "erasedups"))
4072	history_control |= HC_ERASEDUPS;
4073
4074      free (val);
4075    }
4076}
4077
4078#if defined (BANG_HISTORY)
4079/* Setting/unsetting of the history expansion character. */
4080void
4081sv_histchars (name)
4082     char *name;
4083{
4084  char *temp;
4085
4086  temp = get_string_value (name);
4087  if (temp)
4088    {
4089      history_expansion_char = *temp;
4090      if (temp[0] && temp[1])
4091	{
4092	  history_subst_char = temp[1];
4093	  if (temp[2])
4094	      history_comment_char = temp[2];
4095	}
4096    }
4097  else
4098    {
4099      history_expansion_char = '!';
4100      history_subst_char = '^';
4101      history_comment_char = '#';
4102    }
4103}
4104#endif /* BANG_HISTORY */
4105
4106void
4107sv_histtimefmt (name)
4108     char *name;
4109{
4110  SHELL_VAR *v;
4111
4112  v = find_variable (name);
4113  history_write_timestamps = (v != 0);
4114}
4115#endif /* HISTORY */
4116
4117#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
4118void
4119sv_tz (name)
4120     char *name;
4121{
4122  tzset ();
4123}
4124#endif
4125
4126/* If the variable exists, then the value of it can be the number
4127   of times we actually ignore the EOF.  The default is small,
4128   (smaller than csh, anyway). */
4129void
4130sv_ignoreeof (name)
4131     char *name;
4132{
4133  SHELL_VAR *tmp_var;
4134  char *temp;
4135
4136  eof_encountered = 0;
4137
4138  tmp_var = find_variable (name);
4139  ignoreeof = tmp_var != 0;
4140  temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4141  if (temp)
4142    eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
4143  set_shellopts ();	/* make sure `ignoreeof' is/is not in $SHELLOPTS */
4144}
4145
4146void
4147sv_optind (name)
4148     char *name;
4149{
4150  char *tt;
4151  int s;
4152
4153  tt = get_string_value ("OPTIND");
4154  if (tt && *tt)
4155    {
4156      s = atoi (tt);
4157
4158      /* According to POSIX, setting OPTIND=1 resets the internal state
4159	 of getopt (). */
4160      if (s < 0 || s == 1)
4161	s = 0;
4162    }
4163  else
4164    s = 0;
4165  getopts_reset (s);
4166}
4167
4168void
4169sv_opterr (name)
4170     char *name;
4171{
4172  char *tt;
4173
4174  tt = get_string_value ("OPTERR");
4175  sh_opterr = (tt && *tt) ? atoi (tt) : 1;
4176}
4177
4178void
4179sv_strict_posix (name)
4180     char *name;
4181{
4182  SET_INT_VAR (name, posixly_correct);
4183  posix_initialize (posixly_correct);
4184#if defined (READLINE)
4185  if (interactive_shell)
4186    posix_readline_initialize (posixly_correct);
4187#endif /* READLINE */
4188  set_shellopts ();	/* make sure `posix' is/is not in $SHELLOPTS */
4189}
4190
4191void
4192sv_locale (name)
4193     char *name;
4194{
4195  char *v;
4196
4197  v = get_string_value (name);
4198  if (name[0] == 'L' && name[1] == 'A')	/* LANG */
4199    set_lang (name, v);
4200  else
4201    set_locale_var (name, v);		/* LC_*, TEXTDOMAIN* */
4202}
4203
4204#if defined (ARRAY_VARS)
4205void
4206set_pipestatus_array (ps, nproc)
4207     int *ps;
4208     int nproc;
4209{
4210  SHELL_VAR *v;
4211  ARRAY *a;
4212  ARRAY_ELEMENT *ae;
4213  register int i;
4214  char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
4215
4216  v = find_variable ("PIPESTATUS");
4217  if (v == 0)
4218    v = make_new_array_variable ("PIPESTATUS");
4219  if (array_p (v) == 0)
4220    return;		/* Do nothing if not an array variable. */
4221  a = array_cell (v);
4222
4223  if (a == 0 || array_num_elements (a) == 0)
4224    {
4225      for (i = 0; i < nproc; i++)	/* was ps[i] != -1, not i < nproc */
4226	{
4227	  t = inttostr (ps[i], tbuf, sizeof (tbuf));
4228	  array_insert (a, i, t);
4229	}
4230      return;
4231    }
4232
4233  /* Fast case */
4234  if (array_num_elements (a) == nproc && nproc == 1)
4235    {
4236      ae = element_forw (a->head);
4237      free (element_value (ae));
4238      ae->value = itos (ps[0]);
4239    }
4240  else if (array_num_elements (a) <= nproc)
4241    {
4242      /* modify in array_num_elements members in place, then add */
4243      ae = a->head;
4244      for (i = 0; i < array_num_elements (a); i++)
4245	{
4246	  ae = element_forw (ae);
4247	  free (element_value (ae));
4248	  ae->value = itos (ps[i]);
4249	}
4250      /* add any more */
4251      for ( ; i < nproc; i++)
4252	{
4253	  t = inttostr (ps[i], tbuf, sizeof (tbuf));
4254	  array_insert (a, i, t);
4255	}
4256    }
4257  else
4258    {
4259      /* deleting elements.  it's faster to rebuild the array. */
4260      array_flush (a);
4261      for (i = 0; ps[i] != -1; i++)
4262	{
4263	  t = inttostr (ps[i], tbuf, sizeof (tbuf));
4264	  array_insert (a, i, t);
4265	}
4266    }
4267}
4268#endif
4269
4270void
4271set_pipestatus_from_exit (s)
4272     int s;
4273{
4274#if defined (ARRAY_VARS)
4275  static int v[2] = { 0, -1 };
4276
4277  v[0] = s;
4278  set_pipestatus_array (v, 1);
4279#endif
4280}
4281