]> git.ipfire.org Git - thirdparty/bash.git/blame - variables.c
Bash-5.0 patch 1: fix pathname expansion of directory names containing backslashes
[thirdparty/bash.git] / variables.c
CommitLineData
726f6388
JA
1/* variables.c -- Functions for hacking shell variables. */
2
d233b485 3/* Copyright (C) 1987-2018 Free Software Foundation, Inc.
726f6388
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
726f6388 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
726f6388
JA
16
17 You should have received a copy of the GNU General Public License
3185942a
JA
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
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
3185942a
JA
27#if defined (__QNX__)
28# if defined (__QNXNTO__)
29# include <sys/netmgr.h>
95732b49
JA
30# else
31# include <sys/vc.h>
3185942a
JA
32# endif /* !__QNXNTO__ */
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"
3185942a
JA
41#if defined (HAVE_PWD_H)
42# include <pwd.h>
43#endif
726f6388 44#include "bashansi.h"
b80f6443 45#include "bashintl.h"
ccc6cda3 46
0001803f
CR
47#define NEED_XTRACE_SET_DECL
48
726f6388 49#include "shell.h"
d233b485 50#include "parser.h"
726f6388
JA
51#include "flags.h"
52#include "execute_cmd.h"
cce855bc 53#include "findcmd.h"
ccc6cda3
JA
54#include "mailcheck.h"
55#include "input.h"
f73dda09
JA
56#include "hashcmd.h"
57#include "pathexp.h"
3185942a 58#include "alias.h"
ac50fbac
CR
59#include "jobs.h"
60
61#include "version.h"
726f6388 62
d166f048 63#include "builtins/getopt.h"
726f6388 64#include "builtins/common.h"
ac50fbac 65#include "builtins/builtext.h"
cce855bc
JA
66
67#if defined (READLINE)
68# include "bashline.h"
69# include <readline/readline.h>
70#else
71# include <tilde/tilde.h>
72#endif
726f6388 73
ccc6cda3
JA
74#if defined (HISTORY)
75# include "bashhist.h"
cce855bc 76# include <readline/history.h>
ccc6cda3
JA
77#endif /* HISTORY */
78
bb70624e
JA
79#if defined (PROGRAMMABLE_COMPLETION)
80# include "pcomplete.h"
81#endif
82
a0c0a00f
CR
83#define VARIABLES_HASH_BUCKETS 1024 /* must be power of two */
84#define FUNCTIONS_HASH_BUCKETS 512
7117c2d2
JA
85#define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
86
3590145a
CR
87#define BASHFUNC_PREFIX "BASH_FUNC_"
88#define BASHFUNC_PREFLEN 10 /* == strlen(BASHFUNC_PREFIX */
89#define BASHFUNC_SUFFIX "%%"
90#define BASHFUNC_SUFFLEN 2 /* == strlen(BASHFUNC_SUFFIX) */
91
a0c0a00f
CR
92/* flags for find_variable_internal */
93
94#define FV_FORCETEMPENV 0x01
95#define FV_SKIPINVISIBLE 0x02
96
95732b49
JA
97extern char **environ;
98
726f6388 99/* Variables used here and defined in other files. */
726f6388 100extern time_t shell_start_time;
b80f6443 101
7117c2d2
JA
102/* The list of shell variables that the user has created at the global
103 scope, or that came from the environment. */
104VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
105
106/* The current list of shell variables, including function scopes */
107VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
726f6388
JA
108
109/* The list of shell functions that the user has created, or that came from
110 the environment. */
111HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
112
d233b485
CR
113HASH_TABLE *invalid_env = (HASH_TABLE *)NULL;
114
b80f6443
JA
115#if defined (DEBUGGER)
116/* The table of shell function definitions that the user defined or that
117 came from the environment. */
118HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
119#endif
120
726f6388
JA
121/* The current variable context. This is really a count of how deep into
122 executing functions we are. */
123int variable_context = 0;
124
d233b485
CR
125/* If non-zero, local variables inherit values and attributes from a variable
126 with the same name at a previous scope. */
127int localvar_inherit = 0;
128
129/* If non-zero, calling `unset' on local variables in previous scopes marks
130 them as invisible so lookups find them unset. This is the same behavior
131 as local variables in the current local scope. */
132int localvar_unset = 0;
133
7117c2d2 134/* The set of shell assignments which are made only in the environment
726f6388 135 for a single command. */
7117c2d2 136HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
726f6388 137
b80f6443
JA
138/* Set to non-zero if an assignment error occurs while putting variables
139 into the temporary environment. */
140int tempenv_assign_error;
141
726f6388
JA
142/* Some funky variables which are known about specially. Here is where
143 "$*", "$1", and all the cruft is kept. */
144char *dollar_vars[10];
145WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
146
147/* The value of $$. */
f73dda09 148pid_t dollar_dollar_pid;
726f6388 149
3185942a
JA
150/* Non-zero means that we have to remake EXPORT_ENV. */
151int array_needs_making = 1;
152
153/* The number of times BASH has been executed. This is set
154 by initialize_variables (). */
155int shell_level = 0;
156
726f6388 157/* An array which is passed to commands as their environment. It is
d166f048 158 manufactured from the union of the initial environment and the
726f6388
JA
159 shell variables that are marked for export. */
160char **export_env = (char **)NULL;
d166f048
JA
161static int export_env_index;
162static int export_env_size;
726f6388 163
95732b49
JA
164#if defined (READLINE)
165static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
95732b49
JA
166#endif
167
a0c0a00f
CR
168SHELL_VAR nameref_invalid_value;
169static SHELL_VAR nameref_maxloop_value;
170
ac50fbac 171static HASH_TABLE *last_table_searched; /* hash_lookup sets this */
d233b485 172static VAR_CONTEXT *last_context_searched;
ac50fbac 173
726f6388 174/* Some forward declarations. */
0628567a
JA
175static void create_variable_tables __P((void));
176
f73dda09
JA
177static void set_machine_vars __P((void));
178static void set_home_var __P((void));
179static void set_shell_var __P((void));
180static char *get_bash_name __P((void));
181static void initialize_shell_level __P((void));
182static void uidset __P((void));
183#if defined (ARRAY_VARS)
184static void make_vers_array __P((void));
185#endif
f73dda09 186
3185942a 187static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2 188#if defined (ARRAY_VARS)
3185942a 189static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2 190#endif
b80f6443
JA
191static SHELL_VAR *get_self __P((SHELL_VAR *));
192
193#if defined (ARRAY_VARS)
194static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
3185942a 195static SHELL_VAR *init_dynamic_assoc_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
b80f6443 196#endif
7117c2d2 197
3185942a 198static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2
JA
199static SHELL_VAR *get_seconds __P((SHELL_VAR *));
200static SHELL_VAR *init_seconds_var __P((void));
201
202static int brand __P((void));
f73dda09 203static void sbrand __P((unsigned long)); /* set bash random number generator. */
3185942a
JA
204static void seedrand __P((void)); /* seed generator randomly */
205static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2 206static SHELL_VAR *get_random __P((SHELL_VAR *));
f73dda09 207
3185942a 208static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2 209static SHELL_VAR *get_lineno __P((SHELL_VAR *));
f73dda09 210
3185942a 211static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t, char *));
b80f6443
JA
212static SHELL_VAR *get_subshell __P((SHELL_VAR *));
213
d233b485
CR
214static SHELL_VAR *get_epochseconds __P((SHELL_VAR *));
215static SHELL_VAR *get_epochrealtime __P((SHELL_VAR *));
216
3185942a
JA
217static SHELL_VAR *get_bashpid __P((SHELL_VAR *));
218
7117c2d2
JA
219#if defined (HISTORY)
220static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
221#endif
222
3185942a
JA
223#if defined (READLINE)
224static SHELL_VAR *get_comp_wordbreaks __P((SHELL_VAR *));
225static SHELL_VAR *assign_comp_wordbreaks __P((SHELL_VAR *, char *, arrayind_t, char *));
226#endif
227
7117c2d2 228#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
3185942a 229static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t, char *));
7117c2d2 230static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
7117c2d2
JA
231#endif
232
233#if defined (ARRAY_VARS)
234static SHELL_VAR *get_groupset __P((SHELL_VAR *));
d233b485
CR
235# if defined (DEBUGGER)
236static SHELL_VAR *get_bashargcv __P((SHELL_VAR *));
237# endif
3185942a
JA
238static SHELL_VAR *build_hashcmd __P((SHELL_VAR *));
239static SHELL_VAR *get_hashcmd __P((SHELL_VAR *));
240static SHELL_VAR *assign_hashcmd __P((SHELL_VAR *, char *, arrayind_t, char *));
0001803f 241# if defined (ALIAS)
3185942a
JA
242static SHELL_VAR *build_aliasvar __P((SHELL_VAR *));
243static SHELL_VAR *get_aliasvar __P((SHELL_VAR *));
244static SHELL_VAR *assign_aliasvar __P((SHELL_VAR *, char *, arrayind_t, char *));
0001803f 245# endif
7117c2d2
JA
246#endif
247
248static SHELL_VAR *get_funcname __P((SHELL_VAR *));
249static SHELL_VAR *init_funcname_var __P((void));
250
251static void initialize_dynamic_variables __P((void));
252
d233b485
CR
253static SHELL_VAR *bind_invalid_envvar __P((const char *, char *, int));
254
255static int var_sametype __P((SHELL_VAR *, SHELL_VAR *));
256
7117c2d2 257static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
f73dda09 258static SHELL_VAR *new_shell_variable __P((const char *));
7117c2d2 259static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
95732b49 260static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
7117c2d2 261
3185942a 262static void dispose_variable_value __P((SHELL_VAR *));
7117c2d2
JA
263static void free_variable_hash_data __P((PTR_T));
264
265static VARLIST *vlist_alloc __P((int));
266static VARLIST *vlist_realloc __P((VARLIST *, int));
267static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
268
269static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
270
271static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
f73dda09 272
7117c2d2
JA
273static SHELL_VAR **vapply __P((sh_var_map_func_t *));
274static SHELL_VAR **fapply __P((sh_var_map_func_t *));
f73dda09
JA
275
276static int visible_var __P((SHELL_VAR *));
f73dda09 277static int visible_and_exported __P((SHELL_VAR *));
89a92869 278static int export_environment_candidate __P((SHELL_VAR *));
7117c2d2
JA
279static int local_and_exported __P((SHELL_VAR *));
280static int variable_in_context __P((SHELL_VAR *));
f73dda09
JA
281#if defined (ARRAY_VARS)
282static int visible_array_vars __P((SHELL_VAR *));
283#endif
284
a0c0a00f
CR
285static SHELL_VAR *find_variable_internal __P((const char *, int));
286
ac50fbac
CR
287static SHELL_VAR *find_nameref_at_context __P((SHELL_VAR *, VAR_CONTEXT *));
288static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
289static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
290
7117c2d2 291static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
d233b485 292static void push_posix_temp_var __P((PTR_T));
7117c2d2
JA
293static void push_temp_var __P((PTR_T));
294static void propagate_temp_var __P((PTR_T));
295static void dispose_temporary_env __P((sh_free_func_t *));
296
3590145a 297static inline char *mk_env_string __P((const char *, const char *, int));
7117c2d2
JA
298static char **make_env_array_from_var_list __P((SHELL_VAR **));
299static char **make_var_export_array __P((VAR_CONTEXT *));
300static char **make_func_export_array __P((void));
301static void add_temp_array_to_env __P((char **, int, int));
f73dda09 302
7117c2d2
JA
303static int n_shell_variables __P((void));
304static int set_context __P((SHELL_VAR *));
726f6388 305
7117c2d2 306static void push_func_var __P((PTR_T));
d233b485 307static void push_builtin_var __P((PTR_T));
7117c2d2 308static void push_exported_var __P((PTR_T));
726f6388 309
d233b485
CR
310static inline void push_posix_tempvar_internal __P((SHELL_VAR *, int));
311
7117c2d2 312static inline int find_special_var __P((const char *));
726f6388 313
0628567a
JA
314static void
315create_variable_tables ()
316{
cce855bc 317 if (shell_variables == 0)
7117c2d2
JA
318 {
319 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
320 shell_variables->scope = 0;
a0c0a00f 321 shell_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
7117c2d2 322 }
726f6388 323
cce855bc 324 if (shell_functions == 0)
a0c0a00f 325 shell_functions = hash_create (FUNCTIONS_HASH_BUCKETS);
726f6388 326
b80f6443
JA
327#if defined (DEBUGGER)
328 if (shell_function_defs == 0)
a0c0a00f 329 shell_function_defs = hash_create (FUNCTIONS_HASH_BUCKETS);
b80f6443 330#endif
0628567a
JA
331}
332
333/* Initialize the shell variables from the current environment.
334 If PRIVMODE is nonzero, don't import functions from ENV or
335 parse $SHELLOPTS. */
336void
337initialize_shell_variables (env, privmode)
338 char **env;
339 int privmode;
340{
341 char *name, *string, *temp_string;
ac50fbac 342 int c, char_index, string_index, string_length, ro;
0628567a
JA
343 SHELL_VAR *temp_var;
344
345 create_variable_tables ();
b80f6443 346
a0c0a00f 347 for (string_index = 0; env && (string = env[string_index++]); )
726f6388 348 {
726f6388 349 char_index = 0;
d166f048 350 name = string;
726f6388 351 while ((c = *string++) && c != '=')
d166f048
JA
352 ;
353 if (string[-1] == '=')
28ef6c31 354 char_index = string - name - 1;
726f6388 355
d166f048
JA
356 /* If there are weird things in the environment, like `=xxx' or a
357 string without an `=', just skip them. */
358 if (char_index == 0)
28ef6c31 359 continue;
d166f048
JA
360
361 /* ASSERT(name[char_index] == '=') */
726f6388 362 name[char_index] = '\0';
d166f048 363 /* Now, name = env variable name, string = env variable value, and
28ef6c31 364 char_index == strlen (name) */
726f6388 365
3185942a
JA
366 temp_var = (SHELL_VAR *)NULL;
367
a0c0a00f 368#if defined (FUNCTION_IMPORT)
f73dda09 369 /* If exported function, define it now. Don't import functions from
7117c2d2 370 the environment in privileged mode. */
3590145a
CR
371 if (privmode == 0 && read_but_dont_execute == 0 &&
372 STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) &&
373 STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) &&
374 STREQN ("() {", string, 4))
726f6388 375 {
3590145a
CR
376 size_t namelen;
377 char *tname; /* desired imported function name */
378
379 namelen = char_index - BASHFUNC_PREFLEN - BASHFUNC_SUFFLEN;
380
381 tname = name + BASHFUNC_PREFLEN; /* start of func name */
382 tname[namelen] = '\0'; /* now tname == func name */
383
d166f048 384 string_length = strlen (string);
3590145a 385 temp_string = (char *)xmalloc (namelen + string_length + 2);
bb70624e 386
3590145a
CR
387 memcpy (temp_string, tname, namelen);
388 temp_string[namelen] = ' ';
389 memcpy (temp_string + namelen + 1, string, string_length + 1);
726f6388 390
b64a0e1d 391 /* Don't import function names that are invalid identifiers from the
a0c0a00f
CR
392 environment in posix mode, though we still allow them to be defined as
393 shell variables. */
3590145a
CR
394 if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname)))
395 parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
a0c0a00f
CR
396 else
397 free (temp_string); /* parse_and_execute does this */
726f6388 398
3590145a 399 if (temp_var = find_function (tname))
726f6388 400 {
bb70624e 401 VSETATTR (temp_var, (att_exported|att_imported));
726f6388
JA
402 array_needs_making = 1;
403 }
404 else
ac50fbac 405 {
d233b485 406 if (temp_var = bind_invalid_envvar (name, string, 0))
ac50fbac
CR
407 {
408 VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
409 array_needs_making = 1;
410 }
411 last_command_exit_value = 1;
3590145a 412 report_error (_("error importing function definition for `%s'"), tname);
ac50fbac 413 }
3590145a
CR
414
415 /* Restore original suffix */
416 tname[namelen] = BASHFUNC_SUFFIX[0];
726f6388 417 }
a0c0a00f
CR
418 else
419#endif /* FUNCTION_IMPORT */
ccc6cda3 420#if defined (ARRAY_VARS)
ac50fbac 421# if ARRAY_EXPORT
ccc6cda3 422 /* Array variables may not yet be exported. */
a0c0a00f 423 if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
ccc6cda3
JA
424 {
425 string_length = 1;
426 temp_string = extract_array_assignment_list (string, &string_length);
a0c0a00f 427 temp_var = assign_array_from_string (name, temp_string, 0);
ccc6cda3 428 FREE (temp_string);
bb70624e 429 VSETATTR (temp_var, (att_exported | att_imported));
ccc6cda3
JA
430 array_needs_making = 1;
431 }
89a92869 432 else
a0c0a00f 433# endif /* ARRAY_EXPORT */
89a92869 434#endif
726f6388 435 {
ac50fbac 436 ro = 0;
d233b485
CR
437 /* If we processed a command-line option that caused SHELLOPTS to be
438 set, it may already be set (and read-only) by the time we process
439 the shell's environment. */
440 if (/* posixly_correct &&*/ STREQ (name, "SHELLOPTS"))
ac50fbac
CR
441 {
442 temp_var = find_variable ("SHELLOPTS");
443 ro = temp_var && readonly_p (temp_var);
444 if (temp_var)
445 VUNSETATTR (temp_var, att_readonly);
446 }
d233b485 447 if (legal_identifier (name))
495aee44 448 {
d233b485
CR
449 temp_var = bind_variable (name, string, 0);
450 if (temp_var)
451 {
452 VSETATTR (temp_var, (att_exported | att_imported));
453 if (ro)
454 VSETATTR (temp_var, att_readonly);
455 }
456 }
457 else
458 {
459 temp_var = bind_invalid_envvar (name, string, 0);
460 if (temp_var)
495aee44 461 VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
495aee44 462 }
d233b485
CR
463 if (temp_var)
464 array_needs_making = 1;
726f6388 465 }
d166f048
JA
466
467 name[char_index] = '=';
bb70624e 468 /* temp_var can be NULL if it was an exported function with a syntax
28ef6c31 469 error (a different bug, but it still shouldn't dump core). */
bb70624e
JA
470 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
471 {
472 CACHE_IMPORTSTR (temp_var, name);
473 }
726f6388
JA
474 }
475
28ef6c31 476 set_pwd ();
b72432fd 477
ccc6cda3 478 /* Set up initial value of $_ */
95732b49 479 temp_var = set_if_not ("_", dollar_vars[0]);
ccc6cda3 480
726f6388 481 /* Remember this pid. */
f73dda09 482 dollar_dollar_pid = getpid ();
726f6388
JA
483
484 /* Now make our own defaults in case the vars that we think are
485 important are missing. */
486 temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
726f6388 487 temp_var = set_if_not ("TERM", "dumb");
726f6388 488
3185942a 489#if defined (__QNX__)
d166f048
JA
490 /* set node id -- don't import it from the environment */
491 {
492 char node_name[22];
3185942a 493# if defined (__QNXNTO__)
95732b49
JA
494 netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
495# else
d166f048 496 qnx_nidtostr (getnid (), node_name, sizeof (node_name));
95732b49
JA
497# endif
498 temp_var = bind_variable ("NODE", node_name, 0);
a0c0a00f
CR
499 if (temp_var)
500 set_auto_export (temp_var);
d166f048
JA
501 }
502#endif
503
ccc6cda3 504 /* set up the prompts. */
726f6388
JA
505 if (interactive_shell)
506 {
b72432fd 507#if defined (PROMPT_STRING_DECODE)
726f6388 508 set_if_not ("PS1", primary_prompt);
b72432fd
JA
509#else
510 if (current_user.uid == -1)
511 get_current_user_info ();
512 set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
513#endif
726f6388
JA
514 set_if_not ("PS2", secondary_prompt);
515 }
a0c0a00f
CR
516
517 if (current_user.euid == 0)
518 bind_variable ("PS4", "+ ", 0);
519 else
520 set_if_not ("PS4", "+ ");
726f6388 521
ccc6cda3 522 /* Don't allow IFS to be imported from the environment. */
95732b49 523 temp_var = bind_variable ("IFS", " \t\n", 0);
7117c2d2 524 setifs (temp_var);
726f6388
JA
525
526 /* Magic machine types. Pretty convenient. */
f73dda09 527 set_machine_vars ();
726f6388 528
ccc6cda3
JA
529 /* Default MAILCHECK for interactive shells. Defer the creation of a
530 default MAILPATH until the startup files are read, because MAIL
f73dda09 531 names a mail file if MAILPATH is not set, and we should provide a
ccc6cda3 532 default only if neither is set. */
726f6388 533 if (interactive_shell)
95732b49
JA
534 {
535 temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
536 VSETATTR (temp_var, att_integer);
537 }
726f6388
JA
538
539 /* Do some things with shell level. */
d166f048 540 initialize_shell_level ();
726f6388 541
b72432fd 542 set_ppid ();
726f6388 543
726f6388 544 /* Initialize the `getopts' stuff. */
95732b49
JA
545 temp_var = bind_variable ("OPTIND", "1", 0);
546 VSETATTR (temp_var, att_integer);
d166f048 547 getopts_reset (0);
95732b49 548 bind_variable ("OPTERR", "1", 0);
d166f048
JA
549 sh_opterr = 1;
550
0628567a 551 if (login_shell == 1 && posixly_correct == 0)
d166f048 552 set_home_var ();
726f6388
JA
553
554 /* Get the full pathname to THIS shell, and set the BASH variable
555 to it. */
d166f048 556 name = get_bash_name ();
95732b49 557 temp_var = bind_variable ("BASH", name, 0);
ccc6cda3
JA
558 free (name);
559
560 /* Make the exported environment variable SHELL be the user's login
561 shell. Note that the `tset' command looks at this variable
562 to determine what style of commands to output; if it ends in "csh",
563 then C-shell commands are output, else Bourne shell commands. */
d166f048 564 set_shell_var ();
726f6388
JA
565
566 /* Make a variable called BASH_VERSION which contains the version info. */
95732b49 567 bind_variable ("BASH_VERSION", shell_version_string (), 0);
ccc6cda3
JA
568#if defined (ARRAY_VARS)
569 make_vers_array ();
570#endif
726f6388 571
b80f6443 572 if (command_execution_string)
95732b49 573 bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
b80f6443 574
726f6388
JA
575 /* Find out if we're supposed to be in Posix.2 mode via an
576 environment variable. */
577 temp_var = find_variable ("POSIXLY_CORRECT");
578 if (!temp_var)
579 temp_var = find_variable ("POSIX_PEDANTIC");
580 if (temp_var && imported_p (temp_var))
581 sv_strict_posix (temp_var->name);
582
583#if defined (HISTORY)
584 /* Set history variables to defaults, and then do whatever we would
585 do if the variable had just been set. Do this only in the case
586 that we are remembering commands on the history list. */
587 if (remember_on_history)
588 {
7117c2d2 589 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
726f6388
JA
590
591 set_if_not ("HISTFILE", name);
592 free (name);
726f6388
JA
593 }
594#endif /* HISTORY */
595
596 /* Seed the random number generator. */
3185942a 597 seedrand ();
726f6388
JA
598
599 /* Handle some "special" variables that we may have inherited from a
600 parent shell. */
d166f048
JA
601 if (interactive_shell)
602 {
603 temp_var = find_variable ("IGNOREEOF");
604 if (!temp_var)
605 temp_var = find_variable ("ignoreeof");
606 if (temp_var && imported_p (temp_var))
607 sv_ignoreeof (temp_var->name);
608 }
726f6388
JA
609
610#if defined (HISTORY)
611 if (interactive_shell && remember_on_history)
612 {
ccc6cda3
JA
613 sv_history_control ("HISTCONTROL");
614 sv_histignore ("HISTIGNORE");
3185942a 615 sv_histtimefmt ("HISTTIMEFORMAT");
726f6388
JA
616 }
617#endif /* HISTORY */
618
95732b49 619#if defined (READLINE) && defined (STRICT_POSIX)
d233b485
CR
620 /* POSIXLY_CORRECT will be 1 here if the shell was compiled
621 -DSTRICT_POSIX or if POSIXLY_CORRECT was supplied in the shell's
622 environment */
95732b49
JA
623 if (interactive_shell && posixly_correct && no_line_editing == 0)
624 rl_prefer_env_winsize = 1;
625#endif /* READLINE && STRICT_POSIX */
626
f73dda09
JA
627 /*
628 * 24 October 2001
629 *
630 * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
631 * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
632 * isnetconn() to avoid running the startup files more often than wanted.
633 * That will, of course, only work if the user's login shell is bash, so
634 * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
635 * in config-top.h.
636 */
637#if 0
bb70624e 638 temp_var = find_variable ("SSH_CLIENT");
28ef6c31
JA
639 if (temp_var && imported_p (temp_var))
640 {
641 VUNSETATTR (temp_var, att_exported);
642 array_needs_making = 1;
643 }
644 temp_var = find_variable ("SSH2_CLIENT");
bb70624e
JA
645 if (temp_var && imported_p (temp_var))
646 {
647 VUNSETATTR (temp_var, att_exported);
648 array_needs_making = 1;
649 }
f73dda09 650#endif
bb70624e 651
ccc6cda3
JA
652 /* Get the user's real and effective user ids. */
653 uidset ();
654
495aee44
CR
655 temp_var = find_variable ("BASH_XTRACEFD");
656 if (temp_var && imported_p (temp_var))
657 sv_xtracefd (temp_var->name);
658
a0c0a00f
CR
659 sv_shcompat ("BASH_COMPAT");
660
661 /* Allow FUNCNEST to be inherited from the environment. */
662 sv_funcnest ("FUNCNEST");
663
726f6388
JA
664 /* Initialize the dynamic variables, and seed their values. */
665 initialize_dynamic_variables ();
726f6388
JA
666}
667
7117c2d2
JA
668/* **************************************************************** */
669/* */
670/* Setting values for special shell variables */
671/* */
672/* **************************************************************** */
673
f73dda09
JA
674static void
675set_machine_vars ()
676{
677 SHELL_VAR *temp_var;
678
679 temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
680 temp_var = set_if_not ("OSTYPE", OSTYPE);
681 temp_var = set_if_not ("MACHTYPE", MACHTYPE);
682
683 temp_var = set_if_not ("HOSTNAME", current_host_name);
684}
685
d166f048
JA
686/* Set $HOME to the information in the password file if we didn't get
687 it from the environment. */
b72432fd
JA
688
689/* This function is not static so the tilde and readline libraries can
690 use it. */
691char *
28ef6c31 692sh_get_home_dir ()
b72432fd
JA
693{
694 if (current_user.home_dir == 0)
695 get_current_user_info ();
696 return current_user.home_dir;
697}
698
d166f048
JA
699static void
700set_home_var ()
701{
702 SHELL_VAR *temp_var;
703
704 temp_var = find_variable ("HOME");
705 if (temp_var == 0)
95732b49 706 temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
f73dda09 707#if 0
bb70624e 708 VSETATTR (temp_var, att_exported);
f73dda09 709#endif
d166f048
JA
710}
711
712/* Set $SHELL to the user's login shell if it is not already set. Call
713 get_current_user_info if we haven't already fetched the shell. */
714static void
715set_shell_var ()
716{
717 SHELL_VAR *temp_var;
718
719 temp_var = find_variable ("SHELL");
720 if (temp_var == 0)
721 {
722 if (current_user.shell == 0)
723 get_current_user_info ();
95732b49 724 temp_var = bind_variable ("SHELL", current_user.shell, 0);
d166f048 725 }
f73dda09 726#if 0
bb70624e 727 VSETATTR (temp_var, att_exported);
f73dda09 728#endif
d166f048
JA
729}
730
731static char *
732get_bash_name ()
733{
734 char *name;
735
28ef6c31 736 if ((login_shell == 1) && RELPATH(shell_name))
d166f048
JA
737 {
738 if (current_user.shell == 0)
28ef6c31 739 get_current_user_info ();
d166f048
JA
740 name = savestring (current_user.shell);
741 }
28ef6c31 742 else if (ABSPATH(shell_name))
d166f048
JA
743 name = savestring (shell_name);
744 else if (shell_name[0] == '.' && shell_name[1] == '/')
745 {
746 /* Fast path for common case. */
747 char *cdir;
748 int len;
749
750 cdir = get_string_value ("PWD");
28ef6c31
JA
751 if (cdir)
752 {
753 len = strlen (cdir);
f73dda09 754 name = (char *)xmalloc (len + strlen (shell_name) + 1);
28ef6c31
JA
755 strcpy (name, cdir);
756 strcpy (name + len, shell_name + 1);
757 }
758 else
759 name = savestring (shell_name);
d166f048
JA
760 }
761 else
762 {
763 char *tname;
764 int s;
765
766 tname = find_user_command (shell_name);
767
768 if (tname == 0)
769 {
770 /* Try the current directory. If there is not an executable
771 there, just punt and use the login shell. */
772 s = file_status (shell_name);
773 if (s & FS_EXECABLE)
774 {
775 tname = make_absolute (shell_name, get_string_value ("PWD"));
776 if (*shell_name == '.')
777 {
28ef6c31 778 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
d166f048
JA
779 if (name == 0)
780 name = tname;
781 else
782 free (tname);
783 }
784 else
785 name = tname;
786 }
787 else
788 {
789 if (current_user.shell == 0)
790 get_current_user_info ();
791 name = savestring (current_user.shell);
792 }
793 }
794 else
795 {
796 name = full_pathname (tname);
797 free (tname);
798 }
799 }
800
801 return (name);
802}
803
726f6388
JA
804void
805adjust_shell_level (change)
806 int change;
807{
d166f048 808 char new_level[5], *old_SHLVL;
7117c2d2 809 intmax_t old_level;
d166f048 810 SHELL_VAR *temp_var;
726f6388
JA
811
812 old_SHLVL = get_string_value ("SHLVL");
f73dda09
JA
813 if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
814 old_level = 0;
726f6388
JA
815
816 shell_level = old_level + change;
817 if (shell_level < 0)
818 shell_level = 0;
a0c0a00f 819 else if (shell_level >= 1000)
d166f048 820 {
b80f6443 821 internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
d166f048
JA
822 shell_level = 1;
823 }
824
825 /* We don't need the full generality of itos here. */
826 if (shell_level < 10)
827 {
828 new_level[0] = shell_level + '0';
829 new_level[1] = '\0';
830 }
831 else if (shell_level < 100)
832 {
833 new_level[0] = (shell_level / 10) + '0';
834 new_level[1] = (shell_level % 10) + '0';
835 new_level[2] = '\0';
836 }
837 else if (shell_level < 1000)
838 {
839 new_level[0] = (shell_level / 100) + '0';
840 old_level = shell_level % 100;
841 new_level[1] = (old_level / 10) + '0';
842 new_level[2] = (old_level % 10) + '0';
843 new_level[3] = '\0';
844 }
845
95732b49 846 temp_var = bind_variable ("SHLVL", new_level, 0);
d166f048
JA
847 set_auto_export (temp_var);
848}
849
850static void
851initialize_shell_level ()
852{
d166f048 853 adjust_shell_level (1);
726f6388
JA
854}
855
28ef6c31
JA
856/* If we got PWD from the environment, update our idea of the current
857 working directory. In any case, make sure that PWD exists before
858 checking it. It is possible for getcwd () to fail on shell startup,
859 and in that case, PWD would be undefined. If this is an interactive
860 login shell, see if $HOME is the current working directory, and if
861 that's not the same string as $PWD, set PWD=$HOME. */
862
863void
864set_pwd ()
865{
866 SHELL_VAR *temp_var, *home_var;
a0c0a00f 867 char *temp_string, *home_string, *current_dir;
28ef6c31
JA
868
869 home_var = find_variable ("HOME");
870 home_string = home_var ? value_cell (home_var) : (char *)NULL;
871
872 temp_var = find_variable ("PWD");
a0c0a00f 873 /* Follow posix rules for importing PWD */
28ef6c31
JA
874 if (temp_var && imported_p (temp_var) &&
875 (temp_string = value_cell (temp_var)) &&
a0c0a00f 876 temp_string[0] == '/' &&
28ef6c31 877 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
a0c0a00f
CR
878 {
879 current_dir = sh_canonpath (temp_string, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
880 if (current_dir == 0)
881 current_dir = get_working_directory ("shell_init");
d233b485 882 else
a0c0a00f 883 set_working_directory (current_dir);
d233b485
CR
884 if (posixly_correct && current_dir)
885 {
886 temp_var = bind_variable ("PWD", current_dir, 0);
887 set_auto_export (temp_var);
888 }
a0c0a00f
CR
889 free (current_dir);
890 }
28ef6c31
JA
891 else if (home_string && interactive_shell && login_shell &&
892 same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
893 {
894 set_working_directory (home_string);
95732b49 895 temp_var = bind_variable ("PWD", home_string, 0);
28ef6c31
JA
896 set_auto_export (temp_var);
897 }
898 else
899 {
900 temp_string = get_working_directory ("shell-init");
901 if (temp_string)
902 {
95732b49 903 temp_var = bind_variable ("PWD", temp_string, 0);
28ef6c31
JA
904 set_auto_export (temp_var);
905 free (temp_string);
906 }
907 }
908
909 /* According to the Single Unix Specification, v2, $OLDPWD is an
a0c0a00f
CR
910 `environment variable' and therefore should be auto-exported. If we
911 don't find OLDPWD in the environment, or it doesn't name a directory,
912 make a dummy invisible variable for OLDPWD, and mark it as exported. */
913 temp_var = find_variable ("OLDPWD");
d233b485 914#if defined (OLDPWD_CHECK_DIRECTORY)
a0c0a00f 915 if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
d233b485
CR
916#else
917 if (temp_var == 0 || value_cell (temp_var) == 0)
918#endif
a0c0a00f
CR
919 {
920 temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
921 VSETATTR (temp_var, (att_exported | att_invisible));
922 }
28ef6c31
JA
923}
924
b72432fd
JA
925/* Make a variable $PPID, which holds the pid of the shell's parent. */
926void
927set_ppid ()
928{
f73dda09 929 char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
b72432fd
JA
930 SHELL_VAR *temp_var;
931
f73dda09 932 name = inttostr (getppid (), namebuf, sizeof(namebuf));
b72432fd
JA
933 temp_var = find_variable ("PPID");
934 if (temp_var)
bb70624e 935 VUNSETATTR (temp_var, (att_readonly | att_exported));
95732b49 936 temp_var = bind_variable ("PPID", name, 0);
bb70624e 937 VSETATTR (temp_var, (att_readonly | att_integer));
b72432fd
JA
938}
939
ccc6cda3
JA
940static void
941uidset ()
726f6388 942{
f73dda09 943 char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
ccc6cda3
JA
944 register SHELL_VAR *v;
945
b72432fd 946 b = inttostr (current_user.uid, buff, sizeof (buff));
ccc6cda3 947 v = find_variable ("UID");
28ef6c31
JA
948 if (v == 0)
949 {
95732b49 950 v = bind_variable ("UID", b, 0);
28ef6c31
JA
951 VSETATTR (v, (att_readonly | att_integer));
952 }
726f6388 953
ccc6cda3 954 if (current_user.euid != current_user.uid)
b72432fd 955 b = inttostr (current_user.euid, buff, sizeof (buff));
726f6388 956
ccc6cda3 957 v = find_variable ("EUID");
28ef6c31
JA
958 if (v == 0)
959 {
95732b49 960 v = bind_variable ("EUID", b, 0);
28ef6c31
JA
961 VSETATTR (v, (att_readonly | att_integer));
962 }
ccc6cda3
JA
963}
964
965#if defined (ARRAY_VARS)
966static void
967make_vers_array ()
968{
969 SHELL_VAR *vv;
970 ARRAY *av;
f73dda09 971 char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
ccc6cda3 972
a0c0a00f 973 unbind_variable_noref ("BASH_VERSINFO");
ccc6cda3
JA
974
975 vv = make_new_array_variable ("BASH_VERSINFO");
976 av = array_cell (vv);
977 strcpy (d, dist_version);
0001803f 978 s = strchr (d, '.');
ccc6cda3
JA
979 if (s)
980 *s++ = '\0';
7117c2d2
JA
981 array_insert (av, 0, d);
982 array_insert (av, 1, s);
f73dda09 983 s = inttostr (patch_level, b, sizeof (b));
7117c2d2 984 array_insert (av, 2, s);
f73dda09 985 s = inttostr (build_version, b, sizeof (b));
7117c2d2
JA
986 array_insert (av, 3, s);
987 array_insert (av, 4, release_status);
988 array_insert (av, 5, MACHTYPE);
ccc6cda3 989
bb70624e 990 VSETATTR (vv, att_readonly);
ccc6cda3
JA
991}
992#endif /* ARRAY_VARS */
993
994/* Set the environment variables $LINES and $COLUMNS in response to
995 a window size change. */
996void
28ef6c31 997sh_set_lines_and_columns (lines, cols)
ccc6cda3
JA
998 int lines, cols;
999{
f73dda09 1000 char val[INT_STRLEN_BOUND(int) + 1], *v;
ccc6cda3 1001
0628567a 1002#if defined (READLINE)
95732b49
JA
1003 /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
1004 if (winsize_assignment)
1005 return;
0628567a 1006#endif
95732b49 1007
b72432fd 1008 v = inttostr (lines, val, sizeof (val));
95732b49 1009 bind_variable ("LINES", v, 0);
ccc6cda3 1010
b72432fd 1011 v = inttostr (cols, val, sizeof (val));
95732b49 1012 bind_variable ("COLUMNS", v, 0);
726f6388
JA
1013}
1014
7117c2d2
JA
1015/* **************************************************************** */
1016/* */
1017/* Printing variables and values */
1018/* */
1019/* **************************************************************** */
726f6388 1020
28ef6c31
JA
1021/* Print LIST (a list of shell variables) to stdout in such a way that
1022 they can be read back in. */
726f6388
JA
1023void
1024print_var_list (list)
1025 register SHELL_VAR **list;
1026{
1027 register int i;
1028 register SHELL_VAR *var;
1029
1030 for (i = 0; list && (var = list[i]); i++)
7117c2d2 1031 if (invisible_p (var) == 0)
726f6388
JA
1032 print_assignment (var);
1033}
1034
28ef6c31
JA
1035/* Print LIST (a list of shell functions) to stdout in such a way that
1036 they can be read back in. */
1037void
1038print_func_list (list)
1039 register SHELL_VAR **list;
1040{
1041 register int i;
1042 register SHELL_VAR *var;
1043
1044 for (i = 0; list && (var = list[i]); i++)
1045 {
1046 printf ("%s ", var->name);
1047 print_var_function (var);
1048 printf ("\n");
1049 }
1050}
1051
726f6388
JA
1052/* Print the value of a single SHELL_VAR. No newline is
1053 output, but the variable is printed in such a way that
1054 it can be read back in. */
1055void
1056print_assignment (var)
1057 SHELL_VAR *var;
1058{
7117c2d2
JA
1059 if (var_isset (var) == 0)
1060 return;
1061
1062 if (function_p (var))
726f6388 1063 {
28ef6c31 1064 printf ("%s", var->name);
726f6388
JA
1065 print_var_function (var);
1066 printf ("\n");
1067 }
ccc6cda3 1068#if defined (ARRAY_VARS)
7117c2d2 1069 else if (array_p (var))
ccc6cda3 1070 print_array_assignment (var, 0);
3185942a
JA
1071 else if (assoc_p (var))
1072 print_assoc_assignment (var, 0);
ccc6cda3 1073#endif /* ARRAY_VARS */
7117c2d2 1074 else
726f6388
JA
1075 {
1076 printf ("%s=", var->name);
ccc6cda3 1077 print_var_value (var, 1);
726f6388
JA
1078 printf ("\n");
1079 }
1080}
1081
1082/* Print the value cell of VAR, a shell variable. Do not print
ccc6cda3
JA
1083 the name, nor leading/trailing newline. If QUOTE is non-zero,
1084 and the value contains shell metacharacters, quote the value
1085 in such a way that it can be read back in. */
726f6388 1086void
ccc6cda3 1087print_var_value (var, quote)
726f6388 1088 SHELL_VAR *var;
ccc6cda3 1089 int quote;
726f6388 1090{
ccc6cda3
JA
1091 char *t;
1092
7117c2d2
JA
1093 if (var_isset (var) == 0)
1094 return;
1095
1096 if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
ccc6cda3 1097 {
7117c2d2
JA
1098 t = ansic_quote (value_cell (var), 0, (int *)0);
1099 printf ("%s", t);
1100 free (t);
1101 }
1102 else if (quote && sh_contains_shell_metas (value_cell (var)))
1103 {
1104 t = sh_single_quote (value_cell (var));
1105 printf ("%s", t);
1106 free (t);
ccc6cda3 1107 }
7117c2d2
JA
1108 else
1109 printf ("%s", value_cell (var));
726f6388
JA
1110}
1111
1112/* Print the function cell of VAR, a shell variable. Do not
1113 print the name, nor leading/trailing newline. */
1114void
1115print_var_function (var)
1116 SHELL_VAR *var;
1117{
3185942a
JA
1118 char *x;
1119
7117c2d2 1120 if (function_p (var) && var_isset (var))
3185942a
JA
1121 {
1122 x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
1123 printf ("%s", x);
1124 }
726f6388
JA
1125}
1126
1127/* **************************************************************** */
ccc6cda3 1128/* */
7117c2d2 1129/* Dynamic Variables */
ccc6cda3 1130/* */
726f6388
JA
1131/* **************************************************************** */
1132
1133/* DYNAMIC VARIABLES
ccc6cda3 1134
726f6388
JA
1135 These are variables whose values are generated anew each time they are
1136 referenced. These are implemented using a pair of function pointers
7117c2d2
JA
1137 in the struct variable: assign_func, which is called from bind_variable
1138 and, if arrays are compiled into the shell, some of the functions in
1139 arrayfunc.c, and dynamic_value, which is called from find_variable.
1140
1141 assign_func is called from bind_variable_internal, if
1142 bind_variable_internal discovers that the variable being assigned to
1143 has such a function. The function is called as
1144 SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
726f6388 1145 and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
7117c2d2
JA
1146 is usually ENTRY (self). IND is an index for an array variable, and
1147 unused otherwise.
ccc6cda3 1148
7117c2d2
JA
1149 dynamic_value is called from find_variable_internal to return a `new'
1150 value for the specified dynamic varible. If this function is NULL,
1151 the variable is treated as a `normal' shell variable. If it is not,
1152 however, then this function is called like this:
1153 tempvar = (*(var->dynamic_value)) (var);
ccc6cda3 1154
726f6388
JA
1155 Sometimes `tempvar' will replace the value of `var'. Other times, the
1156 shell will simply use the string value. Pretty object-oriented, huh?
ccc6cda3 1157
726f6388
JA
1158 Be warned, though: if you `unset' a special variable, it loses its
1159 special meaning, even if you subsequently set it.
ccc6cda3 1160
726f6388 1161 The special assignment code would probably have been better put in
7117c2d2 1162 subst.c: do_assignment_internal, in the same style as
726f6388
JA
1163 stupidly_hack_special_variables, but I wanted the changes as
1164 localized as possible. */
1165
f73dda09
JA
1166#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1167 do \
1168 { \
95732b49 1169 v = bind_variable (var, (val), 0); \
f73dda09
JA
1170 v->dynamic_value = gfunc; \
1171 v->assign_func = afunc; \
1172 } \
1173 while (0)
1174
1175#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1176 do \
1177 { \
1178 v = make_new_array_variable (var); \
1179 v->dynamic_value = gfunc; \
1180 v->assign_func = afunc; \
1181 } \
1182 while (0)
1183
3185942a
JA
1184#define INIT_DYNAMIC_ASSOC_VAR(var, gfunc, afunc) \
1185 do \
1186 { \
1187 v = make_new_assoc_variable (var); \
1188 v->dynamic_value = gfunc; \
1189 v->assign_func = afunc; \
1190 } \
1191 while (0)
1192
bb70624e 1193static SHELL_VAR *
3185942a 1194null_assign (self, value, unused, key)
bb70624e
JA
1195 SHELL_VAR *self;
1196 char *value;
7117c2d2 1197 arrayind_t unused;
3185942a 1198 char *key;
bb70624e
JA
1199{
1200 return (self);
1201}
1202
1203#if defined (ARRAY_VARS)
1204static SHELL_VAR *
3185942a 1205null_array_assign (self, value, ind, key)
bb70624e 1206 SHELL_VAR *self;
bb70624e 1207 char *value;
7117c2d2 1208 arrayind_t ind;
3185942a 1209 char *key;
bb70624e
JA
1210{
1211 return (self);
1212}
1213#endif
1214
b80f6443
JA
1215/* Degenerate `dynamic_value' function; just returns what's passed without
1216 manipulation. */
1217static SHELL_VAR *
1218get_self (self)
1219 SHELL_VAR *self;
1220{
1221 return (self);
1222}
1223
1224#if defined (ARRAY_VARS)
ac50fbac 1225/* A generic dynamic array variable initializer. Initialize array variable
b80f6443
JA
1226 NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1227static SHELL_VAR *
1228init_dynamic_array_var (name, getfunc, setfunc, attrs)
1229 char *name;
1230 sh_var_value_func_t *getfunc;
1231 sh_var_assign_func_t *setfunc;
1232 int attrs;
1233{
1234 SHELL_VAR *v;
1235
1236 v = find_variable (name);
1237 if (v)
1238 return (v);
1239 INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1240 if (attrs)
1241 VSETATTR (v, attrs);
1242 return v;
1243}
b80f6443 1244
3185942a
JA
1245static SHELL_VAR *
1246init_dynamic_assoc_var (name, getfunc, setfunc, attrs)
1247 char *name;
1248 sh_var_value_func_t *getfunc;
1249 sh_var_assign_func_t *setfunc;
1250 int attrs;
1251{
1252 SHELL_VAR *v;
1253
1254 v = find_variable (name);
1255 if (v)
1256 return (v);
1257 INIT_DYNAMIC_ASSOC_VAR (name, getfunc, setfunc);
1258 if (attrs)
1259 VSETATTR (v, attrs);
1260 return v;
1261}
1262#endif
b80f6443 1263
726f6388
JA
1264/* The value of $SECONDS. This is the number of seconds since shell
1265 invocation, or, the number of seconds since the last assignment + the
1266 value of the last assignment. */
7117c2d2 1267static intmax_t seconds_value_assigned;
726f6388
JA
1268
1269static SHELL_VAR *
3185942a 1270assign_seconds (self, value, unused, key)
726f6388
JA
1271 SHELL_VAR *self;
1272 char *value;
7117c2d2 1273 arrayind_t unused;
3185942a 1274 char *key;
726f6388 1275{
f73dda09
JA
1276 if (legal_number (value, &seconds_value_assigned) == 0)
1277 seconds_value_assigned = 0;
726f6388
JA
1278 shell_start_time = NOW;
1279 return (self);
1280}
1281
1282static SHELL_VAR *
1283get_seconds (var)
1284 SHELL_VAR *var;
1285{
1286 time_t time_since_start;
1287 char *p;
1288
1289 time_since_start = NOW - shell_start_time;
f73dda09 1290 p = itos(seconds_value_assigned + time_since_start);
726f6388 1291
7117c2d2 1292 FREE (value_cell (var));
726f6388 1293
bb70624e 1294 VSETATTR (var, att_integer);
7117c2d2 1295 var_setvalue (var, p);
726f6388
JA
1296 return (var);
1297}
1298
f73dda09
JA
1299static SHELL_VAR *
1300init_seconds_var ()
1301{
1302 SHELL_VAR *v;
1303
1304 v = find_variable ("SECONDS");
1305 if (v)
1306 {
1307 if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1308 seconds_value_assigned = 0;
1309 }
7117c2d2 1310 INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
f73dda09
JA
1311 return v;
1312}
1313
726f6388 1314/* The random number seed. You can change this by setting RANDOM. */
d233b485 1315static u_bits32_t rseed = 1;
f73dda09 1316static int last_random_value;
95732b49 1317static int seeded_subshell = 0;
726f6388 1318
d233b485
CR
1319#define BASH_RANDOM_16 1
1320
1321#if BASH_RANDOM_16
1322# define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */
1323#else
1324# define BASH_RAND_MAX 0x7fffffff /* 32 bits */
1325#endif
726f6388
JA
1326
1327/* Returns a pseudo-random number between 0 and 32767. */
1328static int
1329brand ()
1330{
d233b485
CR
1331 /* Minimal Standard generator from
1332 "Random number generators: good ones are hard to find",
3185942a 1333 Park and Miller, Communications of the ACM, vol. 31, no. 10,
d233b485
CR
1334 October 1988, p. 1195. filtered through FreeBSD.
1335
1336 x(n+1) = 16807 * x(n) mod (2**31 - 1).
1337
1338 We split up the calculations to avoid overflow.
1339
1340 h = rseed / q; l = x - h * q; t = a * l - h * r
1341 m = 2147483647, a = 16807, q = 127773, r = 2836
1342
1343 There are lots of other combinations of constants to use; look at
1344 https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */
1345
1346 bits32_t h, l, t;
3185942a 1347
495aee44 1348 /* Can't seed with 0. */
3185942a 1349 if (rseed == 0)
495aee44 1350 rseed = 123459876;
3185942a 1351 h = rseed / 127773;
d233b485
CR
1352 l = rseed - (127773 * h);
1353 t = 16807 * l - 2836 * h;
1354 rseed = (t < 0) ? t + 0x7fffffff : t;
1355
1356 return ((unsigned int)(rseed & BASH_RAND_MAX)); /* was % BASH_RAND_MAX+1 */
726f6388
JA
1357}
1358
1359/* Set the random number generator seed to SEED. */
1360static void
1361sbrand (seed)
f73dda09 1362 unsigned long seed;
726f6388
JA
1363{
1364 rseed = seed;
e8ce775d 1365 last_random_value = 0;
726f6388
JA
1366}
1367
3185942a
JA
1368static void
1369seedrand ()
1370{
1371 struct timeval tv;
d233b485 1372 SHELL_VAR *v;
3185942a
JA
1373
1374 gettimeofday (&tv, NULL);
d233b485
CR
1375#if 0
1376 v = find_variable ("BASH_VERSION");
1377 sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid () ^ ((u_bits32_t)&v & 0x7fffffff));
1378#else
3185942a 1379 sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ());
d233b485 1380#endif
3185942a
JA
1381}
1382
726f6388 1383static SHELL_VAR *
3185942a 1384assign_random (self, value, unused, key)
726f6388
JA
1385 SHELL_VAR *self;
1386 char *value;
7117c2d2 1387 arrayind_t unused;
3185942a 1388 char *key;
726f6388 1389{
f73dda09 1390 sbrand (strtoul (value, (char **)NULL, 10));
95732b49 1391 if (subshell_environment)
3185942a 1392 seeded_subshell = getpid ();
726f6388
JA
1393 return (self);
1394}
1395
28ef6c31
JA
1396int
1397get_random_number ()
726f6388 1398{
3185942a 1399 int rv, pid;
726f6388 1400
ccc6cda3 1401 /* Reset for command and process substitution. */
3185942a
JA
1402 pid = getpid ();
1403 if (subshell_environment && seeded_subshell != pid)
95732b49 1404 {
3185942a
JA
1405 seedrand ();
1406 seeded_subshell = pid;
95732b49 1407 }
ccc6cda3
JA
1408
1409 do
1410 rv = brand ();
f73dda09 1411 while (rv == last_random_value);
28ef6c31
JA
1412 return rv;
1413}
ccc6cda3 1414
28ef6c31
JA
1415static SHELL_VAR *
1416get_random (var)
1417 SHELL_VAR *var;
1418{
1419 int rv;
1420 char *p;
1421
1422 rv = get_random_number ();
ccc6cda3 1423 last_random_value = rv;
f73dda09 1424 p = itos (rv);
726f6388 1425
7117c2d2 1426 FREE (value_cell (var));
726f6388 1427
bb70624e 1428 VSETATTR (var, att_integer);
7117c2d2 1429 var_setvalue (var, p);
726f6388
JA
1430 return (var);
1431}
1432
7117c2d2 1433static SHELL_VAR *
3185942a 1434assign_lineno (var, value, unused, key)
7117c2d2
JA
1435 SHELL_VAR *var;
1436 char *value;
1437 arrayind_t unused;
3185942a 1438 char *key;
7117c2d2
JA
1439{
1440 intmax_t new_value;
1441
1442 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1443 new_value = 0;
495aee44 1444 line_number = line_number_base = new_value;
7117c2d2
JA
1445 return var;
1446}
1447
726f6388
JA
1448/* Function which returns the current line number. */
1449static SHELL_VAR *
1450get_lineno (var)
1451 SHELL_VAR *var;
1452{
1453 char *p;
ccc6cda3 1454 int ln;
726f6388 1455
ccc6cda3
JA
1456 ln = executing_line_number ();
1457 p = itos (ln);
7117c2d2
JA
1458 FREE (value_cell (var));
1459 var_setvalue (var, p);
726f6388
JA
1460 return (var);
1461}
1462
b80f6443 1463static SHELL_VAR *
3185942a 1464assign_subshell (var, value, unused, key)
b80f6443
JA
1465 SHELL_VAR *var;
1466 char *value;
1467 arrayind_t unused;
3185942a 1468 char *key;
b80f6443
JA
1469{
1470 intmax_t new_value;
1471
1472 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1473 new_value = 0;
1474 subshell_level = new_value;
1475 return var;
1476}
1477
1478static SHELL_VAR *
1479get_subshell (var)
1480 SHELL_VAR *var;
1481{
1482 char *p;
1483
1484 p = itos (subshell_level);
1485 FREE (value_cell (var));
1486 var_setvalue (var, p);
1487 return (var);
1488}
1489
d233b485
CR
1490static SHELL_VAR *
1491get_epochseconds (var)
1492 SHELL_VAR *var;
1493{
1494 intmax_t now;
1495 char *p;
1496
1497 now = NOW;
1498 p = itos (now);
1499
1500 FREE (value_cell (var));
1501 var_setvalue (var, p);
1502 return (var);
1503}
1504
1505static SHELL_VAR *
1506get_epochrealtime (var)
1507 SHELL_VAR *var;
1508{
1509 char buf[32];
1510 char *p;
1511 struct timeval tv;
1512
1513 gettimeofday (&tv, NULL);
1514 snprintf (buf, sizeof (buf), "%u%c%06u", (unsigned)tv.tv_sec,
1515 locale_decpoint (),
1516 (unsigned)tv.tv_usec);
1517
1518 p = savestring (buf);
1519 FREE (value_cell (var));
1520 var_setvalue (var, p);
1521 return (var);
1522}
1523
3185942a
JA
1524static SHELL_VAR *
1525get_bashpid (var)
1526 SHELL_VAR *var;
1527{
1528 int pid;
1529 char *p;
1530
1531 pid = getpid ();
1532 p = itos (pid);
1533
1534 FREE (value_cell (var));
d233b485 1535 VSETATTR (var, att_integer); /* XXX - was also att_readonly */
3185942a
JA
1536 var_setvalue (var, p);
1537 return (var);
1538}
1539
d233b485
CR
1540static SHELL_VAR *
1541get_bash_argv0 (var)
1542 SHELL_VAR *var;
1543{
1544 char *p;
1545
1546 p = savestring (dollar_vars[0]);
1547 FREE (value_cell (var));
1548 var_setvalue (var, p);
1549 return var;
1550}
1551
1552static char *static_shell_name = 0;
1553
1554static SHELL_VAR *
1555assign_bash_argv0 (var, value, unused, key)
1556 SHELL_VAR *var;
1557 char *value;
1558 arrayind_t unused;
1559 char *key;
1560{
1561 size_t vlen;
1562
1563 if (value == 0)
1564 return var;
1565
1566 FREE (dollar_vars[0]);
1567 dollar_vars[0] = savestring (value);
1568
1569 /* Need these gyrations because shell_name isn't dynamically allocated */
1570 vlen = STRLEN (value);
1571 static_shell_name = xrealloc (static_shell_name, vlen + 1);
1572 strcpy (static_shell_name, value);
1573
1574 shell_name = static_shell_name;
1575 return var;
1576}
1577
b80f6443
JA
1578static SHELL_VAR *
1579get_bash_command (var)
1580 SHELL_VAR *var;
1581{
1582 char *p;
1583
95732b49
JA
1584 if (the_printed_command_except_trap)
1585 p = savestring (the_printed_command_except_trap);
1586 else
1587 {
1588 p = (char *)xmalloc (1);
1589 p[0] = '\0';
1590 }
b80f6443
JA
1591 FREE (value_cell (var));
1592 var_setvalue (var, p);
1593 return (var);
1594}
1595
726f6388
JA
1596#if defined (HISTORY)
1597static SHELL_VAR *
1598get_histcmd (var)
1599 SHELL_VAR *var;
1600{
1601 char *p;
1602
1603 p = itos (history_number ());
7117c2d2
JA
1604 FREE (value_cell (var));
1605 var_setvalue (var, p);
726f6388
JA
1606 return (var);
1607}
1608#endif
1609
b80f6443
JA
1610#if defined (READLINE)
1611/* When this function returns, VAR->value points to malloced memory. */
1612static SHELL_VAR *
1613get_comp_wordbreaks (var)
1614 SHELL_VAR *var;
1615{
b80f6443
JA
1616 /* If we don't have anything yet, assign a default value. */
1617 if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1618 enable_hostname_completion (perform_hostname_completion);
1619
3185942a
JA
1620 FREE (value_cell (var));
1621 var_setvalue (var, savestring (rl_completer_word_break_characters));
b80f6443
JA
1622
1623 return (var);
1624}
1625
1626/* When this function returns, rl_completer_word_break_characters points to
1627 malloced memory. */
1628static SHELL_VAR *
3185942a 1629assign_comp_wordbreaks (self, value, unused, key)
b80f6443
JA
1630 SHELL_VAR *self;
1631 char *value;
1632 arrayind_t unused;
3185942a 1633 char *key;
b80f6443
JA
1634{
1635 if (rl_completer_word_break_characters &&
1636 rl_completer_word_break_characters != rl_basic_word_break_characters)
1637 free (rl_completer_word_break_characters);
1638
1639 rl_completer_word_break_characters = savestring (value);
1640 return self;
1641}
1642#endif /* READLINE */
1643
ccc6cda3 1644#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
b80f6443 1645static SHELL_VAR *
3185942a 1646assign_dirstack (self, value, ind, key)
7117c2d2
JA
1647 SHELL_VAR *self;
1648 char *value;
1649 arrayind_t ind;
3185942a 1650 char *key;
7117c2d2
JA
1651{
1652 set_dirstack_element (ind, 1, value);
1653 return self;
1654}
1655
ccc6cda3
JA
1656static SHELL_VAR *
1657get_dirstack (self)
1658 SHELL_VAR *self;
1659{
1660 ARRAY *a;
1661 WORD_LIST *l;
1662
0628567a 1663 l = get_directory_stack (0);
7117c2d2
JA
1664 a = array_from_word_list (l);
1665 array_dispose (array_cell (self));
d166f048 1666 dispose_words (l);
7117c2d2 1667 var_setarray (self, a);
ccc6cda3
JA
1668 return self;
1669}
1670#endif /* PUSHD AND POPD && ARRAY_VARS */
1671
d166f048
JA
1672#if defined (ARRAY_VARS)
1673/* We don't want to initialize the group set with a call to getgroups()
1674 unless we're asked to, but we only want to do it once. */
1675static SHELL_VAR *
1676get_groupset (self)
1677 SHELL_VAR *self;
1678{
1679 register int i;
1680 int ng;
1681 ARRAY *a;
1682 static char **group_set = (char **)NULL;
1683
1684 if (group_set == 0)
1685 {
1686 group_set = get_group_list (&ng);
1687 a = array_cell (self);
1688 for (i = 0; i < ng; i++)
7117c2d2 1689 array_insert (a, i, group_set[i]);
d166f048
JA
1690 }
1691 return (self);
1692}
3185942a 1693
d233b485
CR
1694# if defined (DEBUGGER)
1695static SHELL_VAR *
1696get_bashargcv (self)
1697 SHELL_VAR *self;
1698{
1699 static int self_semaphore = 0;
1700
1701 /* Backwards compatibility: if we refer to BASH_ARGV or BASH_ARGC at the
1702 top level without enabling debug mode, and we don't have an instance
1703 of the variable set, initialize the arg arrays.
1704 This will already have been done if debugging_mode != 0. */
1705 if (self_semaphore == 0 && variable_context == 0 && debugging_mode == 0) /* don't do it for shell functions */
1706 {
1707 self_semaphore = 1;
1708 init_bash_argv ();
1709 self_semaphore = 0;
1710 }
1711 return self;
1712}
1713# endif
1714
3185942a
JA
1715static SHELL_VAR *
1716build_hashcmd (self)
1717 SHELL_VAR *self;
1718{
1719 HASH_TABLE *h;
1720 int i;
1721 char *k, *v;
1722 BUCKET_CONTENTS *item;
1723
1724 h = assoc_cell (self);
1725 if (h)
1726 assoc_dispose (h);
1727
1728 if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
1729 {
1730 var_setvalue (self, (char *)NULL);
1731 return self;
1732 }
1733
1734 h = assoc_create (hashed_filenames->nbuckets);
1735 for (i = 0; i < hashed_filenames->nbuckets; i++)
1736 {
1737 for (item = hash_items (i, hashed_filenames); item; item = item->next)
1738 {
1739 k = savestring (item->key);
1740 v = pathdata(item)->path;
1741 assoc_insert (h, k, v);
1742 }
1743 }
1744
1745 var_setvalue (self, (char *)h);
1746 return self;
1747}
1748
1749static SHELL_VAR *
1750get_hashcmd (self)
1751 SHELL_VAR *self;
1752{
1753 build_hashcmd (self);
1754 return (self);
1755}
1756
1757static SHELL_VAR *
1758assign_hashcmd (self, value, ind, key)
1759 SHELL_VAR *self;
1760 char *value;
1761 arrayind_t ind;
1762 char *key;
1763{
a0c0a00f 1764#if defined (RESTRICTED_SHELL)
d233b485
CR
1765 char *full_path;
1766
1767 if (restricted)
a0c0a00f 1768 {
d233b485
CR
1769 if (strchr (value, '/'))
1770 {
1771 sh_restricted (value);
1772 return (SHELL_VAR *)NULL;
1773 }
1774 /* If we are changing the hash table in a restricted shell, make sure the
1775 target pathname can be found using a $PATH search. */
1776 full_path = find_user_command (value);
1777 if (full_path == 0 || *full_path == 0 || executable_file (full_path) == 0)
1778 {
1779 sh_notfound (value);
1780 free (full_path);
1781 return ((SHELL_VAR *)NULL);
1782 }
1783 free (full_path);
a0c0a00f
CR
1784 }
1785#endif
3185942a
JA
1786 phash_insert (key, value, 0, 0);
1787 return (build_hashcmd (self));
1788}
1789
0001803f 1790#if defined (ALIAS)
3185942a
JA
1791static SHELL_VAR *
1792build_aliasvar (self)
1793 SHELL_VAR *self;
1794{
1795 HASH_TABLE *h;
1796 int i;
1797 char *k, *v;
1798 BUCKET_CONTENTS *item;
1799
1800 h = assoc_cell (self);
1801 if (h)
1802 assoc_dispose (h);
1803
1804 if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
1805 {
1806 var_setvalue (self, (char *)NULL);
1807 return self;
1808 }
1809
1810 h = assoc_create (aliases->nbuckets);
1811 for (i = 0; i < aliases->nbuckets; i++)
1812 {
1813 for (item = hash_items (i, aliases); item; item = item->next)
1814 {
1815 k = savestring (item->key);
1816 v = ((alias_t *)(item->data))->value;
1817 assoc_insert (h, k, v);
1818 }
1819 }
1820
1821 var_setvalue (self, (char *)h);
1822 return self;
1823}
1824
1825static SHELL_VAR *
1826get_aliasvar (self)
1827 SHELL_VAR *self;
1828{
1829 build_aliasvar (self);
1830 return (self);
1831}
1832
1833static SHELL_VAR *
1834assign_aliasvar (self, value, ind, key)
1835 SHELL_VAR *self;
1836 char *value;
1837 arrayind_t ind;
1838 char *key;
1839{
d233b485
CR
1840 if (legal_alias_name (key, 0) == 0)
1841 {
1842 report_error (_("`%s': invalid alias name"), key);
1843 return (self);
1844 }
3185942a
JA
1845 add_alias (key, value);
1846 return (build_aliasvar (self));
1847}
0001803f
CR
1848#endif /* ALIAS */
1849
d166f048 1850#endif /* ARRAY_VARS */
bb70624e 1851
b80f6443
JA
1852/* If ARRAY_VARS is not defined, this just returns the name of any
1853 currently-executing function. If we have arrays, it's a call stack. */
bb70624e
JA
1854static SHELL_VAR *
1855get_funcname (self)
1856 SHELL_VAR *self;
1857{
b80f6443 1858#if ! defined (ARRAY_VARS)
7117c2d2 1859 char *t;
bb70624e
JA
1860 if (variable_context && this_shell_function)
1861 {
7117c2d2
JA
1862 FREE (value_cell (self));
1863 t = savestring (this_shell_function->name);
1864 var_setvalue (self, t);
bb70624e 1865 }
b80f6443 1866#endif
bb70624e
JA
1867 return (self);
1868}
1869
1870void
1871make_funcname_visible (on_or_off)
1872 int on_or_off;
726f6388
JA
1873{
1874 SHELL_VAR *v;
1875
bb70624e
JA
1876 v = find_variable ("FUNCNAME");
1877 if (v == 0 || v->dynamic_value == 0)
1878 return;
1879
1880 if (on_or_off)
1881 VUNSETATTR (v, att_invisible);
1882 else
1883 VSETATTR (v, att_invisible);
1884}
1885
f73dda09
JA
1886static SHELL_VAR *
1887init_funcname_var ()
1888{
1889 SHELL_VAR *v;
bb70624e 1890
f73dda09
JA
1891 v = find_variable ("FUNCNAME");
1892 if (v)
1893 return v;
b80f6443
JA
1894#if defined (ARRAY_VARS)
1895 INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1896#else
f73dda09 1897 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
b80f6443 1898#endif
f73dda09
JA
1899 VSETATTR (v, att_invisible|att_noassign);
1900 return v;
1901}
726f6388 1902
bb70624e
JA
1903static void
1904initialize_dynamic_variables ()
1905{
1906 SHELL_VAR *v;
726f6388 1907
f73dda09
JA
1908 v = init_seconds_var ();
1909
d233b485
CR
1910 INIT_DYNAMIC_VAR ("BASH_ARGV0", (char *)NULL, get_bash_argv0, assign_bash_argv0);
1911
b80f6443
JA
1912 INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1913 INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1914
bb70624e 1915 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
95732b49 1916 VSETATTR (v, att_integer);
bb70624e 1917 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
d233b485 1918 VSETATTR (v, att_integer|att_regenerate);
726f6388 1919
3185942a 1920 INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
d233b485
CR
1921 VSETATTR (v, att_integer);
1922
1923 INIT_DYNAMIC_VAR ("EPOCHSECONDS", (char *)NULL, get_epochseconds, null_assign);
1924 VSETATTR (v, att_regenerate);
1925 INIT_DYNAMIC_VAR ("EPOCHREALTIME", (char *)NULL, get_epochrealtime, null_assign);
1926 VSETATTR (v, att_regenerate);
3185942a 1927
726f6388 1928#if defined (HISTORY)
7117c2d2 1929 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
95732b49 1930 VSETATTR (v, att_integer);
726f6388 1931#endif
ccc6cda3 1932
b80f6443
JA
1933#if defined (READLINE)
1934 INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1935#endif
1936
ccc6cda3 1937#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
b80f6443 1938 v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
ccc6cda3 1939#endif /* PUSHD_AND_POPD && ARRAY_VARS */
d166f048
JA
1940
1941#if defined (ARRAY_VARS)
b80f6443
JA
1942 v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1943
1944# if defined (DEBUGGER)
d233b485
CR
1945 v = init_dynamic_array_var ("BASH_ARGC", get_bashargcv, null_array_assign, att_noassign|att_nounset);
1946 v = init_dynamic_array_var ("BASH_ARGV", get_bashargcv, null_array_assign, att_noassign|att_nounset);
b80f6443 1947# endif /* DEBUGGER */
95732b49
JA
1948 v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
1949 v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
3185942a
JA
1950
1951 v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree);
0001803f 1952# if defined (ALIAS)
3185942a 1953 v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree);
0001803f 1954# endif
d166f048 1955#endif
bb70624e 1956
f73dda09 1957 v = init_funcname_var ();
726f6388
JA
1958}
1959
7117c2d2
JA
1960/* **************************************************************** */
1961/* */
1962/* Retrieving variables and values */
1963/* */
1964/* **************************************************************** */
1965
726f6388
JA
1966/* How to get a pointer to the shell variable or function named NAME.
1967 HASHED_VARS is a pointer to the hash table containing the list
1968 of interest (either variables or functions). */
7117c2d2
JA
1969
1970static SHELL_VAR *
1971hash_lookup (name, hashed_vars)
f73dda09 1972 const char *name;
726f6388
JA
1973 HASH_TABLE *hashed_vars;
1974{
1975 BUCKET_CONTENTS *bucket;
1976
7117c2d2 1977 bucket = hash_search (name, hashed_vars, 0);
ac50fbac
CR
1978 /* If we find the name in HASHED_VARS, set LAST_TABLE_SEARCHED to that
1979 table. */
1980 if (bucket)
1981 last_table_searched = hashed_vars;
ccc6cda3 1982 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
726f6388
JA
1983}
1984
7117c2d2
JA
1985SHELL_VAR *
1986var_lookup (name, vcontext)
1987 const char *name;
1988 VAR_CONTEXT *vcontext;
1989{
1990 VAR_CONTEXT *vc;
1991 SHELL_VAR *v;
1992
1993 v = (SHELL_VAR *)NULL;
1994 for (vc = vcontext; vc; vc = vc->down)
1995 if (v = hash_lookup (name, vc->table))
1996 break;
1997
1998 return v;
1999}
2000
726f6388 2001/* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
7117c2d2
JA
2002 then also search the temporarily built list of exported variables.
2003 The lookup order is:
2004 temporary_env
3185942a 2005 shell_variables list
7117c2d2
JA
2006*/
2007
726f6388 2008SHELL_VAR *
a0c0a00f 2009find_variable_internal (name, flags)
f73dda09 2010 const char *name;
a0c0a00f 2011 int flags;
726f6388 2012{
28ef6c31 2013 SHELL_VAR *var;
a0c0a00f 2014 int search_tempenv, force_tempenv;
ac50fbac 2015 VAR_CONTEXT *vc;
28ef6c31
JA
2016
2017 var = (SHELL_VAR *)NULL;
726f6388 2018
a0c0a00f
CR
2019 force_tempenv = (flags & FV_FORCETEMPENV);
2020
726f6388
JA
2021 /* If explicitly requested, first look in the temporary environment for
2022 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
2023 to get the `exported' value of $foo. This happens if we are executing
2024 a function or builtin, or if we are looking up a variable in a
2025 "subshell environment". */
b80f6443
JA
2026 search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
2027
2028 if (search_tempenv && temporary_env)
7117c2d2 2029 var = hash_lookup (name, temporary_env);
726f6388 2030
7117c2d2 2031 if (var == 0)
a0c0a00f
CR
2032 {
2033 if ((flags & FV_SKIPINVISIBLE) == 0)
2034 var = var_lookup (name, shell_variables);
2035 else
2036 {
2037 /* essentially var_lookup expanded inline so we can check for
2038 att_invisible */
2039 for (vc = shell_variables; vc; vc = vc->down)
2040 {
2041 var = hash_lookup (name, vc->table);
2042 if (var && invisible_p (var))
2043 var = 0;
2044 if (var)
2045 break;
2046 }
2047 }
2048 }
726f6388 2049
7117c2d2 2050 if (var == 0)
726f6388
JA
2051 return ((SHELL_VAR *)NULL);
2052
ccc6cda3 2053 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
726f6388
JA
2054}
2055
ac50fbac
CR
2056/* Look up and resolve the chain of nameref variables starting at V all the
2057 way to NULL or non-nameref. */
2058SHELL_VAR *
2059find_variable_nameref (v)
2060 SHELL_VAR *v;
2061{
a0c0a00f 2062 int level, flags;
d233b485 2063 char *newname;
ac50fbac
CR
2064 SHELL_VAR *orig, *oldv;
2065
2066 level = 0;
2067 orig = v;
2068 while (v && nameref_p (v))
2069 {
2070 level++;
2071 if (level > NAMEREF_MAX)
2072 return ((SHELL_VAR *)0); /* error message here? */
2073 newname = nameref_cell (v);
2074 if (newname == 0 || *newname == '\0')
2075 return ((SHELL_VAR *)0);
2076 oldv = v;
a0c0a00f
CR
2077 flags = 0;
2078 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2079 flags |= FV_FORCETEMPENV;
2080 /* We don't handle array subscripts here. */
2081 v = find_variable_internal (newname, flags);
ac50fbac
CR
2082 if (v == orig || v == oldv)
2083 {
2084 internal_warning (_("%s: circular name reference"), orig->name);
d233b485
CR
2085#if 1
2086 /* XXX - provisional change - circular refs go to
2087 global scope for resolution, without namerefs. */
2088 if (variable_context && v->context)
2089 return (find_global_variable_noref (v->name));
2090 else
2091#endif
ac50fbac
CR
2092 return ((SHELL_VAR *)0);
2093 }
2094 }
2095 return v;
2096}
2097
2098/* Resolve the chain of nameref variables for NAME. XXX - could change later */
2099SHELL_VAR *
a0c0a00f 2100find_variable_last_nameref (name, vflags)
ac50fbac 2101 const char *name;
a0c0a00f 2102 int vflags;
ac50fbac
CR
2103{
2104 SHELL_VAR *v, *nv;
2105 char *newname;
a0c0a00f 2106 int level, flags;
ac50fbac
CR
2107
2108 nv = v = find_variable_noref (name);
2109 level = 0;
2110 while (v && nameref_p (v))
2111 {
2112 level++;
2113 if (level > NAMEREF_MAX)
2114 return ((SHELL_VAR *)0); /* error message here? */
2115 newname = nameref_cell (v);
2116 if (newname == 0 || *newname == '\0')
a0c0a00f 2117 return ((vflags && invisible_p (v)) ? v : (SHELL_VAR *)0);
ac50fbac 2118 nv = v;
a0c0a00f
CR
2119 flags = 0;
2120 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2121 flags |= FV_FORCETEMPENV;
2122 /* We don't accommodate array subscripts here. */
2123 v = find_variable_internal (newname, flags);
ac50fbac
CR
2124 }
2125 return nv;
2126}
2127
2128/* Resolve the chain of nameref variables for NAME. XXX - could change later */
2129SHELL_VAR *
a0c0a00f 2130find_global_variable_last_nameref (name, vflags)
ac50fbac 2131 const char *name;
a0c0a00f 2132 int vflags;
ac50fbac
CR
2133{
2134 SHELL_VAR *v, *nv;
2135 char *newname;
2136 int level;
2137
2138 nv = v = find_global_variable_noref (name);
2139 level = 0;
2140 while (v && nameref_p (v))
2141 {
2142 level++;
2143 if (level > NAMEREF_MAX)
2144 return ((SHELL_VAR *)0); /* error message here? */
2145 newname = nameref_cell (v);
2146 if (newname == 0 || *newname == '\0')
a0c0a00f 2147 return ((vflags && invisible_p (v)) ? v : (SHELL_VAR *)0);
ac50fbac 2148 nv = v;
a0c0a00f 2149 /* We don't accommodate array subscripts here. */
ac50fbac
CR
2150 v = find_global_variable_noref (newname);
2151 }
2152 return nv;
2153}
2154
2155static SHELL_VAR *
2156find_nameref_at_context (v, vc)
2157 SHELL_VAR *v;
2158 VAR_CONTEXT *vc;
2159{
2160 SHELL_VAR *nv, *nv2;
ac50fbac
CR
2161 char *newname;
2162 int level;
2163
2164 nv = v;
2165 level = 1;
2166 while (nv && nameref_p (nv))
2167 {
2168 level++;
2169 if (level > NAMEREF_MAX)
a0c0a00f 2170 return (&nameref_maxloop_value);
ac50fbac
CR
2171 newname = nameref_cell (nv);
2172 if (newname == 0 || *newname == '\0')
2173 return ((SHELL_VAR *)NULL);
2174 nv2 = hash_lookup (newname, vc->table);
2175 if (nv2 == 0)
2176 break;
2177 nv = nv2;
2178 }
2179 return nv;
2180}
2181
2182/* Do nameref resolution from the VC, which is the local context for some
2183 function or builtin, `up' the chain to the global variables context. If
2184 NVCP is not NULL, return the variable context where we finally ended the
2185 nameref resolution (so the bind_variable_internal can use the correct
2186 variable context and hash table). */
2187static SHELL_VAR *
2188find_variable_nameref_context (v, vc, nvcp)
2189 SHELL_VAR *v;
2190 VAR_CONTEXT *vc;
2191 VAR_CONTEXT **nvcp;
2192{
2193 SHELL_VAR *nv, *nv2;
2194 VAR_CONTEXT *nvc;
2195
2196 /* Look starting at the current context all the way `up' */
2197 for (nv = v, nvc = vc; nvc; nvc = nvc->down)
2198 {
2199 nv2 = find_nameref_at_context (nv, nvc);
a0c0a00f
CR
2200 if (nv2 == &nameref_maxloop_value)
2201 return (nv2); /* XXX */
ac50fbac
CR
2202 if (nv2 == 0)
2203 continue;
2204 nv = nv2;
2205 if (*nvcp)
2206 *nvcp = nvc;
2207 if (nameref_p (nv) == 0)
2208 break;
2209 }
2210 return (nameref_p (nv) ? (SHELL_VAR *)NULL : nv);
2211}
2212
2213/* Do nameref resolution from the VC, which is the local context for some
2214 function or builtin, `up' the chain to the global variables context. If
2215 NVCP is not NULL, return the variable context where we finally ended the
2216 nameref resolution (so the bind_variable_internal can use the correct
2217 variable context and hash table). */
2218static SHELL_VAR *
2219find_variable_last_nameref_context (v, vc, nvcp)
2220 SHELL_VAR *v;
2221 VAR_CONTEXT *vc;
2222 VAR_CONTEXT **nvcp;
2223{
2224 SHELL_VAR *nv, *nv2;
2225 VAR_CONTEXT *nvc;
2226
2227 /* Look starting at the current context all the way `up' */
2228 for (nv = v, nvc = vc; nvc; nvc = nvc->down)
2229 {
2230 nv2 = find_nameref_at_context (nv, nvc);
a0c0a00f
CR
2231 if (nv2 == &nameref_maxloop_value)
2232 return (nv2); /* XXX */
ac50fbac
CR
2233 if (nv2 == 0)
2234 continue;
2235 nv = nv2;
2236 if (*nvcp)
2237 *nvcp = nvc;
2238 }
2239 return (nameref_p (nv) ? nv : (SHELL_VAR *)NULL);
2240}
2241
a0c0a00f
CR
2242SHELL_VAR *
2243find_variable_nameref_for_create (name, flags)
2244 const char *name;
2245 int flags;
2246{
2247 SHELL_VAR *var;
2248
2249 /* See if we have a nameref pointing to a variable that hasn't been
2250 created yet. */
2251 var = find_variable_last_nameref (name, 1);
2252 if ((flags&1) && var && nameref_p (var) && invisible_p (var))
2253 {
2254 internal_warning (_("%s: removing nameref attribute"), name);
2255 VUNSETATTR (var, att_nameref);
2256 }
2257 if (var && nameref_p (var))
2258 {
2259 if (legal_identifier (nameref_cell (var)) == 0)
2260 {
2261 sh_invalidid (nameref_cell (var) ? nameref_cell (var) : "");
2262 return ((SHELL_VAR *)INVALID_NAMEREF_VALUE);
2263 }
2264 }
2265 return (var);
2266}
2267
2268SHELL_VAR *
2269find_variable_nameref_for_assignment (name, flags)
2270 const char *name;
2271 int flags;
2272{
2273 SHELL_VAR *var;
2274
2275 /* See if we have a nameref pointing to a variable that hasn't been
2276 created yet. */
2277 var = find_variable_last_nameref (name, 1);
2278 if (var && nameref_p (var) && invisible_p (var)) /* XXX - flags */
2279 {
2280 internal_warning (_("%s: removing nameref attribute"), name);
2281 VUNSETATTR (var, att_nameref);
2282 }
2283 if (var && nameref_p (var))
2284 {
2285 if (valid_nameref_value (nameref_cell (var), 1) == 0)
2286 {
2287 sh_invalidid (nameref_cell (var) ? nameref_cell (var) : "");
2288 return ((SHELL_VAR *)INVALID_NAMEREF_VALUE);
2289 }
2290 }
2291 return (var);
2292}
2293
d233b485
CR
2294/* If find_variable (name) returns NULL, check that it's not a nameref
2295 referencing a variable that doesn't exist. If it is, return the new
2296 name. If not, return the original name. Kind of like the previous
2297 function, but dealing strictly with names. This takes assignment flags
2298 so it can deal with the various assignment modes used by `declare'. */
2299char *
2300nameref_transform_name (name, flags)
2301 char *name;
2302 int flags;
2303{
2304 SHELL_VAR *v;
2305 char *newname;
2306
2307 v = 0;
2308 if (flags & ASS_MKLOCAL)
2309 {
2310 v = find_variable_last_nameref (name, 1);
2311 /* If we're making local variables, only follow namerefs that point to
2312 non-existant variables at the same variable context. */
2313 if (v && v->context != variable_context)
2314 v = 0;
2315 }
2316 else if (flags & ASS_MKGLOBAL)
2317 v = (flags & ASS_CHKLOCAL) ? find_variable_last_nameref (name, 1)
2318 : find_global_variable_last_nameref (name, 1);
2319 if (v && nameref_p (v) && valid_nameref_value (nameref_cell (v), 1))
2320 return nameref_cell (v);
2321 return name;
2322}
2323
ac50fbac
CR
2324/* Find a variable, forcing a search of the temporary environment first */
2325SHELL_VAR *
2326find_variable_tempenv (name)
2327 const char *name;
2328{
2329 SHELL_VAR *var;
2330
a0c0a00f 2331 var = find_variable_internal (name, FV_FORCETEMPENV);
ac50fbac
CR
2332 if (var && nameref_p (var))
2333 var = find_variable_nameref (var);
2334 return (var);
2335}
2336
2337/* Find a variable, not forcing a search of the temporary environment first */
2338SHELL_VAR *
2339find_variable_notempenv (name)
2340 const char *name;
2341{
2342 SHELL_VAR *var;
2343
2344 var = find_variable_internal (name, 0);
2345 if (var && nameref_p (var))
2346 var = find_variable_nameref (var);
2347 return (var);
2348}
2349
495aee44
CR
2350SHELL_VAR *
2351find_global_variable (name)
2352 const char *name;
2353{
2354 SHELL_VAR *var;
2355
ac50fbac
CR
2356 var = var_lookup (name, global_variables);
2357 if (var && nameref_p (var))
2358 var = find_variable_nameref (var);
2359
2360 if (var == 0)
2361 return ((SHELL_VAR *)NULL);
2362
2363 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2364}
2365
2366SHELL_VAR *
2367find_global_variable_noref (name)
2368 const char *name;
2369{
2370 SHELL_VAR *var;
2371
495aee44
CR
2372 var = var_lookup (name, global_variables);
2373
2374 if (var == 0)
2375 return ((SHELL_VAR *)NULL);
2376
2377 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2378}
2379
ac50fbac
CR
2380SHELL_VAR *
2381find_shell_variable (name)
2382 const char *name;
2383{
2384 SHELL_VAR *var;
2385
2386 var = var_lookup (name, shell_variables);
2387 if (var && nameref_p (var))
2388 var = find_variable_nameref (var);
2389
2390 if (var == 0)
2391 return ((SHELL_VAR *)NULL);
2392
2393 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
2394}
2395
726f6388
JA
2396/* Look up the variable entry named NAME. Returns the entry or NULL. */
2397SHELL_VAR *
2398find_variable (name)
f73dda09 2399 const char *name;
726f6388 2400{
ac50fbac 2401 SHELL_VAR *v;
a0c0a00f
CR
2402 int flags;
2403
2404 last_table_searched = 0;
2405 flags = 0;
2406 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2407 flags |= FV_FORCETEMPENV;
2408 v = find_variable_internal (name, flags);
2409 if (v && nameref_p (v))
2410 v = find_variable_nameref (v);
2411 return v;
2412}
2413
2414/* Find the first instance of NAME in the variable context chain; return first
2415 one found without att_invisible set; return 0 if no non-invisible instances
2416 found. */
2417SHELL_VAR *
2418find_variable_no_invisible (name)
2419 const char *name;
2420{
2421 SHELL_VAR *v;
2422 int flags;
ac50fbac
CR
2423
2424 last_table_searched = 0;
a0c0a00f
CR
2425 flags = FV_SKIPINVISIBLE;
2426 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2427 flags |= FV_FORCETEMPENV;
2428 v = find_variable_internal (name, flags);
2429 if (v && nameref_p (v))
2430 v = find_variable_nameref (v);
2431 return v;
2432}
2433
2434/* Find the first instance of NAME in the variable context chain; return first
2435 one found even if att_invisible set. */
2436SHELL_VAR *
2437find_variable_for_assignment (name)
2438 const char *name;
2439{
2440 SHELL_VAR *v;
2441 int flags;
2442
2443 last_table_searched = 0;
2444 flags = 0;
2445 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2446 flags |= FV_FORCETEMPENV;
2447 v = find_variable_internal (name, flags);
ac50fbac
CR
2448 if (v && nameref_p (v))
2449 v = find_variable_nameref (v);
2450 return v;
2451}
2452
2453SHELL_VAR *
2454find_variable_noref (name)
2455 const char *name;
2456{
2457 SHELL_VAR *v;
a0c0a00f 2458 int flags;
ac50fbac 2459
a0c0a00f
CR
2460 flags = 0;
2461 if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
2462 flags |= FV_FORCETEMPENV;
2463 v = find_variable_internal (name, flags);
ac50fbac 2464 return v;
726f6388
JA
2465}
2466
2467/* Look up the function entry whose name matches STRING.
2468 Returns the entry or NULL. */
2469SHELL_VAR *
2470find_function (name)
f73dda09 2471 const char *name;
726f6388 2472{
7117c2d2
JA
2473 return (hash_lookup (name, shell_functions));
2474}
2475
b80f6443
JA
2476/* Find the function definition for the shell function named NAME. Returns
2477 the entry or NULL. */
2478FUNCTION_DEF *
2479find_function_def (name)
2480 const char *name;
2481{
3185942a 2482#if defined (DEBUGGER)
b80f6443 2483 return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
3185942a
JA
2484#else
2485 return ((FUNCTION_DEF *)0);
2486#endif
b80f6443
JA
2487}
2488
7117c2d2
JA
2489/* Return the value of VAR. VAR is assumed to have been the result of a
2490 lookup without any subscript, if arrays are compiled into the shell. */
2491char *
2492get_variable_value (var)
2493 SHELL_VAR *var;
2494{
2495 if (var == 0)
2496 return ((char *)NULL);
2497#if defined (ARRAY_VARS)
2498 else if (array_p (var))
2499 return (array_reference (array_cell (var), 0));
3185942a
JA
2500 else if (assoc_p (var))
2501 return (assoc_reference (assoc_cell (var), "0"));
7117c2d2
JA
2502#endif
2503 else
2504 return (value_cell (var));
726f6388
JA
2505}
2506
2507/* Return the string value of a variable. Return NULL if the variable
7117c2d2 2508 doesn't exist. Don't cons a new string. This is a potential memory
a0c0a00f
CR
2509 leak if the variable is found in the temporary environment, but doesn't
2510 leak in practice. Since functions and variables have separate name
2511 spaces, returns NULL if var_name is a shell function only. */
726f6388
JA
2512char *
2513get_string_value (var_name)
28ef6c31 2514 const char *var_name;
726f6388 2515{
d166f048
JA
2516 SHELL_VAR *var;
2517
f73dda09 2518 var = find_variable (var_name);
7117c2d2 2519 return ((var) ? get_variable_value (var) : (char *)NULL);
726f6388
JA
2520}
2521
b72432fd
JA
2522/* This is present for use by the tilde and readline libraries. */
2523char *
28ef6c31
JA
2524sh_get_env_value (v)
2525 const char *v;
b72432fd
JA
2526{
2527 return get_string_value (v);
2528}
2529
7117c2d2
JA
2530/* **************************************************************** */
2531/* */
2532/* Creating and setting variables */
2533/* */
2534/* **************************************************************** */
2535
d233b485
CR
2536static int
2537var_sametype (v1, v2)
2538 SHELL_VAR *v1;
2539 SHELL_VAR *v2;
2540{
2541 if (v1 == 0 || v2 == 0)
2542 return 0;
2543#if defined (ARRAY_VARS)
2544 else if (assoc_p (v1) && assoc_p (v2))
2545 return 1;
2546 else if (array_p (v1) && array_p (v2))
2547 return 1;
2548 else if (array_p (v1) || array_p (v2))
2549 return 0;
2550 else if (assoc_p (v1) || assoc_p (v2))
2551 return 0;
2552#endif
2553 else
2554 return 1;
2555}
2556
2557int
2558validate_inherited_value (var, type)
2559 SHELL_VAR *var;
2560 int type;
2561{
2562#if defined (ARRAY_VARS)
2563 if (type == att_array && assoc_p (var))
2564 return 0;
2565 else if (type == att_assoc && array_p (var))
2566 return 0;
2567 else
2568#endif
2569 return 1; /* should we run convert_var_to_array here or let the caller? */
2570}
2571
7117c2d2
JA
2572/* Set NAME to VALUE if NAME has no value. */
2573SHELL_VAR *
2574set_if_not (name, value)
2575 char *name, *value;
2576{
2577 SHELL_VAR *v;
2578
0628567a
JA
2579 if (shell_variables == 0)
2580 create_variable_tables ();
2581
7117c2d2
JA
2582 v = find_variable (name);
2583 if (v == 0)
95732b49 2584 v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
7117c2d2
JA
2585 return (v);
2586}
2587
726f6388
JA
2588/* Create a local variable referenced by NAME. */
2589SHELL_VAR *
d233b485 2590make_local_variable (name, flags)
f73dda09 2591 const char *name;
d233b485 2592 int flags;
726f6388 2593{
a0c0a00f 2594 SHELL_VAR *new_var, *old_var, *old_ref;
7117c2d2
JA
2595 VAR_CONTEXT *vc;
2596 int was_tmpvar;
d233b485 2597 char *old_value;
726f6388 2598
a0c0a00f
CR
2599 /* We don't want to follow the nameref chain when making local variables; we
2600 just want to create them. */
2601 old_ref = find_variable_noref (name);
2602 if (old_ref && nameref_p (old_ref) == 0)
2603 old_ref = 0;
726f6388
JA
2604 /* local foo; local foo; is a no-op. */
2605 old_var = find_variable (name);
a0c0a00f 2606 if (old_ref == 0 && old_var && local_p (old_var) && old_var->context == variable_context)
9ddcfa16 2607 return (old_var);
726f6388 2608
a0c0a00f
CR
2609 /* local -n foo; local -n foo; is a no-op. */
2610 if (old_ref && local_p (old_ref) && old_ref->context == variable_context)
2611 return (old_ref);
2612
2613 /* From here on, we want to use the refvar, not the variable it references */
2614 if (old_ref)
2615 old_var = old_ref;
2616
7117c2d2 2617 was_tmpvar = old_var && tempvar_p (old_var);
ac50fbac
CR
2618 /* If we're making a local variable in a shell function, the temporary env
2619 has already been merged into the function's variable context stack. We
2620 can assume that a temporary var in the same context appears in the same
2621 VAR_CONTEXT and can safely be returned without creating a new variable
2622 (which results in duplicate names in the same VAR_CONTEXT->table */
2623 /* We can't just test tmpvar_p because variables in the temporary env given
2624 to a shell function appear in the function's local variable VAR_CONTEXT
2625 but retain their tempvar attribute. We want temporary variables that are
2626 found in temporary_env, hence the test for last_table_searched, which is
2627 set in hash_lookup and only (so far) checked here. */
2628 if (was_tmpvar && old_var->context == variable_context && last_table_searched != temporary_env)
2629 {
a0c0a00f 2630 VUNSETATTR (old_var, att_invisible); /* XXX */
d233b485
CR
2631#if 0 /* TAG:bash-5.1 */
2632 /* We still want to flag this variable as local, though, and set things
2633 up so that it gets treated as a local variable. */
2634 new_var = old_var;
2635 /* Since we found the variable in a temporary environment, this will
2636 succeed. */
2637 for (vc = shell_variables; vc; vc = vc->down)
2638 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2639 break;
2640 goto set_local_var_flags;
2641#endif
ac50fbac
CR
2642 return (old_var);
2643 }
d233b485
CR
2644
2645 /* If we want to change to "inherit the old variable's value" semantics,
2646 here is where to save the old value. */
2647 old_value = was_tmpvar ? value_cell (old_var) : (char *)NULL;
7117c2d2
JA
2648
2649 for (vc = shell_variables; vc; vc = vc->down)
2650 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2651 break;
2652
2653 if (vc == 0)
2654 {
b80f6443 2655 internal_error (_("make_local_variable: no function context at current scope"));
7117c2d2
JA
2656 return ((SHELL_VAR *)NULL);
2657 }
2658 else if (vc->table == 0)
2659 vc->table = hash_create (TEMPENV_HASH_BUCKETS);
2660
bb70624e
JA
2661 /* Since this is called only from the local/declare/typeset code, we can
2662 call builtin_error here without worry (of course, it will also work
28ef6c31
JA
2663 for anything that sets this_command_name). Variables with the `noassign'
2664 attribute may not be made local. The test against old_var's context
2665 level is to disallow local copies of readonly global variables (since I
2666 believe that this could be a security hole). Readonly copies of calling
2667 function local variables are OK. */
2668 if (old_var && (noassign_p (old_var) ||
2669 (readonly_p (old_var) && old_var->context == 0)))
2670 {
2671 if (readonly_p (old_var))
7117c2d2 2672 sh_readonly (name);
ac50fbac
CR
2673 else if (noassign_p (old_var))
2674 builtin_error (_("%s: variable may not be assigned value"), name);
2675#if 0
2676 /* Let noassign variables through with a warning */
2677 if (readonly_p (old_var))
2678#endif
2679 return ((SHELL_VAR *)NULL);
bb70624e
JA
2680 }
2681
d166f048 2682 if (old_var == 0)
3185942a 2683 new_var = make_new_variable (name, vc->table);
726f6388
JA
2684 else
2685 {
7117c2d2 2686 new_var = make_new_variable (name, vc->table);
726f6388 2687
7117c2d2
JA
2688 /* If we found this variable in one of the temporary environments,
2689 inherit its value. Watch to see if this causes problems with
ac50fbac
CR
2690 things like `x=4 local x'. XXX - see above for temporary env
2691 variables with the same context level as variable_context */
2692 /* XXX - we should only do this if the variable is not an array. */
d233b485
CR
2693 /* If we want to change the local variable semantics to "inherit
2694 the old variable's value" here is where to set it. And we would
2695 need to use copy_variable (currently unused) to do it for all
2696 possible variable values. */
7117c2d2 2697 if (was_tmpvar)
d233b485
CR
2698 var_setvalue (new_var, savestring (old_value));
2699 else if (localvar_inherit || (flags & MKLOC_INHERIT))
2700 {
2701 /* This may not make sense for nameref variables that are shadowing
2702 variables with the same name, but we don't know that yet. */
2703#if defined (ARRAY_VARS)
2704 if (assoc_p (old_var))
2705 var_setassoc (new_var, assoc_copy (assoc_cell (old_var)));
2706 else if (array_p (old_var))
2707 var_setarray (new_var, array_copy (array_cell (old_var)));
2708 else if (value_cell (old_var))
2709#else
2710 if (value_cell (old_var))
2711#endif
2712 var_setvalue (new_var, savestring (value_cell (old_var)));
2713 else
2714 var_setvalue (new_var, (char *)NULL);
2715 }
726f6388 2716
d233b485
CR
2717 if (localvar_inherit || (flags & MKLOC_INHERIT))
2718 {
2719 /* It doesn't make sense to inherit the nameref attribute */
2720 new_var->attributes = old_var->attributes & ~att_nameref;
2721 new_var->dynamic_value = old_var->dynamic_value;
2722 new_var->assign_func = old_var->assign_func;
2723 }
2724 else
2725 /* We inherit the export attribute, but no others. */
2726 new_var->attributes = exported_p (old_var) ? att_exported : 0;
726f6388
JA
2727 }
2728
d233b485 2729set_local_var_flags:
7117c2d2
JA
2730 vc->flags |= VC_HASLOCAL;
2731
726f6388 2732 new_var->context = variable_context;
bb70624e 2733 VSETATTR (new_var, att_local);
726f6388 2734
7117c2d2
JA
2735 if (ifsname (name))
2736 setifs (new_var);
726f6388 2737
d233b485
CR
2738 /* value_cell will be 0 if localvar_inherit == 0 or there was no old variable
2739 with the same name or the old variable was invisible */
2740 if (was_tmpvar == 0 && no_invisible_vars == 0 && value_cell (new_var) == 0)
ac50fbac 2741 VSETATTR (new_var, att_invisible); /* XXX */
726f6388
JA
2742 return (new_var);
2743}
2744
7117c2d2 2745/* Create a new shell variable with name NAME. */
f73dda09 2746static SHELL_VAR *
7117c2d2 2747new_shell_variable (name)
f73dda09 2748 const char *name;
726f6388 2749{
ccc6cda3 2750 SHELL_VAR *entry;
726f6388 2751
ccc6cda3 2752 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
726f6388 2753
ccc6cda3 2754 entry->name = savestring (name);
7117c2d2 2755 var_setvalue (entry, (char *)NULL);
bb70624e 2756 CLEAR_EXPORTSTR (entry);
726f6388 2757
7117c2d2
JA
2758 entry->dynamic_value = (sh_var_value_func_t *)NULL;
2759 entry->assign_func = (sh_var_assign_func_t *)NULL;
2760
2761 entry->attributes = 0;
ccc6cda3
JA
2762
2763 /* Always assume variables are to be made at toplevel!
ac50fbac 2764 make_local_variable has the responsibility of changing the
ccc6cda3
JA
2765 variable context. */
2766 entry->context = 0;
7117c2d2
JA
2767
2768 return (entry);
2769}
2770
2771/* Create a new shell variable with name NAME and add it to the hash table
2772 TABLE. */
2773static SHELL_VAR *
2774make_new_variable (name, table)
2775 const char *name;
2776 HASH_TABLE *table;
2777{
2778 SHELL_VAR *entry;
2779 BUCKET_CONTENTS *elt;
2780
2781 entry = new_shell_variable (name);
ccc6cda3 2782
28ef6c31
JA
2783 /* Make sure we have a shell_variables hash table to add to. */
2784 if (shell_variables == 0)
0628567a 2785 create_variable_tables ();
28ef6c31 2786
7117c2d2
JA
2787 elt = hash_insert (savestring (name), table, HASH_NOSRCH);
2788 elt->data = (PTR_T)entry;
ccc6cda3
JA
2789
2790 return entry;
2791}
2792
2793#if defined (ARRAY_VARS)
2794SHELL_VAR *
2795make_new_array_variable (name)
2796 char *name;
2797{
2798 SHELL_VAR *entry;
2799 ARRAY *array;
2800
7117c2d2
JA
2801 entry = make_new_variable (name, global_variables->table);
2802 array = array_create ();
3185942a 2803
7117c2d2 2804 var_setarray (entry, array);
bb70624e 2805 VSETATTR (entry, att_array);
ccc6cda3
JA
2806 return entry;
2807}
3185942a
JA
2808
2809SHELL_VAR *
ac50fbac 2810make_local_array_variable (name, assoc_ok)
3185942a 2811 char *name;
ac50fbac 2812 int assoc_ok;
3185942a
JA
2813{
2814 SHELL_VAR *var;
2815 ARRAY *array;
2816
d233b485
CR
2817 var = make_local_variable (name, 0); /* XXX for now */
2818 /* If ASSOC_OK is non-zero, assume that we are ok with letting an assoc
2819 variable return to the caller without converting it. The caller will
2820 either flag an error or do the conversion itself. */
ac50fbac 2821 if (var == 0 || array_p (var) || (assoc_ok && assoc_p (var)))
3185942a
JA
2822 return var;
2823
d233b485
CR
2824 /* Validate any value we inherited from a variable instance at a previous
2825 scope and disard anything that's invalid. */
2826 if (localvar_inherit && assoc_p (var))
2827 {
2828 internal_warning ("%s: cannot inherit value from incompatible type", name);
2829 VUNSETATTR (var, att_assoc);
2830 dispose_variable_value (var);
2831 array = array_create ();
2832 var_setarray (var, array);
2833 }
2834 else if (localvar_inherit)
2835 var = convert_var_to_array (var); /* XXX */
2836 else
2837 {
2838 dispose_variable_value (var);
2839 array = array_create ();
2840 var_setarray (var, array);
2841 }
3185942a 2842
3185942a
JA
2843 VSETATTR (var, att_array);
2844 return var;
2845}
2846
2847SHELL_VAR *
2848make_new_assoc_variable (name)
2849 char *name;
2850{
2851 SHELL_VAR *entry;
2852 HASH_TABLE *hash;
2853
2854 entry = make_new_variable (name, global_variables->table);
2855 hash = assoc_create (0);
2856
2857 var_setassoc (entry, hash);
2858 VSETATTR (entry, att_assoc);
2859 return entry;
2860}
2861
2862SHELL_VAR *
d233b485 2863make_local_assoc_variable (name, array_ok)
3185942a 2864 char *name;
d233b485 2865 int array_ok;
3185942a
JA
2866{
2867 SHELL_VAR *var;
2868 HASH_TABLE *hash;
2869
d233b485
CR
2870 var = make_local_variable (name, 0); /* XXX for now */
2871 /* If ARRAY_OK is non-zero, assume that we are ok with letting an array
2872 variable return to the caller without converting it. The caller will
2873 either flag an error or do the conversion itself. */
2874 if (var == 0 || assoc_p (var) || (array_ok && array_p (var)))
3185942a
JA
2875 return var;
2876
d233b485
CR
2877 /* Validate any value we inherited from a variable instance at a previous
2878 scope and disard anything that's invalid. */
2879 if (localvar_inherit && array_p (var))
2880 {
2881 internal_warning ("%s: cannot inherit value from incompatible type", name);
2882 VUNSETATTR (var, att_array);
2883 dispose_variable_value (var);
2884 hash = assoc_create (0);
2885 var_setassoc (var, hash);
2886 }
2887 else if (localvar_inherit)
2888 var = convert_var_to_assoc (var); /* XXX */
2889 else
2890 {
2891 dispose_variable_value (var);
2892 hash = assoc_create (0);
2893 var_setassoc (var, hash);
2894 }
3185942a 2895
3185942a
JA
2896 VSETATTR (var, att_assoc);
2897 return var;
2898}
ccc6cda3
JA
2899#endif
2900
2901char *
95732b49 2902make_variable_value (var, value, flags)
ccc6cda3
JA
2903 SHELL_VAR *var;
2904 char *value;
95732b49 2905 int flags;
ccc6cda3 2906{
95732b49
JA
2907 char *retval, *oval;
2908 intmax_t lval, rval;
3185942a 2909 int expok, olen, op;
ccc6cda3
JA
2910
2911 /* If this variable has had its type set to integer (via `declare -i'),
2912 then do expression evaluation on it and store the result. The
7117c2d2 2913 functions in expr.c (evalexp()) and bind_int_variable() are responsible
ccc6cda3 2914 for turning off the integer flag if they don't want further
d233b485
CR
2915 evaluation done. Callers that find it inconvenient to do this can set
2916 the ASS_NOEVAL flag. For the special case of arithmetic expression
2917 evaluation, the caller can set ASS_NOLONGJMP to avoid jumping out to
2918 top_level. */
2919 if ((flags & ASS_NOEVAL) == 0 && integer_p (var))
ccc6cda3 2920 {
95732b49
JA
2921 if (flags & ASS_APPEND)
2922 {
2923 oval = value_cell (var);
d233b485 2924 lval = evalexp (oval, 0, &expok); /* ksh93 seems to do this */
95732b49 2925 if (expok == 0)
f1be666c 2926 {
d233b485
CR
2927 if (flags & ASS_NOLONGJMP)
2928 goto make_value;
2929 else
2930 {
2931 top_level_cleanup ();
2932 jump_to_top_level (DISCARD);
2933 }
f1be666c 2934 }
95732b49 2935 }
d233b485 2936 rval = evalexp (value, 0, &expok);
d166f048 2937 if (expok == 0)
f1be666c 2938 {
d233b485
CR
2939 if (flags & ASS_NOLONGJMP)
2940 goto make_value;
2941 else
2942 {
2943 top_level_cleanup ();
2944 jump_to_top_level (DISCARD);
2945 }
f1be666c 2946 }
ac50fbac
CR
2947 /* This can be fooled if the variable's value changes while evaluating
2948 `rval'. We can change it if we move the evaluation of lval to here. */
95732b49
JA
2949 if (flags & ASS_APPEND)
2950 rval += lval;
2951 retval = itos (rval);
ccc6cda3 2952 }
3185942a 2953#if defined (CASEMOD_ATTRS)
d233b485 2954 else if ((flags & ASS_NOEVAL) == 0 && (capcase_p (var) || uppercase_p (var) || lowercase_p (var)))
3185942a
JA
2955 {
2956 if (flags & ASS_APPEND)
2957 {
2958 oval = get_variable_value (var);
2959 if (oval == 0) /* paranoia */
2960 oval = "";
2961 olen = STRLEN (oval);
2962 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2963 strcpy (retval, oval);
2964 if (value)
2965 strcpy (retval+olen, value);
2966 }
2967 else if (*value)
2968 retval = savestring (value);
2969 else
2970 {
2971 retval = (char *)xmalloc (1);
2972 retval[0] = '\0';
2973 }
2974 op = capcase_p (var) ? CASE_CAPITALIZE
2975 : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER);
2976 oval = sh_modcase (retval, (char *)0, op);
2977 free (retval);
2978 retval = oval;
2979 }
2980#endif /* CASEMOD_ATTRS */
ccc6cda3
JA
2981 else if (value)
2982 {
d233b485 2983make_value:
95732b49
JA
2984 if (flags & ASS_APPEND)
2985 {
2986 oval = get_variable_value (var);
2987 if (oval == 0) /* paranoia */
2988 oval = "";
2989 olen = STRLEN (oval);
2990 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2991 strcpy (retval, oval);
2992 if (value)
2993 strcpy (retval+olen, value);
2994 }
2995 else if (*value)
ccc6cda3
JA
2996 retval = savestring (value);
2997 else
726f6388 2998 {
f73dda09 2999 retval = (char *)xmalloc (1);
ccc6cda3 3000 retval[0] = '\0';
726f6388 3001 }
ccc6cda3
JA
3002 }
3003 else
3004 retval = (char *)NULL;
726f6388 3005
ccc6cda3
JA
3006 return retval;
3007}
726f6388 3008
d233b485
CR
3009/* If we can optimize appending to string variables, say so */
3010static int
3011can_optimize_assignment (entry, value, aflags)
3012 SHELL_VAR *entry;
3013 char *value;
3014 int aflags;
3015{
3016 if ((aflags & ASS_APPEND) == 0)
3017 return 0;
3018#if defined (ARRAY_VARS)
3019 if (array_p (entry) || assoc_p (entry))
3020 return 0;
3021#endif
3022 if (integer_p (entry) || uppercase_p (entry) || lowercase_p (entry) || capcase_p (entry))
3023 return 0;
3024 if (readonly_p (entry) || noassign_p (entry))
3025 return 0;
3026 return 1;
3027}
3028
3029/* right now we optimize appends to string variables */
3030static SHELL_VAR *
3031optimized_assignment (entry, value, aflags)
3032 SHELL_VAR *entry;
3033 char *value;
3034 int aflags;
3035{
3036 size_t len, vlen;
3037 char *v, *new;
3038
3039 v = value_cell (entry);
3040 len = STRLEN (v);
3041 vlen = STRLEN (value);
3042
3043 new = (char *)xrealloc (v, len + vlen + 8); /* for now */
3044 if (vlen == 1)
3045 {
3046 new[len] = *value;
3047 new[len+1] = '\0';
3048 }
3049 else
3050 strcpy (new + len, value);
3051 var_setvalue (entry, new);
3052 return entry;
3053}
3054
7117c2d2 3055/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
d233b485
CR
3056 temporary environment (but usually is not). HFLAGS controls how NAME
3057 is looked up in TABLE; AFLAGS controls how VALUE is assigned */
7117c2d2 3058static SHELL_VAR *
95732b49 3059bind_variable_internal (name, value, table, hflags, aflags)
f73dda09
JA
3060 const char *name;
3061 char *value;
7117c2d2 3062 HASH_TABLE *table;
95732b49 3063 int hflags, aflags;
ccc6cda3 3064{
a0c0a00f
CR
3065 char *newval, *tname;
3066 SHELL_VAR *entry, *tentry;
28ef6c31 3067
7117c2d2 3068 entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
ac50fbac
CR
3069 /* Follow the nameref chain here if this is the global variables table */
3070 if (entry && nameref_p (entry) && (invisible_p (entry) == 0) && table == global_variables->table)
3071 {
3072 entry = find_global_variable (entry->name);
3073 /* Let's see if we have a nameref referencing a variable that hasn't yet
3074 been created. */
3075 if (entry == 0)
a0c0a00f 3076 entry = find_variable_last_nameref (name, 0); /* XXX */
ac50fbac
CR
3077 if (entry == 0) /* just in case */
3078 return (entry);
3079 }
ccc6cda3 3080
a0c0a00f
CR
3081 /* The first clause handles `declare -n ref; ref=x;' or `declare -n ref;
3082 declare -n ref' */
ac50fbac 3083 if (entry && invisible_p (entry) && nameref_p (entry))
a0c0a00f
CR
3084 {
3085 if ((aflags & ASS_FORCE) == 0 && value && valid_nameref_value (value, 0) == 0)
3086 {
3087 sh_invalidid (value);
3088 return ((SHELL_VAR *)NULL);
3089 }
3090 goto assign_value;
3091 }
ac50fbac
CR
3092 else if (entry && nameref_p (entry))
3093 {
d233b485
CR
3094 newval = nameref_cell (entry); /* XXX - newval can't be NULL here */
3095 if (valid_nameref_value (newval, 0) == 0)
3096 {
3097 sh_invalidid (newval);
3098 return ((SHELL_VAR *)NULL);
3099 }
ac50fbac 3100#if defined (ARRAY_VARS)
a0c0a00f
CR
3101 /* declare -n foo=x[2] ; foo=bar */
3102 if (valid_array_reference (newval, 0))
3103 {
d233b485 3104 tname = array_variable_name (newval, 0, (char **)0, (int *)0);
a0c0a00f
CR
3105 if (tname && (tentry = find_variable_noref (tname)) && nameref_p (tentry))
3106 {
3107 /* nameref variables can't be arrays */
3108 internal_warning (_("%s: removing nameref attribute"), name_cell (tentry));
3109 FREE (value_cell (tentry)); /* XXX - bash-4.3 compat */
3110 var_setvalue (tentry, (char *)NULL);
3111 VUNSETATTR (tentry, att_nameref);
3112 }
3113 free (tname);
3114 /* XXX - should it be aflags? */
d233b485 3115 entry = assign_array_element (newval, make_variable_value (entry, value, aflags), aflags|ASS_NAMEREF);
a0c0a00f
CR
3116 if (entry == 0)
3117 return entry;
3118 }
ac50fbac
CR
3119 else
3120#endif
d233b485
CR
3121 {
3122 entry = make_new_variable (newval, table);
3123 var_setvalue (entry, make_variable_value (entry, value, aflags));
3124 }
ac50fbac
CR
3125 }
3126 else if (entry == 0)
ccc6cda3 3127 {
7117c2d2 3128 entry = make_new_variable (name, table);
d233b485 3129 var_setvalue (entry, make_variable_value (entry, value, aflags)); /* XXX */
726f6388 3130 }
28ef6c31 3131 else if (entry->assign_func) /* array vars have assign functions now */
bb70624e
JA
3132 {
3133 INVALIDATE_EXPORTSTR (entry);
95732b49 3134 newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
0001803f
CR
3135 if (assoc_p (entry))
3136 entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0"));
3137 else if (array_p (entry))
3138 entry = (*(entry->assign_func)) (entry, newval, 0, 0);
3139 else
3140 entry = (*(entry->assign_func)) (entry, newval, -1, 0);
95732b49 3141 if (newval != value)
3185942a 3142 free (newval);
95732b49 3143 return (entry);
bb70624e 3144 }
726f6388
JA
3145 else
3146 {
ac50fbac 3147assign_value:
a0c0a00f 3148 if ((readonly_p (entry) && (aflags & ASS_FORCE) == 0) || noassign_p (entry))
726f6388 3149 {
28ef6c31 3150 if (readonly_p (entry))
a0c0a00f 3151 err_readonly (name_cell (entry));
726f6388
JA
3152 return (entry);
3153 }
3154
3155 /* Variables which are bound are visible. */
bb70624e 3156 VUNSETATTR (entry, att_invisible);
726f6388 3157
d233b485
CR
3158 /* If we can optimize the assignment, do so and return. Right now, we
3159 optimize appends to string variables. */
3160 if (can_optimize_assignment (entry, value, aflags))
3161 {
3162 INVALIDATE_EXPORTSTR (entry);
3163 optimized_assignment (entry, value, aflags);
3164
3165 if (mark_modified_vars)
3166 VSETATTR (entry, att_exported);
3167
3168 if (exported_p (entry))
3169 array_needs_making = 1;
3170
3171 return (entry);
3172 }
3173
ac50fbac
CR
3174#if defined (ARRAY_VARS)
3175 if (assoc_p (entry) || array_p (entry))
3176 newval = make_array_variable_value (entry, 0, "0", value, aflags);
3177 else
3178#endif
95732b49 3179 newval = make_variable_value (entry, value, aflags); /* XXX */
726f6388 3180
bb70624e
JA
3181 /* Invalidate any cached export string */
3182 INVALIDATE_EXPORTSTR (entry);
3183
ccc6cda3
JA
3184#if defined (ARRAY_VARS)
3185 /* XXX -- this bears looking at again -- XXX */
3186 /* If an existing array variable x is being assigned to with x=b or
3187 `read x' or something of that nature, silently convert it to
3188 x[0]=b or `read x[0]'. */
ac50fbac 3189 if (assoc_p (entry))
d166f048 3190 {
ac50fbac 3191 assoc_insert (assoc_cell (entry), savestring ("0"), newval);
d166f048
JA
3192 free (newval);
3193 }
ac50fbac 3194 else if (array_p (entry))
3185942a 3195 {
ac50fbac 3196 array_insert (array_cell (entry), 0, newval);
3185942a
JA
3197 free (newval);
3198 }
726f6388 3199 else
f73dda09 3200#endif
726f6388 3201 {
7117c2d2
JA
3202 FREE (value_cell (entry));
3203 var_setvalue (entry, newval);
726f6388
JA
3204 }
3205 }
3206
3207 if (mark_modified_vars)
bb70624e 3208 VSETATTR (entry, att_exported);
726f6388
JA
3209
3210 if (exported_p (entry))
3211 array_needs_making = 1;
3212
3213 return (entry);
3214}
7117c2d2
JA
3215
3216/* Bind a variable NAME to VALUE. This conses up the name
3217 and value strings. If we have a temporary environment, we bind there
3218 first, then we bind into shell_variables. */
3219
3220SHELL_VAR *
95732b49 3221bind_variable (name, value, flags)
7117c2d2
JA
3222 const char *name;
3223 char *value;
95732b49 3224 int flags;
7117c2d2 3225{
ac50fbac
CR
3226 SHELL_VAR *v, *nv;
3227 VAR_CONTEXT *vc, *nvc;
7117c2d2
JA
3228
3229 if (shell_variables == 0)
0628567a 3230 create_variable_tables ();
7117c2d2
JA
3231
3232 /* If we have a temporary environment, look there first for the variable,
3233 and, if found, modify the value there before modifying it in the
3234 shell_variables table. This allows sourced scripts to modify values
3235 given to them in a temporary environment while modifying the variable
3236 value that the caller sees. */
a0c0a00f 3237 if (temporary_env && value) /* XXX - can value be null here? */
7117c2d2
JA
3238 bind_tempenv_variable (name, value);
3239
3240 /* XXX -- handle local variables here. */
3241 for (vc = shell_variables; vc; vc = vc->down)
3242 {
3243 if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
3185942a
JA
3244 {
3245 v = hash_lookup (name, vc->table);
ac50fbac
CR
3246 nvc = vc;
3247 if (v && nameref_p (v))
3248 {
d233b485
CR
3249 /* This starts at the context where we found the nameref. If we
3250 want to start the name resolution over again at the original
3251 context, this is where we need to change it */
ac50fbac
CR
3252 nv = find_variable_nameref_context (v, vc, &nvc);
3253 if (nv == 0)
3254 {
3255 nv = find_variable_last_nameref_context (v, vc, &nvc);
3256 if (nv && nameref_p (nv))
3257 {
3258 /* If this nameref variable doesn't have a value yet,
3259 set the value. Otherwise, assign using the value as
3260 normal. */
3261 if (nameref_cell (nv) == 0)
3262 return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
a0c0a00f
CR
3263#if defined (ARRAY_VARS)
3264 else if (valid_array_reference (nameref_cell (nv), 0))
3265 return (assign_array_element (nameref_cell (nv), value, flags));
3266 else
3267#endif
3268 return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
3269 }
3270 else if (nv == &nameref_maxloop_value)
3271 {
3272 internal_warning (_("%s: circular name reference"), v->name);
d233b485
CR
3273#if 1
3274 /* TAG:bash-5.1 */
3275 return (bind_global_variable (v->name, value, flags));
a0c0a00f
CR
3276#else
3277 v = 0; /* backwards compat */
3278#endif
ac50fbac
CR
3279 }
3280 else
3281 v = nv;
3282 }
a0c0a00f
CR
3283 else if (nv == &nameref_maxloop_value)
3284 {
3285 internal_warning (_("%s: circular name reference"), v->name);
d233b485
CR
3286#if 1
3287 /* TAG:bash-5.1 */
3288 return (bind_global_variable (v->name, value, flags));
a0c0a00f
CR
3289#else
3290 v = 0; /* backwards compat */
3291#endif
3292 }
ac50fbac
CR
3293 else
3294 v = nv;
3295 }
3185942a 3296 if (v)
ac50fbac 3297 return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
3185942a 3298 }
7117c2d2 3299 }
ac50fbac
CR
3300 /* bind_variable_internal will handle nameref resolution in this case */
3301 return (bind_variable_internal (name, value, global_variables->table, 0, flags));
3302}
3303
3304SHELL_VAR *
3305bind_global_variable (name, value, flags)
3306 const char *name;
3307 char *value;
3308 int flags;
3309{
ac50fbac
CR
3310 if (shell_variables == 0)
3311 create_variable_tables ();
3312
3313 /* bind_variable_internal will handle nameref resolution in this case */
95732b49 3314 return (bind_variable_internal (name, value, global_variables->table, 0, flags));
7117c2d2 3315}
726f6388 3316
d233b485
CR
3317static SHELL_VAR *
3318bind_invalid_envvar (name, value, flags)
3319 const char *name;
3320 char *value;
3321 int flags;
3322{
3323 if (invalid_env == 0)
3324 invalid_env = hash_create (64); /* XXX */
3325 return (bind_variable_internal (name, value, invalid_env, HASH_NOSRCH, flags));
3326}
3327
bb70624e
JA
3328/* Make VAR, a simple shell variable, have value VALUE. Once assigned a
3329 value, variables are no longer invisible. This is a duplicate of part
3330 of the internals of bind_variable. If the variable is exported, or
3331 all modified variables should be exported, mark the variable for export
3332 and note that the export environment needs to be recreated. */
3333SHELL_VAR *
95732b49 3334bind_variable_value (var, value, aflags)
bb70624e
JA
3335 SHELL_VAR *var;
3336 char *value;
95732b49 3337 int aflags;
bb70624e
JA
3338{
3339 char *t;
ac50fbac 3340 int invis;
bb70624e 3341
ac50fbac 3342 invis = invisible_p (var);
bb70624e
JA
3343 VUNSETATTR (var, att_invisible);
3344
95732b49
JA
3345 if (var->assign_func)
3346 {
3347 /* If we're appending, we need the old value, so use
3348 make_variable_value */
3349 t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
3185942a 3350 (*(var->assign_func)) (var, t, -1, 0);
95732b49
JA
3351 if (t != value && t)
3352 free (t);
3353 }
3354 else
3355 {
3356 t = make_variable_value (var, value, aflags);
a0c0a00f
CR
3357 if ((aflags & (ASS_NAMEREF|ASS_FORCE)) == ASS_NAMEREF && check_selfref (name_cell (var), t, 0))
3358 {
3359 if (variable_context)
3360 internal_warning (_("%s: circular name reference"), name_cell (var));
3361 else
3362 {
3363 internal_error (_("%s: nameref variable self references not allowed"), name_cell (var));
3364 free (t);
3365 if (invis)
3366 VSETATTR (var, att_invisible); /* XXX */
3367 return ((SHELL_VAR *)NULL);
3368 }
3369 }
3370 if ((aflags & ASS_NAMEREF) && (valid_nameref_value (t, 0) == 0))
ac50fbac
CR
3371 {
3372 free (t);
3373 if (invis)
3374 VSETATTR (var, att_invisible); /* XXX */
3375 return ((SHELL_VAR *)NULL);
3376 }
95732b49
JA
3377 FREE (value_cell (var));
3378 var_setvalue (var, t);
3379 }
bb70624e
JA
3380
3381 INVALIDATE_EXPORTSTR (var);
3382
3383 if (mark_modified_vars)
3384 VSETATTR (var, att_exported);
3385
3386 if (exported_p (var))
3387 array_needs_making = 1;
3388
3389 return (var);
3390}
3391
3392/* Bind/create a shell variable with the name LHS to the RHS.
3393 This creates or modifies a variable such that it is an integer.
3394
3395 This used to be in expr.c, but it is here so that all of the
3396 variable binding stuff is localized. Since we don't want any
3397 recursive evaluation from bind_variable() (possible without this code,
3398 since bind_variable() calls the evaluator for variables with the integer
3399 attribute set), we temporarily turn off the integer attribute for each
3400 variable we set here, then turn it back on after binding as necessary. */
3401
3402SHELL_VAR *
d233b485 3403bind_int_variable (lhs, rhs, flags)
bb70624e 3404 char *lhs, *rhs;
d233b485 3405 int flags;
bb70624e
JA
3406{
3407 register SHELL_VAR *v;
ac50fbac 3408 int isint, isarr, implicitarray;
7117c2d2 3409
ac50fbac 3410 isint = isarr = implicitarray = 0;
7117c2d2 3411#if defined (ARRAY_VARS)
d233b485 3412 if (valid_array_reference (lhs, (flags & ASS_NOEXPAND) != 0))
7117c2d2
JA
3413 {
3414 isarr = 1;
d233b485
CR
3415 v = array_variable_part (lhs, (flags & ASS_NOEXPAND) != 0, (char **)0, (int *)0);
3416 }
3417 else if (legal_identifier (lhs) == 0)
3418 {
3419 sh_invalidid (lhs);
3420 return ((SHELL_VAR *)NULL);
7117c2d2
JA
3421 }
3422 else
3423#endif
3424 v = find_variable (lhs);
bb70624e 3425
bb70624e
JA
3426 if (v)
3427 {
3428 isint = integer_p (v);
3429 VUNSETATTR (v, att_integer);
ac50fbac
CR
3430#if defined (ARRAY_VARS)
3431 if (array_p (v) && isarr == 0)
3432 implicitarray = 1;
3433#endif
bb70624e
JA
3434 }
3435
7117c2d2
JA
3436#if defined (ARRAY_VARS)
3437 if (isarr)
d233b485 3438 v = assign_array_element (lhs, rhs, flags);
ac50fbac 3439 else if (implicitarray)
d233b485 3440 v = bind_array_variable (lhs, 0, rhs, 0); /* XXX - check on flags */
7117c2d2
JA
3441 else
3442#endif
d233b485 3443 v = bind_variable (lhs, rhs, 0); /* why not use bind_variable_value? */
7117c2d2 3444
4e3e5312
CR
3445 if (v)
3446 {
3447 if (isint)
3448 VSETATTR (v, att_integer);
3449 VUNSETATTR (v, att_invisible);
3450 }
ac50fbac 3451
a0c0a00f
CR
3452 if (v && nameref_p (v))
3453 internal_warning (_("%s: assigning integer to name reference"), lhs);
3454
bb70624e
JA
3455 return (v);
3456}
3457
ccc6cda3 3458SHELL_VAR *
f73dda09
JA
3459bind_var_to_int (var, val)
3460 char *var;
7117c2d2 3461 intmax_t val;
ccc6cda3 3462{
7117c2d2 3463 char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
ccc6cda3 3464
f73dda09 3465 p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
d233b485 3466 return (bind_int_variable (var, p, 0));
ccc6cda3
JA
3467}
3468
7117c2d2
JA
3469/* Do a function binding to a variable. You pass the name and
3470 the command to bind to. This conses the name and command. */
3471SHELL_VAR *
3472bind_function (name, value)
3473 const char *name;
3474 COMMAND *value;
3475{
3476 SHELL_VAR *entry;
3477
3478 entry = find_function (name);
3479 if (entry == 0)
3480 {
3481 BUCKET_CONTENTS *elt;
3482
3483 elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
3484 entry = new_shell_variable (name);
3485 elt->data = (PTR_T)entry;
3486 }
3487 else
3488 INVALIDATE_EXPORTSTR (entry);
3489
3490 if (var_isset (entry))
3491 dispose_command (function_cell (entry));
3492
3493 if (value)
3494 var_setfunc (entry, copy_command (value));
3495 else
3496 var_setfunc (entry, 0);
3497
3498 VSETATTR (entry, att_function);
3499
3500 if (mark_modified_vars)
3501 VSETATTR (entry, att_exported);
3502
3503 VUNSETATTR (entry, att_invisible); /* Just to be sure */
3504
3505 if (exported_p (entry))
3506 array_needs_making = 1;
3507
3508#if defined (PROGRAMMABLE_COMPLETION)
3509 set_itemlist_dirty (&it_functions);
3510#endif
3511
3512 return (entry);
3513}
3514
3185942a 3515#if defined (DEBUGGER)
b80f6443 3516/* Bind a function definition, which includes source file and line number
d233b485
CR
3517 information in addition to the command, into the FUNCTION_DEF hash table.
3518 If (FLAGS & 1), overwrite any existing definition. If FLAGS == 0, leave
3519 any existing definition alone. */
b80f6443 3520void
d233b485 3521bind_function_def (name, value, flags)
b80f6443
JA
3522 const char *name;
3523 FUNCTION_DEF *value;
d233b485 3524 int flags;
b80f6443
JA
3525{
3526 FUNCTION_DEF *entry;
3527 BUCKET_CONTENTS *elt;
3528 COMMAND *cmd;
3529
3530 entry = find_function_def (name);
d233b485 3531 if (entry && (flags & 1))
b80f6443
JA
3532 {
3533 dispose_function_def_contents (entry);
3534 entry = copy_function_def_contents (value, entry);
3535 }
d233b485
CR
3536 else if (entry)
3537 return;
b80f6443
JA
3538 else
3539 {
3540 cmd = value->command;
3541 value->command = 0;
3542 entry = copy_function_def (value);
3543 value->command = cmd;
3544
3545 elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
3546 elt->data = (PTR_T *)entry;
3547 }
3548}
3185942a 3549#endif /* DEBUGGER */
b80f6443 3550
7117c2d2
JA
3551/* Add STRING, which is of the form foo=bar, to the temporary environment
3552 HASH_TABLE (temporary_env). The functions in execute_cmd.c are
3553 responsible for moving the main temporary env to one of the other
3554 temporary environments. The expansion code in subst.c calls this. */
3555int
495aee44 3556assign_in_env (word, flags)
95732b49 3557 WORD_DESC *word;
495aee44 3558 int flags;
7117c2d2 3559{
ac50fbac 3560 int offset, aflags;
a0c0a00f 3561 char *name, *temp, *value, *newname;
7117c2d2 3562 SHELL_VAR *var;
95732b49
JA
3563 const char *string;
3564
3565 string = word->word;
7117c2d2 3566
ac50fbac 3567 aflags = 0;
b80f6443 3568 offset = assignment (string, 0);
a0c0a00f 3569 newname = name = savestring (string);
7117c2d2
JA
3570 value = (char *)NULL;
3571
3572 if (name[offset] == '=')
3573 {
3574 name[offset] = 0;
3575
ac50fbac 3576 /* don't ignore the `+' when assigning temporary environment */
95732b49 3577 if (name[offset - 1] == '+')
ac50fbac
CR
3578 {
3579 name[offset - 1] = '\0';
3580 aflags |= ASS_APPEND;
3581 }
95732b49 3582
d233b485
CR
3583 if (legal_identifier (name) == 0)
3584 {
3585 sh_invalidid (name);
3586 return (0);
3587 }
3588
7117c2d2 3589 var = find_variable (name);
a0c0a00f
CR
3590 if (var == 0)
3591 {
3592 var = find_variable_last_nameref (name, 1);
3593 /* If we're assigning a value to a nameref variable in the temp
3594 environment, and the value of the nameref is valid for assignment,
3595 but the variable does not already exist, assign to the nameref
3596 target and add the target to the temporary environment. This is
3597 what ksh93 does */
d233b485
CR
3598 /* We use 2 in the call to valid_nameref_value because we don't want
3599 to allow array references here at all (newname will be used to
3600 create a variable directly below) */
3601 if (var && nameref_p (var) && valid_nameref_value (nameref_cell (var), 2))
a0c0a00f
CR
3602 {
3603 newname = nameref_cell (var);
3604 var = 0; /* don't use it for append */
3605 }
3606 }
3607 else
3608 newname = name_cell (var); /* no-op if not nameref */
3609
7117c2d2
JA
3610 if (var && (readonly_p (var) || noassign_p (var)))
3611 {
3612 if (readonly_p (var))
3613 err_readonly (name);
3614 free (name);
3615 return (0);
3616 }
7117c2d2 3617 temp = name + offset + 1;
a0c0a00f 3618
95732b49 3619 value = expand_assignment_string_to_string (temp, 0);
ac50fbac
CR
3620
3621 if (var && (aflags & ASS_APPEND))
3622 {
a0c0a00f
CR
3623 if (value == 0)
3624 {
3625 value = (char *)xmalloc (1); /* like do_assignment_internal */
3626 value[0] = '\0';
3627 }
ac50fbac
CR
3628 temp = make_variable_value (var, value, aflags);
3629 FREE (value);
3630 value = temp;
3631 }
7117c2d2
JA
3632 }
3633
3634 if (temporary_env == 0)
3635 temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
3636
a0c0a00f 3637 var = hash_lookup (newname, temporary_env);
7117c2d2 3638 if (var == 0)
a0c0a00f 3639 var = make_new_variable (newname, temporary_env);
7117c2d2
JA
3640 else
3641 FREE (value_cell (var));
3642
3643 if (value == 0)
3644 {
a0c0a00f 3645 value = (char *)xmalloc (1); /* see above */
7117c2d2
JA
3646 value[0] = '\0';
3647 }
3648
3649 var_setvalue (var, value);
3650 var->attributes |= (att_exported|att_tempvar);
3651 var->context = variable_context; /* XXX */
3652
3653 INVALIDATE_EXPORTSTR (var);
a0c0a00f 3654 var->exportstr = mk_env_string (newname, value, 0);
7117c2d2
JA
3655
3656 array_needs_making = 1;
3657
495aee44 3658 if (flags)
a0c0a00f 3659 stupidly_hack_special_variables (newname);
7117c2d2
JA
3660
3661 if (echo_command_at_execute)
b80f6443
JA
3662 /* The Korn shell prints the `+ ' in front of assignment statements,
3663 so we do too. */
3664 xtrace_print_assignment (name, value, 0, 1);
7117c2d2 3665
b80f6443 3666 free (name);
7117c2d2
JA
3667 return 1;
3668}
3669
3670/* **************************************************************** */
3671/* */
3672/* Copying variables */
3673/* */
3674/* **************************************************************** */
3675
3676#ifdef INCLUDE_UNUSED
3677/* Copy VAR to a new data structure and return that structure. */
3678SHELL_VAR *
3679copy_variable (var)
3680 SHELL_VAR *var;
3681{
3682 SHELL_VAR *copy = (SHELL_VAR *)NULL;
3683
3684 if (var)
3685 {
3686 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
3687
3688 copy->attributes = var->attributes;
3689 copy->name = savestring (var->name);
3690
3691 if (function_p (var))
3692 var_setfunc (copy, copy_command (function_cell (var)));
3693#if defined (ARRAY_VARS)
3694 else if (array_p (var))
3185942a
JA
3695 var_setarray (copy, array_copy (array_cell (var)));
3696 else if (assoc_p (var))
3697 var_setassoc (copy, assoc_copy (assoc_cell (var)));
7117c2d2 3698#endif
ac50fbac
CR
3699 else if (nameref_cell (var)) /* XXX - nameref */
3700 var_setref (copy, savestring (nameref_cell (var)));
3701 else if (value_cell (var)) /* XXX - nameref */
7117c2d2
JA
3702 var_setvalue (copy, savestring (value_cell (var)));
3703 else
3704 var_setvalue (copy, (char *)NULL);
3705
3706 copy->dynamic_value = var->dynamic_value;
3707 copy->assign_func = var->assign_func;
3708
3709 copy->exportstr = COPY_EXPORTSTR (var);
3710
3711 copy->context = var->context;
3712 }
3713 return (copy);
3714}
3715#endif
3716
3717/* **************************************************************** */
3718/* */
3719/* Deleting and unsetting variables */
3720/* */
3721/* **************************************************************** */
3722
726f6388 3723/* Dispose of the information attached to VAR. */
3185942a
JA
3724static void
3725dispose_variable_value (var)
726f6388
JA
3726 SHELL_VAR *var;
3727{
726f6388 3728 if (function_p (var))
ccc6cda3
JA
3729 dispose_command (function_cell (var));
3730#if defined (ARRAY_VARS)
3731 else if (array_p (var))
7117c2d2 3732 array_dispose (array_cell (var));
3185942a
JA
3733 else if (assoc_p (var))
3734 assoc_dispose (assoc_cell (var));
ccc6cda3 3735#endif
ac50fbac
CR
3736 else if (nameref_p (var))
3737 FREE (nameref_cell (var));
ccc6cda3
JA
3738 else
3739 FREE (value_cell (var));
3185942a
JA
3740}
3741
3742void
3743dispose_variable (var)
3744 SHELL_VAR *var;
3745{
3746 if (var == 0)
3747 return;
3748
3749 if (nofree_p (var) == 0)
3750 dispose_variable_value (var);
726f6388 3751
bb70624e
JA
3752 FREE_EXPORTSTR (var);
3753
726f6388
JA
3754 free (var->name);
3755
3756 if (exported_p (var))
3757 array_needs_making = 1;
3758
3759 free (var);
3760}
3761
ac50fbac
CR
3762/* Unset the shell variable referenced by NAME. Unsetting a nameref variable
3763 unsets the variable it resolves to but leaves the nameref alone. */
ccc6cda3 3764int
726f6388 3765unbind_variable (name)
f73dda09 3766 const char *name;
726f6388 3767{
ac50fbac
CR
3768 SHELL_VAR *v, *nv;
3769 int r;
3770
3771 v = var_lookup (name, shell_variables);
3772 nv = (v && nameref_p (v)) ? find_variable_nameref (v) : (SHELL_VAR *)NULL;
3773
3774 r = nv ? makunbound (nv->name, shell_variables) : makunbound (name, shell_variables);
3775 return r;
3776}
3777
3778/* Unbind NAME, where NAME is assumed to be a nameref variable */
3779int
3780unbind_nameref (name)
3781 const char *name;
3782{
3783 SHELL_VAR *v;
3784
3785 v = var_lookup (name, shell_variables);
3786 if (v && nameref_p (v))
3787 return makunbound (name, shell_variables);
3788 return 0;
7117c2d2 3789}
726f6388 3790
a0c0a00f
CR
3791/* Unbind the first instance of NAME, whether it's a nameref or not */
3792int
3793unbind_variable_noref (name)
3794 const char *name;
3795{
3796 SHELL_VAR *v;
3797
3798 v = var_lookup (name, shell_variables);
3799 if (v)
3800 return makunbound (name, shell_variables);
3801 return 0;
3802}
3803
3804int
3805check_unbind_variable (name)
3806 const char *name;
3807{
3808 SHELL_VAR *v;
3809
3810 v = find_variable (name);
3811 if (v && readonly_p (v))
3812 {
3813 internal_error (_("%s: cannot unset: readonly %s"), name, "variable");
3814 return -1;
3815 }
3816 return (unbind_variable (name));
3817}
3818
7117c2d2
JA
3819/* Unset the shell function named NAME. */
3820int
3821unbind_func (name)
3822 const char *name;
3823{
3824 BUCKET_CONTENTS *elt;
3825 SHELL_VAR *func;
726f6388 3826
7117c2d2
JA
3827 elt = hash_remove (name, shell_functions, 0);
3828
3829 if (elt == 0)
3830 return -1;
3831
3832#if defined (PROGRAMMABLE_COMPLETION)
3833 set_itemlist_dirty (&it_functions);
ccc6cda3 3834#endif
7117c2d2
JA
3835
3836 func = (SHELL_VAR *)elt->data;
3837 if (func)
726f6388 3838 {
7117c2d2
JA
3839 if (exported_p (func))
3840 array_needs_making++;
3841 dispose_variable (func);
726f6388
JA
3842 }
3843
7117c2d2
JA
3844 free (elt->key);
3845 free (elt);
726f6388 3846
7117c2d2 3847 return 0;
726f6388
JA
3848}
3849
3185942a 3850#if defined (DEBUGGER)
b80f6443
JA
3851int
3852unbind_function_def (name)
3853 const char *name;
3854{
3855 BUCKET_CONTENTS *elt;
3856 FUNCTION_DEF *funcdef;
3857
3858 elt = hash_remove (name, shell_function_defs, 0);
3859
3860 if (elt == 0)
3861 return -1;
3862
3863 funcdef = (FUNCTION_DEF *)elt->data;
3864 if (funcdef)
3865 dispose_function_def (funcdef);
3866
3867 free (elt->key);
3868 free (elt);
3869
3870 return 0;
3871}
3185942a 3872#endif /* DEBUGGER */
b80f6443 3873
ac50fbac
CR
3874int
3875delete_var (name, vc)
3876 const char *name;
3877 VAR_CONTEXT *vc;
3878{
3879 BUCKET_CONTENTS *elt;
3880 SHELL_VAR *old_var;
3881 VAR_CONTEXT *v;
3882
3883 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
3884 if (elt = hash_remove (name, v->table, 0))
3885 break;
3886
3887 if (elt == 0)
3888 return (-1);
3889
3890 old_var = (SHELL_VAR *)elt->data;
3891 free (elt->key);
3892 free (elt);
3893
3894 dispose_variable (old_var);
3895 return (0);
3896}
3897
726f6388
JA
3898/* Make the variable associated with NAME go away. HASH_LIST is the
3899 hash table from which this variable should be deleted (either
3900 shell_variables or shell_functions).
3901 Returns non-zero if the variable couldn't be found. */
ccc6cda3 3902int
7117c2d2 3903makunbound (name, vc)
f73dda09 3904 const char *name;
7117c2d2 3905 VAR_CONTEXT *vc;
726f6388 3906{
d166f048 3907 BUCKET_CONTENTS *elt, *new_elt;
7117c2d2
JA
3908 SHELL_VAR *old_var;
3909 VAR_CONTEXT *v;
726f6388
JA
3910 char *t;
3911
7117c2d2
JA
3912 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
3913 if (elt = hash_remove (name, v->table, 0))
3914 break;
726f6388 3915
d166f048 3916 if (elt == 0)
726f6388
JA
3917 return (-1);
3918
3919 old_var = (SHELL_VAR *)elt->data;
726f6388
JA
3920
3921 if (old_var && exported_p (old_var))
3922 array_needs_making++;
3923
ccc6cda3 3924 /* If we're unsetting a local variable and we're still executing inside
7117c2d2
JA
3925 the function, just mark the variable as invisible. The function
3926 eventually called by pop_var_context() will clean it up later. This
3927 must be done so that if the variable is subsequently assigned a new
3928 value inside the function, the `local' attribute is still present.
3929 We also need to add it back into the correct hash table. */
d233b485
CR
3930 if (old_var && local_p (old_var) &&
3931 (old_var->context == variable_context || (localvar_unset && old_var->context < variable_context)))
ccc6cda3 3932 {
3185942a
JA
3933 if (nofree_p (old_var))
3934 var_setvalue (old_var, (char *)NULL);
95732b49 3935#if defined (ARRAY_VARS)
3185942a 3936 else if (array_p (old_var))
95732b49 3937 array_dispose (array_cell (old_var));
3185942a
JA
3938 else if (assoc_p (old_var))
3939 assoc_dispose (assoc_cell (old_var));
95732b49 3940#endif
ac50fbac
CR
3941 else if (nameref_p (old_var))
3942 FREE (nameref_cell (old_var));
3185942a 3943 else
95732b49 3944 FREE (value_cell (old_var));
b80f6443 3945 /* Reset the attributes. Preserve the export attribute if the variable
3185942a
JA
3946 came from a temporary environment. Make sure it stays local, and
3947 make it invisible. */
b80f6443
JA
3948 old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
3949 VSETATTR (old_var, att_local);
bb70624e 3950 VSETATTR (old_var, att_invisible);
7117c2d2 3951 var_setvalue (old_var, (char *)NULL);
bb70624e 3952 INVALIDATE_EXPORTSTR (old_var);
7117c2d2
JA
3953
3954 new_elt = hash_insert (savestring (old_var->name), v->table, 0);
3955 new_elt->data = (PTR_T)old_var;
ccc6cda3 3956 stupidly_hack_special_variables (old_var->name);
7117c2d2 3957
d166f048
JA
3958 free (elt->key);
3959 free (elt);
ccc6cda3
JA
3960 return (0);
3961 }
3962
726f6388
JA
3963 /* Have to save a copy of name here, because it might refer to
3964 old_var->name. If so, stupidly_hack_special_variables will
3965 reference freed memory. */
3966 t = savestring (name);
3967
3968 free (elt->key);
3969 free (elt);
3970
3971 dispose_variable (old_var);
3972 stupidly_hack_special_variables (t);
3973 free (t);
7117c2d2 3974
726f6388
JA
3975 return (0);
3976}
3977
7117c2d2
JA
3978/* Get rid of all of the variables in the current context. */
3979void
3980kill_all_local_variables ()
726f6388 3981{
7117c2d2
JA
3982 VAR_CONTEXT *vc;
3983
3984 for (vc = shell_variables; vc; vc = vc->down)
3985 if (vc_isfuncenv (vc) && vc->scope == variable_context)
3986 break;
3987 if (vc == 0)
3988 return; /* XXX */
726f6388 3989
7117c2d2 3990 if (vc->table && vc_haslocals (vc))
726f6388 3991 {
7117c2d2
JA
3992 delete_all_variables (vc->table);
3993 hash_dispose (vc->table);
726f6388 3994 }
7117c2d2 3995 vc->table = (HASH_TABLE *)NULL;
726f6388
JA
3996}
3997
ccc6cda3
JA
3998static void
3999free_variable_hash_data (data)
f73dda09 4000 PTR_T data;
ccc6cda3 4001{
7117c2d2 4002 SHELL_VAR *var;
ccc6cda3
JA
4003
4004 var = (SHELL_VAR *)data;
7117c2d2 4005 dispose_variable (var);
ccc6cda3
JA
4006}
4007
726f6388
JA
4008/* Delete the entire contents of the hash table. */
4009void
4010delete_all_variables (hashed_vars)
4011 HASH_TABLE *hashed_vars;
4012{
7117c2d2 4013 hash_flush (hashed_vars, free_variable_hash_data);
726f6388
JA
4014}
4015
7117c2d2
JA
4016/* **************************************************************** */
4017/* */
4018/* Setting variable attributes */
4019/* */
4020/* **************************************************************** */
726f6388 4021
ccc6cda3
JA
4022#define FIND_OR_MAKE_VARIABLE(name, entry) \
4023 do \
4024 { \
4025 entry = find_variable (name); \
4026 if (!entry) \
4027 { \
95732b49 4028 entry = bind_variable (name, "", 0); \
495aee44 4029 if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \
ccc6cda3
JA
4030 } \
4031 } \
4032 while (0)
4033
4034/* Make the variable associated with NAME be readonly.
726f6388
JA
4035 If NAME does not exist yet, create it. */
4036void
4037set_var_read_only (name)
4038 char *name;
4039{
ccc6cda3 4040 SHELL_VAR *entry;
726f6388 4041
ccc6cda3 4042 FIND_OR_MAKE_VARIABLE (name, entry);
bb70624e 4043 VSETATTR (entry, att_readonly);
726f6388
JA
4044}
4045
cce855bc 4046#ifdef INCLUDE_UNUSED
ccc6cda3 4047/* Make the function associated with NAME be readonly.
726f6388
JA
4048 If NAME does not exist, we just punt, like auto_export code below. */
4049void
4050set_func_read_only (name)
f73dda09 4051 const char *name;
726f6388 4052{
d166f048 4053 SHELL_VAR *entry;
726f6388 4054
d166f048 4055 entry = find_function (name);
726f6388 4056 if (entry)
bb70624e 4057 VSETATTR (entry, att_readonly);
726f6388
JA
4058}
4059
4060/* Make the variable associated with NAME be auto-exported.
4061 If NAME does not exist yet, create it. */
4062void
4063set_var_auto_export (name)
4064 char *name;
4065{
ccc6cda3 4066 SHELL_VAR *entry;
726f6388 4067
ccc6cda3 4068 FIND_OR_MAKE_VARIABLE (name, entry);
726f6388
JA
4069 set_auto_export (entry);
4070}
4071
4072/* Make the function associated with NAME be auto-exported. */
4073void
4074set_func_auto_export (name)
f73dda09 4075 const char *name;
726f6388 4076{
ccc6cda3 4077 SHELL_VAR *entry;
726f6388 4078
ccc6cda3 4079 entry = find_function (name);
726f6388 4080 if (entry)
ccc6cda3
JA
4081 set_auto_export (entry);
4082}
cce855bc 4083#endif
ccc6cda3 4084
7117c2d2
JA
4085/* **************************************************************** */
4086/* */
4087/* Creating lists of variables */
4088/* */
4089/* **************************************************************** */
4090
4091static VARLIST *
4092vlist_alloc (nentries)
4093 int nentries;
726f6388 4094{
7117c2d2 4095 VARLIST *vlist;
726f6388 4096
7117c2d2
JA
4097 vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
4098 vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
4099 vlist->list_size = nentries;
4100 vlist->list_len = 0;
4101 vlist->list[0] = (SHELL_VAR *)NULL;
726f6388 4102
7117c2d2
JA
4103 return vlist;
4104}
726f6388 4105
7117c2d2
JA
4106static VARLIST *
4107vlist_realloc (vlist, n)
4108 VARLIST *vlist;
4109 int n;
4110{
4111 if (vlist == 0)
4112 return (vlist = vlist_alloc (n));
4113 if (n > vlist->list_size)
726f6388 4114 {
7117c2d2
JA
4115 vlist->list_size = n;
4116 vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
4117 }
4118 return vlist;
4119}
726f6388 4120
7117c2d2
JA
4121static void
4122vlist_add (vlist, var, flags)
4123 VARLIST *vlist;
4124 SHELL_VAR *var;
4125 int flags;
4126{
4127 register int i;
ccc6cda3 4128
7117c2d2
JA
4129 for (i = 0; i < vlist->list_len; i++)
4130 if (STREQ (var->name, vlist->list[i]->name))
4131 break;
4132 if (i < vlist->list_len)
4133 return;
4134
4135 if (i >= vlist->list_size)
4136 vlist = vlist_realloc (vlist, vlist->list_size + 16);
726f6388 4137
7117c2d2
JA
4138 vlist->list[vlist->list_len++] = var;
4139 vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
4140}
4141
4142/* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
4143 variables for which FUNCTION returns a non-zero value. A NULL value
4144 for FUNCTION means to use all variables. */
4145SHELL_VAR **
4146map_over (function, vc)
4147 sh_var_map_func_t *function;
4148 VAR_CONTEXT *vc;
4149{
4150 VAR_CONTEXT *v;
4151 VARLIST *vlist;
4152 SHELL_VAR **ret;
4153 int nentries;
4154
4155 for (nentries = 0, v = vc; v; v = v->down)
4156 nentries += HASH_ENTRIES (v->table);
4157
4158 if (nentries == 0)
4159 return (SHELL_VAR **)NULL;
4160
4161 vlist = vlist_alloc (nentries);
4162
4163 for (v = vc; v; v = v->down)
4164 flatten (v->table, function, vlist, 0);
4165
4166 ret = vlist->list;
4167 free (vlist);
4168 return ret;
4169}
4170
4171SHELL_VAR **
4172map_over_funcs (function)
4173 sh_var_map_func_t *function;
4174{
4175 VARLIST *vlist;
4176 SHELL_VAR **ret;
4177
4178 if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
4179 return ((SHELL_VAR **)NULL);
4180
4181 vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
4182
4183 flatten (shell_functions, function, vlist, 0);
4184
4185 ret = vlist->list;
4186 free (vlist);
4187 return ret;
4188}
4189
4190/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
4191 elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
4192 for future use. Only unique names are added to VLIST. If FUNC is
4193 NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
4194 NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
4195 and FUNC are both NULL, nothing happens. */
4196static void
4197flatten (var_hash_table, func, vlist, flags)
4198 HASH_TABLE *var_hash_table;
4199 sh_var_map_func_t *func;
4200 VARLIST *vlist;
4201 int flags;
4202{
4203 register int i;
4204 register BUCKET_CONTENTS *tlist;
4205 int r;
4206 SHELL_VAR *var;
4207
4208 if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
4209 return;
4210
4211 for (i = 0; i < var_hash_table->nbuckets; i++)
4212 {
4213 for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
4214 {
4215 var = (SHELL_VAR *)tlist->data;
4216
4217 r = func ? (*func) (var) : 1;
4218 if (r && vlist)
4219 vlist_add (vlist, var, flags);
4220 }
726f6388 4221 }
7117c2d2
JA
4222}
4223
4224void
4225sort_variables (array)
4226 SHELL_VAR **array;
4227{
4228 qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
726f6388
JA
4229}
4230
4231static int
7117c2d2
JA
4232qsort_var_comp (var1, var2)
4233 SHELL_VAR **var1, **var2;
726f6388 4234{
7117c2d2
JA
4235 int result;
4236
4237 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
4238 result = strcmp ((*var1)->name, (*var2)->name);
4239
4240 return (result);
726f6388
JA
4241}
4242
7117c2d2
JA
4243/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
4244 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
ccc6cda3 4245static SHELL_VAR **
7117c2d2
JA
4246vapply (func)
4247 sh_var_map_func_t *func;
726f6388
JA
4248{
4249 SHELL_VAR **list;
4250
7117c2d2 4251 list = map_over (func, shell_variables);
d166f048 4252 if (list /* && posixly_correct */)
726f6388 4253 sort_variables (list);
7117c2d2
JA
4254 return (list);
4255}
726f6388 4256
7117c2d2
JA
4257/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
4258 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
4259static SHELL_VAR **
4260fapply (func)
4261 sh_var_map_func_t *func;
4262{
4263 SHELL_VAR **list;
4264
4265 list = map_over_funcs (func);
4266 if (list /* && posixly_correct */)
4267 sort_variables (list);
726f6388
JA
4268 return (list);
4269}
4270
7117c2d2
JA
4271/* Create a NULL terminated array of all the shell variables. */
4272SHELL_VAR **
4273all_shell_variables ()
4274{
4275 return (vapply ((sh_var_map_func_t *)NULL));
4276}
4277
4278/* Create a NULL terminated array of all the shell functions. */
4279SHELL_VAR **
4280all_shell_functions ()
4281{
4282 return (fapply ((sh_var_map_func_t *)NULL));
4283}
4284
4285static int
4286visible_var (var)
4287 SHELL_VAR *var;
4288{
4289 return (invisible_p (var) == 0);
4290}
4291
726f6388 4292SHELL_VAR **
bb70624e 4293all_visible_functions ()
726f6388 4294{
7117c2d2 4295 return (fapply (visible_var));
ccc6cda3 4296}
726f6388 4297
ccc6cda3 4298SHELL_VAR **
bb70624e 4299all_visible_variables ()
ccc6cda3 4300{
7117c2d2 4301 return (vapply (visible_var));
726f6388
JA
4302}
4303
ccc6cda3
JA
4304/* Return non-zero if the variable VAR is visible and exported. Array
4305 variables cannot be exported. */
726f6388
JA
4306static int
4307visible_and_exported (var)
4308 SHELL_VAR *var;
4309{
ccc6cda3 4310 return (invisible_p (var) == 0 && exported_p (var));
726f6388
JA
4311}
4312
89a92869
CR
4313/* Candidate variables for the export environment are either valid variables
4314 with the export attribute or invalid variables inherited from the initial
4315 environment and simply passed through. */
4316static int
4317export_environment_candidate (var)
4318 SHELL_VAR *var;
4319{
4320 return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
4321}
4322
7117c2d2
JA
4323/* Return non-zero if VAR is a local variable in the current context and
4324 is exported. */
4325static int
4326local_and_exported (var)
4327 SHELL_VAR *var;
4328{
4329 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
4330}
4331
bb70624e
JA
4332SHELL_VAR **
4333all_exported_variables ()
4334{
7117c2d2
JA
4335 return (vapply (visible_and_exported));
4336}
bb70624e 4337
7117c2d2
JA
4338SHELL_VAR **
4339local_exported_variables ()
4340{
4341 return (vapply (local_and_exported));
4342}
4343
4344static int
4345variable_in_context (var)
4346 SHELL_VAR *var;
4347{
4348 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
4349}
4350
4351SHELL_VAR **
4352all_local_variables ()
4353{
4354 VARLIST *vlist;
4355 SHELL_VAR **ret;
4356 VAR_CONTEXT *vc;
4357
4358 vc = shell_variables;
4359 for (vc = shell_variables; vc; vc = vc->down)
4360 if (vc_isfuncenv (vc) && vc->scope == variable_context)
4361 break;
4362
4363 if (vc == 0)
4364 {
b80f6443 4365 internal_error (_("all_local_variables: no function context at current scope"));
7117c2d2
JA
4366 return (SHELL_VAR **)NULL;
4367 }
4368 if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
4369 return (SHELL_VAR **)NULL;
4370
4371 vlist = vlist_alloc (HASH_ENTRIES (vc->table));
4372
4373 flatten (vc->table, variable_in_context, vlist, 0);
4374
4375 ret = vlist->list;
4376 free (vlist);
4377 if (ret)
4378 sort_variables (ret);
4379 return ret;
bb70624e
JA
4380}
4381
4382#if defined (ARRAY_VARS)
4383/* Return non-zero if the variable VAR is visible and an array. */
4384static int
4385visible_array_vars (var)
4386 SHELL_VAR *var;
4387{
d233b485 4388 return (invisible_p (var) == 0 && (array_p (var) || assoc_p (var)));
bb70624e
JA
4389}
4390
4391SHELL_VAR **
4392all_array_variables ()
4393{
7117c2d2 4394 return (vapply (visible_array_vars));
bb70624e
JA
4395}
4396#endif /* ARRAY_VARS */
4397
4398char **
4399all_variables_matching_prefix (prefix)
f73dda09 4400 const char *prefix;
bb70624e
JA
4401{
4402 SHELL_VAR **varlist;
4403 char **rlist;
4404 int vind, rind, plen;
4405
4406 plen = STRLEN (prefix);
4407 varlist = all_visible_variables ();
4408 for (vind = 0; varlist && varlist[vind]; vind++)
4409 ;
4410 if (varlist == 0 || vind == 0)
4411 return ((char **)NULL);
7117c2d2 4412 rlist = strvec_create (vind + 1);
bb70624e
JA
4413 for (vind = rind = 0; varlist[vind]; vind++)
4414 {
4415 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
28ef6c31 4416 rlist[rind++] = savestring (varlist[vind]->name);
bb70624e
JA
4417 }
4418 rlist[rind] = (char *)0;
4419 free (varlist);
4420
4421 return rlist;
4422}
4423
7117c2d2
JA
4424/* **************************************************************** */
4425/* */
4426/* Managing temporary variable scopes */
4427/* */
4428/* **************************************************************** */
4429
4430/* Make variable NAME have VALUE in the temporary environment. */
4431static SHELL_VAR *
4432bind_tempenv_variable (name, value)
4433 const char *name;
4434 char *value;
4435{
4436 SHELL_VAR *var;
4437
4438 var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
4439
4440 if (var)
4441 {
4442 FREE (value_cell (var));
4443 var_setvalue (var, savestring (value));
4444 INVALIDATE_EXPORTSTR (var);
4445 }
4446
4447 return (var);
4448}
4449
4450/* Find a variable in the temporary environment that is named NAME.
4451 Return the SHELL_VAR *, or NULL if not found. */
4452SHELL_VAR *
4453find_tempenv_variable (name)
4454 const char *name;
4455{
4456 return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
4457}
4458
495aee44
CR
4459char **tempvar_list;
4460int tvlist_ind;
4461
d233b485
CR
4462/* Take a variable from an assignment statement preceding a posix special
4463 builtin (including `return') and create a global variable from it. This
4464 is called from merge_temporary_env, which is only called when in posix
4465 mode. */
4466static void
4467push_posix_temp_var (data)
4468 PTR_T data;
4469{
4470 SHELL_VAR *var, *v;
4471 HASH_TABLE *binding_table;
4472
4473 var = (SHELL_VAR *)data;
4474
4475 binding_table = global_variables->table;
4476 if (binding_table == 0)
4477 binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
4478
4479 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
4480
4481 /* global variables are no longer temporary and don't need propagating. */
4482 var->attributes &= ~(att_tempvar|att_propagate);
4483 if (v)
4484 v->attributes |= var->attributes;
4485
4486 if (find_special_var (var->name) >= 0)
4487 tempvar_list[tvlist_ind++] = savestring (var->name);
4488
4489 dispose_variable (var);
4490}
4491
7117c2d2 4492/* Push the variable described by (SHELL_VAR *)DATA down to the next
d233b485
CR
4493 variable context from the temporary environment. This can be called
4494 from one context:
4495 1. propagate_temp_var: which is called to propagate variables in
4496 assignments like `var=value declare -x var' to the surrounding
4497 scope.
4498
4499 In this case, the variable should have the att_propagate flag set and
4500 we can create variables in the current scope.
4501*/
7117c2d2
JA
4502static void
4503push_temp_var (data)
4504 PTR_T data;
4505{
4506 SHELL_VAR *var, *v;
4507 HASH_TABLE *binding_table;
4508
4509 var = (SHELL_VAR *)data;
4510
4511 binding_table = shell_variables->table;
4512 if (binding_table == 0)
4513 {
4514 if (shell_variables == global_variables)
4515 /* shouldn't happen */
a0c0a00f 4516 binding_table = shell_variables->table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
7117c2d2
JA
4517 else
4518 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
4519 }
4520
d233b485 4521 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
7117c2d2
JA
4522
4523 /* XXX - should we set the context here? It shouldn't matter because of how
d233b485
CR
4524 assign_in_env works, but we do it anyway. */
4525 if (v)
4526 v->context = shell_variables->scope;
4527
7117c2d2
JA
4528 if (binding_table == global_variables->table) /* XXX */
4529 var->attributes &= ~(att_tempvar|att_propagate);
4530 else
4531 {
4532 var->attributes |= att_propagate;
4533 if (binding_table == shell_variables->table)
4534 shell_variables->flags |= VC_HASTMPVAR;
4535 }
a0c0a00f
CR
4536 if (v)
4537 v->attributes |= var->attributes;
7117c2d2 4538
495aee44
CR
4539 if (find_special_var (var->name) >= 0)
4540 tempvar_list[tvlist_ind++] = savestring (var->name);
4541
7117c2d2
JA
4542 dispose_variable (var);
4543}
4544
d233b485
CR
4545/* Take a variable described by DATA and push it to the surrounding scope if
4546 the PROPAGATE attribute is set. That gets set by push_temp_var if we are
4547 taking a variable like `var=value declare -x var' and propagating it to
4548 the enclosing scope. */
7117c2d2
JA
4549static void
4550propagate_temp_var (data)
4551 PTR_T data;
4552{
4553 SHELL_VAR *var;
4554
4555 var = (SHELL_VAR *)data;
4556 if (tempvar_p (var) && (var->attributes & att_propagate))
4557 push_temp_var (data);
4558 else
495aee44
CR
4559 {
4560 if (find_special_var (var->name) >= 0)
4561 tempvar_list[tvlist_ind++] = savestring (var->name);
4562 dispose_variable (var);
4563 }
7117c2d2
JA
4564}
4565
4566/* Free the storage used in the hash table for temporary
4567 environment variables. PUSHF is a function to be called
4568 to free each hash table entry. It takes care of pushing variables
495aee44
CR
4569 to previous scopes if appropriate. PUSHF stores names of variables
4570 that require special handling (e.g., IFS) on tempvar_list, so this
4571 function can call stupidly_hack_special_variables on all the
4572 variables in the list when the temporary hash table is destroyed. */
7117c2d2
JA
4573static void
4574dispose_temporary_env (pushf)
4575 sh_free_func_t *pushf;
4576{
495aee44
CR
4577 int i;
4578
4579 tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
4580 tempvar_list[tvlist_ind = 0] = 0;
4581
7117c2d2
JA
4582 hash_flush (temporary_env, pushf);
4583 hash_dispose (temporary_env);
3185942a 4584 temporary_env = (HASH_TABLE *)NULL;
7117c2d2 4585
495aee44
CR
4586 tempvar_list[tvlist_ind] = 0;
4587
7117c2d2
JA
4588 array_needs_making = 1;
4589
495aee44
CR
4590 for (i = 0; i < tvlist_ind; i++)
4591 stupidly_hack_special_variables (tempvar_list[i]);
4592
4593 strvec_dispose (tempvar_list);
4594 tempvar_list = 0;
4595 tvlist_ind = 0;
7117c2d2
JA
4596}
4597
4598void
4599dispose_used_env_vars ()
4600{
4601 if (temporary_env)
0628567a
JA
4602 {
4603 dispose_temporary_env (propagate_temp_var);
4604 maybe_make_export_env ();
4605 }
7117c2d2
JA
4606}
4607
4608/* Take all of the shell variables in the temporary environment HASH_TABLE
d233b485
CR
4609 and make shell variables from them at the current variable context.
4610 Right now, this is only called in Posix mode to implement the historical
4611 accident of creating global variables from assignment statements preceding
4612 special builtins, but we check in case this acquires another caller later. */
7117c2d2
JA
4613void
4614merge_temporary_env ()
4615{
4616 if (temporary_env)
d233b485 4617 dispose_temporary_env (posixly_correct ? push_posix_temp_var : push_temp_var);
7117c2d2
JA
4618}
4619
a0c0a00f
CR
4620void
4621flush_temporary_env ()
4622{
4623 if (temporary_env)
4624 {
4625 hash_flush (temporary_env, free_variable_hash_data);
4626 hash_dispose (temporary_env);
4627 temporary_env = (HASH_TABLE *)NULL;
4628 }
4629}
4630
7117c2d2
JA
4631/* **************************************************************** */
4632/* */
4633/* Creating and manipulating the environment */
4634/* */
4635/* **************************************************************** */
4636
bb70624e 4637static inline char *
3590145a 4638mk_env_string (name, value, isfunc)
f73dda09 4639 const char *name, *value;
3590145a 4640 int isfunc;
bb70624e 4641{
3590145a 4642 size_t name_len, value_len;
d233b485 4643 char *p, *q, *t;
bb70624e
JA
4644
4645 name_len = strlen (name);
4646 value_len = STRLEN (value);
3590145a
CR
4647
4648 /* If we are exporting a shell function, construct the encoded function
4649 name. */
4650 if (isfunc && value)
4651 {
4652 p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2);
4653 q = p;
4654 memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN);
4655 q += BASHFUNC_PREFLEN;
4656 memcpy (q, name, name_len);
4657 q += name_len;
4658 memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN);
4659 q += BASHFUNC_SUFFLEN;
4660 }
4661 else
4662 {
4663 p = (char *)xmalloc (2 + name_len + value_len);
4664 memcpy (p, name, name_len);
4665 q = p + name_len;
4666 }
4667
4668 q[0] = '=';
bb70624e 4669 if (value && *value)
d233b485
CR
4670 {
4671 if (isfunc)
4672 {
4673 t = dequote_escapes (value);
4674 value_len = STRLEN (t);
4675 memcpy (q + 1, t, value_len + 1);
4676 free (t);
4677 }
4678 else
4679 memcpy (q + 1, value, value_len + 1);
4680 }
bb70624e 4681 else
3590145a
CR
4682 q[1] = '\0';
4683
bb70624e
JA
4684 return (p);
4685}
4686
f73dda09 4687#ifdef DEBUG
bb70624e
JA
4688/* Debugging */
4689static int
4690valid_exportstr (v)
4691 SHELL_VAR *v;
4692{
4693 char *s;
4694
4695 s = v->exportstr;
0001803f
CR
4696 if (s == 0)
4697 {
4698 internal_error (_("%s has null exportstr"), v->name);
4699 return (0);
4700 }
f73dda09 4701 if (legal_variable_starter ((unsigned char)*s) == 0)
bb70624e 4702 {
b80f6443 4703 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
4704 return (0);
4705 }
4706 for (s = v->exportstr + 1; s && *s; s++)
4707 {
4708 if (*s == '=')
28ef6c31 4709 break;
f73dda09 4710 if (legal_variable_char ((unsigned char)*s) == 0)
bb70624e 4711 {
b80f6443 4712 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
4713 return (0);
4714 }
4715 }
4716 if (*s != '=')
4717 {
b80f6443 4718 internal_error (_("no `=' in exportstr for %s"), v->name);
bb70624e
JA
4719 return (0);
4720 }
4721 return (1);
4722}
f73dda09 4723#endif
bb70624e 4724
7117c2d2
JA
4725static char **
4726make_env_array_from_var_list (vars)
4727 SHELL_VAR **vars;
726f6388
JA
4728{
4729 register int i, list_index;
4730 register SHELL_VAR *var;
ccc6cda3 4731 char **list, *value;
726f6388 4732
7117c2d2 4733 list = strvec_create ((1 + strvec_len ((char **)vars)));
bb70624e
JA
4734
4735#define USE_EXPORTSTR (value == var->exportstr)
726f6388
JA
4736
4737 for (i = 0, list_index = 0; var = vars[i]; i++)
4738 {
28ef6c31
JA
4739#if defined (__CYGWIN__)
4740 /* We don't use the exportstr stuff on Cygwin at all. */
4741 INVALIDATE_EXPORTSTR (var);
bb70624e 4742#endif
d233b485
CR
4743
4744 /* If the value is generated dynamically, generate it here. */
4745 if (regen_p (var) && var->dynamic_value)
4746 {
4747 var = (*(var->dynamic_value)) (var);
4748 INVALIDATE_EXPORTSTR (var);
4749 }
4750
28ef6c31
JA
4751 if (var->exportstr)
4752 value = var->exportstr;
bb70624e 4753 else if (function_p (var))
ccc6cda3
JA
4754 value = named_function_string ((char *)NULL, function_cell (var), 0);
4755#if defined (ARRAY_VARS)
4756 else if (array_p (var))
ac50fbac 4757# if ARRAY_EXPORT
a0c0a00f 4758 value = array_to_assign (array_cell (var), 0);
ccc6cda3
JA
4759# else
4760 continue; /* XXX array vars cannot yet be exported */
ac50fbac 4761# endif /* ARRAY_EXPORT */
3185942a
JA
4762 else if (assoc_p (var))
4763# if 0
a0c0a00f 4764 value = assoc_to_assign (assoc_cell (var), 0);
3185942a
JA
4765# else
4766 continue; /* XXX associative array vars cannot yet be exported */
ccc6cda3
JA
4767# endif
4768#endif
726f6388
JA
4769 else
4770 value = value_cell (var);
4771
4772 if (value)
4773 {
bb70624e
JA
4774 /* Gee, I'd like to get away with not using savestring() if we're
4775 using the cached exportstr... */
4776 list[list_index] = USE_EXPORTSTR ? savestring (value)
3590145a 4777 : mk_env_string (var->name, value, function_p (var));
bb70624e 4778
7117c2d2
JA
4779 if (USE_EXPORTSTR == 0)
4780 SAVE_EXPORTSTR (var, list[list_index]);
4781
726f6388 4782 list_index++;
bb70624e
JA
4783#undef USE_EXPORTSTR
4784
4785#if 0 /* not yet */
ccc6cda3 4786#if defined (ARRAY_VARS)
3185942a 4787 if (array_p (var) || assoc_p (var))
ccc6cda3 4788 free (value);
bb70624e 4789#endif
ccc6cda3 4790#endif
726f6388
JA
4791 }
4792 }
4793
726f6388
JA
4794 list[list_index] = (char *)NULL;
4795 return (list);
4796}
4797
7117c2d2
JA
4798/* Make an array of assignment statements from the hash table
4799 HASHED_VARS which contains SHELL_VARs. Only visible, exported
4800 variables are eligible. */
4801static char **
4802make_var_export_array (vcxt)
4803 VAR_CONTEXT *vcxt;
726f6388 4804{
7117c2d2
JA
4805 char **list;
4806 SHELL_VAR **vars;
726f6388 4807
89a92869 4808#if 0
7117c2d2 4809 vars = map_over (visible_and_exported, vcxt);
89a92869
CR
4810#else
4811 vars = map_over (export_environment_candidate, vcxt);
4812#endif
726f6388 4813
7117c2d2
JA
4814 if (vars == 0)
4815 return (char **)NULL;
ccc6cda3 4816
7117c2d2 4817 list = make_env_array_from_var_list (vars);
ccc6cda3 4818
7117c2d2
JA
4819 free (vars);
4820 return (list);
ccc6cda3
JA
4821}
4822
7117c2d2
JA
4823static char **
4824make_func_export_array ()
726f6388 4825{
7117c2d2
JA
4826 char **list;
4827 SHELL_VAR **vars;
ccc6cda3 4828
7117c2d2
JA
4829 vars = map_over_funcs (visible_and_exported);
4830 if (vars == 0)
4831 return (char **)NULL;
726f6388 4832
7117c2d2 4833 list = make_env_array_from_var_list (vars);
28ef6c31 4834
7117c2d2
JA
4835 free (vars);
4836 return (list);
bb70624e
JA
4837}
4838
d166f048
JA
4839/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
4840#define add_to_export_env(envstr,do_alloc) \
4841do \
4842 { \
4843 if (export_env_index >= (export_env_size - 1)) \
4844 { \
4845 export_env_size += 16; \
7117c2d2 4846 export_env = strvec_resize (export_env, export_env_size); \
95732b49 4847 environ = export_env; \
d166f048
JA
4848 } \
4849 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
4850 export_env[export_env_index] = (char *)NULL; \
4851 } while (0)
4852
d166f048
JA
4853/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
4854 array with the same left-hand side. Return the new EXPORT_ENV. */
726f6388 4855char **
d166f048 4856add_or_supercede_exported_var (assign, do_alloc)
726f6388 4857 char *assign;
d166f048 4858 int do_alloc;
726f6388
JA
4859{
4860 register int i;
d166f048 4861 int equal_offset;
726f6388 4862
b80f6443 4863 equal_offset = assignment (assign, 0);
d166f048
JA
4864 if (equal_offset == 0)
4865 return (export_env);
726f6388 4866
7117c2d2
JA
4867 /* If this is a function, then only supersede the function definition.
4868 We do this by including the `=() {' in the comparison, like
4869 initialize_shell_variables does. */
4870 if (assign[equal_offset + 1] == '(' &&
4871 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
4872 equal_offset += 4;
726f6388 4873
d166f048 4874 for (i = 0; i < export_env_index; i++)
726f6388 4875 {
d166f048 4876 if (STREQN (assign, export_env[i], equal_offset + 1))
726f6388 4877 {
d166f048
JA
4878 free (export_env[i]);
4879 export_env[i] = do_alloc ? savestring (assign) : assign;
4880 return (export_env);
726f6388
JA
4881 }
4882 }
d166f048
JA
4883 add_to_export_env (assign, do_alloc);
4884 return (export_env);
726f6388
JA
4885}
4886
7117c2d2
JA
4887static void
4888add_temp_array_to_env (temp_array, do_alloc, do_supercede)
4889 char **temp_array;
4890 int do_alloc, do_supercede;
4891{
4892 register int i;
4893
4894 if (temp_array == 0)
4895 return;
4896
4897 for (i = 0; temp_array[i]; i++)
4898 {
4899 if (do_supercede)
4900 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
4901 else
4902 add_to_export_env (temp_array[i], do_alloc);
4903 }
4904
4905 free (temp_array);
4906}
4907
d166f048 4908/* Make the environment array for the command about to be executed, if the
726f6388
JA
4909 array needs making. Otherwise, do nothing. If a shell action could
4910 change the array that commands receive for their environment, then the
7117c2d2
JA
4911 code should `array_needs_making++'.
4912
4913 The order to add to the array is:
4914 temporary_env
4915 list of var contexts whose head is shell_variables
4916 shell_functions
4917
4918 This is the shell variable lookup order. We add only new variable
4919 names at each step, which allows local variables and variables in
4920 the temporary environments to shadow variables in the global (or
4921 any previous) scope.
4922*/
4923
4924static int
4925n_shell_variables ()
4926{
4927 VAR_CONTEXT *vc;
4928 int n;
4929
4930 for (n = 0, vc = shell_variables; vc; vc = vc->down)
4931 n += HASH_ENTRIES (vc->table);
4932 return n;
4933}
4934
2bbe8058
CR
4935int
4936chkexport (name)
4937 char *name;
4938{
4939 SHELL_VAR *v;
4940
4941 v = find_variable (name);
eafc91a3 4942 if (v && exported_p (v))
2bbe8058
CR
4943 {
4944 array_needs_making = 1;
4945 maybe_make_export_env ();
4946 return 1;
4947 }
4948 return 0;
4949}
4950
726f6388
JA
4951void
4952maybe_make_export_env ()
4953{
726f6388 4954 register char **temp_array;
d166f048 4955 int new_size;
d233b485 4956 VAR_CONTEXT *tcxt, *icxt;
726f6388
JA
4957
4958 if (array_needs_making)
4959 {
4960 if (export_env)
3185942a 4961 strvec_flush (export_env);
d166f048
JA
4962
4963 /* Make a guess based on how many shell variables and functions we
4964 have. Since there will always be array variables, and array
4965 variables are not (yet) exported, this will always be big enough
7117c2d2
JA
4966 for the exported variables and functions. */
4967 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
d233b485 4968 HASH_ENTRIES (temporary_env) + HASH_ENTRIES (invalid_env);
d166f048
JA
4969 if (new_size > export_env_size)
4970 {
4971 export_env_size = new_size;
7117c2d2 4972 export_env = strvec_resize (export_env, export_env_size);
95732b49 4973 environ = export_env;
d166f048
JA
4974 }
4975 export_env[export_env_index = 0] = (char *)NULL;
726f6388 4976
0001803f 4977 /* Make a dummy variable context from the temporary_env, stick it on
3185942a
JA
4978 the front of shell_variables, call make_var_export_array on the
4979 whole thing to flatten it, and convert the list of SHELL_VAR *s
4980 to the form needed by the environment. */
7117c2d2 4981 if (temporary_env)
3185942a
JA
4982 {
4983 tcxt = new_var_context ((char *)NULL, 0);
4984 tcxt->table = temporary_env;
4985 tcxt->down = shell_variables;
4986 }
7117c2d2 4987 else
3185942a 4988 tcxt = shell_variables;
d233b485
CR
4989
4990 if (invalid_env)
4991 {
4992 icxt = new_var_context ((char *)NULL, 0);
4993 icxt->table = invalid_env;
4994 icxt->down = tcxt;
4995 }
4996 else
4997 icxt = tcxt;
7117c2d2 4998
d233b485 4999 temp_array = make_var_export_array (icxt);
d166f048 5000 if (temp_array)
7117c2d2
JA
5001 add_temp_array_to_env (temp_array, 0, 0);
5002
d233b485
CR
5003 if (icxt != tcxt)
5004 free (icxt);
5005
7117c2d2 5006 if (tcxt != shell_variables)
3185942a 5007 free (tcxt);
726f6388 5008
f73dda09
JA
5009#if defined (RESTRICTED_SHELL)
5010 /* Restricted shells may not export shell functions. */
7117c2d2 5011 temp_array = restricted ? (char **)0 : make_func_export_array ();
f73dda09 5012#else
7117c2d2 5013 temp_array = make_func_export_array ();
f73dda09 5014#endif
d166f048 5015 if (temp_array)
7117c2d2 5016 add_temp_array_to_env (temp_array, 0, 0);
726f6388
JA
5017
5018 array_needs_making = 0;
5019 }
5020}
5021
b72432fd
JA
5022/* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
5023 we will need to remake the exported environment every time we
5024 change directories. `_' is always put into the environment for
5025 every external command, so without special treatment it will always
5026 cause the environment to be remade.
5027
5028 If there is no other reason to make the exported environment, we can
5029 just update the variables in place and mark the exported environment
5030 as no longer needing a remake. */
5031void
5032update_export_env_inplace (env_prefix, preflen, value)
5033 char *env_prefix;
5034 int preflen;
5035 char *value;
5036{
5037 char *evar;
5038
f73dda09 5039 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
b72432fd
JA
5040 strcpy (evar, env_prefix);
5041 if (value)
5042 strcpy (evar + preflen, value);
5043 export_env = add_or_supercede_exported_var (evar, 0);
5044}
5045
726f6388
JA
5046/* We always put _ in the environment as the name of this command. */
5047void
5048put_command_name_into_env (command_name)
5049 char *command_name;
5050{
b72432fd 5051 update_export_env_inplace ("_=", 2, command_name);
726f6388
JA
5052}
5053
7117c2d2
JA
5054/* **************************************************************** */
5055/* */
5056/* Managing variable contexts */
5057/* */
5058/* **************************************************************** */
5059
5060/* Allocate and return a new variable context with NAME and FLAGS.
5061 NAME can be NULL. */
726f6388 5062
7117c2d2
JA
5063VAR_CONTEXT *
5064new_var_context (name, flags)
5065 char *name;
5066 int flags;
5067{
5068 VAR_CONTEXT *vc;
5069
5070 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
5071 vc->name = name ? savestring (name) : (char *)NULL;
5072 vc->scope = variable_context;
5073 vc->flags = flags;
5074
5075 vc->up = vc->down = (VAR_CONTEXT *)NULL;
5076 vc->table = (HASH_TABLE *)NULL;
5077
5078 return vc;
5079}
5080
5081/* Free a variable context and its data, including the hash table. Dispose
5082 all of the variables. */
5083void
5084dispose_var_context (vc)
5085 VAR_CONTEXT *vc;
5086{
5087 FREE (vc->name);
5088
5089 if (vc->table)
5090 {
5091 delete_all_variables (vc->table);
5092 hash_dispose (vc->table);
5093 }
5094
5095 free (vc);
5096}
5097
5098/* Set VAR's scope level to the current variable context. */
5099static int
5100set_context (var)
5101 SHELL_VAR *var;
5102{
5103 return (var->context = variable_context);
5104}
5105
5106/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
5107 temporary variables, and push it onto shell_variables. This is
5108 for shell functions. */
5109VAR_CONTEXT *
5110push_var_context (name, flags, tempvars)
5111 char *name;
5112 int flags;
5113 HASH_TABLE *tempvars;
5114{
5115 VAR_CONTEXT *vc;
d233b485
CR
5116 int posix_func_behavior;
5117
5118 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5119 functions no longer behave like assignment statements preceding
5120 special builtins, and do not persist in the current shell environment.
5121 This is austin group interp #654, though nobody implements it yet. */
5122#if 0 /* XXX - TAG: bash-5.1 */
5123 posix_func_behavior = 0;
5124#else
5125 posix_func_behavior = posixly_correct;
5126#endif
7117c2d2
JA
5127
5128 vc = new_var_context (name, flags);
d233b485
CR
5129 /* Posix interp 1009, temporary assignments preceding function calls modify
5130 the current environment *before* the command is executed. */
5131 if (posix_func_behavior && (flags & VC_FUNCENV) && tempvars == temporary_env)
5132 merge_temporary_env ();
5133 else if (tempvars)
7117c2d2 5134 {
d233b485 5135 vc->table = tempvars;
7117c2d2
JA
5136 /* Have to do this because the temp environment was created before
5137 variable_context was incremented. */
5138 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
5139 vc->flags |= VC_HASTMPVAR;
5140 }
5141 vc->down = shell_variables;
5142 shell_variables->up = vc;
5143
5144 return (shell_variables = vc);
5145}
5146
d233b485
CR
5147/* This can be called from one of two code paths:
5148 1. pop_scope, which implements the posix rules for propagating variable
5149 assignments preceding special builtins to the surrounding scope
5150 (push_builtin_var);
5151 2. pop_var_context, which is called from pop_context and implements the
5152 posix rules for propagating variable assignments preceding function
5153 calls to the surrounding scope (push_func_var).
7117c2d2 5154
d233b485
CR
5155 It takes variables out of a temporary environment hash table. We take the
5156 variable in data.
5157*/
5158
5159static inline void
5160push_posix_tempvar_internal (var, isbltin)
5161 SHELL_VAR *var;
5162 int isbltin;
5163{
5164 SHELL_VAR *v;
5165 int posix_var_behavior;
5166
5167 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5168 functions no longer behave like assignment statements preceding
5169 special builtins, and do not persist in the current shell environment.
5170 This is austin group interp #654, though nobody implements it yet. */
5171#if 0 /* XXX - TAG: bash-5.1 */
5172 posix_var_behavior = posixly_correct && isbltin;
5173#else
5174 posix_var_behavior = posixly_correct;
5175#endif
7117c2d2 5176
a0c0a00f
CR
5177 if (local_p (var) && STREQ (var->name, "-"))
5178 set_current_options (value_cell (var));
d233b485 5179 else if (tempvar_p (var) && (posix_var_behavior || (var->attributes & att_propagate)))
7117c2d2 5180 {
30d188c2
CR
5181 /* Make sure we have a hash table to store the variable in while it is
5182 being propagated down to the global variables table. Create one if
5183 we have to */
5184 if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
a0c0a00f 5185 shell_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
95732b49 5186 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
d233b485
CR
5187 /* XXX - should we set v->context here? */
5188 if (v)
5189 v->context = shell_variables->scope;
a0c0a00f 5190#if defined (ARRAY_VARS)
d233b485 5191 if (v && (array_p (var) || assoc_p (var)))
a0c0a00f
CR
5192 {
5193 FREE (value_cell (v));
5194 if (array_p (var))
5195 var_setarray (v, array_copy (array_cell (var)));
5196 else
5197 var_setassoc (v, assoc_copy (assoc_cell (var)));
5198 }
5199#endif
7117c2d2
JA
5200 if (shell_variables == global_variables)
5201 var->attributes &= ~(att_tempvar|att_propagate);
5202 else
f1be666c 5203 shell_variables->flags |= VC_HASTMPVAR;
a0c0a00f
CR
5204 if (v)
5205 v->attributes |= var->attributes;
7117c2d2 5206 }
f1be666c
JA
5207 else
5208 stupidly_hack_special_variables (var->name); /* XXX */
7117c2d2
JA
5209
5210 dispose_variable (var);
5211}
5212
d233b485
CR
5213static void
5214push_func_var (data)
5215 PTR_T data;
5216{
5217 SHELL_VAR *var;
5218
5219 var = (SHELL_VAR *)data;
5220 push_posix_tempvar_internal (var, 0);
5221}
5222
5223static void
5224push_builtin_var (data)
5225 PTR_T data;
5226{
5227 SHELL_VAR *var;
5228
5229 var = (SHELL_VAR *)data;
5230 push_posix_tempvar_internal (var, 1);
5231}
5232
7117c2d2
JA
5233/* Pop the top context off of VCXT and dispose of it, returning the rest of
5234 the stack. */
5235void
5236pop_var_context ()
5237{
5238 VAR_CONTEXT *ret, *vcxt;
5239
5240 vcxt = shell_variables;
5241 if (vc_isfuncenv (vcxt) == 0)
5242 {
b80f6443 5243 internal_error (_("pop_var_context: head of shell_variables not a function context"));
7117c2d2
JA
5244 return;
5245 }
5246
5247 if (ret = vcxt->down)
5248 {
5249 ret->up = (VAR_CONTEXT *)NULL;
5250 shell_variables = ret;
5251 if (vcxt->table)
5252 hash_flush (vcxt->table, push_func_var);
5253 dispose_var_context (vcxt);
5254 }
5255 else
b80f6443 5256 internal_error (_("pop_var_context: no global_variables context"));
7117c2d2
JA
5257}
5258
5259/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
5260 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
5261void
5262delete_all_contexts (vcxt)
5263 VAR_CONTEXT *vcxt;
5264{
5265 VAR_CONTEXT *v, *t;
5266
5267 for (v = vcxt; v != global_variables; v = t)
5268 {
5269 t = v->down;
5270 dispose_var_context (v);
3185942a 5271 }
7117c2d2
JA
5272
5273 delete_all_variables (global_variables->table);
5274 shell_variables = global_variables;
5275}
5276
5277/* **************************************************************** */
5278/* */
5279/* Pushing and Popping temporary variable scopes */
5280/* */
5281/* **************************************************************** */
5282
5283VAR_CONTEXT *
5284push_scope (flags, tmpvars)
5285 int flags;
5286 HASH_TABLE *tmpvars;
5287{
5288 return (push_var_context ((char *)NULL, flags, tmpvars));
5289}
5290
5291static void
5292push_exported_var (data)
5293 PTR_T data;
5294{
5295 SHELL_VAR *var, *v;
5296
5297 var = (SHELL_VAR *)data;
5298
5299 /* If a temp var had its export attribute set, or it's marked to be
5300 propagated, bind it in the previous scope before disposing it. */
95732b49
JA
5301 /* XXX - This isn't exactly right, because all tempenv variables have the
5302 export attribute set. */
95732b49 5303 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
7117c2d2
JA
5304 {
5305 var->attributes &= ~att_tempvar; /* XXX */
95732b49 5306 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
7117c2d2
JA
5307 if (shell_variables == global_variables)
5308 var->attributes &= ~att_propagate;
a0c0a00f 5309 if (v)
d233b485
CR
5310 {
5311 v->attributes |= var->attributes;
5312 v->context = shell_variables->scope;
5313 }
7117c2d2 5314 }
f1be666c
JA
5315 else
5316 stupidly_hack_special_variables (var->name); /* XXX */
7117c2d2
JA
5317
5318 dispose_variable (var);
5319}
5320
d233b485
CR
5321/* This is called to propagate variables in the temporary environment of a
5322 special builtin (if IS_SPECIAL != 0) or exported variables that are the
5323 result of a builtin like `source' or `command' that can operate on the
5324 variables in its temporary environment. In the first case, we call
5325 push_builtin_var, which does the right thing. */
7117c2d2
JA
5326void
5327pop_scope (is_special)
5328 int is_special;
5329{
5330 VAR_CONTEXT *vcxt, *ret;
d233b485 5331 int is_bltinenv;
7117c2d2
JA
5332
5333 vcxt = shell_variables;
5334 if (vc_istempscope (vcxt) == 0)
5335 {
b80f6443 5336 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
7117c2d2
JA
5337 return;
5338 }
d233b485 5339 is_bltinenv = vc_isbltnenv (vcxt); /* XXX - for later */
7117c2d2
JA
5340
5341 ret = vcxt->down;
5342 if (ret)
5343 ret->up = (VAR_CONTEXT *)NULL;
5344
5345 shell_variables = ret;
5346
5347 /* Now we can take care of merging variables in VCXT into set of scopes
5348 whose head is RET (shell_variables). */
5349 FREE (vcxt->name);
5350 if (vcxt->table)
5351 {
5352 if (is_special)
d233b485 5353 hash_flush (vcxt->table, push_builtin_var);
7117c2d2
JA
5354 else
5355 hash_flush (vcxt->table, push_exported_var);
5356 hash_dispose (vcxt->table);
5357 }
5358 free (vcxt);
5359
5360 sv_ifs ("IFS"); /* XXX here for now */
5361}
5362
5363/* **************************************************************** */
5364/* */
5365/* Pushing and Popping function contexts */
5366/* */
5367/* **************************************************************** */
5368
d233b485
CR
5369struct saved_dollar_vars {
5370 char **first_ten;
5371 WORD_LIST *rest;
5372};
5373
5374static struct saved_dollar_vars *dollar_arg_stack = (struct saved_dollar_vars *)NULL;
7117c2d2
JA
5375static int dollar_arg_stack_slots;
5376static int dollar_arg_stack_index;
5377
d233b485
CR
5378/* Functions to manipulate dollar_vars array. Need to keep these in sync with
5379 whatever remember_args() does. */
5380static char **
5381save_dollar_vars ()
5382{
5383 char **ret;
5384 int i;
5385
5386 ret = strvec_create (10);
5387 for (i = 1; i < 10; i++)
5388 {
5389 ret[i] = dollar_vars[i];
5390 dollar_vars[i] = (char *)NULL;
5391 }
5392 return ret;
5393}
5394
5395static void
5396restore_dollar_vars (args)
5397 char **args;
5398{
5399 int i;
5400
5401 for (i = 1; i < 10; i++)
5402 dollar_vars[i] = args[i];
5403}
5404
5405static void
5406free_dollar_vars ()
5407{
5408 int i;
5409
5410 for (i = 1; i < 10; i++)
5411 {
5412 FREE (dollar_vars[i]);
5413 dollar_vars[i] = (char *)NULL;
5414 }
5415}
5416
5417static void
5418free_saved_dollar_vars (args)
5419 char **args;
5420{
5421 int i;
5422
5423 for (i = 1; i < 10; i++)
5424 FREE (args[i]);
5425}
5426
a0c0a00f 5427/* XXX - should always be followed by remember_args () */
7117c2d2
JA
5428void
5429push_context (name, is_subshell, tempvars)
5430 char *name; /* function name */
5431 int is_subshell;
5432 HASH_TABLE *tempvars;
5433{
5434 if (is_subshell == 0)
5435 push_dollar_vars ();
5436 variable_context++;
5437 push_var_context (name, VC_FUNCENV, tempvars);
5438}
5439
5440/* Only called when subshell == 0, so we don't need to check, and can
5441 unconditionally pop the dollar vars off the stack. */
5442void
5443pop_context ()
726f6388 5444{
7117c2d2
JA
5445 pop_dollar_vars ();
5446 variable_context--;
5447 pop_var_context ();
726f6388 5448
7117c2d2
JA
5449 sv_ifs ("IFS"); /* XXX here for now */
5450}
726f6388 5451
7117c2d2
JA
5452/* Save the existing positional parameters on a stack. */
5453void
5454push_dollar_vars ()
5455{
5456 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
5457 {
d233b485 5458 dollar_arg_stack = (struct saved_dollar_vars *)
7117c2d2 5459 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
d233b485 5460 * sizeof (struct saved_dollar_vars));
7117c2d2 5461 }
d233b485
CR
5462
5463 dollar_arg_stack[dollar_arg_stack_index].first_ten = save_dollar_vars ();
5464 dollar_arg_stack[dollar_arg_stack_index++].rest = rest_of_args;
5465 rest_of_args = (WORD_LIST *)NULL;
5466
5467 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5468 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
7117c2d2 5469}
726f6388 5470
7117c2d2
JA
5471/* Restore the positional parameters from our stack. */
5472void
5473pop_dollar_vars ()
5474{
d233b485 5475 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
7117c2d2 5476 return;
726f6388 5477
d233b485
CR
5478 /* Do what remember_args (xxx, 1) would have done. */
5479 free_dollar_vars ();
5480 dispose_words (rest_of_args);
5481
5482 rest_of_args = dollar_arg_stack[--dollar_arg_stack_index].rest;
5483 restore_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5484 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5485
5486 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5487 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5488
7117c2d2 5489 set_dollar_vars_unchanged ();
d233b485 5490 invalidate_cached_quoted_dollar_at ();
7117c2d2 5491}
ccc6cda3 5492
7117c2d2
JA
5493void
5494dispose_saved_dollar_vars ()
5495{
d233b485 5496 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
7117c2d2 5497 return;
726f6388 5498
d233b485
CR
5499 dispose_words (dollar_arg_stack[--dollar_arg_stack_index].rest);
5500 free_saved_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5501 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5502
5503 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5504 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5505}
5506
5507/* Initialize BASH_ARGV and BASH_ARGC after turning on extdebug after the
5508 shell is initialized */
5509void
5510init_bash_argv ()
5511{
5512 if (bash_argv_initialized == 0)
5513 {
5514 save_bash_argv ();
5515 bash_argv_initialized = 1;
5516 }
5517}
5518
5519void
5520save_bash_argv ()
5521{
5522 WORD_LIST *list;
5523
5524 list = list_rest_of_args ();
5525 push_args (list);
5526 dispose_words (list);
726f6388 5527}
cce855bc 5528
b80f6443
JA
5529/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
5530
5531void
5532push_args (list)
5533 WORD_LIST *list;
5534{
5535#if defined (ARRAY_VARS) && defined (DEBUGGER)
5536 SHELL_VAR *bash_argv_v, *bash_argc_v;
5537 ARRAY *bash_argv_a, *bash_argc_a;
5538 WORD_LIST *l;
5539 arrayind_t i;
5540 char *t;
5541
5542 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5543 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5544
5545 for (l = list, i = 0; l; l = l->next, i++)
5546 array_push (bash_argv_a, l->word->word);
5547
5548 t = itos (i);
5549 array_push (bash_argc_a, t);
5550 free (t);
5551#endif /* ARRAY_VARS && DEBUGGER */
5552}
5553
5554/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
5555 array and use that value as the count of elements to remove from
5556 BASH_ARGV. */
5557void
5558pop_args ()
5559{
5560#if defined (ARRAY_VARS) && defined (DEBUGGER)
5561 SHELL_VAR *bash_argv_v, *bash_argc_v;
5562 ARRAY *bash_argv_a, *bash_argc_a;
5563 ARRAY_ELEMENT *ce;
5564 intmax_t i;
5565
5566 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5567 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5568
5569 ce = array_shift (bash_argc_a, 1, 0);
5570 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
5571 i = 0;
5572
5573 for ( ; i > 0; i--)
5574 array_pop (bash_argv_a);
5575 array_dispose_element (ce);
5576#endif /* ARRAY_VARS && DEBUGGER */
5577}
5578
cce855bc
JA
5579/*************************************************
5580 * *
5581 * Functions to manage special variables *
5582 * *
5583 *************************************************/
5584
5585/* Extern declarations for variables this code has to manage. */
cce855bc
JA
5586
5587/* An alist of name.function for each special variable. Most of the
5588 functions don't do much, and in fact, this would be faster with a
5589 switch statement, but by the end of this file, I am sick of switch
5590 statements. */
5591
5592#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
5593
7117c2d2 5594/* This table will be sorted with qsort() the first time it's accessed. */
cce855bc
JA
5595struct name_and_function {
5596 char *name;
f73dda09 5597 sh_sv_func_t *function;
7117c2d2 5598};
cce855bc 5599
7117c2d2 5600static struct name_and_function special_vars[] = {
ac50fbac 5601 { "BASH_COMPAT", sv_shcompat },
0001803f
CR
5602 { "BASH_XTRACEFD", sv_xtracefd },
5603
ac50fbac
CR
5604#if defined (JOB_CONTROL)
5605 { "CHILD_MAX", sv_childmax },
5606#endif
5607
95732b49
JA
5608#if defined (READLINE)
5609# if defined (STRICT_POSIX)
5610 { "COLUMNS", sv_winsize },
5611# endif
5612 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
5613#endif
5614
a0c0a00f
CR
5615 { "EXECIGNORE", sv_execignore },
5616
495aee44
CR
5617 { "FUNCNEST", sv_funcnest },
5618
cce855bc
JA
5619 { "GLOBIGNORE", sv_globignore },
5620
cce855bc 5621#if defined (HISTORY)
7117c2d2
JA
5622 { "HISTCONTROL", sv_history_control },
5623 { "HISTFILESIZE", sv_histsize },
cce855bc
JA
5624 { "HISTIGNORE", sv_histignore },
5625 { "HISTSIZE", sv_histsize },
b80f6443 5626 { "HISTTIMEFORMAT", sv_histtimefmt },
7117c2d2 5627#endif
cce855bc 5628
95732b49
JA
5629#if defined (__CYGWIN__)
5630 { "HOME", sv_home },
5631#endif
5632
7117c2d2
JA
5633#if defined (READLINE)
5634 { "HOSTFILE", sv_hostfile },
5635#endif
cce855bc 5636
7117c2d2
JA
5637 { "IFS", sv_ifs },
5638 { "IGNOREEOF", sv_ignoreeof },
cce855bc 5639
7117c2d2 5640 { "LANG", sv_locale },
cce855bc
JA
5641 { "LC_ALL", sv_locale },
5642 { "LC_COLLATE", sv_locale },
5643 { "LC_CTYPE", sv_locale },
5644 { "LC_MESSAGES", sv_locale },
bb70624e 5645 { "LC_NUMERIC", sv_locale },
95732b49
JA
5646 { "LC_TIME", sv_locale },
5647
5648#if defined (READLINE) && defined (STRICT_POSIX)
5649 { "LINES", sv_winsize },
5650#endif
7117c2d2
JA
5651
5652 { "MAIL", sv_mail },
5653 { "MAILCHECK", sv_mail },
5654 { "MAILPATH", sv_mail },
5655
5656 { "OPTERR", sv_opterr },
5657 { "OPTIND", sv_optind },
5658
5659 { "PATH", sv_path },
5660 { "POSIXLY_CORRECT", sv_strict_posix },
5661
5662#if defined (READLINE)
5663 { "TERM", sv_terminal },
5664 { "TERMCAP", sv_terminal },
5665 { "TERMINFO", sv_terminal },
5666#endif /* READLINE */
5667
5668 { "TEXTDOMAIN", sv_locale },
5669 { "TEXTDOMAINDIR", sv_locale },
cce855bc 5670
2bbe8058 5671#if defined (HAVE_TZSET)
cce855bc
JA
5672 { "TZ", sv_tz },
5673#endif
5674
7117c2d2
JA
5675#if defined (HISTORY) && defined (BANG_HISTORY)
5676 { "histchars", sv_histchars },
5677#endif /* HISTORY && BANG_HISTORY */
5678
5679 { "ignoreeof", sv_ignoreeof },
5680
f73dda09 5681 { (char *)0, (sh_sv_func_t *)0 }
cce855bc
JA
5682};
5683
7117c2d2
JA
5684#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
5685
5686static int
5687sv_compare (sv1, sv2)
5688 struct name_and_function *sv1, *sv2;
5689{
5690 int r;
5691
5692 if ((r = sv1->name[0] - sv2->name[0]) == 0)
5693 r = strcmp (sv1->name, sv2->name);
5694 return r;
5695}
5696
5697static inline int
5698find_special_var (name)
5699 const char *name;
5700{
5701 register int i, r;
5702
5703 for (i = 0; special_vars[i].name; i++)
5704 {
5705 r = special_vars[i].name[0] - name[0];
5706 if (r == 0)
5707 r = strcmp (special_vars[i].name, name);
5708 if (r == 0)
5709 return i;
5710 else if (r > 0)
5711 /* Can't match any of rest of elements in sorted list. Take this out
5712 if it causes problems in certain environments. */
3185942a 5713 break;
7117c2d2
JA
5714 }
5715 return -1;
5716}
5717
cce855bc
JA
5718/* The variable in NAME has just had its state changed. Check to see if it
5719 is one of the special ones where something special happens. */
5720void
5721stupidly_hack_special_variables (name)
5722 char *name;
5723{
7117c2d2 5724 static int sv_sorted = 0;
cce855bc
JA
5725 int i;
5726
7117c2d2 5727 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
cce855bc 5728 {
7117c2d2
JA
5729 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
5730 (QSFUNC *)sv_compare);
5731 sv_sorted = 1;
cce855bc 5732 }
7117c2d2
JA
5733
5734 i = find_special_var (name);
5735 if (i != -1)
5736 (*(special_vars[i].function)) (name);
5737}
5738
3185942a
JA
5739/* Special variables that need hooks to be run when they are unset as part
5740 of shell reinitialization should have their sv_ functions run here. */
5741void
5742reinit_special_variables ()
5743{
5744#if defined (READLINE)
5745 sv_comp_wordbreaks ("COMP_WORDBREAKS");
5746#endif
5747 sv_globignore ("GLOBIGNORE");
5748 sv_opterr ("OPTERR");
5749}
5750
7117c2d2
JA
5751void
5752sv_ifs (name)
5753 char *name;
5754{
5755 SHELL_VAR *v;
5756
5757 v = find_variable ("IFS");
5758 setifs (v);
cce855bc
JA
5759}
5760
5761/* What to do just after the PATH variable has changed. */
5762void
5763sv_path (name)
5764 char *name;
5765{
5766 /* hash -r */
7117c2d2 5767 phash_flush ();
cce855bc
JA
5768}
5769
5770/* What to do just after one of the MAILxxxx variables has changed. NAME
5771 is the name of the variable. This is called with NAME set to one of
5772 MAIL, MAILCHECK, or MAILPATH. */
5773void
5774sv_mail (name)
5775 char *name;
5776{
5777 /* If the time interval for checking the files has changed, then
5778 reset the mail timer. Otherwise, one of the pathname vars
5779 to the users mailbox has changed, so rebuild the array of
5780 filenames. */
5781 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
5782 reset_mail_timer ();
5783 else
5784 {
5785 free_mail_files ();
5786 remember_mail_dates ();
5787 }
5788}
5789
495aee44
CR
5790void
5791sv_funcnest (name)
5792 char *name;
5793{
5794 SHELL_VAR *v;
5795 intmax_t num;
5796
5797 v = find_variable (name);
5798 if (v == 0)
5799 funcnest_max = 0;
5800 else if (legal_number (value_cell (v), &num) == 0)
5801 funcnest_max = 0;
5802 else
5803 funcnest_max = num;
5804}
5805
a0c0a00f
CR
5806/* What to do when EXECIGNORE changes. */
5807void
5808sv_execignore (name)
5809 char *name;
5810{
5811 setup_exec_ignore (name);
5812}
5813
cce855bc
JA
5814/* What to do when GLOBIGNORE changes. */
5815void
5816sv_globignore (name)
5817 char *name;
5818{
3185942a
JA
5819 if (privileged_mode == 0)
5820 setup_glob_ignore (name);
cce855bc
JA
5821}
5822
5823#if defined (READLINE)
95732b49
JA
5824void
5825sv_comp_wordbreaks (name)
5826 char *name;
5827{
5828 SHELL_VAR *sv;
5829
5830 sv = find_variable (name);
5831 if (sv == 0)
3185942a 5832 reset_completer_word_break_chars ();
95732b49
JA
5833}
5834
cce855bc
JA
5835/* What to do just after one of the TERMxxx variables has changed.
5836 If we are an interactive shell, then try to reset the terminal
5837 information in readline. */
5838void
5839sv_terminal (name)
5840 char *name;
5841{
5842 if (interactive_shell && no_line_editing == 0)
5843 rl_reset_terminal (get_string_value ("TERM"));
5844}
5845
5846void
5847sv_hostfile (name)
5848 char *name;
5849{
bb70624e
JA
5850 SHELL_VAR *v;
5851
5852 v = find_variable (name);
5853 if (v == 0)
5854 clear_hostname_list ();
5855 else
5856 hostname_list_initialized = 0;
cce855bc 5857}
95732b49
JA
5858
5859#if defined (STRICT_POSIX)
5860/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
5861 found in the initial environment) to override the terminal size reported by
5862 the kernel. */
5863void
5864sv_winsize (name)
5865 char *name;
5866{
5867 SHELL_VAR *v;
5868 intmax_t xd;
5869 int d;
5870
5871 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
5872 return;
5873
5874 v = find_variable (name);
a0c0a00f 5875 if (v == 0 || var_isset (v) == 0)
95732b49
JA
5876 rl_reset_screen_size ();
5877 else
5878 {
5879 if (legal_number (value_cell (v), &xd) == 0)
5880 return;
495aee44 5881 winsize_assignment = 1;
95732b49
JA
5882 d = xd; /* truncate */
5883 if (name[0] == 'L') /* LINES */
5884 rl_set_screen_size (d, -1);
5885 else /* COLUMNS */
5886 rl_set_screen_size (-1, d);
5887 winsize_assignment = 0;
5888 }
5889}
5890#endif /* STRICT_POSIX */
cce855bc
JA
5891#endif /* READLINE */
5892
95732b49
JA
5893/* Update the value of HOME in the export environment so tilde expansion will
5894 work on cygwin. */
5895#if defined (__CYGWIN__)
5896sv_home (name)
5897 char *name;
5898{
5899 array_needs_making = 1;
5900 maybe_make_export_env ();
5901}
5902#endif
5903
cce855bc
JA
5904#if defined (HISTORY)
5905/* What to do after the HISTSIZE or HISTFILESIZE variables change.
5906 If there is a value for this HISTSIZE (and it is numeric), then stifle
5907 the history. Otherwise, if there is NO value for this variable,
5908 unstifle the history. If name is HISTFILESIZE, and its value is
5909 numeric, truncate the history file to hold no more than that many
5910 lines. */
5911void
5912sv_histsize (name)
5913 char *name;
5914{
5915 char *temp;
7117c2d2 5916 intmax_t num;
95732b49 5917 int hmax;
cce855bc
JA
5918
5919 temp = get_string_value (name);
5920
5921 if (temp && *temp)
5922 {
5923 if (legal_number (temp, &num))
28ef6c31 5924 {
0628567a 5925 hmax = num;
ac50fbac
CR
5926 if (hmax < 0 && name[4] == 'S')
5927 unstifle_history (); /* unstifle history if HISTSIZE < 0 */
5928 else if (name[4] == 'S')
cce855bc 5929 {
95732b49 5930 stifle_history (hmax);
0628567a
JA
5931 hmax = where_history ();
5932 if (history_lines_this_session > hmax)
5933 history_lines_this_session = hmax;
cce855bc 5934 }
ac50fbac 5935 else if (hmax >= 0) /* truncate HISTFILE if HISTFILESIZE >= 0 */
cce855bc 5936 {
0628567a 5937 history_truncate_file (get_string_value ("HISTFILE"), hmax);
a0c0a00f
CR
5938 /* If we just shrank the history file to fewer lines than we've
5939 already read, make sure we adjust our idea of how many lines
5940 we have read from the file. */
5941 if (hmax < history_lines_in_file)
0628567a 5942 history_lines_in_file = hmax;
cce855bc
JA
5943 }
5944 }
5945 }
5946 else if (name[4] == 'S')
5947 unstifle_history ();
5948}
5949
5950/* What to do after the HISTIGNORE variable changes. */
5951void
5952sv_histignore (name)
5953 char *name;
5954{
5955 setup_history_ignore (name);
5956}
5957
5958/* What to do after the HISTCONTROL variable changes. */
5959void
5960sv_history_control (name)
5961 char *name;
5962{
5963 char *temp;
b80f6443
JA
5964 char *val;
5965 int tptr;
cce855bc
JA
5966
5967 history_control = 0;
5968 temp = get_string_value (name);
5969
b80f6443
JA
5970 if (temp == 0 || *temp == 0)
5971 return;
5972
5973 tptr = 0;
5974 while (val = extract_colon_unit (temp, &tptr))
cce855bc 5975 {
b80f6443
JA
5976 if (STREQ (val, "ignorespace"))
5977 history_control |= HC_IGNSPACE;
5978 else if (STREQ (val, "ignoredups"))
5979 history_control |= HC_IGNDUPS;
5980 else if (STREQ (val, "ignoreboth"))
5981 history_control |= HC_IGNBOTH;
5982 else if (STREQ (val, "erasedups"))
5983 history_control |= HC_ERASEDUPS;
5984
5985 free (val);
cce855bc
JA
5986 }
5987}
5988
5989#if defined (BANG_HISTORY)
5990/* Setting/unsetting of the history expansion character. */
5991void
5992sv_histchars (name)
5993 char *name;
5994{
5995 char *temp;
5996
5997 temp = get_string_value (name);
5998 if (temp)
5999 {
6000 history_expansion_char = *temp;
6001 if (temp[0] && temp[1])
6002 {
6003 history_subst_char = temp[1];
6004 if (temp[2])
6005 history_comment_char = temp[2];
6006 }
6007 }
6008 else
6009 {
6010 history_expansion_char = '!';
6011 history_subst_char = '^';
6012 history_comment_char = '#';
6013 }
6014}
6015#endif /* BANG_HISTORY */
b80f6443
JA
6016
6017void
6018sv_histtimefmt (name)
6019 char *name;
6020{
6021 SHELL_VAR *v;
6022
ac50fbac
CR
6023 if (v = find_variable (name))
6024 {
6025 if (history_comment_char == 0)
6026 history_comment_char = '#';
6027 }
b80f6443
JA
6028 history_write_timestamps = (v != 0);
6029}
cce855bc
JA
6030#endif /* HISTORY */
6031
2bbe8058 6032#if defined (HAVE_TZSET)
cce855bc
JA
6033void
6034sv_tz (name)
6035 char *name;
6036{
2bbe8058
CR
6037 if (chkexport (name))
6038 tzset ();
cce855bc
JA
6039}
6040#endif
6041
6042/* If the variable exists, then the value of it can be the number
6043 of times we actually ignore the EOF. The default is small,
6044 (smaller than csh, anyway). */
6045void
6046sv_ignoreeof (name)
6047 char *name;
6048{
6049 SHELL_VAR *tmp_var;
6050 char *temp;
6051
6052 eof_encountered = 0;
6053
6054 tmp_var = find_variable (name);
a0c0a00f 6055 ignoreeof = tmp_var && var_isset (tmp_var);
cce855bc
JA
6056 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
6057 if (temp)
6058 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
6059 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
6060}
6061
6062void
6063sv_optind (name)
6064 char *name;
6065{
a0c0a00f 6066 SHELL_VAR *var;
cce855bc
JA
6067 char *tt;
6068 int s;
6069
a0c0a00f
CR
6070 var = find_variable ("OPTIND");
6071 tt = var ? get_variable_value (var) : (char *)NULL;
6072
6073 /* Assume that if var->context < variable_context and variable_context > 0
6074 then we are restoring the variables's previous state while returning
6075 from a function. */
cce855bc
JA
6076 if (tt && *tt)
6077 {
6078 s = atoi (tt);
6079
6080 /* According to POSIX, setting OPTIND=1 resets the internal state
6081 of getopt (). */
6082 if (s < 0 || s == 1)
6083 s = 0;
6084 }
6085 else
6086 s = 0;
6087 getopts_reset (s);
6088}
6089
6090void
6091sv_opterr (name)
6092 char *name;
6093{
6094 char *tt;
6095
6096 tt = get_string_value ("OPTERR");
6097 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
6098}
6099
6100void
6101sv_strict_posix (name)
6102 char *name;
6103{
a0c0a00f
CR
6104 SHELL_VAR *var;
6105
6106 var = find_variable (name);
6107 posixly_correct = var && var_isset (var);
cce855bc
JA
6108 posix_initialize (posixly_correct);
6109#if defined (READLINE)
6110 if (interactive_shell)
6111 posix_readline_initialize (posixly_correct);
6112#endif /* READLINE */
6113 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
6114}
6115
6116void
6117sv_locale (name)
6118 char *name;
6119{
6120 char *v;
ac50fbac 6121 int r;
cce855bc
JA
6122
6123 v = get_string_value (name);
6124 if (name[0] == 'L' && name[1] == 'A') /* LANG */
ac50fbac 6125 r = set_lang (name, v);
cce855bc 6126 else
ac50fbac
CR
6127 r = set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
6128
6129#if 1
6130 if (r == 0 && posixly_correct)
6131 last_command_exit_value = 1;
6132#endif
cce855bc
JA
6133}
6134
6135#if defined (ARRAY_VARS)
6136void
7117c2d2 6137set_pipestatus_array (ps, nproc)
cce855bc 6138 int *ps;
7117c2d2 6139 int nproc;
cce855bc
JA
6140{
6141 SHELL_VAR *v;
6142 ARRAY *a;
7117c2d2 6143 ARRAY_ELEMENT *ae;
cce855bc 6144 register int i;
f73dda09 6145 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
cce855bc
JA
6146
6147 v = find_variable ("PIPESTATUS");
6148 if (v == 0)
6149 v = make_new_array_variable ("PIPESTATUS");
6150 if (array_p (v) == 0)
6151 return; /* Do nothing if not an array variable. */
6152 a = array_cell (v);
7117c2d2
JA
6153
6154 if (a == 0 || array_num_elements (a) == 0)
cce855bc 6155 {
7117c2d2
JA
6156 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
6157 {
6158 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6159 array_insert (a, i, t);
6160 }
6161 return;
6162 }
6163
6164 /* Fast case */
6165 if (array_num_elements (a) == nproc && nproc == 1)
6166 {
6167 ae = element_forw (a->head);
6168 free (element_value (ae));
d233b485 6169 set_element_value (ae, itos (ps[0]));
7117c2d2
JA
6170 }
6171 else if (array_num_elements (a) <= nproc)
6172 {
6173 /* modify in array_num_elements members in place, then add */
6174 ae = a->head;
6175 for (i = 0; i < array_num_elements (a); i++)
6176 {
6177 ae = element_forw (ae);
6178 free (element_value (ae));
d233b485 6179 set_element_value (ae, itos (ps[i]));
7117c2d2
JA
6180 }
6181 /* add any more */
6182 for ( ; i < nproc; i++)
6183 {
6184 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6185 array_insert (a, i, t);
6186 }
6187 }
6188 else
6189 {
6190 /* deleting elements. it's faster to rebuild the array. */
6191 array_flush (a);
6192 for (i = 0; ps[i] != -1; i++)
6193 {
6194 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6195 array_insert (a, i, t);
6196 }
cce855bc
JA
6197 }
6198}
495aee44
CR
6199
6200ARRAY *
6201save_pipestatus_array ()
6202{
6203 SHELL_VAR *v;
d233b485 6204 ARRAY *a;
495aee44
CR
6205
6206 v = find_variable ("PIPESTATUS");
6207 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6208 return ((ARRAY *)NULL);
6209
d233b485 6210 a = array_copy (array_cell (v));
495aee44 6211
d233b485 6212 return a;
495aee44
CR
6213}
6214
6215void
6216restore_pipestatus_array (a)
6217 ARRAY *a;
6218{
6219 SHELL_VAR *v;
6220 ARRAY *a2;
6221
6222 v = find_variable ("PIPESTATUS");
6223 /* XXX - should we still assign even if existing value is NULL? */
6224 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6225 return;
6226
6227 a2 = array_cell (v);
6228 var_setarray (v, a);
6229
6230 array_dispose (a2);
6231}
cce855bc
JA
6232#endif
6233
6234void
6235set_pipestatus_from_exit (s)
6236 int s;
6237{
6238#if defined (ARRAY_VARS)
6239 static int v[2] = { 0, -1 };
6240
6241 v[0] = s;
7117c2d2 6242 set_pipestatus_array (v, 1);
cce855bc
JA
6243#endif
6244}
0001803f
CR
6245
6246void
6247sv_xtracefd (name)
6248 char *name;
6249{
6250 SHELL_VAR *v;
6251 char *t, *e;
6252 int fd;
6253 FILE *fp;
6254
6255 v = find_variable (name);
6256 if (v == 0)
6257 {
6258 xtrace_reset ();
6259 return;
6260 }
6261
6262 t = value_cell (v);
6263 if (t == 0 || *t == 0)
6264 xtrace_reset ();
6265 else
6266 {
6267 fd = (int)strtol (t, &e, 10);
6268 if (e != t && *e == '\0' && sh_validfd (fd))
6269 {
6270 fp = fdopen (fd, "w");
6271 if (fp == 0)
6272 internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
6273 else
6274 xtrace_set (fd, fp);
6275 }
6276 else
6277 internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
6278 }
6279}
ac50fbac
CR
6280
6281#define MIN_COMPAT_LEVEL 31
6282
6283void
6284sv_shcompat (name)
6285 char *name;
6286{
6287 SHELL_VAR *v;
6288 char *val;
6289 int tens, ones, compatval;
6290
6291 v = find_variable (name);
6292 if (v == 0)
6293 {
6294 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6295 set_compatibility_opts ();
6296 return;
6297 }
6298 val = value_cell (v);
6299 if (val == 0 || *val == '\0')
6300 {
6301 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6302 set_compatibility_opts ();
6303 return;
6304 }
6305 /* Handle decimal-like compatibility version specifications: 4.2 */
a0c0a00f 6306 if (ISDIGIT (val[0]) && val[1] == '.' && ISDIGIT (val[2]) && val[3] == 0)
ac50fbac
CR
6307 {
6308 tens = val[0] - '0';
6309 ones = val[2] - '0';
6310 compatval = tens*10 + ones;
6311 }
6312 /* Handle integer-like compatibility version specifications: 42 */
a0c0a00f 6313 else if (ISDIGIT (val[0]) && ISDIGIT (val[1]) && val[2] == 0)
ac50fbac
CR
6314 {
6315 tens = val[0] - '0';
6316 ones = val[1] - '0';
6317 compatval = tens*10 + ones;
6318 }
6319 else
6320 {
6321compat_error:
6322 internal_error (_("%s: %s: compatibility value out of range"), name, val);
6323 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6324 set_compatibility_opts ();
6325 return;
6326 }
6327
6328 if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL)
6329 goto compat_error;
6330
6331 shell_compatibility_level = compatval;
6332 set_compatibility_opts ();
6333}
6334
6335#if defined (JOB_CONTROL)
6336void
6337sv_childmax (name)
6338 char *name;
6339{
6340 char *tt;
6341 int s;
6342
6343 tt = get_string_value (name);
6344 s = (tt && *tt) ? atoi (tt) : 0;
6345 set_maxchild (s);
6346}
6347#endif