]> git.ipfire.org Git - thirdparty/bash.git/blame - variables.c
Imported from ../bash-3.1.tar.gz.
[thirdparty/bash.git] / variables.c
CommitLineData
726f6388
JA
1/* variables.c -- Functions for hacking shell variables. */
2
95732b49 3/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
726f6388
JA
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"
f73dda09 25#include "posixtime.h"
ccc6cda3 26
d166f048 27#if defined (qnx)
95732b49
JA
28# if defined (qnx6)
29# include <sy/netmgr.h>
30# else
31# include <sys/vc.h>
32# endif /* !qnx6 */
33#endif /* qnx */
d166f048 34
ccc6cda3
JA
35#if defined (HAVE_UNISTD_H)
36# include <unistd.h>
37#endif
38
39#include <stdio.h>
f73dda09 40#include "chartypes.h"
726f6388 41#include <pwd.h>
726f6388 42#include "bashansi.h"
b80f6443 43#include "bashintl.h"
ccc6cda3 44
726f6388 45#include "shell.h"
726f6388
JA
46#include "flags.h"
47#include "execute_cmd.h"
cce855bc 48#include "findcmd.h"
ccc6cda3
JA
49#include "mailcheck.h"
50#include "input.h"
f73dda09
JA
51#include "hashcmd.h"
52#include "pathexp.h"
726f6388 53
d166f048 54#include "builtins/getopt.h"
726f6388 55#include "builtins/common.h"
cce855bc
JA
56
57#if defined (READLINE)
58# include "bashline.h"
59# include <readline/readline.h>
60#else
61# include <tilde/tilde.h>
62#endif
726f6388 63
ccc6cda3
JA
64#if defined (HISTORY)
65# include "bashhist.h"
cce855bc 66# include <readline/history.h>
ccc6cda3
JA
67#endif /* HISTORY */
68
bb70624e
JA
69#if defined (PROGRAMMABLE_COMPLETION)
70# include "pcomplete.h"
71#endif
72
7117c2d2
JA
73#define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
74
75#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
76
95732b49
JA
77extern char **environ;
78
726f6388
JA
79/* Variables used here and defined in other files. */
80extern int posixly_correct;
f73dda09 81extern int line_number;
b80f6443 82extern int subshell_environment, indirection_level, subshell_level;
ccc6cda3 83extern int build_version, patch_level;
b80f6443 84extern int expanding_redir;
ccc6cda3 85extern char *dist_version, *release_status;
726f6388
JA
86extern char *shell_name;
87extern char *primary_prompt, *secondary_prompt;
ccc6cda3 88extern char *current_host_name;
f73dda09 89extern sh_builtin_func_t *this_shell_builtin;
bb70624e 90extern SHELL_VAR *this_shell_function;
b80f6443 91extern char *the_printed_command_except_trap;
ccc6cda3 92extern char *this_command_name;
b80f6443 93extern char *command_execution_string;
726f6388
JA
94extern time_t shell_start_time;
95
b80f6443 96#if defined (READLINE)
95732b49 97extern int no_line_editing;
b80f6443
JA
98extern int perform_hostname_completion;
99#endif
100
7117c2d2
JA
101/* The list of shell variables that the user has created at the global
102 scope, or that came from the environment. */
103VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
104
105/* The current list of shell variables, including function scopes */
106VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
726f6388
JA
107
108/* The list of shell functions that the user has created, or that came from
109 the environment. */
110HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
111
b80f6443
JA
112#if defined (DEBUGGER)
113/* The table of shell function definitions that the user defined or that
114 came from the environment. */
115HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
116#endif
117
726f6388
JA
118/* The current variable context. This is really a count of how deep into
119 executing functions we are. */
120int variable_context = 0;
121
7117c2d2 122/* The set of shell assignments which are made only in the environment
726f6388 123 for a single command. */
7117c2d2 124HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
726f6388 125
b80f6443
JA
126/* Set to non-zero if an assignment error occurs while putting variables
127 into the temporary environment. */
128int tempenv_assign_error;
129
726f6388
JA
130/* Some funky variables which are known about specially. Here is where
131 "$*", "$1", and all the cruft is kept. */
132char *dollar_vars[10];
133WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
134
135/* The value of $$. */
f73dda09 136pid_t dollar_dollar_pid;
726f6388
JA
137
138/* An array which is passed to commands as their environment. It is
d166f048 139 manufactured from the union of the initial environment and the
726f6388
JA
140 shell variables that are marked for export. */
141char **export_env = (char **)NULL;
d166f048
JA
142static int export_env_index;
143static int export_env_size;
726f6388 144
95732b49
JA
145#if defined (READLINE)
146static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
147static int winsize_assigned; /* assigned to LINES or COLUMNS */
148#endif
149
726f6388
JA
150/* Non-zero means that we have to remake EXPORT_ENV. */
151int array_needs_making = 1;
152
ccc6cda3
JA
153/* The number of times BASH has been executed. This is set
154 by initialize_variables (). */
155int shell_level = 0;
726f6388 156
726f6388 157/* Some forward declarations. */
f73dda09
JA
158static void set_machine_vars __P((void));
159static void set_home_var __P((void));
160static void set_shell_var __P((void));
161static char *get_bash_name __P((void));
162static void initialize_shell_level __P((void));
163static void uidset __P((void));
164#if defined (ARRAY_VARS)
165static void make_vers_array __P((void));
166#endif
f73dda09 167
7117c2d2
JA
168static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
169#if defined (ARRAY_VARS)
170static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
171#endif
b80f6443
JA
172static SHELL_VAR *get_self __P((SHELL_VAR *));
173
174#if defined (ARRAY_VARS)
175static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
176#endif
7117c2d2
JA
177
178static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
179static SHELL_VAR *get_seconds __P((SHELL_VAR *));
180static SHELL_VAR *init_seconds_var __P((void));
181
182static int brand __P((void));
f73dda09 183static void sbrand __P((unsigned long)); /* set bash random number generator. */
7117c2d2
JA
184static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
185static SHELL_VAR *get_random __P((SHELL_VAR *));
f73dda09 186
7117c2d2
JA
187static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
188static SHELL_VAR *get_lineno __P((SHELL_VAR *));
f73dda09 189
b80f6443
JA
190static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
191static SHELL_VAR *get_subshell __P((SHELL_VAR *));
192
7117c2d2
JA
193#if defined (HISTORY)
194static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
195#endif
196
197#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
198static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
199static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
7117c2d2
JA
200#endif
201
202#if defined (ARRAY_VARS)
203static SHELL_VAR *get_groupset __P((SHELL_VAR *));
7117c2d2
JA
204#endif
205
206static SHELL_VAR *get_funcname __P((SHELL_VAR *));
207static SHELL_VAR *init_funcname_var __P((void));
208
209static void initialize_dynamic_variables __P((void));
210
211static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
f73dda09 212static SHELL_VAR *new_shell_variable __P((const char *));
7117c2d2 213static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
95732b49 214static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
7117c2d2
JA
215
216static void free_variable_hash_data __P((PTR_T));
217
218static VARLIST *vlist_alloc __P((int));
219static VARLIST *vlist_realloc __P((VARLIST *, int));
220static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
221
222static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
223
224static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
f73dda09 225
7117c2d2
JA
226static SHELL_VAR **vapply __P((sh_var_map_func_t *));
227static SHELL_VAR **fapply __P((sh_var_map_func_t *));
f73dda09
JA
228
229static int visible_var __P((SHELL_VAR *));
f73dda09 230static int visible_and_exported __P((SHELL_VAR *));
7117c2d2
JA
231static int local_and_exported __P((SHELL_VAR *));
232static int variable_in_context __P((SHELL_VAR *));
f73dda09
JA
233#if defined (ARRAY_VARS)
234static int visible_array_vars __P((SHELL_VAR *));
235#endif
236
7117c2d2
JA
237static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
238static void push_temp_var __P((PTR_T));
239static void propagate_temp_var __P((PTR_T));
240static void dispose_temporary_env __P((sh_free_func_t *));
241
f73dda09 242static inline char *mk_env_string __P((const char *, const char *));
7117c2d2
JA
243static char **make_env_array_from_var_list __P((SHELL_VAR **));
244static char **make_var_export_array __P((VAR_CONTEXT *));
245static char **make_func_export_array __P((void));
246static void add_temp_array_to_env __P((char **, int, int));
f73dda09 247
7117c2d2
JA
248static int n_shell_variables __P((void));
249static int set_context __P((SHELL_VAR *));
726f6388 250
7117c2d2
JA
251static void push_func_var __P((PTR_T));
252static void push_exported_var __P((PTR_T));
726f6388 253
7117c2d2
JA
254static inline int find_special_var __P((const char *));
255
cce855bc
JA
256/* Initialize the shell variables from the current environment.
257 If PRIVMODE is nonzero, don't import functions from ENV or
258 parse $SHELLOPTS. */
726f6388 259void
cce855bc 260initialize_shell_variables (env, privmode)
726f6388 261 char **env;
cce855bc 262 int privmode;
726f6388 263{
ccc6cda3
JA
264 char *name, *string, *temp_string;
265 int c, char_index, string_index, string_length;
726f6388
JA
266 SHELL_VAR *temp_var;
267
cce855bc 268 if (shell_variables == 0)
7117c2d2
JA
269 {
270 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
271 shell_variables->scope = 0;
272 shell_variables->table = hash_create (0);
273 }
726f6388 274
cce855bc 275 if (shell_functions == 0)
7117c2d2 276 shell_functions = hash_create (0);
726f6388 277
b80f6443
JA
278#if defined (DEBUGGER)
279 if (shell_function_defs == 0)
280 shell_function_defs = hash_create (0);
281#endif
282
ccc6cda3 283 for (string_index = 0; string = env[string_index++]; )
726f6388 284 {
726f6388 285 char_index = 0;
d166f048 286 name = string;
726f6388 287 while ((c = *string++) && c != '=')
d166f048
JA
288 ;
289 if (string[-1] == '=')
28ef6c31 290 char_index = string - name - 1;
726f6388 291
d166f048
JA
292 /* If there are weird things in the environment, like `=xxx' or a
293 string without an `=', just skip them. */
294 if (char_index == 0)
28ef6c31 295 continue;
d166f048
JA
296
297 /* ASSERT(name[char_index] == '=') */
726f6388 298 name[char_index] = '\0';
d166f048 299 /* Now, name = env variable name, string = env variable value, and
28ef6c31 300 char_index == strlen (name) */
726f6388 301
f73dda09 302 /* If exported function, define it now. Don't import functions from
7117c2d2 303 the environment in privileged mode. */
bb70624e 304 if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
726f6388 305 {
d166f048 306 string_length = strlen (string);
f73dda09 307 temp_string = (char *)xmalloc (3 + string_length + char_index);
bb70624e 308
d166f048
JA
309 strcpy (temp_string, name);
310 temp_string[char_index] = ' ';
311 strcpy (temp_string + char_index + 1, string);
726f6388 312
d166f048 313 parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
726f6388 314
d166f048
JA
315 /* Ancient backwards compatibility. Old versions of bash exported
316 functions like name()=() {...} */
317 if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
726f6388
JA
318 name[char_index - 2] = '\0';
319
ccc6cda3 320 if (temp_var = find_function (name))
726f6388 321 {
bb70624e 322 VSETATTR (temp_var, (att_exported|att_imported));
726f6388
JA
323 array_needs_making = 1;
324 }
325 else
b80f6443 326 report_error (_("error importing function definition for `%s'"), name);
d166f048 327
bb70624e 328 /* ( */
d166f048 329 if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
bb70624e 330 name[char_index - 2] = '('; /* ) */
726f6388 331 }
ccc6cda3
JA
332#if defined (ARRAY_VARS)
333# if 0
334 /* Array variables may not yet be exported. */
95732b49 335 else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
ccc6cda3
JA
336 {
337 string_length = 1;
338 temp_string = extract_array_assignment_list (string, &string_length);
339 temp_var = assign_array_from_string (name, temp_string);
340 FREE (temp_string);
bb70624e 341 VSETATTR (temp_var, (att_exported | att_imported));
ccc6cda3
JA
342 array_needs_making = 1;
343 }
344# endif
345#endif
726f6388
JA
346 else
347 {
95732b49 348 temp_var = bind_variable (name, string, 0);
bb70624e 349 VSETATTR (temp_var, (att_exported | att_imported));
726f6388
JA
350 array_needs_making = 1;
351 }
d166f048
JA
352
353 name[char_index] = '=';
bb70624e 354 /* temp_var can be NULL if it was an exported function with a syntax
28ef6c31 355 error (a different bug, but it still shouldn't dump core). */
bb70624e
JA
356 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
357 {
358 CACHE_IMPORTSTR (temp_var, name);
359 }
726f6388
JA
360 }
361
28ef6c31 362 set_pwd ();
b72432fd 363
ccc6cda3 364 /* Set up initial value of $_ */
95732b49
JA
365#if 0
366 temp_var = bind_variable ("_", dollar_vars[0], 0);
367#else
368 temp_var = set_if_not ("_", dollar_vars[0]);
369#endif
ccc6cda3 370
726f6388 371 /* Remember this pid. */
f73dda09 372 dollar_dollar_pid = getpid ();
726f6388
JA
373
374 /* Now make our own defaults in case the vars that we think are
375 important are missing. */
376 temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
f73dda09
JA
377#if 0
378 set_auto_export (temp_var); /* XXX */
379#endif
726f6388
JA
380
381 temp_var = set_if_not ("TERM", "dumb");
f73dda09
JA
382#if 0
383 set_auto_export (temp_var); /* XXX */
384#endif
726f6388 385
d166f048
JA
386#if defined (qnx)
387 /* set node id -- don't import it from the environment */
388 {
389 char node_name[22];
95732b49
JA
390# if defined (qnx6)
391 netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
392# else
d166f048 393 qnx_nidtostr (getnid (), node_name, sizeof (node_name));
95732b49
JA
394# endif
395 temp_var = bind_variable ("NODE", node_name, 0);
d166f048
JA
396 set_auto_export (temp_var);
397 }
398#endif
399
ccc6cda3 400 /* set up the prompts. */
726f6388
JA
401 if (interactive_shell)
402 {
b72432fd 403#if defined (PROMPT_STRING_DECODE)
726f6388 404 set_if_not ("PS1", primary_prompt);
b72432fd
JA
405#else
406 if (current_user.uid == -1)
407 get_current_user_info ();
408 set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
409#endif
726f6388
JA
410 set_if_not ("PS2", secondary_prompt);
411 }
412 set_if_not ("PS4", "+ ");
413
ccc6cda3 414 /* Don't allow IFS to be imported from the environment. */
95732b49 415 temp_var = bind_variable ("IFS", " \t\n", 0);
7117c2d2 416 setifs (temp_var);
726f6388
JA
417
418 /* Magic machine types. Pretty convenient. */
f73dda09 419 set_machine_vars ();
726f6388 420
ccc6cda3
JA
421 /* Default MAILCHECK for interactive shells. Defer the creation of a
422 default MAILPATH until the startup files are read, because MAIL
f73dda09 423 names a mail file if MAILPATH is not set, and we should provide a
ccc6cda3 424 default only if neither is set. */
726f6388 425 if (interactive_shell)
95732b49
JA
426 {
427 temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
428 VSETATTR (temp_var, att_integer);
429 }
726f6388
JA
430
431 /* Do some things with shell level. */
d166f048 432 initialize_shell_level ();
726f6388 433
b72432fd 434 set_ppid ();
726f6388 435
726f6388 436 /* Initialize the `getopts' stuff. */
95732b49
JA
437 temp_var = bind_variable ("OPTIND", "1", 0);
438 VSETATTR (temp_var, att_integer);
d166f048 439 getopts_reset (0);
95732b49 440 bind_variable ("OPTERR", "1", 0);
d166f048
JA
441 sh_opterr = 1;
442
443 if (login_shell == 1)
444 set_home_var ();
726f6388
JA
445
446 /* Get the full pathname to THIS shell, and set the BASH variable
447 to it. */
d166f048 448 name = get_bash_name ();
95732b49 449 temp_var = bind_variable ("BASH", name, 0);
ccc6cda3
JA
450 free (name);
451
452 /* Make the exported environment variable SHELL be the user's login
453 shell. Note that the `tset' command looks at this variable
454 to determine what style of commands to output; if it ends in "csh",
455 then C-shell commands are output, else Bourne shell commands. */
d166f048 456 set_shell_var ();
726f6388
JA
457
458 /* Make a variable called BASH_VERSION which contains the version info. */
95732b49 459 bind_variable ("BASH_VERSION", shell_version_string (), 0);
ccc6cda3
JA
460#if defined (ARRAY_VARS)
461 make_vers_array ();
462#endif
726f6388 463
b80f6443 464 if (command_execution_string)
95732b49 465 bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
b80f6443 466
726f6388
JA
467 /* Find out if we're supposed to be in Posix.2 mode via an
468 environment variable. */
469 temp_var = find_variable ("POSIXLY_CORRECT");
470 if (!temp_var)
471 temp_var = find_variable ("POSIX_PEDANTIC");
472 if (temp_var && imported_p (temp_var))
473 sv_strict_posix (temp_var->name);
474
475#if defined (HISTORY)
476 /* Set history variables to defaults, and then do whatever we would
477 do if the variable had just been set. Do this only in the case
478 that we are remembering commands on the history list. */
479 if (remember_on_history)
480 {
7117c2d2 481 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
726f6388
JA
482
483 set_if_not ("HISTFILE", name);
484 free (name);
485
486 set_if_not ("HISTSIZE", "500");
487 sv_histsize ("HISTSIZE");
488 }
489#endif /* HISTORY */
490
491 /* Seed the random number generator. */
f73dda09 492 sbrand (dollar_dollar_pid + shell_start_time);
726f6388
JA
493
494 /* Handle some "special" variables that we may have inherited from a
495 parent shell. */
d166f048
JA
496 if (interactive_shell)
497 {
498 temp_var = find_variable ("IGNOREEOF");
499 if (!temp_var)
500 temp_var = find_variable ("ignoreeof");
501 if (temp_var && imported_p (temp_var))
502 sv_ignoreeof (temp_var->name);
503 }
726f6388
JA
504
505#if defined (HISTORY)
506 if (interactive_shell && remember_on_history)
507 {
ccc6cda3
JA
508 sv_history_control ("HISTCONTROL");
509 sv_histignore ("HISTIGNORE");
726f6388
JA
510 }
511#endif /* HISTORY */
512
95732b49
JA
513#if defined (READLINE) && defined (STRICT_POSIX)
514 /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
515 -DSTRICT_POSIX */
516 if (interactive_shell && posixly_correct && no_line_editing == 0)
517 rl_prefer_env_winsize = 1;
518#endif /* READLINE && STRICT_POSIX */
519
f73dda09
JA
520 /*
521 * 24 October 2001
522 *
523 * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
524 * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
525 * isnetconn() to avoid running the startup files more often than wanted.
526 * That will, of course, only work if the user's login shell is bash, so
527 * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
528 * in config-top.h.
529 */
530#if 0
bb70624e 531 temp_var = find_variable ("SSH_CLIENT");
28ef6c31
JA
532 if (temp_var && imported_p (temp_var))
533 {
534 VUNSETATTR (temp_var, att_exported);
535 array_needs_making = 1;
536 }
537 temp_var = find_variable ("SSH2_CLIENT");
bb70624e
JA
538 if (temp_var && imported_p (temp_var))
539 {
540 VUNSETATTR (temp_var, att_exported);
541 array_needs_making = 1;
542 }
f73dda09 543#endif
bb70624e 544
ccc6cda3
JA
545 /* Get the user's real and effective user ids. */
546 uidset ();
547
726f6388
JA
548 /* Initialize the dynamic variables, and seed their values. */
549 initialize_dynamic_variables ();
726f6388
JA
550}
551
7117c2d2
JA
552/* **************************************************************** */
553/* */
554/* Setting values for special shell variables */
555/* */
556/* **************************************************************** */
557
f73dda09
JA
558static void
559set_machine_vars ()
560{
561 SHELL_VAR *temp_var;
562
563 temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
564 temp_var = set_if_not ("OSTYPE", OSTYPE);
565 temp_var = set_if_not ("MACHTYPE", MACHTYPE);
566
567 temp_var = set_if_not ("HOSTNAME", current_host_name);
568}
569
d166f048
JA
570/* Set $HOME to the information in the password file if we didn't get
571 it from the environment. */
b72432fd
JA
572
573/* This function is not static so the tilde and readline libraries can
574 use it. */
575char *
28ef6c31 576sh_get_home_dir ()
b72432fd
JA
577{
578 if (current_user.home_dir == 0)
579 get_current_user_info ();
580 return current_user.home_dir;
581}
582
d166f048
JA
583static void
584set_home_var ()
585{
586 SHELL_VAR *temp_var;
587
588 temp_var = find_variable ("HOME");
589 if (temp_var == 0)
95732b49 590 temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
f73dda09 591#if 0
bb70624e 592 VSETATTR (temp_var, att_exported);
f73dda09 593#endif
d166f048
JA
594}
595
596/* Set $SHELL to the user's login shell if it is not already set. Call
597 get_current_user_info if we haven't already fetched the shell. */
598static void
599set_shell_var ()
600{
601 SHELL_VAR *temp_var;
602
603 temp_var = find_variable ("SHELL");
604 if (temp_var == 0)
605 {
606 if (current_user.shell == 0)
607 get_current_user_info ();
95732b49 608 temp_var = bind_variable ("SHELL", current_user.shell, 0);
d166f048 609 }
f73dda09 610#if 0
bb70624e 611 VSETATTR (temp_var, att_exported);
f73dda09 612#endif
d166f048
JA
613}
614
615static char *
616get_bash_name ()
617{
618 char *name;
619
28ef6c31 620 if ((login_shell == 1) && RELPATH(shell_name))
d166f048
JA
621 {
622 if (current_user.shell == 0)
28ef6c31 623 get_current_user_info ();
d166f048
JA
624 name = savestring (current_user.shell);
625 }
28ef6c31 626 else if (ABSPATH(shell_name))
d166f048
JA
627 name = savestring (shell_name);
628 else if (shell_name[0] == '.' && shell_name[1] == '/')
629 {
630 /* Fast path for common case. */
631 char *cdir;
632 int len;
633
634 cdir = get_string_value ("PWD");
28ef6c31
JA
635 if (cdir)
636 {
637 len = strlen (cdir);
f73dda09 638 name = (char *)xmalloc (len + strlen (shell_name) + 1);
28ef6c31
JA
639 strcpy (name, cdir);
640 strcpy (name + len, shell_name + 1);
641 }
642 else
643 name = savestring (shell_name);
d166f048
JA
644 }
645 else
646 {
647 char *tname;
648 int s;
649
650 tname = find_user_command (shell_name);
651
652 if (tname == 0)
653 {
654 /* Try the current directory. If there is not an executable
655 there, just punt and use the login shell. */
656 s = file_status (shell_name);
657 if (s & FS_EXECABLE)
658 {
659 tname = make_absolute (shell_name, get_string_value ("PWD"));
660 if (*shell_name == '.')
661 {
28ef6c31 662 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
d166f048
JA
663 if (name == 0)
664 name = tname;
665 else
666 free (tname);
667 }
668 else
669 name = tname;
670 }
671 else
672 {
673 if (current_user.shell == 0)
674 get_current_user_info ();
675 name = savestring (current_user.shell);
676 }
677 }
678 else
679 {
680 name = full_pathname (tname);
681 free (tname);
682 }
683 }
684
685 return (name);
686}
687
726f6388
JA
688void
689adjust_shell_level (change)
690 int change;
691{
d166f048 692 char new_level[5], *old_SHLVL;
7117c2d2 693 intmax_t old_level;
d166f048 694 SHELL_VAR *temp_var;
726f6388
JA
695
696 old_SHLVL = get_string_value ("SHLVL");
f73dda09
JA
697 if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
698 old_level = 0;
726f6388
JA
699
700 shell_level = old_level + change;
701 if (shell_level < 0)
702 shell_level = 0;
d166f048
JA
703 else if (shell_level > 1000)
704 {
b80f6443 705 internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
d166f048
JA
706 shell_level = 1;
707 }
708
709 /* We don't need the full generality of itos here. */
710 if (shell_level < 10)
711 {
712 new_level[0] = shell_level + '0';
713 new_level[1] = '\0';
714 }
715 else if (shell_level < 100)
716 {
717 new_level[0] = (shell_level / 10) + '0';
718 new_level[1] = (shell_level % 10) + '0';
719 new_level[2] = '\0';
720 }
721 else if (shell_level < 1000)
722 {
723 new_level[0] = (shell_level / 100) + '0';
724 old_level = shell_level % 100;
725 new_level[1] = (old_level / 10) + '0';
726 new_level[2] = (old_level % 10) + '0';
727 new_level[3] = '\0';
728 }
729
95732b49 730 temp_var = bind_variable ("SHLVL", new_level, 0);
d166f048
JA
731 set_auto_export (temp_var);
732}
733
734static void
735initialize_shell_level ()
736{
d166f048 737 adjust_shell_level (1);
726f6388
JA
738}
739
28ef6c31
JA
740/* If we got PWD from the environment, update our idea of the current
741 working directory. In any case, make sure that PWD exists before
742 checking it. It is possible for getcwd () to fail on shell startup,
743 and in that case, PWD would be undefined. If this is an interactive
744 login shell, see if $HOME is the current working directory, and if
745 that's not the same string as $PWD, set PWD=$HOME. */
746
747void
748set_pwd ()
749{
750 SHELL_VAR *temp_var, *home_var;
751 char *temp_string, *home_string;
752
753 home_var = find_variable ("HOME");
754 home_string = home_var ? value_cell (home_var) : (char *)NULL;
755
756 temp_var = find_variable ("PWD");
757 if (temp_var && imported_p (temp_var) &&
758 (temp_string = value_cell (temp_var)) &&
759 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
760 set_working_directory (temp_string);
761 else if (home_string && interactive_shell && login_shell &&
762 same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
763 {
764 set_working_directory (home_string);
95732b49 765 temp_var = bind_variable ("PWD", home_string, 0);
28ef6c31
JA
766 set_auto_export (temp_var);
767 }
768 else
769 {
770 temp_string = get_working_directory ("shell-init");
771 if (temp_string)
772 {
95732b49 773 temp_var = bind_variable ("PWD", temp_string, 0);
28ef6c31
JA
774 set_auto_export (temp_var);
775 free (temp_string);
776 }
777 }
778
779 /* According to the Single Unix Specification, v2, $OLDPWD is an
780 `environment variable' and therefore should be auto-exported.
781 Make a dummy invisible variable for OLDPWD, and mark it as exported. */
95732b49 782 temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
28ef6c31
JA
783 VSETATTR (temp_var, (att_exported | att_invisible));
784}
785
b72432fd
JA
786/* Make a variable $PPID, which holds the pid of the shell's parent. */
787void
788set_ppid ()
789{
f73dda09 790 char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
b72432fd
JA
791 SHELL_VAR *temp_var;
792
f73dda09 793 name = inttostr (getppid (), namebuf, sizeof(namebuf));
b72432fd
JA
794 temp_var = find_variable ("PPID");
795 if (temp_var)
bb70624e 796 VUNSETATTR (temp_var, (att_readonly | att_exported));
95732b49 797 temp_var = bind_variable ("PPID", name, 0);
bb70624e 798 VSETATTR (temp_var, (att_readonly | att_integer));
b72432fd
JA
799}
800
ccc6cda3
JA
801static void
802uidset ()
726f6388 803{
f73dda09 804 char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
ccc6cda3
JA
805 register SHELL_VAR *v;
806
b72432fd 807 b = inttostr (current_user.uid, buff, sizeof (buff));
ccc6cda3 808 v = find_variable ("UID");
28ef6c31
JA
809 if (v == 0)
810 {
95732b49 811 v = bind_variable ("UID", b, 0);
28ef6c31
JA
812 VSETATTR (v, (att_readonly | att_integer));
813 }
726f6388 814
ccc6cda3 815 if (current_user.euid != current_user.uid)
b72432fd 816 b = inttostr (current_user.euid, buff, sizeof (buff));
726f6388 817
ccc6cda3 818 v = find_variable ("EUID");
28ef6c31
JA
819 if (v == 0)
820 {
95732b49 821 v = bind_variable ("EUID", b, 0);
28ef6c31
JA
822 VSETATTR (v, (att_readonly | att_integer));
823 }
ccc6cda3
JA
824}
825
826#if defined (ARRAY_VARS)
827static void
828make_vers_array ()
829{
830 SHELL_VAR *vv;
831 ARRAY *av;
f73dda09 832 char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
ccc6cda3 833
7117c2d2 834 unbind_variable ("BASH_VERSINFO");
ccc6cda3
JA
835
836 vv = make_new_array_variable ("BASH_VERSINFO");
837 av = array_cell (vv);
838 strcpy (d, dist_version);
7117c2d2 839 s = xstrchr (d, '.');
ccc6cda3
JA
840 if (s)
841 *s++ = '\0';
7117c2d2
JA
842 array_insert (av, 0, d);
843 array_insert (av, 1, s);
f73dda09 844 s = inttostr (patch_level, b, sizeof (b));
7117c2d2 845 array_insert (av, 2, s);
f73dda09 846 s = inttostr (build_version, b, sizeof (b));
7117c2d2
JA
847 array_insert (av, 3, s);
848 array_insert (av, 4, release_status);
849 array_insert (av, 5, MACHTYPE);
ccc6cda3 850
bb70624e 851 VSETATTR (vv, att_readonly);
ccc6cda3
JA
852}
853#endif /* ARRAY_VARS */
854
855/* Set the environment variables $LINES and $COLUMNS in response to
856 a window size change. */
857void
28ef6c31 858sh_set_lines_and_columns (lines, cols)
ccc6cda3
JA
859 int lines, cols;
860{
f73dda09 861 char val[INT_STRLEN_BOUND(int) + 1], *v;
ccc6cda3 862
95732b49
JA
863 /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
864 if (winsize_assignment)
865 return;
866
b72432fd 867 v = inttostr (lines, val, sizeof (val));
95732b49 868 bind_variable ("LINES", v, 0);
ccc6cda3 869
b72432fd 870 v = inttostr (cols, val, sizeof (val));
95732b49 871 bind_variable ("COLUMNS", v, 0);
726f6388
JA
872}
873
7117c2d2
JA
874/* **************************************************************** */
875/* */
876/* Printing variables and values */
877/* */
878/* **************************************************************** */
726f6388 879
28ef6c31
JA
880/* Print LIST (a list of shell variables) to stdout in such a way that
881 they can be read back in. */
726f6388
JA
882void
883print_var_list (list)
884 register SHELL_VAR **list;
885{
886 register int i;
887 register SHELL_VAR *var;
888
889 for (i = 0; list && (var = list[i]); i++)
7117c2d2 890 if (invisible_p (var) == 0)
726f6388
JA
891 print_assignment (var);
892}
893
28ef6c31
JA
894/* Print LIST (a list of shell functions) to stdout in such a way that
895 they can be read back in. */
896void
897print_func_list (list)
898 register SHELL_VAR **list;
899{
900 register int i;
901 register SHELL_VAR *var;
902
903 for (i = 0; list && (var = list[i]); i++)
904 {
905 printf ("%s ", var->name);
906 print_var_function (var);
907 printf ("\n");
908 }
909}
910
726f6388
JA
911/* Print the value of a single SHELL_VAR. No newline is
912 output, but the variable is printed in such a way that
913 it can be read back in. */
914void
915print_assignment (var)
916 SHELL_VAR *var;
917{
7117c2d2
JA
918 if (var_isset (var) == 0)
919 return;
920
921 if (function_p (var))
726f6388 922 {
28ef6c31 923 printf ("%s", var->name);
726f6388
JA
924 print_var_function (var);
925 printf ("\n");
926 }
ccc6cda3 927#if defined (ARRAY_VARS)
7117c2d2 928 else if (array_p (var))
ccc6cda3
JA
929 print_array_assignment (var, 0);
930#endif /* ARRAY_VARS */
7117c2d2 931 else
726f6388
JA
932 {
933 printf ("%s=", var->name);
ccc6cda3 934 print_var_value (var, 1);
726f6388
JA
935 printf ("\n");
936 }
937}
938
939/* Print the value cell of VAR, a shell variable. Do not print
ccc6cda3
JA
940 the name, nor leading/trailing newline. If QUOTE is non-zero,
941 and the value contains shell metacharacters, quote the value
942 in such a way that it can be read back in. */
726f6388 943void
ccc6cda3 944print_var_value (var, quote)
726f6388 945 SHELL_VAR *var;
ccc6cda3 946 int quote;
726f6388 947{
ccc6cda3
JA
948 char *t;
949
7117c2d2
JA
950 if (var_isset (var) == 0)
951 return;
952
953 if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
ccc6cda3 954 {
7117c2d2
JA
955 t = ansic_quote (value_cell (var), 0, (int *)0);
956 printf ("%s", t);
957 free (t);
958 }
959 else if (quote && sh_contains_shell_metas (value_cell (var)))
960 {
961 t = sh_single_quote (value_cell (var));
962 printf ("%s", t);
963 free (t);
ccc6cda3 964 }
7117c2d2
JA
965 else
966 printf ("%s", value_cell (var));
726f6388
JA
967}
968
969/* Print the function cell of VAR, a shell variable. Do not
970 print the name, nor leading/trailing newline. */
971void
972print_var_function (var)
973 SHELL_VAR *var;
974{
7117c2d2 975 if (function_p (var) && var_isset (var))
726f6388
JA
976 printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
977}
978
979/* **************************************************************** */
ccc6cda3 980/* */
7117c2d2 981/* Dynamic Variables */
ccc6cda3 982/* */
726f6388
JA
983/* **************************************************************** */
984
985/* DYNAMIC VARIABLES
ccc6cda3 986
726f6388
JA
987 These are variables whose values are generated anew each time they are
988 referenced. These are implemented using a pair of function pointers
7117c2d2
JA
989 in the struct variable: assign_func, which is called from bind_variable
990 and, if arrays are compiled into the shell, some of the functions in
991 arrayfunc.c, and dynamic_value, which is called from find_variable.
992
993 assign_func is called from bind_variable_internal, if
994 bind_variable_internal discovers that the variable being assigned to
995 has such a function. The function is called as
996 SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
726f6388 997 and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
7117c2d2
JA
998 is usually ENTRY (self). IND is an index for an array variable, and
999 unused otherwise.
ccc6cda3 1000
7117c2d2
JA
1001 dynamic_value is called from find_variable_internal to return a `new'
1002 value for the specified dynamic varible. If this function is NULL,
1003 the variable is treated as a `normal' shell variable. If it is not,
1004 however, then this function is called like this:
1005 tempvar = (*(var->dynamic_value)) (var);
ccc6cda3 1006
726f6388
JA
1007 Sometimes `tempvar' will replace the value of `var'. Other times, the
1008 shell will simply use the string value. Pretty object-oriented, huh?
ccc6cda3 1009
726f6388
JA
1010 Be warned, though: if you `unset' a special variable, it loses its
1011 special meaning, even if you subsequently set it.
ccc6cda3 1012
726f6388 1013 The special assignment code would probably have been better put in
7117c2d2 1014 subst.c: do_assignment_internal, in the same style as
726f6388
JA
1015 stupidly_hack_special_variables, but I wanted the changes as
1016 localized as possible. */
1017
f73dda09
JA
1018#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1019 do \
1020 { \
95732b49 1021 v = bind_variable (var, (val), 0); \
f73dda09
JA
1022 v->dynamic_value = gfunc; \
1023 v->assign_func = afunc; \
1024 } \
1025 while (0)
1026
1027#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1028 do \
1029 { \
1030 v = make_new_array_variable (var); \
1031 v->dynamic_value = gfunc; \
1032 v->assign_func = afunc; \
1033 } \
1034 while (0)
1035
bb70624e 1036static SHELL_VAR *
7117c2d2 1037null_assign (self, value, unused)
bb70624e
JA
1038 SHELL_VAR *self;
1039 char *value;
7117c2d2 1040 arrayind_t unused;
bb70624e
JA
1041{
1042 return (self);
1043}
1044
1045#if defined (ARRAY_VARS)
1046static SHELL_VAR *
7117c2d2 1047null_array_assign (self, value, ind)
bb70624e 1048 SHELL_VAR *self;
bb70624e 1049 char *value;
7117c2d2 1050 arrayind_t ind;
bb70624e
JA
1051{
1052 return (self);
1053}
1054#endif
1055
b80f6443
JA
1056/* Degenerate `dynamic_value' function; just returns what's passed without
1057 manipulation. */
1058static SHELL_VAR *
1059get_self (self)
1060 SHELL_VAR *self;
1061{
1062 return (self);
1063}
1064
1065#if defined (ARRAY_VARS)
1066/* A generic dynamic array variable initializer. Intialize array variable
1067 NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1068static SHELL_VAR *
1069init_dynamic_array_var (name, getfunc, setfunc, attrs)
1070 char *name;
1071 sh_var_value_func_t *getfunc;
1072 sh_var_assign_func_t *setfunc;
1073 int attrs;
1074{
1075 SHELL_VAR *v;
1076
1077 v = find_variable (name);
1078 if (v)
1079 return (v);
1080 INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1081 if (attrs)
1082 VSETATTR (v, attrs);
1083 return v;
1084}
1085#endif
1086
1087
726f6388
JA
1088/* The value of $SECONDS. This is the number of seconds since shell
1089 invocation, or, the number of seconds since the last assignment + the
1090 value of the last assignment. */
7117c2d2 1091static intmax_t seconds_value_assigned;
726f6388
JA
1092
1093static SHELL_VAR *
7117c2d2 1094assign_seconds (self, value, unused)
726f6388
JA
1095 SHELL_VAR *self;
1096 char *value;
7117c2d2 1097 arrayind_t unused;
726f6388 1098{
f73dda09
JA
1099 if (legal_number (value, &seconds_value_assigned) == 0)
1100 seconds_value_assigned = 0;
726f6388
JA
1101 shell_start_time = NOW;
1102 return (self);
1103}
1104
1105static SHELL_VAR *
1106get_seconds (var)
1107 SHELL_VAR *var;
1108{
1109 time_t time_since_start;
1110 char *p;
1111
1112 time_since_start = NOW - shell_start_time;
f73dda09 1113 p = itos(seconds_value_assigned + time_since_start);
726f6388 1114
7117c2d2 1115 FREE (value_cell (var));
726f6388 1116
bb70624e 1117 VSETATTR (var, att_integer);
7117c2d2 1118 var_setvalue (var, p);
726f6388
JA
1119 return (var);
1120}
1121
f73dda09
JA
1122static SHELL_VAR *
1123init_seconds_var ()
1124{
1125 SHELL_VAR *v;
1126
1127 v = find_variable ("SECONDS");
1128 if (v)
1129 {
1130 if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1131 seconds_value_assigned = 0;
1132 }
7117c2d2 1133 INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
f73dda09
JA
1134 return v;
1135}
1136
726f6388
JA
1137/* The random number seed. You can change this by setting RANDOM. */
1138static unsigned long rseed = 1;
f73dda09 1139static int last_random_value;
95732b49 1140static int seeded_subshell = 0;
726f6388 1141
f73dda09 1142/* A linear congruential random number generator based on the example
7117c2d2 1143 one in the ANSI C standard. This one isn't very good, but a more
f73dda09 1144 complicated one is overkill. */
726f6388
JA
1145
1146/* Returns a pseudo-random number between 0 and 32767. */
1147static int
1148brand ()
1149{
1150 rseed = rseed * 1103515245 + 12345;
f73dda09 1151 return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
726f6388
JA
1152}
1153
1154/* Set the random number generator seed to SEED. */
1155static void
1156sbrand (seed)
f73dda09 1157 unsigned long seed;
726f6388
JA
1158{
1159 rseed = seed;
e8ce775d 1160 last_random_value = 0;
726f6388
JA
1161}
1162
1163static SHELL_VAR *
7117c2d2 1164assign_random (self, value, unused)
726f6388
JA
1165 SHELL_VAR *self;
1166 char *value;
7117c2d2 1167 arrayind_t unused;
726f6388 1168{
f73dda09 1169 sbrand (strtoul (value, (char **)NULL, 10));
95732b49
JA
1170 if (subshell_environment)
1171 seeded_subshell = 1;
726f6388
JA
1172 return (self);
1173}
1174
28ef6c31
JA
1175int
1176get_random_number ()
726f6388
JA
1177{
1178 int rv;
726f6388 1179
ccc6cda3 1180 /* Reset for command and process substitution. */
95732b49
JA
1181 if (subshell_environment && seeded_subshell == 0)
1182 {
1183 sbrand (rseed + getpid() + NOW);
1184 seeded_subshell = 1;
1185 }
ccc6cda3
JA
1186
1187 do
1188 rv = brand ();
f73dda09 1189 while (rv == last_random_value);
28ef6c31
JA
1190 return rv;
1191}
ccc6cda3 1192
28ef6c31
JA
1193static SHELL_VAR *
1194get_random (var)
1195 SHELL_VAR *var;
1196{
1197 int rv;
1198 char *p;
1199
1200 rv = get_random_number ();
ccc6cda3 1201 last_random_value = rv;
f73dda09 1202 p = itos (rv);
726f6388 1203
7117c2d2 1204 FREE (value_cell (var));
726f6388 1205
bb70624e 1206 VSETATTR (var, att_integer);
7117c2d2 1207 var_setvalue (var, p);
726f6388
JA
1208 return (var);
1209}
1210
7117c2d2
JA
1211static SHELL_VAR *
1212assign_lineno (var, value, unused)
1213 SHELL_VAR *var;
1214 char *value;
1215 arrayind_t unused;
1216{
1217 intmax_t new_value;
1218
1219 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1220 new_value = 0;
1221 line_number = new_value;
1222 return var;
1223}
1224
726f6388
JA
1225/* Function which returns the current line number. */
1226static SHELL_VAR *
1227get_lineno (var)
1228 SHELL_VAR *var;
1229{
1230 char *p;
ccc6cda3 1231 int ln;
726f6388 1232
ccc6cda3
JA
1233 ln = executing_line_number ();
1234 p = itos (ln);
7117c2d2
JA
1235 FREE (value_cell (var));
1236 var_setvalue (var, p);
726f6388
JA
1237 return (var);
1238}
1239
b80f6443
JA
1240static SHELL_VAR *
1241assign_subshell (var, value, unused)
1242 SHELL_VAR *var;
1243 char *value;
1244 arrayind_t unused;
1245{
1246 intmax_t new_value;
1247
1248 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1249 new_value = 0;
1250 subshell_level = new_value;
1251 return var;
1252}
1253
1254static SHELL_VAR *
1255get_subshell (var)
1256 SHELL_VAR *var;
1257{
1258 char *p;
1259
1260 p = itos (subshell_level);
1261 FREE (value_cell (var));
1262 var_setvalue (var, p);
1263 return (var);
1264}
1265
1266static SHELL_VAR *
1267get_bash_command (var)
1268 SHELL_VAR *var;
1269{
1270 char *p;
1271
95732b49
JA
1272
1273 if (the_printed_command_except_trap)
1274 p = savestring (the_printed_command_except_trap);
1275 else
1276 {
1277 p = (char *)xmalloc (1);
1278 p[0] = '\0';
1279 }
b80f6443
JA
1280 FREE (value_cell (var));
1281 var_setvalue (var, p);
1282 return (var);
1283}
1284
726f6388
JA
1285#if defined (HISTORY)
1286static SHELL_VAR *
1287get_histcmd (var)
1288 SHELL_VAR *var;
1289{
1290 char *p;
1291
1292 p = itos (history_number ());
7117c2d2
JA
1293 FREE (value_cell (var));
1294 var_setvalue (var, p);
726f6388
JA
1295 return (var);
1296}
1297#endif
1298
b80f6443
JA
1299#if defined (READLINE)
1300/* When this function returns, VAR->value points to malloced memory. */
1301static SHELL_VAR *
1302get_comp_wordbreaks (var)
1303 SHELL_VAR *var;
1304{
1305 char *p;
1306
1307 /* If we don't have anything yet, assign a default value. */
1308 if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1309 enable_hostname_completion (perform_hostname_completion);
1310
1311#if 0
1312 FREE (value_cell (var));
1313 p = savestring (rl_completer_word_break_characters);
1314
1315 var_setvalue (var, p);
1316#else
1317 var_setvalue (var, rl_completer_word_break_characters);
1318#endif
1319
1320 return (var);
1321}
1322
1323/* When this function returns, rl_completer_word_break_characters points to
1324 malloced memory. */
1325static SHELL_VAR *
1326assign_comp_wordbreaks (self, value, unused)
1327 SHELL_VAR *self;
1328 char *value;
1329 arrayind_t unused;
1330{
1331 if (rl_completer_word_break_characters &&
1332 rl_completer_word_break_characters != rl_basic_word_break_characters)
1333 free (rl_completer_word_break_characters);
1334
1335 rl_completer_word_break_characters = savestring (value);
1336 return self;
1337}
1338#endif /* READLINE */
1339
ccc6cda3 1340#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
b80f6443 1341static SHELL_VAR *
7117c2d2
JA
1342assign_dirstack (self, value, ind)
1343 SHELL_VAR *self;
1344 char *value;
1345 arrayind_t ind;
1346{
1347 set_dirstack_element (ind, 1, value);
1348 return self;
1349}
1350
ccc6cda3
JA
1351static SHELL_VAR *
1352get_dirstack (self)
1353 SHELL_VAR *self;
1354{
1355 ARRAY *a;
1356 WORD_LIST *l;
1357
1358 l = get_directory_stack ();
7117c2d2
JA
1359 a = array_from_word_list (l);
1360 array_dispose (array_cell (self));
d166f048 1361 dispose_words (l);
7117c2d2 1362 var_setarray (self, a);
ccc6cda3
JA
1363 return self;
1364}
1365#endif /* PUSHD AND POPD && ARRAY_VARS */
1366
d166f048
JA
1367#if defined (ARRAY_VARS)
1368/* We don't want to initialize the group set with a call to getgroups()
1369 unless we're asked to, but we only want to do it once. */
1370static SHELL_VAR *
1371get_groupset (self)
1372 SHELL_VAR *self;
1373{
1374 register int i;
1375 int ng;
1376 ARRAY *a;
1377 static char **group_set = (char **)NULL;
1378
1379 if (group_set == 0)
1380 {
1381 group_set = get_group_list (&ng);
1382 a = array_cell (self);
1383 for (i = 0; i < ng; i++)
7117c2d2 1384 array_insert (a, i, group_set[i]);
d166f048
JA
1385 }
1386 return (self);
1387}
1388#endif /* ARRAY_VARS */
bb70624e 1389
b80f6443
JA
1390/* If ARRAY_VARS is not defined, this just returns the name of any
1391 currently-executing function. If we have arrays, it's a call stack. */
bb70624e
JA
1392static SHELL_VAR *
1393get_funcname (self)
1394 SHELL_VAR *self;
1395{
b80f6443 1396#if ! defined (ARRAY_VARS)
7117c2d2 1397 char *t;
bb70624e
JA
1398 if (variable_context && this_shell_function)
1399 {
7117c2d2
JA
1400 FREE (value_cell (self));
1401 t = savestring (this_shell_function->name);
1402 var_setvalue (self, t);
bb70624e 1403 }
b80f6443 1404#endif
bb70624e
JA
1405 return (self);
1406}
1407
1408void
1409make_funcname_visible (on_or_off)
1410 int on_or_off;
726f6388
JA
1411{
1412 SHELL_VAR *v;
1413
bb70624e
JA
1414 v = find_variable ("FUNCNAME");
1415 if (v == 0 || v->dynamic_value == 0)
1416 return;
1417
1418 if (on_or_off)
1419 VUNSETATTR (v, att_invisible);
1420 else
1421 VSETATTR (v, att_invisible);
1422}
1423
f73dda09
JA
1424static SHELL_VAR *
1425init_funcname_var ()
1426{
1427 SHELL_VAR *v;
bb70624e 1428
f73dda09
JA
1429 v = find_variable ("FUNCNAME");
1430 if (v)
1431 return v;
b80f6443
JA
1432#if defined (ARRAY_VARS)
1433 INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1434#else
f73dda09 1435 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
b80f6443 1436#endif
f73dda09
JA
1437 VSETATTR (v, att_invisible|att_noassign);
1438 return v;
1439}
726f6388 1440
bb70624e
JA
1441static void
1442initialize_dynamic_variables ()
1443{
1444 SHELL_VAR *v;
726f6388 1445
f73dda09
JA
1446 v = init_seconds_var ();
1447
b80f6443
JA
1448 INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1449 INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1450
bb70624e 1451 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
95732b49 1452 VSETATTR (v, att_integer);
bb70624e 1453 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
95732b49 1454 VSETATTR (v, att_integer);
726f6388
JA
1455
1456#if defined (HISTORY)
7117c2d2 1457 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
95732b49 1458 VSETATTR (v, att_integer);
726f6388 1459#endif
ccc6cda3 1460
b80f6443
JA
1461#if defined (READLINE)
1462 INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1463#endif
1464
ccc6cda3 1465#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
b80f6443 1466 v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
ccc6cda3 1467#endif /* PUSHD_AND_POPD && ARRAY_VARS */
d166f048
JA
1468
1469#if defined (ARRAY_VARS)
b80f6443
JA
1470 v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1471
1472# if defined (DEBUGGER)
95732b49
JA
1473 v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
1474 v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
b80f6443 1475# endif /* DEBUGGER */
95732b49
JA
1476 v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
1477 v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
d166f048 1478#endif
bb70624e 1479
f73dda09 1480 v = init_funcname_var ();
726f6388
JA
1481}
1482
7117c2d2
JA
1483/* **************************************************************** */
1484/* */
1485/* Retrieving variables and values */
1486/* */
1487/* **************************************************************** */
1488
726f6388
JA
1489/* How to get a pointer to the shell variable or function named NAME.
1490 HASHED_VARS is a pointer to the hash table containing the list
1491 of interest (either variables or functions). */
7117c2d2
JA
1492
1493static SHELL_VAR *
1494hash_lookup (name, hashed_vars)
f73dda09 1495 const char *name;
726f6388
JA
1496 HASH_TABLE *hashed_vars;
1497{
1498 BUCKET_CONTENTS *bucket;
1499
7117c2d2 1500 bucket = hash_search (name, hashed_vars, 0);
ccc6cda3 1501 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
726f6388
JA
1502}
1503
7117c2d2
JA
1504SHELL_VAR *
1505var_lookup (name, vcontext)
1506 const char *name;
1507 VAR_CONTEXT *vcontext;
1508{
1509 VAR_CONTEXT *vc;
1510 SHELL_VAR *v;
1511
1512 v = (SHELL_VAR *)NULL;
1513 for (vc = vcontext; vc; vc = vc->down)
1514 if (v = hash_lookup (name, vc->table))
1515 break;
1516
1517 return v;
1518}
1519
726f6388 1520/* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
7117c2d2
JA
1521 then also search the temporarily built list of exported variables.
1522 The lookup order is:
1523 temporary_env
1524 shell_variables list
1525*/
1526
726f6388 1527SHELL_VAR *
b80f6443 1528find_variable_internal (name, force_tempenv)
f73dda09 1529 const char *name;
b80f6443 1530 int force_tempenv;
726f6388 1531{
28ef6c31 1532 SHELL_VAR *var;
b80f6443 1533 int search_tempenv;
28ef6c31
JA
1534
1535 var = (SHELL_VAR *)NULL;
726f6388
JA
1536
1537 /* If explicitly requested, first look in the temporary environment for
1538 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
1539 to get the `exported' value of $foo. This happens if we are executing
1540 a function or builtin, or if we are looking up a variable in a
1541 "subshell environment". */
b80f6443
JA
1542 search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1543
1544 if (search_tempenv && temporary_env)
7117c2d2 1545 var = hash_lookup (name, temporary_env);
726f6388 1546
7117c2d2 1547 if (var == 0)
726f6388
JA
1548 var = var_lookup (name, shell_variables);
1549
7117c2d2 1550 if (var == 0)
726f6388
JA
1551 return ((SHELL_VAR *)NULL);
1552
ccc6cda3 1553 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
726f6388
JA
1554}
1555
1556/* Look up the variable entry named NAME. Returns the entry or NULL. */
1557SHELL_VAR *
1558find_variable (name)
f73dda09 1559 const char *name;
726f6388 1560{
b80f6443 1561 return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
726f6388
JA
1562}
1563
1564/* Look up the function entry whose name matches STRING.
1565 Returns the entry or NULL. */
1566SHELL_VAR *
1567find_function (name)
f73dda09 1568 const char *name;
726f6388 1569{
7117c2d2
JA
1570 return (hash_lookup (name, shell_functions));
1571}
1572
b80f6443
JA
1573/* Find the function definition for the shell function named NAME. Returns
1574 the entry or NULL. */
1575FUNCTION_DEF *
1576find_function_def (name)
1577 const char *name;
1578{
1579 return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
1580}
1581
7117c2d2
JA
1582/* Return the value of VAR. VAR is assumed to have been the result of a
1583 lookup without any subscript, if arrays are compiled into the shell. */
1584char *
1585get_variable_value (var)
1586 SHELL_VAR *var;
1587{
1588 if (var == 0)
1589 return ((char *)NULL);
1590#if defined (ARRAY_VARS)
1591 else if (array_p (var))
1592 return (array_reference (array_cell (var), 0));
1593#endif
1594 else
1595 return (value_cell (var));
726f6388
JA
1596}
1597
1598/* Return the string value of a variable. Return NULL if the variable
7117c2d2
JA
1599 doesn't exist. Don't cons a new string. This is a potential memory
1600 leak if the variable is found in the temporary environment. Since
1601 functions and variables have separate name spaces, returns NULL if
1602 var_name is a shell function only. */
726f6388
JA
1603char *
1604get_string_value (var_name)
28ef6c31 1605 const char *var_name;
726f6388 1606{
d166f048
JA
1607 SHELL_VAR *var;
1608
f73dda09 1609 var = find_variable (var_name);
7117c2d2 1610 return ((var) ? get_variable_value (var) : (char *)NULL);
726f6388
JA
1611}
1612
b72432fd
JA
1613/* This is present for use by the tilde and readline libraries. */
1614char *
28ef6c31
JA
1615sh_get_env_value (v)
1616 const char *v;
b72432fd
JA
1617{
1618 return get_string_value (v);
1619}
1620
7117c2d2
JA
1621/* **************************************************************** */
1622/* */
1623/* Creating and setting variables */
1624/* */
1625/* **************************************************************** */
1626
1627/* Set NAME to VALUE if NAME has no value. */
1628SHELL_VAR *
1629set_if_not (name, value)
1630 char *name, *value;
1631{
1632 SHELL_VAR *v;
1633
1634 v = find_variable (name);
1635 if (v == 0)
95732b49 1636 v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
7117c2d2
JA
1637 return (v);
1638}
1639
726f6388
JA
1640/* Create a local variable referenced by NAME. */
1641SHELL_VAR *
1642make_local_variable (name)
f73dda09 1643 const char *name;
726f6388
JA
1644{
1645 SHELL_VAR *new_var, *old_var;
7117c2d2
JA
1646 VAR_CONTEXT *vc;
1647 int was_tmpvar;
1648 char *tmp_value;
726f6388
JA
1649
1650 /* local foo; local foo; is a no-op. */
1651 old_var = find_variable (name);
7117c2d2 1652 if (old_var && local_p (old_var) && old_var->context == variable_context)
eb873671
JA
1653 {
1654 VUNSETATTR (old_var, att_invisible);
1655 return (old_var);
1656 }
726f6388 1657
7117c2d2
JA
1658 was_tmpvar = old_var && tempvar_p (old_var);
1659 if (was_tmpvar)
1660 tmp_value = value_cell (old_var);
1661
1662 for (vc = shell_variables; vc; vc = vc->down)
1663 if (vc_isfuncenv (vc) && vc->scope == variable_context)
1664 break;
1665
1666 if (vc == 0)
1667 {
b80f6443 1668 internal_error (_("make_local_variable: no function context at current scope"));
7117c2d2
JA
1669 return ((SHELL_VAR *)NULL);
1670 }
1671 else if (vc->table == 0)
1672 vc->table = hash_create (TEMPENV_HASH_BUCKETS);
1673
bb70624e
JA
1674 /* Since this is called only from the local/declare/typeset code, we can
1675 call builtin_error here without worry (of course, it will also work
28ef6c31
JA
1676 for anything that sets this_command_name). Variables with the `noassign'
1677 attribute may not be made local. The test against old_var's context
1678 level is to disallow local copies of readonly global variables (since I
1679 believe that this could be a security hole). Readonly copies of calling
1680 function local variables are OK. */
1681 if (old_var && (noassign_p (old_var) ||
1682 (readonly_p (old_var) && old_var->context == 0)))
1683 {
1684 if (readonly_p (old_var))
7117c2d2 1685 sh_readonly (name);
bb70624e
JA
1686 return ((SHELL_VAR *)NULL);
1687 }
1688
d166f048 1689 if (old_var == 0)
95732b49 1690 new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH, 0);
726f6388
JA
1691 else
1692 {
7117c2d2 1693 new_var = make_new_variable (name, vc->table);
726f6388 1694
7117c2d2
JA
1695 /* If we found this variable in one of the temporary environments,
1696 inherit its value. Watch to see if this causes problems with
1697 things like `x=4 local x'. */
1698 if (was_tmpvar)
1699 var_setvalue (new_var, savestring (tmp_value));
726f6388 1700
ccc6cda3 1701 new_var->attributes = exported_p (old_var) ? att_exported : 0;
726f6388
JA
1702 }
1703
7117c2d2
JA
1704 vc->flags |= VC_HASLOCAL;
1705
726f6388 1706 new_var->context = variable_context;
bb70624e 1707 VSETATTR (new_var, att_local);
726f6388 1708
7117c2d2
JA
1709 if (ifsname (name))
1710 setifs (new_var);
726f6388
JA
1711
1712 return (new_var);
1713}
1714
ccc6cda3 1715#if defined (ARRAY_VARS)
726f6388 1716SHELL_VAR *
ccc6cda3
JA
1717make_local_array_variable (name)
1718 char *name;
1719{
1720 SHELL_VAR *var;
1721 ARRAY *array;
1722
1723 var = make_local_variable (name);
b80f6443 1724 if (var == 0 || array_p (var))
bb70624e 1725 return var;
b80f6443 1726
7117c2d2 1727 array = array_create ();
ccc6cda3
JA
1728
1729 FREE (value_cell(var));
7117c2d2 1730 var_setarray (var, array);
bb70624e 1731 VSETATTR (var, att_array);
ccc6cda3
JA
1732 return var;
1733}
1734#endif /* ARRAY_VARS */
1735
7117c2d2 1736/* Create a new shell variable with name NAME. */
f73dda09 1737static SHELL_VAR *
7117c2d2 1738new_shell_variable (name)
f73dda09 1739 const char *name;
726f6388 1740{
ccc6cda3 1741 SHELL_VAR *entry;
726f6388 1742
ccc6cda3 1743 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
726f6388 1744
ccc6cda3 1745 entry->name = savestring (name);
7117c2d2 1746 var_setvalue (entry, (char *)NULL);
bb70624e 1747 CLEAR_EXPORTSTR (entry);
726f6388 1748
7117c2d2
JA
1749 entry->dynamic_value = (sh_var_value_func_t *)NULL;
1750 entry->assign_func = (sh_var_assign_func_t *)NULL;
1751
1752 entry->attributes = 0;
ccc6cda3
JA
1753
1754 /* Always assume variables are to be made at toplevel!
1755 make_local_variable has the responsibilty of changing the
1756 variable context. */
1757 entry->context = 0;
7117c2d2
JA
1758
1759 return (entry);
1760}
1761
1762/* Create a new shell variable with name NAME and add it to the hash table
1763 TABLE. */
1764static SHELL_VAR *
1765make_new_variable (name, table)
1766 const char *name;
1767 HASH_TABLE *table;
1768{
1769 SHELL_VAR *entry;
1770 BUCKET_CONTENTS *elt;
1771
1772 entry = new_shell_variable (name);
ccc6cda3 1773
28ef6c31
JA
1774 /* Make sure we have a shell_variables hash table to add to. */
1775 if (shell_variables == 0)
7117c2d2
JA
1776 {
1777 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1778 shell_variables->scope = 0;
1779 shell_variables->table = hash_create (0);
1780 }
28ef6c31 1781
7117c2d2
JA
1782 elt = hash_insert (savestring (name), table, HASH_NOSRCH);
1783 elt->data = (PTR_T)entry;
ccc6cda3
JA
1784
1785 return entry;
1786}
1787
1788#if defined (ARRAY_VARS)
1789SHELL_VAR *
1790make_new_array_variable (name)
1791 char *name;
1792{
1793 SHELL_VAR *entry;
1794 ARRAY *array;
1795
7117c2d2
JA
1796 entry = make_new_variable (name, global_variables->table);
1797 array = array_create ();
1798 var_setarray (entry, array);
bb70624e 1799 VSETATTR (entry, att_array);
ccc6cda3
JA
1800 return entry;
1801}
1802#endif
1803
1804char *
95732b49 1805make_variable_value (var, value, flags)
ccc6cda3
JA
1806 SHELL_VAR *var;
1807 char *value;
95732b49 1808 int flags;
ccc6cda3 1809{
95732b49
JA
1810 char *retval, *oval;
1811 intmax_t lval, rval;
1812 int expok, olen;
ccc6cda3
JA
1813
1814 /* If this variable has had its type set to integer (via `declare -i'),
1815 then do expression evaluation on it and store the result. The
7117c2d2 1816 functions in expr.c (evalexp()) and bind_int_variable() are responsible
ccc6cda3
JA
1817 for turning off the integer flag if they don't want further
1818 evaluation done. */
1819 if (integer_p (var))
1820 {
95732b49
JA
1821 if (flags & ASS_APPEND)
1822 {
1823 oval = value_cell (var);
1824 lval = evalexp (oval, &expok); /* ksh93 seems to do this */
1825 if (expok == 0)
1826 jump_to_top_level (DISCARD);
1827 }
1828 rval = evalexp (value, &expok);
d166f048
JA
1829 if (expok == 0)
1830 jump_to_top_level (DISCARD);
95732b49
JA
1831 if (flags & ASS_APPEND)
1832 rval += lval;
1833 retval = itos (rval);
ccc6cda3
JA
1834 }
1835 else if (value)
1836 {
95732b49
JA
1837 if (flags & ASS_APPEND)
1838 {
1839 oval = get_variable_value (var);
1840 if (oval == 0) /* paranoia */
1841 oval = "";
1842 olen = STRLEN (oval);
1843 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
1844 strcpy (retval, oval);
1845 if (value)
1846 strcpy (retval+olen, value);
1847 }
1848 else if (*value)
ccc6cda3
JA
1849 retval = savestring (value);
1850 else
726f6388 1851 {
f73dda09 1852 retval = (char *)xmalloc (1);
ccc6cda3 1853 retval[0] = '\0';
726f6388 1854 }
ccc6cda3
JA
1855 }
1856 else
1857 retval = (char *)NULL;
726f6388 1858
ccc6cda3
JA
1859 return retval;
1860}
726f6388 1861
7117c2d2
JA
1862/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
1863 temporary environment (but usually is not). */
1864static SHELL_VAR *
95732b49 1865bind_variable_internal (name, value, table, hflags, aflags)
f73dda09
JA
1866 const char *name;
1867 char *value;
7117c2d2 1868 HASH_TABLE *table;
95732b49 1869 int hflags, aflags;
ccc6cda3
JA
1870{
1871 char *newval;
7117c2d2 1872 SHELL_VAR *entry;
28ef6c31 1873
7117c2d2 1874 entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
ccc6cda3
JA
1875
1876 if (entry == 0)
1877 {
7117c2d2 1878 entry = make_new_variable (name, table);
95732b49 1879 var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
726f6388 1880 }
28ef6c31 1881 else if (entry->assign_func) /* array vars have assign functions now */
bb70624e
JA
1882 {
1883 INVALIDATE_EXPORTSTR (entry);
95732b49
JA
1884 newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
1885 entry = (*(entry->assign_func)) (entry, newval, -1);
1886 if (newval != value)
1887 free (newval);
1888 return (entry);
bb70624e 1889 }
726f6388
JA
1890 else
1891 {
28ef6c31 1892 if (readonly_p (entry) || noassign_p (entry))
726f6388 1893 {
28ef6c31 1894 if (readonly_p (entry))
7117c2d2 1895 err_readonly (name);
726f6388
JA
1896 return (entry);
1897 }
1898
1899 /* Variables which are bound are visible. */
bb70624e 1900 VUNSETATTR (entry, att_invisible);
726f6388 1901
95732b49 1902 newval = make_variable_value (entry, value, aflags); /* XXX */
726f6388 1903
bb70624e
JA
1904 /* Invalidate any cached export string */
1905 INVALIDATE_EXPORTSTR (entry);
1906
ccc6cda3
JA
1907#if defined (ARRAY_VARS)
1908 /* XXX -- this bears looking at again -- XXX */
1909 /* If an existing array variable x is being assigned to with x=b or
1910 `read x' or something of that nature, silently convert it to
1911 x[0]=b or `read x[0]'. */
1912 if (array_p (entry))
d166f048 1913 {
7117c2d2 1914 array_insert (array_cell (entry), 0, newval);
d166f048
JA
1915 free (newval);
1916 }
726f6388 1917 else
f73dda09 1918#endif
726f6388 1919 {
7117c2d2
JA
1920 FREE (value_cell (entry));
1921 var_setvalue (entry, newval);
726f6388
JA
1922 }
1923 }
1924
1925 if (mark_modified_vars)
bb70624e 1926 VSETATTR (entry, att_exported);
726f6388
JA
1927
1928 if (exported_p (entry))
1929 array_needs_making = 1;
1930
1931 return (entry);
1932}
7117c2d2
JA
1933
1934/* Bind a variable NAME to VALUE. This conses up the name
1935 and value strings. If we have a temporary environment, we bind there
1936 first, then we bind into shell_variables. */
1937
1938SHELL_VAR *
95732b49 1939bind_variable (name, value, flags)
7117c2d2
JA
1940 const char *name;
1941 char *value;
95732b49 1942 int flags;
7117c2d2
JA
1943{
1944 SHELL_VAR *v;
1945 VAR_CONTEXT *vc;
1946
1947 if (shell_variables == 0)
1948 {
1949 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1950 shell_variables->scope = 0;
1951 shell_variables->table = hash_create (0);
1952 }
1953
1954 /* If we have a temporary environment, look there first for the variable,
1955 and, if found, modify the value there before modifying it in the
1956 shell_variables table. This allows sourced scripts to modify values
1957 given to them in a temporary environment while modifying the variable
1958 value that the caller sees. */
1959 if (temporary_env)
1960 bind_tempenv_variable (name, value);
1961
1962 /* XXX -- handle local variables here. */
1963 for (vc = shell_variables; vc; vc = vc->down)
1964 {
1965 if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
1966 {
1967 v = hash_lookup (name, vc->table);
1968 if (v)
95732b49 1969 return (bind_variable_internal (name, value, vc->table, 0, flags));
7117c2d2
JA
1970 }
1971 }
95732b49 1972 return (bind_variable_internal (name, value, global_variables->table, 0, flags));
7117c2d2 1973}
726f6388 1974
bb70624e
JA
1975/* Make VAR, a simple shell variable, have value VALUE. Once assigned a
1976 value, variables are no longer invisible. This is a duplicate of part
1977 of the internals of bind_variable. If the variable is exported, or
1978 all modified variables should be exported, mark the variable for export
1979 and note that the export environment needs to be recreated. */
1980SHELL_VAR *
95732b49 1981bind_variable_value (var, value, aflags)
bb70624e
JA
1982 SHELL_VAR *var;
1983 char *value;
95732b49 1984 int aflags;
bb70624e
JA
1985{
1986 char *t;
1987
1988 VUNSETATTR (var, att_invisible);
1989
95732b49
JA
1990 if (var->assign_func)
1991 {
1992 /* If we're appending, we need the old value, so use
1993 make_variable_value */
1994 t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
1995 (*(var->assign_func)) (var, t, -1);
1996 if (t != value && t)
1997 free (t);
1998 }
1999 else
2000 {
2001 t = make_variable_value (var, value, aflags);
2002 FREE (value_cell (var));
2003 var_setvalue (var, t);
2004 }
bb70624e
JA
2005
2006 INVALIDATE_EXPORTSTR (var);
2007
2008 if (mark_modified_vars)
2009 VSETATTR (var, att_exported);
2010
2011 if (exported_p (var))
2012 array_needs_making = 1;
2013
2014 return (var);
2015}
2016
2017/* Bind/create a shell variable with the name LHS to the RHS.
2018 This creates or modifies a variable such that it is an integer.
2019
2020 This used to be in expr.c, but it is here so that all of the
2021 variable binding stuff is localized. Since we don't want any
2022 recursive evaluation from bind_variable() (possible without this code,
2023 since bind_variable() calls the evaluator for variables with the integer
2024 attribute set), we temporarily turn off the integer attribute for each
2025 variable we set here, then turn it back on after binding as necessary. */
2026
2027SHELL_VAR *
2028bind_int_variable (lhs, rhs)
2029 char *lhs, *rhs;
2030{
2031 register SHELL_VAR *v;
7117c2d2
JA
2032 char *t;
2033 int isint, isarr;
2034
2035 isint = isarr = 0;
2036#if defined (ARRAY_VARS)
b80f6443 2037# if 0
7117c2d2 2038 if (t = xstrchr (lhs, '[')) /*]*/
b80f6443
JA
2039# else
2040 if (valid_array_reference (lhs))
2041# endif
7117c2d2
JA
2042 {
2043 isarr = 1;
2044 v = array_variable_part (lhs, (char **)0, (int *)0);
2045 }
2046 else
2047#endif
2048 v = find_variable (lhs);
bb70624e 2049
bb70624e
JA
2050 if (v)
2051 {
2052 isint = integer_p (v);
2053 VUNSETATTR (v, att_integer);
2054 }
2055
7117c2d2
JA
2056#if defined (ARRAY_VARS)
2057 if (isarr)
95732b49 2058 v = assign_array_element (lhs, rhs, 0);
7117c2d2
JA
2059 else
2060#endif
95732b49 2061 v = bind_variable (lhs, rhs, 0);
7117c2d2 2062
bb70624e
JA
2063 if (isint)
2064 VSETATTR (v, att_integer);
2065
2066 return (v);
2067}
2068
ccc6cda3 2069SHELL_VAR *
f73dda09
JA
2070bind_var_to_int (var, val)
2071 char *var;
7117c2d2 2072 intmax_t val;
ccc6cda3 2073{
7117c2d2 2074 char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
ccc6cda3 2075
f73dda09
JA
2076 p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
2077 return (bind_int_variable (var, p));
ccc6cda3
JA
2078}
2079
7117c2d2
JA
2080/* Do a function binding to a variable. You pass the name and
2081 the command to bind to. This conses the name and command. */
2082SHELL_VAR *
2083bind_function (name, value)
2084 const char *name;
2085 COMMAND *value;
2086{
2087 SHELL_VAR *entry;
2088
2089 entry = find_function (name);
2090 if (entry == 0)
2091 {
2092 BUCKET_CONTENTS *elt;
2093
2094 elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2095 entry = new_shell_variable (name);
2096 elt->data = (PTR_T)entry;
2097 }
2098 else
2099 INVALIDATE_EXPORTSTR (entry);
2100
2101 if (var_isset (entry))
2102 dispose_command (function_cell (entry));
2103
2104 if (value)
2105 var_setfunc (entry, copy_command (value));
2106 else
2107 var_setfunc (entry, 0);
2108
2109 VSETATTR (entry, att_function);
2110
2111 if (mark_modified_vars)
2112 VSETATTR (entry, att_exported);
2113
2114 VUNSETATTR (entry, att_invisible); /* Just to be sure */
2115
2116 if (exported_p (entry))
2117 array_needs_making = 1;
2118
2119#if defined (PROGRAMMABLE_COMPLETION)
2120 set_itemlist_dirty (&it_functions);
2121#endif
2122
2123 return (entry);
2124}
2125
b80f6443
JA
2126/* Bind a function definition, which includes source file and line number
2127 information in addition to the command, into the FUNCTION_DEF hash table.*/
2128void
2129bind_function_def (name, value)
2130 const char *name;
2131 FUNCTION_DEF *value;
2132{
2133 FUNCTION_DEF *entry;
2134 BUCKET_CONTENTS *elt;
2135 COMMAND *cmd;
2136
2137 entry = find_function_def (name);
2138 if (entry)
2139 {
2140 dispose_function_def_contents (entry);
2141 entry = copy_function_def_contents (value, entry);
2142 }
2143 else
2144 {
2145 cmd = value->command;
2146 value->command = 0;
2147 entry = copy_function_def (value);
2148 value->command = cmd;
2149
2150 elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2151 elt->data = (PTR_T *)entry;
2152 }
2153}
2154
7117c2d2
JA
2155/* Add STRING, which is of the form foo=bar, to the temporary environment
2156 HASH_TABLE (temporary_env). The functions in execute_cmd.c are
2157 responsible for moving the main temporary env to one of the other
2158 temporary environments. The expansion code in subst.c calls this. */
2159int
95732b49
JA
2160assign_in_env (word)
2161 WORD_DESC *word;
7117c2d2
JA
2162{
2163 int offset;
2164 char *name, *temp, *value;
2165 SHELL_VAR *var;
95732b49
JA
2166 const char *string;
2167
2168 string = word->word;
7117c2d2 2169
b80f6443 2170 offset = assignment (string, 0);
7117c2d2
JA
2171 name = savestring (string);
2172 value = (char *)NULL;
2173
2174 if (name[offset] == '=')
2175 {
2176 name[offset] = 0;
2177
95732b49
JA
2178 /* ignore the `+' when assigning temporary environment */
2179 if (name[offset - 1] == '+')
2180 name[offset - 1] = '\0';
2181
7117c2d2
JA
2182 var = find_variable (name);
2183 if (var && (readonly_p (var) || noassign_p (var)))
2184 {
2185 if (readonly_p (var))
2186 err_readonly (name);
2187 free (name);
2188 return (0);
2189 }
2190
2191 temp = name + offset + 1;
95732b49 2192#if 0
7117c2d2 2193 temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
7117c2d2
JA
2194 value = expand_string_unsplit_to_string (temp, 0);
2195 free (temp);
95732b49
JA
2196#else
2197 value = expand_assignment_string_to_string (temp, 0);
2198#endif
7117c2d2
JA
2199 }
2200
2201 if (temporary_env == 0)
2202 temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2203
2204 var = hash_lookup (name, temporary_env);
2205 if (var == 0)
2206 var = make_new_variable (name, temporary_env);
2207 else
2208 FREE (value_cell (var));
2209
2210 if (value == 0)
2211 {
2212 value = (char *)xmalloc (1); /* like do_assignment_internal */
2213 value[0] = '\0';
2214 }
2215
2216 var_setvalue (var, value);
2217 var->attributes |= (att_exported|att_tempvar);
2218 var->context = variable_context; /* XXX */
2219
2220 INVALIDATE_EXPORTSTR (var);
2221 var->exportstr = mk_env_string (name, value);
2222
2223 array_needs_making = 1;
2224
2225 if (ifsname (name))
2226 setifs (var);
2227
2228 if (echo_command_at_execute)
b80f6443
JA
2229 /* The Korn shell prints the `+ ' in front of assignment statements,
2230 so we do too. */
2231 xtrace_print_assignment (name, value, 0, 1);
7117c2d2 2232
b80f6443 2233 free (name);
7117c2d2
JA
2234 return 1;
2235}
2236
2237/* **************************************************************** */
2238/* */
2239/* Copying variables */
2240/* */
2241/* **************************************************************** */
2242
2243#ifdef INCLUDE_UNUSED
2244/* Copy VAR to a new data structure and return that structure. */
2245SHELL_VAR *
2246copy_variable (var)
2247 SHELL_VAR *var;
2248{
2249 SHELL_VAR *copy = (SHELL_VAR *)NULL;
2250
2251 if (var)
2252 {
2253 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2254
2255 copy->attributes = var->attributes;
2256 copy->name = savestring (var->name);
2257
2258 if (function_p (var))
2259 var_setfunc (copy, copy_command (function_cell (var)));
2260#if defined (ARRAY_VARS)
2261 else if (array_p (var))
2262 var_setarray (copy, dup_array (array_cell (var)));
2263#endif
2264 else if (value_cell (var))
2265 var_setvalue (copy, savestring (value_cell (var)));
2266 else
2267 var_setvalue (copy, (char *)NULL);
2268
2269 copy->dynamic_value = var->dynamic_value;
2270 copy->assign_func = var->assign_func;
2271
2272 copy->exportstr = COPY_EXPORTSTR (var);
2273
2274 copy->context = var->context;
2275 }
2276 return (copy);
2277}
2278#endif
2279
2280/* **************************************************************** */
2281/* */
2282/* Deleting and unsetting variables */
2283/* */
2284/* **************************************************************** */
2285
726f6388
JA
2286/* Dispose of the information attached to VAR. */
2287void
2288dispose_variable (var)
2289 SHELL_VAR *var;
2290{
7117c2d2 2291 if (var == 0)
726f6388
JA
2292 return;
2293
2294 if (function_p (var))
ccc6cda3
JA
2295 dispose_command (function_cell (var));
2296#if defined (ARRAY_VARS)
2297 else if (array_p (var))
7117c2d2 2298 array_dispose (array_cell (var));
ccc6cda3
JA
2299#endif
2300 else
2301 FREE (value_cell (var));
726f6388 2302
bb70624e
JA
2303 FREE_EXPORTSTR (var);
2304
726f6388
JA
2305 free (var->name);
2306
2307 if (exported_p (var))
2308 array_needs_making = 1;
2309
2310 free (var);
2311}
2312
7117c2d2 2313/* Unset the shell variable referenced by NAME. */
ccc6cda3 2314int
726f6388 2315unbind_variable (name)
f73dda09 2316 const char *name;
726f6388 2317{
7117c2d2
JA
2318 return makunbound (name, shell_variables);
2319}
726f6388 2320
7117c2d2
JA
2321/* Unset the shell function named NAME. */
2322int
2323unbind_func (name)
2324 const char *name;
2325{
2326 BUCKET_CONTENTS *elt;
2327 SHELL_VAR *func;
726f6388 2328
7117c2d2
JA
2329 elt = hash_remove (name, shell_functions, 0);
2330
2331 if (elt == 0)
2332 return -1;
2333
2334#if defined (PROGRAMMABLE_COMPLETION)
2335 set_itemlist_dirty (&it_functions);
ccc6cda3 2336#endif
7117c2d2
JA
2337
2338 func = (SHELL_VAR *)elt->data;
2339 if (func)
726f6388 2340 {
7117c2d2
JA
2341 if (exported_p (func))
2342 array_needs_making++;
2343 dispose_variable (func);
726f6388
JA
2344 }
2345
7117c2d2
JA
2346 free (elt->key);
2347 free (elt);
726f6388 2348
7117c2d2 2349 return 0;
726f6388
JA
2350}
2351
b80f6443
JA
2352int
2353unbind_function_def (name)
2354 const char *name;
2355{
2356 BUCKET_CONTENTS *elt;
2357 FUNCTION_DEF *funcdef;
2358
2359 elt = hash_remove (name, shell_function_defs, 0);
2360
2361 if (elt == 0)
2362 return -1;
2363
2364 funcdef = (FUNCTION_DEF *)elt->data;
2365 if (funcdef)
2366 dispose_function_def (funcdef);
2367
2368 free (elt->key);
2369 free (elt);
2370
2371 return 0;
2372}
2373
726f6388
JA
2374/* Make the variable associated with NAME go away. HASH_LIST is the
2375 hash table from which this variable should be deleted (either
2376 shell_variables or shell_functions).
2377 Returns non-zero if the variable couldn't be found. */
ccc6cda3 2378int
7117c2d2 2379makunbound (name, vc)
f73dda09 2380 const char *name;
7117c2d2 2381 VAR_CONTEXT *vc;
726f6388 2382{
d166f048 2383 BUCKET_CONTENTS *elt, *new_elt;
7117c2d2
JA
2384 SHELL_VAR *old_var;
2385 VAR_CONTEXT *v;
726f6388
JA
2386 char *t;
2387
7117c2d2
JA
2388 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2389 if (elt = hash_remove (name, v->table, 0))
2390 break;
726f6388 2391
d166f048 2392 if (elt == 0)
726f6388
JA
2393 return (-1);
2394
2395 old_var = (SHELL_VAR *)elt->data;
726f6388
JA
2396
2397 if (old_var && exported_p (old_var))
2398 array_needs_making++;
2399
ccc6cda3 2400 /* If we're unsetting a local variable and we're still executing inside
7117c2d2
JA
2401 the function, just mark the variable as invisible. The function
2402 eventually called by pop_var_context() will clean it up later. This
2403 must be done so that if the variable is subsequently assigned a new
2404 value inside the function, the `local' attribute is still present.
2405 We also need to add it back into the correct hash table. */
ccc6cda3
JA
2406 if (old_var && local_p (old_var) && variable_context == old_var->context)
2407 {
95732b49
JA
2408#if defined (ARRAY_VARS)
2409 if (array_p (old_var))
2410 array_dispose (array_cell (old_var));
2411 else
2412#endif
2413 FREE (value_cell (old_var));
b80f6443
JA
2414 /* Reset the attributes. Preserve the export attribute if the variable
2415 came from a temporary environment. Make sure it stays local, and
2416 make it invisible. */
2417 old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
2418 VSETATTR (old_var, att_local);
bb70624e 2419 VSETATTR (old_var, att_invisible);
7117c2d2 2420 var_setvalue (old_var, (char *)NULL);
bb70624e 2421 INVALIDATE_EXPORTSTR (old_var);
7117c2d2
JA
2422
2423 new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2424 new_elt->data = (PTR_T)old_var;
ccc6cda3 2425 stupidly_hack_special_variables (old_var->name);
7117c2d2 2426
d166f048
JA
2427 free (elt->key);
2428 free (elt);
ccc6cda3
JA
2429 return (0);
2430 }
2431
726f6388
JA
2432 /* Have to save a copy of name here, because it might refer to
2433 old_var->name. If so, stupidly_hack_special_variables will
2434 reference freed memory. */
2435 t = savestring (name);
2436
2437 free (elt->key);
2438 free (elt);
2439
2440 dispose_variable (old_var);
2441 stupidly_hack_special_variables (t);
2442 free (t);
7117c2d2 2443
726f6388
JA
2444 return (0);
2445}
2446
7117c2d2
JA
2447/* Get rid of all of the variables in the current context. */
2448void
2449kill_all_local_variables ()
726f6388 2450{
7117c2d2
JA
2451 VAR_CONTEXT *vc;
2452
2453 for (vc = shell_variables; vc; vc = vc->down)
2454 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2455 break;
2456 if (vc == 0)
2457 return; /* XXX */
726f6388 2458
7117c2d2 2459 if (vc->table && vc_haslocals (vc))
726f6388 2460 {
7117c2d2
JA
2461 delete_all_variables (vc->table);
2462 hash_dispose (vc->table);
726f6388 2463 }
7117c2d2 2464 vc->table = (HASH_TABLE *)NULL;
726f6388
JA
2465}
2466
ccc6cda3
JA
2467static void
2468free_variable_hash_data (data)
f73dda09 2469 PTR_T data;
ccc6cda3 2470{
7117c2d2 2471 SHELL_VAR *var;
ccc6cda3
JA
2472
2473 var = (SHELL_VAR *)data;
7117c2d2 2474 dispose_variable (var);
ccc6cda3
JA
2475}
2476
726f6388
JA
2477/* Delete the entire contents of the hash table. */
2478void
2479delete_all_variables (hashed_vars)
2480 HASH_TABLE *hashed_vars;
2481{
7117c2d2 2482 hash_flush (hashed_vars, free_variable_hash_data);
726f6388
JA
2483}
2484
7117c2d2
JA
2485/* **************************************************************** */
2486/* */
2487/* Setting variable attributes */
2488/* */
2489/* **************************************************************** */
726f6388 2490
ccc6cda3
JA
2491#define FIND_OR_MAKE_VARIABLE(name, entry) \
2492 do \
2493 { \
2494 entry = find_variable (name); \
2495 if (!entry) \
2496 { \
95732b49 2497 entry = bind_variable (name, "", 0); \
ccc6cda3
JA
2498 if (!no_invisible_vars) entry->attributes |= att_invisible; \
2499 } \
2500 } \
2501 while (0)
2502
2503/* Make the variable associated with NAME be readonly.
726f6388
JA
2504 If NAME does not exist yet, create it. */
2505void
2506set_var_read_only (name)
2507 char *name;
2508{
ccc6cda3 2509 SHELL_VAR *entry;
726f6388 2510
ccc6cda3 2511 FIND_OR_MAKE_VARIABLE (name, entry);
bb70624e 2512 VSETATTR (entry, att_readonly);
726f6388
JA
2513}
2514
cce855bc 2515#ifdef INCLUDE_UNUSED
ccc6cda3 2516/* Make the function associated with NAME be readonly.
726f6388
JA
2517 If NAME does not exist, we just punt, like auto_export code below. */
2518void
2519set_func_read_only (name)
f73dda09 2520 const char *name;
726f6388 2521{
d166f048 2522 SHELL_VAR *entry;
726f6388 2523
d166f048 2524 entry = find_function (name);
726f6388 2525 if (entry)
bb70624e 2526 VSETATTR (entry, att_readonly);
726f6388
JA
2527}
2528
2529/* Make the variable associated with NAME be auto-exported.
2530 If NAME does not exist yet, create it. */
2531void
2532set_var_auto_export (name)
2533 char *name;
2534{
ccc6cda3 2535 SHELL_VAR *entry;
726f6388 2536
ccc6cda3 2537 FIND_OR_MAKE_VARIABLE (name, entry);
726f6388
JA
2538 set_auto_export (entry);
2539}
2540
2541/* Make the function associated with NAME be auto-exported. */
2542void
2543set_func_auto_export (name)
f73dda09 2544 const char *name;
726f6388 2545{
ccc6cda3 2546 SHELL_VAR *entry;
726f6388 2547
ccc6cda3 2548 entry = find_function (name);
726f6388 2549 if (entry)
ccc6cda3
JA
2550 set_auto_export (entry);
2551}
cce855bc 2552#endif
ccc6cda3 2553
7117c2d2
JA
2554/* **************************************************************** */
2555/* */
2556/* Creating lists of variables */
2557/* */
2558/* **************************************************************** */
2559
2560static VARLIST *
2561vlist_alloc (nentries)
2562 int nentries;
726f6388 2563{
7117c2d2 2564 VARLIST *vlist;
726f6388 2565
7117c2d2
JA
2566 vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2567 vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2568 vlist->list_size = nentries;
2569 vlist->list_len = 0;
2570 vlist->list[0] = (SHELL_VAR *)NULL;
726f6388 2571
7117c2d2
JA
2572 return vlist;
2573}
726f6388 2574
7117c2d2
JA
2575static VARLIST *
2576vlist_realloc (vlist, n)
2577 VARLIST *vlist;
2578 int n;
2579{
2580 if (vlist == 0)
2581 return (vlist = vlist_alloc (n));
2582 if (n > vlist->list_size)
726f6388 2583 {
7117c2d2
JA
2584 vlist->list_size = n;
2585 vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2586 }
2587 return vlist;
2588}
726f6388 2589
7117c2d2
JA
2590static void
2591vlist_add (vlist, var, flags)
2592 VARLIST *vlist;
2593 SHELL_VAR *var;
2594 int flags;
2595{
2596 register int i;
ccc6cda3 2597
7117c2d2
JA
2598 for (i = 0; i < vlist->list_len; i++)
2599 if (STREQ (var->name, vlist->list[i]->name))
2600 break;
2601 if (i < vlist->list_len)
2602 return;
2603
2604 if (i >= vlist->list_size)
2605 vlist = vlist_realloc (vlist, vlist->list_size + 16);
726f6388 2606
7117c2d2
JA
2607 vlist->list[vlist->list_len++] = var;
2608 vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2609}
2610
2611/* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
2612 variables for which FUNCTION returns a non-zero value. A NULL value
2613 for FUNCTION means to use all variables. */
2614SHELL_VAR **
2615map_over (function, vc)
2616 sh_var_map_func_t *function;
2617 VAR_CONTEXT *vc;
2618{
2619 VAR_CONTEXT *v;
2620 VARLIST *vlist;
2621 SHELL_VAR **ret;
2622 int nentries;
2623
2624 for (nentries = 0, v = vc; v; v = v->down)
2625 nentries += HASH_ENTRIES (v->table);
2626
2627 if (nentries == 0)
2628 return (SHELL_VAR **)NULL;
2629
2630 vlist = vlist_alloc (nentries);
2631
2632 for (v = vc; v; v = v->down)
2633 flatten (v->table, function, vlist, 0);
2634
2635 ret = vlist->list;
2636 free (vlist);
2637 return ret;
2638}
2639
2640SHELL_VAR **
2641map_over_funcs (function)
2642 sh_var_map_func_t *function;
2643{
2644 VARLIST *vlist;
2645 SHELL_VAR **ret;
2646
2647 if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2648 return ((SHELL_VAR **)NULL);
2649
2650 vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2651
2652 flatten (shell_functions, function, vlist, 0);
2653
2654 ret = vlist->list;
2655 free (vlist);
2656 return ret;
2657}
2658
2659/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2660 elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
2661 for future use. Only unique names are added to VLIST. If FUNC is
2662 NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
2663 NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
2664 and FUNC are both NULL, nothing happens. */
2665static void
2666flatten (var_hash_table, func, vlist, flags)
2667 HASH_TABLE *var_hash_table;
2668 sh_var_map_func_t *func;
2669 VARLIST *vlist;
2670 int flags;
2671{
2672 register int i;
2673 register BUCKET_CONTENTS *tlist;
2674 int r;
2675 SHELL_VAR *var;
2676
2677 if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
2678 return;
2679
2680 for (i = 0; i < var_hash_table->nbuckets; i++)
2681 {
2682 for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
2683 {
2684 var = (SHELL_VAR *)tlist->data;
2685
2686 r = func ? (*func) (var) : 1;
2687 if (r && vlist)
2688 vlist_add (vlist, var, flags);
2689 }
726f6388 2690 }
7117c2d2
JA
2691}
2692
2693void
2694sort_variables (array)
2695 SHELL_VAR **array;
2696{
2697 qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
726f6388
JA
2698}
2699
2700static int
7117c2d2
JA
2701qsort_var_comp (var1, var2)
2702 SHELL_VAR **var1, **var2;
726f6388 2703{
7117c2d2
JA
2704 int result;
2705
2706 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
2707 result = strcmp ((*var1)->name, (*var2)->name);
2708
2709 return (result);
726f6388
JA
2710}
2711
7117c2d2
JA
2712/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
2713 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
ccc6cda3 2714static SHELL_VAR **
7117c2d2
JA
2715vapply (func)
2716 sh_var_map_func_t *func;
726f6388
JA
2717{
2718 SHELL_VAR **list;
2719
7117c2d2 2720 list = map_over (func, shell_variables);
d166f048 2721 if (list /* && posixly_correct */)
726f6388 2722 sort_variables (list);
7117c2d2
JA
2723 return (list);
2724}
726f6388 2725
7117c2d2
JA
2726/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
2727 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
2728static SHELL_VAR **
2729fapply (func)
2730 sh_var_map_func_t *func;
2731{
2732 SHELL_VAR **list;
2733
2734 list = map_over_funcs (func);
2735 if (list /* && posixly_correct */)
2736 sort_variables (list);
726f6388
JA
2737 return (list);
2738}
2739
7117c2d2
JA
2740/* Create a NULL terminated array of all the shell variables. */
2741SHELL_VAR **
2742all_shell_variables ()
2743{
2744 return (vapply ((sh_var_map_func_t *)NULL));
2745}
2746
2747/* Create a NULL terminated array of all the shell functions. */
2748SHELL_VAR **
2749all_shell_functions ()
2750{
2751 return (fapply ((sh_var_map_func_t *)NULL));
2752}
2753
2754static int
2755visible_var (var)
2756 SHELL_VAR *var;
2757{
2758 return (invisible_p (var) == 0);
2759}
2760
726f6388 2761SHELL_VAR **
bb70624e 2762all_visible_functions ()
726f6388 2763{
7117c2d2 2764 return (fapply (visible_var));
ccc6cda3 2765}
726f6388 2766
ccc6cda3 2767SHELL_VAR **
bb70624e 2768all_visible_variables ()
ccc6cda3 2769{
7117c2d2 2770 return (vapply (visible_var));
726f6388
JA
2771}
2772
ccc6cda3
JA
2773/* Return non-zero if the variable VAR is visible and exported. Array
2774 variables cannot be exported. */
726f6388
JA
2775static int
2776visible_and_exported (var)
2777 SHELL_VAR *var;
2778{
ccc6cda3 2779 return (invisible_p (var) == 0 && exported_p (var));
726f6388
JA
2780}
2781
7117c2d2
JA
2782/* Return non-zero if VAR is a local variable in the current context and
2783 is exported. */
2784static int
2785local_and_exported (var)
2786 SHELL_VAR *var;
2787{
2788 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
2789}
2790
bb70624e
JA
2791SHELL_VAR **
2792all_exported_variables ()
2793{
7117c2d2
JA
2794 return (vapply (visible_and_exported));
2795}
bb70624e 2796
7117c2d2
JA
2797SHELL_VAR **
2798local_exported_variables ()
2799{
2800 return (vapply (local_and_exported));
2801}
2802
2803static int
2804variable_in_context (var)
2805 SHELL_VAR *var;
2806{
2807 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
2808}
2809
2810SHELL_VAR **
2811all_local_variables ()
2812{
2813 VARLIST *vlist;
2814 SHELL_VAR **ret;
2815 VAR_CONTEXT *vc;
2816
2817 vc = shell_variables;
2818 for (vc = shell_variables; vc; vc = vc->down)
2819 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2820 break;
2821
2822 if (vc == 0)
2823 {
b80f6443 2824 internal_error (_("all_local_variables: no function context at current scope"));
7117c2d2
JA
2825 return (SHELL_VAR **)NULL;
2826 }
2827 if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
2828 return (SHELL_VAR **)NULL;
2829
2830 vlist = vlist_alloc (HASH_ENTRIES (vc->table));
2831
2832 flatten (vc->table, variable_in_context, vlist, 0);
2833
2834 ret = vlist->list;
2835 free (vlist);
2836 if (ret)
2837 sort_variables (ret);
2838 return ret;
bb70624e
JA
2839}
2840
2841#if defined (ARRAY_VARS)
2842/* Return non-zero if the variable VAR is visible and an array. */
2843static int
2844visible_array_vars (var)
2845 SHELL_VAR *var;
2846{
2847 return (invisible_p (var) == 0 && array_p (var));
2848}
2849
2850SHELL_VAR **
2851all_array_variables ()
2852{
7117c2d2 2853 return (vapply (visible_array_vars));
bb70624e
JA
2854}
2855#endif /* ARRAY_VARS */
2856
2857char **
2858all_variables_matching_prefix (prefix)
f73dda09 2859 const char *prefix;
bb70624e
JA
2860{
2861 SHELL_VAR **varlist;
2862 char **rlist;
2863 int vind, rind, plen;
2864
2865 plen = STRLEN (prefix);
2866 varlist = all_visible_variables ();
2867 for (vind = 0; varlist && varlist[vind]; vind++)
2868 ;
2869 if (varlist == 0 || vind == 0)
2870 return ((char **)NULL);
7117c2d2 2871 rlist = strvec_create (vind + 1);
bb70624e
JA
2872 for (vind = rind = 0; varlist[vind]; vind++)
2873 {
2874 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
28ef6c31 2875 rlist[rind++] = savestring (varlist[vind]->name);
bb70624e
JA
2876 }
2877 rlist[rind] = (char *)0;
2878 free (varlist);
2879
2880 return rlist;
2881}
2882
7117c2d2
JA
2883/* **************************************************************** */
2884/* */
2885/* Managing temporary variable scopes */
2886/* */
2887/* **************************************************************** */
2888
2889/* Make variable NAME have VALUE in the temporary environment. */
2890static SHELL_VAR *
2891bind_tempenv_variable (name, value)
2892 const char *name;
2893 char *value;
2894{
2895 SHELL_VAR *var;
2896
2897 var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
2898
2899 if (var)
2900 {
2901 FREE (value_cell (var));
2902 var_setvalue (var, savestring (value));
2903 INVALIDATE_EXPORTSTR (var);
2904 }
2905
2906 return (var);
2907}
2908
2909/* Find a variable in the temporary environment that is named NAME.
2910 Return the SHELL_VAR *, or NULL if not found. */
2911SHELL_VAR *
2912find_tempenv_variable (name)
2913 const char *name;
2914{
2915 return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
2916}
2917
2918/* Push the variable described by (SHELL_VAR *)DATA down to the next
2919 variable context from the temporary environment. */
2920static void
2921push_temp_var (data)
2922 PTR_T data;
2923{
2924 SHELL_VAR *var, *v;
2925 HASH_TABLE *binding_table;
2926
2927 var = (SHELL_VAR *)data;
2928
2929 binding_table = shell_variables->table;
2930 if (binding_table == 0)
2931 {
2932 if (shell_variables == global_variables)
2933 /* shouldn't happen */
2934 binding_table = shell_variables->table = global_variables->table = hash_create (0);
2935 else
2936 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
2937 }
2938
95732b49 2939 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
7117c2d2
JA
2940
2941 /* XXX - should we set the context here? It shouldn't matter because of how
2942 assign_in_env works, but might want to check. */
2943 if (binding_table == global_variables->table) /* XXX */
2944 var->attributes &= ~(att_tempvar|att_propagate);
2945 else
2946 {
2947 var->attributes |= att_propagate;
2948 if (binding_table == shell_variables->table)
2949 shell_variables->flags |= VC_HASTMPVAR;
2950 }
2951 v->attributes |= var->attributes;
2952
2953 dispose_variable (var);
2954}
2955
2956static void
2957propagate_temp_var (data)
2958 PTR_T data;
2959{
2960 SHELL_VAR *var;
2961
2962 var = (SHELL_VAR *)data;
2963 if (tempvar_p (var) && (var->attributes & att_propagate))
2964 push_temp_var (data);
2965 else
2966 dispose_variable (var);
2967}
2968
2969/* Free the storage used in the hash table for temporary
2970 environment variables. PUSHF is a function to be called
2971 to free each hash table entry. It takes care of pushing variables
2972 to previous scopes if appropriate. */
2973static void
2974dispose_temporary_env (pushf)
2975 sh_free_func_t *pushf;
2976{
2977 hash_flush (temporary_env, pushf);
2978 hash_dispose (temporary_env);
2979 temporary_env = (HASH_TABLE *)NULL;
2980
2981 array_needs_making = 1;
2982
2983 sv_ifs ("IFS"); /* XXX here for now */
2984}
2985
2986void
2987dispose_used_env_vars ()
2988{
2989 if (temporary_env)
2990 dispose_temporary_env (propagate_temp_var);
2991}
2992
2993/* Take all of the shell variables in the temporary environment HASH_TABLE
2994 and make shell variables from them at the current variable context. */
2995void
2996merge_temporary_env ()
2997{
2998 if (temporary_env)
2999 dispose_temporary_env (push_temp_var);
3000}
3001
3002/* **************************************************************** */
3003/* */
3004/* Creating and manipulating the environment */
3005/* */
3006/* **************************************************************** */
3007
bb70624e
JA
3008static inline char *
3009mk_env_string (name, value)
f73dda09 3010 const char *name, *value;
bb70624e
JA
3011{
3012 int name_len, value_len;
3013 char *p;
3014
3015 name_len = strlen (name);
3016 value_len = STRLEN (value);
f73dda09 3017 p = (char *)xmalloc (2 + name_len + value_len);
bb70624e
JA
3018 strcpy (p, name);
3019 p[name_len] = '=';
3020 if (value && *value)
3021 strcpy (p + name_len + 1, value);
3022 else
3023 p[name_len + 1] = '\0';
3024 return (p);
3025}
3026
f73dda09 3027#ifdef DEBUG
bb70624e
JA
3028/* Debugging */
3029static int
3030valid_exportstr (v)
3031 SHELL_VAR *v;
3032{
3033 char *s;
3034
3035 s = v->exportstr;
f73dda09 3036 if (legal_variable_starter ((unsigned char)*s) == 0)
bb70624e 3037 {
b80f6443 3038 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
3039 return (0);
3040 }
3041 for (s = v->exportstr + 1; s && *s; s++)
3042 {
3043 if (*s == '=')
28ef6c31 3044 break;
f73dda09 3045 if (legal_variable_char ((unsigned char)*s) == 0)
bb70624e 3046 {
b80f6443 3047 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
3048 return (0);
3049 }
3050 }
3051 if (*s != '=')
3052 {
b80f6443 3053 internal_error (_("no `=' in exportstr for %s"), v->name);
bb70624e
JA
3054 return (0);
3055 }
3056 return (1);
3057}
f73dda09 3058#endif
bb70624e 3059
7117c2d2
JA
3060static char **
3061make_env_array_from_var_list (vars)
3062 SHELL_VAR **vars;
726f6388
JA
3063{
3064 register int i, list_index;
3065 register SHELL_VAR *var;
ccc6cda3 3066 char **list, *value;
726f6388 3067
7117c2d2 3068 list = strvec_create ((1 + strvec_len ((char **)vars)));
bb70624e
JA
3069
3070#define USE_EXPORTSTR (value == var->exportstr)
726f6388
JA
3071
3072 for (i = 0, list_index = 0; var = vars[i]; i++)
3073 {
28ef6c31
JA
3074#if defined (__CYGWIN__)
3075 /* We don't use the exportstr stuff on Cygwin at all. */
3076 INVALIDATE_EXPORTSTR (var);
bb70624e 3077#endif
28ef6c31
JA
3078 if (var->exportstr)
3079 value = var->exportstr;
bb70624e 3080 else if (function_p (var))
ccc6cda3
JA
3081 value = named_function_string ((char *)NULL, function_cell (var), 0);
3082#if defined (ARRAY_VARS)
3083 else if (array_p (var))
3084# if 0
3085 value = array_to_assignment_string (array_cell (var));
3086# else
3087 continue; /* XXX array vars cannot yet be exported */
3088# endif
3089#endif
726f6388
JA
3090 else
3091 value = value_cell (var);
3092
3093 if (value)
3094 {
bb70624e
JA
3095 /* Gee, I'd like to get away with not using savestring() if we're
3096 using the cached exportstr... */
3097 list[list_index] = USE_EXPORTSTR ? savestring (value)
3098 : mk_env_string (var->name, value);
3099
7117c2d2
JA
3100 if (USE_EXPORTSTR == 0)
3101 SAVE_EXPORTSTR (var, list[list_index]);
3102
726f6388 3103 list_index++;
bb70624e
JA
3104#undef USE_EXPORTSTR
3105
3106#if 0 /* not yet */
ccc6cda3
JA
3107#if defined (ARRAY_VARS)
3108 if (array_p (var))
3109 free (value);
bb70624e 3110#endif
ccc6cda3 3111#endif
726f6388
JA
3112 }
3113 }
3114
726f6388
JA
3115 list[list_index] = (char *)NULL;
3116 return (list);
3117}
3118
7117c2d2
JA
3119/* Make an array of assignment statements from the hash table
3120 HASHED_VARS which contains SHELL_VARs. Only visible, exported
3121 variables are eligible. */
3122static char **
3123make_var_export_array (vcxt)
3124 VAR_CONTEXT *vcxt;
726f6388 3125{
7117c2d2
JA
3126 char **list;
3127 SHELL_VAR **vars;
726f6388 3128
7117c2d2 3129 vars = map_over (visible_and_exported, vcxt);
726f6388 3130
7117c2d2
JA
3131 if (vars == 0)
3132 return (char **)NULL;
ccc6cda3 3133
7117c2d2 3134 list = make_env_array_from_var_list (vars);
ccc6cda3 3135
7117c2d2
JA
3136 free (vars);
3137 return (list);
ccc6cda3
JA
3138}
3139
7117c2d2
JA
3140static char **
3141make_func_export_array ()
726f6388 3142{
7117c2d2
JA
3143 char **list;
3144 SHELL_VAR **vars;
ccc6cda3 3145
7117c2d2
JA
3146 vars = map_over_funcs (visible_and_exported);
3147 if (vars == 0)
3148 return (char **)NULL;
726f6388 3149
7117c2d2 3150 list = make_env_array_from_var_list (vars);
28ef6c31 3151
7117c2d2
JA
3152 free (vars);
3153 return (list);
bb70624e
JA
3154}
3155
d166f048
JA
3156/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3157#define add_to_export_env(envstr,do_alloc) \
3158do \
3159 { \
3160 if (export_env_index >= (export_env_size - 1)) \
3161 { \
3162 export_env_size += 16; \
7117c2d2 3163 export_env = strvec_resize (export_env, export_env_size); \
95732b49 3164 environ = export_env; \
d166f048
JA
3165 } \
3166 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3167 export_env[export_env_index] = (char *)NULL; \
3168 } while (0)
3169
d166f048
JA
3170/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3171 array with the same left-hand side. Return the new EXPORT_ENV. */
726f6388 3172char **
d166f048 3173add_or_supercede_exported_var (assign, do_alloc)
726f6388 3174 char *assign;
d166f048 3175 int do_alloc;
726f6388
JA
3176{
3177 register int i;
d166f048 3178 int equal_offset;
726f6388 3179
b80f6443 3180 equal_offset = assignment (assign, 0);
d166f048
JA
3181 if (equal_offset == 0)
3182 return (export_env);
726f6388 3183
7117c2d2
JA
3184 /* If this is a function, then only supersede the function definition.
3185 We do this by including the `=() {' in the comparison, like
3186 initialize_shell_variables does. */
3187 if (assign[equal_offset + 1] == '(' &&
3188 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
3189 equal_offset += 4;
726f6388 3190
d166f048 3191 for (i = 0; i < export_env_index; i++)
726f6388 3192 {
d166f048 3193 if (STREQN (assign, export_env[i], equal_offset + 1))
726f6388 3194 {
d166f048
JA
3195 free (export_env[i]);
3196 export_env[i] = do_alloc ? savestring (assign) : assign;
3197 return (export_env);
726f6388
JA
3198 }
3199 }
d166f048
JA
3200 add_to_export_env (assign, do_alloc);
3201 return (export_env);
726f6388
JA
3202}
3203
7117c2d2
JA
3204static void
3205add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3206 char **temp_array;
3207 int do_alloc, do_supercede;
3208{
3209 register int i;
3210
3211 if (temp_array == 0)
3212 return;
3213
3214 for (i = 0; temp_array[i]; i++)
3215 {
3216 if (do_supercede)
3217 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3218 else
3219 add_to_export_env (temp_array[i], do_alloc);
3220 }
3221
3222 free (temp_array);
3223}
3224
d166f048 3225/* Make the environment array for the command about to be executed, if the
726f6388
JA
3226 array needs making. Otherwise, do nothing. If a shell action could
3227 change the array that commands receive for their environment, then the
7117c2d2
JA
3228 code should `array_needs_making++'.
3229
3230 The order to add to the array is:
3231 temporary_env
3232 list of var contexts whose head is shell_variables
3233 shell_functions
3234
3235 This is the shell variable lookup order. We add only new variable
3236 names at each step, which allows local variables and variables in
3237 the temporary environments to shadow variables in the global (or
3238 any previous) scope.
3239*/
3240
3241static int
3242n_shell_variables ()
3243{
3244 VAR_CONTEXT *vc;
3245 int n;
3246
3247 for (n = 0, vc = shell_variables; vc; vc = vc->down)
3248 n += HASH_ENTRIES (vc->table);
3249 return n;
3250}
3251
726f6388
JA
3252void
3253maybe_make_export_env ()
3254{
726f6388 3255 register char **temp_array;
d166f048 3256 int new_size;
7117c2d2 3257 VAR_CONTEXT *tcxt;
726f6388
JA
3258
3259 if (array_needs_making)
3260 {
3261 if (export_env)
7117c2d2 3262 strvec_flush (export_env);
d166f048
JA
3263
3264 /* Make a guess based on how many shell variables and functions we
3265 have. Since there will always be array variables, and array
3266 variables are not (yet) exported, this will always be big enough
7117c2d2
JA
3267 for the exported variables and functions. */
3268 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3269 HASH_ENTRIES (temporary_env);
d166f048
JA
3270 if (new_size > export_env_size)
3271 {
3272 export_env_size = new_size;
7117c2d2 3273 export_env = strvec_resize (export_env, export_env_size);
95732b49 3274 environ = export_env;
d166f048
JA
3275 }
3276 export_env[export_env_index = 0] = (char *)NULL;
726f6388 3277
7117c2d2
JA
3278 /* Make a dummy variable context from the temporary_env, stick it on
3279 the front of shell_variables, call make_var_export_array on the
3280 whole thing to flatten it, and convert the list of SHELL_VAR *s
3281 to the form needed by the environment. */
3282 if (temporary_env)
3283 {
3284 tcxt = new_var_context ((char *)NULL, 0);
3285 tcxt->table = temporary_env;
3286 tcxt->down = shell_variables;
3287 }
3288 else
3289 tcxt = shell_variables;
3290
3291 temp_array = make_var_export_array (tcxt);
d166f048 3292 if (temp_array)
7117c2d2
JA
3293 add_temp_array_to_env (temp_array, 0, 0);
3294
3295 if (tcxt != shell_variables)
3296 free (tcxt);
726f6388 3297
f73dda09
JA
3298#if defined (RESTRICTED_SHELL)
3299 /* Restricted shells may not export shell functions. */
7117c2d2 3300 temp_array = restricted ? (char **)0 : make_func_export_array ();
f73dda09 3301#else
7117c2d2 3302 temp_array = make_func_export_array ();
f73dda09 3303#endif
d166f048 3304 if (temp_array)
7117c2d2 3305 add_temp_array_to_env (temp_array, 0, 0);
726f6388
JA
3306
3307 array_needs_making = 0;
3308 }
3309}
3310
b72432fd
JA
3311/* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
3312 we will need to remake the exported environment every time we
3313 change directories. `_' is always put into the environment for
3314 every external command, so without special treatment it will always
3315 cause the environment to be remade.
3316
3317 If there is no other reason to make the exported environment, we can
3318 just update the variables in place and mark the exported environment
3319 as no longer needing a remake. */
3320void
3321update_export_env_inplace (env_prefix, preflen, value)
3322 char *env_prefix;
3323 int preflen;
3324 char *value;
3325{
3326 char *evar;
3327
f73dda09 3328 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
b72432fd
JA
3329 strcpy (evar, env_prefix);
3330 if (value)
3331 strcpy (evar + preflen, value);
3332 export_env = add_or_supercede_exported_var (evar, 0);
3333}
3334
726f6388
JA
3335/* We always put _ in the environment as the name of this command. */
3336void
3337put_command_name_into_env (command_name)
3338 char *command_name;
3339{
b72432fd 3340 update_export_env_inplace ("_=", 2, command_name);
726f6388
JA
3341}
3342
cce855bc 3343#if 0 /* UNUSED -- it caused too many problems */
ccc6cda3
JA
3344void
3345put_gnu_argv_flags_into_env (pid, flags_string)
7117c2d2 3346 intmax_t pid;
ccc6cda3
JA
3347 char *flags_string;
3348{
3349 char *dummy, *pbuf;
3350 int l, fl;
3351
3352 pbuf = itos (pid);
3353 l = strlen (pbuf);
3354
3355 fl = strlen (flags_string);
3356
f73dda09 3357 dummy = (char *)xmalloc (l + fl + 30);
ccc6cda3
JA
3358 dummy[0] = '_';
3359 strcpy (dummy + 1, pbuf);
3360 strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3361 dummy[l + 27] = '=';
3362 strcpy (dummy + l + 28, flags_string);
3363
3364 free (pbuf);
3365
d166f048 3366 export_env = add_or_supercede_exported_var (dummy, 0);
ccc6cda3 3367}
cce855bc 3368#endif
726f6388 3369
7117c2d2
JA
3370/* **************************************************************** */
3371/* */
3372/* Managing variable contexts */
3373/* */
3374/* **************************************************************** */
3375
3376/* Allocate and return a new variable context with NAME and FLAGS.
3377 NAME can be NULL. */
726f6388 3378
7117c2d2
JA
3379VAR_CONTEXT *
3380new_var_context (name, flags)
3381 char *name;
3382 int flags;
3383{
3384 VAR_CONTEXT *vc;
3385
3386 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3387 vc->name = name ? savestring (name) : (char *)NULL;
3388 vc->scope = variable_context;
3389 vc->flags = flags;
3390
3391 vc->up = vc->down = (VAR_CONTEXT *)NULL;
3392 vc->table = (HASH_TABLE *)NULL;
3393
3394 return vc;
3395}
3396
3397/* Free a variable context and its data, including the hash table. Dispose
3398 all of the variables. */
3399void
3400dispose_var_context (vc)
3401 VAR_CONTEXT *vc;
3402{
3403 FREE (vc->name);
3404
3405 if (vc->table)
3406 {
3407 delete_all_variables (vc->table);
3408 hash_dispose (vc->table);
3409 }
3410
3411 free (vc);
3412}
3413
3414/* Set VAR's scope level to the current variable context. */
3415static int
3416set_context (var)
3417 SHELL_VAR *var;
3418{
3419 return (var->context = variable_context);
3420}
3421
3422/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3423 temporary variables, and push it onto shell_variables. This is
3424 for shell functions. */
3425VAR_CONTEXT *
3426push_var_context (name, flags, tempvars)
3427 char *name;
3428 int flags;
3429 HASH_TABLE *tempvars;
3430{
3431 VAR_CONTEXT *vc;
3432
3433 vc = new_var_context (name, flags);
3434 vc->table = tempvars;
3435 if (tempvars)
3436 {
3437 /* Have to do this because the temp environment was created before
3438 variable_context was incremented. */
3439 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3440 vc->flags |= VC_HASTMPVAR;
3441 }
3442 vc->down = shell_variables;
3443 shell_variables->up = vc;
3444
3445 return (shell_variables = vc);
3446}
3447
3448static void
3449push_func_var (data)
3450 PTR_T data;
3451{
3452 SHELL_VAR *var, *v;
3453
3454 var = (SHELL_VAR *)data;
3455
3456 if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3457 {
3458 /* XXX - should we set v->context here? */
95732b49 3459 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
7117c2d2
JA
3460 if (shell_variables == global_variables)
3461 var->attributes &= ~(att_tempvar|att_propagate);
3462 else
3463 shell_variables->flags |= VC_HASTMPVAR;
3464 v->attributes |= var->attributes;
3465 }
3466
3467 dispose_variable (var);
3468}
3469
3470/* Pop the top context off of VCXT and dispose of it, returning the rest of
3471 the stack. */
3472void
3473pop_var_context ()
3474{
3475 VAR_CONTEXT *ret, *vcxt;
3476
3477 vcxt = shell_variables;
3478 if (vc_isfuncenv (vcxt) == 0)
3479 {
b80f6443 3480 internal_error (_("pop_var_context: head of shell_variables not a function context"));
7117c2d2
JA
3481 return;
3482 }
3483
3484 if (ret = vcxt->down)
3485 {
3486 ret->up = (VAR_CONTEXT *)NULL;
3487 shell_variables = ret;
3488 if (vcxt->table)
3489 hash_flush (vcxt->table, push_func_var);
3490 dispose_var_context (vcxt);
3491 }
3492 else
b80f6443 3493 internal_error (_("pop_var_context: no global_variables context"));
7117c2d2
JA
3494}
3495
3496/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3497 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3498void
3499delete_all_contexts (vcxt)
3500 VAR_CONTEXT *vcxt;
3501{
3502 VAR_CONTEXT *v, *t;
3503
3504 for (v = vcxt; v != global_variables; v = t)
3505 {
3506 t = v->down;
3507 dispose_var_context (v);
3508 }
3509
3510 delete_all_variables (global_variables->table);
3511 shell_variables = global_variables;
3512}
3513
3514/* **************************************************************** */
3515/* */
3516/* Pushing and Popping temporary variable scopes */
3517/* */
3518/* **************************************************************** */
3519
3520VAR_CONTEXT *
3521push_scope (flags, tmpvars)
3522 int flags;
3523 HASH_TABLE *tmpvars;
3524{
3525 return (push_var_context ((char *)NULL, flags, tmpvars));
3526}
3527
3528static void
3529push_exported_var (data)
3530 PTR_T data;
3531{
3532 SHELL_VAR *var, *v;
3533
3534 var = (SHELL_VAR *)data;
3535
3536 /* If a temp var had its export attribute set, or it's marked to be
3537 propagated, bind it in the previous scope before disposing it. */
95732b49
JA
3538 /* XXX - This isn't exactly right, because all tempenv variables have the
3539 export attribute set. */
3540#if 0
7117c2d2 3541 if (exported_p (var) || (var->attributes & att_propagate))
95732b49
JA
3542#else
3543 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
3544#endif
7117c2d2
JA
3545 {
3546 var->attributes &= ~att_tempvar; /* XXX */
95732b49 3547 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
7117c2d2
JA
3548 if (shell_variables == global_variables)
3549 var->attributes &= ~att_propagate;
3550 v->attributes |= var->attributes;
3551 }
3552
3553 dispose_variable (var);
3554}
3555
3556void
3557pop_scope (is_special)
3558 int is_special;
3559{
3560 VAR_CONTEXT *vcxt, *ret;
3561
3562 vcxt = shell_variables;
3563 if (vc_istempscope (vcxt) == 0)
3564 {
b80f6443 3565 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
7117c2d2
JA
3566 return;
3567 }
3568
3569 ret = vcxt->down;
3570 if (ret)
3571 ret->up = (VAR_CONTEXT *)NULL;
3572
3573 shell_variables = ret;
3574
3575 /* Now we can take care of merging variables in VCXT into set of scopes
3576 whose head is RET (shell_variables). */
3577 FREE (vcxt->name);
3578 if (vcxt->table)
3579 {
3580 if (is_special)
3581 hash_flush (vcxt->table, push_func_var);
3582 else
3583 hash_flush (vcxt->table, push_exported_var);
3584 hash_dispose (vcxt->table);
3585 }
3586 free (vcxt);
3587
3588 sv_ifs ("IFS"); /* XXX here for now */
3589}
3590
3591/* **************************************************************** */
3592/* */
3593/* Pushing and Popping function contexts */
3594/* */
3595/* **************************************************************** */
3596
3597static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3598static int dollar_arg_stack_slots;
3599static int dollar_arg_stack_index;
3600
3601/* XXX - we might want to consider pushing and popping the `getopts' state
3602 when we modify the positional parameters. */
3603void
3604push_context (name, is_subshell, tempvars)
3605 char *name; /* function name */
3606 int is_subshell;
3607 HASH_TABLE *tempvars;
3608{
3609 if (is_subshell == 0)
3610 push_dollar_vars ();
3611 variable_context++;
3612 push_var_context (name, VC_FUNCENV, tempvars);
3613}
3614
3615/* Only called when subshell == 0, so we don't need to check, and can
3616 unconditionally pop the dollar vars off the stack. */
3617void
3618pop_context ()
726f6388 3619{
7117c2d2
JA
3620 pop_dollar_vars ();
3621 variable_context--;
3622 pop_var_context ();
726f6388 3623
7117c2d2
JA
3624 sv_ifs ("IFS"); /* XXX here for now */
3625}
726f6388 3626
7117c2d2
JA
3627/* Save the existing positional parameters on a stack. */
3628void
3629push_dollar_vars ()
3630{
3631 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3632 {
3633 dollar_arg_stack = (WORD_LIST **)
3634 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3635 * sizeof (WORD_LIST **));
3636 }
3637 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3638 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3639}
726f6388 3640
7117c2d2
JA
3641/* Restore the positional parameters from our stack. */
3642void
3643pop_dollar_vars ()
3644{
3645 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3646 return;
726f6388 3647
7117c2d2
JA
3648 remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
3649 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3650 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3651 set_dollar_vars_unchanged ();
3652}
ccc6cda3 3653
7117c2d2
JA
3654void
3655dispose_saved_dollar_vars ()
3656{
3657 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3658 return;
726f6388 3659
7117c2d2
JA
3660 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3661 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
726f6388 3662}
cce855bc 3663
b80f6443
JA
3664/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
3665
3666void
3667push_args (list)
3668 WORD_LIST *list;
3669{
3670#if defined (ARRAY_VARS) && defined (DEBUGGER)
3671 SHELL_VAR *bash_argv_v, *bash_argc_v;
3672 ARRAY *bash_argv_a, *bash_argc_a;
3673 WORD_LIST *l;
3674 arrayind_t i;
3675 char *t;
3676
3677 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3678 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3679
3680 for (l = list, i = 0; l; l = l->next, i++)
3681 array_push (bash_argv_a, l->word->word);
3682
3683 t = itos (i);
3684 array_push (bash_argc_a, t);
3685 free (t);
3686#endif /* ARRAY_VARS && DEBUGGER */
3687}
3688
3689/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
3690 array and use that value as the count of elements to remove from
3691 BASH_ARGV. */
3692void
3693pop_args ()
3694{
3695#if defined (ARRAY_VARS) && defined (DEBUGGER)
3696 SHELL_VAR *bash_argv_v, *bash_argc_v;
3697 ARRAY *bash_argv_a, *bash_argc_a;
3698 ARRAY_ELEMENT *ce;
3699 intmax_t i;
3700
3701 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3702 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3703
3704 ce = array_shift (bash_argc_a, 1, 0);
3705 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
3706 i = 0;
3707
3708 for ( ; i > 0; i--)
3709 array_pop (bash_argv_a);
3710 array_dispose_element (ce);
3711#endif /* ARRAY_VARS && DEBUGGER */
3712}
3713
cce855bc
JA
3714/*************************************************
3715 * *
3716 * Functions to manage special variables *
3717 * *
3718 *************************************************/
3719
3720/* Extern declarations for variables this code has to manage. */
3721extern int eof_encountered, eof_encountered_limit, ignoreeof;
3722
3723#if defined (READLINE)
cce855bc
JA
3724extern int hostname_list_initialized;
3725#endif
3726
3727/* An alist of name.function for each special variable. Most of the
3728 functions don't do much, and in fact, this would be faster with a
3729 switch statement, but by the end of this file, I am sick of switch
3730 statements. */
3731
3732#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
3733
7117c2d2 3734/* This table will be sorted with qsort() the first time it's accessed. */
cce855bc
JA
3735struct name_and_function {
3736 char *name;
f73dda09 3737 sh_sv_func_t *function;
7117c2d2 3738};
cce855bc 3739
7117c2d2 3740static struct name_and_function special_vars[] = {
95732b49
JA
3741#if defined (READLINE)
3742# if defined (STRICT_POSIX)
3743 { "COLUMNS", sv_winsize },
3744# endif
3745 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
3746#endif
3747
cce855bc
JA
3748 { "GLOBIGNORE", sv_globignore },
3749
cce855bc 3750#if defined (HISTORY)
7117c2d2
JA
3751 { "HISTCONTROL", sv_history_control },
3752 { "HISTFILESIZE", sv_histsize },
cce855bc
JA
3753 { "HISTIGNORE", sv_histignore },
3754 { "HISTSIZE", sv_histsize },
b80f6443 3755 { "HISTTIMEFORMAT", sv_histtimefmt },
7117c2d2 3756#endif
cce855bc 3757
95732b49
JA
3758#if defined (__CYGWIN__)
3759 { "HOME", sv_home },
3760#endif
3761
7117c2d2
JA
3762#if defined (READLINE)
3763 { "HOSTFILE", sv_hostfile },
3764#endif
cce855bc 3765
7117c2d2
JA
3766 { "IFS", sv_ifs },
3767 { "IGNOREEOF", sv_ignoreeof },
cce855bc 3768
7117c2d2 3769 { "LANG", sv_locale },
cce855bc
JA
3770 { "LC_ALL", sv_locale },
3771 { "LC_COLLATE", sv_locale },
3772 { "LC_CTYPE", sv_locale },
3773 { "LC_MESSAGES", sv_locale },
bb70624e 3774 { "LC_NUMERIC", sv_locale },
95732b49
JA
3775 { "LC_TIME", sv_locale },
3776
3777#if defined (READLINE) && defined (STRICT_POSIX)
3778 { "LINES", sv_winsize },
3779#endif
7117c2d2
JA
3780
3781 { "MAIL", sv_mail },
3782 { "MAILCHECK", sv_mail },
3783 { "MAILPATH", sv_mail },
3784
3785 { "OPTERR", sv_opterr },
3786 { "OPTIND", sv_optind },
3787
3788 { "PATH", sv_path },
3789 { "POSIXLY_CORRECT", sv_strict_posix },
3790
3791#if defined (READLINE)
3792 { "TERM", sv_terminal },
3793 { "TERMCAP", sv_terminal },
3794 { "TERMINFO", sv_terminal },
3795#endif /* READLINE */
3796
3797 { "TEXTDOMAIN", sv_locale },
3798 { "TEXTDOMAINDIR", sv_locale },
cce855bc
JA
3799
3800#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3801 { "TZ", sv_tz },
3802#endif
3803
7117c2d2
JA
3804#if defined (HISTORY) && defined (BANG_HISTORY)
3805 { "histchars", sv_histchars },
3806#endif /* HISTORY && BANG_HISTORY */
3807
3808 { "ignoreeof", sv_ignoreeof },
3809
f73dda09 3810 { (char *)0, (sh_sv_func_t *)0 }
cce855bc
JA
3811};
3812
7117c2d2
JA
3813#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
3814
3815static int
3816sv_compare (sv1, sv2)
3817 struct name_and_function *sv1, *sv2;
3818{
3819 int r;
3820
3821 if ((r = sv1->name[0] - sv2->name[0]) == 0)
3822 r = strcmp (sv1->name, sv2->name);
3823 return r;
3824}
3825
3826static inline int
3827find_special_var (name)
3828 const char *name;
3829{
3830 register int i, r;
3831
3832 for (i = 0; special_vars[i].name; i++)
3833 {
3834 r = special_vars[i].name[0] - name[0];
3835 if (r == 0)
3836 r = strcmp (special_vars[i].name, name);
3837 if (r == 0)
3838 return i;
3839 else if (r > 0)
3840 /* Can't match any of rest of elements in sorted list. Take this out
3841 if it causes problems in certain environments. */
3842 break;
3843 }
3844 return -1;
3845}
3846
cce855bc
JA
3847/* The variable in NAME has just had its state changed. Check to see if it
3848 is one of the special ones where something special happens. */
3849void
3850stupidly_hack_special_variables (name)
3851 char *name;
3852{
7117c2d2 3853 static int sv_sorted = 0;
cce855bc
JA
3854 int i;
3855
7117c2d2 3856 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
cce855bc 3857 {
7117c2d2
JA
3858 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
3859 (QSFUNC *)sv_compare);
3860 sv_sorted = 1;
cce855bc 3861 }
7117c2d2
JA
3862
3863 i = find_special_var (name);
3864 if (i != -1)
3865 (*(special_vars[i].function)) (name);
3866}
3867
3868void
3869sv_ifs (name)
3870 char *name;
3871{
3872 SHELL_VAR *v;
3873
3874 v = find_variable ("IFS");
3875 setifs (v);
cce855bc
JA
3876}
3877
3878/* What to do just after the PATH variable has changed. */
3879void
3880sv_path (name)
3881 char *name;
3882{
3883 /* hash -r */
7117c2d2 3884 phash_flush ();
cce855bc
JA
3885}
3886
3887/* What to do just after one of the MAILxxxx variables has changed. NAME
3888 is the name of the variable. This is called with NAME set to one of
3889 MAIL, MAILCHECK, or MAILPATH. */
3890void
3891sv_mail (name)
3892 char *name;
3893{
3894 /* If the time interval for checking the files has changed, then
3895 reset the mail timer. Otherwise, one of the pathname vars
3896 to the users mailbox has changed, so rebuild the array of
3897 filenames. */
3898 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
3899 reset_mail_timer ();
3900 else
3901 {
3902 free_mail_files ();
3903 remember_mail_dates ();
3904 }
3905}
3906
3907/* What to do when GLOBIGNORE changes. */
3908void
3909sv_globignore (name)
3910 char *name;
3911{
3912 setup_glob_ignore (name);
3913}
3914
3915#if defined (READLINE)
95732b49
JA
3916void
3917sv_comp_wordbreaks (name)
3918 char *name;
3919{
3920 SHELL_VAR *sv;
3921
3922 sv = find_variable (name);
3923 if (sv == 0)
3924 rl_completer_word_break_characters = (char *)NULL;
3925}
3926
cce855bc
JA
3927/* What to do just after one of the TERMxxx variables has changed.
3928 If we are an interactive shell, then try to reset the terminal
3929 information in readline. */
3930void
3931sv_terminal (name)
3932 char *name;
3933{
3934 if (interactive_shell && no_line_editing == 0)
3935 rl_reset_terminal (get_string_value ("TERM"));
3936}
3937
3938void
3939sv_hostfile (name)
3940 char *name;
3941{
bb70624e
JA
3942 SHELL_VAR *v;
3943
3944 v = find_variable (name);
3945 if (v == 0)
3946 clear_hostname_list ();
3947 else
3948 hostname_list_initialized = 0;
cce855bc 3949}
95732b49
JA
3950
3951#if defined (STRICT_POSIX)
3952/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
3953 found in the initial environment) to override the terminal size reported by
3954 the kernel. */
3955void
3956sv_winsize (name)
3957 char *name;
3958{
3959 SHELL_VAR *v;
3960 intmax_t xd;
3961 int d;
3962
3963 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
3964 return;
3965
3966 v = find_variable (name);
3967 if (v == 0 || var_isnull (v))
3968 rl_reset_screen_size ();
3969 else
3970 {
3971 if (legal_number (value_cell (v), &xd) == 0)
3972 return;
3973 winsize_assignment = winsize_assigned = 1;
3974 d = xd; /* truncate */
3975 if (name[0] == 'L') /* LINES */
3976 rl_set_screen_size (d, -1);
3977 else /* COLUMNS */
3978 rl_set_screen_size (-1, d);
3979 winsize_assignment = 0;
3980 }
3981}
3982#endif /* STRICT_POSIX */
cce855bc
JA
3983#endif /* READLINE */
3984
95732b49
JA
3985/* Update the value of HOME in the export environment so tilde expansion will
3986 work on cygwin. */
3987#if defined (__CYGWIN__)
3988sv_home (name)
3989 char *name;
3990{
3991 array_needs_making = 1;
3992 maybe_make_export_env ();
3993}
3994#endif
3995
cce855bc
JA
3996#if defined (HISTORY)
3997/* What to do after the HISTSIZE or HISTFILESIZE variables change.
3998 If there is a value for this HISTSIZE (and it is numeric), then stifle
3999 the history. Otherwise, if there is NO value for this variable,
4000 unstifle the history. If name is HISTFILESIZE, and its value is
4001 numeric, truncate the history file to hold no more than that many
4002 lines. */
4003void
4004sv_histsize (name)
4005 char *name;
4006{
4007 char *temp;
7117c2d2 4008 intmax_t num;
95732b49 4009 int hmax;
cce855bc
JA
4010
4011 temp = get_string_value (name);
4012
4013 if (temp && *temp)
4014 {
4015 if (legal_number (temp, &num))
28ef6c31 4016 {
cce855bc
JA
4017 if (name[4] == 'S')
4018 {
95732b49
JA
4019 hmax = num;
4020 stifle_history (hmax);
cce855bc
JA
4021 num = where_history ();
4022 if (history_lines_this_session > num)
4023 history_lines_this_session = num;
4024 }
4025 else
4026 {
4027 history_truncate_file (get_string_value ("HISTFILE"), (int)num);
4028 if (num <= history_lines_in_file)
4029 history_lines_in_file = num;
4030 }
4031 }
4032 }
4033 else if (name[4] == 'S')
4034 unstifle_history ();
4035}
4036
4037/* What to do after the HISTIGNORE variable changes. */
4038void
4039sv_histignore (name)
4040 char *name;
4041{
4042 setup_history_ignore (name);
4043}
4044
4045/* What to do after the HISTCONTROL variable changes. */
4046void
4047sv_history_control (name)
4048 char *name;
4049{
4050 char *temp;
b80f6443
JA
4051 char *val;
4052 int tptr;
cce855bc
JA
4053
4054 history_control = 0;
4055 temp = get_string_value (name);
4056
b80f6443
JA
4057 if (temp == 0 || *temp == 0)
4058 return;
4059
4060 tptr = 0;
4061 while (val = extract_colon_unit (temp, &tptr))
cce855bc 4062 {
b80f6443
JA
4063 if (STREQ (val, "ignorespace"))
4064 history_control |= HC_IGNSPACE;
4065 else if (STREQ (val, "ignoredups"))
4066 history_control |= HC_IGNDUPS;
4067 else if (STREQ (val, "ignoreboth"))
4068 history_control |= HC_IGNBOTH;
4069 else if (STREQ (val, "erasedups"))
4070 history_control |= HC_ERASEDUPS;
4071
4072 free (val);
cce855bc
JA
4073 }
4074}
4075
4076#if defined (BANG_HISTORY)
4077/* Setting/unsetting of the history expansion character. */
4078void
4079sv_histchars (name)
4080 char *name;
4081{
4082 char *temp;
4083
4084 temp = get_string_value (name);
4085 if (temp)
4086 {
4087 history_expansion_char = *temp;
4088 if (temp[0] && temp[1])
4089 {
4090 history_subst_char = temp[1];
4091 if (temp[2])
4092 history_comment_char = temp[2];
4093 }
4094 }
4095 else
4096 {
4097 history_expansion_char = '!';
4098 history_subst_char = '^';
4099 history_comment_char = '#';
4100 }
4101}
4102#endif /* BANG_HISTORY */
b80f6443
JA
4103
4104void
4105sv_histtimefmt (name)
4106 char *name;
4107{
4108 SHELL_VAR *v;
4109
4110 v = find_variable (name);
4111 history_write_timestamps = (v != 0);
4112}
cce855bc
JA
4113#endif /* HISTORY */
4114
4115#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
4116void
4117sv_tz (name)
4118 char *name;
4119{
4120 tzset ();
4121}
4122#endif
4123
4124/* If the variable exists, then the value of it can be the number
4125 of times we actually ignore the EOF. The default is small,
4126 (smaller than csh, anyway). */
4127void
4128sv_ignoreeof (name)
4129 char *name;
4130{
4131 SHELL_VAR *tmp_var;
4132 char *temp;
4133
4134 eof_encountered = 0;
4135
4136 tmp_var = find_variable (name);
4137 ignoreeof = tmp_var != 0;
4138 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4139 if (temp)
4140 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
4141 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
4142}
4143
4144void
4145sv_optind (name)
4146 char *name;
4147{
4148 char *tt;
4149 int s;
4150
4151 tt = get_string_value ("OPTIND");
4152 if (tt && *tt)
4153 {
4154 s = atoi (tt);
4155
4156 /* According to POSIX, setting OPTIND=1 resets the internal state
4157 of getopt (). */
4158 if (s < 0 || s == 1)
4159 s = 0;
4160 }
4161 else
4162 s = 0;
4163 getopts_reset (s);
4164}
4165
4166void
4167sv_opterr (name)
4168 char *name;
4169{
4170 char *tt;
4171
4172 tt = get_string_value ("OPTERR");
4173 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
4174}
4175
4176void
4177sv_strict_posix (name)
4178 char *name;
4179{
4180 SET_INT_VAR (name, posixly_correct);
4181 posix_initialize (posixly_correct);
4182#if defined (READLINE)
4183 if (interactive_shell)
4184 posix_readline_initialize (posixly_correct);
4185#endif /* READLINE */
4186 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
4187}
4188
4189void
4190sv_locale (name)
4191 char *name;
4192{
4193 char *v;
4194
4195 v = get_string_value (name);
4196 if (name[0] == 'L' && name[1] == 'A') /* LANG */
4197 set_lang (name, v);
4198 else
4199 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
4200}
4201
4202#if defined (ARRAY_VARS)
4203void
7117c2d2 4204set_pipestatus_array (ps, nproc)
cce855bc 4205 int *ps;
7117c2d2 4206 int nproc;
cce855bc
JA
4207{
4208 SHELL_VAR *v;
4209 ARRAY *a;
7117c2d2 4210 ARRAY_ELEMENT *ae;
cce855bc 4211 register int i;
f73dda09 4212 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
cce855bc
JA
4213
4214 v = find_variable ("PIPESTATUS");
4215 if (v == 0)
4216 v = make_new_array_variable ("PIPESTATUS");
4217 if (array_p (v) == 0)
4218 return; /* Do nothing if not an array variable. */
4219 a = array_cell (v);
7117c2d2
JA
4220
4221 if (a == 0 || array_num_elements (a) == 0)
cce855bc 4222 {
7117c2d2
JA
4223 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
4224 {
4225 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4226 array_insert (a, i, t);
4227 }
4228 return;
4229 }
4230
4231 /* Fast case */
4232 if (array_num_elements (a) == nproc && nproc == 1)
4233 {
4234 ae = element_forw (a->head);
4235 free (element_value (ae));
4236 ae->value = itos (ps[0]);
4237 }
4238 else if (array_num_elements (a) <= nproc)
4239 {
4240 /* modify in array_num_elements members in place, then add */
4241 ae = a->head;
4242 for (i = 0; i < array_num_elements (a); i++)
4243 {
4244 ae = element_forw (ae);
4245 free (element_value (ae));
4246 ae->value = itos (ps[i]);
4247 }
4248 /* add any more */
4249 for ( ; i < nproc; i++)
4250 {
4251 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4252 array_insert (a, i, t);
4253 }
4254 }
4255 else
4256 {
4257 /* deleting elements. it's faster to rebuild the array. */
4258 array_flush (a);
4259 for (i = 0; ps[i] != -1; i++)
4260 {
4261 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4262 array_insert (a, i, t);
4263 }
cce855bc
JA
4264 }
4265}
4266#endif
4267
4268void
4269set_pipestatus_from_exit (s)
4270 int s;
4271{
4272#if defined (ARRAY_VARS)
4273 static int v[2] = { 0, -1 };
4274
4275 v[0] = s;
7117c2d2 4276 set_pipestatus_array (v, 1);
cce855bc
JA
4277#endif
4278}