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