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