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