]> git.ipfire.org Git - thirdparty/bash.git/blame - variables.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / variables.c
CommitLineData
726f6388
JA
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
bb70624e 9 the Free Software Foundation; either version 2, or (at your option)
726f6388
JA
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
bb70624e 19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388 20
ccc6cda3
JA
21#include "config.h"
22
726f6388
JA
23#include "bashtypes.h"
24#include "posixstat.h"
ccc6cda3 25
d166f048
JA
26#if defined (qnx)
27# include <sys/vc.h>
28#endif
29
ccc6cda3
JA
30#if defined (HAVE_UNISTD_H)
31# include <unistd.h>
32#endif
33
34#include <stdio.h>
726f6388
JA
35#include <ctype.h>
36#include <pwd.h>
726f6388 37#include "bashansi.h"
ccc6cda3 38
726f6388 39#include "shell.h"
726f6388
JA
40#include "flags.h"
41#include "execute_cmd.h"
cce855bc 42#include "findcmd.h"
ccc6cda3
JA
43#include "mailcheck.h"
44#include "input.h"
726f6388 45
d166f048 46#include "builtins/getopt.h"
726f6388 47#include "builtins/common.h"
cce855bc
JA
48
49#if defined (READLINE)
50# include "bashline.h"
51# include <readline/readline.h>
52#else
53# include <tilde/tilde.h>
54#endif
726f6388 55
ccc6cda3
JA
56#if defined (HISTORY)
57# include "bashhist.h"
cce855bc 58# include <readline/history.h>
ccc6cda3
JA
59#endif /* HISTORY */
60
bb70624e
JA
61#if defined (PROGRAMMABLE_COMPLETION)
62# include "pcomplete.h"
63#endif
64
726f6388
JA
65/* Variables used here and defined in other files. */
66extern int posixly_correct;
67extern int variable_context, line_number;
ccc6cda3
JA
68extern int interactive, interactive_shell, login_shell;
69extern int subshell_environment, indirection_level;
70extern int build_version, patch_level;
71extern char *dist_version, *release_status;
726f6388
JA
72extern char *shell_name;
73extern char *primary_prompt, *secondary_prompt;
ccc6cda3 74extern char *current_host_name;
726f6388 75extern Function *this_shell_builtin;
bb70624e 76extern SHELL_VAR *this_shell_function;
ccc6cda3 77extern char *this_command_name;
726f6388
JA
78extern time_t shell_start_time;
79
80/* The list of shell variables that the user has created, or that came from
81 the environment. */
82HASH_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. */
86HASH_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. */
90int variable_context = 0;
91
92/* The array of shell assignments which are made only in the environment
93 for a single command. */
94char **temporary_env = (char **)NULL;
95
96/* The array of shell assignments which are in the environment for the
97 execution of a shell function. */
98char **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
28ef6c31 102 one command to be executed (e.g., "eval" or "source"). */
726f6388
JA
103char **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. */
107char *dollar_vars[10];
108WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
109
110/* The value of $$. */
111int dollar_dollar_pid;
112
113/* An array which is passed to commands as their environment. It is
d166f048 114 manufactured from the union of the initial environment and the
726f6388
JA
115 shell variables that are marked for export. */
116char **export_env = (char **)NULL;
d166f048
JA
117static int export_env_index;
118static int export_env_size;
726f6388
JA
119
120/* Non-zero means that we have to remake EXPORT_ENV. */
121int array_needs_making = 1;
122
ccc6cda3
JA
123/* The number of times BASH has been executed. This is set
124 by initialize_variables (). */
125int shell_level = 0;
726f6388 126
ccc6cda3
JA
127static char *have_local_variables;
128static int local_variable_stack_size;
726f6388
JA
129
130/* Some forward declarations. */
d166f048
JA
131static void set_home_var ();
132static void set_shell_var ();
133static char *get_bash_name ();
134static void initialize_shell_level ();
ccc6cda3 135static void uidset ();
726f6388 136static void initialize_dynamic_variables ();
ccc6cda3 137static void make_vers_array ();
726f6388
JA
138static void sbrand (); /* set bash random number generator. */
139static int qsort_var_comp ();
28ef6c31 140static SHELL_VAR *bind_tempenv_variable ();
726f6388
JA
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
cce855bc
JA
146/* Initialize the shell variables from the current environment.
147 If PRIVMODE is nonzero, don't import functions from ENV or
148 parse $SHELLOPTS. */
726f6388 149void
cce855bc 150initialize_shell_variables (env, privmode)
726f6388 151 char **env;
cce855bc 152 int privmode;
726f6388 153{
ccc6cda3
JA
154 char *name, *string, *temp_string;
155 int c, char_index, string_index, string_length;
726f6388
JA
156 SHELL_VAR *temp_var;
157
cce855bc 158 if (shell_variables == 0)
726f6388
JA
159 shell_variables = make_hash_table (0);
160
cce855bc 161 if (shell_functions == 0)
726f6388
JA
162 shell_functions = make_hash_table (0);
163
ccc6cda3 164 for (string_index = 0; string = env[string_index++]; )
726f6388 165 {
726f6388 166 char_index = 0;
d166f048 167 name = string;
726f6388 168 while ((c = *string++) && c != '=')
d166f048
JA
169 ;
170 if (string[-1] == '=')
28ef6c31 171 char_index = string - name - 1;
726f6388 172
d166f048
JA
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)
28ef6c31 176 continue;
d166f048
JA
177
178 /* ASSERT(name[char_index] == '=') */
726f6388 179 name[char_index] = '\0';
d166f048 180 /* Now, name = env variable name, string = env variable value, and
28ef6c31 181 char_index == strlen (name) */
726f6388
JA
182
183 /* If exported function, define it now. */
bb70624e 184 if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
726f6388 185 {
d166f048
JA
186 string_length = strlen (string);
187 temp_string = xmalloc (3 + string_length + char_index);
bb70624e 188
d166f048
JA
189 strcpy (temp_string, name);
190 temp_string[char_index] = ' ';
191 strcpy (temp_string + char_index + 1, string);
726f6388 192
d166f048 193 parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
726f6388 194
d166f048
JA
195 /* Ancient backwards compatibility. Old versions of bash exported
196 functions like name()=() {...} */
197 if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
726f6388
JA
198 name[char_index - 2] = '\0';
199
ccc6cda3 200 if (temp_var = find_function (name))
726f6388 201 {
bb70624e 202 VSETATTR (temp_var, (att_exported|att_imported));
726f6388
JA
203 array_needs_making = 1;
204 }
205 else
206 report_error ("error importing function definition for `%s'", name);
d166f048 207
bb70624e 208 /* ( */
d166f048 209 if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
bb70624e 210 name[char_index - 2] = '('; /* ) */
726f6388 211 }
ccc6cda3
JA
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);
bb70624e 221 VSETATTR (temp_var, (att_exported | att_imported));
ccc6cda3
JA
222 array_needs_making = 1;
223 }
224# endif
225#endif
726f6388
JA
226 else
227 {
ccc6cda3 228 temp_var = bind_variable (name, string);
bb70624e 229 VSETATTR (temp_var, (att_exported | att_imported));
726f6388
JA
230 array_needs_making = 1;
231 }
d166f048
JA
232
233 name[char_index] = '=';
bb70624e 234 /* temp_var can be NULL if it was an exported function with a syntax
28ef6c31 235 error (a different bug, but it still shouldn't dump core). */
bb70624e
JA
236 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
237 {
238 CACHE_IMPORTSTR (temp_var, name);
239 }
726f6388
JA
240 }
241
28ef6c31 242 set_pwd ();
b72432fd 243
ccc6cda3
JA
244 /* Set up initial value of $_ */
245 temp_var = bind_variable ("_", dollar_vars[0]);
246
726f6388
JA
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
d166f048
JA
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
ccc6cda3 268 /* set up the prompts. */
726f6388
JA
269 if (interactive_shell)
270 {
b72432fd 271#if defined (PROMPT_STRING_DECODE)
726f6388 272 set_if_not ("PS1", primary_prompt);
b72432fd
JA
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
726f6388
JA
278 set_if_not ("PS2", secondary_prompt);
279 }
280 set_if_not ("PS4", "+ ");
281
ccc6cda3
JA
282 /* Don't allow IFS to be imported from the environment. */
283 temp_var = bind_variable ("IFS", " \t\n");
726f6388
JA
284
285 /* Magic machine types. Pretty convenient. */
28ef6c31 286 temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
726f6388 287 set_auto_export (temp_var);
28ef6c31 288 temp_var = set_if_not ("OSTYPE", OSTYPE);
ccc6cda3 289 set_auto_export (temp_var);
28ef6c31 290 temp_var = set_if_not ("MACHTYPE", MACHTYPE);
ccc6cda3 291 set_auto_export (temp_var);
28ef6c31
JA
292
293 temp_var = set_if_not ("HOSTNAME", current_host_name);
726f6388
JA
294 set_auto_export (temp_var);
295
ccc6cda3
JA
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. */
726f6388
JA
300 if (interactive_shell)
301 set_if_not ("MAILCHECK", "60");
302
303 /* Do some things with shell level. */
d166f048 304 initialize_shell_level ();
726f6388 305
b72432fd 306 set_ppid ();
726f6388 307
726f6388
JA
308 /* Initialize the `getopts' stuff. */
309 bind_variable ("OPTIND", "1");
d166f048 310 getopts_reset (0);
726f6388 311 bind_variable ("OPTERR", "1");
d166f048
JA
312 sh_opterr = 1;
313
314 if (login_shell == 1)
315 set_home_var ();
726f6388
JA
316
317 /* Get the full pathname to THIS shell, and set the BASH variable
318 to it. */
d166f048 319 name = get_bash_name ();
ccc6cda3
JA
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. */
d166f048 327 set_shell_var ();
726f6388
JA
328
329 /* Make a variable called BASH_VERSION which contains the version info. */
330 bind_variable ("BASH_VERSION", shell_version_string ());
ccc6cda3
JA
331#if defined (ARRAY_VARS)
332 make_vers_array ();
333#endif
726f6388
JA
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 {
ccc6cda3 349 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history");
726f6388
JA
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. */
ccc6cda3 360 sbrand (dollar_dollar_pid + (long)shell_start_time);
726f6388
JA
361
362 /* Handle some "special" variables that we may have inherited from a
363 parent shell. */
d166f048
JA
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 }
726f6388
JA
372
373#if defined (HISTORY)
374 if (interactive_shell && remember_on_history)
375 {
ccc6cda3
JA
376 sv_history_control ("HISTCONTROL");
377 sv_histignore ("HISTIGNORE");
726f6388
JA
378 }
379#endif /* HISTORY */
380
bb70624e 381 temp_var = find_variable ("SSH_CLIENT");
28ef6c31
JA
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");
bb70624e
JA
388 if (temp_var && imported_p (temp_var))
389 {
390 VUNSETATTR (temp_var, att_exported);
391 array_needs_making = 1;
392 }
393
ccc6cda3
JA
394 /* Get the user's real and effective user ids. */
395 uidset ();
396
726f6388
JA
397 /* Initialize the dynamic variables, and seed their values. */
398 initialize_dynamic_variables ();
726f6388
JA
399}
400
d166f048
JA
401/* Set $HOME to the information in the password file if we didn't get
402 it from the environment. */
b72432fd
JA
403
404/* This function is not static so the tilde and readline libraries can
405 use it. */
406char *
28ef6c31 407sh_get_home_dir ()
b72432fd
JA
408{
409 if (current_user.home_dir == 0)
410 get_current_user_info ();
411 return current_user.home_dir;
412}
413
d166f048
JA
414static void
415set_home_var ()
416{
417 SHELL_VAR *temp_var;
418
419 temp_var = find_variable ("HOME");
420 if (temp_var == 0)
28ef6c31 421 temp_var = bind_variable ("HOME", sh_get_home_dir ());
bb70624e 422 VSETATTR (temp_var, att_exported);
d166f048
JA
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. */
427static void
428set_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 }
bb70624e 439 VSETATTR (temp_var, att_exported);
d166f048
JA
440}
441
442static char *
443get_bash_name ()
444{
445 char *name;
446
28ef6c31 447 if ((login_shell == 1) && RELPATH(shell_name))
d166f048
JA
448 {
449 if (current_user.shell == 0)
28ef6c31 450 get_current_user_info ();
d166f048
JA
451 name = savestring (current_user.shell);
452 }
28ef6c31 453 else if (ABSPATH(shell_name))
d166f048
JA
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");
28ef6c31
JA
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);
d166f048
JA
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 {
28ef6c31 489 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
d166f048
JA
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
726f6388
JA
515void
516adjust_shell_level (change)
517 int change;
518{
d166f048 519 char new_level[5], *old_SHLVL;
726f6388 520 int old_level;
d166f048 521 SHELL_VAR *temp_var;
726f6388
JA
522
523 old_SHLVL = get_string_value ("SHLVL");
d166f048 524 old_level = old_SHLVL ? atoi (old_SHLVL) : 0;
726f6388
JA
525
526 shell_level = old_level + change;
527 if (shell_level < 0)
528 shell_level = 0;
d166f048
JA
529 else if (shell_level > 1000)
530 {
cce855bc 531 internal_warning ("shell level (%d) too high, resetting to 1", shell_level);
d166f048
JA
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
560static void
561initialize_shell_level ()
562{
d166f048 563 adjust_shell_level (1);
726f6388
JA
564}
565
28ef6c31
JA
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
573void
574set_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
b72432fd
JA
612/* Make a variable $PPID, which holds the pid of the shell's parent. */
613void
614set_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)
bb70624e 622 VUNSETATTR (temp_var, (att_readonly | att_exported));
b72432fd 623 temp_var = bind_variable ("PPID", name);
bb70624e 624 VSETATTR (temp_var, (att_readonly | att_integer));
b72432fd
JA
625}
626
ccc6cda3
JA
627static void
628uidset ()
726f6388 629{
b72432fd 630 char buff[32], *b;
ccc6cda3
JA
631 register SHELL_VAR *v;
632
b72432fd 633 b = inttostr (current_user.uid, buff, sizeof (buff));
ccc6cda3 634 v = find_variable ("UID");
28ef6c31
JA
635 if (v == 0)
636 {
637 v = bind_variable ("UID", b);
638 VSETATTR (v, (att_readonly | att_integer));
639 }
726f6388 640
ccc6cda3 641 if (current_user.euid != current_user.uid)
b72432fd 642 b = inttostr (current_user.euid, buff, sizeof (buff));
726f6388 643
ccc6cda3 644 v = find_variable ("EUID");
28ef6c31
JA
645 if (v == 0)
646 {
647 v = bind_variable ("EUID", b);
648 VSETATTR (v, (att_readonly | att_integer));
649 }
ccc6cda3
JA
650}
651
652#if defined (ARRAY_VARS)
653static void
654make_vers_array ()
655{
656 SHELL_VAR *vv;
657 ARRAY *av;
b72432fd 658 char *s, d[32];
ccc6cda3
JA
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);
b72432fd 670 s = inttostr (patch_level, d, sizeof (d));
ccc6cda3 671 array_add_element (av, 2, s);
b72432fd 672 s = inttostr (build_version, d, sizeof (d));
ccc6cda3 673 array_add_element (av, 3, s);
ccc6cda3
JA
674 array_add_element (av, 4, release_status);
675 array_add_element (av, 5, MACHTYPE);
676
bb70624e 677 VSETATTR (vv, att_readonly);
ccc6cda3
JA
678}
679#endif /* ARRAY_VARS */
680
681/* Set the environment variables $LINES and $COLUMNS in response to
682 a window size change. */
683void
28ef6c31 684sh_set_lines_and_columns (lines, cols)
ccc6cda3
JA
685 int lines, cols;
686{
b72432fd 687 char val[32], *v;
ccc6cda3 688
b72432fd
JA
689 v = inttostr (lines, val, sizeof (val));
690 bind_variable ("LINES", v);
ccc6cda3 691
b72432fd
JA
692 v = inttostr (cols, val, sizeof (val));
693 bind_variable ("COLUMNS", v);
726f6388
JA
694}
695
696/* Set NAME to VALUE if NAME has no value. */
697SHELL_VAR *
698set_if_not (name, value)
699 char *name, *value;
700{
ccc6cda3 701 SHELL_VAR *v;
726f6388 702
ccc6cda3 703 v = find_variable (name);
cce855bc 704 if (v == 0)
726f6388
JA
705 v = bind_variable (name, value);
706 return (v);
707}
708
709/* Map FUNCTION over the variables in VARIABLES. Return an array of the
d166f048
JA
710 variables for which FUNCTION returns a non-zero value. A NULL value
711 for FUNCTION means to use all variables. */
726f6388
JA
712SHELL_VAR **
713map_over (function, var_hash_table)
714 Function *function;
715 HASH_TABLE* var_hash_table;
716{
717 register int i;
718 register BUCKET_CONTENTS *tlist;
d166f048
JA
719 SHELL_VAR *var, **list;
720 int list_index, list_size;
726f6388 721
d166f048
JA
722 list = (SHELL_VAR **)NULL;
723 for (i = list_index = list_size = 0; i < var_hash_table->nbuckets; i++)
726f6388
JA
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
746void
747sort_variables (array)
748 SHELL_VAR **array;
749{
750 qsort (array, array_len ((char **)array), sizeof (SHELL_VAR *), qsort_var_comp);
751}
752
753static int
754qsort_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. */
766static SHELL_VAR **
767all_vars (table)
768 HASH_TABLE *table;
769{
770 SHELL_VAR **list;
771
772 list = map_over ((Function *)NULL, table);
d166f048 773 if (list /* && posixly_correct */)
726f6388
JA
774 sort_variables (list);
775 return (list);
776}
777
778/* Create a NULL terminated array of all the shell variables. */
779SHELL_VAR **
780all_shell_variables ()
781{
782 return (all_vars (shell_variables));
783}
784
785/* Create a NULL terminated array of all the shell functions. */
786SHELL_VAR **
787all_shell_functions ()
788{
789 return (all_vars (shell_functions));
790}
791
28ef6c31
JA
792/* Print LIST (a list of shell variables) to stdout in such a way that
793 they can be read back in. */
726f6388
JA
794void
795print_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
28ef6c31
JA
806/* Print LIST (a list of shell functions) to stdout in such a way that
807 they can be read back in. */
808void
809print_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
726f6388
JA
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. */
ccc6cda3 827void
726f6388
JA
828print_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. */
843void
844print_assignment (var)
845 SHELL_VAR *var;
846{
847 if (function_p (var) && var->value)
848 {
28ef6c31 849 printf ("%s", var->name);
726f6388
JA
850 print_var_function (var);
851 printf ("\n");
852 }
ccc6cda3
JA
853#if defined (ARRAY_VARS)
854 else if (array_p (var) && var->value)
855 print_array_assignment (var, 0);
856#endif /* ARRAY_VARS */
726f6388
JA
857 else if (var->value)
858 {
859 printf ("%s=", var->name);
ccc6cda3 860 print_var_value (var, 1);
726f6388
JA
861 printf ("\n");
862 }
863}
864
865/* Print the value cell of VAR, a shell variable. Do not print
ccc6cda3
JA
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. */
726f6388 869void
ccc6cda3 870print_var_value (var, quote)
726f6388 871 SHELL_VAR *var;
ccc6cda3 872 int quote;
726f6388 873{
ccc6cda3
JA
874 char *t;
875
726f6388 876 if (var->value)
ccc6cda3 877 {
28ef6c31 878 if (quote && sh_contains_shell_metas (var->value))
ccc6cda3 879 {
28ef6c31
JA
880#if 0
881 t = sh_single_quote (var->value);
882#else
883 t = ansic_quote (var->value, 0, (int *)0);
884#endif
ccc6cda3
JA
885 printf ("%s", t);
886 free (t);
887 }
888 else
889 printf ("%s", var->value);
890 }
726f6388
JA
891}
892
893/* Print the function cell of VAR, a shell variable. Do not
894 print the name, nor leading/trailing newline. */
895void
896print_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
ccc6cda3
JA
903#if defined (ARRAY_VARS)
904void
905print_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
726f6388 926/* **************************************************************** */
ccc6cda3 927/* */
28ef6c31 928/* Dynamic Variable Extension */
ccc6cda3 929/* */
726f6388
JA
930/* **************************************************************** */
931
932/* DYNAMIC VARIABLES
ccc6cda3 933
726f6388
JA
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.
ccc6cda3 938
726f6388
JA
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).
ccc6cda3 945
726f6388
JA
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);
ccc6cda3 951
726f6388
JA
952 Sometimes `tempvar' will replace the value of `var'. Other times, the
953 shell will simply use the string value. Pretty object-oriented, huh?
ccc6cda3 954
726f6388
JA
955 Be warned, though: if you `unset' a special variable, it loses its
956 special meaning, even if you subsequently set it.
ccc6cda3 957
726f6388
JA
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
bb70624e
JA
963static SHELL_VAR *
964null_assign (self, value)
965 SHELL_VAR *self;
966 char *value;
967{
968 return (self);
969}
970
971#if defined (ARRAY_VARS)
972static SHELL_VAR *
973null_array_assign (self, ind, value)
974 SHELL_VAR *self;
975 int ind;
976 char *value;
977{
978 return (self);
979}
980#endif
981
726f6388
JA
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. */
ccc6cda3 985static long seconds_value_assigned;
726f6388
JA
986
987static SHELL_VAR *
988assign_seconds (self, value)
989 SHELL_VAR *self;
990 char *value;
991{
cce855bc 992 seconds_value_assigned = strtol (value, (char **)NULL, 10);
726f6388
JA
993 shell_start_time = NOW;
994 return (self);
995}
996
997static SHELL_VAR *
998get_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
bb70624e 1009 VSETATTR (var, att_integer);
726f6388
JA
1010 var->value = p;
1011 return (var);
1012}
1013
1014/* The random number seed. You can change this by setting RANDOM. */
1015static unsigned long rseed = 1;
ccc6cda3 1016static unsigned long last_random_value;
726f6388
JA
1017
1018/* A linear congruential random number generator based on the ANSI
cce855bc
JA
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. */
726f6388
JA
1021
1022/* Returns a pseudo-random number between 0 and 32767. */
1023static int
1024brand ()
1025{
1026 rseed = rseed * 1103515245 + 12345;
cce855bc 1027 return ((unsigned int)(rseed & 32767)); /* was % 32768 */
726f6388
JA
1028}
1029
1030/* Set the random number generator seed to SEED. */
1031static void
1032sbrand (seed)
1033 int seed;
1034{
1035 rseed = seed;
e8ce775d 1036 last_random_value = 0;
726f6388
JA
1037}
1038
1039static SHELL_VAR *
1040assign_random (self, value)
1041 SHELL_VAR *self;
1042 char *value;
1043{
ccc6cda3 1044 sbrand (atoi (value));
726f6388
JA
1045 return (self);
1046}
1047
28ef6c31
JA
1048int
1049get_random_number ()
726f6388
JA
1050{
1051 int rv;
726f6388 1052
ccc6cda3
JA
1053 /* Reset for command and process substitution. */
1054 if (subshell_environment)
e8ce775d 1055 sbrand (rseed + (int)(getpid() + NOW));
ccc6cda3
JA
1056
1057 do
1058 rv = brand ();
1059 while (rv == (int)last_random_value);
28ef6c31
JA
1060 return rv;
1061}
ccc6cda3 1062
28ef6c31
JA
1063static SHELL_VAR *
1064get_random (var)
1065 SHELL_VAR *var;
1066{
1067 int rv;
1068 char *p;
1069
1070 rv = get_random_number ();
ccc6cda3 1071 last_random_value = rv;
726f6388
JA
1072 p = itos ((int)rv);
1073
1074 FREE (var->value);
1075
bb70624e 1076 VSETATTR (var, att_integer);
726f6388
JA
1077 var->value = p;
1078 return (var);
1079}
1080
1081/* Function which returns the current line number. */
1082static SHELL_VAR *
1083get_lineno (var)
1084 SHELL_VAR *var;
1085{
1086 char *p;
ccc6cda3 1087 int ln;
726f6388 1088
ccc6cda3
JA
1089 ln = executing_line_number ();
1090 p = itos (ln);
726f6388
JA
1091 FREE (var->value);
1092 var->value = p;
1093 return (var);
1094}
1095
ccc6cda3
JA
1096static SHELL_VAR *
1097assign_lineno (var, value)
1098 SHELL_VAR *var;
1099 char *value;
1100{
1101 line_number = atoi (value);
1102 return var;
1103}
1104
726f6388
JA
1105#if defined (HISTORY)
1106static SHELL_VAR *
1107get_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
ccc6cda3
JA
1119#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1120static SHELL_VAR *
1121get_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));
d166f048 1130 dispose_words (l);
ccc6cda3
JA
1131 self->value = (char *)a;
1132 return self;
1133}
1134
1135static SHELL_VAR *
1136assign_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
d166f048
JA
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. */
1149static SHELL_VAR *
1150get_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 */
bb70624e
JA
1168
1169static SHELL_VAR *
1170get_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
1181void
1182make_funcname_visible (on_or_off)
1183 int on_or_off;
726f6388
JA
1184{
1185 SHELL_VAR *v;
1186
bb70624e
JA
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)
726f6388 1212
bb70624e
JA
1213static void
1214initialize_dynamic_variables ()
1215{
1216 SHELL_VAR *v;
726f6388 1217
bb70624e
JA
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);
726f6388
JA
1221
1222#if defined (HISTORY)
bb70624e 1223 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (DYNAMIC_FUNC *)NULL);
726f6388 1224#endif
ccc6cda3
JA
1225
1226#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
bb70624e 1227 INIT_DYNAMIC_ARRAY_VAR ("DIRSTACK", get_dirstack, assign_dirstack);
ccc6cda3 1228#endif /* PUSHD_AND_POPD && ARRAY_VARS */
d166f048
JA
1229
1230#if defined (ARRAY_VARS)
bb70624e 1231 INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign);
28ef6c31 1232 VSETATTR (v, att_noassign);
d166f048 1233#endif
bb70624e
JA
1234
1235 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
28ef6c31 1236 VSETATTR (v, att_invisible|att_noassign);
726f6388
JA
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). */
1242SHELL_VAR *
1243var_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);
ccc6cda3 1250 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
726f6388
JA
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. */
1255SHELL_VAR *
1256find_variable_internal (name, search_tempenv)
1257 char *name;
1258 int search_tempenv;
1259{
28ef6c31
JA
1260 SHELL_VAR *var;
1261
1262 var = (SHELL_VAR *)NULL;
726f6388
JA
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
ccc6cda3 1279 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
726f6388
JA
1280}
1281
1282/* Look up the variable entry named NAME. Returns the entry or NULL. */
1283SHELL_VAR *
1284find_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. */
1293SHELL_VAR *
1294find_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
cce855bc
JA
1302 string. This is a potential memory leak if the variable is found
1303 in the temporary environment. */
726f6388
JA
1304char *
1305get_string_value (var_name)
28ef6c31 1306 const char *var_name;
726f6388 1307{
d166f048
JA
1308 SHELL_VAR *var;
1309
28ef6c31 1310 var = find_variable ((char *)var_name); /* XXX fix later */
726f6388
JA
1311
1312 if (!var)
1313 return (char *)NULL;
ccc6cda3
JA
1314#if defined (ARRAY_VARS)
1315 else if (array_p (var))
1316 return (array_reference (array_cell (var), 0));
1317#endif
726f6388
JA
1318 else
1319 return (var->value);
1320}
1321
b72432fd
JA
1322/* This is present for use by the tilde and readline libraries. */
1323char *
28ef6c31
JA
1324sh_get_env_value (v)
1325 const char *v;
b72432fd
JA
1326{
1327 return get_string_value (v);
1328}
1329
726f6388
JA
1330/* Create a local variable referenced by NAME. */
1331SHELL_VAR *
1332make_local_variable (name)
1333 char *name;
1334{
1335 SHELL_VAR *new_var, *old_var;
1336 BUCKET_CONTENTS *elt;
28ef6c31 1337 int old_var_context;
726f6388
JA
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
bb70624e
JA
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
28ef6c31
JA
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");
bb70624e
JA
1356 return ((SHELL_VAR *)NULL);
1357 }
1358
726f6388
JA
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. */
d166f048
JA
1371 if (old_var == 0)
1372 new_var = bind_variable (name, "");
726f6388
JA
1373 else
1374 {
1375 new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1376
1377 new_var->name = savestring (name);
ccc6cda3
JA
1378 new_var->value = xmalloc (1);
1379 new_var->value[0] = '\0';
726f6388 1380
bb70624e
JA
1381 CLEAR_EXPORTSTR (new_var);
1382
726f6388
JA
1383 new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
1384 new_var->assign_func = (DYNAMIC_FUNC *)NULL;
1385
ccc6cda3 1386 new_var->attributes = exported_p (old_var) ? att_exported : 0;
726f6388
JA
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;
bb70624e 1394 VSETATTR (new_var, att_local);
726f6388
JA
1395
1396 /* XXX */
ccc6cda3 1397 if (variable_context >= local_variable_stack_size)
726f6388
JA
1398 {
1399 int old_size = local_variable_stack_size;
ccc6cda3
JA
1400 RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
1401 local_variable_stack_size, 8);
726f6388
JA
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
ccc6cda3 1410#if defined (ARRAY_VARS)
726f6388 1411SHELL_VAR *
ccc6cda3
JA
1412make_local_array_variable (name)
1413 char *name;
1414{
1415 SHELL_VAR *var;
1416 ARRAY *array;
1417
1418 var = make_local_variable (name);
bb70624e
JA
1419 if (var == 0)
1420 return var;
ccc6cda3
JA
1421 array = new_array ();
1422
1423 FREE (value_cell(var));
1424 var->value = (char *)array;
bb70624e 1425 VSETATTR (var, att_array);
ccc6cda3
JA
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. */
1432static
1433SHELL_VAR *
1434make_new_variable (name)
1435 char *name;
726f6388 1436{
ccc6cda3 1437 SHELL_VAR *entry;
726f6388
JA
1438 BUCKET_CONTENTS *elt;
1439
ccc6cda3 1440 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
726f6388 1441
ccc6cda3
JA
1442 entry->attributes = 0;
1443 entry->name = savestring (name);
1444 entry->value = (char *)NULL;
bb70624e 1445 CLEAR_EXPORTSTR (entry);
726f6388 1446
ccc6cda3
JA
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
28ef6c31
JA
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
ccc6cda3
JA
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)
1467SHELL_VAR *
1468make_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;
bb70624e 1477 VSETATTR (entry, att_array);
ccc6cda3
JA
1478 return entry;
1479}
1480#endif
1481
1482char *
1483make_variable_value (var, value)
1484 SHELL_VAR *var;
1485 char *value;
1486{
1487 char *retval;
1488 long lval;
d166f048 1489 int expok;
ccc6cda3
JA
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 {
d166f048
JA
1498 lval = evalexp (value, &expok);
1499 if (expok == 0)
1500 jump_to_top_level (DISCARD);
ccc6cda3
JA
1501 retval = itos (lval);
1502 }
1503 else if (value)
1504 {
1505 if (*value)
1506 retval = savestring (value);
1507 else
726f6388 1508 {
ccc6cda3
JA
1509 retval = xmalloc (1);
1510 retval[0] = '\0';
726f6388 1511 }
ccc6cda3
JA
1512 }
1513 else
1514 retval = (char *)NULL;
726f6388 1515
ccc6cda3
JA
1516 return retval;
1517}
726f6388 1518
ccc6cda3
JA
1519/* Bind a variable NAME to VALUE. This conses up the name
1520 and value strings. */
1521SHELL_VAR *
1522bind_variable (name, value)
1523 char *name, *value;
1524{
1525 char *newval;
28ef6c31
JA
1526 SHELL_VAR *entry, *tempenv_entry;
1527 int found_in_tempenv;
726f6388 1528
28ef6c31
JA
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
ccc6cda3
JA
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);
726f6388 1554 }
28ef6c31 1555 else if (entry->assign_func) /* array vars have assign functions now */
bb70624e
JA
1556 {
1557 INVALIDATE_EXPORTSTR (entry);
1558 return ((*(entry->assign_func)) (entry, value));
1559 }
726f6388
JA
1560 else
1561 {
28ef6c31 1562 if (readonly_p (entry) || noassign_p (entry))
726f6388 1563 {
28ef6c31
JA
1564 if (readonly_p (entry))
1565 report_error ("%s: readonly variable", name);
726f6388
JA
1566 return (entry);
1567 }
1568
1569 /* Variables which are bound are visible. */
bb70624e 1570 VUNSETATTR (entry, att_invisible);
726f6388 1571
ccc6cda3 1572 newval = make_variable_value (entry, value);
726f6388 1573
bb70624e
JA
1574 /* Invalidate any cached export string */
1575 INVALIDATE_EXPORTSTR (entry);
1576
ccc6cda3
JA
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))
d166f048
JA
1583 {
1584 array_add_element (array_cell (entry), 0, newval);
1585 free (newval);
1586 }
726f6388
JA
1587 else
1588 {
1589 FREE (entry->value);
ccc6cda3 1590 entry->value = newval;
726f6388 1591 }
ccc6cda3
JA
1592#else
1593 FREE (entry->value);
1594 entry->value = newval;
1595#endif
726f6388
JA
1596 }
1597
1598 if (mark_modified_vars)
bb70624e 1599 VSETATTR (entry, att_exported);
726f6388
JA
1600
1601 if (exported_p (entry))
1602 array_needs_making = 1;
1603
1604 return (entry);
1605}
1606
bb70624e
JA
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. */
1612SHELL_VAR *
1613bind_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
1646SHELL_VAR *
1647bind_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
ccc6cda3
JA
1668#if defined (ARRAY_VARS)
1669/* Convert a shell variable to an array variable. The original value is
1670 saved as array[0]. */
1671SHELL_VAR *
1672convert_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);
bb70624e 1681
ccc6cda3
JA
1682 FREE (value_cell (var));
1683 var->value = (char *)array;
bb70624e
JA
1684
1685 INVALIDATE_EXPORTSTR (var);
1686
1687 VSETATTR (var, att_array);
1688 VUNSETATTR (var, att_invisible);
ccc6cda3
JA
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. */
1700SHELL_VAR *
1701bind_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);
28ef6c31 1713 else if (readonly_p (entry) || noassign_p (entry))
ccc6cda3 1714 {
28ef6c31
JA
1715 if (readonly_p (entry))
1716 report_error ("%s: readonly variable", name);
ccc6cda3
JA
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
cce855bc
JA
1733/* Perform a compound assignment statement for array NAME, where VALUE is
1734 the text between the parens: NAME=( VALUE ) */
ccc6cda3
JA
1735SHELL_VAR *
1736assign_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);
28ef6c31 1744 else if (readonly_p (var) || noassign_p (var))
d166f048 1745 {
28ef6c31
JA
1746 if (readonly_p (var))
1747 report_error ("%s: readonly variable", name);
d166f048
JA
1748 return ((SHELL_VAR *)NULL);
1749 }
ccc6cda3
JA
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
1756SHELL_VAR *
1757assign_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
bb70624e
JA
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. */
1776static void
1777quote_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
cce855bc
JA
1807/* Perform a compound array assignment: VAR->name=( VALUE ). The
1808 VALUE has already had the parentheses stripped. */
ccc6cda3
JA
1809SHELL_VAR *
1810assign_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
cce855bc
JA
1819 if (value == 0)
1820 return var;
ccc6cda3 1821
cce855bc
JA
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 == '(') /*)*/
ccc6cda3
JA
1826 {
1827 ni = 1;
1828 val = extract_array_assignment_list (value, &ni);
1829 if (val == 0)
28ef6c31 1830 return var;
ccc6cda3
JA
1831 }
1832 else
cce855bc 1833 val = value;
ccc6cda3 1834
cce855bc 1835 /* Expand the value string into a list of words, performing all the
b72432fd 1836 shell expansions including pathname generation and word splitting. */
cce855bc
JA
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");
bb70624e
JA
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
cce855bc
JA
1846 /* Now that we've split it, perform the shell expansions on each
1847 word in the list. */
b72432fd 1848 nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
cce855bc 1849
b72432fd
JA
1850 dispose_words (list);
1851
cce855bc
JA
1852 if (val != value)
1853 free (val);
1854
1855 a = array_cell (var);
1856
e8ce775d
JA
1857 /* Now that we are ready to assign values to the array, kill the existing
1858 value. */
1859 if (a)
1860 empty_array (a);
e8ce775d 1861
ccc6cda3
JA
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))
28ef6c31 1911 this_command_name = (char *)NULL; /* no command name for errors */
ccc6cda3
JA
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
726f6388
JA
1926/* Dispose of the information attached to VAR. */
1927void
1928dispose_variable (var)
1929 SHELL_VAR *var;
1930{
1931 if (!var)
1932 return;
1933
1934 if (function_p (var))
ccc6cda3
JA
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));
726f6388 1942
bb70624e
JA
1943 FREE_EXPORTSTR (var);
1944
726f6388
JA
1945 free (var->name);
1946
1947 if (exported_p (var))
1948 array_needs_making = 1;
1949
1950 free (var);
1951}
1952
ccc6cda3
JA
1953#if defined (ARRAY_VARS)
1954/* This function is called with SUB pointing to just after the beginning
1955 `[' of an array subscript. */
1956int
1957unbind_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 {
d166f048 1980 builtin_error ("[%s]: bad array subscript", sub);
ccc6cda3
JA
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
726f6388 1990/* Unset the variable referenced by NAME. */
ccc6cda3 1991int
726f6388
JA
1992unbind_variable (name)
1993 char *name;
1994{
cce855bc 1995 SHELL_VAR *var;
726f6388 1996
cce855bc 1997 var = find_variable (name);
726f6388
JA
1998 if (!var)
1999 return (-1);
2000
ccc6cda3
JA
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
726f6388 2005 if (var->value)
ccc6cda3 2006#endif
726f6388
JA
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. */
ccc6cda3 2021int
726f6388
JA
2022makunbound (name, hash_list)
2023 char *name;
2024 HASH_TABLE *hash_list;
2025{
d166f048 2026 BUCKET_CONTENTS *elt, *new_elt;
726f6388
JA
2027 SHELL_VAR *old_var, *new_var;
2028 char *t;
2029
2030 elt = remove_hash_item (name, hash_list);
2031
d166f048 2032 if (elt == 0)
726f6388
JA
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
bb70624e
JA
2041#if defined (PROGRAMMABLE_COMPLETION)
2042 if (hash_list == shell_functions)
2043 set_itemlist_dirty (&it_functions);
2044#endif
2045
ccc6cda3
JA
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 {
bb70624e
JA
2054 VSETATTR (old_var, att_invisible);
2055 INVALIDATE_EXPORTSTR (old_var);
d166f048
JA
2056 new_elt = add_hash_item (savestring (old_var->name), hash_list);
2057 new_elt->data = (char *)old_var;
ccc6cda3 2058 stupidly_hack_special_variables (old_var->name);
d166f048
JA
2059 free (elt->key);
2060 free (elt);
ccc6cda3
JA
2061 return (0);
2062 }
2063
726f6388
JA
2064 if (new_var)
2065 {
2066 /* Has to be a variable, functions don't have previous contexts. */
726f6388
JA
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))
ccc6cda3 2071 set_auto_export (new_var);
726f6388
JA
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
d166f048 2088#ifdef INCLUDE_UNUSED
726f6388
JA
2089/* Remove the variable with NAME if it is a local variable in the
2090 current context. */
ccc6cda3 2091int
726f6388
JA
2092kill_local_variable (name)
2093 char *name;
2094{
d166f048 2095 SHELL_VAR *temp;
726f6388 2096
d166f048 2097 temp = find_variable (name);
ccc6cda3 2098 if (temp && temp->context == variable_context)
726f6388
JA
2099 {
2100 makunbound (name, shell_variables);
2101 return (0);
2102 }
2103 return (-1);
2104}
d166f048 2105#endif
726f6388
JA
2106
2107/* Get rid of all of the variables in the current context. */
2108int
2109variable_in_context (var)
2110 SHELL_VAR *var;
2111{
2112 return (var && var->context == variable_context);
2113}
2114
2115void
2116kill_all_local_variables ()
2117{
2118 register int i, pass;
2119 register SHELL_VAR *var, **list;
2120 HASH_TABLE *varlist;
2121
ccc6cda3
JA
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)
726f6388
JA
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++)
ccc6cda3 2142 {
bb70624e 2143 VUNSETATTR (var, att_local);
ccc6cda3
JA
2144 makunbound (var->name, varlist);
2145 }
726f6388
JA
2146 free (list);
2147 }
2148 }
2149
2150 have_local_variables[variable_context] = 0; /* XXX */
2151}
2152
ccc6cda3
JA
2153static void
2154free_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
726f6388
JA
2168/* Delete the entire contents of the hash table. */
2169void
2170delete_all_variables (hashed_vars)
2171 HASH_TABLE *hashed_vars;
2172{
ccc6cda3 2173 flush_hash_table (hashed_vars, free_variable_hash_data);
726f6388
JA
2174}
2175
2176static SHELL_VAR *
2177new_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. */
2191SHELL_VAR *
2192bind_function (name, value)
2193 char *name;
2194 COMMAND *value;
2195{
ccc6cda3 2196 SHELL_VAR *entry;
726f6388 2197
ccc6cda3 2198 entry = find_function (name);
726f6388
JA
2199 if (!entry)
2200 {
2201 BUCKET_CONTENTS *elt;
2202
2203 elt = add_hash_item (savestring (name), shell_functions);
2204
bb70624e 2205 entry = new_shell_variable (name);
ccc6cda3 2206 entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
bb70624e 2207 CLEAR_EXPORTSTR (entry);
726f6388
JA
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;
bb70624e
JA
2212
2213 elt->data = (char *)entry;
726f6388
JA
2214 }
2215
bb70624e
JA
2216 INVALIDATE_EXPORTSTR (entry);
2217
726f6388
JA
2218 if (entry->value)
2219 dispose_command ((COMMAND *)entry->value);
2220
ccc6cda3 2221 entry->value = value ? (char *)copy_command (value) : (char *)NULL;
bb70624e 2222 VSETATTR (entry, att_function);
726f6388
JA
2223
2224 if (mark_modified_vars)
bb70624e 2225 VSETATTR (entry, att_exported);
726f6388 2226
bb70624e 2227 VUNSETATTR (entry, att_invisible); /* Just to be sure */
726f6388 2228
ccc6cda3
JA
2229 if (exported_p (entry))
2230 array_needs_making = 1;
726f6388 2231
bb70624e
JA
2232#if defined (PROGRAMMABLE_COMPLETION)
2233 set_itemlist_dirty (&it_functions);
2234#endif
2235
726f6388
JA
2236 return (entry);
2237}
2238
d166f048 2239#ifdef INCLUDE_UNUSED
726f6388
JA
2240/* Copy VAR to a new data structure and return that structure. */
2241SHELL_VAR *
2242copy_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))
ccc6cda3
JA
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));
726f6388
JA
2262 else
2263 copy->value = (char *)NULL;
2264
2265 copy->dynamic_value = var->dynamic_value;
2266 copy->assign_func = var->assign_func;
2267
bb70624e
JA
2268 copy->exportstr = COPY_EXPORTSTR (var);
2269
726f6388
JA
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}
d166f048 2277#endif
726f6388 2278
ccc6cda3
JA
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.
726f6388
JA
2292 If NAME does not exist yet, create it. */
2293void
2294set_var_read_only (name)
2295 char *name;
2296{
ccc6cda3 2297 SHELL_VAR *entry;
726f6388 2298
ccc6cda3 2299 FIND_OR_MAKE_VARIABLE (name, entry);
bb70624e 2300 VSETATTR (entry, att_readonly);
726f6388
JA
2301}
2302
cce855bc 2303#ifdef INCLUDE_UNUSED
ccc6cda3 2304/* Make the function associated with NAME be readonly.
726f6388
JA
2305 If NAME does not exist, we just punt, like auto_export code below. */
2306void
2307set_func_read_only (name)
2308 char *name;
2309{
d166f048 2310 SHELL_VAR *entry;
726f6388 2311
d166f048 2312 entry = find_function (name);
726f6388 2313 if (entry)
bb70624e 2314 VSETATTR (entry, att_readonly);
726f6388
JA
2315}
2316
2317/* Make the variable associated with NAME be auto-exported.
2318 If NAME does not exist yet, create it. */
2319void
2320set_var_auto_export (name)
2321 char *name;
2322{
ccc6cda3 2323 SHELL_VAR *entry;
726f6388 2324
ccc6cda3 2325 FIND_OR_MAKE_VARIABLE (name, entry);
726f6388
JA
2326 set_auto_export (entry);
2327}
2328
2329/* Make the function associated with NAME be auto-exported. */
2330void
2331set_func_auto_export (name)
2332 char *name;
2333{
ccc6cda3 2334 SHELL_VAR *entry;
726f6388 2335
ccc6cda3 2336 entry = find_function (name);
726f6388 2337 if (entry)
ccc6cda3
JA
2338 set_auto_export (entry);
2339}
cce855bc 2340#endif
ccc6cda3
JA
2341
2342#if defined (ARRAY_VARS)
2343/* This function assumes s[i] == '['; returns with s[ret] == ']' if
2344 an array subscript is correctly parsed. */
2345int
2346skipsubscript (s, i)
2347 char *s;
2348 int i;
2349{
2350 int count, c;
2351
2352 for (count = 1; count && (c = s[++i]); )
726f6388 2353 {
ccc6cda3
JA
2354 if (c == '[')
2355 count++;
2356 else if (c == ']')
2357 count--;
726f6388 2358 }
ccc6cda3 2359 return i;
726f6388 2360}
ccc6cda3 2361#endif /* ARRAY_VARS */
726f6388
JA
2362
2363/* Returns non-zero if STRING is an assignment statement. The returned value
2364 is the index of the `=' sign. */
ccc6cda3 2365int
726f6388
JA
2366assignment (string)
2367 char *string;
2368{
ccc6cda3 2369 register int c, newi, indx;
726f6388 2370
ccc6cda3 2371 c = string[indx = 0];
726f6388 2372
ccc6cda3 2373 if (legal_variable_starter (c) == 0)
726f6388
JA
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
ccc6cda3
JA
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)
726f6388
JA
2396 return (0);
2397
2398 indx++;
2399 }
2400 return (0);
2401}
2402
2403static int
2404visible_var (var)
2405 SHELL_VAR *var;
2406{
ccc6cda3 2407 return (invisible_p (var) == 0);
726f6388
JA
2408}
2409
ccc6cda3
JA
2410static SHELL_VAR **
2411_visible_names (table)
2412 HASH_TABLE *table;
726f6388
JA
2413{
2414 SHELL_VAR **list;
2415
ccc6cda3 2416 list = map_over (visible_var, table);
726f6388 2417
d166f048 2418 if (list /* && posixly_correct */)
726f6388
JA
2419 sort_variables (list);
2420
2421 return (list);
2422}
2423
2424SHELL_VAR **
bb70624e 2425all_visible_functions ()
726f6388 2426{
bb70624e 2427 return (_visible_names (shell_functions));
ccc6cda3 2428}
726f6388 2429
ccc6cda3 2430SHELL_VAR **
bb70624e 2431all_visible_variables ()
ccc6cda3 2432{
bb70624e 2433 return (_visible_names (shell_variables));
726f6388
JA
2434}
2435
ccc6cda3
JA
2436/* Return non-zero if the variable VAR is visible and exported. Array
2437 variables cannot be exported. */
726f6388
JA
2438static int
2439visible_and_exported (var)
2440 SHELL_VAR *var;
2441{
ccc6cda3 2442 return (invisible_p (var) == 0 && exported_p (var));
726f6388
JA
2443}
2444
bb70624e
JA
2445SHELL_VAR **
2446all_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. */
2458static int
2459visible_array_vars (var)
2460 SHELL_VAR *var;
2461{
2462 return (invisible_p (var) == 0 && array_p (var));
2463}
2464
2465SHELL_VAR **
2466all_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
2477char **
2478all_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))
28ef6c31 2495 rlist[rind++] = savestring (varlist[vind]->name);
bb70624e
JA
2496 }
2497 rlist[rind] = (char *)0;
2498 free (varlist);
2499
2500 return rlist;
2501}
2502
2503static inline char *
2504mk_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 */
2523static int
2524valid_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 == '=')
28ef6c31 2538 break;
bb70624e
JA
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
726f6388
JA
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. */
2556char **
2557make_var_array (hashed_vars)
2558 HASH_TABLE *hashed_vars;
2559{
2560 register int i, list_index;
2561 register SHELL_VAR *var;
ccc6cda3 2562 char **list, *value;
726f6388
JA
2563 SHELL_VAR **vars;
2564
2565 vars = map_over (visible_and_exported, hashed_vars);
2566
d166f048 2567 if (vars == 0)
726f6388
JA
2568 return (char **)NULL;
2569
bb70624e
JA
2570 list = alloc_array ((1 + array_len ((char **)vars)));
2571
2572#define USE_EXPORTSTR (value == var->exportstr)
726f6388
JA
2573
2574 for (i = 0, list_index = 0; var = vars[i]; i++)
2575 {
28ef6c31
JA
2576#if defined (__CYGWIN__)
2577 /* We don't use the exportstr stuff on Cygwin at all. */
2578 INVALIDATE_EXPORTSTR (var);
bb70624e 2579#endif
28ef6c31
JA
2580 if (var->exportstr)
2581 value = var->exportstr;
bb70624e 2582 else if (function_p (var))
ccc6cda3
JA
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
726f6388
JA
2592 else
2593 value = value_cell (var);
2594
2595 if (value)
2596 {
bb70624e
JA
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 }
726f6388 2606 list_index++;
bb70624e
JA
2607#undef USE_EXPORTSTR
2608
2609#if 0 /* not yet */
ccc6cda3
JA
2610#if defined (ARRAY_VARS)
2611 if (array_p (var))
2612 free (value);
bb70624e 2613#endif
ccc6cda3 2614#endif
726f6388
JA
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. */
ccc6cda3 2625int
726f6388
JA
2626assign_in_env (string)
2627 char *string;
2628{
ccc6cda3
JA
2629 int size, offset;
2630 char *name, *temp, *value;
726f6388 2631 int nlen, vlen;
ccc6cda3
JA
2632 WORD_LIST *list;
2633 SHELL_VAR *var;
2634
2635 offset = assignment (string);
2636 name = savestring (string);
2637 value = (char *)NULL;
726f6388
JA
2638
2639 if (name[offset] == '=')
2640 {
726f6388 2641 name[offset] = 0;
ccc6cda3
JA
2642
2643 var = find_variable (name);
28ef6c31 2644 if (var && (readonly_p (var) || noassign_p (var)))
ccc6cda3 2645 {
28ef6c31
JA
2646 if (readonly_p (var))
2647 report_error ("%s: readonly variable", name);
d166f048 2648 free (name);
ccc6cda3
JA
2649 return (0);
2650 }
28ef6c31 2651
726f6388 2652 temp = name + offset + 1;
cce855bc 2653 temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
726f6388
JA
2654
2655 list = expand_string_unsplit (temp, 0);
2656 value = string_list (list);
2657
2658 if (list)
2659 dispose_words (list);
2660
cce855bc 2661 free (temp);
726f6388 2662 }
726f6388 2663
bb70624e
JA
2664 temp = mk_env_string (name, value);
2665 FREE (value);
726f6388 2666 free (name);
726f6388 2667
ccc6cda3 2668 if (temporary_env == 0)
726f6388
JA
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
ccc6cda3 2678 temporary_env[size] = temp;
726f6388
JA
2679 temporary_env[size + 1] = (char *)NULL;
2680 array_needs_making = 1;
2681
2682 if (echo_command_at_execute)
2683 {
ccc6cda3 2684 /* The Korn shell prints the `+ ' in front of assignment statements,
726f6388
JA
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
28ef6c31
JA
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). */
2696static SHELL_VAR *
2697shell_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
2726static SHELL_VAR *
2727bind_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
726f6388
JA
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. */
2758static SHELL_VAR *
2759find_name_in_env_array (name, array)
2760 char *name;
2761 char **array;
2762{
ccc6cda3 2763 register int i, l;
28ef6c31 2764 SHELL_VAR *temp;
726f6388 2765
ccc6cda3 2766 if (array == 0)
726f6388
JA
2767 return ((SHELL_VAR *)NULL);
2768
ccc6cda3 2769 for (i = 0, l = strlen (name); array[i]; i++)
726f6388
JA
2770 {
2771 if (STREQN (array[i], name, l) && array[i][l] == '=')
2772 {
28ef6c31
JA
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. */
2794static SHELL_VAR *
2795bind_tempenv_variable (name, value)
2796 char *name, *value;
2797{
2798 SHELL_VAR *var;
726f6388 2799
28ef6c31 2800 var = (SHELL_VAR *)NULL;
726f6388 2801
28ef6c31
JA
2802 if (temporary_env)
2803 FIND_AND_BIND_IN_ENV_ARRAY (name, value, temporary_env);
726f6388 2804
28ef6c31
JA
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);
726f6388 2810
28ef6c31
JA
2811 if (variable_context && function_env)
2812 FIND_AND_BIND_IN_ENV_ARRAY (name, value, function_env);
726f6388 2813
28ef6c31 2814 return (SHELL_VAR *)NULL;
726f6388
JA
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. */
2823SHELL_VAR *
2824find_tempenv_variable (name)
2825 char *name;
2826{
cce855bc
JA
2827 SHELL_VAR *var;
2828
2829 var = (SHELL_VAR *)NULL;
726f6388
JA
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. */
2848static void
2849dispose_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. */
2862void
2863dispose_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. */
2870void
2871dispose_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". */
2878void
2879dispose_builtin_env ()
2880{
2881 dispose_temporary_vars (&builtin_env);
2882}
2883
ccc6cda3
JA
2884/* Take all of the shell variables in ENV_ARRAY and make shell variables
2885 from them at the current variable context. */
2886static void
2887merge_env_array (env_array)
2888 char **env_array;
2889{
2890 register int i, l;
2891 SHELL_VAR *temp;
d166f048 2892 char *val, *name;
ccc6cda3
JA
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];
d166f048 2901 val = env_array[i] + l + 1;
ccc6cda3 2902 name[l] = '\0';
d166f048 2903 temp = bind_variable (name, val);
ccc6cda3
JA
2904 name[l] = '=';
2905 }
2906}
2907
726f6388 2908void
ccc6cda3 2909merge_temporary_env ()
726f6388 2910{
ccc6cda3
JA
2911 merge_env_array (temporary_env);
2912}
2913
2914void
2915merge_builtin_env ()
2916{
2917 merge_env_array (builtin_env);
726f6388
JA
2918}
2919
28ef6c31
JA
2920void
2921merge_function_env ()
2922{
2923 merge_env_array (function_env);
2924}
2925
bb70624e
JA
2926int
2927any_temporary_variables ()
2928{
2929 return (temporary_env || function_env);
2930}
2931
d166f048
JA
2932/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
2933#define add_to_export_env(envstr,do_alloc) \
2934do \
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
cce855bc 2945#define ISFUNCTION(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')'))
726f6388 2946
d166f048
JA
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. */
726f6388 2949char **
d166f048 2950add_or_supercede_exported_var (assign, do_alloc)
726f6388 2951 char *assign;
d166f048 2952 int do_alloc;
726f6388
JA
2953{
2954 register int i;
d166f048 2955 int equal_offset;
726f6388 2956
d166f048
JA
2957 equal_offset = assignment (assign);
2958 if (equal_offset == 0)
2959 return (export_env);
726f6388
JA
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
d166f048 2966 for (i = 0; i < export_env_index; i++)
726f6388 2967 {
d166f048 2968 if (STREQN (assign, export_env[i], equal_offset + 1))
726f6388 2969 {
d166f048
JA
2970 free (export_env[i]);
2971 export_env[i] = do_alloc ? savestring (assign) : assign;
2972 return (export_env);
726f6388
JA
2973 }
2974 }
d166f048
JA
2975 add_to_export_env (assign, do_alloc);
2976 return (export_env);
726f6388
JA
2977}
2978
d166f048 2979/* Make the environment array for the command about to be executed, if the
726f6388
JA
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++'. */
2983void
2984maybe_make_export_env ()
2985{
2986 register int i;
2987 register char **temp_array;
d166f048 2988 int new_size;
726f6388
JA
2989
2990 if (array_needs_making)
2991 {
2992 if (export_env)
d166f048
JA
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. */
bb70624e 3000 new_size = HASH_ENTRIES (shell_variables) + HASH_ENTRIES (shell_functions) + 1;
d166f048
JA
3001 if (new_size > export_env_size)
3002 {
3003 export_env_size = new_size;
28ef6c31 3004 export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
d166f048
JA
3005 }
3006 export_env[export_env_index = 0] = (char *)NULL;
726f6388 3007
726f6388 3008 temp_array = make_var_array (shell_variables);
d166f048
JA
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 }
726f6388
JA
3015
3016 temp_array = make_var_array (shell_functions);
d166f048
JA
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 }
726f6388
JA
3023
3024 if (function_env)
3025 for (i = 0; function_env[i]; i++)
d166f048 3026 export_env = add_or_supercede_exported_var (function_env[i], 1);
726f6388 3027
28ef6c31
JA
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
726f6388
JA
3032 if (temporary_env)
3033 for (i = 0; temporary_env[i]; i++)
d166f048 3034 export_env = add_or_supercede_exported_var (temporary_env[i], 1);
726f6388 3035
ccc6cda3 3036#if 0
726f6388 3037 /* If we changed the array, then sort it alphabetically. */
ccc6cda3 3038 if (posixly_correct == 0 && (temporary_env || function_env))
726f6388 3039 sort_char_array (export_env);
ccc6cda3 3040#endif
726f6388
JA
3041
3042 array_needs_making = 0;
3043 }
3044}
3045
b72432fd
JA
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. */
3055void
3056update_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
726f6388
JA
3070/* We always put _ in the environment as the name of this command. */
3071void
3072put_command_name_into_env (command_name)
3073 char *command_name;
3074{
b72432fd 3075 update_export_env_inplace ("_=", 2, command_name);
726f6388
JA
3076}
3077
cce855bc 3078#if 0 /* UNUSED -- it caused too many problems */
ccc6cda3
JA
3079void
3080put_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
d166f048 3101 export_env = add_or_supercede_exported_var (dummy, 0);
ccc6cda3 3102}
cce855bc 3103#endif
726f6388 3104
ccc6cda3
JA
3105/* Return a string denoting what our indirection level is. */
3106static char indirection_string[100];
726f6388
JA
3107
3108char *
ccc6cda3 3109indirection_level_string ()
726f6388 3110{
ccc6cda3
JA
3111 register int i, j;
3112 char *ps4;
726f6388 3113
ccc6cda3
JA
3114 indirection_string[0] = '\0';
3115 ps4 = get_string_value ("PS4");
726f6388 3116
ccc6cda3
JA
3117 if (ps4 == 0 || *ps4 == '\0')
3118 return (indirection_string);
726f6388 3119
ccc6cda3 3120 ps4 = decode_prompt_string (ps4);
726f6388 3121
ccc6cda3
JA
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];
726f6388 3127
ccc6cda3
JA
3128 indirection_string[i] = '\0';
3129 free (ps4);
3130 return (indirection_string);
726f6388 3131}
cce855bc
JA
3132
3133/*************************************************
3134 * *
3135 * Functions to manage special variables *
3136 * *
3137 *************************************************/
3138
3139/* Extern declarations for variables this code has to manage. */
3140extern int eof_encountered, eof_encountered_limit, ignoreeof;
3141
3142#if defined (READLINE)
3143extern int no_line_editing;
3144extern 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
3154struct 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 },
bb70624e 3197 { "LC_NUMERIC", sv_locale },
cce855bc
JA
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. */
3209void
3210stupidly_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. */
3226void
3227sv_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. */
3237void
3238sv_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. */
3255void
3256sv_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. */
3266void
3267sv_terminal (name)
3268 char *name;
3269{
3270 if (interactive_shell && no_line_editing == 0)
3271 rl_reset_terminal (get_string_value ("TERM"));
3272}
3273
3274void
3275sv_hostfile (name)
3276 char *name;
3277{
bb70624e
JA
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;
cce855bc
JA
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. */
3295void
3296sv_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))
28ef6c31 3307 {
cce855bc
JA
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. */
3328void
3329sv_histignore (name)
3330 char *name;
3331{
3332 setup_history_ignore (name);
3333}
3334
3335/* What to do after the HISTCONTROL variable changes. */
3336void
3337sv_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. */
3358void
3359sv_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)
3386void
3387sv_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). */
3397void
3398sv_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
3414void
3415sv_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
3436void
3437sv_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
3446void
3447sv_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
3459void
3460sv_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)
3473void
3474set_pipestatus_array (ps)
3475 int *ps;
3476{
3477 SHELL_VAR *v;
3478 ARRAY *a;
3479 register int i;
b72432fd 3480 char *t, tbuf[16];
cce855bc
JA
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 {
b72432fd 3492 t = inttostr (ps[i], tbuf, sizeof (tbuf));
cce855bc 3493 array_add_element (a, i, t);
cce855bc
JA
3494 }
3495}
3496#endif
3497
3498void
3499set_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}