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