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