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