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