]> git.ipfire.org Git - thirdparty/bash.git/blob - variables.c
Imported from ../bash-2.01.1.tar.gz.
[thirdparty/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 }