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