Imported from ../bash-2.01.1.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 1, 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, 675 Mass Ave, Cambridge, MA 02139, 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 "mailcheck.h"
43 #include "input.h"
44
45 #include "builtins/getopt.h"
46 #include "builtins/common.h"
47 #include <tilde/tilde.h>
48
49 #if defined (HISTORY)
50 #  include "bashhist.h"
51 #endif /* HISTORY */
52
53 /* Variables used here and defined in other files. */
54 extern int posixly_correct;
55 extern int variable_context, line_number;
56 extern int interactive, interactive_shell, login_shell;
57 extern int subshell_environment, indirection_level;
58 extern int build_version, patch_level;
59 extern char *dist_version, *release_status;
60 extern char *shell_name;
61 extern char *primary_prompt, *secondary_prompt;
62 extern char *current_host_name;
63 extern Function *this_shell_builtin;
64 extern char *this_command_name;
65 extern time_t shell_start_time;
66
67 /* The list of shell variables that the user has created, or that came from
68    the environment. */
69 HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
70
71 /* The list of shell functions that the user has created, or that came from
72    the environment. */
73 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
74
75 /* The current variable context.  This is really a count of how deep into
76    executing functions we are. */
77 int variable_context = 0;
78
79 /* The array of shell assignments which are made only in the environment
80    for a single command. */
81 char **temporary_env = (char **)NULL;
82
83 /* The array of shell assignments which are in the environment for the
84    execution of a shell function. */
85 char **function_env = (char **)NULL;
86
87 /* The array of shell assignments which are made only in the environment
88    for the execution of a shell builtin command which may cause more than
89    one command to be executed (e.g., "source"). */
90 char **builtin_env = (char **)NULL;
91
92 /* Some funky variables which are known about specially.  Here is where
93    "$*", "$1", and all the cruft is kept. */
94 char *dollar_vars[10];
95 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
96
97 /* The value of $$. */
98 int dollar_dollar_pid;
99
100 /* An array which is passed to commands as their environment.  It is
101    manufactured from the union of the initial environment and the
102    shell variables that are marked for export. */
103 char **export_env = (char **)NULL;
104 static int export_env_index;
105 static int export_env_size;
106
107 /* Non-zero means that we have to remake EXPORT_ENV. */
108 int array_needs_making = 1;
109
110 /* The number of times BASH has been executed.  This is set
111    by initialize_variables (). */
112 int shell_level = 0;
113
114 static char *have_local_variables;
115 static int local_variable_stack_size;
116
117 /* Some forward declarations. */
118 static void set_home_var ();
119 static void set_shell_var ();
120 static char *get_bash_name ();
121 static void initialize_shell_level ();
122 static void uidset ();
123 static void initialize_dynamic_variables ();
124 static void make_vers_array ();
125 static void sbrand ();          /* set bash random number generator. */
126 static int qsort_var_comp ();
127
128 /* Make VAR be auto-exported.  VAR is a pointer to a SHELL_VAR. */
129 #define set_auto_export(var) \
130   do { var->attributes |= att_exported; array_needs_making = 1; } while (0)
131
132 /* Initialize the shell variables from the current environment. */
133 void
134 initialize_shell_variables (env, no_functions)
135      char **env;
136      int no_functions;  /* If set, don't import functions from ENV. */
137 {
138   char *name, *string, *temp_string;
139   int c, char_index, string_index, string_length;
140   SHELL_VAR *temp_var;
141
142   if (!shell_variables)
143     shell_variables = make_hash_table (0);
144
145   if (!shell_functions)
146     shell_functions = make_hash_table (0);
147
148   for (string_index = 0; string = env[string_index++]; )
149     {
150       char_index = 0;
151       name = string;
152       while ((c = *string++) && c != '=')
153         ;
154       if (string[-1] == '=')
155         char_index = string - name - 1;
156
157       /* If there are weird things in the environment, like `=xxx' or a
158          string without an `=', just skip them. */
159       if (char_index == 0)
160         continue;
161
162       /* ASSERT(name[char_index] == '=') */
163       name[char_index] = '\0';
164       /* Now, name = env variable name, string = env variable value, and
165          char_index == strlen (name) */
166
167       /* If exported function, define it now. */
168       if (no_functions == 0 && STREQN ("() {", string, 4))
169         {
170           string_length = strlen (string);
171           temp_string = xmalloc (3 + string_length + char_index);
172 #if 1
173           strcpy (temp_string, name);
174           temp_string[char_index] = ' ';
175           strcpy (temp_string + char_index + 1, string);
176 #else
177           sprintf (temp_string, "%s %s", name, string);
178 #endif
179
180           parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
181
182           /* Ancient backwards compatibility.  Old versions of bash exported
183              functions like name()=() {...} */
184           if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
185             name[char_index - 2] = '\0';
186
187           if (temp_var = find_function (name))
188             {
189               temp_var->attributes |= (att_exported | att_imported);
190               array_needs_making = 1;
191             }
192           else
193             report_error ("error importing function definition for `%s'", name);
194
195           if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
196             name[char_index - 2] = '(';
197         }
198 #if defined (ARRAY_VARS)
199 #  if 0
200       /* Array variables may not yet be exported. */
201       else if (*string == '(' && string[1] == '[' && strchr (string, ')'))
202         {
203           string_length = 1;
204           temp_string = extract_array_assignment_list (string, &string_length);
205           temp_var = assign_array_from_string (name, temp_string);
206           FREE (temp_string);
207           temp_var->attributes |= (att_exported | att_imported);
208           array_needs_making = 1;
209         }
210 #  endif
211 #endif
212       else
213         {
214           temp_var = bind_variable (name, string);
215           temp_var->attributes |= (att_exported | att_imported);
216           array_needs_making = 1;
217         }
218
219       name[char_index] = '=';
220     }
221
222   /* If we got PWD from the environment, update our idea of the current
223      working directory.  In any case, make sure that PWD exists before
224      checking it.  It is possible for getcwd () to fail on shell startup,
225      and in that case, PWD would be undefined. */
226   temp_var = find_variable ("PWD");
227   if (temp_var && imported_p (temp_var) &&
228       (temp_string = value_cell (temp_var)) &&
229       same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
230     set_working_directory (temp_string);
231   else
232     {
233       temp_string = get_working_directory ("shell-init");
234       if (temp_string)
235         {
236           bind_variable ("PWD", temp_string);
237           free (temp_string);
238         }
239     }
240
241   /* Set up initial value of $_ */
242   temp_var = bind_variable ("_", dollar_vars[0]);
243
244   /* Remember this pid. */
245   dollar_dollar_pid = (int)getpid ();
246
247   /* Now make our own defaults in case the vars that we think are
248      important are missing. */
249   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
250   set_auto_export (temp_var);
251
252   temp_var = set_if_not ("TERM", "dumb");
253   set_auto_export (temp_var);
254
255 #if defined (qnx)
256   /* set node id -- don't import it from the environment */
257   {
258     char node_name[22];
259     qnx_nidtostr (getnid (), node_name, sizeof (node_name));
260     temp_var = bind_variable ("NODE", node_name);
261     set_auto_export (temp_var);
262   }
263 #endif
264
265   /* set up the prompts. */
266   if (interactive_shell)
267     {
268       set_if_not ("PS1", primary_prompt);
269       set_if_not ("PS2", secondary_prompt);
270     }
271   set_if_not ("PS4", "+ ");
272
273   /* Don't allow IFS to be imported from the environment. */
274   temp_var = bind_variable ("IFS", " \t\n");
275
276   /* Magic machine types.  Pretty convenient. */
277   temp_var = bind_variable ("HOSTTYPE", HOSTTYPE);
278   set_auto_export (temp_var);
279   temp_var = bind_variable ("OSTYPE", OSTYPE);
280   set_auto_export (temp_var);
281   temp_var = bind_variable ("MACHTYPE", MACHTYPE);
282   set_auto_export (temp_var);
283   temp_var = bind_variable ("HOSTNAME", current_host_name);
284   set_auto_export (temp_var);
285
286   /* Default MAILCHECK for interactive shells.  Defer the creation of a
287      default MAILPATH until the startup files are read, because MAIL
288      names a mail file if MAILCHECK is not set, and we should provide a
289      default only if neither is set. */
290   if (interactive_shell)
291     set_if_not ("MAILCHECK", "60");
292
293   /* Do some things with shell level. */
294   initialize_shell_level ();
295
296   /* Make a variable $PPID, which holds the pid of the shell's parent.  */
297   name = itos ((int) getppid ());
298   temp_var = find_variable ("PPID");
299   if (temp_var)
300     temp_var->attributes &= ~(att_readonly | att_exported);
301   temp_var = bind_variable ("PPID", name);
302   temp_var->attributes |= (att_readonly | att_integer);
303   free (name);
304
305   /* Initialize the `getopts' stuff. */
306   bind_variable ("OPTIND", "1");
307   getopts_reset (0);
308   bind_variable ("OPTERR", "1");
309   sh_opterr = 1;
310
311   if (login_shell == 1)
312     set_home_var ();
313
314   /* Get the full pathname to THIS shell, and set the BASH variable
315      to it. */
316   name = get_bash_name ();
317   temp_var = bind_variable ("BASH", name);
318   free (name);
319
320   /* Make the exported environment variable SHELL be the user's login
321      shell.  Note that the `tset' command looks at this variable
322      to determine what style of commands to output; if it ends in "csh",
323      then C-shell commands are output, else Bourne shell commands. */
324   set_shell_var ();
325
326   /* Make a variable called BASH_VERSION which contains the version info. */
327   bind_variable ("BASH_VERSION", shell_version_string ());
328 #if defined (ARRAY_VARS)
329   make_vers_array ();
330 #endif
331
332   /* Find out if we're supposed to be in Posix.2 mode via an
333      environment variable. */
334   temp_var = find_variable ("POSIXLY_CORRECT");
335   if (!temp_var)
336     temp_var = find_variable ("POSIX_PEDANTIC");
337   if (temp_var && imported_p (temp_var))
338     sv_strict_posix (temp_var->name);
339
340 #if defined (HISTORY)
341   /* Set history variables to defaults, and then do whatever we would
342      do if the variable had just been set.  Do this only in the case
343      that we are remembering commands on the history list. */
344   if (remember_on_history)
345     {
346       name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history");
347
348       set_if_not ("HISTFILE", name);
349       free (name);
350
351       set_if_not ("HISTSIZE", "500");
352       sv_histsize ("HISTSIZE");
353     }
354 #endif /* HISTORY */
355
356   /* Seed the random number generator. */
357   sbrand (dollar_dollar_pid + (long)shell_start_time);
358
359   /* Handle some "special" variables that we may have inherited from a
360      parent shell. */
361   if (interactive_shell)
362     {
363       temp_var = find_variable ("IGNOREEOF");
364       if (!temp_var)
365         temp_var = find_variable ("ignoreeof");
366       if (temp_var && imported_p (temp_var))
367         sv_ignoreeof (temp_var->name);
368     }
369
370 #if defined (HISTORY)
371   if (interactive_shell && remember_on_history)
372     {
373       sv_history_control ("HISTCONTROL");
374       sv_histignore ("HISTIGNORE");
375     }
376 #endif /* HISTORY */
377
378   /* Get the user's real and effective user ids. */
379   uidset ();
380
381   /* Initialize the dynamic variables, and seed their values. */
382   initialize_dynamic_variables ();
383 }
384
385 /* Set $HOME to the information in the password file if we didn't get
386    it from the environment. */
387 static void
388 set_home_var ()
389 {
390   SHELL_VAR *temp_var;
391
392   temp_var = find_variable ("HOME");
393   if (temp_var == 0)
394     {
395       if (current_user.home_dir == 0)
396         get_current_user_info ();
397       temp_var = bind_variable ("HOME", current_user.home_dir);
398     }
399   temp_var->attributes |= att_exported;
400 }
401
402 /* Set $SHELL to the user's login shell if it is not already set.  Call
403    get_current_user_info if we haven't already fetched the shell. */
404 static void
405 set_shell_var ()
406 {
407   SHELL_VAR *temp_var;
408
409   temp_var = find_variable ("SHELL");
410   if (temp_var == 0)
411     {
412       if (current_user.shell == 0)
413         get_current_user_info ();
414       temp_var = bind_variable ("SHELL", current_user.shell);
415     }
416   temp_var->attributes |= att_exported;
417 }
418
419 static char *
420 get_bash_name ()
421 {
422   char *name;
423
424   if ((login_shell == 1) && (*shell_name != '/'))
425     {
426       if (current_user.shell == 0)
427         get_current_user_info ();
428       name = savestring (current_user.shell);
429     }
430   else if (*shell_name == '/')
431     name = savestring (shell_name);
432   else if (shell_name[0] == '.' && shell_name[1] == '/')
433     {
434       /* Fast path for common case. */
435       char *cdir;
436       int len;
437
438       cdir = get_string_value ("PWD");
439       len = strlen (cdir);
440       name = xmalloc (len + strlen (shell_name) + 1);
441       strcpy (name, cdir);
442       strcpy (name + len, shell_name + 1);
443     }
444   else
445     {
446       char *tname;
447       int s;
448
449       tname = find_user_command (shell_name);
450
451       if (tname == 0)
452         {
453           /* Try the current directory.  If there is not an executable
454              there, just punt and use the login shell. */
455           s = file_status (shell_name);
456           if (s & FS_EXECABLE)
457             {
458               tname = make_absolute (shell_name, get_string_value ("PWD"));
459               if (*shell_name == '.')
460                 {
461                   name = canonicalize_pathname (tname);
462                   if (name == 0)
463                     name = tname;
464                   else
465                     free (tname);
466                 }
467              else
468                 name = tname;
469             }
470           else
471             {
472               if (current_user.shell == 0)
473                 get_current_user_info ();
474               name = savestring (current_user.shell);
475             }
476         }
477       else
478         {
479           name = full_pathname (tname);
480           free (tname);
481         }
482     }
483
484   return (name);
485 }
486
487 void
488 adjust_shell_level (change)
489      int change;
490 {
491   char new_level[5], *old_SHLVL;
492   int old_level;
493   SHELL_VAR *temp_var;
494
495   old_SHLVL = get_string_value ("SHLVL");
496   old_level = old_SHLVL ? atoi (old_SHLVL) : 0;
497
498   shell_level = old_level + change;
499   if (shell_level < 0)
500     shell_level = 0;
501   else if (shell_level > 1000)
502     {
503       internal_error ("warning: shell level (%d) too high, resetting to 1", shell_level);
504       shell_level = 1;
505     }
506
507   /* We don't need the full generality of itos here. */
508   if (shell_level < 10)
509     {
510       new_level[0] = shell_level + '0';
511       new_level[1] = '\0';
512     }
513   else if (shell_level < 100)
514     {
515       new_level[0] = (shell_level / 10) + '0';
516       new_level[1] = (shell_level % 10) + '0';
517       new_level[2] = '\0';
518     }
519   else if (shell_level < 1000)
520     {
521       new_level[0] = (shell_level / 100) + '0';
522       old_level = shell_level % 100;
523       new_level[1] = (old_level / 10) + '0';
524       new_level[2] = (old_level % 10) + '0';
525       new_level[3] = '\0';
526     }
527
528   temp_var = bind_variable ("SHLVL", new_level);
529   set_auto_export (temp_var);
530 }
531
532 static void
533 initialize_shell_level ()
534 {
535 #if 0
536   SHELL_VAR *temp_var;
537
538   temp_var = set_if_not ("SHLVL", "0");
539   set_auto_export (temp_var);
540 #endif
541   adjust_shell_level (1);
542 }
543
544 static void
545 uidset ()
546 {
547   char *buff;
548   register SHELL_VAR *v;
549
550   buff = itos (current_user.uid);
551   v = find_variable ("UID");
552   if (v)
553     v->attributes &= ~att_readonly;
554
555   v = bind_variable ("UID", buff);
556   v->attributes |= (att_readonly | att_integer);
557
558   if (current_user.euid != current_user.uid)
559     {
560       free (buff);
561       buff = itos (current_user.euid);
562     }
563
564   v = find_variable ("EUID");
565   if (v)
566     v->attributes &= ~att_readonly;
567
568   v = bind_variable ("EUID", buff);
569   v->attributes |= (att_readonly | att_integer);
570   free (buff);
571 }
572
573 #if defined (ARRAY_VARS)
574 static void
575 make_vers_array ()
576 {
577   SHELL_VAR *vv;
578   ARRAY *av;
579   char *s, d[16];
580
581   makunbound ("BASH_VERSINFO", shell_variables);
582
583   vv = make_new_array_variable ("BASH_VERSINFO");
584   av = array_cell (vv);
585   strcpy (d, dist_version);
586   s = strchr (d, '.');
587   if (s)
588     *s++ = '\0';
589   array_add_element (av, 0, d);
590   array_add_element (av, 1, s);
591   s = itos (patch_level);
592   array_add_element (av, 2, s);
593   free (s);
594   s = itos (build_version);
595   array_add_element (av, 3, s);
596   free (s);
597   array_add_element (av, 4, release_status);
598   array_add_element (av, 5, MACHTYPE);
599
600   vv->attributes |= att_readonly;
601 }
602 #endif /* ARRAY_VARS */
603
604 /* Set the environment variables $LINES and $COLUMNS in response to
605    a window size change. */
606 void
607 set_lines_and_columns (lines, cols)
608      int lines, cols;
609 {
610   char *val;
611
612   val = itos (lines);
613   bind_variable ("LINES", val);
614   free (val);
615
616   val = itos (cols);
617   bind_variable ("COLUMNS", val);
618   free (val);
619 }
620
621 /* Set NAME to VALUE if NAME has no value. */
622 SHELL_VAR *
623 set_if_not (name, value)
624      char *name, *value;
625 {
626   SHELL_VAR *v;
627
628   v = find_variable (name);
629   if (!v)
630     v = bind_variable (name, value);
631   return (v);
632 }
633
634 /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
635    variables for which FUNCTION returns a non-zero value.  A NULL value
636    for FUNCTION means to use all variables. */
637 SHELL_VAR **
638 map_over (function, var_hash_table)
639      Function *function;
640      HASH_TABLE* var_hash_table;
641 {
642   register int i;
643   register BUCKET_CONTENTS *tlist;
644   SHELL_VAR *var, **list;
645   int list_index, list_size;
646
647   list = (SHELL_VAR **)NULL;
648   for (i = list_index = list_size = 0; i < var_hash_table->nbuckets; i++)
649     {
650       tlist = get_hash_bucket (i, var_hash_table);
651
652       while (tlist)
653         {
654           var = (SHELL_VAR *)tlist->data;
655
656           if (!function || (*function) (var))
657             {
658               if (list_index + 1 >= list_size)
659                 list = (SHELL_VAR **)
660                   xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
661
662               list[list_index++] = var;
663               list[list_index] = (SHELL_VAR *)NULL;
664             }
665           tlist = tlist->next;
666         }
667     }
668   return (list);
669 }
670
671 void
672 sort_variables (array)
673      SHELL_VAR **array;
674 {
675   qsort (array, array_len ((char **)array), sizeof (SHELL_VAR *), qsort_var_comp);
676 }
677
678 static int
679 qsort_var_comp (var1, var2)
680      SHELL_VAR **var1, **var2;
681 {
682   int result;
683
684   if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
685     result = strcmp ((*var1)->name, (*var2)->name);
686
687   return (result);
688 }
689
690 /* Create a NULL terminated array of all the shell variables in TABLE. */
691 static SHELL_VAR **
692 all_vars (table)
693      HASH_TABLE *table;
694 {
695   SHELL_VAR **list;
696
697   list = map_over ((Function *)NULL, table);
698   if (list /* && posixly_correct */)
699     sort_variables (list);
700   return (list);
701 }
702
703 /* Create a NULL terminated array of all the shell variables. */
704 SHELL_VAR **
705 all_shell_variables ()
706 {
707   return (all_vars (shell_variables));
708 }
709
710 /* Create a NULL terminated array of all the shell functions. */
711 SHELL_VAR **
712 all_shell_functions ()
713 {
714   return (all_vars (shell_functions));
715 }
716
717 /* Print VARS to stdout in such a way that they can be read back in. */
718 void
719 print_var_list (list)
720      register SHELL_VAR **list;
721 {
722   register int i;
723   register SHELL_VAR *var;
724
725   for (i = 0; list && (var = list[i]); i++)
726     if (!invisible_p (var))
727       print_assignment (var);
728 }
729
730 #if defined (NOTDEF)
731 /* Print LIST (a linked list of shell variables) to stdout
732    by printing the names, without the values.  Used to support the
733    `set +' command. */
734 void
735 print_vars_no_values (list)
736      register SHELL_VAR **list;
737 {
738   register int i;
739   register SHELL_VAR *var;
740
741   for (i = 0; list && (var = list[i]); i++)
742     if (!invisible_p (var))
743       printf ("%s\n", var->name);
744 }
745 #endif
746
747 /* Print the value of a single SHELL_VAR.  No newline is
748    output, but the variable is printed in such a way that
749    it can be read back in. */
750 void
751 print_assignment (var)
752      SHELL_VAR *var;
753 {
754   if (function_p (var) && var->value)
755     {
756       printf ("%s=", var->name);
757       print_var_function (var);
758       printf ("\n");
759     }
760 #if defined (ARRAY_VARS)
761   else if (array_p (var) && var->value)
762     print_array_assignment (var, 0);
763 #endif /* ARRAY_VARS */
764   else if (var->value)
765     {
766       printf ("%s=", var->name);
767       print_var_value (var, 1);
768       printf ("\n");
769     }
770 }
771
772 /* Print the value cell of VAR, a shell variable.  Do not print
773    the name, nor leading/trailing newline.  If QUOTE is non-zero,
774    and the value contains shell metacharacters, quote the value
775    in such a way that it can be read back in. */
776 void
777 print_var_value (var, quote)
778      SHELL_VAR *var;
779      int quote;
780 {
781   char *t;
782
783   if (var->value)
784     {
785       if (quote && contains_shell_metas (var->value))
786         {
787           t = single_quote (var->value);
788           printf ("%s", t);
789           free (t);
790         }
791       else
792         printf ("%s", var->value);
793     }
794 }
795
796 /* Print the function cell of VAR, a shell variable.  Do not
797    print the name, nor leading/trailing newline. */
798 void
799 print_var_function (var)
800      SHELL_VAR *var;
801 {
802   if (function_p (var) && var->value)
803     printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
804 }
805
806 #if defined (ARRAY_VARS)
807 void
808 print_array_assignment (var, quoted)
809      SHELL_VAR *var;
810      int quoted;
811 {
812   char *vstr;
813
814   if (quoted)
815     vstr = quoted_array_assignment_string (array_cell (var));
816   else
817     vstr = array_to_assignment_string (array_cell (var));
818
819   if (vstr == 0)
820     printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
821   else
822     {
823       printf ("%s=%s\n", var->name, vstr);
824       free (vstr);
825     }
826 }
827 #endif /* ARRAY_VARS */
828
829 /* **************************************************************** */
830 /*                                                                  */
831 /*               Dynamic Variable Extension                         */
832 /*                                                                  */
833 /* **************************************************************** */
834
835 /* DYNAMIC VARIABLES
836
837    These are variables whose values are generated anew each time they are
838    referenced.  These are implemented using a pair of function pointers
839    in the struct variable: assign_func, which is called from bind_variable,
840    and dynamic_value, which is called from find_variable.
841
842    assign_func is called from bind_variable, if bind_variable discovers
843    that the variable being assigned to has such a function.  The function
844    is called as
845         SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
846    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
847    is usually ENTRY (self).
848
849    dynamic_value is called from find_variable to return a `new' value for
850    the specified dynamic varible.  If this function is NULL, the variable
851    is treated as a `normal' shell variable.  If it is not, however, then
852    this function is called like this:
853         tempvar = (*(var->dynamic_value)) (var);
854
855    Sometimes `tempvar' will replace the value of `var'.  Other times, the
856    shell will simply use the string value.  Pretty object-oriented, huh?
857
858    Be warned, though: if you `unset' a special variable, it loses its
859    special meaning, even if you subsequently set it.
860
861    The special assignment code would probably have been better put in
862    subst.c: do_assignment, in the same style as
863    stupidly_hack_special_variables, but I wanted the changes as
864    localized as possible.  */
865
866 /* The value of $SECONDS.  This is the number of seconds since shell
867    invocation, or, the number of seconds since the last assignment + the
868    value of the last assignment. */
869 static long seconds_value_assigned;
870
871 static SHELL_VAR *
872 assign_seconds (self, value)
873      SHELL_VAR *self;
874      char *value;
875 {
876   seconds_value_assigned = string_to_long (value);
877   shell_start_time = NOW;
878   return (self);
879 }
880
881 static SHELL_VAR *
882 get_seconds (var)
883      SHELL_VAR *var;
884 {
885   time_t time_since_start;
886   char *p;
887
888   time_since_start = NOW - shell_start_time;
889   p = itos((int) seconds_value_assigned + time_since_start);
890
891   FREE (var->value);
892
893   var->attributes |= att_integer;
894   var->value = p;
895   return (var);
896 }
897
898 /* The random number seed.  You can change this by setting RANDOM. */
899 static unsigned long rseed = 1;
900 static unsigned long last_random_value;
901
902 /* A linear congruential random number generator based on the ANSI
903    C standard.  A more complicated one is overkill.  */
904
905 /* Returns a pseudo-random number between 0 and 32767. */
906 static int
907 brand ()
908 {
909   rseed = rseed * 1103515245 + 12345;
910 #if 0
911   return ((unsigned int)(rseed / 65536) % 32768);
912 #else
913   return ((unsigned int)(rseed % 32768));
914 #endif
915 }
916
917 /* Set the random number generator seed to SEED. */
918 static void
919 sbrand (seed)
920      int seed;
921 {
922   rseed = seed;
923   last_random_value = 0;
924 }
925
926 static SHELL_VAR *
927 assign_random (self, value)
928      SHELL_VAR *self;
929      char *value;
930 {
931   sbrand (atoi (value));
932   return (self);
933 }
934
935 static SHELL_VAR *
936 get_random (var)
937      SHELL_VAR *var;
938 {
939   int rv;
940   char *p;
941
942   /* Reset for command and process substitution. */
943   if (subshell_environment)
944     sbrand (rseed + (int)(getpid() + NOW));
945
946   do
947     rv = brand ();
948   while (rv == (int)last_random_value);
949
950   last_random_value = rv;
951   p = itos ((int)rv);
952
953   FREE (var->value);
954
955   var->attributes |= att_integer;
956   var->value = p;
957   return (var);
958 }
959
960 /* Function which returns the current line number. */
961 static SHELL_VAR *
962 get_lineno (var)
963      SHELL_VAR *var;
964 {
965   char *p;
966   int ln;
967
968   ln = executing_line_number ();
969   p = itos (ln);
970   FREE (var->value);
971   var->value = p;
972   return (var);
973 }
974
975 static SHELL_VAR *
976 assign_lineno (var, value)
977      SHELL_VAR *var;
978      char *value;
979 {
980   line_number = atoi (value);
981   return var;
982 }
983
984 #if defined (HISTORY)
985 static SHELL_VAR *
986 get_histcmd (var)
987      SHELL_VAR *var;
988 {
989   char *p;
990
991   p = itos (history_number ());
992   FREE (var->value);
993   var->value = p;
994   return (var);
995 }
996 #endif
997
998 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
999 static SHELL_VAR *
1000 get_dirstack (self)
1001      SHELL_VAR *self;
1002 {
1003   ARRAY *a;
1004   WORD_LIST *l;
1005
1006   l = get_directory_stack ();
1007   a = word_list_to_array (l);
1008   dispose_array (array_cell (self));
1009   dispose_words (l);
1010   self->value = (char *)a;
1011   return self;
1012 }
1013
1014 static  SHELL_VAR *
1015 assign_dirstack (self, ind, value)
1016      SHELL_VAR *self;
1017      int ind;
1018      char *value;
1019 {
1020   set_dirstack_element (ind, 1, value);
1021   return self;
1022 }
1023 #endif /* PUSHD AND POPD && ARRAY_VARS */
1024
1025 #if defined (ARRAY_VARS)
1026 /* We don't want to initialize the group set with a call to getgroups()
1027    unless we're asked to, but we only want to do it once. */
1028 static SHELL_VAR *
1029 get_groupset (self)
1030      SHELL_VAR *self;
1031 {
1032   register int i;
1033   int ng;
1034   ARRAY *a;
1035   static char **group_set = (char **)NULL;
1036
1037   if (group_set == 0)
1038     {
1039       group_set = get_group_list (&ng);
1040       a = array_cell (self);
1041       for (i = 0; i < ng; i++)
1042         array_add_element (a, i, group_set[i]);
1043     }
1044   return (self);
1045 }
1046 #endif /* ARRAY_VARS */
1047   
1048 static void
1049 initialize_dynamic_variables ()
1050 {
1051   SHELL_VAR *v;
1052
1053   v = bind_variable ("SECONDS", (char *)NULL);
1054   v->dynamic_value = get_seconds;
1055   v->assign_func = assign_seconds;
1056
1057   v = bind_variable ("RANDOM", (char *)NULL);
1058   v->dynamic_value = get_random;
1059   v->assign_func = assign_random;
1060
1061   v = bind_variable ("LINENO", (char *)NULL);
1062   v->dynamic_value = get_lineno;
1063   v->assign_func = assign_lineno;
1064
1065 #if defined (HISTORY)
1066   v = bind_variable ("HISTCMD", (char *)NULL);
1067   v->dynamic_value = get_histcmd;
1068   v->assign_func = (DYNAMIC_FUNC *)NULL;
1069 #endif
1070
1071 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1072   v = make_new_array_variable ("DIRSTACK");
1073   v->dynamic_value = get_dirstack;
1074   v->assign_func = assign_dirstack;
1075 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1076
1077 #if defined (ARRAY_VARS)
1078   v = make_new_array_variable ("GROUPS");
1079   v->dynamic_value = get_groupset;
1080   v->assign_func = (DYNAMIC_FUNC *)NULL;
1081   v->attributes |= att_readonly;
1082 #endif
1083 }
1084
1085 /* How to get a pointer to the shell variable or function named NAME.
1086    HASHED_VARS is a pointer to the hash table containing the list
1087    of interest (either variables or functions). */
1088 SHELL_VAR *
1089 var_lookup (name, hashed_vars)
1090      char *name;
1091      HASH_TABLE *hashed_vars;
1092 {
1093   BUCKET_CONTENTS *bucket;
1094
1095   bucket = find_hash_item (name, hashed_vars);
1096   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1097 }
1098
1099 /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
1100    then also search the temporarily built list of exported variables. */
1101 SHELL_VAR *
1102 find_variable_internal (name, search_tempenv)
1103      char *name;
1104      int search_tempenv;
1105 {
1106   SHELL_VAR *var = (SHELL_VAR *)NULL;
1107
1108   /* If explicitly requested, first look in the temporary environment for
1109      the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
1110      to get the `exported' value of $foo.  This happens if we are executing
1111      a function or builtin, or if we are looking up a variable in a
1112      "subshell environment". */
1113   if ((search_tempenv || subshell_environment) &&
1114       (temporary_env || builtin_env || function_env))
1115     var = find_tempenv_variable (name);
1116
1117   if (!var)
1118     var = var_lookup (name, shell_variables);
1119
1120   if (!var)
1121     return ((SHELL_VAR *)NULL);
1122
1123   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1124 }
1125
1126 /* Look up the variable entry named NAME.  Returns the entry or NULL. */
1127 SHELL_VAR *
1128 find_variable (name)
1129      char *name;
1130 {
1131   return (find_variable_internal
1132           (name, (variable_context || this_shell_builtin || builtin_env)));
1133 }
1134
1135 /* Look up the function entry whose name matches STRING.
1136    Returns the entry or NULL. */
1137 SHELL_VAR *
1138 find_function (name)
1139      char *name;
1140 {
1141   return (var_lookup (name, shell_functions));
1142 }
1143
1144 /* Return the string value of a variable.  Return NULL if the variable
1145    doesn't exist, or only has a function as a value.  Don't cons a new
1146    string. */
1147 char *
1148 get_string_value (var_name)
1149      char *var_name;
1150 {
1151   SHELL_VAR *var;
1152
1153   var = find_variable (var_name);
1154
1155   if (!var)
1156     return (char *)NULL;
1157 #if defined (ARRAY_VARS)
1158   else if (array_p (var))
1159     return (array_reference (array_cell (var), 0));
1160 #endif
1161   else
1162     return (var->value);
1163 }
1164
1165 /* Create a local variable referenced by NAME. */
1166 SHELL_VAR *
1167 make_local_variable (name)
1168      char *name;
1169 {
1170   SHELL_VAR *new_var, *old_var;
1171   BUCKET_CONTENTS *elt;
1172
1173   /* local foo; local foo;  is a no-op. */
1174   old_var = find_variable (name);
1175   if (old_var && old_var->context == variable_context)
1176     return (old_var);
1177
1178   elt = remove_hash_item (name, shell_variables);
1179   if (elt)
1180     {
1181       old_var = (SHELL_VAR *)elt->data;
1182       free (elt->key);
1183       free (elt);
1184     }
1185   else
1186     old_var = (SHELL_VAR *)NULL;
1187
1188   /* If a variable does not already exist with this name, then
1189      just make a new one. */
1190   if (old_var == 0)
1191     new_var = bind_variable (name, "");
1192   else
1193     {
1194       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1195
1196       new_var->name = savestring (name);
1197       new_var->value = xmalloc (1);
1198       new_var->value[0] = '\0';
1199
1200       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
1201       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
1202
1203       new_var->attributes = exported_p (old_var) ? att_exported : 0;
1204
1205       new_var->prev_context = old_var;
1206       elt = add_hash_item (savestring (name), shell_variables);
1207       elt->data = (char *)new_var;
1208     }
1209
1210   new_var->context = variable_context;
1211   new_var->attributes |= att_local;
1212
1213   /* XXX */
1214   if (variable_context >= local_variable_stack_size)
1215     {
1216       int old_size = local_variable_stack_size;
1217       RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
1218                               local_variable_stack_size, 8);
1219       bzero ((char *)have_local_variables + old_size,
1220              local_variable_stack_size - old_size);
1221     }
1222   have_local_variables[variable_context] = 1;           /* XXX */
1223
1224   return (new_var);
1225 }
1226
1227 #if defined (ARRAY_VARS)
1228 SHELL_VAR *
1229 make_local_array_variable (name)
1230      char *name;
1231 {
1232   SHELL_VAR *var;
1233   ARRAY *array;
1234
1235   var = make_local_variable (name);
1236   array = new_array ();
1237
1238   FREE (value_cell(var));
1239   var->value = (char *)array;
1240   var->attributes |= att_array;
1241   return var;
1242 }
1243 #endif /* ARRAY_VARS */
1244
1245 /* Create a new shell variable with name NAME and add it to the hash table
1246    of shell variables. */
1247 static
1248 SHELL_VAR *
1249 make_new_variable (name)
1250      char *name;
1251 {
1252   SHELL_VAR *entry;
1253   BUCKET_CONTENTS *elt;
1254
1255   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1256
1257   entry->attributes = 0;
1258   entry->name = savestring (name);
1259   entry->value = (char *)NULL;
1260
1261   entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
1262   entry->assign_func = (DYNAMIC_FUNC *)NULL;
1263
1264   /* Always assume variables are to be made at toplevel!
1265      make_local_variable has the responsibilty of changing the
1266      variable context. */
1267   entry->context = 0;
1268   entry->prev_context = (SHELL_VAR *)NULL;
1269
1270   elt = add_hash_item (savestring (name), shell_variables);
1271   elt->data = (char *)entry;
1272
1273   return entry;
1274 }
1275
1276 #if defined (ARRAY_VARS)
1277 SHELL_VAR *
1278 make_new_array_variable (name)
1279      char *name;
1280 {
1281   SHELL_VAR *entry;
1282   ARRAY *array;
1283
1284   entry = make_new_variable (name);
1285   array = new_array ();
1286   entry->value = (char *)array;
1287   entry->attributes |= att_array;
1288   return entry;
1289 }
1290 #endif
1291
1292 char *
1293 make_variable_value (var, value)
1294      SHELL_VAR *var;
1295      char *value;
1296 {
1297   char *retval;
1298   long lval;
1299   int expok;
1300
1301   /* If this variable has had its type set to integer (via `declare -i'),
1302      then do expression evaluation on it and store the result.  The
1303      functions in expr.c (evalexp and bind_int_variable) are responsible
1304      for turning off the integer flag if they don't want further
1305      evaluation done. */
1306   if (integer_p (var))
1307     {
1308       lval = evalexp (value, &expok);
1309       if (expok == 0)
1310         jump_to_top_level (DISCARD);
1311       retval = itos (lval);
1312     }
1313   else if (value)
1314     {
1315       if (*value)
1316         retval = savestring (value);
1317       else
1318         {
1319           retval = xmalloc (1);
1320           retval[0] = '\0';
1321         }
1322     }
1323   else
1324     retval = (char *)NULL;
1325
1326   return retval;
1327 }
1328
1329 /* Bind a variable NAME to VALUE.  This conses up the name
1330    and value strings. */
1331 SHELL_VAR *
1332 bind_variable (name, value)
1333      char *name, *value;
1334 {
1335   char *newval;
1336   SHELL_VAR *entry;
1337
1338   entry = var_lookup (name, shell_variables);
1339
1340   if (entry == 0)
1341     {
1342       entry = make_new_variable (name);
1343       entry->value = make_variable_value (entry, value);
1344     }
1345 #if defined (ARRAY_VARS)
1346   else if (entry->assign_func && array_p (entry) == 0)
1347 #else
1348   else if (entry->assign_func)
1349 #endif
1350     return ((*(entry->assign_func)) (entry, value));
1351   else
1352     {
1353       if (readonly_p (entry))
1354         {
1355           report_error ("%s: readonly variable", name);
1356           return (entry);
1357         }
1358
1359       /* Variables which are bound are visible. */
1360       entry->attributes &= ~att_invisible;
1361
1362       newval = make_variable_value (entry, value);
1363
1364 #if defined (ARRAY_VARS)
1365       /* XXX -- this bears looking at again -- XXX */
1366       /* If an existing array variable x is being assigned to with x=b or
1367          `read x' or something of that nature, silently convert it to
1368          x[0]=b or `read x[0]'. */
1369       if (array_p (entry))
1370         {
1371           array_add_element (array_cell (entry), 0, newval);
1372           free (newval);
1373         }
1374       else
1375         {
1376           FREE (entry->value);
1377           entry->value = newval;
1378         }
1379 #else
1380       FREE (entry->value);
1381       entry->value = newval;
1382 #endif
1383     }
1384
1385   if (mark_modified_vars)
1386     entry->attributes |= att_exported;
1387
1388   if (exported_p (entry))
1389     array_needs_making = 1;
1390
1391   return (entry);
1392 }
1393
1394 #if defined (ARRAY_VARS)
1395 /* Convert a shell variable to an array variable.  The original value is
1396    saved as array[0]. */
1397 SHELL_VAR *
1398 convert_var_to_array (var)
1399      SHELL_VAR *var;
1400 {
1401   char *oldval;
1402   ARRAY *array;
1403
1404   oldval = value_cell (var);
1405   array = new_array ();
1406   array_add_element (array, 0, oldval);
1407   FREE (value_cell (var));
1408   var->value = (char *)array;
1409   var->attributes |= att_array;
1410   var->attributes &= ~att_invisible;
1411
1412   return var;
1413 }
1414
1415 /* Perform an array assignment name[ind]=value.  If NAME already exists and
1416    is not an array, and IND is 0, perform name=value instead.  If NAME exists
1417    and is not an array, and IND is not 0, convert it into an array with the
1418    existing value as name[0].
1419
1420    If NAME does not exist, just create an array variable, no matter what
1421    IND's value may be. */
1422 SHELL_VAR *
1423 bind_array_variable (name, ind, value)
1424      char *name;
1425      int ind;
1426      char *value;
1427 {
1428   SHELL_VAR *entry;
1429   char *newval;
1430
1431   entry = var_lookup (name, shell_variables);
1432
1433   if (entry == (SHELL_VAR *) 0)
1434     entry = make_new_array_variable (name);
1435   else if (readonly_p (entry))
1436     {
1437       report_error ("%s: readonly variable", name);
1438       return (entry);
1439     }
1440   else if (array_p (entry) == 0)
1441     entry = convert_var_to_array (entry);
1442
1443   /* ENTRY is an array variable, and ARRAY points to the value. */
1444   newval = make_variable_value (entry, value);
1445   if (entry->assign_func)
1446     (*entry->assign_func) (entry, ind, newval);
1447   else
1448     array_add_element (array_cell (entry), ind, newval);
1449   FREE (newval);
1450
1451   return (entry);
1452 }
1453
1454 SHELL_VAR *
1455 assign_array_from_string (name, value)
1456      char *name, *value;
1457 {
1458   SHELL_VAR *var;
1459
1460   var = find_variable (name);
1461   if (var == 0)
1462     var = make_new_array_variable (name);
1463   else if (readonly_p (var))
1464     {
1465       report_error ("%s: readonly variable", name);
1466       return ((SHELL_VAR *)NULL);
1467     }
1468   else if (array_p (var) == 0)
1469     var = convert_var_to_array (var);
1470 #if 0
1471   else
1472     empty_array (array_cell (var));
1473 #endif
1474
1475   return (assign_array_var_from_string (var, value));
1476 }
1477
1478 SHELL_VAR *
1479 assign_array_var_from_word_list (var, list)
1480      SHELL_VAR *var;
1481      WORD_LIST *list;
1482 {
1483   register int i;
1484   register WORD_LIST *l;
1485   ARRAY *a;
1486
1487   for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
1488     if (var->assign_func)
1489       (*var->assign_func) (var, i, l->word->word);
1490     else
1491       array_add_element (a, i, l->word->word);
1492   return var;
1493 }
1494
1495 SHELL_VAR *
1496 assign_array_var_from_string (var, value)
1497      SHELL_VAR *var;
1498      char *value;
1499 {
1500   ARRAY *a;
1501   WORD_LIST *list, *nlist;
1502   char *w, *val, *nval;
1503   int ni, len, ind, last_ind;
1504
1505   a = array_cell (var);
1506
1507   /* Expand the value string into a list of words, performing all the
1508      shell expansions including word splitting. */
1509   if (*value == '(')
1510     {
1511       ni = 1;
1512       val = extract_array_assignment_list (value, &ni);
1513       if (val == 0)
1514         return var;
1515       nlist = expand_string (val, 0);
1516       free (val);
1517     }
1518   else
1519     nlist = expand_string (value, 0);
1520
1521 #if 1
1522   /* Now that we are ready to assign values to the array, kill the existing
1523      value. */
1524   if (a)
1525     empty_array (a);
1526 #endif
1527
1528   for (last_ind = 0, list = nlist; list; list = list->next)
1529     {
1530       w = list->word->word;
1531
1532       /* We have a word of the form [ind]=value */
1533       if (w[0] == '[')
1534         {
1535           len = skipsubscript (w, 0);
1536
1537           if (w[len] != ']' || w[len+1] != '=')
1538             {
1539               nval = make_variable_value (var, w);
1540               if (var->assign_func)
1541                 (*var->assign_func) (var, last_ind, nval);
1542               else
1543                 array_add_element (a, last_ind, nval);
1544               FREE (nval);
1545               last_ind++;
1546               continue;
1547             }
1548
1549           if (len == 1)
1550             {
1551               report_error ("%s: bad array subscript", w);
1552               continue;
1553             }
1554
1555           if (ALL_ELEMENT_SUB (w[1]) && len == 2)
1556             {
1557               report_error ("%s: cannot assign to non-numeric index", w);
1558               continue;
1559             }
1560
1561           ind = array_expand_index (w + 1, len);
1562           if (ind < 0)
1563             {
1564               report_error ("%s: bad array subscript", w);
1565               continue;
1566             }
1567           last_ind = ind;
1568           val = w + len + 2;
1569         }
1570       else              /* No [ind]=value, just a stray `=' */
1571         {
1572           ind = last_ind;
1573           val = w;
1574         }
1575
1576       if (integer_p (var))
1577         this_command_name = (char *)NULL;       /* no command name for errors */
1578       nval = make_variable_value (var, val);
1579       if (var->assign_func)
1580         (*var->assign_func) (var, ind, nval);
1581       else
1582         array_add_element (a, ind, nval);
1583       FREE (nval);
1584       last_ind++;
1585     }
1586
1587   dispose_words (nlist);
1588   return (var);
1589 }
1590 #endif /* ARRAY_VARS */
1591
1592 /* Dispose of the information attached to VAR. */
1593 void
1594 dispose_variable (var)
1595      SHELL_VAR *var;
1596 {
1597   if (!var)
1598     return;
1599
1600   if (function_p (var))
1601     dispose_command (function_cell (var));
1602 #if defined (ARRAY_VARS)
1603   else if (array_p (var))
1604     dispose_array (array_cell (var));
1605 #endif
1606   else
1607     FREE (value_cell (var));
1608
1609   free (var->name);
1610
1611   if (exported_p (var))
1612     array_needs_making = 1;
1613
1614   free (var);
1615 }
1616
1617 #if defined (ARRAY_VARS)
1618 /* This function is called with SUB pointing to just after the beginning
1619    `[' of an array subscript. */
1620 int
1621 unbind_array_element (var, sub)
1622      SHELL_VAR *var;
1623      char *sub;
1624 {
1625   int len, ind;
1626   ARRAY_ELEMENT *ae;
1627
1628   len = skipsubscript (sub, 0);
1629   if (sub[len] != ']' || len == 0)
1630     {
1631       builtin_error ("%s[%s: bad array subscript", var->name, sub);
1632       return -1;
1633     }
1634   sub[len] = '\0';
1635
1636   if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
1637     {
1638       makunbound (var->name, shell_variables);
1639       return (0);
1640     }
1641   ind = array_expand_index (sub, len+1);
1642   if (ind < 0)
1643     {
1644       builtin_error ("[%s]: bad array subscript", sub);
1645       return -1;
1646     }
1647   ae = array_delete_element (array_cell (var), ind);
1648   if (ae)
1649     destroy_array_element (ae);
1650   return 0;
1651 }
1652 #endif
1653
1654 /* Unset the variable referenced by NAME. */
1655 int
1656 unbind_variable (name)
1657      char *name;
1658 {
1659   SHELL_VAR *var = find_variable (name);
1660
1661   if (!var)
1662     return (-1);
1663
1664   /* This function should never be called with an array variable name. */
1665 #if defined (ARRAY_VARS)
1666   if (array_p (var) == 0 && var->value)
1667 #else
1668   if (var->value)
1669 #endif
1670     {
1671       free (var->value);
1672       var->value = (char *)NULL;
1673     }
1674
1675   makunbound (name, shell_variables);
1676
1677   return (0);
1678 }
1679
1680 /* Make the variable associated with NAME go away.  HASH_LIST is the
1681    hash table from which this variable should be deleted (either
1682    shell_variables or shell_functions).
1683    Returns non-zero if the variable couldn't be found. */
1684 int
1685 makunbound (name, hash_list)
1686      char *name;
1687      HASH_TABLE *hash_list;
1688 {
1689   BUCKET_CONTENTS *elt, *new_elt;
1690   SHELL_VAR *old_var, *new_var;
1691   char *t;
1692
1693   elt = remove_hash_item (name, hash_list);
1694
1695   if (elt == 0)
1696     return (-1);
1697
1698   old_var = (SHELL_VAR *)elt->data;
1699   new_var = old_var->prev_context;
1700
1701   if (old_var && exported_p (old_var))
1702     array_needs_making++;
1703
1704   /* If we're unsetting a local variable and we're still executing inside
1705      the function, just mark the variable as invisible.
1706      kill_all_local_variables will clean it up later.  This must be done
1707      so that if the variable is subsequently assigned a new value inside
1708      the function, the `local' attribute is still present.  We also need
1709      to add it back into the correct hash table. */
1710   if (old_var && local_p (old_var) && variable_context == old_var->context)
1711     {
1712       old_var->attributes |= att_invisible;
1713       new_elt = add_hash_item (savestring (old_var->name), hash_list);
1714       new_elt->data = (char *)old_var;
1715       stupidly_hack_special_variables (old_var->name);
1716       free (elt->key);
1717       free (elt);
1718       return (0);
1719     }
1720
1721   if (new_var)
1722     {
1723       /* Has to be a variable, functions don't have previous contexts. */
1724       new_elt = add_hash_item (savestring (new_var->name), hash_list);
1725       new_elt->data = (char *)new_var;
1726
1727       if (exported_p (new_var))
1728         set_auto_export (new_var);
1729     }
1730
1731   /* Have to save a copy of name here, because it might refer to
1732      old_var->name.  If so, stupidly_hack_special_variables will
1733      reference freed memory. */
1734   t = savestring (name);
1735
1736   free (elt->key);
1737   free (elt);
1738
1739   dispose_variable (old_var);
1740   stupidly_hack_special_variables (t);
1741   free (t);
1742   return (0);
1743 }
1744
1745 #ifdef INCLUDE_UNUSED
1746 /* Remove the variable with NAME if it is a local variable in the
1747    current context. */
1748 int
1749 kill_local_variable (name)
1750      char *name;
1751 {
1752   SHELL_VAR *temp;
1753
1754   temp = find_variable (name);
1755   if (temp && temp->context == variable_context)
1756     {
1757       makunbound (name, shell_variables);
1758       return (0);
1759     }
1760   return (-1);
1761 }
1762 #endif
1763
1764 /* Get rid of all of the variables in the current context. */
1765 int
1766 variable_in_context (var)
1767      SHELL_VAR *var;
1768 {
1769   return (var && var->context == variable_context);
1770 }
1771
1772 void
1773 kill_all_local_variables ()
1774 {
1775   register int i, pass;
1776   register SHELL_VAR *var, **list;
1777   HASH_TABLE *varlist;
1778
1779   /* If HAVE_LOCAL_VARIABLES == 0, it means that we don't have any local
1780      variables at all.  If VARIABLE_CONTEXT >= LOCAL_VARIABLE_STACK_SIZE,
1781      it means that we have some local variables, but not in this variable
1782      context (level of function nesting).  Also, if
1783      HAVE_LOCAL_VARIABLES[VARIABLE_CONTEXT] == 0, we have no local variables
1784      at this context. */
1785   if (have_local_variables == 0 ||
1786       variable_context >= local_variable_stack_size ||
1787       have_local_variables[variable_context] == 0)
1788     return;
1789
1790   for (pass = 0; pass < 2; pass++)
1791     {
1792       varlist = pass ? shell_functions : shell_variables;
1793
1794       list = map_over (variable_in_context, varlist);
1795
1796       if (list)
1797         {
1798           for (i = 0; var = list[i]; i++)
1799             {
1800               var->attributes &= ~att_local;
1801               makunbound (var->name, varlist);
1802             }
1803           free (list);
1804         }
1805     }
1806
1807   have_local_variables[variable_context] = 0;           /* XXX */
1808 }
1809
1810 static void
1811 free_variable_hash_data (data)
1812      char *data;
1813 {
1814   SHELL_VAR *var, *prev;
1815
1816   var = (SHELL_VAR *)data;
1817   while (var)
1818     {
1819       prev = var->prev_context;
1820       dispose_variable (var);
1821       var = prev;
1822     }
1823 }
1824
1825 /* Delete the entire contents of the hash table. */
1826 void
1827 delete_all_variables (hashed_vars)
1828      HASH_TABLE *hashed_vars;
1829 {
1830   flush_hash_table (hashed_vars, free_variable_hash_data);
1831 }
1832
1833 static SHELL_VAR *
1834 new_shell_variable (name)
1835      char *name;
1836 {
1837   SHELL_VAR *var;
1838
1839   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1840
1841   bzero ((char *)var, sizeof (SHELL_VAR));
1842   var->name = savestring (name);
1843   return (var);
1844 }
1845
1846 /* Do a function binding to a variable.  You pass the name and
1847    the command to bind to.  This conses the name and command. */
1848 SHELL_VAR *
1849 bind_function (name, value)
1850      char *name;
1851      COMMAND *value;
1852 {
1853   SHELL_VAR *entry;
1854
1855   entry = find_function (name);
1856   if (!entry)
1857     {
1858       BUCKET_CONTENTS *elt;
1859
1860       elt = add_hash_item (savestring (name), shell_functions);
1861
1862       elt->data = (char *)new_shell_variable (name);
1863       entry = (SHELL_VAR *)elt->data;
1864       entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
1865
1866       /* Functions are always made at the top level.  This allows a
1867          function to define another function (like autoload). */
1868       entry->context = 0;
1869     }
1870
1871   if (entry->value)
1872     dispose_command ((COMMAND *)entry->value);
1873
1874   entry->value = value ? (char *)copy_command (value) : (char *)NULL;
1875   entry->attributes |= att_function;
1876
1877   if (mark_modified_vars)
1878     entry->attributes |= att_exported;
1879
1880   entry->attributes &= ~att_invisible;  /* Just to be sure */
1881
1882   if (exported_p (entry))
1883     array_needs_making = 1;
1884
1885   return (entry);
1886 }
1887
1888 #ifdef INCLUDE_UNUSED
1889 /* Copy VAR to a new data structure and return that structure. */
1890 SHELL_VAR *
1891 copy_variable (var)
1892      SHELL_VAR *var;
1893 {
1894   SHELL_VAR *copy = (SHELL_VAR *)NULL;
1895
1896   if (var)
1897     {
1898       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1899
1900       copy->attributes = var->attributes;
1901       copy->name = savestring (var->name);
1902
1903       if (function_p (var))
1904         copy->value = (char *)copy_command (function_cell (var));
1905 #if defined (ARRAY_VARS)
1906       else if (array_p (var))
1907         copy->value = (char *)dup_array (array_cell (var));
1908 #endif
1909       else if (value_cell (var))
1910         copy->value = savestring (value_cell (var));
1911       else
1912         copy->value = (char *)NULL;
1913
1914       copy->dynamic_value = var->dynamic_value;
1915       copy->assign_func = var->assign_func;
1916
1917       copy->context = var->context;
1918
1919       /* Don't bother copying previous contexts along with this variable. */
1920       copy->prev_context = (SHELL_VAR *)NULL;
1921     }
1922   return (copy);
1923 }
1924 #endif
1925
1926 #define FIND_OR_MAKE_VARIABLE(name, entry) \
1927   do \
1928     { \
1929       entry = find_variable (name); \
1930       if (!entry) \
1931         { \
1932           entry = bind_variable (name, ""); \
1933           if (!no_invisible_vars) entry->attributes |= att_invisible; \
1934         } \
1935     } \
1936   while (0)
1937
1938 /* Make the variable associated with NAME be readonly.
1939    If NAME does not exist yet, create it. */
1940 void
1941 set_var_read_only (name)
1942      char *name;
1943 {
1944   SHELL_VAR *entry;
1945
1946   FIND_OR_MAKE_VARIABLE (name, entry);
1947   entry->attributes |= att_readonly;
1948 }
1949
1950 /* Make the function associated with NAME be readonly.
1951    If NAME does not exist, we just punt, like auto_export code below. */
1952 void
1953 set_func_read_only (name)
1954      char *name;
1955 {
1956   SHELL_VAR *entry;
1957
1958   entry = find_function (name);
1959   if (entry)
1960     entry->attributes |= att_readonly;
1961 }
1962
1963 /* Make the variable associated with NAME be auto-exported.
1964    If NAME does not exist yet, create it. */
1965 void
1966 set_var_auto_export (name)
1967      char *name;
1968 {
1969   SHELL_VAR *entry;
1970
1971   FIND_OR_MAKE_VARIABLE (name, entry);
1972   set_auto_export (entry);
1973 }
1974
1975 /* Make the function associated with NAME be auto-exported. */
1976 void
1977 set_func_auto_export (name)
1978      char *name;
1979 {
1980   SHELL_VAR *entry;
1981
1982   entry = find_function (name);
1983   if (entry)
1984     set_auto_export (entry);
1985 }
1986
1987 #if defined (ARRAY_VARS)
1988 /* This function assumes s[i] == '['; returns with s[ret] == ']' if
1989    an array subscript is correctly parsed. */
1990 int
1991 skipsubscript (s, i)
1992      char *s;
1993      int i;
1994 {
1995   int count, c;
1996
1997   for (count = 1; count && (c = s[++i]); )
1998     {
1999       if (c == '[')
2000         count++;
2001       else if (c == ']')
2002         count--;
2003     }
2004   return i;
2005 }
2006 #endif /* ARRAY_VARS */
2007
2008 /* Returns non-zero if STRING is an assignment statement.  The returned value
2009    is the index of the `=' sign. */
2010 int
2011 assignment (string)
2012      char *string;
2013 {
2014   register int c, newi, indx;
2015
2016   c = string[indx = 0];
2017
2018   if (legal_variable_starter (c) == 0)
2019     return (0);
2020
2021   while (c = string[indx])
2022     {
2023       /* The following is safe.  Note that '=' at the start of a word
2024          is not an assignment statement. */
2025       if (c == '=')
2026         return (indx);
2027
2028 #if defined (ARRAY_VARS)
2029       if (c == '[')
2030         {
2031           newi = skipsubscript (string, indx);
2032           if (string[newi++] != ']')
2033             return (0);
2034           return ((string[newi] == '=') ? newi : 0);
2035         }
2036 #endif /* ARRAY_VARS */
2037
2038       /* Variable names in assignment statements may contain only letters,
2039          digits, and `_'. */
2040       if (legal_variable_char (c) == 0)
2041         return (0);
2042
2043       indx++;
2044     }
2045   return (0);
2046 }
2047
2048 static int
2049 visible_var (var)
2050      SHELL_VAR *var;
2051 {
2052   return (invisible_p (var) == 0);
2053 }
2054
2055 static SHELL_VAR **
2056 _visible_names (table)
2057      HASH_TABLE *table;
2058 {
2059   SHELL_VAR **list;
2060
2061   list = map_over (visible_var, table);
2062
2063   if (list /* && posixly_correct */)
2064     sort_variables (list);
2065
2066   return (list);
2067 }
2068
2069 SHELL_VAR **
2070 all_visible_variables ()
2071 {
2072   return (_visible_names (shell_variables));
2073 }
2074
2075 SHELL_VAR **
2076 all_visible_functions ()
2077 {
2078   return (_visible_names (shell_functions));
2079 }
2080
2081 /* Return non-zero if the variable VAR is visible and exported.  Array
2082    variables cannot be exported. */
2083 static int
2084 visible_and_exported (var)
2085      SHELL_VAR *var;
2086 {
2087   return (invisible_p (var) == 0 && exported_p (var));
2088 }
2089
2090 /* Make an array of assignment statements from the hash table
2091    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
2092    variables are eligible. */
2093 char **
2094 make_var_array (hashed_vars)
2095      HASH_TABLE *hashed_vars;
2096 {
2097   register int i, list_index;
2098   register SHELL_VAR *var;
2099   char **list, *value;
2100   SHELL_VAR **vars;
2101
2102   vars = map_over (visible_and_exported, hashed_vars);
2103
2104   if (vars == 0)
2105     return (char **)NULL;
2106
2107   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
2108
2109   for (i = 0, list_index = 0; var = vars[i]; i++)
2110     {
2111       if (function_p (var))
2112         value = named_function_string ((char *)NULL, function_cell (var), 0);
2113 #if defined (ARRAY_VARS)
2114       else if (array_p (var))
2115 #  if 0
2116         value = array_to_assignment_string (array_cell (var));
2117 #  else
2118         continue;       /* XXX array vars cannot yet be exported */
2119 #  endif
2120 #endif
2121       else
2122         value = value_cell (var);
2123
2124       if (value)
2125         {
2126           int name_len, value_len;
2127           char  *p;
2128
2129           name_len = strlen (var->name);
2130           value_len = strlen (value);
2131           p = list[list_index] = xmalloc (2 + name_len + value_len);
2132           strcpy (p, var->name);
2133           p[name_len] = '=';
2134           strcpy (p + name_len + 1, value);
2135           list_index++;
2136 #if defined (ARRAY_VARS)
2137           if (array_p (var))
2138             free (value);
2139 #endif
2140         }
2141     }
2142
2143   free (vars);
2144   list[list_index] = (char *)NULL;
2145   return (list);
2146 }
2147
2148 /* Add STRING to the array of foo=bar strings that we already
2149    have to add to the environment.  */
2150 int
2151 assign_in_env (string)
2152      char *string;
2153 {
2154   int size, offset;
2155   char *name, *temp, *value;
2156   int nlen, vlen;
2157   WORD_LIST *list;
2158   SHELL_VAR *var;
2159
2160   offset = assignment (string);
2161   name = savestring (string);
2162   value = (char *)NULL;
2163
2164 #define freetemp nlen
2165   if (name[offset] == '=')
2166     {
2167       name[offset] = 0;
2168
2169       var = find_variable (name);
2170       if (var && readonly_p (var))
2171         {
2172           report_error ("%s: readonly variable", name);
2173           free (name);
2174           return (0);
2175         }
2176       temp = name + offset + 1;
2177       freetemp = strchr (temp, '~') != 0;
2178       if (freetemp)
2179         temp = bash_tilde_expand (temp);
2180
2181       list = expand_string_unsplit (temp, 0);
2182       value = string_list (list);
2183
2184       if (list)
2185         dispose_words (list);
2186
2187       if (freetemp)
2188         free (temp);
2189     }
2190 #undef freetemp
2191
2192   nlen = strlen (name);
2193   vlen = value ? strlen (value) : 0;
2194   temp = xmalloc (2 + nlen + vlen);
2195   strcpy (temp, name);
2196   temp[nlen] = '=';
2197   temp[nlen + 1] = '\0';
2198   if (value)
2199     {
2200       if (*value)
2201         strcpy (temp + nlen + 1, value);
2202       free (value);
2203     }
2204   free (name);
2205
2206   if (temporary_env == 0)
2207     {
2208       temporary_env = (char **)xmalloc (sizeof (char *));
2209       temporary_env [0] = (char *)NULL;
2210     }
2211
2212   size = array_len (temporary_env);
2213   temporary_env = (char **)
2214     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
2215
2216   temporary_env[size] = temp;
2217   temporary_env[size + 1] = (char *)NULL;
2218   array_needs_making = 1;
2219
2220   if (echo_command_at_execute)
2221     {
2222       /* The Korn shell prints the `+ ' in front of assignment statements,
2223          so we do too. */
2224       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
2225       fflush (stderr);
2226     }
2227
2228   return 1;
2229 }
2230
2231 /* Search for NAME in ARRAY, an array of strings in the same format as the
2232    environment array (i.e, name=value).  If NAME is present, make a new
2233    variable and return it.  Otherwise, return NULL. */
2234 static SHELL_VAR *
2235 find_name_in_env_array (name, array)
2236      char *name;
2237      char **array;
2238 {
2239   register int i, l;
2240
2241   if (array == 0)
2242     return ((SHELL_VAR *)NULL);
2243
2244   for (i = 0, l = strlen (name); array[i]; i++)
2245     {
2246       if (STREQN (array[i], name, l) && array[i][l] == '=')
2247         {
2248           SHELL_VAR *temp;
2249           char *w;
2250
2251           temp = new_shell_variable (name);     /* XXX memory leak here */
2252           w = array[i] + l + 1;
2253
2254           temp->value = *w ? savestring (w) : (char *)NULL;
2255
2256           temp->attributes = att_exported;
2257           temp->context = 0;
2258           temp->prev_context = (SHELL_VAR *)NULL;
2259
2260           temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
2261
2262           return (temp);
2263         }
2264     }
2265   return ((SHELL_VAR *)NULL);
2266 }
2267
2268 /* Find a variable in the temporary environment that is named NAME.
2269    The temporary environment can be either the environment provided
2270    to a simple command, or the environment provided to a shell function.
2271    We only search the function environment if we are currently executing
2272    a shell function body (variable_context > 0).  Return a consed variable,
2273    or NULL if not found. */
2274 SHELL_VAR *
2275 find_tempenv_variable (name)
2276      char *name;
2277 {
2278   SHELL_VAR *var = (SHELL_VAR *)NULL;
2279
2280   if (temporary_env)
2281     var = find_name_in_env_array (name, temporary_env);
2282
2283   /* We don't check this_shell_builtin because the command that needs the
2284      value from builtin_env may be a disk command run inside a script run
2285      with `.' and a temporary env. */
2286   if (!var && builtin_env)
2287     var = find_name_in_env_array (name, builtin_env);
2288
2289   if (!var && variable_context && function_env)
2290     var = find_name_in_env_array (name, function_env);
2291
2292   return (var);
2293 }
2294
2295 /* Free the storage allocated to the string array pointed to by ARRAYP, and
2296    make that variable have a null pointer as a value. */
2297 static void
2298 dispose_temporary_vars (arrayp)
2299      char ***arrayp;
2300 {
2301   if (!*arrayp)
2302     return;
2303
2304   free_array (*arrayp);
2305   *arrayp = (char **)NULL;
2306   array_needs_making = 1;
2307 }
2308
2309 /* Free the storage used in the variable array for temporary
2310    environment variables. */
2311 void
2312 dispose_used_env_vars ()
2313 {
2314   dispose_temporary_vars (&temporary_env);
2315 }
2316
2317 /* Free the storage used for temporary environment variables given to
2318    commands when executing inside of a function body. */
2319 void
2320 dispose_function_env ()
2321 {
2322   dispose_temporary_vars (&function_env);
2323 }
2324
2325 /* Free the storage used for temporary environment variables given to
2326    commands when executing a builtin command such as "source". */
2327 void
2328 dispose_builtin_env ()
2329 {
2330   dispose_temporary_vars (&builtin_env);
2331 }
2332
2333 /* Take all of the shell variables in ENV_ARRAY and make shell variables
2334    from them at the current variable context. */
2335 static void
2336 merge_env_array (env_array)
2337      char **env_array;
2338 {
2339   register int i, l;
2340   SHELL_VAR *temp;
2341   char *val, *name;
2342
2343   if (env_array == 0)
2344     return;
2345
2346   for (i = 0; env_array[i]; i++)
2347     {
2348       l = assignment (env_array[i]);
2349       name = env_array[i];
2350       val = env_array[i] + l + 1;
2351       name[l] = '\0';
2352       temp = bind_variable (name, val);
2353       name[l] = '=';
2354     }
2355 }
2356
2357 void
2358 merge_temporary_env ()
2359 {
2360   merge_env_array (temporary_env);
2361 }
2362
2363 void
2364 merge_builtin_env ()
2365 {
2366   merge_env_array (builtin_env);
2367 }
2368
2369 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
2370 #define add_to_export_env(envstr,do_alloc) \
2371 do \
2372   { \
2373     if (export_env_index >= (export_env_size - 1)) \
2374       { \
2375         export_env_size += 16; \
2376         export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *)); \
2377       } \
2378     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
2379     export_env[export_env_index] = (char *)NULL; \
2380   } while (0)
2381
2382 #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
2383
2384 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
2385    array with the same left-hand side.  Return the new EXPORT_ENV. */
2386 char **
2387 add_or_supercede_exported_var (assign, do_alloc)
2388      char *assign;
2389      int do_alloc;
2390 {
2391   register int i;
2392   int equal_offset;
2393
2394   equal_offset = assignment (assign);
2395   if (equal_offset == 0)
2396     return (export_env);
2397
2398   /* If this is a function, then only supercede the function definition.
2399      We do this by including the `=(' in the comparison.  */
2400   if (assign[equal_offset + 1] == '(')
2401     equal_offset++;
2402
2403   for (i = 0; i < export_env_index; i++)
2404     {
2405       if (STREQN (assign, export_env[i], equal_offset + 1))
2406         {
2407           free (export_env[i]);
2408           export_env[i] = do_alloc ? savestring (assign) : assign;
2409           return (export_env);
2410         }
2411     }
2412   add_to_export_env (assign, do_alloc);
2413   return (export_env);
2414 }
2415
2416 /* Make the environment array for the command about to be executed, if the
2417    array needs making.  Otherwise, do nothing.  If a shell action could
2418    change the array that commands receive for their environment, then the
2419    code should `array_needs_making++'. */
2420 void
2421 maybe_make_export_env ()
2422 {
2423   register int i;
2424   register char **temp_array;
2425   int new_size;
2426
2427   if (array_needs_making)
2428     {
2429       if (export_env)
2430         free_array_members (export_env);
2431
2432       /* Make a guess based on how many shell variables and functions we
2433          have.  Since there will always be array variables, and array
2434          variables are not (yet) exported, this will always be big enough
2435          for the exported variables and functions, without any temporary
2436          or function environments. */
2437       new_size = shell_variables->nentries + shell_functions->nentries + 1;
2438       if (new_size > export_env_size)
2439         {
2440           export_env_size = new_size;
2441           export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
2442         }
2443       export_env[export_env_index = 0] = (char *)NULL;
2444
2445       temp_array = make_var_array (shell_variables);
2446       if (temp_array)
2447         {
2448           for (i = 0; temp_array[i]; i++)
2449             add_to_export_env (temp_array[i], 0);
2450           free (temp_array);
2451         }
2452
2453       temp_array = make_var_array (shell_functions);
2454       if (temp_array)
2455         {
2456           for (i = 0; temp_array[i]; i++)
2457             add_to_export_env (temp_array[i], 0);
2458           free (temp_array);
2459         }
2460
2461       if (function_env)
2462         for (i = 0; function_env[i]; i++)
2463           export_env = add_or_supercede_exported_var (function_env[i], 1);
2464
2465       if (temporary_env)
2466         for (i = 0; temporary_env[i]; i++)
2467           export_env = add_or_supercede_exported_var (temporary_env[i], 1);
2468
2469 #if 0
2470       /* If we changed the array, then sort it alphabetically. */
2471       if (posixly_correct == 0 && (temporary_env || function_env))
2472         sort_char_array (export_env);
2473 #endif
2474
2475       array_needs_making = 0;
2476     }
2477 }
2478
2479 /* We always put _ in the environment as the name of this command. */
2480 void
2481 put_command_name_into_env (command_name)
2482      char *command_name;
2483 {
2484   char *dummy;
2485
2486   dummy = xmalloc (4 + strlen (command_name));
2487
2488   /* These three statements replace a call to sprintf */
2489   dummy[0] = '_';
2490   dummy[1] = '=';
2491   strcpy (dummy + 2, command_name);
2492   export_env = add_or_supercede_exported_var (dummy, 0);
2493 }
2494
2495 void
2496 put_gnu_argv_flags_into_env (pid, flags_string)
2497      int pid;
2498      char *flags_string;
2499 {
2500   char *dummy, *pbuf;
2501   int l, fl;
2502
2503   pbuf = itos (pid);
2504   l = strlen (pbuf);
2505
2506   fl = strlen (flags_string);
2507
2508   dummy = xmalloc (l + fl + 30);
2509   dummy[0] = '_';
2510   strcpy (dummy + 1, pbuf);
2511   strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
2512   dummy[l + 27] = '=';
2513   strcpy (dummy + l + 28, flags_string);
2514
2515   free (pbuf);
2516
2517   export_env = add_or_supercede_exported_var (dummy, 0);
2518 }
2519
2520 /* Return a string denoting what our indirection level is. */
2521 static char indirection_string[100];
2522
2523 char *
2524 indirection_level_string ()
2525 {
2526   register int i, j;
2527   char *ps4;
2528
2529   indirection_string[0] = '\0';
2530   ps4 = get_string_value ("PS4");
2531
2532   if (ps4 == 0 || *ps4 == '\0')
2533     return (indirection_string);
2534
2535   ps4 = decode_prompt_string (ps4);
2536
2537   for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
2538     indirection_string[i] = *ps4;
2539
2540   for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
2541     indirection_string[i] = ps4[j];
2542
2543   indirection_string[i] = '\0';
2544   free (ps4);
2545   return (indirection_string);
2546 }