Imported from ../bash-2.01.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   return ((unsigned int)(rseed / 65536) % 32768);
911 }
912
913 /* Set the random number generator seed to SEED. */
914 static void
915 sbrand (seed)
916      int seed;
917 {
918   rseed = seed;
919 }
920
921 static SHELL_VAR *
922 assign_random (self, value)
923      SHELL_VAR *self;
924      char *value;
925 {
926   sbrand (atoi (value));
927   return (self);
928 }
929
930 static SHELL_VAR *
931 get_random (var)
932      SHELL_VAR *var;
933 {
934   int rv;
935   char *p;
936
937   /* Reset for command and process substitution. */
938   if (subshell_environment)
939     sbrand ((int)(getpid() + NOW));
940
941   do
942     rv = brand ();
943   while (rv == (int)last_random_value);
944
945   last_random_value = rv;
946   p = itos ((int)rv);
947
948   FREE (var->value);
949
950   var->attributes |= att_integer;
951   var->value = p;
952   return (var);
953 }
954
955 /* Function which returns the current line number. */
956 static SHELL_VAR *
957 get_lineno (var)
958      SHELL_VAR *var;
959 {
960   char *p;
961   int ln;
962
963   ln = executing_line_number ();
964   p = itos (ln);
965   FREE (var->value);
966   var->value = p;
967   return (var);
968 }
969
970 static SHELL_VAR *
971 assign_lineno (var, value)
972      SHELL_VAR *var;
973      char *value;
974 {
975   line_number = atoi (value);
976   return var;
977 }
978
979 #if defined (HISTORY)
980 static SHELL_VAR *
981 get_histcmd (var)
982      SHELL_VAR *var;
983 {
984   char *p;
985
986   p = itos (history_number ());
987   FREE (var->value);
988   var->value = p;
989   return (var);
990 }
991 #endif
992
993 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
994 static SHELL_VAR *
995 get_dirstack (self)
996      SHELL_VAR *self;
997 {
998   ARRAY *a;
999   WORD_LIST *l;
1000
1001   l = get_directory_stack ();
1002   a = word_list_to_array (l);
1003   dispose_array (array_cell (self));
1004   dispose_words (l);
1005   self->value = (char *)a;
1006   return self;
1007 }
1008
1009 static  SHELL_VAR *
1010 assign_dirstack (self, ind, value)
1011      SHELL_VAR *self;
1012      int ind;
1013      char *value;
1014 {
1015   set_dirstack_element (ind, 1, value);
1016   return self;
1017 }
1018 #endif /* PUSHD AND POPD && ARRAY_VARS */
1019
1020 #if defined (ARRAY_VARS)
1021 /* We don't want to initialize the group set with a call to getgroups()
1022    unless we're asked to, but we only want to do it once. */
1023 static SHELL_VAR *
1024 get_groupset (self)
1025      SHELL_VAR *self;
1026 {
1027   register int i;
1028   int ng;
1029   ARRAY *a;
1030   static char **group_set = (char **)NULL;
1031
1032   if (group_set == 0)
1033     {
1034       group_set = get_group_list (&ng);
1035       a = array_cell (self);
1036       for (i = 0; i < ng; i++)
1037         array_add_element (a, i, group_set[i]);
1038     }
1039   return (self);
1040 }
1041 #endif /* ARRAY_VARS */
1042   
1043 static void
1044 initialize_dynamic_variables ()
1045 {
1046   SHELL_VAR *v;
1047
1048   v = bind_variable ("SECONDS", (char *)NULL);
1049   v->dynamic_value = get_seconds;
1050   v->assign_func = assign_seconds;
1051
1052   v = bind_variable ("RANDOM", (char *)NULL);
1053   v->dynamic_value = get_random;
1054   v->assign_func = assign_random;
1055
1056   v = bind_variable ("LINENO", (char *)NULL);
1057   v->dynamic_value = get_lineno;
1058   v->assign_func = assign_lineno;
1059
1060 #if defined (HISTORY)
1061   v = bind_variable ("HISTCMD", (char *)NULL);
1062   v->dynamic_value = get_histcmd;
1063   v->assign_func = (DYNAMIC_FUNC *)NULL;
1064 #endif
1065
1066 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1067   v = make_new_array_variable ("DIRSTACK");
1068   v->dynamic_value = get_dirstack;
1069   v->assign_func = assign_dirstack;
1070 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1071
1072 #if defined (ARRAY_VARS)
1073   v = make_new_array_variable ("GROUPS");
1074   v->dynamic_value = get_groupset;
1075   v->assign_func = (DYNAMIC_FUNC *)NULL;
1076   v->attributes |= att_readonly;
1077 #endif
1078 }
1079
1080 /* How to get a pointer to the shell variable or function named NAME.
1081    HASHED_VARS is a pointer to the hash table containing the list
1082    of interest (either variables or functions). */
1083 SHELL_VAR *
1084 var_lookup (name, hashed_vars)
1085      char *name;
1086      HASH_TABLE *hashed_vars;
1087 {
1088   BUCKET_CONTENTS *bucket;
1089
1090   bucket = find_hash_item (name, hashed_vars);
1091   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1092 }
1093
1094 /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
1095    then also search the temporarily built list of exported variables. */
1096 SHELL_VAR *
1097 find_variable_internal (name, search_tempenv)
1098      char *name;
1099      int search_tempenv;
1100 {
1101   SHELL_VAR *var = (SHELL_VAR *)NULL;
1102
1103   /* If explicitly requested, first look in the temporary environment for
1104      the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
1105      to get the `exported' value of $foo.  This happens if we are executing
1106      a function or builtin, or if we are looking up a variable in a
1107      "subshell environment". */
1108   if ((search_tempenv || subshell_environment) &&
1109       (temporary_env || builtin_env || function_env))
1110     var = find_tempenv_variable (name);
1111
1112   if (!var)
1113     var = var_lookup (name, shell_variables);
1114
1115   if (!var)
1116     return ((SHELL_VAR *)NULL);
1117
1118   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1119 }
1120
1121 /* Look up the variable entry named NAME.  Returns the entry or NULL. */
1122 SHELL_VAR *
1123 find_variable (name)
1124      char *name;
1125 {
1126   return (find_variable_internal
1127           (name, (variable_context || this_shell_builtin || builtin_env)));
1128 }
1129
1130 /* Look up the function entry whose name matches STRING.
1131    Returns the entry or NULL. */
1132 SHELL_VAR *
1133 find_function (name)
1134      char *name;
1135 {
1136   return (var_lookup (name, shell_functions));
1137 }
1138
1139 /* Return the string value of a variable.  Return NULL if the variable
1140    doesn't exist, or only has a function as a value.  Don't cons a new
1141    string. */
1142 char *
1143 get_string_value (var_name)
1144      char *var_name;
1145 {
1146   SHELL_VAR *var;
1147
1148   var = find_variable (var_name);
1149
1150   if (!var)
1151     return (char *)NULL;
1152 #if defined (ARRAY_VARS)
1153   else if (array_p (var))
1154     return (array_reference (array_cell (var), 0));
1155 #endif
1156   else
1157     return (var->value);
1158 }
1159
1160 /* Create a local variable referenced by NAME. */
1161 SHELL_VAR *
1162 make_local_variable (name)
1163      char *name;
1164 {
1165   SHELL_VAR *new_var, *old_var;
1166   BUCKET_CONTENTS *elt;
1167
1168   /* local foo; local foo;  is a no-op. */
1169   old_var = find_variable (name);
1170   if (old_var && old_var->context == variable_context)
1171     return (old_var);
1172
1173   elt = remove_hash_item (name, shell_variables);
1174   if (elt)
1175     {
1176       old_var = (SHELL_VAR *)elt->data;
1177       free (elt->key);
1178       free (elt);
1179     }
1180   else
1181     old_var = (SHELL_VAR *)NULL;
1182
1183   /* If a variable does not already exist with this name, then
1184      just make a new one. */
1185   if (old_var == 0)
1186     new_var = bind_variable (name, "");
1187   else
1188     {
1189       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1190
1191       new_var->name = savestring (name);
1192       new_var->value = xmalloc (1);
1193       new_var->value[0] = '\0';
1194
1195       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
1196       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
1197
1198       new_var->attributes = exported_p (old_var) ? att_exported : 0;
1199
1200       new_var->prev_context = old_var;
1201       elt = add_hash_item (savestring (name), shell_variables);
1202       elt->data = (char *)new_var;
1203     }
1204
1205   new_var->context = variable_context;
1206   new_var->attributes |= att_local;
1207
1208   /* XXX */
1209   if (variable_context >= local_variable_stack_size)
1210     {
1211       int old_size = local_variable_stack_size;
1212       RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
1213                               local_variable_stack_size, 8);
1214       bzero ((char *)have_local_variables + old_size,
1215              local_variable_stack_size - old_size);
1216     }
1217   have_local_variables[variable_context] = 1;           /* XXX */
1218
1219   return (new_var);
1220 }
1221
1222 #if defined (ARRAY_VARS)
1223 SHELL_VAR *
1224 make_local_array_variable (name)
1225      char *name;
1226 {
1227   SHELL_VAR *var;
1228   ARRAY *array;
1229
1230   var = make_local_variable (name);
1231   array = new_array ();
1232
1233   FREE (value_cell(var));
1234   var->value = (char *)array;
1235   var->attributes |= att_array;
1236   return var;
1237 }
1238 #endif /* ARRAY_VARS */
1239
1240 /* Create a new shell variable with name NAME and add it to the hash table
1241    of shell variables. */
1242 static
1243 SHELL_VAR *
1244 make_new_variable (name)
1245      char *name;
1246 {
1247   SHELL_VAR *entry;
1248   BUCKET_CONTENTS *elt;
1249
1250   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1251
1252   entry->attributes = 0;
1253   entry->name = savestring (name);
1254   entry->value = (char *)NULL;
1255
1256   entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
1257   entry->assign_func = (DYNAMIC_FUNC *)NULL;
1258
1259   /* Always assume variables are to be made at toplevel!
1260      make_local_variable has the responsibilty of changing the
1261      variable context. */
1262   entry->context = 0;
1263   entry->prev_context = (SHELL_VAR *)NULL;
1264
1265   elt = add_hash_item (savestring (name), shell_variables);
1266   elt->data = (char *)entry;
1267
1268   return entry;
1269 }
1270
1271 #if defined (ARRAY_VARS)
1272 SHELL_VAR *
1273 make_new_array_variable (name)
1274      char *name;
1275 {
1276   SHELL_VAR *entry;
1277   ARRAY *array;
1278
1279   entry = make_new_variable (name);
1280   array = new_array ();
1281   entry->value = (char *)array;
1282   entry->attributes |= att_array;
1283   return entry;
1284 }
1285 #endif
1286
1287 char *
1288 make_variable_value (var, value)
1289      SHELL_VAR *var;
1290      char *value;
1291 {
1292   char *retval;
1293   long lval;
1294   int expok;
1295
1296   /* If this variable has had its type set to integer (via `declare -i'),
1297      then do expression evaluation on it and store the result.  The
1298      functions in expr.c (evalexp and bind_int_variable) are responsible
1299      for turning off the integer flag if they don't want further
1300      evaluation done. */
1301   if (integer_p (var))
1302     {
1303       lval = evalexp (value, &expok);
1304       if (expok == 0)
1305         jump_to_top_level (DISCARD);
1306       retval = itos (lval);
1307     }
1308   else if (value)
1309     {
1310       if (*value)
1311         retval = savestring (value);
1312       else
1313         {
1314           retval = xmalloc (1);
1315           retval[0] = '\0';
1316         }
1317     }
1318   else
1319     retval = (char *)NULL;
1320
1321   return retval;
1322 }
1323
1324 /* Bind a variable NAME to VALUE.  This conses up the name
1325    and value strings. */
1326 SHELL_VAR *
1327 bind_variable (name, value)
1328      char *name, *value;
1329 {
1330   char *newval;
1331   SHELL_VAR *entry;
1332
1333   entry = var_lookup (name, shell_variables);
1334
1335   if (entry == 0)
1336     {
1337       entry = make_new_variable (name);
1338       entry->value = make_variable_value (entry, value);
1339     }
1340 #if defined (ARRAY_VARS)
1341   else if (entry->assign_func && array_p (entry) == 0)
1342 #else
1343   else if (entry->assign_func)
1344 #endif
1345     return ((*(entry->assign_func)) (entry, value));
1346   else
1347     {
1348       if (readonly_p (entry))
1349         {
1350           report_error ("%s: readonly variable", name);
1351           return (entry);
1352         }
1353
1354       /* Variables which are bound are visible. */
1355       entry->attributes &= ~att_invisible;
1356
1357       newval = make_variable_value (entry, value);
1358
1359 #if defined (ARRAY_VARS)
1360       /* XXX -- this bears looking at again -- XXX */
1361       /* If an existing array variable x is being assigned to with x=b or
1362          `read x' or something of that nature, silently convert it to
1363          x[0]=b or `read x[0]'. */
1364       if (array_p (entry))
1365         {
1366           array_add_element (array_cell (entry), 0, newval);
1367           free (newval);
1368         }
1369       else
1370         {
1371           FREE (entry->value);
1372           entry->value = newval;
1373         }
1374 #else
1375       FREE (entry->value);
1376       entry->value = newval;
1377 #endif
1378     }
1379
1380   if (mark_modified_vars)
1381     entry->attributes |= att_exported;
1382
1383   if (exported_p (entry))
1384     array_needs_making = 1;
1385
1386   return (entry);
1387 }
1388
1389 #if defined (ARRAY_VARS)
1390 /* Convert a shell variable to an array variable.  The original value is
1391    saved as array[0]. */
1392 SHELL_VAR *
1393 convert_var_to_array (var)
1394      SHELL_VAR *var;
1395 {
1396   char *oldval;
1397   ARRAY *array;
1398
1399   oldval = value_cell (var);
1400   array = new_array ();
1401   array_add_element (array, 0, oldval);
1402   FREE (value_cell (var));
1403   var->value = (char *)array;
1404   var->attributes |= att_array;
1405   var->attributes &= ~att_invisible;
1406
1407   return var;
1408 }
1409
1410 /* Perform an array assignment name[ind]=value.  If NAME already exists and
1411    is not an array, and IND is 0, perform name=value instead.  If NAME exists
1412    and is not an array, and IND is not 0, convert it into an array with the
1413    existing value as name[0].
1414
1415    If NAME does not exist, just create an array variable, no matter what
1416    IND's value may be. */
1417 SHELL_VAR *
1418 bind_array_variable (name, ind, value)
1419      char *name;
1420      int ind;
1421      char *value;
1422 {
1423   SHELL_VAR *entry;
1424   char *newval;
1425
1426   entry = var_lookup (name, shell_variables);
1427
1428   if (entry == (SHELL_VAR *) 0)
1429     entry = make_new_array_variable (name);
1430   else if (readonly_p (entry))
1431     {
1432       report_error ("%s: readonly variable", name);
1433       return (entry);
1434     }
1435   else if (array_p (entry) == 0)
1436     entry = convert_var_to_array (entry);
1437
1438   /* ENTRY is an array variable, and ARRAY points to the value. */
1439   newval = make_variable_value (entry, value);
1440   if (entry->assign_func)
1441     (*entry->assign_func) (entry, ind, newval);
1442   else
1443     array_add_element (array_cell (entry), ind, newval);
1444   FREE (newval);
1445
1446   return (entry);
1447 }
1448
1449 SHELL_VAR *
1450 assign_array_from_string (name, value)
1451      char *name, *value;
1452 {
1453   SHELL_VAR *var;
1454
1455   var = find_variable (name);
1456   if (var == 0)
1457     var = make_new_array_variable (name);
1458   else if (readonly_p (var))
1459     {
1460       report_error ("%s: readonly variable", name);
1461       return ((SHELL_VAR *)NULL);
1462     }
1463   else if (array_p (var) == 0)
1464     var = convert_var_to_array (var);
1465
1466   return (assign_array_var_from_string (var, value));
1467 }
1468
1469 SHELL_VAR *
1470 assign_array_var_from_word_list (var, list)
1471      SHELL_VAR *var;
1472      WORD_LIST *list;
1473 {
1474   register int i;
1475   register WORD_LIST *l;
1476   ARRAY *a;
1477
1478   for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
1479     if (var->assign_func)
1480       (*var->assign_func) (var, i, l->word->word);
1481     else
1482       array_add_element (a, i, l->word->word);
1483   return var;
1484 }
1485
1486 SHELL_VAR *
1487 assign_array_var_from_string (var, value)
1488      SHELL_VAR *var;
1489      char *value;
1490 {
1491   ARRAY *a;
1492   WORD_LIST *list, *nlist;
1493   char *w, *val, *nval;
1494   int ni, len, ind, last_ind;
1495
1496   a = array_cell (var);
1497
1498   /* Expand the value string into a list of words, performing all the
1499      shell expansions including word splitting. */
1500   if (*value == '(')
1501     {
1502       ni = 1;
1503       val = extract_array_assignment_list (value, &ni);
1504       if (val == 0)
1505         return var;
1506       nlist = expand_string (val, 0);
1507       free (val);
1508     }
1509   else
1510     nlist = expand_string (value, 0);
1511
1512   for (last_ind = 0, list = nlist; list; list = list->next)
1513     {
1514       w = list->word->word;
1515
1516       /* We have a word of the form [ind]=value */
1517       if (w[0] == '[')
1518         {
1519           len = skipsubscript (w, 0);
1520
1521           if (w[len] != ']' || w[len+1] != '=')
1522             {
1523               nval = make_variable_value (var, w);
1524               if (var->assign_func)
1525                 (*var->assign_func) (var, last_ind, nval);
1526               else
1527                 array_add_element (a, last_ind, nval);
1528               FREE (nval);
1529               last_ind++;
1530               continue;
1531             }
1532
1533           if (len == 1)
1534             {
1535               report_error ("%s: bad array subscript", w);
1536               continue;
1537             }
1538
1539           if (ALL_ELEMENT_SUB (w[1]) && len == 2)
1540             {
1541               report_error ("%s: cannot assign to non-numeric index", w);
1542               continue;
1543             }
1544
1545           ind = array_expand_index (w + 1, len);
1546           if (ind < 0)
1547             {
1548               report_error ("%s: bad array subscript", w);
1549               continue;
1550             }
1551           last_ind = ind;
1552           val = w + len + 2;
1553         }
1554       else              /* No [ind]=value, just a stray `=' */
1555         {
1556           ind = last_ind;
1557           val = w;
1558         }
1559
1560       if (integer_p (var))
1561         this_command_name = (char *)NULL;       /* no command name for errors */
1562       nval = make_variable_value (var, val);
1563       if (var->assign_func)
1564         (*var->assign_func) (var, ind, nval);
1565       else
1566         array_add_element (a, ind, nval);
1567       FREE (nval);
1568       last_ind++;
1569     }
1570
1571   dispose_words (nlist);
1572   return (var);
1573 }
1574 #endif /* ARRAY_VARS */
1575
1576 /* Dispose of the information attached to VAR. */
1577 void
1578 dispose_variable (var)
1579      SHELL_VAR *var;
1580 {
1581   if (!var)
1582     return;
1583
1584   if (function_p (var))
1585     dispose_command (function_cell (var));
1586 #if defined (ARRAY_VARS)
1587   else if (array_p (var))
1588     dispose_array (array_cell (var));
1589 #endif
1590   else
1591     FREE (value_cell (var));
1592
1593   free (var->name);
1594
1595   if (exported_p (var))
1596     array_needs_making = 1;
1597
1598   free (var);
1599 }
1600
1601 #if defined (ARRAY_VARS)
1602 /* This function is called with SUB pointing to just after the beginning
1603    `[' of an array subscript. */
1604 int
1605 unbind_array_element (var, sub)
1606      SHELL_VAR *var;
1607      char *sub;
1608 {
1609   int len, ind;
1610   ARRAY_ELEMENT *ae;
1611
1612   len = skipsubscript (sub, 0);
1613   if (sub[len] != ']' || len == 0)
1614     {
1615       builtin_error ("%s[%s: bad array subscript", var->name, sub);
1616       return -1;
1617     }
1618   sub[len] = '\0';
1619
1620   if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
1621     {
1622       makunbound (var->name, shell_variables);
1623       return (0);
1624     }
1625   ind = array_expand_index (sub, len+1);
1626   if (ind < 0)
1627     {
1628       builtin_error ("[%s]: bad array subscript", sub);
1629       return -1;
1630     }
1631   ae = array_delete_element (array_cell (var), ind);
1632   if (ae)
1633     destroy_array_element (ae);
1634   return 0;
1635 }
1636 #endif
1637
1638 /* Unset the variable referenced by NAME. */
1639 int
1640 unbind_variable (name)
1641      char *name;
1642 {
1643   SHELL_VAR *var = find_variable (name);
1644
1645   if (!var)
1646     return (-1);
1647
1648   /* This function should never be called with an array variable name. */
1649 #if defined (ARRAY_VARS)
1650   if (array_p (var) == 0 && var->value)
1651 #else
1652   if (var->value)
1653 #endif
1654     {
1655       free (var->value);
1656       var->value = (char *)NULL;
1657     }
1658
1659   makunbound (name, shell_variables);
1660
1661   return (0);
1662 }
1663
1664 /* Make the variable associated with NAME go away.  HASH_LIST is the
1665    hash table from which this variable should be deleted (either
1666    shell_variables or shell_functions).
1667    Returns non-zero if the variable couldn't be found. */
1668 int
1669 makunbound (name, hash_list)
1670      char *name;
1671      HASH_TABLE *hash_list;
1672 {
1673   BUCKET_CONTENTS *elt, *new_elt;
1674   SHELL_VAR *old_var, *new_var;
1675   char *t;
1676
1677   elt = remove_hash_item (name, hash_list);
1678
1679   if (elt == 0)
1680     return (-1);
1681
1682   old_var = (SHELL_VAR *)elt->data;
1683   new_var = old_var->prev_context;
1684
1685   if (old_var && exported_p (old_var))
1686     array_needs_making++;
1687
1688   /* If we're unsetting a local variable and we're still executing inside
1689      the function, just mark the variable as invisible.
1690      kill_all_local_variables will clean it up later.  This must be done
1691      so that if the variable is subsequently assigned a new value inside
1692      the function, the `local' attribute is still present.  We also need
1693      to add it back into the correct hash table. */
1694   if (old_var && local_p (old_var) && variable_context == old_var->context)
1695     {
1696       old_var->attributes |= att_invisible;
1697       new_elt = add_hash_item (savestring (old_var->name), hash_list);
1698       new_elt->data = (char *)old_var;
1699       stupidly_hack_special_variables (old_var->name);
1700       free (elt->key);
1701       free (elt);
1702       return (0);
1703     }
1704
1705   if (new_var)
1706     {
1707       /* Has to be a variable, functions don't have previous contexts. */
1708       new_elt = add_hash_item (savestring (new_var->name), hash_list);
1709       new_elt->data = (char *)new_var;
1710
1711       if (exported_p (new_var))
1712         set_auto_export (new_var);
1713     }
1714
1715   /* Have to save a copy of name here, because it might refer to
1716      old_var->name.  If so, stupidly_hack_special_variables will
1717      reference freed memory. */
1718   t = savestring (name);
1719
1720   free (elt->key);
1721   free (elt);
1722
1723   dispose_variable (old_var);
1724   stupidly_hack_special_variables (t);
1725   free (t);
1726   return (0);
1727 }
1728
1729 #ifdef INCLUDE_UNUSED
1730 /* Remove the variable with NAME if it is a local variable in the
1731    current context. */
1732 int
1733 kill_local_variable (name)
1734      char *name;
1735 {
1736   SHELL_VAR *temp;
1737
1738   temp = find_variable (name);
1739   if (temp && temp->context == variable_context)
1740     {
1741       makunbound (name, shell_variables);
1742       return (0);
1743     }
1744   return (-1);
1745 }
1746 #endif
1747
1748 /* Get rid of all of the variables in the current context. */
1749 int
1750 variable_in_context (var)
1751      SHELL_VAR *var;
1752 {
1753   return (var && var->context == variable_context);
1754 }
1755
1756 void
1757 kill_all_local_variables ()
1758 {
1759   register int i, pass;
1760   register SHELL_VAR *var, **list;
1761   HASH_TABLE *varlist;
1762
1763   /* If HAVE_LOCAL_VARIABLES == 0, it means that we don't have any local
1764      variables at all.  If VARIABLE_CONTEXT >= LOCAL_VARIABLE_STACK_SIZE,
1765      it means that we have some local variables, but not in this variable
1766      context (level of function nesting).  Also, if
1767      HAVE_LOCAL_VARIABLES[VARIABLE_CONTEXT] == 0, we have no local variables
1768      at this context. */
1769   if (have_local_variables == 0 ||
1770       variable_context >= local_variable_stack_size ||
1771       have_local_variables[variable_context] == 0)
1772     return;
1773
1774   for (pass = 0; pass < 2; pass++)
1775     {
1776       varlist = pass ? shell_functions : shell_variables;
1777
1778       list = map_over (variable_in_context, varlist);
1779
1780       if (list)
1781         {
1782           for (i = 0; var = list[i]; i++)
1783             {
1784               var->attributes &= ~att_local;
1785               makunbound (var->name, varlist);
1786             }
1787           free (list);
1788         }
1789     }
1790
1791   have_local_variables[variable_context] = 0;           /* XXX */
1792 }
1793
1794 static void
1795 free_variable_hash_data (data)
1796      char *data;
1797 {
1798   SHELL_VAR *var, *prev;
1799
1800   var = (SHELL_VAR *)data;
1801   while (var)
1802     {
1803       prev = var->prev_context;
1804       dispose_variable (var);
1805       var = prev;
1806     }
1807 }
1808
1809 /* Delete the entire contents of the hash table. */
1810 void
1811 delete_all_variables (hashed_vars)
1812      HASH_TABLE *hashed_vars;
1813 {
1814   flush_hash_table (hashed_vars, free_variable_hash_data);
1815 }
1816
1817 static SHELL_VAR *
1818 new_shell_variable (name)
1819      char *name;
1820 {
1821   SHELL_VAR *var;
1822
1823   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1824
1825   bzero ((char *)var, sizeof (SHELL_VAR));
1826   var->name = savestring (name);
1827   return (var);
1828 }
1829
1830 /* Do a function binding to a variable.  You pass the name and
1831    the command to bind to.  This conses the name and command. */
1832 SHELL_VAR *
1833 bind_function (name, value)
1834      char *name;
1835      COMMAND *value;
1836 {
1837   SHELL_VAR *entry;
1838
1839   entry = find_function (name);
1840   if (!entry)
1841     {
1842       BUCKET_CONTENTS *elt;
1843
1844       elt = add_hash_item (savestring (name), shell_functions);
1845
1846       elt->data = (char *)new_shell_variable (name);
1847       entry = (SHELL_VAR *)elt->data;
1848       entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
1849
1850       /* Functions are always made at the top level.  This allows a
1851          function to define another function (like autoload). */
1852       entry->context = 0;
1853     }
1854
1855   if (entry->value)
1856     dispose_command ((COMMAND *)entry->value);
1857
1858   entry->value = value ? (char *)copy_command (value) : (char *)NULL;
1859   entry->attributes |= att_function;
1860
1861   if (mark_modified_vars)
1862     entry->attributes |= att_exported;
1863
1864   entry->attributes &= ~att_invisible;  /* Just to be sure */
1865
1866   if (exported_p (entry))
1867     array_needs_making = 1;
1868
1869   return (entry);
1870 }
1871
1872 #ifdef INCLUDE_UNUSED
1873 /* Copy VAR to a new data structure and return that structure. */
1874 SHELL_VAR *
1875 copy_variable (var)
1876      SHELL_VAR *var;
1877 {
1878   SHELL_VAR *copy = (SHELL_VAR *)NULL;
1879
1880   if (var)
1881     {
1882       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1883
1884       copy->attributes = var->attributes;
1885       copy->name = savestring (var->name);
1886
1887       if (function_p (var))
1888         copy->value = (char *)copy_command (function_cell (var));
1889 #if defined (ARRAY_VARS)
1890       else if (array_p (var))
1891         copy->value = (char *)dup_array (array_cell (var));
1892 #endif
1893       else if (value_cell (var))
1894         copy->value = savestring (value_cell (var));
1895       else
1896         copy->value = (char *)NULL;
1897
1898       copy->dynamic_value = var->dynamic_value;
1899       copy->assign_func = var->assign_func;
1900
1901       copy->context = var->context;
1902
1903       /* Don't bother copying previous contexts along with this variable. */
1904       copy->prev_context = (SHELL_VAR *)NULL;
1905     }
1906   return (copy);
1907 }
1908 #endif
1909
1910 #define FIND_OR_MAKE_VARIABLE(name, entry) \
1911   do \
1912     { \
1913       entry = find_variable (name); \
1914       if (!entry) \
1915         { \
1916           entry = bind_variable (name, ""); \
1917           if (!no_invisible_vars) entry->attributes |= att_invisible; \
1918         } \
1919     } \
1920   while (0)
1921
1922 /* Make the variable associated with NAME be readonly.
1923    If NAME does not exist yet, create it. */
1924 void
1925 set_var_read_only (name)
1926      char *name;
1927 {
1928   SHELL_VAR *entry;
1929
1930   FIND_OR_MAKE_VARIABLE (name, entry);
1931   entry->attributes |= att_readonly;
1932 }
1933
1934 /* Make the function associated with NAME be readonly.
1935    If NAME does not exist, we just punt, like auto_export code below. */
1936 void
1937 set_func_read_only (name)
1938      char *name;
1939 {
1940   SHELL_VAR *entry;
1941
1942   entry = find_function (name);
1943   if (entry)
1944     entry->attributes |= att_readonly;
1945 }
1946
1947 /* Make the variable associated with NAME be auto-exported.
1948    If NAME does not exist yet, create it. */
1949 void
1950 set_var_auto_export (name)
1951      char *name;
1952 {
1953   SHELL_VAR *entry;
1954
1955   FIND_OR_MAKE_VARIABLE (name, entry);
1956   set_auto_export (entry);
1957 }
1958
1959 /* Make the function associated with NAME be auto-exported. */
1960 void
1961 set_func_auto_export (name)
1962      char *name;
1963 {
1964   SHELL_VAR *entry;
1965
1966   entry = find_function (name);
1967   if (entry)
1968     set_auto_export (entry);
1969 }
1970
1971 #if defined (ARRAY_VARS)
1972 /* This function assumes s[i] == '['; returns with s[ret] == ']' if
1973    an array subscript is correctly parsed. */
1974 int
1975 skipsubscript (s, i)
1976      char *s;
1977      int i;
1978 {
1979   int count, c;
1980
1981   for (count = 1; count && (c = s[++i]); )
1982     {
1983       if (c == '[')
1984         count++;
1985       else if (c == ']')
1986         count--;
1987     }
1988   return i;
1989 }
1990 #endif /* ARRAY_VARS */
1991
1992 /* Returns non-zero if STRING is an assignment statement.  The returned value
1993    is the index of the `=' sign. */
1994 int
1995 assignment (string)
1996      char *string;
1997 {
1998   register int c, newi, indx;
1999
2000   c = string[indx = 0];
2001
2002   if (legal_variable_starter (c) == 0)
2003     return (0);
2004
2005   while (c = string[indx])
2006     {
2007       /* The following is safe.  Note that '=' at the start of a word
2008          is not an assignment statement. */
2009       if (c == '=')
2010         return (indx);
2011
2012 #if defined (ARRAY_VARS)
2013       if (c == '[')
2014         {
2015           newi = skipsubscript (string, indx);
2016           if (string[newi++] != ']')
2017             return (0);
2018           return ((string[newi] == '=') ? newi : 0);
2019         }
2020 #endif /* ARRAY_VARS */
2021
2022       /* Variable names in assignment statements may contain only letters,
2023          digits, and `_'. */
2024       if (legal_variable_char (c) == 0)
2025         return (0);
2026
2027       indx++;
2028     }
2029   return (0);
2030 }
2031
2032 static int
2033 visible_var (var)
2034      SHELL_VAR *var;
2035 {
2036   return (invisible_p (var) == 0);
2037 }
2038
2039 static SHELL_VAR **
2040 _visible_names (table)
2041      HASH_TABLE *table;
2042 {
2043   SHELL_VAR **list;
2044
2045   list = map_over (visible_var, table);
2046
2047   if (list /* && posixly_correct */)
2048     sort_variables (list);
2049
2050   return (list);
2051 }
2052
2053 SHELL_VAR **
2054 all_visible_variables ()
2055 {
2056   return (_visible_names (shell_variables));
2057 }
2058
2059 SHELL_VAR **
2060 all_visible_functions ()
2061 {
2062   return (_visible_names (shell_functions));
2063 }
2064
2065 /* Return non-zero if the variable VAR is visible and exported.  Array
2066    variables cannot be exported. */
2067 static int
2068 visible_and_exported (var)
2069      SHELL_VAR *var;
2070 {
2071   return (invisible_p (var) == 0 && exported_p (var));
2072 }
2073
2074 /* Make an array of assignment statements from the hash table
2075    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
2076    variables are eligible. */
2077 char **
2078 make_var_array (hashed_vars)
2079      HASH_TABLE *hashed_vars;
2080 {
2081   register int i, list_index;
2082   register SHELL_VAR *var;
2083   char **list, *value;
2084   SHELL_VAR **vars;
2085
2086   vars = map_over (visible_and_exported, hashed_vars);
2087
2088   if (vars == 0)
2089     return (char **)NULL;
2090
2091   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
2092
2093   for (i = 0, list_index = 0; var = vars[i]; i++)
2094     {
2095       if (function_p (var))
2096         value = named_function_string ((char *)NULL, function_cell (var), 0);
2097 #if defined (ARRAY_VARS)
2098       else if (array_p (var))
2099 #  if 0
2100         value = array_to_assignment_string (array_cell (var));
2101 #  else
2102         continue;       /* XXX array vars cannot yet be exported */
2103 #  endif
2104 #endif
2105       else
2106         value = value_cell (var);
2107
2108       if (value)
2109         {
2110           int name_len, value_len;
2111           char  *p;
2112
2113           name_len = strlen (var->name);
2114           value_len = strlen (value);
2115           p = list[list_index] = xmalloc (2 + name_len + value_len);
2116           strcpy (p, var->name);
2117           p[name_len] = '=';
2118           strcpy (p + name_len + 1, value);
2119           list_index++;
2120 #if defined (ARRAY_VARS)
2121           if (array_p (var))
2122             free (value);
2123 #endif
2124         }
2125     }
2126
2127   free (vars);
2128   list[list_index] = (char *)NULL;
2129   return (list);
2130 }
2131
2132 /* Add STRING to the array of foo=bar strings that we already
2133    have to add to the environment.  */
2134 int
2135 assign_in_env (string)
2136      char *string;
2137 {
2138   int size, offset;
2139   char *name, *temp, *value;
2140   int nlen, vlen;
2141   WORD_LIST *list;
2142   SHELL_VAR *var;
2143
2144   offset = assignment (string);
2145   name = savestring (string);
2146   value = (char *)NULL;
2147
2148 #define freetemp nlen
2149   if (name[offset] == '=')
2150     {
2151       name[offset] = 0;
2152
2153       var = find_variable (name);
2154       if (var && readonly_p (var))
2155         {
2156           report_error ("%s: readonly variable", name);
2157           free (name);
2158           return (0);
2159         }
2160       temp = name + offset + 1;
2161       freetemp = strchr (temp, '~') != 0;
2162       if (freetemp)
2163         temp = bash_tilde_expand (temp);
2164
2165       list = expand_string_unsplit (temp, 0);
2166       value = string_list (list);
2167
2168       if (list)
2169         dispose_words (list);
2170
2171       if (freetemp)
2172         free (temp);
2173     }
2174 #undef freetemp
2175
2176   nlen = strlen (name);
2177   vlen = value ? strlen (value) : 0;
2178   temp = xmalloc (2 + nlen + vlen);
2179   strcpy (temp, name);
2180   temp[nlen] = '=';
2181   temp[nlen + 1] = '\0';
2182   if (value)
2183     {
2184       if (*value)
2185         strcpy (temp + nlen + 1, value);
2186       free (value);
2187     }
2188   free (name);
2189
2190   if (temporary_env == 0)
2191     {
2192       temporary_env = (char **)xmalloc (sizeof (char *));
2193       temporary_env [0] = (char *)NULL;
2194     }
2195
2196   size = array_len (temporary_env);
2197   temporary_env = (char **)
2198     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
2199
2200   temporary_env[size] = temp;
2201   temporary_env[size + 1] = (char *)NULL;
2202   array_needs_making = 1;
2203
2204   if (echo_command_at_execute)
2205     {
2206       /* The Korn shell prints the `+ ' in front of assignment statements,
2207          so we do too. */
2208       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
2209       fflush (stderr);
2210     }
2211
2212   return 1;
2213 }
2214
2215 /* Search for NAME in ARRAY, an array of strings in the same format as the
2216    environment array (i.e, name=value).  If NAME is present, make a new
2217    variable and return it.  Otherwise, return NULL. */
2218 static SHELL_VAR *
2219 find_name_in_env_array (name, array)
2220      char *name;
2221      char **array;
2222 {
2223   register int i, l;
2224
2225   if (array == 0)
2226     return ((SHELL_VAR *)NULL);
2227
2228   for (i = 0, l = strlen (name); array[i]; i++)
2229     {
2230       if (STREQN (array[i], name, l) && array[i][l] == '=')
2231         {
2232           SHELL_VAR *temp;
2233           char *w;
2234
2235           temp = new_shell_variable (name);     /* XXX memory leak here */
2236           w = array[i] + l + 1;
2237
2238           temp->value = *w ? savestring (w) : (char *)NULL;
2239
2240           temp->attributes = att_exported;
2241           temp->context = 0;
2242           temp->prev_context = (SHELL_VAR *)NULL;
2243
2244           temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
2245
2246           return (temp);
2247         }
2248     }
2249   return ((SHELL_VAR *)NULL);
2250 }
2251
2252 /* Find a variable in the temporary environment that is named NAME.
2253    The temporary environment can be either the environment provided
2254    to a simple command, or the environment provided to a shell function.
2255    We only search the function environment if we are currently executing
2256    a shell function body (variable_context > 0).  Return a consed variable,
2257    or NULL if not found. */
2258 SHELL_VAR *
2259 find_tempenv_variable (name)
2260      char *name;
2261 {
2262   SHELL_VAR *var = (SHELL_VAR *)NULL;
2263
2264   if (temporary_env)
2265     var = find_name_in_env_array (name, temporary_env);
2266
2267   /* We don't check this_shell_builtin because the command that needs the
2268      value from builtin_env may be a disk command run inside a script run
2269      with `.' and a temporary env. */
2270   if (!var && builtin_env)
2271     var = find_name_in_env_array (name, builtin_env);
2272
2273   if (!var && variable_context && function_env)
2274     var = find_name_in_env_array (name, function_env);
2275
2276   return (var);
2277 }
2278
2279 /* Free the storage allocated to the string array pointed to by ARRAYP, and
2280    make that variable have a null pointer as a value. */
2281 static void
2282 dispose_temporary_vars (arrayp)
2283      char ***arrayp;
2284 {
2285   if (!*arrayp)
2286     return;
2287
2288   free_array (*arrayp);
2289   *arrayp = (char **)NULL;
2290   array_needs_making = 1;
2291 }
2292
2293 /* Free the storage used in the variable array for temporary
2294    environment variables. */
2295 void
2296 dispose_used_env_vars ()
2297 {
2298   dispose_temporary_vars (&temporary_env);
2299 }
2300
2301 /* Free the storage used for temporary environment variables given to
2302    commands when executing inside of a function body. */
2303 void
2304 dispose_function_env ()
2305 {
2306   dispose_temporary_vars (&function_env);
2307 }
2308
2309 /* Free the storage used for temporary environment variables given to
2310    commands when executing a builtin command such as "source". */
2311 void
2312 dispose_builtin_env ()
2313 {
2314   dispose_temporary_vars (&builtin_env);
2315 }
2316
2317 /* Take all of the shell variables in ENV_ARRAY and make shell variables
2318    from them at the current variable context. */
2319 static void
2320 merge_env_array (env_array)
2321      char **env_array;
2322 {
2323   register int i, l;
2324   SHELL_VAR *temp;
2325   char *val, *name;
2326
2327   if (env_array == 0)
2328     return;
2329
2330   for (i = 0; env_array[i]; i++)
2331     {
2332       l = assignment (env_array[i]);
2333       name = env_array[i];
2334       val = env_array[i] + l + 1;
2335       name[l] = '\0';
2336       temp = bind_variable (name, val);
2337       name[l] = '=';
2338     }
2339 }
2340
2341 void
2342 merge_temporary_env ()
2343 {
2344   merge_env_array (temporary_env);
2345 }
2346
2347 void
2348 merge_builtin_env ()
2349 {
2350   merge_env_array (builtin_env);
2351 }
2352
2353 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
2354 #define add_to_export_env(envstr,do_alloc) \
2355 do \
2356   { \
2357     if (export_env_index >= (export_env_size - 1)) \
2358       { \
2359         export_env_size += 16; \
2360         export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *)); \
2361       } \
2362     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
2363     export_env[export_env_index] = (char *)NULL; \
2364   } while (0)
2365
2366 #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
2367
2368 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
2369    array with the same left-hand side.  Return the new EXPORT_ENV. */
2370 char **
2371 add_or_supercede_exported_var (assign, do_alloc)
2372      char *assign;
2373      int do_alloc;
2374 {
2375   register int i;
2376   int equal_offset;
2377
2378   equal_offset = assignment (assign);
2379   if (equal_offset == 0)
2380     return (export_env);
2381
2382   /* If this is a function, then only supercede the function definition.
2383      We do this by including the `=(' in the comparison.  */
2384   if (assign[equal_offset + 1] == '(')
2385     equal_offset++;
2386
2387   for (i = 0; i < export_env_index; i++)
2388     {
2389       if (STREQN (assign, export_env[i], equal_offset + 1))
2390         {
2391           free (export_env[i]);
2392           export_env[i] = do_alloc ? savestring (assign) : assign;
2393           return (export_env);
2394         }
2395     }
2396   add_to_export_env (assign, do_alloc);
2397   return (export_env);
2398 }
2399
2400 /* Make the environment array for the command about to be executed, if the
2401    array needs making.  Otherwise, do nothing.  If a shell action could
2402    change the array that commands receive for their environment, then the
2403    code should `array_needs_making++'. */
2404 void
2405 maybe_make_export_env ()
2406 {
2407   register int i;
2408   register char **temp_array;
2409   int new_size;
2410
2411   if (array_needs_making)
2412     {
2413       if (export_env)
2414         free_array_members (export_env);
2415
2416       /* Make a guess based on how many shell variables and functions we
2417          have.  Since there will always be array variables, and array
2418          variables are not (yet) exported, this will always be big enough
2419          for the exported variables and functions, without any temporary
2420          or function environments. */
2421       new_size = shell_variables->nentries + shell_functions->nentries + 1;
2422       if (new_size > export_env_size)
2423         {
2424           export_env_size = new_size;
2425           export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
2426         }
2427       export_env[export_env_index = 0] = (char *)NULL;
2428
2429       temp_array = make_var_array (shell_variables);
2430       if (temp_array)
2431         {
2432           for (i = 0; temp_array[i]; i++)
2433             add_to_export_env (temp_array[i], 0);
2434           free (temp_array);
2435         }
2436
2437       temp_array = make_var_array (shell_functions);
2438       if (temp_array)
2439         {
2440           for (i = 0; temp_array[i]; i++)
2441             add_to_export_env (temp_array[i], 0);
2442           free (temp_array);
2443         }
2444
2445       if (function_env)
2446         for (i = 0; function_env[i]; i++)
2447           export_env = add_or_supercede_exported_var (function_env[i], 1);
2448
2449       if (temporary_env)
2450         for (i = 0; temporary_env[i]; i++)
2451           export_env = add_or_supercede_exported_var (temporary_env[i], 1);
2452
2453 #if 0
2454       /* If we changed the array, then sort it alphabetically. */
2455       if (posixly_correct == 0 && (temporary_env || function_env))
2456         sort_char_array (export_env);
2457 #endif
2458
2459       array_needs_making = 0;
2460     }
2461 }
2462
2463 /* We always put _ in the environment as the name of this command. */
2464 void
2465 put_command_name_into_env (command_name)
2466      char *command_name;
2467 {
2468   char *dummy;
2469
2470   dummy = xmalloc (4 + strlen (command_name));
2471
2472   /* These three statements replace a call to sprintf */
2473   dummy[0] = '_';
2474   dummy[1] = '=';
2475   strcpy (dummy + 2, command_name);
2476   export_env = add_or_supercede_exported_var (dummy, 0);
2477 }
2478
2479 void
2480 put_gnu_argv_flags_into_env (pid, flags_string)
2481      int pid;
2482      char *flags_string;
2483 {
2484   char *dummy, *pbuf;
2485   int l, fl;
2486
2487   pbuf = itos (pid);
2488   l = strlen (pbuf);
2489
2490   fl = strlen (flags_string);
2491
2492   dummy = xmalloc (l + fl + 30);
2493   dummy[0] = '_';
2494   strcpy (dummy + 1, pbuf);
2495   strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
2496   dummy[l + 27] = '=';
2497   strcpy (dummy + l + 28, flags_string);
2498
2499   free (pbuf);
2500
2501   export_env = add_or_supercede_exported_var (dummy, 0);
2502 }
2503
2504 /* Return a string denoting what our indirection level is. */
2505 static char indirection_string[100];
2506
2507 char *
2508 indirection_level_string ()
2509 {
2510   register int i, j;
2511   char *ps4;
2512
2513   indirection_string[0] = '\0';
2514   ps4 = get_string_value ("PS4");
2515
2516   if (ps4 == 0 || *ps4 == '\0')
2517     return (indirection_string);
2518
2519   ps4 = decode_prompt_string (ps4);
2520
2521   for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
2522     indirection_string[i] = *ps4;
2523
2524   for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
2525     indirection_string[i] = ps4[j];
2526
2527   indirection_string[i] = '\0';
2528   free (ps4);
2529   return (indirection_string);
2530 }