Imported from ../bash-2.05.tar.gz.
[platform/upstream/bash.git] / variables.c
1 /* variables.c -- Functions for hacking shell variables. */
2
3 /* Copyright (C) 1987,1989 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 it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Bash; see the file COPYING.  If not, write to the Free
19    Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #include "posixstat.h"
25
26 #if defined (qnx)
27 #  include <sys/vc.h>
28 #endif
29
30 #if defined (HAVE_UNISTD_H)
31 #  include <unistd.h>
32 #endif
33
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <pwd.h>
37 #include "bashansi.h"
38
39 #include "shell.h"
40 #include "flags.h"
41 #include "execute_cmd.h"
42 #include "findcmd.h"
43 #include "mailcheck.h"
44 #include "input.h"
45
46 #include "builtins/getopt.h"
47 #include "builtins/common.h"
48
49 #if defined (READLINE)
50 #  include "bashline.h"
51 #  include <readline/readline.h>
52 #else
53 #  include <tilde/tilde.h>
54 #endif
55
56 #if defined (HISTORY)
57 #  include "bashhist.h"
58 #  include <readline/history.h>
59 #endif /* HISTORY */
60
61 #if defined (PROGRAMMABLE_COMPLETION)
62 #  include "pcomplete.h"
63 #endif
64
65 /* Variables used here and defined in other files. */
66 extern int posixly_correct;
67 extern int variable_context, line_number;
68 extern int interactive, interactive_shell, login_shell;
69 extern int subshell_environment, indirection_level;
70 extern int build_version, patch_level;
71 extern char *dist_version, *release_status;
72 extern char *shell_name;
73 extern char *primary_prompt, *secondary_prompt;
74 extern char *current_host_name;
75 extern Function *this_shell_builtin;
76 extern SHELL_VAR *this_shell_function;
77 extern char *this_command_name;
78 extern time_t shell_start_time;
79
80 /* The list of shell variables that the user has created, or that came from
81    the environment. */
82 HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
83
84 /* The list of shell functions that the user has created, or that came from
85    the environment. */
86 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
87
88 /* The current variable context.  This is really a count of how deep into
89    executing functions we are. */
90 int variable_context = 0;
91
92 /* The array of shell assignments which are made only in the environment
93    for a single command. */
94 char **temporary_env = (char **)NULL;
95
96 /* The array of shell assignments which are in the environment for the
97    execution of a shell function. */
98 char **function_env = (char **)NULL;
99
100 /* The array of shell assignments which are made only in the environment
101    for the execution of a shell builtin command which may cause more than
102    one command to be executed (e.g., "eval" or "source"). */
103 char **builtin_env = (char **)NULL;
104
105 /* Some funky variables which are known about specially.  Here is where
106    "$*", "$1", and all the cruft is kept. */
107 char *dollar_vars[10];
108 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
109
110 /* The value of $$. */
111 int dollar_dollar_pid;
112
113 /* An array which is passed to commands as their environment.  It is
114    manufactured from the union of the initial environment and the
115    shell variables that are marked for export. */
116 char **export_env = (char **)NULL;
117 static int export_env_index;
118 static int export_env_size;
119
120 /* Non-zero means that we have to remake EXPORT_ENV. */
121 int array_needs_making = 1;
122
123 /* The number of times BASH has been executed.  This is set
124    by initialize_variables (). */
125 int shell_level = 0;
126
127 static char *have_local_variables;
128 static int local_variable_stack_size;
129
130 /* Some forward declarations. */
131 static void set_home_var ();
132 static void set_shell_var ();
133 static char *get_bash_name ();
134 static void initialize_shell_level ();
135 static void uidset ();
136 static void initialize_dynamic_variables ();
137 static void make_vers_array ();
138 static void sbrand ();          /* set bash random number generator. */
139 static int qsort_var_comp ();
140 static SHELL_VAR *bind_tempenv_variable ();
141
142 /* Make VAR be auto-exported.  VAR is a pointer to a SHELL_VAR. */
143 #define set_auto_export(var) \
144   do { var->attributes |= att_exported; array_needs_making = 1; } while (0)
145
146 /* Initialize the shell variables from the current environment.
147    If PRIVMODE is nonzero, don't import functions from ENV or
148    parse $SHELLOPTS. */
149 void
150 initialize_shell_variables (env, privmode)
151      char **env;
152      int privmode;
153 {
154   char *name, *string, *temp_string;
155   int c, char_index, string_index, string_length;
156   SHELL_VAR *temp_var;
157
158   if (shell_variables == 0)
159     shell_variables = make_hash_table (0);
160
161   if (shell_functions == 0)
162     shell_functions = make_hash_table (0);
163
164   for (string_index = 0; string = env[string_index++]; )
165     {
166       char_index = 0;
167       name = string;
168       while ((c = *string++) && c != '=')
169         ;
170       if (string[-1] == '=')
171         char_index = string - name - 1;
172
173       /* If there are weird things in the environment, like `=xxx' or a
174          string without an `=', just skip them. */
175       if (char_index == 0)
176         continue;
177
178       /* ASSERT(name[char_index] == '=') */
179       name[char_index] = '\0';
180       /* Now, name = env variable name, string = env variable value, and
181          char_index == strlen (name) */
182
183       /* If exported function, define it now. */
184       if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
185         {
186           string_length = strlen (string);
187           temp_string = xmalloc (3 + string_length + char_index);
188
189           strcpy (temp_string, name);
190           temp_string[char_index] = ' ';
191           strcpy (temp_string + char_index + 1, string);
192
193           parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
194
195           /* Ancient backwards compatibility.  Old versions of bash exported
196              functions like name()=() {...} */
197           if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
198             name[char_index - 2] = '\0';
199
200           if (temp_var = find_function (name))
201             {
202               VSETATTR (temp_var, (att_exported|att_imported));
203               array_needs_making = 1;
204             }
205           else
206             report_error ("error importing function definition for `%s'", name);
207
208           /* ( */
209           if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
210             name[char_index - 2] = '(';         /* ) */
211         }
212 #if defined (ARRAY_VARS)
213 #  if 0
214       /* Array variables may not yet be exported. */
215       else if (*string == '(' && string[1] == '[' && strchr (string, ')'))
216         {
217           string_length = 1;
218           temp_string = extract_array_assignment_list (string, &string_length);
219           temp_var = assign_array_from_string (name, temp_string);
220           FREE (temp_string);
221           VSETATTR (temp_var, (att_exported | att_imported));
222           array_needs_making = 1;
223         }
224 #  endif
225 #endif
226       else
227         {
228           temp_var = bind_variable (name, string);
229           VSETATTR (temp_var, (att_exported | att_imported));
230           array_needs_making = 1;
231         }
232
233       name[char_index] = '=';
234       /* temp_var can be NULL if it was an exported function with a syntax
235          error (a different bug, but it still shouldn't dump core). */
236       if (temp_var && function_p (temp_var) == 0)       /* XXX not yet */
237         {
238           CACHE_IMPORTSTR (temp_var, name);
239         }
240     }
241
242   set_pwd ();
243
244   /* Set up initial value of $_ */
245   temp_var = bind_variable ("_", dollar_vars[0]);
246
247   /* Remember this pid. */
248   dollar_dollar_pid = (int)getpid ();
249
250   /* Now make our own defaults in case the vars that we think are
251      important are missing. */
252   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
253   set_auto_export (temp_var);
254
255   temp_var = set_if_not ("TERM", "dumb");
256   set_auto_export (temp_var);
257
258 #if defined (qnx)
259   /* set node id -- don't import it from the environment */
260   {
261     char node_name[22];
262     qnx_nidtostr (getnid (), node_name, sizeof (node_name));
263     temp_var = bind_variable ("NODE", node_name);
264     set_auto_export (temp_var);
265   }
266 #endif
267
268   /* set up the prompts. */
269   if (interactive_shell)
270     {
271 #if defined (PROMPT_STRING_DECODE)
272       set_if_not ("PS1", primary_prompt);
273 #else
274       if (current_user.uid == -1)
275         get_current_user_info ();
276       set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
277 #endif
278       set_if_not ("PS2", secondary_prompt);
279     }
280   set_if_not ("PS4", "+ ");
281
282   /* Don't allow IFS to be imported from the environment. */
283   temp_var = bind_variable ("IFS", " \t\n");
284
285   /* Magic machine types.  Pretty convenient. */
286   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
287   set_auto_export (temp_var);
288   temp_var = set_if_not ("OSTYPE", OSTYPE);
289   set_auto_export (temp_var);
290   temp_var = set_if_not ("MACHTYPE", MACHTYPE);
291   set_auto_export (temp_var);
292
293   temp_var = set_if_not ("HOSTNAME", current_host_name);
294   set_auto_export (temp_var);
295
296   /* Default MAILCHECK for interactive shells.  Defer the creation of a
297      default MAILPATH until the startup files are read, because MAIL
298      names a mail file if MAILCHECK is not set, and we should provide a
299      default only if neither is set. */
300   if (interactive_shell)
301     set_if_not ("MAILCHECK", "60");
302
303   /* Do some things with shell level. */
304   initialize_shell_level ();
305
306   set_ppid ();
307
308   /* Initialize the `getopts' stuff. */
309   bind_variable ("OPTIND", "1");
310   getopts_reset (0);
311   bind_variable ("OPTERR", "1");
312   sh_opterr = 1;
313
314   if (login_shell == 1)
315     set_home_var ();
316
317   /* Get the full pathname to THIS shell, and set the BASH variable
318      to it. */
319   name = get_bash_name ();
320   temp_var = bind_variable ("BASH", name);
321   free (name);
322
323   /* Make the exported environment variable SHELL be the user's login
324      shell.  Note that the `tset' command looks at this variable
325      to determine what style of commands to output; if it ends in "csh",
326      then C-shell commands are output, else Bourne shell commands. */
327   set_shell_var ();
328
329   /* Make a variable called BASH_VERSION which contains the version info. */
330   bind_variable ("BASH_VERSION", shell_version_string ());
331 #if defined (ARRAY_VARS)
332   make_vers_array ();
333 #endif
334
335   /* Find out if we're supposed to be in Posix.2 mode via an
336      environment variable. */
337   temp_var = find_variable ("POSIXLY_CORRECT");
338   if (!temp_var)
339     temp_var = find_variable ("POSIX_PEDANTIC");
340   if (temp_var && imported_p (temp_var))
341     sv_strict_posix (temp_var->name);
342
343 #if defined (HISTORY)
344   /* Set history variables to defaults, and then do whatever we would
345      do if the variable had just been set.  Do this only in the case
346      that we are remembering commands on the history list. */
347   if (remember_on_history)
348     {
349       name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history");
350
351       set_if_not ("HISTFILE", name);
352       free (name);
353
354       set_if_not ("HISTSIZE", "500");
355       sv_histsize ("HISTSIZE");
356     }
357 #endif /* HISTORY */
358
359   /* Seed the random number generator. */
360   sbrand (dollar_dollar_pid + (long)shell_start_time);
361
362   /* Handle some "special" variables that we may have inherited from a
363      parent shell. */
364   if (interactive_shell)
365     {
366       temp_var = find_variable ("IGNOREEOF");
367       if (!temp_var)
368         temp_var = find_variable ("ignoreeof");
369       if (temp_var && imported_p (temp_var))
370         sv_ignoreeof (temp_var->name);
371     }
372
373 #if defined (HISTORY)
374   if (interactive_shell && remember_on_history)
375     {
376       sv_history_control ("HISTCONTROL");
377       sv_histignore ("HISTIGNORE");
378     }
379 #endif /* HISTORY */
380
381   temp_var = find_variable ("SSH_CLIENT");
382   if (temp_var && imported_p (temp_var))
383     {
384       VUNSETATTR (temp_var, att_exported);
385       array_needs_making = 1;
386     }
387   temp_var = find_variable ("SSH2_CLIENT");
388   if (temp_var && imported_p (temp_var))
389     {
390       VUNSETATTR (temp_var, att_exported);
391       array_needs_making = 1;
392     }
393
394   /* Get the user's real and effective user ids. */
395   uidset ();
396
397   /* Initialize the dynamic variables, and seed their values. */
398   initialize_dynamic_variables ();
399 }
400
401 /* Set $HOME to the information in the password file if we didn't get
402    it from the environment. */
403
404 /* This function is not static so the tilde and readline libraries can
405    use it. */
406 char *
407 sh_get_home_dir ()
408 {
409   if (current_user.home_dir == 0)
410     get_current_user_info ();
411   return current_user.home_dir;
412 }
413
414 static void
415 set_home_var ()
416 {
417   SHELL_VAR *temp_var;
418
419   temp_var = find_variable ("HOME");
420   if (temp_var == 0)
421     temp_var = bind_variable ("HOME", sh_get_home_dir ());
422   VSETATTR (temp_var, att_exported);
423 }
424
425 /* Set $SHELL to the user's login shell if it is not already set.  Call
426    get_current_user_info if we haven't already fetched the shell. */
427 static void
428 set_shell_var ()
429 {
430   SHELL_VAR *temp_var;
431
432   temp_var = find_variable ("SHELL");
433   if (temp_var == 0)
434     {
435       if (current_user.shell == 0)
436         get_current_user_info ();
437       temp_var = bind_variable ("SHELL", current_user.shell);
438     }
439   VSETATTR (temp_var, att_exported);
440 }
441
442 static char *
443 get_bash_name ()
444 {
445   char *name;
446
447   if ((login_shell == 1) && RELPATH(shell_name))
448     {
449       if (current_user.shell == 0)
450         get_current_user_info ();
451       name = savestring (current_user.shell);
452     }
453   else if (ABSPATH(shell_name))
454     name = savestring (shell_name);
455   else if (shell_name[0] == '.' && shell_name[1] == '/')
456     {
457       /* Fast path for common case. */
458       char *cdir;
459       int len;
460
461       cdir = get_string_value ("PWD");
462       if (cdir)
463         {
464           len = strlen (cdir);
465           name = xmalloc (len + strlen (shell_name) + 1);
466           strcpy (name, cdir);
467           strcpy (name + len, shell_name + 1);
468         }
469       else
470         name = savestring (shell_name);
471     }
472   else
473     {
474       char *tname;
475       int s;
476
477       tname = find_user_command (shell_name);
478
479       if (tname == 0)
480         {
481           /* Try the current directory.  If there is not an executable
482              there, just punt and use the login shell. */
483           s = file_status (shell_name);
484           if (s & FS_EXECABLE)
485             {
486               tname = make_absolute (shell_name, get_string_value ("PWD"));
487               if (*shell_name == '.')
488                 {
489                   name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
490                   if (name == 0)
491                     name = tname;
492                   else
493                     free (tname);
494                 }
495              else
496                 name = tname;
497             }
498           else
499             {
500               if (current_user.shell == 0)
501                 get_current_user_info ();
502               name = savestring (current_user.shell);
503             }
504         }
505       else
506         {
507           name = full_pathname (tname);
508           free (tname);
509         }
510     }
511
512   return (name);
513 }
514
515 void
516 adjust_shell_level (change)
517      int change;
518 {
519   char new_level[5], *old_SHLVL;
520   int old_level;
521   SHELL_VAR *temp_var;
522
523   old_SHLVL = get_string_value ("SHLVL");
524   old_level = old_SHLVL ? atoi (old_SHLVL) : 0;
525
526   shell_level = old_level + change;
527   if (shell_level < 0)
528     shell_level = 0;
529   else if (shell_level > 1000)
530     {
531       internal_warning ("shell level (%d) too high, resetting to 1", shell_level);
532       shell_level = 1;
533     }
534
535   /* We don't need the full generality of itos here. */
536   if (shell_level < 10)
537     {
538       new_level[0] = shell_level + '0';
539       new_level[1] = '\0';
540     }
541   else if (shell_level < 100)
542     {
543       new_level[0] = (shell_level / 10) + '0';
544       new_level[1] = (shell_level % 10) + '0';
545       new_level[2] = '\0';
546     }
547   else if (shell_level < 1000)
548     {
549       new_level[0] = (shell_level / 100) + '0';
550       old_level = shell_level % 100;
551       new_level[1] = (old_level / 10) + '0';
552       new_level[2] = (old_level % 10) + '0';
553       new_level[3] = '\0';
554     }
555
556   temp_var = bind_variable ("SHLVL", new_level);
557   set_auto_export (temp_var);
558 }
559
560 static void
561 initialize_shell_level ()
562 {
563   adjust_shell_level (1);
564 }
565
566 /* If we got PWD from the environment, update our idea of the current
567    working directory.  In any case, make sure that PWD exists before
568    checking it.  It is possible for getcwd () to fail on shell startup,
569    and in that case, PWD would be undefined.  If this is an interactive
570    login shell, see if $HOME is the current working directory, and if
571    that's not the same string as $PWD, set PWD=$HOME. */
572
573 void
574 set_pwd ()
575 {
576   SHELL_VAR *temp_var, *home_var;
577   char *temp_string, *home_string;
578
579   home_var = find_variable ("HOME");
580   home_string = home_var ? value_cell (home_var) : (char *)NULL;
581
582   temp_var = find_variable ("PWD");
583   if (temp_var && imported_p (temp_var) &&
584       (temp_string = value_cell (temp_var)) &&
585       same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
586     set_working_directory (temp_string);
587   else if (home_string && interactive_shell && login_shell &&
588            same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
589     {
590       set_working_directory (home_string);
591       temp_var = bind_variable ("PWD", home_string);
592       set_auto_export (temp_var);
593     }
594   else
595     {
596       temp_string = get_working_directory ("shell-init");
597       if (temp_string)
598         {
599           temp_var = bind_variable ("PWD", temp_string);
600           set_auto_export (temp_var);
601           free (temp_string);
602         }
603     }
604
605   /* According to the Single Unix Specification, v2, $OLDPWD is an
606      `environment variable' and therefore should be auto-exported.
607      Make a dummy invisible variable for OLDPWD, and mark it as exported. */
608   temp_var = bind_variable ("OLDPWD", (char *)NULL);
609   VSETATTR (temp_var, (att_exported | att_invisible));
610 }
611
612 /* Make a variable $PPID, which holds the pid of the shell's parent.  */
613 void
614 set_ppid ()
615 {
616   char namebuf[32], *name;
617   SHELL_VAR *temp_var;
618
619   name = inttostr ((int) getppid (), namebuf, sizeof(namebuf));
620   temp_var = find_variable ("PPID");
621   if (temp_var)
622     VUNSETATTR (temp_var, (att_readonly | att_exported));
623   temp_var = bind_variable ("PPID", name);
624   VSETATTR (temp_var, (att_readonly | att_integer));
625 }
626
627 static void
628 uidset ()
629 {
630   char buff[32], *b;
631   register SHELL_VAR *v;
632
633   b = inttostr (current_user.uid, buff, sizeof (buff));
634   v = find_variable ("UID");
635   if (v == 0)
636     {
637       v = bind_variable ("UID", b);
638       VSETATTR (v, (att_readonly | att_integer));
639     }
640
641   if (current_user.euid != current_user.uid)
642     b = inttostr (current_user.euid, buff, sizeof (buff));
643
644   v = find_variable ("EUID");
645   if (v == 0)
646     {
647       v = bind_variable ("EUID", b);
648       VSETATTR (v, (att_readonly | att_integer));
649     }
650 }
651
652 #if defined (ARRAY_VARS)
653 static void
654 make_vers_array ()
655 {
656   SHELL_VAR *vv;
657   ARRAY *av;
658   char *s, d[32];
659
660   makunbound ("BASH_VERSINFO", shell_variables);
661
662   vv = make_new_array_variable ("BASH_VERSINFO");
663   av = array_cell (vv);
664   strcpy (d, dist_version);
665   s = strchr (d, '.');
666   if (s)
667     *s++ = '\0';
668   array_add_element (av, 0, d);
669   array_add_element (av, 1, s);
670   s = inttostr (patch_level, d, sizeof (d));
671   array_add_element (av, 2, s);
672   s = inttostr (build_version, d, sizeof (d));
673   array_add_element (av, 3, s);
674   array_add_element (av, 4, release_status);
675   array_add_element (av, 5, MACHTYPE);
676
677   VSETATTR (vv, att_readonly);
678 }
679 #endif /* ARRAY_VARS */
680
681 /* Set the environment variables $LINES and $COLUMNS in response to
682    a window size change. */
683 void
684 sh_set_lines_and_columns (lines, cols)
685      int lines, cols;
686 {
687   char val[32], *v;
688
689   v = inttostr (lines, val, sizeof (val));
690   bind_variable ("LINES", v);
691
692   v = inttostr (cols, val, sizeof (val));
693   bind_variable ("COLUMNS", v);
694 }
695
696 /* Set NAME to VALUE if NAME has no value. */
697 SHELL_VAR *
698 set_if_not (name, value)
699      char *name, *value;
700 {
701   SHELL_VAR *v;
702
703   v = find_variable (name);
704   if (v == 0)
705     v = bind_variable (name, value);
706   return (v);
707 }
708
709 /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
710    variables for which FUNCTION returns a non-zero value.  A NULL value
711    for FUNCTION means to use all variables. */
712 SHELL_VAR **
713 map_over (function, var_hash_table)
714      Function *function;
715      HASH_TABLE* var_hash_table;
716 {
717   register int i;
718   register BUCKET_CONTENTS *tlist;
719   SHELL_VAR *var, **list;
720   int list_index, list_size;
721
722   list = (SHELL_VAR **)NULL;
723   for (i = list_index = list_size = 0; i < var_hash_table->nbuckets; i++)
724     {
725       tlist = get_hash_bucket (i, var_hash_table);
726
727       while (tlist)
728         {
729           var = (SHELL_VAR *)tlist->data;
730
731           if (!function || (*function) (var))
732             {
733               if (list_index + 1 >= list_size)
734                 list = (SHELL_VAR **)
735                   xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
736
737               list[list_index++] = var;
738               list[list_index] = (SHELL_VAR *)NULL;
739             }
740           tlist = tlist->next;
741         }
742     }
743   return (list);
744 }
745
746 void
747 sort_variables (array)
748      SHELL_VAR **array;
749 {
750   qsort (array, array_len ((char **)array), sizeof (SHELL_VAR *), qsort_var_comp);
751 }
752
753 static int
754 qsort_var_comp (var1, var2)
755      SHELL_VAR **var1, **var2;
756 {
757   int result;
758
759   if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
760     result = strcmp ((*var1)->name, (*var2)->name);
761
762   return (result);
763 }
764
765 /* Create a NULL terminated array of all the shell variables in TABLE. */
766 static SHELL_VAR **
767 all_vars (table)
768      HASH_TABLE *table;
769 {
770   SHELL_VAR **list;
771
772   list = map_over ((Function *)NULL, table);
773   if (list /* && posixly_correct */)
774     sort_variables (list);
775   return (list);
776 }
777
778 /* Create a NULL terminated array of all the shell variables. */
779 SHELL_VAR **
780 all_shell_variables ()
781 {
782   return (all_vars (shell_variables));
783 }
784
785 /* Create a NULL terminated array of all the shell functions. */
786 SHELL_VAR **
787 all_shell_functions ()
788 {
789   return (all_vars (shell_functions));
790 }
791
792 /* Print LIST (a list of shell variables) to stdout in such a way that
793    they can be read back in. */
794 void
795 print_var_list (list)
796      register SHELL_VAR **list;
797 {
798   register int i;
799   register SHELL_VAR *var;
800
801   for (i = 0; list && (var = list[i]); i++)
802     if (!invisible_p (var))
803       print_assignment (var);
804 }
805
806 /* Print LIST (a list of shell functions) to stdout in such a way that
807    they can be read back in. */
808 void
809 print_func_list (list)
810      register SHELL_VAR **list;
811 {
812   register int i;
813   register SHELL_VAR *var;
814
815   for (i = 0; list && (var = list[i]); i++)
816     {
817       printf ("%s ", var->name);
818       print_var_function (var);
819       printf ("\n");
820     }
821 }
822       
823 #if defined (NOTDEF)
824 /* Print LIST (a linked list of shell variables) to stdout
825    by printing the names, without the values.  Used to support the
826    `set +' command. */
827 void
828 print_vars_no_values (list)
829      register SHELL_VAR **list;
830 {
831   register int i;
832   register SHELL_VAR *var;
833
834   for (i = 0; list && (var = list[i]); i++)
835     if (!invisible_p (var))
836       printf ("%s\n", var->name);
837 }
838 #endif
839
840 /* Print the value of a single SHELL_VAR.  No newline is
841    output, but the variable is printed in such a way that
842    it can be read back in. */
843 void
844 print_assignment (var)
845      SHELL_VAR *var;
846 {
847   if (function_p (var) && var->value)
848     {
849       printf ("%s", var->name);
850       print_var_function (var);
851       printf ("\n");
852     }
853 #if defined (ARRAY_VARS)
854   else if (array_p (var) && var->value)
855     print_array_assignment (var, 0);
856 #endif /* ARRAY_VARS */
857   else if (var->value)
858     {
859       printf ("%s=", var->name);
860       print_var_value (var, 1);
861       printf ("\n");
862     }
863 }
864
865 /* Print the value cell of VAR, a shell variable.  Do not print
866    the name, nor leading/trailing newline.  If QUOTE is non-zero,
867    and the value contains shell metacharacters, quote the value
868    in such a way that it can be read back in. */
869 void
870 print_var_value (var, quote)
871      SHELL_VAR *var;
872      int quote;
873 {
874   char *t;
875
876   if (var->value)
877     {
878       if (quote && sh_contains_shell_metas (var->value))
879         {
880 #if 0
881           t = sh_single_quote (var->value);
882 #else
883           t = ansic_quote (var->value, 0, (int *)0);
884 #endif
885           printf ("%s", t);
886           free (t);
887         }
888       else
889         printf ("%s", var->value);
890     }
891 }
892
893 /* Print the function cell of VAR, a shell variable.  Do not
894    print the name, nor leading/trailing newline. */
895 void
896 print_var_function (var)
897      SHELL_VAR *var;
898 {
899   if (function_p (var) && var->value)
900     printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
901 }
902
903 #if defined (ARRAY_VARS)
904 void
905 print_array_assignment (var, quoted)
906      SHELL_VAR *var;
907      int quoted;
908 {
909   char *vstr;
910
911   if (quoted)
912     vstr = quoted_array_assignment_string (array_cell (var));
913   else
914     vstr = array_to_assignment_string (array_cell (var));
915
916   if (vstr == 0)
917     printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
918   else
919     {
920       printf ("%s=%s\n", var->name, vstr);
921       free (vstr);
922     }
923 }
924 #endif /* ARRAY_VARS */
925
926 /* **************************************************************** */
927 /*                                                                  */
928 /*               Dynamic Variable Extension                         */
929 /*                                                                  */
930 /* **************************************************************** */
931
932 /* DYNAMIC VARIABLES
933
934    These are variables whose values are generated anew each time they are
935    referenced.  These are implemented using a pair of function pointers
936    in the struct variable: assign_func, which is called from bind_variable,
937    and dynamic_value, which is called from find_variable.
938
939    assign_func is called from bind_variable, if bind_variable discovers
940    that the variable being assigned to has such a function.  The function
941    is called as
942         SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
943    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
944    is usually ENTRY (self).
945
946    dynamic_value is called from find_variable to return a `new' value for
947    the specified dynamic varible.  If this function is NULL, the variable
948    is treated as a `normal' shell variable.  If it is not, however, then
949    this function is called like this:
950         tempvar = (*(var->dynamic_value)) (var);
951
952    Sometimes `tempvar' will replace the value of `var'.  Other times, the
953    shell will simply use the string value.  Pretty object-oriented, huh?
954
955    Be warned, though: if you `unset' a special variable, it loses its
956    special meaning, even if you subsequently set it.
957
958    The special assignment code would probably have been better put in
959    subst.c: do_assignment, in the same style as
960    stupidly_hack_special_variables, but I wanted the changes as
961    localized as possible.  */
962
963 static SHELL_VAR *
964 null_assign (self, value)
965      SHELL_VAR *self;
966      char *value;
967 {
968   return (self);
969 }
970
971 #if defined (ARRAY_VARS)
972 static SHELL_VAR *
973 null_array_assign (self, ind, value)
974      SHELL_VAR *self;
975      int ind;
976      char *value;
977 {
978   return (self);
979 }
980 #endif
981
982 /* The value of $SECONDS.  This is the number of seconds since shell
983    invocation, or, the number of seconds since the last assignment + the
984    value of the last assignment. */
985 static long seconds_value_assigned;
986
987 static SHELL_VAR *
988 assign_seconds (self, value)
989      SHELL_VAR *self;
990      char *value;
991 {
992   seconds_value_assigned = strtol (value, (char **)NULL, 10);
993   shell_start_time = NOW;
994   return (self);
995 }
996
997 static SHELL_VAR *
998 get_seconds (var)
999      SHELL_VAR *var;
1000 {
1001   time_t time_since_start;
1002   char *p;
1003
1004   time_since_start = NOW - shell_start_time;
1005   p = itos((int) seconds_value_assigned + time_since_start);
1006
1007   FREE (var->value);
1008
1009   VSETATTR (var, att_integer);
1010   var->value = p;
1011   return (var);
1012 }
1013
1014 /* The random number seed.  You can change this by setting RANDOM. */
1015 static unsigned long rseed = 1;
1016 static unsigned long last_random_value;
1017
1018 /* A linear congruential random number generator based on the ANSI
1019    C standard.  This one isn't very good (the values are alternately
1020    odd and even, for example), but a more complicated one is overkill.  */
1021
1022 /* Returns a pseudo-random number between 0 and 32767. */
1023 static int
1024 brand ()
1025 {
1026   rseed = rseed * 1103515245 + 12345;
1027   return ((unsigned int)(rseed & 32767));       /* was % 32768 */
1028 }
1029
1030 /* Set the random number generator seed to SEED. */
1031 static void
1032 sbrand (seed)
1033      int seed;
1034 {
1035   rseed = seed;
1036   last_random_value = 0;
1037 }
1038
1039 static SHELL_VAR *
1040 assign_random (self, value)
1041      SHELL_VAR *self;
1042      char *value;
1043 {
1044   sbrand (atoi (value));
1045   return (self);
1046 }
1047
1048 int
1049 get_random_number ()
1050 {
1051   int rv;
1052
1053   /* Reset for command and process substitution. */
1054   if (subshell_environment)
1055     sbrand (rseed + (int)(getpid() + NOW));
1056
1057   do
1058     rv = brand ();
1059   while (rv == (int)last_random_value);
1060   return rv;
1061 }
1062
1063 static SHELL_VAR *
1064 get_random (var)
1065      SHELL_VAR *var;
1066 {
1067   int rv;
1068   char *p;
1069
1070   rv = get_random_number ();
1071   last_random_value = rv;
1072   p = itos ((int)rv);
1073
1074   FREE (var->value);
1075
1076   VSETATTR (var, att_integer);
1077   var->value = p;
1078   return (var);
1079 }
1080
1081 /* Function which returns the current line number. */
1082 static SHELL_VAR *
1083 get_lineno (var)
1084      SHELL_VAR *var;
1085 {
1086   char *p;
1087   int ln;
1088
1089   ln = executing_line_number ();
1090   p = itos (ln);
1091   FREE (var->value);
1092   var->value = p;
1093   return (var);
1094 }
1095
1096 static SHELL_VAR *
1097 assign_lineno (var, value)
1098      SHELL_VAR *var;
1099      char *value;
1100 {
1101   line_number = atoi (value);
1102   return var;
1103 }
1104
1105 #if defined (HISTORY)
1106 static SHELL_VAR *
1107 get_histcmd (var)
1108      SHELL_VAR *var;
1109 {
1110   char *p;
1111
1112   p = itos (history_number ());
1113   FREE (var->value);
1114   var->value = p;
1115   return (var);
1116 }
1117 #endif
1118
1119 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1120 static SHELL_VAR *
1121 get_dirstack (self)
1122      SHELL_VAR *self;
1123 {
1124   ARRAY *a;
1125   WORD_LIST *l;
1126
1127   l = get_directory_stack ();
1128   a = word_list_to_array (l);
1129   dispose_array (array_cell (self));
1130   dispose_words (l);
1131   self->value = (char *)a;
1132   return self;
1133 }
1134
1135 static  SHELL_VAR *
1136 assign_dirstack (self, ind, value)
1137      SHELL_VAR *self;
1138      int ind;
1139      char *value;
1140 {
1141   set_dirstack_element (ind, 1, value);
1142   return self;
1143 }
1144 #endif /* PUSHD AND POPD && ARRAY_VARS */
1145
1146 #if defined (ARRAY_VARS)
1147 /* We don't want to initialize the group set with a call to getgroups()
1148    unless we're asked to, but we only want to do it once. */
1149 static SHELL_VAR *
1150 get_groupset (self)
1151      SHELL_VAR *self;
1152 {
1153   register int i;
1154   int ng;
1155   ARRAY *a;
1156   static char **group_set = (char **)NULL;
1157
1158   if (group_set == 0)
1159     {
1160       group_set = get_group_list (&ng);
1161       a = array_cell (self);
1162       for (i = 0; i < ng; i++)
1163         array_add_element (a, i, group_set[i]);
1164     }
1165   return (self);
1166 }
1167 #endif /* ARRAY_VARS */
1168
1169 static SHELL_VAR *
1170 get_funcname (self)
1171      SHELL_VAR *self;
1172 {
1173   if (variable_context && this_shell_function)
1174     {
1175       FREE (self->value);
1176       self->value = savestring (this_shell_function->name);
1177     }
1178   return (self);
1179 }
1180
1181 void
1182 make_funcname_visible (on_or_off)
1183      int on_or_off;
1184 {
1185   SHELL_VAR *v;
1186
1187   v = find_variable ("FUNCNAME");
1188   if (v == 0 || v->dynamic_value == 0)
1189     return;
1190
1191   if (on_or_off)
1192     VUNSETATTR (v, att_invisible);
1193   else
1194     VSETATTR (v, att_invisible);
1195 }
1196
1197 #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1198   do \
1199     { \
1200       v = bind_variable (var, val); \
1201       v->dynamic_value = gfunc; \
1202       v->assign_func = afunc; \
1203     } while (0)
1204
1205 #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1206   do \
1207     { \
1208       v = make_new_array_variable (var); \
1209       v->dynamic_value = gfunc; \
1210       v->assign_func = afunc; \
1211     } while (0)
1212
1213 static void
1214 initialize_dynamic_variables ()
1215 {
1216   SHELL_VAR *v;
1217
1218   INIT_DYNAMIC_VAR ("SECONDS", (char *)NULL, get_seconds, assign_seconds);
1219   INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1220   INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1221
1222 #if defined (HISTORY)
1223   INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (DYNAMIC_FUNC *)NULL);
1224 #endif
1225
1226 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1227   INIT_DYNAMIC_ARRAY_VAR ("DIRSTACK", get_dirstack, assign_dirstack);
1228 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1229
1230 #if defined (ARRAY_VARS)
1231   INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign);
1232   VSETATTR (v, att_noassign);
1233 #endif
1234
1235   INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1236   VSETATTR (v, att_invisible|att_noassign);
1237 }
1238
1239 /* How to get a pointer to the shell variable or function named NAME.
1240    HASHED_VARS is a pointer to the hash table containing the list
1241    of interest (either variables or functions). */
1242 SHELL_VAR *
1243 var_lookup (name, hashed_vars)
1244      char *name;
1245      HASH_TABLE *hashed_vars;
1246 {
1247   BUCKET_CONTENTS *bucket;
1248
1249   bucket = find_hash_item (name, hashed_vars);
1250   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1251 }
1252
1253 /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
1254    then also search the temporarily built list of exported variables. */
1255 SHELL_VAR *
1256 find_variable_internal (name, search_tempenv)
1257      char *name;
1258      int search_tempenv;
1259 {
1260   SHELL_VAR *var;
1261
1262   var = (SHELL_VAR *)NULL;
1263
1264   /* If explicitly requested, first look in the temporary environment for
1265      the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
1266      to get the `exported' value of $foo.  This happens if we are executing
1267      a function or builtin, or if we are looking up a variable in a
1268      "subshell environment". */
1269   if ((search_tempenv || subshell_environment) &&
1270       (temporary_env || builtin_env || function_env))
1271     var = find_tempenv_variable (name);
1272
1273   if (!var)
1274     var = var_lookup (name, shell_variables);
1275
1276   if (!var)
1277     return ((SHELL_VAR *)NULL);
1278
1279   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1280 }
1281
1282 /* Look up the variable entry named NAME.  Returns the entry or NULL. */
1283 SHELL_VAR *
1284 find_variable (name)
1285      char *name;
1286 {
1287   return (find_variable_internal
1288           (name, (variable_context || this_shell_builtin || builtin_env)));
1289 }
1290
1291 /* Look up the function entry whose name matches STRING.
1292    Returns the entry or NULL. */
1293 SHELL_VAR *
1294 find_function (name)
1295      char *name;
1296 {
1297   return (var_lookup (name, shell_functions));
1298 }
1299
1300 /* Return the string value of a variable.  Return NULL if the variable
1301    doesn't exist, or only has a function as a value.  Don't cons a new
1302    string.  This is a potential memory leak if the variable is found
1303    in the temporary environment. */
1304 char *
1305 get_string_value (var_name)
1306      const char *var_name;
1307 {
1308   SHELL_VAR *var;
1309
1310   var = find_variable ((char *)var_name);       /* XXX fix later */
1311
1312   if (!var)
1313     return (char *)NULL;
1314 #if defined (ARRAY_VARS)
1315   else if (array_p (var))
1316     return (array_reference (array_cell (var), 0));
1317 #endif
1318   else
1319     return (var->value);
1320 }
1321
1322 /* This is present for use by the tilde and readline libraries. */
1323 char *
1324 sh_get_env_value (v)
1325      const char *v;
1326 {
1327   return get_string_value (v);
1328 }
1329
1330 /* Create a local variable referenced by NAME. */
1331 SHELL_VAR *
1332 make_local_variable (name)
1333      char *name;
1334 {
1335   SHELL_VAR *new_var, *old_var;
1336   BUCKET_CONTENTS *elt;
1337   int old_var_context;
1338
1339   /* local foo; local foo;  is a no-op. */
1340   old_var = find_variable (name);
1341   if (old_var && old_var->context == variable_context)
1342     return (old_var);
1343
1344   /* Since this is called only from the local/declare/typeset code, we can
1345      call builtin_error here without worry (of course, it will also work
1346      for anything that sets this_command_name).  Variables with the `noassign'
1347      attribute may not be made local.  The test against old_var's context
1348      level is to disallow local copies of readonly global variables (since I
1349      believe that this could be a security hole).  Readonly copies of calling
1350      function local variables are OK. */
1351   if (old_var && (noassign_p (old_var) ||
1352                  (readonly_p (old_var) && old_var->context == 0)))
1353     {
1354       if (readonly_p (old_var))
1355         builtin_error ("%s: readonly variable");
1356       return ((SHELL_VAR *)NULL);
1357     }
1358
1359   elt = remove_hash_item (name, shell_variables);
1360   if (elt)
1361     {
1362       old_var = (SHELL_VAR *)elt->data;
1363       free (elt->key);
1364       free (elt);
1365     }
1366   else
1367     old_var = (SHELL_VAR *)NULL;
1368
1369   /* If a variable does not already exist with this name, then
1370      just make a new one. */
1371   if (old_var == 0)
1372     new_var = bind_variable (name, "");
1373   else
1374     {
1375       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1376
1377       new_var->name = savestring (name);
1378       new_var->value = xmalloc (1);
1379       new_var->value[0] = '\0';
1380
1381       CLEAR_EXPORTSTR (new_var);
1382
1383       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
1384       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
1385
1386       new_var->attributes = exported_p (old_var) ? att_exported : 0;
1387
1388       new_var->prev_context = old_var;
1389       elt = add_hash_item (savestring (name), shell_variables);
1390       elt->data = (char *)new_var;
1391     }
1392
1393   new_var->context = variable_context;
1394   VSETATTR (new_var, att_local);
1395
1396   /* XXX */
1397   if (variable_context >= local_variable_stack_size)
1398     {
1399       int old_size = local_variable_stack_size;
1400       RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
1401                               local_variable_stack_size, 8);
1402       bzero ((char *)have_local_variables + old_size,
1403              local_variable_stack_size - old_size);
1404     }
1405   have_local_variables[variable_context] = 1;           /* XXX */
1406
1407   return (new_var);
1408 }
1409
1410 #if defined (ARRAY_VARS)
1411 SHELL_VAR *
1412 make_local_array_variable (name)
1413      char *name;
1414 {
1415   SHELL_VAR *var;
1416   ARRAY *array;
1417
1418   var = make_local_variable (name);
1419   if (var == 0)
1420     return var;
1421   array = new_array ();
1422
1423   FREE (value_cell(var));
1424   var->value = (char *)array;
1425   VSETATTR (var, att_array);
1426   return var;
1427 }
1428 #endif /* ARRAY_VARS */
1429
1430 /* Create a new shell variable with name NAME and add it to the hash table
1431    of shell variables. */
1432 static
1433 SHELL_VAR *
1434 make_new_variable (name)
1435      char *name;
1436 {
1437   SHELL_VAR *entry;
1438   BUCKET_CONTENTS *elt;
1439
1440   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1441
1442   entry->attributes = 0;
1443   entry->name = savestring (name);
1444   entry->value = (char *)NULL;
1445   CLEAR_EXPORTSTR (entry);
1446
1447   entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
1448   entry->assign_func = (DYNAMIC_FUNC *)NULL;
1449
1450   /* Always assume variables are to be made at toplevel!
1451      make_local_variable has the responsibilty of changing the
1452      variable context. */
1453   entry->context = 0;
1454   entry->prev_context = (SHELL_VAR *)NULL;
1455
1456   /* Make sure we have a shell_variables hash table to add to. */
1457   if (shell_variables == 0)
1458     shell_variables = make_hash_table (0);
1459
1460   elt = add_hash_item (savestring (name), shell_variables);
1461   elt->data = (char *)entry;
1462
1463   return entry;
1464 }
1465
1466 #if defined (ARRAY_VARS)
1467 SHELL_VAR *
1468 make_new_array_variable (name)
1469      char *name;
1470 {
1471   SHELL_VAR *entry;
1472   ARRAY *array;
1473
1474   entry = make_new_variable (name);
1475   array = new_array ();
1476   entry->value = (char *)array;
1477   VSETATTR (entry, att_array);
1478   return entry;
1479 }
1480 #endif
1481
1482 char *
1483 make_variable_value (var, value)
1484      SHELL_VAR *var;
1485      char *value;
1486 {
1487   char *retval;
1488   long lval;
1489   int expok;
1490
1491   /* If this variable has had its type set to integer (via `declare -i'),
1492      then do expression evaluation on it and store the result.  The
1493      functions in expr.c (evalexp and bind_int_variable) are responsible
1494      for turning off the integer flag if they don't want further
1495      evaluation done. */
1496   if (integer_p (var))
1497     {
1498       lval = evalexp (value, &expok);
1499       if (expok == 0)
1500         jump_to_top_level (DISCARD);
1501       retval = itos (lval);
1502     }
1503   else if (value)
1504     {
1505       if (*value)
1506         retval = savestring (value);
1507       else
1508         {
1509           retval = xmalloc (1);
1510           retval[0] = '\0';
1511         }
1512     }
1513   else
1514     retval = (char *)NULL;
1515
1516   return retval;
1517 }
1518
1519 /* Bind a variable NAME to VALUE.  This conses up the name
1520    and value strings. */
1521 SHELL_VAR *
1522 bind_variable (name, value)
1523      char *name, *value;
1524 {
1525   char *newval;
1526   SHELL_VAR *entry, *tempenv_entry;
1527   int found_in_tempenv;
1528
1529   entry = (SHELL_VAR *)0;
1530   found_in_tempenv = 0;
1531
1532   /* If we have a temporary environment, look there first for the variable,
1533      and, if found, modify the value there before modifying it in the
1534      shell_variables table.  This allows sourced scripts to modify values
1535      given to them in a temporary environment while modifying the variable
1536      value that the caller sees. */
1537   if (temporary_env || builtin_env || function_env)
1538     {
1539       tempenv_entry = find_tempenv_variable (name);
1540       if (tempenv_entry)
1541         {
1542           dispose_variable (tempenv_entry);
1543           tempenv_entry = bind_tempenv_variable (name, value);
1544           dispose_variable (tempenv_entry);
1545         }
1546     }
1547     
1548   entry = var_lookup (name, shell_variables);
1549
1550   if (entry == 0)
1551     {
1552       entry = make_new_variable (name);
1553       entry->value = make_variable_value (entry, value);
1554     }
1555   else if (entry->assign_func)  /* array vars have assign functions now */
1556     {
1557       INVALIDATE_EXPORTSTR (entry);
1558       return ((*(entry->assign_func)) (entry, value));
1559     }
1560   else
1561     {
1562       if (readonly_p (entry) || noassign_p (entry))
1563         {
1564           if (readonly_p (entry))
1565             report_error ("%s: readonly variable", name);
1566           return (entry);
1567         }
1568
1569       /* Variables which are bound are visible. */
1570       VUNSETATTR (entry, att_invisible);
1571
1572       newval = make_variable_value (entry, value);
1573
1574       /* Invalidate any cached export string */
1575       INVALIDATE_EXPORTSTR (entry);
1576
1577 #if defined (ARRAY_VARS)
1578       /* XXX -- this bears looking at again -- XXX */
1579       /* If an existing array variable x is being assigned to with x=b or
1580          `read x' or something of that nature, silently convert it to
1581          x[0]=b or `read x[0]'. */
1582       if (array_p (entry))
1583         {
1584           array_add_element (array_cell (entry), 0, newval);
1585           free (newval);
1586         }
1587       else
1588         {
1589           FREE (entry->value);
1590           entry->value = newval;
1591         }
1592 #else
1593       FREE (entry->value);
1594       entry->value = newval;
1595 #endif
1596     }
1597
1598   if (mark_modified_vars)
1599     VSETATTR (entry, att_exported);
1600
1601   if (exported_p (entry))
1602     array_needs_making = 1;
1603
1604   return (entry);
1605 }
1606
1607 /* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
1608    value, variables are no longer invisible.  This is a duplicate of part
1609    of the internals of bind_variable.  If the variable is exported, or
1610    all modified variables should be exported, mark the variable for export
1611    and note that the export environment needs to be recreated. */
1612 SHELL_VAR *
1613 bind_variable_value (var, value)
1614      SHELL_VAR *var;
1615      char *value;
1616 {
1617   char *t;
1618
1619   VUNSETATTR (var, att_invisible);
1620
1621   t = make_variable_value (var, value);
1622   FREE (var->value);
1623   var->value = t;
1624
1625   INVALIDATE_EXPORTSTR (var);
1626
1627   if (mark_modified_vars)
1628     VSETATTR (var, att_exported);
1629
1630   if (exported_p (var))
1631     array_needs_making = 1;
1632
1633   return (var);
1634 }
1635
1636 /* Bind/create a shell variable with the name LHS to the RHS.
1637    This creates or modifies a variable such that it is an integer.
1638
1639    This used to be in expr.c, but it is here so that all of the
1640    variable binding stuff is localized.  Since we don't want any
1641    recursive evaluation from bind_variable() (possible without this code,
1642    since bind_variable() calls the evaluator for variables with the integer
1643    attribute set), we temporarily turn off the integer attribute for each
1644    variable we set here, then turn it back on after binding as necessary. */
1645
1646 SHELL_VAR *
1647 bind_int_variable (lhs, rhs)
1648      char *lhs, *rhs;
1649 {
1650   register SHELL_VAR *v;
1651   int isint;
1652
1653   isint = 0;
1654   v = find_variable (lhs);
1655   if (v)
1656     {
1657       isint = integer_p (v);
1658       VUNSETATTR (v, att_integer);
1659     }
1660
1661   v = bind_variable (lhs, rhs);
1662   if (isint)
1663     VSETATTR (v, att_integer);
1664
1665   return (v);
1666 }
1667
1668 #if defined (ARRAY_VARS)
1669 /* Convert a shell variable to an array variable.  The original value is
1670    saved as array[0]. */
1671 SHELL_VAR *
1672 convert_var_to_array (var)
1673      SHELL_VAR *var;
1674 {
1675   char *oldval;
1676   ARRAY *array;
1677
1678   oldval = value_cell (var);
1679   array = new_array ();
1680   array_add_element (array, 0, oldval);
1681
1682   FREE (value_cell (var));
1683   var->value = (char *)array;
1684
1685   INVALIDATE_EXPORTSTR (var);
1686
1687   VSETATTR (var, att_array);
1688   VUNSETATTR (var, att_invisible);
1689
1690   return var;
1691 }
1692
1693 /* Perform an array assignment name[ind]=value.  If NAME already exists and
1694    is not an array, and IND is 0, perform name=value instead.  If NAME exists
1695    and is not an array, and IND is not 0, convert it into an array with the
1696    existing value as name[0].
1697
1698    If NAME does not exist, just create an array variable, no matter what
1699    IND's value may be. */
1700 SHELL_VAR *
1701 bind_array_variable (name, ind, value)
1702      char *name;
1703      int ind;
1704      char *value;
1705 {
1706   SHELL_VAR *entry;
1707   char *newval;
1708
1709   entry = var_lookup (name, shell_variables);
1710
1711   if (entry == (SHELL_VAR *) 0)
1712     entry = make_new_array_variable (name);
1713   else if (readonly_p (entry) || noassign_p (entry))
1714     {
1715       if (readonly_p (entry))
1716         report_error ("%s: readonly variable", name);
1717       return (entry);
1718     }
1719   else if (array_p (entry) == 0)
1720     entry = convert_var_to_array (entry);
1721
1722   /* ENTRY is an array variable, and ARRAY points to the value. */
1723   newval = make_variable_value (entry, value);
1724   if (entry->assign_func)
1725     (*entry->assign_func) (entry, ind, newval);
1726   else
1727     array_add_element (array_cell (entry), ind, newval);
1728   FREE (newval);
1729
1730   return (entry);
1731 }
1732
1733 /* Perform a compound assignment statement for array NAME, where VALUE is
1734    the text between the parens:  NAME=( VALUE ) */
1735 SHELL_VAR *
1736 assign_array_from_string (name, value)
1737      char *name, *value;
1738 {
1739   SHELL_VAR *var;
1740
1741   var = find_variable (name);
1742   if (var == 0)
1743     var = make_new_array_variable (name);
1744   else if (readonly_p (var) || noassign_p (var))
1745     {
1746       if (readonly_p (var))
1747         report_error ("%s: readonly variable", name);
1748       return ((SHELL_VAR *)NULL);
1749     }
1750   else if (array_p (var) == 0)
1751     var = convert_var_to_array (var);
1752
1753   return (assign_array_var_from_string (var, value));
1754 }
1755
1756 SHELL_VAR *
1757 assign_array_var_from_word_list (var, list)
1758      SHELL_VAR *var;
1759      WORD_LIST *list;
1760 {
1761   register int i;
1762   register WORD_LIST *l;
1763   ARRAY *a;
1764
1765   for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
1766     if (var->assign_func)
1767       (*var->assign_func) (var, i, l->word->word);
1768     else
1769       array_add_element (a, i, l->word->word);
1770   return var;
1771 }
1772
1773 /* For each word in a compound array assignment, if the word looks like
1774    [ind]=value, quote the `[' and `]' before the `=' to protect them from
1775    unwanted filename expansion. */
1776 static void
1777 quote_array_assignment_chars (list)
1778      WORD_LIST *list;
1779 {
1780   char *s, *t, *nword;
1781   int saw_eq;
1782   WORD_LIST *l;
1783
1784   for (l = list; l; l = l->next)
1785     {
1786       if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
1787         continue;       /* should not happen, but just in case... */
1788       /* Don't bother if it doesn't look like [ind]=value */
1789       if (l->word->word[0] != '[' || strchr (l->word->word, '=') == 0) /* ] */
1790         continue;
1791       s = nword = xmalloc (strlen (l->word->word) * 2 + 1);
1792       saw_eq = 0;
1793       for (t = l->word->word; *t; )
1794         {
1795           if (*t == '=')
1796             saw_eq = 1;
1797           if (saw_eq == 0 && (*t == '[' || *t == ']'))
1798             *s++ = '\\';
1799           *s++ = *t++;
1800         }
1801       *s = '\0';
1802       free (l->word->word);
1803       l->word->word = nword;
1804     }
1805 }
1806
1807 /* Perform a compound array assignment:  VAR->name=( VALUE ).  The
1808    VALUE has already had the parentheses stripped. */
1809 SHELL_VAR *
1810 assign_array_var_from_string (var, value)
1811      SHELL_VAR *var;
1812      char *value;
1813 {
1814   ARRAY *a;
1815   WORD_LIST *list, *nlist;
1816   char *w, *val, *nval;
1817   int ni, len, ind, last_ind;
1818
1819   if (value == 0)
1820     return var;
1821
1822   /* If this is called from declare_builtin, value[0] == '(' and
1823      strchr(value, ')') != 0.  In this case, we need to extract
1824      the value from between the parens before going on. */
1825   if (*value == '(')    /*)*/
1826     {
1827       ni = 1;
1828       val = extract_array_assignment_list (value, &ni);
1829       if (val == 0)
1830         return var;
1831     }
1832   else
1833     val = value;
1834
1835   /* Expand the value string into a list of words, performing all the
1836      shell expansions including pathname generation and word splitting. */
1837   /* First we split the string on whitespace, using the shell parser
1838      (ksh93 seems to do this). */
1839   list = parse_string_to_word_list (val, "array assign");
1840
1841   /* If we're using [subscript]=value, we need to quote each [ and ] to
1842      prevent unwanted filename expansion. */
1843   if (list)
1844     quote_array_assignment_chars (list);
1845
1846   /* Now that we've split it, perform the shell expansions on each
1847      word in the list. */
1848   nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
1849
1850   dispose_words (list);
1851
1852   if (val != value)
1853     free (val);
1854
1855   a = array_cell (var);
1856
1857   /* Now that we are ready to assign values to the array, kill the existing
1858      value. */
1859   if (a)
1860     empty_array (a);
1861
1862   for (last_ind = 0, list = nlist; list; list = list->next)
1863     {
1864       w = list->word->word;
1865
1866       /* We have a word of the form [ind]=value */
1867       if (w[0] == '[')
1868         {
1869           len = skipsubscript (w, 0);
1870
1871           if (w[len] != ']' || w[len+1] != '=')
1872             {
1873               nval = make_variable_value (var, w);
1874               if (var->assign_func)
1875                 (*var->assign_func) (var, last_ind, nval);
1876               else
1877                 array_add_element (a, last_ind, nval);
1878               FREE (nval);
1879               last_ind++;
1880               continue;
1881             }
1882
1883           if (len == 1)
1884             {
1885               report_error ("%s: bad array subscript", w);
1886               continue;
1887             }
1888
1889           if (ALL_ELEMENT_SUB (w[1]) && len == 2)
1890             {
1891               report_error ("%s: cannot assign to non-numeric index", w);
1892               continue;
1893             }
1894
1895           ind = array_expand_index (w + 1, len);
1896           if (ind < 0)
1897             {
1898               report_error ("%s: bad array subscript", w);
1899               continue;
1900             }
1901           last_ind = ind;
1902           val = w + len + 2;
1903         }
1904       else              /* No [ind]=value, just a stray `=' */
1905         {
1906           ind = last_ind;
1907           val = w;
1908         }
1909
1910       if (integer_p (var))
1911         this_command_name = (char *)NULL;       /* no command name for errors */
1912       nval = make_variable_value (var, val);
1913       if (var->assign_func)
1914         (*var->assign_func) (var, ind, nval);
1915       else
1916         array_add_element (a, ind, nval);
1917       FREE (nval);
1918       last_ind++;
1919     }
1920
1921   dispose_words (nlist);
1922   return (var);
1923 }
1924 #endif /* ARRAY_VARS */
1925
1926 /* Dispose of the information attached to VAR. */
1927 void
1928 dispose_variable (var)
1929      SHELL_VAR *var;
1930 {
1931   if (!var)
1932     return;
1933
1934   if (function_p (var))
1935     dispose_command (function_cell (var));
1936 #if defined (ARRAY_VARS)
1937   else if (array_p (var))
1938     dispose_array (array_cell (var));
1939 #endif
1940   else
1941     FREE (value_cell (var));
1942
1943   FREE_EXPORTSTR (var);
1944
1945   free (var->name);
1946
1947   if (exported_p (var))
1948     array_needs_making = 1;
1949
1950   free (var);
1951 }
1952
1953 #if defined (ARRAY_VARS)
1954 /* This function is called with SUB pointing to just after the beginning
1955    `[' of an array subscript. */
1956 int
1957 unbind_array_element (var, sub)
1958      SHELL_VAR *var;
1959      char *sub;
1960 {
1961   int len, ind;
1962   ARRAY_ELEMENT *ae;
1963
1964   len = skipsubscript (sub, 0);
1965   if (sub[len] != ']' || len == 0)
1966     {
1967       builtin_error ("%s[%s: bad array subscript", var->name, sub);
1968       return -1;
1969     }
1970   sub[len] = '\0';
1971
1972   if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
1973     {
1974       makunbound (var->name, shell_variables);
1975       return (0);
1976     }
1977   ind = array_expand_index (sub, len+1);
1978   if (ind < 0)
1979     {
1980       builtin_error ("[%s]: bad array subscript", sub);
1981       return -1;
1982     }
1983   ae = array_delete_element (array_cell (var), ind);
1984   if (ae)
1985     destroy_array_element (ae);
1986   return 0;
1987 }
1988 #endif
1989
1990 /* Unset the variable referenced by NAME. */
1991 int
1992 unbind_variable (name)
1993      char *name;
1994 {
1995   SHELL_VAR *var;
1996
1997   var = find_variable (name);
1998   if (!var)
1999     return (-1);
2000
2001   /* This function should never be called with an array variable name. */
2002 #if defined (ARRAY_VARS)
2003   if (array_p (var) == 0 && var->value)
2004 #else
2005   if (var->value)
2006 #endif
2007     {
2008       free (var->value);
2009       var->value = (char *)NULL;
2010     }
2011
2012   makunbound (name, shell_variables);
2013
2014   return (0);
2015 }
2016
2017 /* Make the variable associated with NAME go away.  HASH_LIST is the
2018    hash table from which this variable should be deleted (either
2019    shell_variables or shell_functions).
2020    Returns non-zero if the variable couldn't be found. */
2021 int
2022 makunbound (name, hash_list)
2023      char *name;
2024      HASH_TABLE *hash_list;
2025 {
2026   BUCKET_CONTENTS *elt, *new_elt;
2027   SHELL_VAR *old_var, *new_var;
2028   char *t;
2029
2030   elt = remove_hash_item (name, hash_list);
2031
2032   if (elt == 0)
2033     return (-1);
2034
2035   old_var = (SHELL_VAR *)elt->data;
2036   new_var = old_var->prev_context;
2037
2038   if (old_var && exported_p (old_var))
2039     array_needs_making++;
2040
2041 #if defined (PROGRAMMABLE_COMPLETION)
2042   if (hash_list == shell_functions)
2043     set_itemlist_dirty (&it_functions);
2044 #endif
2045
2046   /* If we're unsetting a local variable and we're still executing inside
2047      the function, just mark the variable as invisible.
2048      kill_all_local_variables will clean it up later.  This must be done
2049      so that if the variable is subsequently assigned a new value inside
2050      the function, the `local' attribute is still present.  We also need
2051      to add it back into the correct hash table. */
2052   if (old_var && local_p (old_var) && variable_context == old_var->context)
2053     {
2054       VSETATTR (old_var, att_invisible);
2055       INVALIDATE_EXPORTSTR (old_var);
2056       new_elt = add_hash_item (savestring (old_var->name), hash_list);
2057       new_elt->data = (char *)old_var;
2058       stupidly_hack_special_variables (old_var->name);
2059       free (elt->key);
2060       free (elt);
2061       return (0);
2062     }
2063
2064   if (new_var)
2065     {
2066       /* Has to be a variable, functions don't have previous contexts. */
2067       new_elt = add_hash_item (savestring (new_var->name), hash_list);
2068       new_elt->data = (char *)new_var;
2069
2070       if (exported_p (new_var))
2071         set_auto_export (new_var);
2072     }
2073
2074   /* Have to save a copy of name here, because it might refer to
2075      old_var->name.  If so, stupidly_hack_special_variables will
2076      reference freed memory. */
2077   t = savestring (name);
2078
2079   free (elt->key);
2080   free (elt);
2081
2082   dispose_variable (old_var);
2083   stupidly_hack_special_variables (t);
2084   free (t);
2085   return (0);
2086 }
2087
2088 #ifdef INCLUDE_UNUSED
2089 /* Remove the variable with NAME if it is a local variable in the
2090    current context. */
2091 int
2092 kill_local_variable (name)
2093      char *name;
2094 {
2095   SHELL_VAR *temp;
2096
2097   temp = find_variable (name);
2098   if (temp && temp->context == variable_context)
2099     {
2100       makunbound (name, shell_variables);
2101       return (0);
2102     }
2103   return (-1);
2104 }
2105 #endif
2106
2107 /* Get rid of all of the variables in the current context. */
2108 int
2109 variable_in_context (var)
2110      SHELL_VAR *var;
2111 {
2112   return (var && var->context == variable_context);
2113 }
2114
2115 void
2116 kill_all_local_variables ()
2117 {
2118   register int i, pass;
2119   register SHELL_VAR *var, **list;
2120   HASH_TABLE *varlist;
2121
2122   /* If HAVE_LOCAL_VARIABLES == 0, it means that we don't have any local
2123      variables at all.  If VARIABLE_CONTEXT >= LOCAL_VARIABLE_STACK_SIZE,
2124      it means that we have some local variables, but not in this variable
2125      context (level of function nesting).  Also, if
2126      HAVE_LOCAL_VARIABLES[VARIABLE_CONTEXT] == 0, we have no local variables
2127      at this context. */
2128   if (have_local_variables == 0 ||
2129       variable_context >= local_variable_stack_size ||
2130       have_local_variables[variable_context] == 0)
2131     return;
2132
2133   for (pass = 0; pass < 2; pass++)
2134     {
2135       varlist = pass ? shell_functions : shell_variables;
2136
2137       list = map_over (variable_in_context, varlist);
2138
2139       if (list)
2140         {
2141           for (i = 0; var = list[i]; i++)
2142             {
2143               VUNSETATTR (var, att_local);
2144               makunbound (var->name, varlist);
2145             }
2146           free (list);
2147         }
2148     }
2149
2150   have_local_variables[variable_context] = 0;           /* XXX */
2151 }
2152
2153 static void
2154 free_variable_hash_data (data)
2155      char *data;
2156 {
2157   SHELL_VAR *var, *prev;
2158
2159   var = (SHELL_VAR *)data;
2160   while (var)
2161     {
2162       prev = var->prev_context;
2163       dispose_variable (var);
2164       var = prev;
2165     }
2166 }
2167
2168 /* Delete the entire contents of the hash table. */
2169 void
2170 delete_all_variables (hashed_vars)
2171      HASH_TABLE *hashed_vars;
2172 {
2173   flush_hash_table (hashed_vars, free_variable_hash_data);
2174 }
2175
2176 static SHELL_VAR *
2177 new_shell_variable (name)
2178      char *name;
2179 {
2180   SHELL_VAR *var;
2181
2182   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2183
2184   bzero ((char *)var, sizeof (SHELL_VAR));
2185   var->name = savestring (name);
2186   return (var);
2187 }
2188
2189 /* Do a function binding to a variable.  You pass the name and
2190    the command to bind to.  This conses the name and command. */
2191 SHELL_VAR *
2192 bind_function (name, value)
2193      char *name;
2194      COMMAND *value;
2195 {
2196   SHELL_VAR *entry;
2197
2198   entry = find_function (name);
2199   if (!entry)
2200     {
2201       BUCKET_CONTENTS *elt;
2202
2203       elt = add_hash_item (savestring (name), shell_functions);
2204
2205       entry = new_shell_variable (name);
2206       entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
2207       CLEAR_EXPORTSTR (entry);
2208
2209       /* Functions are always made at the top level.  This allows a
2210          function to define another function (like autoload). */
2211       entry->context = 0;
2212
2213       elt->data = (char *)entry;
2214     }
2215
2216   INVALIDATE_EXPORTSTR (entry);
2217
2218   if (entry->value)
2219     dispose_command ((COMMAND *)entry->value);
2220
2221   entry->value = value ? (char *)copy_command (value) : (char *)NULL;
2222   VSETATTR (entry, att_function);
2223
2224   if (mark_modified_vars)
2225     VSETATTR (entry, att_exported);
2226
2227   VUNSETATTR (entry, att_invisible);            /* Just to be sure */
2228
2229   if (exported_p (entry))
2230     array_needs_making = 1;
2231
2232 #if defined (PROGRAMMABLE_COMPLETION)
2233   set_itemlist_dirty (&it_functions);
2234 #endif
2235
2236   return (entry);
2237 }
2238
2239 #ifdef INCLUDE_UNUSED
2240 /* Copy VAR to a new data structure and return that structure. */
2241 SHELL_VAR *
2242 copy_variable (var)
2243      SHELL_VAR *var;
2244 {
2245   SHELL_VAR *copy = (SHELL_VAR *)NULL;
2246
2247   if (var)
2248     {
2249       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2250
2251       copy->attributes = var->attributes;
2252       copy->name = savestring (var->name);
2253
2254       if (function_p (var))
2255         copy->value = (char *)copy_command (function_cell (var));
2256 #if defined (ARRAY_VARS)
2257       else if (array_p (var))
2258         copy->value = (char *)dup_array (array_cell (var));
2259 #endif
2260       else if (value_cell (var))
2261         copy->value = savestring (value_cell (var));
2262       else
2263         copy->value = (char *)NULL;
2264
2265       copy->dynamic_value = var->dynamic_value;
2266       copy->assign_func = var->assign_func;
2267
2268       copy->exportstr = COPY_EXPORTSTR (var);
2269
2270       copy->context = var->context;
2271
2272       /* Don't bother copying previous contexts along with this variable. */
2273       copy->prev_context = (SHELL_VAR *)NULL;
2274     }
2275   return (copy);
2276 }
2277 #endif
2278
2279 #define FIND_OR_MAKE_VARIABLE(name, entry) \
2280   do \
2281     { \
2282       entry = find_variable (name); \
2283       if (!entry) \
2284         { \
2285           entry = bind_variable (name, ""); \
2286           if (!no_invisible_vars) entry->attributes |= att_invisible; \
2287         } \
2288     } \
2289   while (0)
2290
2291 /* Make the variable associated with NAME be readonly.
2292    If NAME does not exist yet, create it. */
2293 void
2294 set_var_read_only (name)
2295      char *name;
2296 {
2297   SHELL_VAR *entry;
2298
2299   FIND_OR_MAKE_VARIABLE (name, entry);
2300   VSETATTR (entry, att_readonly);
2301 }
2302
2303 #ifdef INCLUDE_UNUSED
2304 /* Make the function associated with NAME be readonly.
2305    If NAME does not exist, we just punt, like auto_export code below. */
2306 void
2307 set_func_read_only (name)
2308      char *name;
2309 {
2310   SHELL_VAR *entry;
2311
2312   entry = find_function (name);
2313   if (entry)
2314     VSETATTR (entry, att_readonly);
2315 }
2316
2317 /* Make the variable associated with NAME be auto-exported.
2318    If NAME does not exist yet, create it. */
2319 void
2320 set_var_auto_export (name)
2321      char *name;
2322 {
2323   SHELL_VAR *entry;
2324
2325   FIND_OR_MAKE_VARIABLE (name, entry);
2326   set_auto_export (entry);
2327 }
2328
2329 /* Make the function associated with NAME be auto-exported. */
2330 void
2331 set_func_auto_export (name)
2332      char *name;
2333 {
2334   SHELL_VAR *entry;
2335
2336   entry = find_function (name);
2337   if (entry)
2338     set_auto_export (entry);
2339 }
2340 #endif
2341
2342 #if defined (ARRAY_VARS)
2343 /* This function assumes s[i] == '['; returns with s[ret] == ']' if
2344    an array subscript is correctly parsed. */
2345 int
2346 skipsubscript (s, i)
2347      char *s;
2348      int i;
2349 {
2350   int count, c;
2351
2352   for (count = 1; count && (c = s[++i]); )
2353     {
2354       if (c == '[')
2355         count++;
2356       else if (c == ']')
2357         count--;
2358     }
2359   return i;
2360 }
2361 #endif /* ARRAY_VARS */
2362
2363 /* Returns non-zero if STRING is an assignment statement.  The returned value
2364    is the index of the `=' sign. */
2365 int
2366 assignment (string)
2367      char *string;
2368 {
2369   register int c, newi, indx;
2370
2371   c = string[indx = 0];
2372
2373   if (legal_variable_starter (c) == 0)
2374     return (0);
2375
2376   while (c = string[indx])
2377     {
2378       /* The following is safe.  Note that '=' at the start of a word
2379          is not an assignment statement. */
2380       if (c == '=')
2381         return (indx);
2382
2383 #if defined (ARRAY_VARS)
2384       if (c == '[')
2385         {
2386           newi = skipsubscript (string, indx);
2387           if (string[newi++] != ']')
2388             return (0);
2389           return ((string[newi] == '=') ? newi : 0);
2390         }
2391 #endif /* ARRAY_VARS */
2392
2393       /* Variable names in assignment statements may contain only letters,
2394          digits, and `_'. */
2395       if (legal_variable_char (c) == 0)
2396         return (0);
2397
2398       indx++;
2399     }
2400   return (0);
2401 }
2402
2403 static int
2404 visible_var (var)
2405      SHELL_VAR *var;
2406 {
2407   return (invisible_p (var) == 0);
2408 }
2409
2410 static SHELL_VAR **
2411 _visible_names (table)
2412      HASH_TABLE *table;
2413 {
2414   SHELL_VAR **list;
2415
2416   list = map_over (visible_var, table);
2417
2418   if (list /* && posixly_correct */)
2419     sort_variables (list);
2420
2421   return (list);
2422 }
2423
2424 SHELL_VAR **
2425 all_visible_functions ()
2426 {
2427   return (_visible_names (shell_functions));
2428 }
2429
2430 SHELL_VAR **
2431 all_visible_variables ()
2432 {
2433   return (_visible_names (shell_variables));
2434 }
2435
2436 /* Return non-zero if the variable VAR is visible and exported.  Array
2437    variables cannot be exported. */
2438 static int
2439 visible_and_exported (var)
2440      SHELL_VAR *var;
2441 {
2442   return (invisible_p (var) == 0 && exported_p (var));
2443 }
2444
2445 SHELL_VAR **
2446 all_exported_variables ()
2447 {
2448   SHELL_VAR **list;
2449
2450   list = map_over (visible_and_exported, shell_variables);
2451   if (list)
2452     sort_variables (list);
2453   return (list);
2454 }
2455
2456 #if defined (ARRAY_VARS)
2457 /* Return non-zero if the variable VAR is visible and an array. */
2458 static int
2459 visible_array_vars (var)
2460      SHELL_VAR *var;
2461 {
2462   return (invisible_p (var) == 0 && array_p (var));
2463 }
2464
2465 SHELL_VAR **
2466 all_array_variables ()
2467 {
2468   SHELL_VAR **list;
2469
2470   list = map_over (visible_array_vars, shell_variables);
2471   if (list)
2472     sort_variables (list);
2473   return (list);
2474 }
2475 #endif /* ARRAY_VARS */
2476
2477 char **
2478 all_variables_matching_prefix (prefix)
2479      char *prefix;
2480 {
2481   SHELL_VAR **varlist;
2482   char **rlist;
2483   int vind, rind, plen;
2484
2485   plen = STRLEN (prefix);
2486   varlist = all_visible_variables ();
2487   for (vind = 0; varlist && varlist[vind]; vind++)
2488     ;
2489   if (varlist == 0 || vind == 0)
2490     return ((char **)NULL);
2491   rlist = alloc_array (vind + 1);
2492   for (vind = rind = 0; varlist[vind]; vind++)
2493     {
2494       if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
2495         rlist[rind++] = savestring (varlist[vind]->name);
2496     }
2497   rlist[rind] = (char *)0;
2498   free (varlist);
2499
2500   return rlist;
2501 }
2502
2503 static inline char *
2504 mk_env_string (name, value)
2505      char *name, *value;
2506 {
2507   int name_len, value_len;
2508   char  *p;
2509
2510   name_len = strlen (name);
2511   value_len = STRLEN (value);
2512   p = xmalloc (2 + name_len + value_len);
2513   strcpy (p, name);
2514   p[name_len] = '=';
2515   if (value && *value)
2516     strcpy (p + name_len + 1, value);
2517   else
2518     p[name_len + 1] = '\0';
2519   return (p);
2520 }
2521
2522 /* Debugging */
2523 static int
2524 valid_exportstr (v)
2525      SHELL_VAR *v;
2526 {
2527   char *s;
2528
2529   s = v->exportstr;
2530   if (legal_variable_starter (*s) == 0)
2531     {
2532       internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2533       return (0);
2534     }
2535   for (s = v->exportstr + 1; s && *s; s++)
2536     {
2537       if (*s == '=')
2538         break;
2539       if (legal_variable_char (*s) == 0)
2540         {
2541           internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2542           return (0);
2543         }
2544     }
2545   if (*s != '=')
2546     {
2547       internal_error ("no `=' in exportstr for %s", v->name);
2548       return (0);
2549     }
2550   return (1);
2551 }
2552
2553 /* Make an array of assignment statements from the hash table
2554    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
2555    variables are eligible. */
2556 char **
2557 make_var_array (hashed_vars)
2558      HASH_TABLE *hashed_vars;
2559 {
2560   register int i, list_index;
2561   register SHELL_VAR *var;
2562   char **list, *value;
2563   SHELL_VAR **vars;
2564
2565   vars = map_over (visible_and_exported, hashed_vars);
2566
2567   if (vars == 0)
2568     return (char **)NULL;
2569
2570   list = alloc_array ((1 + array_len ((char **)vars)));
2571
2572 #define USE_EXPORTSTR (value == var->exportstr)
2573
2574   for (i = 0, list_index = 0; var = vars[i]; i++)
2575     {
2576 #if defined (__CYGWIN__)
2577       /* We don't use the exportstr stuff on Cygwin at all. */
2578       INVALIDATE_EXPORTSTR (var);
2579 #endif
2580       if (var->exportstr)
2581         value = var->exportstr;
2582       else if (function_p (var))
2583         value = named_function_string ((char *)NULL, function_cell (var), 0);
2584 #if defined (ARRAY_VARS)
2585       else if (array_p (var))
2586 #  if 0
2587         value = array_to_assignment_string (array_cell (var));
2588 #  else
2589         continue;       /* XXX array vars cannot yet be exported */
2590 #  endif
2591 #endif
2592       else
2593         value = value_cell (var);
2594
2595       if (value)
2596         {
2597           /* Gee, I'd like to get away with not using savestring() if we're
2598              using the cached exportstr... */
2599           list[list_index] = USE_EXPORTSTR ? savestring (value)
2600                                            : mk_env_string (var->name, value);
2601
2602           if (USE_EXPORTSTR == 0 && function_p (var))
2603             {
2604               SAVE_EXPORTSTR (var, list[list_index]);
2605             }
2606           list_index++;
2607 #undef USE_EXPORTSTR
2608
2609 #if 0   /* not yet */
2610 #if defined (ARRAY_VARS)
2611           if (array_p (var))
2612             free (value);
2613 #endif
2614 #endif
2615         }
2616     }
2617
2618   free (vars);
2619   list[list_index] = (char *)NULL;
2620   return (list);
2621 }
2622
2623 /* Add STRING to the array of foo=bar strings that we already
2624    have to add to the environment.  */
2625 int
2626 assign_in_env (string)
2627      char *string;
2628 {
2629   int size, offset;
2630   char *name, *temp, *value;
2631   int nlen, vlen;
2632   WORD_LIST *list;
2633   SHELL_VAR *var;
2634
2635   offset = assignment (string);
2636   name = savestring (string);
2637   value = (char *)NULL;
2638
2639   if (name[offset] == '=')
2640     {
2641       name[offset] = 0;
2642
2643       var = find_variable (name);
2644       if (var && (readonly_p (var) || noassign_p (var)))
2645         {
2646           if (readonly_p (var))
2647             report_error ("%s: readonly variable", name);
2648           free (name);
2649           return (0);
2650         }
2651
2652       temp = name + offset + 1;
2653       temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
2654
2655       list = expand_string_unsplit (temp, 0);
2656       value = string_list (list);
2657
2658       if (list)
2659         dispose_words (list);
2660
2661       free (temp);
2662     }
2663
2664   temp = mk_env_string (name, value);
2665   FREE (value);
2666   free (name);
2667
2668   if (temporary_env == 0)
2669     {
2670       temporary_env = (char **)xmalloc (sizeof (char *));
2671       temporary_env [0] = (char *)NULL;
2672     }
2673
2674   size = array_len (temporary_env);
2675   temporary_env = (char **)
2676     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
2677
2678   temporary_env[size] = temp;
2679   temporary_env[size + 1] = (char *)NULL;
2680   array_needs_making = 1;
2681
2682   if (echo_command_at_execute)
2683     {
2684       /* The Korn shell prints the `+ ' in front of assignment statements,
2685          so we do too. */
2686       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
2687       fflush (stderr);
2688     }
2689
2690   return 1;
2691 }
2692
2693 /* Create a SHELL_VAR from a `name=value' string as in the environment, taking
2694    the variable name, the environment string, and an index into the string
2695    which is the offset of the `=' (the char before the value begins). */
2696 static SHELL_VAR *
2697 shell_var_from_env_string (name, env_string, l)
2698      char *name, *env_string;
2699      int l;
2700 {
2701   SHELL_VAR *temp;
2702   char *w;
2703
2704   /* This is a potential memory leak.  The code should really save
2705      the created variables in some auxiliary data structure, which
2706      can be disposed of at the appropriate time. */
2707   temp = new_shell_variable (name);
2708   w = env_string + l + 1;
2709
2710   temp->value = *w ? savestring (w) : (char *)NULL;
2711
2712   temp->attributes = att_exported|att_tempvar;
2713   temp->context = 0;
2714   temp->prev_context = (SHELL_VAR *)NULL;
2715
2716   temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
2717   CLEAR_EXPORTSTR (temp);
2718
2719   return (temp);
2720 }
2721
2722 /* Bind NAME to VALUE in ARRAY, an array of strings in the same format as the
2723    environment array (i.e, name=value).  If NAME is present, change the value,
2724    cons up a new SHELL_VAR and return it.  Otherwise return (SHELL_VAR *)NULL. */
2725
2726 static SHELL_VAR *
2727 bind_name_in_env_array (name, value, array)
2728      char *name, *value;
2729      char **array;
2730 {
2731   register int i, l;
2732   char *new_env_string, *w;
2733   SHELL_VAR *temp;
2734
2735   if (array == 0)
2736     return ((SHELL_VAR *)NULL);
2737
2738   for (i = 0, l = strlen (name); array[i]; i++)
2739     {
2740       if (STREQN (array[i], name, l) && array[i][l] == '=')
2741         {
2742           new_env_string = mk_env_string (name, value);
2743
2744           temp = shell_var_from_env_string (name, new_env_string, l);
2745
2746           free (array[i]);
2747           array[i] = new_env_string;
2748
2749           return (temp);
2750         }
2751     }
2752   return ((SHELL_VAR *)NULL);
2753 }
2754
2755 /* Search for NAME in ARRAY, an array of strings in the same format as the
2756    environment array (i.e, name=value).  If NAME is present, make a new
2757    variable and return it.  Otherwise, return NULL. */
2758 static SHELL_VAR *
2759 find_name_in_env_array (name, array)
2760      char *name;
2761      char **array;
2762 {
2763   register int i, l;
2764   SHELL_VAR *temp;
2765
2766   if (array == 0)
2767     return ((SHELL_VAR *)NULL);
2768
2769   for (i = 0, l = strlen (name); array[i]; i++)
2770     {
2771       if (STREQN (array[i], name, l) && array[i][l] == '=')
2772         {
2773           temp = shell_var_from_env_string (name, array[i], l);
2774           return (temp);
2775         }
2776     }
2777   return ((SHELL_VAR *)NULL);
2778 }
2779
2780 #define FIND_AND_BIND_IN_ENV_ARRAY(N, V, A) \
2781   do \
2782     { \
2783       var = find_name_in_env_array (N, A); \
2784       if (var) \
2785         { \
2786           dispose_variable (var); \
2787           var = bind_name_in_env_array (N, V, A); \
2788           return (var); \
2789         } \
2790     } \
2791   while (0)
2792
2793 /* Make variable NAME have VALUE in one of the temporary environments. */
2794 static SHELL_VAR *
2795 bind_tempenv_variable (name, value)
2796      char *name, *value;
2797 {
2798   SHELL_VAR *var;
2799
2800   var = (SHELL_VAR *)NULL;
2801
2802   if (temporary_env)
2803     FIND_AND_BIND_IN_ENV_ARRAY (name, value, temporary_env);
2804
2805   /* We don't check this_shell_builtin because the command that needs the
2806      value from builtin_env may be a disk command run inside a script run
2807      with `.' and a temporary env. */
2808   if (builtin_env)
2809     FIND_AND_BIND_IN_ENV_ARRAY (name, value, builtin_env);
2810
2811   if (variable_context && function_env)
2812     FIND_AND_BIND_IN_ENV_ARRAY (name, value, function_env);
2813
2814   return (SHELL_VAR *)NULL;
2815 }
2816
2817 /* Find a variable in the temporary environment that is named NAME.
2818    The temporary environment can be either the environment provided
2819    to a simple command, or the environment provided to a shell function.
2820    We only search the function environment if we are currently executing
2821    a shell function body (variable_context > 0).  Return a consed variable,
2822    or NULL if not found. */
2823 SHELL_VAR *
2824 find_tempenv_variable (name)
2825      char *name;
2826 {
2827   SHELL_VAR *var;
2828
2829   var = (SHELL_VAR *)NULL;
2830
2831   if (temporary_env)
2832     var = find_name_in_env_array (name, temporary_env);
2833
2834   /* We don't check this_shell_builtin because the command that needs the
2835      value from builtin_env may be a disk command run inside a script run
2836      with `.' and a temporary env. */
2837   if (!var && builtin_env)
2838     var = find_name_in_env_array (name, builtin_env);
2839
2840   if (!var && variable_context && function_env)
2841     var = find_name_in_env_array (name, function_env);
2842
2843   return (var);
2844 }
2845
2846 /* Free the storage allocated to the string array pointed to by ARRAYP, and
2847    make that variable have a null pointer as a value. */
2848 static void
2849 dispose_temporary_vars (arrayp)
2850      char ***arrayp;
2851 {
2852   if (!*arrayp)
2853     return;
2854
2855   free_array (*arrayp);
2856   *arrayp = (char **)NULL;
2857   array_needs_making = 1;
2858 }
2859
2860 /* Free the storage used in the variable array for temporary
2861    environment variables. */
2862 void
2863 dispose_used_env_vars ()
2864 {
2865   dispose_temporary_vars (&temporary_env);
2866 }
2867
2868 /* Free the storage used for temporary environment variables given to
2869    commands when executing inside of a function body. */
2870 void
2871 dispose_function_env ()
2872 {
2873   dispose_temporary_vars (&function_env);
2874 }
2875
2876 /* Free the storage used for temporary environment variables given to
2877    commands when executing a builtin command such as "source". */
2878 void
2879 dispose_builtin_env ()
2880 {
2881   dispose_temporary_vars (&builtin_env);
2882 }
2883
2884 /* Take all of the shell variables in ENV_ARRAY and make shell variables
2885    from them at the current variable context. */
2886 static void
2887 merge_env_array (env_array)
2888      char **env_array;
2889 {
2890   register int i, l;
2891   SHELL_VAR *temp;
2892   char *val, *name;
2893
2894   if (env_array == 0)
2895     return;
2896
2897   for (i = 0; env_array[i]; i++)
2898     {
2899       l = assignment (env_array[i]);
2900       name = env_array[i];
2901       val = env_array[i] + l + 1;
2902       name[l] = '\0';
2903       temp = bind_variable (name, val);
2904       name[l] = '=';
2905     }
2906 }
2907
2908 void
2909 merge_temporary_env ()
2910 {
2911   merge_env_array (temporary_env);
2912 }
2913
2914 void
2915 merge_builtin_env ()
2916 {
2917   merge_env_array (builtin_env);
2918 }
2919
2920 void
2921 merge_function_env ()
2922 {
2923   merge_env_array (function_env);
2924 }
2925
2926 int
2927 any_temporary_variables ()
2928 {
2929   return (temporary_env || function_env);
2930 }
2931
2932 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
2933 #define add_to_export_env(envstr,do_alloc) \
2934 do \
2935   { \
2936     if (export_env_index >= (export_env_size - 1)) \
2937       { \
2938         export_env_size += 16; \
2939         export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *)); \
2940       } \
2941     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
2942     export_env[export_env_index] = (char *)NULL; \
2943   } while (0)
2944
2945 #define ISFUNCTION(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
2946
2947 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
2948    array with the same left-hand side.  Return the new EXPORT_ENV. */
2949 char **
2950 add_or_supercede_exported_var (assign, do_alloc)
2951      char *assign;
2952      int do_alloc;
2953 {
2954   register int i;
2955   int equal_offset;
2956
2957   equal_offset = assignment (assign);
2958   if (equal_offset == 0)
2959     return (export_env);
2960
2961   /* If this is a function, then only supercede the function definition.
2962      We do this by including the `=(' in the comparison.  */
2963   if (assign[equal_offset + 1] == '(')
2964     equal_offset++;
2965
2966   for (i = 0; i < export_env_index; i++)
2967     {
2968       if (STREQN (assign, export_env[i], equal_offset + 1))
2969         {
2970           free (export_env[i]);
2971           export_env[i] = do_alloc ? savestring (assign) : assign;
2972           return (export_env);
2973         }
2974     }
2975   add_to_export_env (assign, do_alloc);
2976   return (export_env);
2977 }
2978
2979 /* Make the environment array for the command about to be executed, if the
2980    array needs making.  Otherwise, do nothing.  If a shell action could
2981    change the array that commands receive for their environment, then the
2982    code should `array_needs_making++'. */
2983 void
2984 maybe_make_export_env ()
2985 {
2986   register int i;
2987   register char **temp_array;
2988   int new_size;
2989
2990   if (array_needs_making)
2991     {
2992       if (export_env)
2993         free_array_members (export_env);
2994
2995       /* Make a guess based on how many shell variables and functions we
2996          have.  Since there will always be array variables, and array
2997          variables are not (yet) exported, this will always be big enough
2998          for the exported variables and functions, without any temporary
2999          or function environments. */
3000       new_size = HASH_ENTRIES (shell_variables) + HASH_ENTRIES (shell_functions) + 1;
3001       if (new_size > export_env_size)
3002         {
3003           export_env_size = new_size;
3004           export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
3005         }
3006       export_env[export_env_index = 0] = (char *)NULL;
3007
3008       temp_array = make_var_array (shell_variables);
3009       if (temp_array)
3010         {
3011           for (i = 0; temp_array[i]; i++)
3012             add_to_export_env (temp_array[i], 0);
3013           free (temp_array);
3014         }
3015
3016       temp_array = make_var_array (shell_functions);
3017       if (temp_array)
3018         {
3019           for (i = 0; temp_array[i]; i++)
3020             add_to_export_env (temp_array[i], 0);
3021           free (temp_array);
3022         }
3023
3024       if (function_env)
3025         for (i = 0; function_env[i]; i++)
3026           export_env = add_or_supercede_exported_var (function_env[i], 1);
3027
3028       if (builtin_env)
3029         for (i = 0; builtin_env[i]; i++)
3030           export_env = add_or_supercede_exported_var (builtin_env[i], 1);
3031
3032       if (temporary_env)
3033         for (i = 0; temporary_env[i]; i++)
3034           export_env = add_or_supercede_exported_var (temporary_env[i], 1);
3035
3036 #if 0
3037       /* If we changed the array, then sort it alphabetically. */
3038       if (posixly_correct == 0 && (temporary_env || function_env))
3039         sort_char_array (export_env);
3040 #endif
3041
3042       array_needs_making = 0;
3043     }
3044 }
3045
3046 /* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
3047    we will need to remake the exported environment every time we
3048    change directories.  `_' is always put into the environment for
3049    every external command, so without special treatment it will always
3050    cause the environment to be remade.
3051
3052    If there is no other reason to make the exported environment, we can
3053    just update the variables in place and mark the exported environment
3054    as no longer needing a remake. */
3055 void
3056 update_export_env_inplace (env_prefix, preflen, value)
3057      char *env_prefix;
3058      int preflen;
3059      char *value;
3060 {
3061   char *evar;
3062
3063   evar = xmalloc (STRLEN (value) + preflen + 1);
3064   strcpy (evar, env_prefix);
3065   if (value)
3066     strcpy (evar + preflen, value);
3067   export_env = add_or_supercede_exported_var (evar, 0);
3068 }
3069
3070 /* We always put _ in the environment as the name of this command. */
3071 void
3072 put_command_name_into_env (command_name)
3073      char *command_name;
3074 {
3075   update_export_env_inplace ("_=", 2, command_name);
3076 }
3077
3078 #if 0   /* UNUSED -- it caused too many problems */
3079 void
3080 put_gnu_argv_flags_into_env (pid, flags_string)
3081      int pid;
3082      char *flags_string;
3083 {
3084   char *dummy, *pbuf;
3085   int l, fl;
3086
3087   pbuf = itos (pid);
3088   l = strlen (pbuf);
3089
3090   fl = strlen (flags_string);
3091
3092   dummy = xmalloc (l + fl + 30);
3093   dummy[0] = '_';
3094   strcpy (dummy + 1, pbuf);
3095   strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3096   dummy[l + 27] = '=';
3097   strcpy (dummy + l + 28, flags_string);
3098
3099   free (pbuf);
3100
3101   export_env = add_or_supercede_exported_var (dummy, 0);
3102 }
3103 #endif
3104
3105 /* Return a string denoting what our indirection level is. */
3106 static char indirection_string[100];
3107
3108 char *
3109 indirection_level_string ()
3110 {
3111   register int i, j;
3112   char *ps4;
3113
3114   indirection_string[0] = '\0';
3115   ps4 = get_string_value ("PS4");
3116
3117   if (ps4 == 0 || *ps4 == '\0')
3118     return (indirection_string);
3119
3120   ps4 = decode_prompt_string (ps4);
3121
3122   for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
3123     indirection_string[i] = *ps4;
3124
3125   for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
3126     indirection_string[i] = ps4[j];
3127
3128   indirection_string[i] = '\0';
3129   free (ps4);
3130   return (indirection_string);
3131 }
3132
3133 /*************************************************
3134  *                                               *
3135  *      Functions to manage special variables    *
3136  *                                               *
3137  *************************************************/
3138
3139 /* Extern declarations for variables this code has to manage. */
3140 extern int eof_encountered, eof_encountered_limit, ignoreeof;
3141
3142 #if defined (READLINE)
3143 extern int no_line_editing;
3144 extern int hostname_list_initialized;
3145 #endif
3146
3147 /* An alist of name.function for each special variable.  Most of the
3148    functions don't do much, and in fact, this would be faster with a
3149    switch statement, but by the end of this file, I am sick of switch
3150    statements. */
3151
3152 #define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
3153
3154 struct name_and_function {
3155   char *name;
3156   VFunction *function;
3157 } special_vars[] = {
3158   { "PATH", sv_path },
3159   { "MAIL", sv_mail },
3160   { "MAILPATH", sv_mail },
3161   { "MAILCHECK", sv_mail },
3162
3163   { "POSIXLY_CORRECT", sv_strict_posix },
3164   { "GLOBIGNORE", sv_globignore },
3165
3166   /* Variables which only do something special when READLINE is defined. */
3167 #if defined (READLINE)
3168   { "TERM", sv_terminal },
3169   { "TERMCAP", sv_terminal },
3170   { "TERMINFO", sv_terminal },
3171   { "HOSTFILE", sv_hostfile },
3172 #endif /* READLINE */
3173
3174   /* Variables which only do something special when HISTORY is defined. */
3175 #if defined (HISTORY)
3176   { "HISTIGNORE", sv_histignore },
3177   { "HISTSIZE", sv_histsize },
3178   { "HISTFILESIZE", sv_histsize },
3179   { "HISTCONTROL", sv_history_control },
3180 #  if defined (BANG_HISTORY)
3181   { "histchars", sv_histchars },
3182 #  endif /* BANG_HISTORY */
3183 #endif /* HISTORY */
3184
3185   { "IGNOREEOF", sv_ignoreeof },
3186   { "ignoreeof", sv_ignoreeof },
3187
3188   { "OPTIND", sv_optind },
3189   { "OPTERR", sv_opterr },
3190
3191   { "TEXTDOMAIN", sv_locale },
3192   { "TEXTDOMAINDIR", sv_locale },
3193   { "LC_ALL", sv_locale },
3194   { "LC_COLLATE", sv_locale },
3195   { "LC_CTYPE", sv_locale },
3196   { "LC_MESSAGES", sv_locale },
3197   { "LC_NUMERIC", sv_locale },
3198   { "LANG", sv_locale },
3199
3200 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3201   { "TZ", sv_tz },
3202 #endif
3203
3204   { (char *)0, (VFunction *)0 }
3205 };
3206
3207 /* The variable in NAME has just had its state changed.  Check to see if it
3208    is one of the special ones where something special happens. */
3209 void
3210 stupidly_hack_special_variables (name)
3211      char *name;
3212 {
3213   int i;
3214
3215   for (i = 0; special_vars[i].name; i++)
3216     {
3217       if (STREQ (special_vars[i].name, name))
3218         {
3219           (*(special_vars[i].function)) (name);
3220           return;
3221         }
3222     }
3223 }
3224
3225 /* What to do just after the PATH variable has changed. */
3226 void
3227 sv_path (name)
3228      char *name;
3229 {
3230   /* hash -r */
3231   flush_hashed_filenames ();
3232 }
3233
3234 /* What to do just after one of the MAILxxxx variables has changed.  NAME
3235    is the name of the variable.  This is called with NAME set to one of
3236    MAIL, MAILCHECK, or MAILPATH.  */
3237 void
3238 sv_mail (name)
3239      char *name;
3240 {
3241   /* If the time interval for checking the files has changed, then
3242      reset the mail timer.  Otherwise, one of the pathname vars
3243      to the users mailbox has changed, so rebuild the array of
3244      filenames. */
3245   if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
3246     reset_mail_timer ();
3247   else
3248     {
3249       free_mail_files ();
3250       remember_mail_dates ();
3251     }
3252 }
3253
3254 /* What to do when GLOBIGNORE changes. */
3255 void
3256 sv_globignore (name)
3257      char *name;
3258 {
3259   setup_glob_ignore (name);
3260 }
3261
3262 #if defined (READLINE)
3263 /* What to do just after one of the TERMxxx variables has changed.
3264    If we are an interactive shell, then try to reset the terminal
3265    information in readline. */
3266 void
3267 sv_terminal (name)
3268      char *name;
3269 {
3270   if (interactive_shell && no_line_editing == 0)
3271     rl_reset_terminal (get_string_value ("TERM"));
3272 }
3273
3274 void
3275 sv_hostfile (name)
3276      char *name;
3277 {
3278   SHELL_VAR *v;
3279
3280   v = find_variable (name);
3281   if (v == 0)
3282     clear_hostname_list ();
3283   else
3284     hostname_list_initialized = 0;
3285 }
3286 #endif /* READLINE */
3287
3288 #if defined (HISTORY)
3289 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
3290    If there is a value for this HISTSIZE (and it is numeric), then stifle
3291    the history.  Otherwise, if there is NO value for this variable,
3292    unstifle the history.  If name is HISTFILESIZE, and its value is
3293    numeric, truncate the history file to hold no more than that many
3294    lines. */
3295 void
3296 sv_histsize (name)
3297      char *name;
3298 {
3299   char *temp;
3300   long num;
3301
3302   temp = get_string_value (name);
3303
3304   if (temp && *temp)
3305     {
3306       if (legal_number (temp, &num))
3307         {
3308           if (name[4] == 'S')
3309             {
3310               stifle_history (num);
3311               num = where_history ();
3312               if (history_lines_this_session > num)
3313                 history_lines_this_session = num;
3314             }
3315           else
3316             {
3317               history_truncate_file (get_string_value ("HISTFILE"), (int)num);
3318               if (num <= history_lines_in_file)
3319                 history_lines_in_file = num;
3320             }
3321         }
3322     }
3323   else if (name[4] == 'S')
3324     unstifle_history ();
3325 }
3326
3327 /* What to do after the HISTIGNORE variable changes. */
3328 void
3329 sv_histignore (name)
3330      char *name;
3331 {
3332   setup_history_ignore (name);
3333 }
3334
3335 /* What to do after the HISTCONTROL variable changes. */
3336 void
3337 sv_history_control (name)
3338      char *name;
3339 {
3340   char *temp;
3341
3342   history_control = 0;
3343   temp = get_string_value (name);
3344
3345   if (temp && *temp && STREQN (temp, "ignore", 6))
3346     {
3347       if (temp[6] == 's')       /* ignorespace */
3348         history_control = 1;
3349       else if (temp[6] == 'd')  /* ignoredups */
3350         history_control = 2;
3351       else if (temp[6] == 'b')  /* ignoreboth */
3352         history_control = 3;
3353     }
3354 }
3355
3356 #if defined (BANG_HISTORY)
3357 /* Setting/unsetting of the history expansion character. */
3358 void
3359 sv_histchars (name)
3360      char *name;
3361 {
3362   char *temp;
3363
3364   temp = get_string_value (name);
3365   if (temp)
3366     {
3367       history_expansion_char = *temp;
3368       if (temp[0] && temp[1])
3369         {
3370           history_subst_char = temp[1];
3371           if (temp[2])
3372               history_comment_char = temp[2];
3373         }
3374     }
3375   else
3376     {
3377       history_expansion_char = '!';
3378       history_subst_char = '^';
3379       history_comment_char = '#';
3380     }
3381 }
3382 #endif /* BANG_HISTORY */
3383 #endif /* HISTORY */
3384
3385 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3386 void
3387 sv_tz (name)
3388      char *name;
3389 {
3390   tzset ();
3391 }
3392 #endif
3393
3394 /* If the variable exists, then the value of it can be the number
3395    of times we actually ignore the EOF.  The default is small,
3396    (smaller than csh, anyway). */
3397 void
3398 sv_ignoreeof (name)
3399      char *name;
3400 {
3401   SHELL_VAR *tmp_var;
3402   char *temp;
3403
3404   eof_encountered = 0;
3405
3406   tmp_var = find_variable (name);
3407   ignoreeof = tmp_var != 0;
3408   temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
3409   if (temp)
3410     eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
3411   set_shellopts ();     /* make sure `ignoreeof' is/is not in $SHELLOPTS */
3412 }
3413
3414 void
3415 sv_optind (name)
3416      char *name;
3417 {
3418   char *tt;
3419   int s;
3420
3421   tt = get_string_value ("OPTIND");
3422   if (tt && *tt)
3423     {
3424       s = atoi (tt);
3425
3426       /* According to POSIX, setting OPTIND=1 resets the internal state
3427          of getopt (). */
3428       if (s < 0 || s == 1)
3429         s = 0;
3430     }
3431   else
3432     s = 0;
3433   getopts_reset (s);
3434 }
3435
3436 void
3437 sv_opterr (name)
3438      char *name;
3439 {
3440   char *tt;
3441
3442   tt = get_string_value ("OPTERR");
3443   sh_opterr = (tt && *tt) ? atoi (tt) : 1;
3444 }
3445
3446 void
3447 sv_strict_posix (name)
3448      char *name;
3449 {
3450   SET_INT_VAR (name, posixly_correct);
3451   posix_initialize (posixly_correct);
3452 #if defined (READLINE)
3453   if (interactive_shell)
3454     posix_readline_initialize (posixly_correct);
3455 #endif /* READLINE */
3456   set_shellopts ();     /* make sure `posix' is/is not in $SHELLOPTS */
3457 }
3458
3459 void
3460 sv_locale (name)
3461      char *name;
3462 {
3463   char *v;
3464
3465   v = get_string_value (name);
3466   if (name[0] == 'L' && name[1] == 'A') /* LANG */
3467     set_lang (name, v);
3468   else
3469     set_locale_var (name, v);           /* LC_*, TEXTDOMAIN* */
3470 }
3471
3472 #if defined (ARRAY_VARS)
3473 void
3474 set_pipestatus_array (ps)
3475      int *ps;
3476 {
3477   SHELL_VAR *v;
3478   ARRAY *a;
3479   register int i;
3480   char *t, tbuf[16];
3481
3482   v = find_variable ("PIPESTATUS");
3483   if (v == 0)
3484     v = make_new_array_variable ("PIPESTATUS");
3485   if (array_p (v) == 0)
3486     return;             /* Do nothing if not an array variable. */
3487   a = array_cell (v);
3488   if (a)
3489     empty_array (a);
3490   for (i = 0; ps[i] != -1; i++)
3491     {
3492       t = inttostr (ps[i], tbuf, sizeof (tbuf));
3493       array_add_element (a, i, t);
3494     }
3495 }
3496 #endif
3497
3498 void
3499 set_pipestatus_from_exit (s)
3500      int s;
3501 {
3502 #if defined (ARRAY_VARS)
3503   static int v[2] = { 0, -1 };
3504
3505   v[0] = s;
3506   set_pipestatus_array (v);
3507 #endif
3508 }