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