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