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