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