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