]> git.ipfire.org Git - thirdparty/bash.git/blame - variables.c
Bash-5.0 patch 11: fix quoted null character removal in operands of conditional ...
[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 4462/* Take a variable from an assignment statement preceding a posix special
6a3116f5
CR
4463 builtin (including `return') and create a variable from it as if a
4464 standalone assignment statement had been performed. This is called from
4465 merge_temporary_env, which is only called when in posix mode. */
d233b485
CR
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
6a3116f5
CR
4475 /* Just like do_assignment_internal(). This makes assignments preceding
4476 special builtins act like standalone assignment statements when in
4477 posix mode, satisfying the posix requirement that this affect the
4478 "current execution environment." */
4479 v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP);
d233b485 4480
6a3116f5
CR
4481 /* If this modifies an existing local variable, v->context will be non-zero.
4482 If it comes back with v->context == 0, we bound at the global context.
4483 Set binding_table appropriately. It doesn't matter whether it's correct
4484 if the variable is local, only that it's not global_variables->table */
4485 binding_table = v->context ? shell_variables->table : global_variables->table;
d233b485
CR
4486
4487 /* global variables are no longer temporary and don't need propagating. */
6a3116f5
CR
4488 if (binding_table == global_variables->table)
4489 var->attributes &= ~(att_tempvar|att_propagate);
4490
d233b485 4491 if (v)
6a3116f5
CR
4492 {
4493 v->attributes |= var->attributes;
4494 v->attributes &= ~att_tempvar; /* not a temp var now */
4495 }
d233b485
CR
4496
4497 if (find_special_var (var->name) >= 0)
4498 tempvar_list[tvlist_ind++] = savestring (var->name);
4499
4500 dispose_variable (var);
4501}
4502
7117c2d2 4503/* Push the variable described by (SHELL_VAR *)DATA down to the next
d233b485
CR
4504 variable context from the temporary environment. This can be called
4505 from one context:
4506 1. propagate_temp_var: which is called to propagate variables in
4507 assignments like `var=value declare -x var' to the surrounding
4508 scope.
4509
4510 In this case, the variable should have the att_propagate flag set and
4511 we can create variables in the current scope.
4512*/
7117c2d2
JA
4513static void
4514push_temp_var (data)
4515 PTR_T data;
4516{
4517 SHELL_VAR *var, *v;
4518 HASH_TABLE *binding_table;
4519
4520 var = (SHELL_VAR *)data;
4521
4522 binding_table = shell_variables->table;
4523 if (binding_table == 0)
4524 {
4525 if (shell_variables == global_variables)
4526 /* shouldn't happen */
a0c0a00f 4527 binding_table = shell_variables->table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
7117c2d2
JA
4528 else
4529 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
4530 }
4531
d233b485 4532 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
7117c2d2
JA
4533
4534 /* XXX - should we set the context here? It shouldn't matter because of how
d233b485
CR
4535 assign_in_env works, but we do it anyway. */
4536 if (v)
4537 v->context = shell_variables->scope;
4538
7117c2d2
JA
4539 if (binding_table == global_variables->table) /* XXX */
4540 var->attributes &= ~(att_tempvar|att_propagate);
4541 else
4542 {
4543 var->attributes |= att_propagate;
4544 if (binding_table == shell_variables->table)
4545 shell_variables->flags |= VC_HASTMPVAR;
4546 }
a0c0a00f
CR
4547 if (v)
4548 v->attributes |= var->attributes;
7117c2d2 4549
495aee44
CR
4550 if (find_special_var (var->name) >= 0)
4551 tempvar_list[tvlist_ind++] = savestring (var->name);
4552
7117c2d2
JA
4553 dispose_variable (var);
4554}
4555
d233b485
CR
4556/* Take a variable described by DATA and push it to the surrounding scope if
4557 the PROPAGATE attribute is set. That gets set by push_temp_var if we are
4558 taking a variable like `var=value declare -x var' and propagating it to
4559 the enclosing scope. */
7117c2d2
JA
4560static void
4561propagate_temp_var (data)
4562 PTR_T data;
4563{
4564 SHELL_VAR *var;
4565
4566 var = (SHELL_VAR *)data;
4567 if (tempvar_p (var) && (var->attributes & att_propagate))
4568 push_temp_var (data);
4569 else
495aee44
CR
4570 {
4571 if (find_special_var (var->name) >= 0)
4572 tempvar_list[tvlist_ind++] = savestring (var->name);
4573 dispose_variable (var);
4574 }
7117c2d2
JA
4575}
4576
4577/* Free the storage used in the hash table for temporary
4578 environment variables. PUSHF is a function to be called
4579 to free each hash table entry. It takes care of pushing variables
495aee44
CR
4580 to previous scopes if appropriate. PUSHF stores names of variables
4581 that require special handling (e.g., IFS) on tempvar_list, so this
4582 function can call stupidly_hack_special_variables on all the
4583 variables in the list when the temporary hash table is destroyed. */
7117c2d2
JA
4584static void
4585dispose_temporary_env (pushf)
4586 sh_free_func_t *pushf;
4587{
495aee44 4588 int i;
6a3116f5 4589 HASH_TABLE *disposer;
495aee44
CR
4590
4591 tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
4592 tempvar_list[tvlist_ind = 0] = 0;
6a3116f5
CR
4593
4594 disposer = temporary_env;
3185942a 4595 temporary_env = (HASH_TABLE *)NULL;
7117c2d2 4596
6a3116f5
CR
4597 hash_flush (disposer, pushf);
4598 hash_dispose (disposer);
4599
495aee44
CR
4600 tempvar_list[tvlist_ind] = 0;
4601
7117c2d2
JA
4602 array_needs_making = 1;
4603
495aee44
CR
4604 for (i = 0; i < tvlist_ind; i++)
4605 stupidly_hack_special_variables (tempvar_list[i]);
4606
4607 strvec_dispose (tempvar_list);
4608 tempvar_list = 0;
4609 tvlist_ind = 0;
7117c2d2
JA
4610}
4611
4612void
4613dispose_used_env_vars ()
4614{
4615 if (temporary_env)
0628567a
JA
4616 {
4617 dispose_temporary_env (propagate_temp_var);
4618 maybe_make_export_env ();
4619 }
7117c2d2
JA
4620}
4621
4622/* Take all of the shell variables in the temporary environment HASH_TABLE
d233b485
CR
4623 and make shell variables from them at the current variable context.
4624 Right now, this is only called in Posix mode to implement the historical
4625 accident of creating global variables from assignment statements preceding
4626 special builtins, but we check in case this acquires another caller later. */
7117c2d2
JA
4627void
4628merge_temporary_env ()
4629{
4630 if (temporary_env)
d233b485 4631 dispose_temporary_env (posixly_correct ? push_posix_temp_var : push_temp_var);
7117c2d2
JA
4632}
4633
a0c0a00f
CR
4634void
4635flush_temporary_env ()
4636{
4637 if (temporary_env)
4638 {
4639 hash_flush (temporary_env, free_variable_hash_data);
4640 hash_dispose (temporary_env);
4641 temporary_env = (HASH_TABLE *)NULL;
4642 }
4643}
4644
7117c2d2
JA
4645/* **************************************************************** */
4646/* */
4647/* Creating and manipulating the environment */
4648/* */
4649/* **************************************************************** */
4650
bb70624e 4651static inline char *
3590145a 4652mk_env_string (name, value, isfunc)
f73dda09 4653 const char *name, *value;
3590145a 4654 int isfunc;
bb70624e 4655{
3590145a 4656 size_t name_len, value_len;
d233b485 4657 char *p, *q, *t;
bb70624e
JA
4658
4659 name_len = strlen (name);
4660 value_len = STRLEN (value);
3590145a
CR
4661
4662 /* If we are exporting a shell function, construct the encoded function
4663 name. */
4664 if (isfunc && value)
4665 {
4666 p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2);
4667 q = p;
4668 memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN);
4669 q += BASHFUNC_PREFLEN;
4670 memcpy (q, name, name_len);
4671 q += name_len;
4672 memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN);
4673 q += BASHFUNC_SUFFLEN;
4674 }
4675 else
4676 {
4677 p = (char *)xmalloc (2 + name_len + value_len);
4678 memcpy (p, name, name_len);
4679 q = p + name_len;
4680 }
4681
4682 q[0] = '=';
bb70624e 4683 if (value && *value)
d233b485
CR
4684 {
4685 if (isfunc)
4686 {
4687 t = dequote_escapes (value);
4688 value_len = STRLEN (t);
4689 memcpy (q + 1, t, value_len + 1);
4690 free (t);
4691 }
4692 else
4693 memcpy (q + 1, value, value_len + 1);
4694 }
bb70624e 4695 else
3590145a
CR
4696 q[1] = '\0';
4697
bb70624e
JA
4698 return (p);
4699}
4700
f73dda09 4701#ifdef DEBUG
bb70624e
JA
4702/* Debugging */
4703static int
4704valid_exportstr (v)
4705 SHELL_VAR *v;
4706{
4707 char *s;
4708
4709 s = v->exportstr;
0001803f
CR
4710 if (s == 0)
4711 {
4712 internal_error (_("%s has null exportstr"), v->name);
4713 return (0);
4714 }
f73dda09 4715 if (legal_variable_starter ((unsigned char)*s) == 0)
bb70624e 4716 {
b80f6443 4717 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
4718 return (0);
4719 }
4720 for (s = v->exportstr + 1; s && *s; s++)
4721 {
4722 if (*s == '=')
28ef6c31 4723 break;
f73dda09 4724 if (legal_variable_char ((unsigned char)*s) == 0)
bb70624e 4725 {
b80f6443 4726 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
bb70624e
JA
4727 return (0);
4728 }
4729 }
4730 if (*s != '=')
4731 {
b80f6443 4732 internal_error (_("no `=' in exportstr for %s"), v->name);
bb70624e
JA
4733 return (0);
4734 }
4735 return (1);
4736}
f73dda09 4737#endif
bb70624e 4738
7117c2d2
JA
4739static char **
4740make_env_array_from_var_list (vars)
4741 SHELL_VAR **vars;
726f6388
JA
4742{
4743 register int i, list_index;
4744 register SHELL_VAR *var;
ccc6cda3 4745 char **list, *value;
726f6388 4746
7117c2d2 4747 list = strvec_create ((1 + strvec_len ((char **)vars)));
bb70624e
JA
4748
4749#define USE_EXPORTSTR (value == var->exportstr)
726f6388
JA
4750
4751 for (i = 0, list_index = 0; var = vars[i]; i++)
4752 {
28ef6c31
JA
4753#if defined (__CYGWIN__)
4754 /* We don't use the exportstr stuff on Cygwin at all. */
4755 INVALIDATE_EXPORTSTR (var);
bb70624e 4756#endif
d233b485
CR
4757
4758 /* If the value is generated dynamically, generate it here. */
4759 if (regen_p (var) && var->dynamic_value)
4760 {
4761 var = (*(var->dynamic_value)) (var);
4762 INVALIDATE_EXPORTSTR (var);
4763 }
4764
28ef6c31
JA
4765 if (var->exportstr)
4766 value = var->exportstr;
bb70624e 4767 else if (function_p (var))
ccc6cda3
JA
4768 value = named_function_string ((char *)NULL, function_cell (var), 0);
4769#if defined (ARRAY_VARS)
4770 else if (array_p (var))
ac50fbac 4771# if ARRAY_EXPORT
a0c0a00f 4772 value = array_to_assign (array_cell (var), 0);
ccc6cda3
JA
4773# else
4774 continue; /* XXX array vars cannot yet be exported */
ac50fbac 4775# endif /* ARRAY_EXPORT */
3185942a
JA
4776 else if (assoc_p (var))
4777# if 0
a0c0a00f 4778 value = assoc_to_assign (assoc_cell (var), 0);
3185942a
JA
4779# else
4780 continue; /* XXX associative array vars cannot yet be exported */
ccc6cda3
JA
4781# endif
4782#endif
726f6388
JA
4783 else
4784 value = value_cell (var);
4785
4786 if (value)
4787 {
bb70624e
JA
4788 /* Gee, I'd like to get away with not using savestring() if we're
4789 using the cached exportstr... */
4790 list[list_index] = USE_EXPORTSTR ? savestring (value)
3590145a 4791 : mk_env_string (var->name, value, function_p (var));
bb70624e 4792
7117c2d2
JA
4793 if (USE_EXPORTSTR == 0)
4794 SAVE_EXPORTSTR (var, list[list_index]);
4795
726f6388 4796 list_index++;
bb70624e
JA
4797#undef USE_EXPORTSTR
4798
4799#if 0 /* not yet */
ccc6cda3 4800#if defined (ARRAY_VARS)
3185942a 4801 if (array_p (var) || assoc_p (var))
ccc6cda3 4802 free (value);
bb70624e 4803#endif
ccc6cda3 4804#endif
726f6388
JA
4805 }
4806 }
4807
726f6388
JA
4808 list[list_index] = (char *)NULL;
4809 return (list);
4810}
4811
7117c2d2
JA
4812/* Make an array of assignment statements from the hash table
4813 HASHED_VARS which contains SHELL_VARs. Only visible, exported
4814 variables are eligible. */
4815static char **
4816make_var_export_array (vcxt)
4817 VAR_CONTEXT *vcxt;
726f6388 4818{
7117c2d2
JA
4819 char **list;
4820 SHELL_VAR **vars;
726f6388 4821
89a92869 4822#if 0
7117c2d2 4823 vars = map_over (visible_and_exported, vcxt);
89a92869
CR
4824#else
4825 vars = map_over (export_environment_candidate, vcxt);
4826#endif
726f6388 4827
7117c2d2
JA
4828 if (vars == 0)
4829 return (char **)NULL;
ccc6cda3 4830
7117c2d2 4831 list = make_env_array_from_var_list (vars);
ccc6cda3 4832
7117c2d2
JA
4833 free (vars);
4834 return (list);
ccc6cda3
JA
4835}
4836
7117c2d2
JA
4837static char **
4838make_func_export_array ()
726f6388 4839{
7117c2d2
JA
4840 char **list;
4841 SHELL_VAR **vars;
ccc6cda3 4842
7117c2d2
JA
4843 vars = map_over_funcs (visible_and_exported);
4844 if (vars == 0)
4845 return (char **)NULL;
726f6388 4846
7117c2d2 4847 list = make_env_array_from_var_list (vars);
28ef6c31 4848
7117c2d2
JA
4849 free (vars);
4850 return (list);
bb70624e
JA
4851}
4852
d166f048
JA
4853/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
4854#define add_to_export_env(envstr,do_alloc) \
4855do \
4856 { \
4857 if (export_env_index >= (export_env_size - 1)) \
4858 { \
4859 export_env_size += 16; \
7117c2d2 4860 export_env = strvec_resize (export_env, export_env_size); \
95732b49 4861 environ = export_env; \
d166f048
JA
4862 } \
4863 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
4864 export_env[export_env_index] = (char *)NULL; \
4865 } while (0)
4866
d166f048
JA
4867/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
4868 array with the same left-hand side. Return the new EXPORT_ENV. */
726f6388 4869char **
d166f048 4870add_or_supercede_exported_var (assign, do_alloc)
726f6388 4871 char *assign;
d166f048 4872 int do_alloc;
726f6388
JA
4873{
4874 register int i;
d166f048 4875 int equal_offset;
726f6388 4876
b80f6443 4877 equal_offset = assignment (assign, 0);
d166f048
JA
4878 if (equal_offset == 0)
4879 return (export_env);
726f6388 4880
7117c2d2
JA
4881 /* If this is a function, then only supersede the function definition.
4882 We do this by including the `=() {' in the comparison, like
4883 initialize_shell_variables does. */
4884 if (assign[equal_offset + 1] == '(' &&
4885 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
4886 equal_offset += 4;
726f6388 4887
d166f048 4888 for (i = 0; i < export_env_index; i++)
726f6388 4889 {
d166f048 4890 if (STREQN (assign, export_env[i], equal_offset + 1))
726f6388 4891 {
d166f048
JA
4892 free (export_env[i]);
4893 export_env[i] = do_alloc ? savestring (assign) : assign;
4894 return (export_env);
726f6388
JA
4895 }
4896 }
d166f048
JA
4897 add_to_export_env (assign, do_alloc);
4898 return (export_env);
726f6388
JA
4899}
4900
7117c2d2
JA
4901static void
4902add_temp_array_to_env (temp_array, do_alloc, do_supercede)
4903 char **temp_array;
4904 int do_alloc, do_supercede;
4905{
4906 register int i;
4907
4908 if (temp_array == 0)
4909 return;
4910
4911 for (i = 0; temp_array[i]; i++)
4912 {
4913 if (do_supercede)
4914 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
4915 else
4916 add_to_export_env (temp_array[i], do_alloc);
4917 }
4918
4919 free (temp_array);
4920}
4921
d166f048 4922/* Make the environment array for the command about to be executed, if the
726f6388
JA
4923 array needs making. Otherwise, do nothing. If a shell action could
4924 change the array that commands receive for their environment, then the
7117c2d2
JA
4925 code should `array_needs_making++'.
4926
4927 The order to add to the array is:
4928 temporary_env
4929 list of var contexts whose head is shell_variables
4930 shell_functions
4931
4932 This is the shell variable lookup order. We add only new variable
4933 names at each step, which allows local variables and variables in
4934 the temporary environments to shadow variables in the global (or
4935 any previous) scope.
4936*/
4937
4938static int
4939n_shell_variables ()
4940{
4941 VAR_CONTEXT *vc;
4942 int n;
4943
4944 for (n = 0, vc = shell_variables; vc; vc = vc->down)
4945 n += HASH_ENTRIES (vc->table);
4946 return n;
4947}
4948
2bbe8058
CR
4949int
4950chkexport (name)
4951 char *name;
4952{
4953 SHELL_VAR *v;
4954
4955 v = find_variable (name);
eafc91a3 4956 if (v && exported_p (v))
2bbe8058
CR
4957 {
4958 array_needs_making = 1;
4959 maybe_make_export_env ();
4960 return 1;
4961 }
4962 return 0;
4963}
4964
726f6388
JA
4965void
4966maybe_make_export_env ()
4967{
726f6388 4968 register char **temp_array;
d166f048 4969 int new_size;
d233b485 4970 VAR_CONTEXT *tcxt, *icxt;
726f6388
JA
4971
4972 if (array_needs_making)
4973 {
4974 if (export_env)
3185942a 4975 strvec_flush (export_env);
d166f048
JA
4976
4977 /* Make a guess based on how many shell variables and functions we
4978 have. Since there will always be array variables, and array
4979 variables are not (yet) exported, this will always be big enough
7117c2d2
JA
4980 for the exported variables and functions. */
4981 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
d233b485 4982 HASH_ENTRIES (temporary_env) + HASH_ENTRIES (invalid_env);
d166f048
JA
4983 if (new_size > export_env_size)
4984 {
4985 export_env_size = new_size;
7117c2d2 4986 export_env = strvec_resize (export_env, export_env_size);
95732b49 4987 environ = export_env;
d166f048
JA
4988 }
4989 export_env[export_env_index = 0] = (char *)NULL;
726f6388 4990
0001803f 4991 /* Make a dummy variable context from the temporary_env, stick it on
3185942a
JA
4992 the front of shell_variables, call make_var_export_array on the
4993 whole thing to flatten it, and convert the list of SHELL_VAR *s
4994 to the form needed by the environment. */
7117c2d2 4995 if (temporary_env)
3185942a
JA
4996 {
4997 tcxt = new_var_context ((char *)NULL, 0);
4998 tcxt->table = temporary_env;
4999 tcxt->down = shell_variables;
5000 }
7117c2d2 5001 else
3185942a 5002 tcxt = shell_variables;
d233b485
CR
5003
5004 if (invalid_env)
5005 {
5006 icxt = new_var_context ((char *)NULL, 0);
5007 icxt->table = invalid_env;
5008 icxt->down = tcxt;
5009 }
5010 else
5011 icxt = tcxt;
7117c2d2 5012
d233b485 5013 temp_array = make_var_export_array (icxt);
d166f048 5014 if (temp_array)
7117c2d2
JA
5015 add_temp_array_to_env (temp_array, 0, 0);
5016
d233b485
CR
5017 if (icxt != tcxt)
5018 free (icxt);
5019
7117c2d2 5020 if (tcxt != shell_variables)
3185942a 5021 free (tcxt);
726f6388 5022
f73dda09
JA
5023#if defined (RESTRICTED_SHELL)
5024 /* Restricted shells may not export shell functions. */
7117c2d2 5025 temp_array = restricted ? (char **)0 : make_func_export_array ();
f73dda09 5026#else
7117c2d2 5027 temp_array = make_func_export_array ();
f73dda09 5028#endif
d166f048 5029 if (temp_array)
7117c2d2 5030 add_temp_array_to_env (temp_array, 0, 0);
726f6388
JA
5031
5032 array_needs_making = 0;
5033 }
5034}
5035
b72432fd
JA
5036/* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
5037 we will need to remake the exported environment every time we
5038 change directories. `_' is always put into the environment for
5039 every external command, so without special treatment it will always
5040 cause the environment to be remade.
5041
5042 If there is no other reason to make the exported environment, we can
5043 just update the variables in place and mark the exported environment
5044 as no longer needing a remake. */
5045void
5046update_export_env_inplace (env_prefix, preflen, value)
5047 char *env_prefix;
5048 int preflen;
5049 char *value;
5050{
5051 char *evar;
5052
f73dda09 5053 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
b72432fd
JA
5054 strcpy (evar, env_prefix);
5055 if (value)
5056 strcpy (evar + preflen, value);
5057 export_env = add_or_supercede_exported_var (evar, 0);
5058}
5059
726f6388
JA
5060/* We always put _ in the environment as the name of this command. */
5061void
5062put_command_name_into_env (command_name)
5063 char *command_name;
5064{
b72432fd 5065 update_export_env_inplace ("_=", 2, command_name);
726f6388
JA
5066}
5067
7117c2d2
JA
5068/* **************************************************************** */
5069/* */
5070/* Managing variable contexts */
5071/* */
5072/* **************************************************************** */
5073
5074/* Allocate and return a new variable context with NAME and FLAGS.
5075 NAME can be NULL. */
726f6388 5076
7117c2d2
JA
5077VAR_CONTEXT *
5078new_var_context (name, flags)
5079 char *name;
5080 int flags;
5081{
5082 VAR_CONTEXT *vc;
5083
5084 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
5085 vc->name = name ? savestring (name) : (char *)NULL;
5086 vc->scope = variable_context;
5087 vc->flags = flags;
5088
5089 vc->up = vc->down = (VAR_CONTEXT *)NULL;
5090 vc->table = (HASH_TABLE *)NULL;
5091
5092 return vc;
5093}
5094
5095/* Free a variable context and its data, including the hash table. Dispose
5096 all of the variables. */
5097void
5098dispose_var_context (vc)
5099 VAR_CONTEXT *vc;
5100{
5101 FREE (vc->name);
5102
5103 if (vc->table)
5104 {
5105 delete_all_variables (vc->table);
5106 hash_dispose (vc->table);
5107 }
5108
5109 free (vc);
5110}
5111
5112/* Set VAR's scope level to the current variable context. */
5113static int
5114set_context (var)
5115 SHELL_VAR *var;
5116{
5117 return (var->context = variable_context);
5118}
5119
5120/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
5121 temporary variables, and push it onto shell_variables. This is
5122 for shell functions. */
5123VAR_CONTEXT *
5124push_var_context (name, flags, tempvars)
5125 char *name;
5126 int flags;
5127 HASH_TABLE *tempvars;
5128{
5129 VAR_CONTEXT *vc;
d233b485
CR
5130 int posix_func_behavior;
5131
5132 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5133 functions no longer behave like assignment statements preceding
5134 special builtins, and do not persist in the current shell environment.
5135 This is austin group interp #654, though nobody implements it yet. */
5136#if 0 /* XXX - TAG: bash-5.1 */
5137 posix_func_behavior = 0;
5138#else
5139 posix_func_behavior = posixly_correct;
5140#endif
7117c2d2
JA
5141
5142 vc = new_var_context (name, flags);
d233b485
CR
5143 /* Posix interp 1009, temporary assignments preceding function calls modify
5144 the current environment *before* the command is executed. */
5145 if (posix_func_behavior && (flags & VC_FUNCENV) && tempvars == temporary_env)
5146 merge_temporary_env ();
5147 else if (tempvars)
7117c2d2 5148 {
d233b485 5149 vc->table = tempvars;
7117c2d2
JA
5150 /* Have to do this because the temp environment was created before
5151 variable_context was incremented. */
5152 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
5153 vc->flags |= VC_HASTMPVAR;
5154 }
5155 vc->down = shell_variables;
5156 shell_variables->up = vc;
5157
5158 return (shell_variables = vc);
5159}
5160
d233b485
CR
5161/* This can be called from one of two code paths:
5162 1. pop_scope, which implements the posix rules for propagating variable
5163 assignments preceding special builtins to the surrounding scope
5164 (push_builtin_var);
5165 2. pop_var_context, which is called from pop_context and implements the
5166 posix rules for propagating variable assignments preceding function
5167 calls to the surrounding scope (push_func_var).
7117c2d2 5168
d233b485
CR
5169 It takes variables out of a temporary environment hash table. We take the
5170 variable in data.
5171*/
5172
5173static inline void
5174push_posix_tempvar_internal (var, isbltin)
5175 SHELL_VAR *var;
5176 int isbltin;
5177{
5178 SHELL_VAR *v;
5179 int posix_var_behavior;
5180
5181 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5182 functions no longer behave like assignment statements preceding
5183 special builtins, and do not persist in the current shell environment.
5184 This is austin group interp #654, though nobody implements it yet. */
5185#if 0 /* XXX - TAG: bash-5.1 */
5186 posix_var_behavior = posixly_correct && isbltin;
5187#else
5188 posix_var_behavior = posixly_correct;
5189#endif
7117c2d2 5190
a0c0a00f
CR
5191 if (local_p (var) && STREQ (var->name, "-"))
5192 set_current_options (value_cell (var));
d233b485 5193 else if (tempvar_p (var) && (posix_var_behavior || (var->attributes & att_propagate)))
7117c2d2 5194 {
30d188c2
CR
5195 /* Make sure we have a hash table to store the variable in while it is
5196 being propagated down to the global variables table. Create one if
5197 we have to */
5198 if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
a0c0a00f 5199 shell_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
95732b49 5200 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
d233b485
CR
5201 /* XXX - should we set v->context here? */
5202 if (v)
5203 v->context = shell_variables->scope;
a0c0a00f 5204#if defined (ARRAY_VARS)
d233b485 5205 if (v && (array_p (var) || assoc_p (var)))
a0c0a00f
CR
5206 {
5207 FREE (value_cell (v));
5208 if (array_p (var))
5209 var_setarray (v, array_copy (array_cell (var)));
5210 else
5211 var_setassoc (v, assoc_copy (assoc_cell (var)));
5212 }
5213#endif
7117c2d2
JA
5214 if (shell_variables == global_variables)
5215 var->attributes &= ~(att_tempvar|att_propagate);
5216 else
f1be666c 5217 shell_variables->flags |= VC_HASTMPVAR;
a0c0a00f
CR
5218 if (v)
5219 v->attributes |= var->attributes;
7117c2d2 5220 }
f1be666c
JA
5221 else
5222 stupidly_hack_special_variables (var->name); /* XXX */
7117c2d2
JA
5223
5224 dispose_variable (var);
5225}
5226
d233b485
CR
5227static void
5228push_func_var (data)
5229 PTR_T data;
5230{
5231 SHELL_VAR *var;
5232
5233 var = (SHELL_VAR *)data;
5234 push_posix_tempvar_internal (var, 0);
5235}
5236
5237static void
5238push_builtin_var (data)
5239 PTR_T data;
5240{
5241 SHELL_VAR *var;
5242
5243 var = (SHELL_VAR *)data;
5244 push_posix_tempvar_internal (var, 1);
5245}
5246
7117c2d2
JA
5247/* Pop the top context off of VCXT and dispose of it, returning the rest of
5248 the stack. */
5249void
5250pop_var_context ()
5251{
5252 VAR_CONTEXT *ret, *vcxt;
5253
5254 vcxt = shell_variables;
5255 if (vc_isfuncenv (vcxt) == 0)
5256 {
b80f6443 5257 internal_error (_("pop_var_context: head of shell_variables not a function context"));
7117c2d2
JA
5258 return;
5259 }
5260
5261 if (ret = vcxt->down)
5262 {
5263 ret->up = (VAR_CONTEXT *)NULL;
5264 shell_variables = ret;
5265 if (vcxt->table)
5266 hash_flush (vcxt->table, push_func_var);
5267 dispose_var_context (vcxt);
5268 }
5269 else
b80f6443 5270 internal_error (_("pop_var_context: no global_variables context"));
7117c2d2
JA
5271}
5272
5273/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
5274 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
5275void
5276delete_all_contexts (vcxt)
5277 VAR_CONTEXT *vcxt;
5278{
5279 VAR_CONTEXT *v, *t;
5280
5281 for (v = vcxt; v != global_variables; v = t)
5282 {
5283 t = v->down;
5284 dispose_var_context (v);
3185942a 5285 }
7117c2d2
JA
5286
5287 delete_all_variables (global_variables->table);
5288 shell_variables = global_variables;
5289}
5290
5291/* **************************************************************** */
5292/* */
5293/* Pushing and Popping temporary variable scopes */
5294/* */
5295/* **************************************************************** */
5296
5297VAR_CONTEXT *
5298push_scope (flags, tmpvars)
5299 int flags;
5300 HASH_TABLE *tmpvars;
5301{
5302 return (push_var_context ((char *)NULL, flags, tmpvars));
5303}
5304
5305static void
5306push_exported_var (data)
5307 PTR_T data;
5308{
5309 SHELL_VAR *var, *v;
5310
5311 var = (SHELL_VAR *)data;
5312
5313 /* If a temp var had its export attribute set, or it's marked to be
5314 propagated, bind it in the previous scope before disposing it. */
95732b49
JA
5315 /* XXX - This isn't exactly right, because all tempenv variables have the
5316 export attribute set. */
95732b49 5317 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
7117c2d2
JA
5318 {
5319 var->attributes &= ~att_tempvar; /* XXX */
95732b49 5320 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
7117c2d2
JA
5321 if (shell_variables == global_variables)
5322 var->attributes &= ~att_propagate;
a0c0a00f 5323 if (v)
d233b485
CR
5324 {
5325 v->attributes |= var->attributes;
5326 v->context = shell_variables->scope;
5327 }
7117c2d2 5328 }
f1be666c
JA
5329 else
5330 stupidly_hack_special_variables (var->name); /* XXX */
7117c2d2
JA
5331
5332 dispose_variable (var);
5333}
5334
d233b485
CR
5335/* This is called to propagate variables in the temporary environment of a
5336 special builtin (if IS_SPECIAL != 0) or exported variables that are the
5337 result of a builtin like `source' or `command' that can operate on the
5338 variables in its temporary environment. In the first case, we call
5339 push_builtin_var, which does the right thing. */
7117c2d2
JA
5340void
5341pop_scope (is_special)
5342 int is_special;
5343{
5344 VAR_CONTEXT *vcxt, *ret;
d233b485 5345 int is_bltinenv;
7117c2d2
JA
5346
5347 vcxt = shell_variables;
5348 if (vc_istempscope (vcxt) == 0)
5349 {
b80f6443 5350 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
7117c2d2
JA
5351 return;
5352 }
d233b485 5353 is_bltinenv = vc_isbltnenv (vcxt); /* XXX - for later */
7117c2d2
JA
5354
5355 ret = vcxt->down;
5356 if (ret)
5357 ret->up = (VAR_CONTEXT *)NULL;
5358
5359 shell_variables = ret;
5360
5361 /* Now we can take care of merging variables in VCXT into set of scopes
5362 whose head is RET (shell_variables). */
5363 FREE (vcxt->name);
5364 if (vcxt->table)
5365 {
5366 if (is_special)
d233b485 5367 hash_flush (vcxt->table, push_builtin_var);
7117c2d2
JA
5368 else
5369 hash_flush (vcxt->table, push_exported_var);
5370 hash_dispose (vcxt->table);
5371 }
5372 free (vcxt);
5373
5374 sv_ifs ("IFS"); /* XXX here for now */
5375}
5376
5377/* **************************************************************** */
5378/* */
5379/* Pushing and Popping function contexts */
5380/* */
5381/* **************************************************************** */
5382
d233b485
CR
5383struct saved_dollar_vars {
5384 char **first_ten;
5385 WORD_LIST *rest;
5386};
5387
5388static struct saved_dollar_vars *dollar_arg_stack = (struct saved_dollar_vars *)NULL;
7117c2d2
JA
5389static int dollar_arg_stack_slots;
5390static int dollar_arg_stack_index;
5391
d233b485
CR
5392/* Functions to manipulate dollar_vars array. Need to keep these in sync with
5393 whatever remember_args() does. */
5394static char **
5395save_dollar_vars ()
5396{
5397 char **ret;
5398 int i;
5399
5400 ret = strvec_create (10);
5401 for (i = 1; i < 10; i++)
5402 {
5403 ret[i] = dollar_vars[i];
5404 dollar_vars[i] = (char *)NULL;
5405 }
5406 return ret;
5407}
5408
5409static void
5410restore_dollar_vars (args)
5411 char **args;
5412{
5413 int i;
5414
5415 for (i = 1; i < 10; i++)
5416 dollar_vars[i] = args[i];
5417}
5418
5419static void
5420free_dollar_vars ()
5421{
5422 int i;
5423
5424 for (i = 1; i < 10; i++)
5425 {
5426 FREE (dollar_vars[i]);
5427 dollar_vars[i] = (char *)NULL;
5428 }
5429}
5430
5431static void
5432free_saved_dollar_vars (args)
5433 char **args;
5434{
5435 int i;
5436
5437 for (i = 1; i < 10; i++)
5438 FREE (args[i]);
5439}
5440
a0c0a00f 5441/* XXX - should always be followed by remember_args () */
7117c2d2
JA
5442void
5443push_context (name, is_subshell, tempvars)
5444 char *name; /* function name */
5445 int is_subshell;
5446 HASH_TABLE *tempvars;
5447{
5448 if (is_subshell == 0)
5449 push_dollar_vars ();
5450 variable_context++;
5451 push_var_context (name, VC_FUNCENV, tempvars);
5452}
5453
5454/* Only called when subshell == 0, so we don't need to check, and can
5455 unconditionally pop the dollar vars off the stack. */
5456void
5457pop_context ()
726f6388 5458{
7117c2d2
JA
5459 pop_dollar_vars ();
5460 variable_context--;
5461 pop_var_context ();
726f6388 5462
7117c2d2
JA
5463 sv_ifs ("IFS"); /* XXX here for now */
5464}
726f6388 5465
7117c2d2
JA
5466/* Save the existing positional parameters on a stack. */
5467void
5468push_dollar_vars ()
5469{
5470 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
5471 {
d233b485 5472 dollar_arg_stack = (struct saved_dollar_vars *)
7117c2d2 5473 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
d233b485 5474 * sizeof (struct saved_dollar_vars));
7117c2d2 5475 }
d233b485
CR
5476
5477 dollar_arg_stack[dollar_arg_stack_index].first_ten = save_dollar_vars ();
5478 dollar_arg_stack[dollar_arg_stack_index++].rest = rest_of_args;
5479 rest_of_args = (WORD_LIST *)NULL;
5480
5481 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5482 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
7117c2d2 5483}
726f6388 5484
7117c2d2
JA
5485/* Restore the positional parameters from our stack. */
5486void
5487pop_dollar_vars ()
5488{
d233b485 5489 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
7117c2d2 5490 return;
726f6388 5491
d233b485
CR
5492 /* Do what remember_args (xxx, 1) would have done. */
5493 free_dollar_vars ();
5494 dispose_words (rest_of_args);
5495
5496 rest_of_args = dollar_arg_stack[--dollar_arg_stack_index].rest;
5497 restore_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5498 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5499
5500 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5501 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5502
7117c2d2 5503 set_dollar_vars_unchanged ();
d233b485 5504 invalidate_cached_quoted_dollar_at ();
7117c2d2 5505}
ccc6cda3 5506
7117c2d2
JA
5507void
5508dispose_saved_dollar_vars ()
5509{
d233b485 5510 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
7117c2d2 5511 return;
726f6388 5512
d233b485
CR
5513 dispose_words (dollar_arg_stack[--dollar_arg_stack_index].rest);
5514 free_saved_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5515 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5516
5517 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5518 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5519}
5520
5521/* Initialize BASH_ARGV and BASH_ARGC after turning on extdebug after the
5522 shell is initialized */
5523void
5524init_bash_argv ()
5525{
5526 if (bash_argv_initialized == 0)
5527 {
5528 save_bash_argv ();
5529 bash_argv_initialized = 1;
5530 }
5531}
5532
5533void
5534save_bash_argv ()
5535{
5536 WORD_LIST *list;
5537
5538 list = list_rest_of_args ();
5539 push_args (list);
5540 dispose_words (list);
726f6388 5541}
cce855bc 5542
b80f6443
JA
5543/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
5544
5545void
5546push_args (list)
5547 WORD_LIST *list;
5548{
5549#if defined (ARRAY_VARS) && defined (DEBUGGER)
5550 SHELL_VAR *bash_argv_v, *bash_argc_v;
5551 ARRAY *bash_argv_a, *bash_argc_a;
5552 WORD_LIST *l;
5553 arrayind_t i;
5554 char *t;
5555
5556 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5557 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5558
5559 for (l = list, i = 0; l; l = l->next, i++)
5560 array_push (bash_argv_a, l->word->word);
5561
5562 t = itos (i);
5563 array_push (bash_argc_a, t);
5564 free (t);
5565#endif /* ARRAY_VARS && DEBUGGER */
5566}
5567
5568/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
5569 array and use that value as the count of elements to remove from
5570 BASH_ARGV. */
5571void
5572pop_args ()
5573{
5574#if defined (ARRAY_VARS) && defined (DEBUGGER)
5575 SHELL_VAR *bash_argv_v, *bash_argc_v;
5576 ARRAY *bash_argv_a, *bash_argc_a;
5577 ARRAY_ELEMENT *ce;
5578 intmax_t i;
5579
5580 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5581 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5582
5583 ce = array_shift (bash_argc_a, 1, 0);
5584 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
5585 i = 0;
5586
5587 for ( ; i > 0; i--)
5588 array_pop (bash_argv_a);
5589 array_dispose_element (ce);
5590#endif /* ARRAY_VARS && DEBUGGER */
5591}
5592
cce855bc
JA
5593/*************************************************
5594 * *
5595 * Functions to manage special variables *
5596 * *
5597 *************************************************/
5598
5599/* Extern declarations for variables this code has to manage. */
cce855bc
JA
5600
5601/* An alist of name.function for each special variable. Most of the
5602 functions don't do much, and in fact, this would be faster with a
5603 switch statement, but by the end of this file, I am sick of switch
5604 statements. */
5605
5606#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
5607
7117c2d2 5608/* This table will be sorted with qsort() the first time it's accessed. */
cce855bc
JA
5609struct name_and_function {
5610 char *name;
f73dda09 5611 sh_sv_func_t *function;
7117c2d2 5612};
cce855bc 5613
7117c2d2 5614static struct name_and_function special_vars[] = {
ac50fbac 5615 { "BASH_COMPAT", sv_shcompat },
0001803f
CR
5616 { "BASH_XTRACEFD", sv_xtracefd },
5617
ac50fbac
CR
5618#if defined (JOB_CONTROL)
5619 { "CHILD_MAX", sv_childmax },
5620#endif
5621
95732b49
JA
5622#if defined (READLINE)
5623# if defined (STRICT_POSIX)
5624 { "COLUMNS", sv_winsize },
5625# endif
5626 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
5627#endif
5628
a0c0a00f
CR
5629 { "EXECIGNORE", sv_execignore },
5630
495aee44
CR
5631 { "FUNCNEST", sv_funcnest },
5632
cce855bc
JA
5633 { "GLOBIGNORE", sv_globignore },
5634
cce855bc 5635#if defined (HISTORY)
7117c2d2
JA
5636 { "HISTCONTROL", sv_history_control },
5637 { "HISTFILESIZE", sv_histsize },
cce855bc
JA
5638 { "HISTIGNORE", sv_histignore },
5639 { "HISTSIZE", sv_histsize },
b80f6443 5640 { "HISTTIMEFORMAT", sv_histtimefmt },
7117c2d2 5641#endif
cce855bc 5642
95732b49
JA
5643#if defined (__CYGWIN__)
5644 { "HOME", sv_home },
5645#endif
5646
7117c2d2
JA
5647#if defined (READLINE)
5648 { "HOSTFILE", sv_hostfile },
5649#endif
cce855bc 5650
7117c2d2
JA
5651 { "IFS", sv_ifs },
5652 { "IGNOREEOF", sv_ignoreeof },
cce855bc 5653
7117c2d2 5654 { "LANG", sv_locale },
cce855bc
JA
5655 { "LC_ALL", sv_locale },
5656 { "LC_COLLATE", sv_locale },
5657 { "LC_CTYPE", sv_locale },
5658 { "LC_MESSAGES", sv_locale },
bb70624e 5659 { "LC_NUMERIC", sv_locale },
95732b49
JA
5660 { "LC_TIME", sv_locale },
5661
5662#if defined (READLINE) && defined (STRICT_POSIX)
5663 { "LINES", sv_winsize },
5664#endif
7117c2d2
JA
5665
5666 { "MAIL", sv_mail },
5667 { "MAILCHECK", sv_mail },
5668 { "MAILPATH", sv_mail },
5669
5670 { "OPTERR", sv_opterr },
5671 { "OPTIND", sv_optind },
5672
5673 { "PATH", sv_path },
5674 { "POSIXLY_CORRECT", sv_strict_posix },
5675
5676#if defined (READLINE)
5677 { "TERM", sv_terminal },
5678 { "TERMCAP", sv_terminal },
5679 { "TERMINFO", sv_terminal },
5680#endif /* READLINE */
5681
5682 { "TEXTDOMAIN", sv_locale },
5683 { "TEXTDOMAINDIR", sv_locale },
cce855bc 5684
2bbe8058 5685#if defined (HAVE_TZSET)
cce855bc
JA
5686 { "TZ", sv_tz },
5687#endif
5688
7117c2d2
JA
5689#if defined (HISTORY) && defined (BANG_HISTORY)
5690 { "histchars", sv_histchars },
5691#endif /* HISTORY && BANG_HISTORY */
5692
5693 { "ignoreeof", sv_ignoreeof },
5694
f73dda09 5695 { (char *)0, (sh_sv_func_t *)0 }
cce855bc
JA
5696};
5697
7117c2d2
JA
5698#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
5699
5700static int
5701sv_compare (sv1, sv2)
5702 struct name_and_function *sv1, *sv2;
5703{
5704 int r;
5705
5706 if ((r = sv1->name[0] - sv2->name[0]) == 0)
5707 r = strcmp (sv1->name, sv2->name);
5708 return r;
5709}
5710
5711static inline int
5712find_special_var (name)
5713 const char *name;
5714{
5715 register int i, r;
5716
5717 for (i = 0; special_vars[i].name; i++)
5718 {
5719 r = special_vars[i].name[0] - name[0];
5720 if (r == 0)
5721 r = strcmp (special_vars[i].name, name);
5722 if (r == 0)
5723 return i;
5724 else if (r > 0)
5725 /* Can't match any of rest of elements in sorted list. Take this out
5726 if it causes problems in certain environments. */
3185942a 5727 break;
7117c2d2
JA
5728 }
5729 return -1;
5730}
5731
cce855bc
JA
5732/* The variable in NAME has just had its state changed. Check to see if it
5733 is one of the special ones where something special happens. */
5734void
5735stupidly_hack_special_variables (name)
5736 char *name;
5737{
7117c2d2 5738 static int sv_sorted = 0;
cce855bc
JA
5739 int i;
5740
7117c2d2 5741 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
cce855bc 5742 {
7117c2d2
JA
5743 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
5744 (QSFUNC *)sv_compare);
5745 sv_sorted = 1;
cce855bc 5746 }
7117c2d2
JA
5747
5748 i = find_special_var (name);
5749 if (i != -1)
5750 (*(special_vars[i].function)) (name);
5751}
5752
3185942a
JA
5753/* Special variables that need hooks to be run when they are unset as part
5754 of shell reinitialization should have their sv_ functions run here. */
5755void
5756reinit_special_variables ()
5757{
5758#if defined (READLINE)
5759 sv_comp_wordbreaks ("COMP_WORDBREAKS");
5760#endif
5761 sv_globignore ("GLOBIGNORE");
5762 sv_opterr ("OPTERR");
5763}
5764
7117c2d2
JA
5765void
5766sv_ifs (name)
5767 char *name;
5768{
5769 SHELL_VAR *v;
5770
5771 v = find_variable ("IFS");
5772 setifs (v);
cce855bc
JA
5773}
5774
5775/* What to do just after the PATH variable has changed. */
5776void
5777sv_path (name)
5778 char *name;
5779{
5780 /* hash -r */
7117c2d2 5781 phash_flush ();
cce855bc
JA
5782}
5783
5784/* What to do just after one of the MAILxxxx variables has changed. NAME
5785 is the name of the variable. This is called with NAME set to one of
5786 MAIL, MAILCHECK, or MAILPATH. */
5787void
5788sv_mail (name)
5789 char *name;
5790{
5791 /* If the time interval for checking the files has changed, then
5792 reset the mail timer. Otherwise, one of the pathname vars
5793 to the users mailbox has changed, so rebuild the array of
5794 filenames. */
5795 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
5796 reset_mail_timer ();
5797 else
5798 {
5799 free_mail_files ();
5800 remember_mail_dates ();
5801 }
5802}
5803
495aee44
CR
5804void
5805sv_funcnest (name)
5806 char *name;
5807{
5808 SHELL_VAR *v;
5809 intmax_t num;
5810
5811 v = find_variable (name);
5812 if (v == 0)
5813 funcnest_max = 0;
5814 else if (legal_number (value_cell (v), &num) == 0)
5815 funcnest_max = 0;
5816 else
5817 funcnest_max = num;
5818}
5819
a0c0a00f
CR
5820/* What to do when EXECIGNORE changes. */
5821void
5822sv_execignore (name)
5823 char *name;
5824{
5825 setup_exec_ignore (name);
5826}
5827
cce855bc
JA
5828/* What to do when GLOBIGNORE changes. */
5829void
5830sv_globignore (name)
5831 char *name;
5832{
3185942a
JA
5833 if (privileged_mode == 0)
5834 setup_glob_ignore (name);
cce855bc
JA
5835}
5836
5837#if defined (READLINE)
95732b49
JA
5838void
5839sv_comp_wordbreaks (name)
5840 char *name;
5841{
5842 SHELL_VAR *sv;
5843
5844 sv = find_variable (name);
5845 if (sv == 0)
3185942a 5846 reset_completer_word_break_chars ();
95732b49
JA
5847}
5848
cce855bc
JA
5849/* What to do just after one of the TERMxxx variables has changed.
5850 If we are an interactive shell, then try to reset the terminal
5851 information in readline. */
5852void
5853sv_terminal (name)
5854 char *name;
5855{
5856 if (interactive_shell && no_line_editing == 0)
5857 rl_reset_terminal (get_string_value ("TERM"));
5858}
5859
5860void
5861sv_hostfile (name)
5862 char *name;
5863{
bb70624e
JA
5864 SHELL_VAR *v;
5865
5866 v = find_variable (name);
5867 if (v == 0)
5868 clear_hostname_list ();
5869 else
5870 hostname_list_initialized = 0;
cce855bc 5871}
95732b49
JA
5872
5873#if defined (STRICT_POSIX)
5874/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
5875 found in the initial environment) to override the terminal size reported by
5876 the kernel. */
5877void
5878sv_winsize (name)
5879 char *name;
5880{
5881 SHELL_VAR *v;
5882 intmax_t xd;
5883 int d;
5884
5885 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
5886 return;
5887
5888 v = find_variable (name);
a0c0a00f 5889 if (v == 0 || var_isset (v) == 0)
95732b49
JA
5890 rl_reset_screen_size ();
5891 else
5892 {
5893 if (legal_number (value_cell (v), &xd) == 0)
5894 return;
495aee44 5895 winsize_assignment = 1;
95732b49
JA
5896 d = xd; /* truncate */
5897 if (name[0] == 'L') /* LINES */
5898 rl_set_screen_size (d, -1);
5899 else /* COLUMNS */
5900 rl_set_screen_size (-1, d);
5901 winsize_assignment = 0;
5902 }
5903}
5904#endif /* STRICT_POSIX */
cce855bc
JA
5905#endif /* READLINE */
5906
95732b49
JA
5907/* Update the value of HOME in the export environment so tilde expansion will
5908 work on cygwin. */
5909#if defined (__CYGWIN__)
5910sv_home (name)
5911 char *name;
5912{
5913 array_needs_making = 1;
5914 maybe_make_export_env ();
5915}
5916#endif
5917
cce855bc
JA
5918#if defined (HISTORY)
5919/* What to do after the HISTSIZE or HISTFILESIZE variables change.
5920 If there is a value for this HISTSIZE (and it is numeric), then stifle
5921 the history. Otherwise, if there is NO value for this variable,
5922 unstifle the history. If name is HISTFILESIZE, and its value is
5923 numeric, truncate the history file to hold no more than that many
5924 lines. */
5925void
5926sv_histsize (name)
5927 char *name;
5928{
5929 char *temp;
7117c2d2 5930 intmax_t num;
95732b49 5931 int hmax;
cce855bc
JA
5932
5933 temp = get_string_value (name);
5934
5935 if (temp && *temp)
5936 {
5937 if (legal_number (temp, &num))
28ef6c31 5938 {
0628567a 5939 hmax = num;
ac50fbac
CR
5940 if (hmax < 0 && name[4] == 'S')
5941 unstifle_history (); /* unstifle history if HISTSIZE < 0 */
5942 else if (name[4] == 'S')
cce855bc 5943 {
95732b49 5944 stifle_history (hmax);
0628567a
JA
5945 hmax = where_history ();
5946 if (history_lines_this_session > hmax)
5947 history_lines_this_session = hmax;
cce855bc 5948 }
ac50fbac 5949 else if (hmax >= 0) /* truncate HISTFILE if HISTFILESIZE >= 0 */
cce855bc 5950 {
0628567a 5951 history_truncate_file (get_string_value ("HISTFILE"), hmax);
a0c0a00f
CR
5952 /* If we just shrank the history file to fewer lines than we've
5953 already read, make sure we adjust our idea of how many lines
5954 we have read from the file. */
5955 if (hmax < history_lines_in_file)
0628567a 5956 history_lines_in_file = hmax;
cce855bc
JA
5957 }
5958 }
5959 }
5960 else if (name[4] == 'S')
5961 unstifle_history ();
5962}
5963
5964/* What to do after the HISTIGNORE variable changes. */
5965void
5966sv_histignore (name)
5967 char *name;
5968{
5969 setup_history_ignore (name);
5970}
5971
5972/* What to do after the HISTCONTROL variable changes. */
5973void
5974sv_history_control (name)
5975 char *name;
5976{
5977 char *temp;
b80f6443
JA
5978 char *val;
5979 int tptr;
cce855bc
JA
5980
5981 history_control = 0;
5982 temp = get_string_value (name);
5983
b80f6443
JA
5984 if (temp == 0 || *temp == 0)
5985 return;
5986
5987 tptr = 0;
5988 while (val = extract_colon_unit (temp, &tptr))
cce855bc 5989 {
b80f6443
JA
5990 if (STREQ (val, "ignorespace"))
5991 history_control |= HC_IGNSPACE;
5992 else if (STREQ (val, "ignoredups"))
5993 history_control |= HC_IGNDUPS;
5994 else if (STREQ (val, "ignoreboth"))
5995 history_control |= HC_IGNBOTH;
5996 else if (STREQ (val, "erasedups"))
5997 history_control |= HC_ERASEDUPS;
5998
5999 free (val);
cce855bc
JA
6000 }
6001}
6002
6003#if defined (BANG_HISTORY)
6004/* Setting/unsetting of the history expansion character. */
6005void
6006sv_histchars (name)
6007 char *name;
6008{
6009 char *temp;
6010
6011 temp = get_string_value (name);
6012 if (temp)
6013 {
6014 history_expansion_char = *temp;
6015 if (temp[0] && temp[1])
6016 {
6017 history_subst_char = temp[1];
6018 if (temp[2])
6019 history_comment_char = temp[2];
6020 }
6021 }
6022 else
6023 {
6024 history_expansion_char = '!';
6025 history_subst_char = '^';
6026 history_comment_char = '#';
6027 }
6028}
6029#endif /* BANG_HISTORY */
b80f6443
JA
6030
6031void
6032sv_histtimefmt (name)
6033 char *name;
6034{
6035 SHELL_VAR *v;
6036
ac50fbac
CR
6037 if (v = find_variable (name))
6038 {
6039 if (history_comment_char == 0)
6040 history_comment_char = '#';
6041 }
b80f6443
JA
6042 history_write_timestamps = (v != 0);
6043}
cce855bc
JA
6044#endif /* HISTORY */
6045
2bbe8058 6046#if defined (HAVE_TZSET)
cce855bc
JA
6047void
6048sv_tz (name)
6049 char *name;
6050{
2bbe8058
CR
6051 if (chkexport (name))
6052 tzset ();
cce855bc
JA
6053}
6054#endif
6055
6056/* If the variable exists, then the value of it can be the number
6057 of times we actually ignore the EOF. The default is small,
6058 (smaller than csh, anyway). */
6059void
6060sv_ignoreeof (name)
6061 char *name;
6062{
6063 SHELL_VAR *tmp_var;
6064 char *temp;
6065
6066 eof_encountered = 0;
6067
6068 tmp_var = find_variable (name);
a0c0a00f 6069 ignoreeof = tmp_var && var_isset (tmp_var);
cce855bc
JA
6070 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
6071 if (temp)
6072 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
6073 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
6074}
6075
6076void
6077sv_optind (name)
6078 char *name;
6079{
a0c0a00f 6080 SHELL_VAR *var;
cce855bc
JA
6081 char *tt;
6082 int s;
6083
a0c0a00f
CR
6084 var = find_variable ("OPTIND");
6085 tt = var ? get_variable_value (var) : (char *)NULL;
6086
6087 /* Assume that if var->context < variable_context and variable_context > 0
6088 then we are restoring the variables's previous state while returning
6089 from a function. */
cce855bc
JA
6090 if (tt && *tt)
6091 {
6092 s = atoi (tt);
6093
6094 /* According to POSIX, setting OPTIND=1 resets the internal state
6095 of getopt (). */
6096 if (s < 0 || s == 1)
6097 s = 0;
6098 }
6099 else
6100 s = 0;
6101 getopts_reset (s);
6102}
6103
6104void
6105sv_opterr (name)
6106 char *name;
6107{
6108 char *tt;
6109
6110 tt = get_string_value ("OPTERR");
6111 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
6112}
6113
6114void
6115sv_strict_posix (name)
6116 char *name;
6117{
a0c0a00f
CR
6118 SHELL_VAR *var;
6119
6120 var = find_variable (name);
6121 posixly_correct = var && var_isset (var);
cce855bc
JA
6122 posix_initialize (posixly_correct);
6123#if defined (READLINE)
6124 if (interactive_shell)
6125 posix_readline_initialize (posixly_correct);
6126#endif /* READLINE */
6127 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
6128}
6129
6130void
6131sv_locale (name)
6132 char *name;
6133{
6134 char *v;
ac50fbac 6135 int r;
cce855bc
JA
6136
6137 v = get_string_value (name);
6138 if (name[0] == 'L' && name[1] == 'A') /* LANG */
ac50fbac 6139 r = set_lang (name, v);
cce855bc 6140 else
ac50fbac
CR
6141 r = set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
6142
6143#if 1
6144 if (r == 0 && posixly_correct)
6145 last_command_exit_value = 1;
6146#endif
cce855bc
JA
6147}
6148
6149#if defined (ARRAY_VARS)
6150void
7117c2d2 6151set_pipestatus_array (ps, nproc)
cce855bc 6152 int *ps;
7117c2d2 6153 int nproc;
cce855bc
JA
6154{
6155 SHELL_VAR *v;
6156 ARRAY *a;
7117c2d2 6157 ARRAY_ELEMENT *ae;
cce855bc 6158 register int i;
f73dda09 6159 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
cce855bc
JA
6160
6161 v = find_variable ("PIPESTATUS");
6162 if (v == 0)
6163 v = make_new_array_variable ("PIPESTATUS");
6164 if (array_p (v) == 0)
6165 return; /* Do nothing if not an array variable. */
6166 a = array_cell (v);
7117c2d2
JA
6167
6168 if (a == 0 || array_num_elements (a) == 0)
cce855bc 6169 {
7117c2d2
JA
6170 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
6171 {
6172 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6173 array_insert (a, i, t);
6174 }
6175 return;
6176 }
6177
6178 /* Fast case */
6179 if (array_num_elements (a) == nproc && nproc == 1)
6180 {
6181 ae = element_forw (a->head);
6182 free (element_value (ae));
d233b485 6183 set_element_value (ae, itos (ps[0]));
7117c2d2
JA
6184 }
6185 else if (array_num_elements (a) <= nproc)
6186 {
6187 /* modify in array_num_elements members in place, then add */
6188 ae = a->head;
6189 for (i = 0; i < array_num_elements (a); i++)
6190 {
6191 ae = element_forw (ae);
6192 free (element_value (ae));
d233b485 6193 set_element_value (ae, itos (ps[i]));
7117c2d2
JA
6194 }
6195 /* add any more */
6196 for ( ; i < nproc; i++)
6197 {
6198 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6199 array_insert (a, i, t);
6200 }
6201 }
6202 else
6203 {
6204 /* deleting elements. it's faster to rebuild the array. */
6205 array_flush (a);
6206 for (i = 0; ps[i] != -1; i++)
6207 {
6208 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6209 array_insert (a, i, t);
6210 }
cce855bc
JA
6211 }
6212}
495aee44
CR
6213
6214ARRAY *
6215save_pipestatus_array ()
6216{
6217 SHELL_VAR *v;
d233b485 6218 ARRAY *a;
495aee44
CR
6219
6220 v = find_variable ("PIPESTATUS");
6221 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6222 return ((ARRAY *)NULL);
6223
d233b485 6224 a = array_copy (array_cell (v));
495aee44 6225
d233b485 6226 return a;
495aee44
CR
6227}
6228
6229void
6230restore_pipestatus_array (a)
6231 ARRAY *a;
6232{
6233 SHELL_VAR *v;
6234 ARRAY *a2;
6235
6236 v = find_variable ("PIPESTATUS");
6237 /* XXX - should we still assign even if existing value is NULL? */
6238 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6239 return;
6240
6241 a2 = array_cell (v);
6242 var_setarray (v, a);
6243
6244 array_dispose (a2);
6245}
cce855bc
JA
6246#endif
6247
6248void
6249set_pipestatus_from_exit (s)
6250 int s;
6251{
6252#if defined (ARRAY_VARS)
6253 static int v[2] = { 0, -1 };
6254
6255 v[0] = s;
7117c2d2 6256 set_pipestatus_array (v, 1);
cce855bc
JA
6257#endif
6258}
0001803f
CR
6259
6260void
6261sv_xtracefd (name)
6262 char *name;
6263{
6264 SHELL_VAR *v;
6265 char *t, *e;
6266 int fd;
6267 FILE *fp;
6268
6269 v = find_variable (name);
6270 if (v == 0)
6271 {
6272 xtrace_reset ();
6273 return;
6274 }
6275
6276 t = value_cell (v);
6277 if (t == 0 || *t == 0)
6278 xtrace_reset ();
6279 else
6280 {
6281 fd = (int)strtol (t, &e, 10);
6282 if (e != t && *e == '\0' && sh_validfd (fd))
6283 {
6284 fp = fdopen (fd, "w");
6285 if (fp == 0)
6286 internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
6287 else
6288 xtrace_set (fd, fp);
6289 }
6290 else
6291 internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
6292 }
6293}
ac50fbac
CR
6294
6295#define MIN_COMPAT_LEVEL 31
6296
6297void
6298sv_shcompat (name)
6299 char *name;
6300{
6301 SHELL_VAR *v;
6302 char *val;
6303 int tens, ones, compatval;
6304
6305 v = find_variable (name);
6306 if (v == 0)
6307 {
6308 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6309 set_compatibility_opts ();
6310 return;
6311 }
6312 val = value_cell (v);
6313 if (val == 0 || *val == '\0')
6314 {
6315 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6316 set_compatibility_opts ();
6317 return;
6318 }
6319 /* Handle decimal-like compatibility version specifications: 4.2 */
a0c0a00f 6320 if (ISDIGIT (val[0]) && val[1] == '.' && ISDIGIT (val[2]) && val[3] == 0)
ac50fbac
CR
6321 {
6322 tens = val[0] - '0';
6323 ones = val[2] - '0';
6324 compatval = tens*10 + ones;
6325 }
6326 /* Handle integer-like compatibility version specifications: 42 */
a0c0a00f 6327 else if (ISDIGIT (val[0]) && ISDIGIT (val[1]) && val[2] == 0)
ac50fbac
CR
6328 {
6329 tens = val[0] - '0';
6330 ones = val[1] - '0';
6331 compatval = tens*10 + ones;
6332 }
6333 else
6334 {
6335compat_error:
6336 internal_error (_("%s: %s: compatibility value out of range"), name, val);
6337 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6338 set_compatibility_opts ();
6339 return;
6340 }
6341
6342 if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL)
6343 goto compat_error;
6344
6345 shell_compatibility_level = compatval;
6346 set_compatibility_opts ();
6347}
6348
6349#if defined (JOB_CONTROL)
6350void
6351sv_childmax (name)
6352 char *name;
6353{
6354 char *tt;
6355 int s;
6356
6357 tt = get_string_value (name);
6358 s = (tt && *tt) ? atoi (tt) : 0;
6359 set_maxchild (s);
6360}
6361#endif