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