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