]> git.ipfire.org Git - thirdparty/bash.git/blame - variables.c
Initial devel branch import from bash-3.0-alpha
[thirdparty/bash.git] / variables.c
CommitLineData
726f6388
JA
1/* variables.c -- Functions for hacking shell variables. */
2
d3a24ed2 3/* Copyright (C) 1987-2003 Free Software Foundation, Inc.
726f6388
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
bb70624e 9 the Free Software Foundation; either version 2, or (at your option)
726f6388
JA
10 any later version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
bb70624e 19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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
d166f048
JA
27#if defined (qnx)
28# include <sys/vc.h>
29#endif
30
ccc6cda3
JA
31#if defined (HAVE_UNISTD_H)
32# include <unistd.h>
33#endif
34
35#include <stdio.h>
f73dda09 36#include "chartypes.h"
726f6388 37#include <pwd.h>
726f6388 38#include "bashansi.h"
ccc6cda3 39
726f6388 40#include "shell.h"
726f6388
JA
41#include "flags.h"
42#include "execute_cmd.h"
cce855bc 43#include "findcmd.h"
ccc6cda3
JA
44#include "mailcheck.h"
45#include "input.h"
f73dda09
JA
46#include "hashcmd.h"
47#include "pathexp.h"
726f6388 48
d166f048 49#include "builtins/getopt.h"
726f6388 50#include "builtins/common.h"
cce855bc
JA
51
52#if defined (READLINE)
53# include "bashline.h"
54# include <readline/readline.h>
55#else
56# include <tilde/tilde.h>
57#endif
726f6388 58
ccc6cda3
JA
59#if defined (HISTORY)
60# include "bashhist.h"
cce855bc 61# include <readline/history.h>
ccc6cda3
JA
62#endif /* HISTORY */
63
bb70624e
JA
64#if defined (PROGRAMMABLE_COMPLETION)
65# include "pcomplete.h"
66#endif
67
7117c2d2
JA
68#define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
69
70#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
71
726f6388
JA
72/* Variables used here and defined in other files. */
73extern int posixly_correct;
f73dda09 74extern int line_number;
d3a24ed2 75extern int subshell_environment, indirection_level, subshell_level;
ccc6cda3 76extern int build_version, patch_level;
d3a24ed2 77extern int expanding_redir;
ccc6cda3 78extern char *dist_version, *release_status;
726f6388
JA
79extern char *shell_name;
80extern char *primary_prompt, *secondary_prompt;
ccc6cda3 81extern char *current_host_name;
f73dda09 82extern sh_builtin_func_t *this_shell_builtin;
bb70624e 83extern SHELL_VAR *this_shell_function;
d3a24ed2 84extern char *the_printed_command_except_trap;
ccc6cda3 85extern char *this_command_name;
d3a24ed2 86extern char *command_execution_string;
726f6388
JA
87extern time_t shell_start_time;
88
d3a24ed2
CR
89#if defined (READLINE)
90extern int perform_hostname_completion;
91#endif
92
7117c2d2
JA
93/* The list of shell variables that the user has created at the global
94 scope, or that came from the environment. */
95VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
96
97/* The current list of shell variables, including function scopes */
98VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
726f6388
JA
99
100/* The list of shell functions that the user has created, or that came from
101 the environment. */
102HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
103
d3a24ed2
CR
104#if defined (DEBUGGER)
105/* The table of shell function definitions that the user defined or that
106 came from the environment. */
107HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
108#endif
109
726f6388
JA
110/* The current variable context. This is really a count of how deep into
111 executing functions we are. */
112int variable_context = 0;
113
7117c2d2 114/* The set of shell assignments which are made only in the environment
726f6388 115 for a single command. */
7117c2d2 116HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
726f6388
JA
117
118/* Some funky variables which are known about specially. Here is where
119 "$*", "$1", and all the cruft is kept. */
120char *dollar_vars[10];
121WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
122
123/* The value of $$. */
f73dda09 124pid_t dollar_dollar_pid;
726f6388
JA
125
126/* An array which is passed to commands as their environment. It is
d166f048 127 manufactured from the union of the initial environment and the
726f6388
JA
128 shell variables that are marked for export. */
129char **export_env = (char **)NULL;
d166f048
JA
130static int export_env_index;
131static int export_env_size;
726f6388
JA
132
133/* Non-zero means that we have to remake EXPORT_ENV. */
134int array_needs_making = 1;
135
ccc6cda3
JA
136/* The number of times BASH has been executed. This is set
137 by initialize_variables (). */
138int shell_level = 0;
726f6388 139
726f6388 140/* Some forward declarations. */
f73dda09
JA
141static void set_machine_vars __P((void));
142static void set_home_var __P((void));
143static void set_shell_var __P((void));
144static char *get_bash_name __P((void));
145static void initialize_shell_level __P((void));
146static void uidset __P((void));
147#if defined (ARRAY_VARS)
148static void make_vers_array __P((void));
149#endif
f73dda09 150
7117c2d2
JA
151static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
152#if defined (ARRAY_VARS)
153static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
154#endif
d3a24ed2
CR
155static SHELL_VAR *get_self __P((SHELL_VAR *));
156
157#if defined (ARRAY_VARS)
158static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
159#endif
7117c2d2
JA
160
161static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
162static SHELL_VAR *get_seconds __P((SHELL_VAR *));
163static SHELL_VAR *init_seconds_var __P((void));
164
165static int brand __P((void));
f73dda09 166static void sbrand __P((unsigned long)); /* set bash random number generator. */
7117c2d2
JA
167static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
168static SHELL_VAR *get_random __P((SHELL_VAR *));
f73dda09 169
7117c2d2
JA
170static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
171static SHELL_VAR *get_lineno __P((SHELL_VAR *));
f73dda09 172
d3a24ed2
CR
173static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
174static SHELL_VAR *get_subshell __P((SHELL_VAR *));
175
7117c2d2
JA
176#if defined (HISTORY)
177static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
178#endif
179
180#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
181static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
182static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
7117c2d2
JA
183#endif
184
185#if defined (ARRAY_VARS)
186static SHELL_VAR *get_groupset __P((SHELL_VAR *));
7117c2d2
JA
187#endif
188
189static SHELL_VAR *get_funcname __P((SHELL_VAR *));
190static SHELL_VAR *init_funcname_var __P((void));
191
192static void initialize_dynamic_variables __P((void));
193
194static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
f73dda09 195static SHELL_VAR *new_shell_variable __P((const char *));
7117c2d2
JA
196static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
197static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int));
198
199static void free_variable_hash_data __P((PTR_T));
200
201static VARLIST *vlist_alloc __P((int));
202static VARLIST *vlist_realloc __P((VARLIST *, int));
203static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
204
205static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
206
207static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
f73dda09 208
7117c2d2
JA
209static SHELL_VAR **vapply __P((sh_var_map_func_t *));
210static SHELL_VAR **fapply __P((sh_var_map_func_t *));
f73dda09
JA
211
212static int visible_var __P((SHELL_VAR *));
f73dda09 213static int visible_and_exported __P((SHELL_VAR *));
7117c2d2
JA
214static int local_and_exported __P((SHELL_VAR *));
215static int variable_in_context __P((SHELL_VAR *));
f73dda09
JA
216#if defined (ARRAY_VARS)
217static int visible_array_vars __P((SHELL_VAR *));
218#endif
219
7117c2d2
JA
220static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
221static void push_temp_var __P((PTR_T));
222static void propagate_temp_var __P((PTR_T));
223static void dispose_temporary_env __P((sh_free_func_t *));
224
f73dda09 225static inline char *mk_env_string __P((const char *, const char *));
7117c2d2
JA
226static char **make_env_array_from_var_list __P((SHELL_VAR **));
227static char **make_var_export_array __P((VAR_CONTEXT *));
228static char **make_func_export_array __P((void));
229static void add_temp_array_to_env __P((char **, int, int));
f73dda09 230
7117c2d2
JA
231static int n_shell_variables __P((void));
232static int set_context __P((SHELL_VAR *));
726f6388 233
7117c2d2
JA
234static void push_func_var __P((PTR_T));
235static void push_exported_var __P((PTR_T));
726f6388 236
7117c2d2
JA
237static inline int find_special_var __P((const char *));
238
cce855bc
JA
239/* Initialize the shell variables from the current environment.
240 If PRIVMODE is nonzero, don't import functions from ENV or
241 parse $SHELLOPTS. */
726f6388 242void
cce855bc 243initialize_shell_variables (env, privmode)
726f6388 244 char **env;
cce855bc 245 int privmode;
726f6388 246{
ccc6cda3
JA
247 char *name, *string, *temp_string;
248 int c, char_index, string_index, string_length;
726f6388
JA
249 SHELL_VAR *temp_var;
250
cce855bc 251 if (shell_variables == 0)
7117c2d2
JA
252 {
253 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
254 shell_variables->scope = 0;
255 shell_variables->table = hash_create (0);
256 }
726f6388 257
cce855bc 258 if (shell_functions == 0)
7117c2d2 259 shell_functions = hash_create (0);
726f6388 260
d3a24ed2
CR
261#if defined (DEBUGGER)
262 if (shell_function_defs == 0)
263 shell_function_defs = hash_create (0);
264#endif
265
ccc6cda3 266 for (string_index = 0; string = env[string_index++]; )
726f6388 267 {
726f6388 268 char_index = 0;
d166f048 269 name = string;
726f6388 270 while ((c = *string++) && c != '=')
d166f048
JA
271 ;
272 if (string[-1] == '=')
28ef6c31 273 char_index = string - name - 1;
726f6388 274
d166f048
JA
275 /* If there are weird things in the environment, like `=xxx' or a
276 string without an `=', just skip them. */
277 if (char_index == 0)
28ef6c31 278 continue;
d166f048
JA
279
280 /* ASSERT(name[char_index] == '=') */
726f6388 281 name[char_index] = '\0';
d166f048 282 /* Now, name = env variable name, string = env variable value, and
28ef6c31 283 char_index == strlen (name) */
726f6388 284
f73dda09 285 /* If exported function, define it now. Don't import functions from
7117c2d2 286 the environment in privileged mode. */
bb70624e 287 if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
726f6388 288 {
d166f048 289 string_length = strlen (string);
f73dda09 290 temp_string = (char *)xmalloc (3 + string_length + char_index);
bb70624e 291
d166f048
JA
292 strcpy (temp_string, name);
293 temp_string[char_index] = ' ';
294 strcpy (temp_string + char_index + 1, string);
726f6388 295
d166f048 296 parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
726f6388 297
d166f048
JA
298 /* Ancient backwards compatibility. Old versions of bash exported
299 functions like name()=() {...} */
300 if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
726f6388
JA
301 name[char_index - 2] = '\0';
302
ccc6cda3 303 if (temp_var = find_function (name))
726f6388 304 {
bb70624e 305 VSETATTR (temp_var, (att_exported|att_imported));
726f6388
JA
306 array_needs_making = 1;
307 }
308 else
309 report_error ("error importing function definition for `%s'", name);
d166f048 310
bb70624e 311 /* ( */
d166f048 312 if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
bb70624e 313 name[char_index - 2] = '('; /* ) */
726f6388 314 }
ccc6cda3
JA
315#if defined (ARRAY_VARS)
316# if 0
317 /* Array variables may not yet be exported. */
7117c2d2 318 else if (*string == '(' && string[1] == '[' && xstrchr (string, ')'))
ccc6cda3
JA
319 {
320 string_length = 1;
321 temp_string = extract_array_assignment_list (string, &string_length);
322 temp_var = assign_array_from_string (name, temp_string);
323 FREE (temp_string);
bb70624e 324 VSETATTR (temp_var, (att_exported | att_imported));
ccc6cda3
JA
325 array_needs_making = 1;
326 }
327# endif
328#endif
726f6388
JA
329 else
330 {
ccc6cda3 331 temp_var = bind_variable (name, string);
bb70624e 332 VSETATTR (temp_var, (att_exported | att_imported));
726f6388
JA
333 array_needs_making = 1;
334 }
d166f048
JA
335
336 name[char_index] = '=';
bb70624e 337 /* temp_var can be NULL if it was an exported function with a syntax
28ef6c31 338 error (a different bug, but it still shouldn't dump core). */
bb70624e
JA
339 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
340 {
341 CACHE_IMPORTSTR (temp_var, name);
342 }
726f6388
JA
343 }
344
28ef6c31 345 set_pwd ();
b72432fd 346
ccc6cda3
JA
347 /* Set up initial value of $_ */
348 temp_var = bind_variable ("_", dollar_vars[0]);
349
726f6388 350 /* Remember this pid. */
f73dda09 351 dollar_dollar_pid = getpid ();
726f6388
JA
352
353 /* Now make our own defaults in case the vars that we think are
354 important are missing. */
355 temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
f73dda09
JA
356#if 0
357 set_auto_export (temp_var); /* XXX */
358#endif
726f6388
JA
359
360 temp_var = set_if_not ("TERM", "dumb");
f73dda09
JA
361#if 0
362 set_auto_export (temp_var); /* XXX */
363#endif
726f6388 364
d166f048
JA
365#if defined (qnx)
366 /* set node id -- don't import it from the environment */
367 {
368 char node_name[22];
369 qnx_nidtostr (getnid (), node_name, sizeof (node_name));
370 temp_var = bind_variable ("NODE", node_name);
371 set_auto_export (temp_var);
372 }
373#endif
374
ccc6cda3 375 /* set up the prompts. */
726f6388
JA
376 if (interactive_shell)
377 {
b72432fd 378#if defined (PROMPT_STRING_DECODE)
726f6388 379 set_if_not ("PS1", primary_prompt);
b72432fd
JA
380#else
381 if (current_user.uid == -1)
382 get_current_user_info ();
383 set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
384#endif
726f6388
JA
385 set_if_not ("PS2", secondary_prompt);
386 }
387 set_if_not ("PS4", "+ ");
388
ccc6cda3
JA
389 /* Don't allow IFS to be imported from the environment. */
390 temp_var = bind_variable ("IFS", " \t\n");
7117c2d2 391 setifs (temp_var);
726f6388
JA
392
393 /* Magic machine types. Pretty convenient. */
f73dda09 394 set_machine_vars ();
726f6388 395
ccc6cda3
JA
396 /* Default MAILCHECK for interactive shells. Defer the creation of a
397 default MAILPATH until the startup files are read, because MAIL
f73dda09 398 names a mail file if MAILPATH is not set, and we should provide a
ccc6cda3 399 default only if neither is set. */
726f6388 400 if (interactive_shell)
f73dda09 401 set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
726f6388
JA
402
403 /* Do some things with shell level. */
d166f048 404 initialize_shell_level ();
726f6388 405
b72432fd 406 set_ppid ();
726f6388 407
726f6388
JA
408 /* Initialize the `getopts' stuff. */
409 bind_variable ("OPTIND", "1");
d166f048 410 getopts_reset (0);
726f6388 411 bind_variable ("OPTERR", "1");
d166f048
JA
412 sh_opterr = 1;
413
414 if (login_shell == 1)
415 set_home_var ();
726f6388
JA
416
417 /* Get the full pathname to THIS shell, and set the BASH variable
418 to it. */
d166f048 419 name = get_bash_name ();
ccc6cda3
JA
420 temp_var = bind_variable ("BASH", name);
421 free (name);
422
423 /* Make the exported environment variable SHELL be the user's login
424 shell. Note that the `tset' command looks at this variable
425 to determine what style of commands to output; if it ends in "csh",
426 then C-shell commands are output, else Bourne shell commands. */
d166f048 427 set_shell_var ();
726f6388
JA
428
429 /* Make a variable called BASH_VERSION which contains the version info. */
430 bind_variable ("BASH_VERSION", shell_version_string ());
ccc6cda3
JA
431#if defined (ARRAY_VARS)
432 make_vers_array ();
433#endif
726f6388 434
d3a24ed2
CR
435 if (command_execution_string)
436 bind_variable ("BASH_EXECUTION_STRING", command_execution_string);
437
726f6388
JA
438 /* Find out if we're supposed to be in Posix.2 mode via an
439 environment variable. */
440 temp_var = find_variable ("POSIXLY_CORRECT");
441 if (!temp_var)
442 temp_var = find_variable ("POSIX_PEDANTIC");
443 if (temp_var && imported_p (temp_var))
444 sv_strict_posix (temp_var->name);
445
446#if defined (HISTORY)
447 /* Set history variables to defaults, and then do whatever we would
448 do if the variable had just been set. Do this only in the case
449 that we are remembering commands on the history list. */
450 if (remember_on_history)
451 {
7117c2d2 452 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
726f6388
JA
453
454 set_if_not ("HISTFILE", name);
455 free (name);
456
457 set_if_not ("HISTSIZE", "500");
458 sv_histsize ("HISTSIZE");
459 }
460#endif /* HISTORY */
461
462 /* Seed the random number generator. */
f73dda09 463 sbrand (dollar_dollar_pid + shell_start_time);
726f6388
JA
464
465 /* Handle some "special" variables that we may have inherited from a
466 parent shell. */
d166f048
JA
467 if (interactive_shell)
468 {
469 temp_var = find_variable ("IGNOREEOF");
470 if (!temp_var)
471 temp_var = find_variable ("ignoreeof");
472 if (temp_var && imported_p (temp_var))
473 sv_ignoreeof (temp_var->name);
474 }
726f6388
JA
475
476#if defined (HISTORY)
477 if (interactive_shell && remember_on_history)
478 {
ccc6cda3
JA
479 sv_history_control ("HISTCONTROL");
480 sv_histignore ("HISTIGNORE");
726f6388
JA
481 }
482#endif /* HISTORY */
483
f73dda09
JA
484 /*
485 * 24 October 2001
486 *
487 * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
488 * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
489 * isnetconn() to avoid running the startup files more often than wanted.
490 * That will, of course, only work if the user's login shell is bash, so
491 * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
492 * in config-top.h.
493 */
494#if 0
bb70624e 495 temp_var = find_variable ("SSH_CLIENT");
28ef6c31
JA
496 if (temp_var && imported_p (temp_var))
497 {
498 VUNSETATTR (temp_var, att_exported);
499 array_needs_making = 1;
500 }
501 temp_var = find_variable ("SSH2_CLIENT");
bb70624e
JA
502 if (temp_var && imported_p (temp_var))
503 {
504 VUNSETATTR (temp_var, att_exported);
505 array_needs_making = 1;
506 }
f73dda09 507#endif
bb70624e 508
ccc6cda3
JA
509 /* Get the user's real and effective user ids. */
510 uidset ();
511
726f6388
JA
512 /* Initialize the dynamic variables, and seed their values. */
513 initialize_dynamic_variables ();
726f6388
JA
514}
515
7117c2d2
JA
516/* **************************************************************** */
517/* */
518/* Setting values for special shell variables */
519/* */
520/* **************************************************************** */
521
f73dda09
JA
522static void
523set_machine_vars ()
524{
525 SHELL_VAR *temp_var;
526
527 temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
528 temp_var = set_if_not ("OSTYPE", OSTYPE);
529 temp_var = set_if_not ("MACHTYPE", MACHTYPE);
530
531 temp_var = set_if_not ("HOSTNAME", current_host_name);
532}
533
d166f048
JA
534/* Set $HOME to the information in the password file if we didn't get
535 it from the environment. */
b72432fd
JA
536
537/* This function is not static so the tilde and readline libraries can
538 use it. */
539char *
28ef6c31 540sh_get_home_dir ()
b72432fd
JA
541{
542 if (current_user.home_dir == 0)
543 get_current_user_info ();
544 return current_user.home_dir;
545}
546
d166f048
JA
547static void
548set_home_var ()
549{
550 SHELL_VAR *temp_var;
551
552 temp_var = find_variable ("HOME");
553 if (temp_var == 0)
28ef6c31 554 temp_var = bind_variable ("HOME", sh_get_home_dir ());
f73dda09 555#if 0
bb70624e 556 VSETATTR (temp_var, att_exported);
f73dda09 557#endif
d166f048
JA
558}
559
560/* Set $SHELL to the user's login shell if it is not already set. Call
561 get_current_user_info if we haven't already fetched the shell. */
562static void
563set_shell_var ()
564{
565 SHELL_VAR *temp_var;
566
567 temp_var = find_variable ("SHELL");
568 if (temp_var == 0)
569 {
570 if (current_user.shell == 0)
571 get_current_user_info ();
572 temp_var = bind_variable ("SHELL", current_user.shell);
573 }
f73dda09 574#if 0
bb70624e 575 VSETATTR (temp_var, att_exported);
f73dda09 576#endif
d166f048
JA
577}
578
579static char *
580get_bash_name ()
581{
582 char *name;
583
28ef6c31 584 if ((login_shell == 1) && RELPATH(shell_name))
d166f048
JA
585 {
586 if (current_user.shell == 0)
28ef6c31 587 get_current_user_info ();
d166f048
JA
588 name = savestring (current_user.shell);
589 }
28ef6c31 590 else if (ABSPATH(shell_name))
d166f048
JA
591 name = savestring (shell_name);
592 else if (shell_name[0] == '.' && shell_name[1] == '/')
593 {
594 /* Fast path for common case. */
595 char *cdir;
596 int len;
597
598 cdir = get_string_value ("PWD");
28ef6c31
JA
599 if (cdir)
600 {
601 len = strlen (cdir);
f73dda09 602 name = (char *)xmalloc (len + strlen (shell_name) + 1);
28ef6c31
JA
603 strcpy (name, cdir);
604 strcpy (name + len, shell_name + 1);
605 }
606 else
607 name = savestring (shell_name);
d166f048
JA
608 }
609 else
610 {
611 char *tname;
612 int s;
613
614 tname = find_user_command (shell_name);
615
616 if (tname == 0)
617 {
618 /* Try the current directory. If there is not an executable
619 there, just punt and use the login shell. */
620 s = file_status (shell_name);
621 if (s & FS_EXECABLE)
622 {
623 tname = make_absolute (shell_name, get_string_value ("PWD"));
624 if (*shell_name == '.')
625 {
28ef6c31 626 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
d166f048
JA
627 if (name == 0)
628 name = tname;
629 else
630 free (tname);
631 }
632 else
633 name = tname;
634 }
635 else
636 {
637 if (current_user.shell == 0)
638 get_current_user_info ();
639 name = savestring (current_user.shell);
640 }
641 }
642 else
643 {
644 name = full_pathname (tname);
645 free (tname);
646 }
647 }
648
649 return (name);
650}
651
726f6388
JA
652void
653adjust_shell_level (change)
654 int change;
655{
d166f048 656 char new_level[5], *old_SHLVL;
7117c2d2 657 intmax_t old_level;
d166f048 658 SHELL_VAR *temp_var;
726f6388
JA
659
660 old_SHLVL = get_string_value ("SHLVL");
f73dda09
JA
661 if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
662 old_level = 0;
726f6388
JA
663
664 shell_level = old_level + change;
665 if (shell_level < 0)
666 shell_level = 0;
d166f048
JA
667 else if (shell_level > 1000)
668 {
cce855bc 669 internal_warning ("shell level (%d) too high, resetting to 1", shell_level);
d166f048
JA
670 shell_level = 1;
671 }
672
673 /* We don't need the full generality of itos here. */
674 if (shell_level < 10)
675 {
676 new_level[0] = shell_level + '0';
677 new_level[1] = '\0';
678 }
679 else if (shell_level < 100)
680 {
681 new_level[0] = (shell_level / 10) + '0';
682 new_level[1] = (shell_level % 10) + '0';
683 new_level[2] = '\0';
684 }
685 else if (shell_level < 1000)
686 {
687 new_level[0] = (shell_level / 100) + '0';
688 old_level = shell_level % 100;
689 new_level[1] = (old_level / 10) + '0';
690 new_level[2] = (old_level % 10) + '0';
691 new_level[3] = '\0';
692 }
693
694 temp_var = bind_variable ("SHLVL", new_level);
695 set_auto_export (temp_var);
696}
697
698static void
699initialize_shell_level ()
700{
d166f048 701 adjust_shell_level (1);
726f6388
JA
702}
703
28ef6c31
JA
704/* If we got PWD from the environment, update our idea of the current
705 working directory. In any case, make sure that PWD exists before
706 checking it. It is possible for getcwd () to fail on shell startup,
707 and in that case, PWD would be undefined. If this is an interactive
708 login shell, see if $HOME is the current working directory, and if
709 that's not the same string as $PWD, set PWD=$HOME. */
710
711void
712set_pwd ()
713{
714 SHELL_VAR *temp_var, *home_var;
715 char *temp_string, *home_string;
716
717 home_var = find_variable ("HOME");
718 home_string = home_var ? value_cell (home_var) : (char *)NULL;
719
720 temp_var = find_variable ("PWD");
721 if (temp_var && imported_p (temp_var) &&
722 (temp_string = value_cell (temp_var)) &&
723 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
724 set_working_directory (temp_string);
725 else if (home_string && interactive_shell && login_shell &&
726 same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
727 {
728 set_working_directory (home_string);
729 temp_var = bind_variable ("PWD", home_string);
730 set_auto_export (temp_var);
731 }
732 else
733 {
734 temp_string = get_working_directory ("shell-init");
735 if (temp_string)
736 {
737 temp_var = bind_variable ("PWD", temp_string);
738 set_auto_export (temp_var);
739 free (temp_string);
740 }
741 }
742
743 /* According to the Single Unix Specification, v2, $OLDPWD is an
744 `environment variable' and therefore should be auto-exported.
745 Make a dummy invisible variable for OLDPWD, and mark it as exported. */
746 temp_var = bind_variable ("OLDPWD", (char *)NULL);
747 VSETATTR (temp_var, (att_exported | att_invisible));
748}
749
b72432fd
JA
750/* Make a variable $PPID, which holds the pid of the shell's parent. */
751void
752set_ppid ()
753{
f73dda09 754 char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
b72432fd
JA
755 SHELL_VAR *temp_var;
756
f73dda09 757 name = inttostr (getppid (), namebuf, sizeof(namebuf));
b72432fd
JA
758 temp_var = find_variable ("PPID");
759 if (temp_var)
bb70624e 760 VUNSETATTR (temp_var, (att_readonly | att_exported));
b72432fd 761 temp_var = bind_variable ("PPID", name);
bb70624e 762 VSETATTR (temp_var, (att_readonly | att_integer));
b72432fd
JA
763}
764
ccc6cda3
JA
765static void
766uidset ()
726f6388 767{
f73dda09 768 char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
ccc6cda3
JA
769 register SHELL_VAR *v;
770
b72432fd 771 b = inttostr (current_user.uid, buff, sizeof (buff));
ccc6cda3 772 v = find_variable ("UID");
28ef6c31
JA
773 if (v == 0)
774 {
775 v = bind_variable ("UID", b);
776 VSETATTR (v, (att_readonly | att_integer));
777 }
726f6388 778
ccc6cda3 779 if (current_user.euid != current_user.uid)
b72432fd 780 b = inttostr (current_user.euid, buff, sizeof (buff));
726f6388 781
ccc6cda3 782 v = find_variable ("EUID");
28ef6c31
JA
783 if (v == 0)
784 {
785 v = bind_variable ("EUID", b);
786 VSETATTR (v, (att_readonly | att_integer));
787 }
ccc6cda3
JA
788}
789
790#if defined (ARRAY_VARS)
791static void
792make_vers_array ()
793{
794 SHELL_VAR *vv;
795 ARRAY *av;
f73dda09 796 char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
ccc6cda3 797
7117c2d2 798 unbind_variable ("BASH_VERSINFO");
ccc6cda3
JA
799
800 vv = make_new_array_variable ("BASH_VERSINFO");
801 av = array_cell (vv);
802 strcpy (d, dist_version);
7117c2d2 803 s = xstrchr (d, '.');
ccc6cda3
JA
804 if (s)
805 *s++ = '\0';
7117c2d2
JA
806 array_insert (av, 0, d);
807 array_insert (av, 1, s);
f73dda09 808 s = inttostr (patch_level, b, sizeof (b));
7117c2d2 809 array_insert (av, 2, s);
f73dda09 810 s = inttostr (build_version, b, sizeof (b));
7117c2d2
JA
811 array_insert (av, 3, s);
812 array_insert (av, 4, release_status);
813 array_insert (av, 5, MACHTYPE);
ccc6cda3 814
bb70624e 815 VSETATTR (vv, att_readonly);
ccc6cda3
JA
816}
817#endif /* ARRAY_VARS */
818
819/* Set the environment variables $LINES and $COLUMNS in response to
820 a window size change. */
821void
28ef6c31 822sh_set_lines_and_columns (lines, cols)
ccc6cda3
JA
823 int lines, cols;
824{
f73dda09 825 char val[INT_STRLEN_BOUND(int) + 1], *v;
ccc6cda3 826
b72432fd
JA
827 v = inttostr (lines, val, sizeof (val));
828 bind_variable ("LINES", v);
ccc6cda3 829
b72432fd
JA
830 v = inttostr (cols, val, sizeof (val));
831 bind_variable ("COLUMNS", v);
726f6388
JA
832}
833
7117c2d2
JA
834/* **************************************************************** */
835/* */
836/* Printing variables and values */
837/* */
838/* **************************************************************** */
726f6388 839
28ef6c31
JA
840/* Print LIST (a list of shell variables) to stdout in such a way that
841 they can be read back in. */
726f6388
JA
842void
843print_var_list (list)
844 register SHELL_VAR **list;
845{
846 register int i;
847 register SHELL_VAR *var;
848
849 for (i = 0; list && (var = list[i]); i++)
7117c2d2 850 if (invisible_p (var) == 0)
726f6388
JA
851 print_assignment (var);
852}
853
28ef6c31
JA
854/* Print LIST (a list of shell functions) to stdout in such a way that
855 they can be read back in. */
856void
857print_func_list (list)
858 register SHELL_VAR **list;
859{
860 register int i;
861 register SHELL_VAR *var;
862
863 for (i = 0; list && (var = list[i]); i++)
864 {
865 printf ("%s ", var->name);
866 print_var_function (var);
867 printf ("\n");
868 }
869}
870
726f6388
JA
871/* Print the value of a single SHELL_VAR. No newline is
872 output, but the variable is printed in such a way that
873 it can be read back in. */
874void
875print_assignment (var)
876 SHELL_VAR *var;
877{
7117c2d2
JA
878 if (var_isset (var) == 0)
879 return;
880
881 if (function_p (var))
726f6388 882 {
28ef6c31 883 printf ("%s", var->name);
726f6388
JA
884 print_var_function (var);
885 printf ("\n");
886 }
ccc6cda3 887#if defined (ARRAY_VARS)
7117c2d2 888 else if (array_p (var))
ccc6cda3
JA
889 print_array_assignment (var, 0);
890#endif /* ARRAY_VARS */
7117c2d2 891 else
726f6388
JA
892 {
893 printf ("%s=", var->name);
ccc6cda3 894 print_var_value (var, 1);
726f6388
JA
895 printf ("\n");
896 }
897}
898
899/* Print the value cell of VAR, a shell variable. Do not print
ccc6cda3
JA
900 the name, nor leading/trailing newline. If QUOTE is non-zero,
901 and the value contains shell metacharacters, quote the value
902 in such a way that it can be read back in. */
726f6388 903void
ccc6cda3 904print_var_value (var, quote)
726f6388 905 SHELL_VAR *var;
ccc6cda3 906 int quote;
726f6388 907{
ccc6cda3
JA
908 char *t;
909
7117c2d2
JA
910 if (var_isset (var) == 0)
911 return;
912
913 if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
ccc6cda3 914 {
7117c2d2
JA
915 t = ansic_quote (value_cell (var), 0, (int *)0);
916 printf ("%s", t);
917 free (t);
918 }
919 else if (quote && sh_contains_shell_metas (value_cell (var)))
920 {
921 t = sh_single_quote (value_cell (var));
922 printf ("%s", t);
923 free (t);
ccc6cda3 924 }
7117c2d2
JA
925 else
926 printf ("%s", value_cell (var));
726f6388
JA
927}
928
929/* Print the function cell of VAR, a shell variable. Do not
930 print the name, nor leading/trailing newline. */
931void
932print_var_function (var)
933 SHELL_VAR *var;
934{
7117c2d2 935 if (function_p (var) && var_isset (var))
726f6388
JA
936 printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
937}
938
939/* **************************************************************** */
ccc6cda3 940/* */
7117c2d2 941/* Dynamic Variables */
ccc6cda3 942/* */
726f6388
JA
943/* **************************************************************** */
944
945/* DYNAMIC VARIABLES
ccc6cda3 946
726f6388
JA
947 These are variables whose values are generated anew each time they are
948 referenced. These are implemented using a pair of function pointers
7117c2d2
JA
949 in the struct variable: assign_func, which is called from bind_variable
950 and, if arrays are compiled into the shell, some of the functions in
951 arrayfunc.c, and dynamic_value, which is called from find_variable.
952
953 assign_func is called from bind_variable_internal, if
954 bind_variable_internal discovers that the variable being assigned to
955 has such a function. The function is called as
956 SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
726f6388 957 and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
7117c2d2
JA
958 is usually ENTRY (self). IND is an index for an array variable, and
959 unused otherwise.
ccc6cda3 960
7117c2d2
JA
961 dynamic_value is called from find_variable_internal to return a `new'
962 value for the specified dynamic varible. If this function is NULL,
963 the variable is treated as a `normal' shell variable. If it is not,
964 however, then this function is called like this:
965 tempvar = (*(var->dynamic_value)) (var);
ccc6cda3 966
726f6388
JA
967 Sometimes `tempvar' will replace the value of `var'. Other times, the
968 shell will simply use the string value. Pretty object-oriented, huh?
ccc6cda3 969
726f6388
JA
970 Be warned, though: if you `unset' a special variable, it loses its
971 special meaning, even if you subsequently set it.
ccc6cda3 972
726f6388 973 The special assignment code would probably have been better put in
7117c2d2 974 subst.c: do_assignment_internal, in the same style as
726f6388
JA
975 stupidly_hack_special_variables, but I wanted the changes as
976 localized as possible. */
977
f73dda09
JA
978#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
979 do \
980 { \
981 v = bind_variable (var, (val)); \
982 v->dynamic_value = gfunc; \
983 v->assign_func = afunc; \
984 } \
985 while (0)
986
987#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
988 do \
989 { \
990 v = make_new_array_variable (var); \
991 v->dynamic_value = gfunc; \
992 v->assign_func = afunc; \
993 } \
994 while (0)
995
bb70624e 996static SHELL_VAR *
7117c2d2 997null_assign (self, value, unused)
bb70624e
JA
998 SHELL_VAR *self;
999 char *value;
7117c2d2 1000 arrayind_t unused;
bb70624e
JA
1001{
1002 return (self);
1003}
1004
1005#if defined (ARRAY_VARS)
1006static SHELL_VAR *
7117c2d2 1007null_array_assign (self, value, ind)
bb70624e 1008 SHELL_VAR *self;
bb70624e 1009 char *value;
7117c2d2 1010 arrayind_t ind;
bb70624e
JA
1011{
1012 return (self);
1013}
1014#endif
1015
d3a24ed2
CR
1016/* Degenerate `dynamic_value' function; just returns what's passed without
1017 manipulation. */
1018static SHELL_VAR *
1019get_self (self)
1020 SHELL_VAR *self;
1021{
1022 return (self);
1023}
1024
1025#if defined (ARRAY_VARS)
1026/* A generic dynamic array variable initializer. Intialize array variable
1027 NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1028static SHELL_VAR *
1029init_dynamic_array_var (name, getfunc, setfunc, attrs)
1030 char *name;
1031 sh_var_value_func_t *getfunc;
1032 sh_var_assign_func_t *setfunc;
1033 int attrs;
1034{
1035 SHELL_VAR *v;
1036
1037 v = find_variable (name);
1038 if (v)
1039 return (v);
1040 INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1041 if (attrs)
1042 VSETATTR (v, attrs);
1043 return v;
1044}
1045#endif
1046
1047
726f6388
JA
1048/* The value of $SECONDS. This is the number of seconds since shell
1049 invocation, or, the number of seconds since the last assignment + the
1050 value of the last assignment. */
7117c2d2 1051static intmax_t seconds_value_assigned;
726f6388
JA
1052
1053static SHELL_VAR *
7117c2d2 1054assign_seconds (self, value, unused)
726f6388
JA
1055 SHELL_VAR *self;
1056 char *value;
7117c2d2 1057 arrayind_t unused;
726f6388 1058{
f73dda09
JA
1059 if (legal_number (value, &seconds_value_assigned) == 0)
1060 seconds_value_assigned = 0;
726f6388
JA
1061 shell_start_time = NOW;
1062 return (self);
1063}
1064
1065static SHELL_VAR *
1066get_seconds (var)
1067 SHELL_VAR *var;
1068{
1069 time_t time_since_start;
1070 char *p;
1071
1072 time_since_start = NOW - shell_start_time;
f73dda09 1073 p = itos(seconds_value_assigned + time_since_start);
726f6388 1074
7117c2d2 1075 FREE (value_cell (var));
726f6388 1076
bb70624e 1077 VSETATTR (var, att_integer);
7117c2d2 1078 var_setvalue (var, p);
726f6388
JA
1079 return (var);
1080}
1081
f73dda09
JA
1082static SHELL_VAR *
1083init_seconds_var ()
1084{
1085 SHELL_VAR *v;
1086
1087 v = find_variable ("SECONDS");
1088 if (v)
1089 {
1090 if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1091 seconds_value_assigned = 0;
1092 }
7117c2d2 1093 INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
f73dda09
JA
1094 return v;
1095}
1096
726f6388
JA
1097/* The random number seed. You can change this by setting RANDOM. */
1098static unsigned long rseed = 1;
f73dda09 1099static int last_random_value;
726f6388 1100
f73dda09 1101/* A linear congruential random number generator based on the example
7117c2d2 1102 one in the ANSI C standard. This one isn't very good, but a more
f73dda09 1103 complicated one is overkill. */
726f6388
JA
1104
1105/* Returns a pseudo-random number between 0 and 32767. */
1106static int
1107brand ()
1108{
1109 rseed = rseed * 1103515245 + 12345;
f73dda09 1110 return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
726f6388
JA
1111}
1112
1113/* Set the random number generator seed to SEED. */
1114static void
1115sbrand (seed)
f73dda09 1116 unsigned long seed;
726f6388
JA
1117{
1118 rseed = seed;
e8ce775d 1119 last_random_value = 0;
726f6388
JA
1120}
1121
1122static SHELL_VAR *
7117c2d2 1123assign_random (self, value, unused)
726f6388
JA
1124 SHELL_VAR *self;
1125 char *value;
7117c2d2 1126 arrayind_t unused;
726f6388 1127{
f73dda09 1128 sbrand (strtoul (value, (char **)NULL, 10));
726f6388
JA
1129 return (self);
1130}
1131
28ef6c31
JA
1132int
1133get_random_number ()
726f6388
JA
1134{
1135 int rv;
726f6388 1136
ccc6cda3
JA
1137 /* Reset for command and process substitution. */
1138 if (subshell_environment)
f73dda09 1139 sbrand (rseed + getpid() + NOW);
ccc6cda3
JA
1140
1141 do
1142 rv = brand ();
f73dda09 1143 while (rv == last_random_value);
28ef6c31
JA
1144 return rv;
1145}
ccc6cda3 1146
28ef6c31
JA
1147static SHELL_VAR *
1148get_random (var)
1149 SHELL_VAR *var;
1150{
1151 int rv;
1152 char *p;
1153
1154 rv = get_random_number ();
ccc6cda3 1155 last_random_value = rv;
f73dda09 1156 p = itos (rv);
726f6388 1157
7117c2d2 1158 FREE (value_cell (var));
726f6388 1159
bb70624e 1160 VSETATTR (var, att_integer);
7117c2d2 1161 var_setvalue (var, p);
726f6388
JA
1162 return (var);
1163}
1164
7117c2d2
JA
1165static SHELL_VAR *
1166assign_lineno (var, value, unused)
1167 SHELL_VAR *var;
1168 char *value;
1169 arrayind_t unused;
1170{
1171 intmax_t new_value;
1172
1173 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1174 new_value = 0;
1175 line_number = new_value;
1176 return var;
1177}
1178
726f6388
JA
1179/* Function which returns the current line number. */
1180static SHELL_VAR *
1181get_lineno (var)
1182 SHELL_VAR *var;
1183{
1184 char *p;
ccc6cda3 1185 int ln;
726f6388 1186
ccc6cda3
JA
1187 ln = executing_line_number ();
1188 p = itos (ln);
7117c2d2
JA
1189 FREE (value_cell (var));
1190 var_setvalue (var, p);
726f6388
JA
1191 return (var);
1192}
1193
d3a24ed2
CR
1194static SHELL_VAR *
1195assign_subshell (var, value, unused)
1196 SHELL_VAR *var;
1197 char *value;
1198 arrayind_t unused;
1199{
1200 intmax_t new_value;
1201
1202 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1203 new_value = 0;
1204 subshell_level = new_value;
1205 return var;
1206}
1207
1208static SHELL_VAR *
1209get_subshell (var)
1210 SHELL_VAR *var;
1211{
1212 char *p;
1213
1214 p = itos (subshell_level);
1215 FREE (value_cell (var));
1216 var_setvalue (var, p);
1217 return (var);
1218}
1219
1220static SHELL_VAR *
1221get_bash_command (var)
1222 SHELL_VAR *var;
1223{
1224 char *p;
1225
1226 p = savestring (the_printed_command_except_trap);
1227 FREE (value_cell (var));
1228 var_setvalue (var, p);
1229 return (var);
1230}
1231
726f6388
JA
1232#if defined (HISTORY)
1233static SHELL_VAR *
1234get_histcmd (var)
1235 SHELL_VAR *var;
1236{
1237 char *p;
1238
1239 p = itos (history_number ());
7117c2d2
JA
1240 FREE (value_cell (var));
1241 var_setvalue (var, p);
726f6388
JA
1242 return (var);
1243}
1244#endif
1245
d3a24ed2
CR
1246#if defined (READLINE)
1247/* When this function returns, VAR->value points to malloced memory. */
1248static SHELL_VAR *
1249get_comp_wordbreaks (var)
1250 SHELL_VAR *var;
1251{
1252 char *p;
1253
1254 /* If we don't have anything yet, assign a default value. */
1255 if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1256 enable_hostname_completion (perform_hostname_completion);
1257
1258#if 0
1259 FREE (value_cell (var));
1260 p = savestring (rl_completer_word_break_characters);
1261
1262 var_setvalue (var, p);
1263#else
1264 var_setvalue (var, rl_completer_word_break_characters);
1265#endif
1266
1267 return (var);
1268}
1269
1270/* When this function returns, rl_completer_word_break_characters points to
1271 malloced memory. */
1272static SHELL_VAR *
1273assign_comp_wordbreaks (self, value, unused)
1274 SHELL_VAR *self;
1275 char *value;
1276 arrayind_t unused;
1277{
1278 if (rl_completer_word_break_characters &&
1279 rl_completer_word_break_characters != rl_basic_word_break_characters)
1280 free (rl_completer_word_break_characters);
1281
1282 rl_completer_word_break_characters = savestring (value);
1283 return self;
1284}
1285#endif /* READLINE */
1286
ccc6cda3 1287#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
d3a24ed2 1288static SHELL_VAR *
7117c2d2
JA
1289assign_dirstack (self, value, ind)
1290 SHELL_VAR *self;
1291 char *value;
1292 arrayind_t ind;
1293{
1294 set_dirstack_element (ind, 1, value);
1295 return self;
1296}
1297
ccc6cda3
JA
1298static SHELL_VAR *
1299get_dirstack (self)
1300 SHELL_VAR *self;
1301{
1302 ARRAY *a;
1303 WORD_LIST *l;
1304
1305 l = get_directory_stack ();
7117c2d2
JA
1306 a = array_from_word_list (l);
1307 array_dispose (array_cell (self));
d166f048 1308 dispose_words (l);
7117c2d2 1309 var_setarray (self, a);
ccc6cda3
JA
1310 return self;
1311}
1312#endif /* PUSHD AND POPD && ARRAY_VARS */
1313
d166f048
JA
1314#if defined (ARRAY_VARS)
1315/* We don't want to initialize the group set with a call to getgroups()
1316 unless we're asked to, but we only want to do it once. */
1317static SHELL_VAR *
1318get_groupset (self)
1319 SHELL_VAR *self;
1320{
1321 register int i;
1322 int ng;
1323 ARRAY *a;
1324 static char **group_set = (char **)NULL;
1325
1326 if (group_set == 0)
1327 {
1328 group_set = get_group_list (&ng);
1329 a = array_cell (self);
1330 for (i = 0; i < ng; i++)
7117c2d2 1331 array_insert (a, i, group_set[i]);
d166f048
JA
1332 }
1333 return (self);
1334}
1335#endif /* ARRAY_VARS */
bb70624e 1336
d3a24ed2
CR
1337/* If ARRAY_VARS is not defined, this just returns the name of any
1338 currently-executing function. If we have arrays, it's a call stack. */
bb70624e
JA
1339static SHELL_VAR *
1340get_funcname (self)
1341 SHELL_VAR *self;
1342{
d3a24ed2 1343#if ! defined (ARRAY_VARS)
7117c2d2 1344 char *t;
bb70624e
JA
1345 if (variable_context && this_shell_function)
1346 {
7117c2d2
JA
1347 FREE (value_cell (self));
1348 t = savestring (this_shell_function->name);
1349 var_setvalue (self, t);
bb70624e 1350 }
d3a24ed2 1351#endif
bb70624e
JA
1352 return (self);
1353}
1354
1355void
1356make_funcname_visible (on_or_off)
1357 int on_or_off;
726f6388
JA
1358{
1359 SHELL_VAR *v;
1360
bb70624e
JA
1361 v = find_variable ("FUNCNAME");
1362 if (v == 0 || v->dynamic_value == 0)
1363 return;
1364
1365 if (on_or_off)
1366 VUNSETATTR (v, att_invisible);
1367 else
1368 VSETATTR (v, att_invisible);
1369}
1370
f73dda09
JA
1371static SHELL_VAR *
1372init_funcname_var ()
1373{
1374 SHELL_VAR *v;
bb70624e 1375
f73dda09
JA
1376 v = find_variable ("FUNCNAME");
1377 if (v)
1378 return v;
d3a24ed2
CR
1379#if defined (ARRAY_VARS)
1380 INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1381#else
f73dda09 1382 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
d3a24ed2 1383#endif
f73dda09
JA
1384 VSETATTR (v, att_invisible|att_noassign);
1385 return v;
1386}
726f6388 1387
bb70624e
JA
1388static void
1389initialize_dynamic_variables ()
1390{
1391 SHELL_VAR *v;
726f6388 1392
f73dda09
JA
1393 v = init_seconds_var ();
1394
d3a24ed2
CR
1395 INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1396 INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1397
bb70624e
JA
1398 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1399 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
726f6388
JA
1400
1401#if defined (HISTORY)
7117c2d2 1402 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
726f6388 1403#endif
ccc6cda3 1404
d3a24ed2
CR
1405#if defined (READLINE)
1406 INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1407#endif
1408
ccc6cda3 1409#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
d3a24ed2 1410 v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
ccc6cda3 1411#endif /* PUSHD_AND_POPD && ARRAY_VARS */
d166f048
JA
1412
1413#if defined (ARRAY_VARS)
d3a24ed2
CR
1414 v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1415
1416# if defined (DEBUGGER)
1417 v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, (att_invisible|att_noassign));
1418 v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, (att_invisible|att_noassign));
1419# endif /* DEBUGGER */
1420 v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, (att_invisible|att_noassign));
1421 v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, (att_invisible|att_noassign));
d166f048 1422#endif
bb70624e 1423
f73dda09 1424 v = init_funcname_var ();
726f6388
JA
1425}
1426
7117c2d2
JA
1427/* **************************************************************** */
1428/* */
1429/* Retrieving variables and values */
1430/* */
1431/* **************************************************************** */
1432
726f6388
JA
1433/* How to get a pointer to the shell variable or function named NAME.
1434 HASHED_VARS is a pointer to the hash table containing the list
1435 of interest (either variables or functions). */
7117c2d2
JA
1436
1437static SHELL_VAR *
1438hash_lookup (name, hashed_vars)
f73dda09 1439 const char *name;
726f6388
JA
1440 HASH_TABLE *hashed_vars;
1441{
1442 BUCKET_CONTENTS *bucket;
1443
7117c2d2 1444 bucket = hash_search (name, hashed_vars, 0);
ccc6cda3 1445 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
726f6388
JA
1446}
1447
7117c2d2
JA
1448SHELL_VAR *
1449var_lookup (name, vcontext)
1450 const char *name;
1451 VAR_CONTEXT *vcontext;
1452{
1453 VAR_CONTEXT *vc;
1454 SHELL_VAR *v;
1455
1456 v = (SHELL_VAR *)NULL;
1457 for (vc = vcontext; vc; vc = vc->down)
1458 if (v = hash_lookup (name, vc->table))
1459 break;
1460
1461 return v;
1462}
1463
726f6388 1464/* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
7117c2d2
JA
1465 then also search the temporarily built list of exported variables.
1466 The lookup order is:
1467 temporary_env
1468 shell_variables list
1469*/
1470
726f6388 1471SHELL_VAR *
d3a24ed2 1472find_variable_internal (name, force_tempenv)
f73dda09 1473 const char *name;
d3a24ed2 1474 int force_tempenv;
726f6388 1475{
28ef6c31 1476 SHELL_VAR *var;
d3a24ed2 1477 int search_tempenv;
28ef6c31
JA
1478
1479 var = (SHELL_VAR *)NULL;
726f6388
JA
1480
1481 /* If explicitly requested, first look in the temporary environment for
1482 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
1483 to get the `exported' value of $foo. This happens if we are executing
1484 a function or builtin, or if we are looking up a variable in a
1485 "subshell environment". */
d3a24ed2
CR
1486 search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1487
1488 if (search_tempenv && temporary_env)
7117c2d2 1489 var = hash_lookup (name, temporary_env);
726f6388 1490
7117c2d2 1491 if (var == 0)
726f6388
JA
1492 var = var_lookup (name, shell_variables);
1493
7117c2d2 1494 if (var == 0)
726f6388
JA
1495 return ((SHELL_VAR *)NULL);
1496
ccc6cda3 1497 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
726f6388
JA
1498}
1499
1500/* Look up the variable entry named NAME. Returns the entry or NULL. */
1501SHELL_VAR *
1502find_variable (name)
f73dda09 1503 const char *name;
726f6388 1504{
d3a24ed2 1505 return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
726f6388
JA
1506}
1507
1508/* Look up the function entry whose name matches STRING.
1509 Returns the entry or NULL. */
1510SHELL_VAR *
1511find_function (name)
f73dda09 1512 const char *name;
726f6388 1513{
7117c2d2
JA
1514 return (hash_lookup (name, shell_functions));
1515}
1516
d3a24ed2
CR
1517/* Find the function definition for the shell function named NAME. Returns
1518 the entry or NULL. */
1519FUNCTION_DEF *
1520find_function_def (name)
1521 const char *name;
1522{
1523 return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
1524}
1525
7117c2d2
JA
1526/* Return the value of VAR. VAR is assumed to have been the result of a
1527 lookup without any subscript, if arrays are compiled into the shell. */
1528char *
1529get_variable_value (var)
1530 SHELL_VAR *var;
1531{
1532 if (var == 0)
1533 return ((char *)NULL);
1534#if defined (ARRAY_VARS)
1535 else if (array_p (var))
1536 return (array_reference (array_cell (var), 0));
1537#endif
1538 else
1539 return (value_cell (var));
726f6388
JA
1540}
1541
1542/* Return the string value of a variable. Return NULL if the variable
7117c2d2
JA
1543 doesn't exist. Don't cons a new string. This is a potential memory
1544 leak if the variable is found in the temporary environment. Since
1545 functions and variables have separate name spaces, returns NULL if
1546 var_name is a shell function only. */
726f6388
JA
1547char *
1548get_string_value (var_name)
28ef6c31 1549 const char *var_name;
726f6388 1550{
d166f048
JA
1551 SHELL_VAR *var;
1552
f73dda09 1553 var = find_variable (var_name);
7117c2d2 1554 return ((var) ? get_variable_value (var) : (char *)NULL);
726f6388
JA
1555}
1556
b72432fd
JA
1557/* This is present for use by the tilde and readline libraries. */
1558char *
28ef6c31
JA
1559sh_get_env_value (v)
1560 const char *v;
b72432fd
JA
1561{
1562 return get_string_value (v);
1563}
1564
7117c2d2
JA
1565/* **************************************************************** */
1566/* */
1567/* Creating and setting variables */
1568/* */
1569/* **************************************************************** */
1570
1571/* Set NAME to VALUE if NAME has no value. */
1572SHELL_VAR *
1573set_if_not (name, value)
1574 char *name, *value;
1575{
1576 SHELL_VAR *v;
1577
1578 v = find_variable (name);
1579 if (v == 0)
1580 v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH);
1581 return (v);
1582}
1583
726f6388
JA
1584/* Create a local variable referenced by NAME. */
1585SHELL_VAR *
1586make_local_variable (name)
f73dda09 1587 const char *name;
726f6388
JA
1588{
1589 SHELL_VAR *new_var, *old_var;
7117c2d2
JA
1590 VAR_CONTEXT *vc;
1591 int was_tmpvar;
1592 char *tmp_value;
726f6388
JA
1593
1594 /* local foo; local foo; is a no-op. */
1595 old_var = find_variable (name);
7117c2d2 1596 if (old_var && local_p (old_var) && old_var->context == variable_context)
726f6388
JA
1597 return (old_var);
1598
7117c2d2
JA
1599 was_tmpvar = old_var && tempvar_p (old_var);
1600 if (was_tmpvar)
1601 tmp_value = value_cell (old_var);
1602
1603 for (vc = shell_variables; vc; vc = vc->down)
1604 if (vc_isfuncenv (vc) && vc->scope == variable_context)
1605 break;
1606
1607 if (vc == 0)
1608 {
1609 internal_error ("make_local_variable: no function context at current scope found");
1610 return ((SHELL_VAR *)NULL);
1611 }
1612 else if (vc->table == 0)
1613 vc->table = hash_create (TEMPENV_HASH_BUCKETS);
1614
bb70624e
JA
1615 /* Since this is called only from the local/declare/typeset code, we can
1616 call builtin_error here without worry (of course, it will also work
28ef6c31
JA
1617 for anything that sets this_command_name). Variables with the `noassign'
1618 attribute may not be made local. The test against old_var's context
1619 level is to disallow local copies of readonly global variables (since I
1620 believe that this could be a security hole). Readonly copies of calling
1621 function local variables are OK. */
1622 if (old_var && (noassign_p (old_var) ||
1623 (readonly_p (old_var) && old_var->context == 0)))
1624 {
1625 if (readonly_p (old_var))
7117c2d2 1626 sh_readonly (name);
bb70624e
JA
1627 return ((SHELL_VAR *)NULL);
1628 }
1629
d166f048 1630 if (old_var == 0)
7117c2d2 1631 new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH);
726f6388
JA
1632 else
1633 {
7117c2d2 1634 new_var = make_new_variable (name, vc->table);
726f6388 1635
7117c2d2
JA
1636 /* If we found this variable in one of the temporary environments,
1637 inherit its value. Watch to see if this causes problems with
1638 things like `x=4 local x'. */
1639 if (was_tmpvar)
1640 var_setvalue (new_var, savestring (tmp_value));
726f6388 1641
ccc6cda3 1642 new_var->attributes = exported_p (old_var) ? att_exported : 0;
726f6388
JA
1643 }
1644
7117c2d2
JA
1645 vc->flags |= VC_HASLOCAL;
1646
726f6388 1647 new_var->context = variable_context;
bb70624e 1648 VSETATTR (new_var, att_local);
726f6388 1649
7117c2d2
JA
1650 if (ifsname (name))
1651 setifs (new_var);
726f6388
JA
1652
1653 return (new_var);
1654}
1655
ccc6cda3 1656#if defined (ARRAY_VARS)
726f6388 1657SHELL_VAR *
ccc6cda3
JA
1658make_local_array_variable (name)
1659 char *name;
1660{
1661 SHELL_VAR *var;
1662 ARRAY *array;
1663
1664 var = make_local_variable (name);
bb70624e
JA
1665 if (var == 0)
1666 return var;
7117c2d2 1667 array = array_create ();
ccc6cda3
JA
1668
1669 FREE (value_cell(var));
7117c2d2 1670 var_setarray (var, array);
bb70624e 1671 VSETATTR (var, att_array);
ccc6cda3
JA
1672 return var;
1673}
1674#endif /* ARRAY_VARS */
1675
7117c2d2 1676/* Create a new shell variable with name NAME. */
f73dda09 1677static SHELL_VAR *
7117c2d2 1678new_shell_variable (name)
f73dda09 1679 const char *name;
726f6388 1680{
ccc6cda3 1681 SHELL_VAR *entry;
726f6388 1682
ccc6cda3 1683 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
726f6388 1684
ccc6cda3 1685 entry->name = savestring (name);
7117c2d2 1686 var_setvalue (entry, (char *)NULL);
bb70624e 1687 CLEAR_EXPORTSTR (entry);
726f6388 1688
7117c2d2
JA
1689 entry->dynamic_value = (sh_var_value_func_t *)NULL;
1690 entry->assign_func = (sh_var_assign_func_t *)NULL;
1691
1692 entry->attributes = 0;
ccc6cda3
JA
1693
1694 /* Always assume variables are to be made at toplevel!
1695 make_local_variable has the responsibilty of changing the
1696 variable context. */
1697 entry->context = 0;
7117c2d2
JA
1698
1699 return (entry);
1700}
1701
1702/* Create a new shell variable with name NAME and add it to the hash table
1703 TABLE. */
1704static SHELL_VAR *
1705make_new_variable (name, table)
1706 const char *name;
1707 HASH_TABLE *table;
1708{
1709 SHELL_VAR *entry;
1710 BUCKET_CONTENTS *elt;
1711
1712 entry = new_shell_variable (name);
ccc6cda3 1713
28ef6c31
JA
1714 /* Make sure we have a shell_variables hash table to add to. */
1715 if (shell_variables == 0)
7117c2d2
JA
1716 {
1717 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1718 shell_variables->scope = 0;
1719 shell_variables->table = hash_create (0);
1720 }
28ef6c31 1721
7117c2d2
JA
1722 elt = hash_insert (savestring (name), table, HASH_NOSRCH);
1723 elt->data = (PTR_T)entry;
ccc6cda3
JA
1724
1725 return entry;
1726}
1727
1728#if defined (ARRAY_VARS)
1729SHELL_VAR *
1730make_new_array_variable (name)
1731 char *name;
1732{
1733 SHELL_VAR *entry;
1734 ARRAY *array;
1735
7117c2d2
JA
1736 entry = make_new_variable (name, global_variables->table);
1737 array = array_create ();
1738 var_setarray (entry, array);
bb70624e 1739 VSETATTR (entry, att_array);
ccc6cda3
JA
1740 return entry;
1741}
1742#endif
1743
1744char *
1745make_variable_value (var, value)
1746 SHELL_VAR *var;
1747 char *value;
1748{
1749 char *retval;
7117c2d2 1750 intmax_t lval;
d166f048 1751 int expok;
ccc6cda3
JA
1752
1753 /* If this variable has had its type set to integer (via `declare -i'),
1754 then do expression evaluation on it and store the result. The
7117c2d2 1755 functions in expr.c (evalexp()) and bind_int_variable() are responsible
ccc6cda3
JA
1756 for turning off the integer flag if they don't want further
1757 evaluation done. */
1758 if (integer_p (var))
1759 {
d166f048
JA
1760 lval = evalexp (value, &expok);
1761 if (expok == 0)
1762 jump_to_top_level (DISCARD);
ccc6cda3
JA
1763 retval = itos (lval);
1764 }
1765 else if (value)
1766 {
1767 if (*value)
1768 retval = savestring (value);
1769 else
726f6388 1770 {
f73dda09 1771 retval = (char *)xmalloc (1);
ccc6cda3 1772 retval[0] = '\0';
726f6388 1773 }
ccc6cda3
JA
1774 }
1775 else
1776 retval = (char *)NULL;
726f6388 1777
ccc6cda3
JA
1778 return retval;
1779}
726f6388 1780
7117c2d2
JA
1781/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
1782 temporary environment (but usually is not). */
1783static SHELL_VAR *
1784bind_variable_internal (name, value, table, hflags)
f73dda09
JA
1785 const char *name;
1786 char *value;
7117c2d2
JA
1787 HASH_TABLE *table;
1788 int hflags;
ccc6cda3
JA
1789{
1790 char *newval;
7117c2d2 1791 SHELL_VAR *entry;
28ef6c31 1792
7117c2d2 1793 entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
ccc6cda3
JA
1794
1795 if (entry == 0)
1796 {
7117c2d2
JA
1797 entry = make_new_variable (name, table);
1798 var_setvalue (entry, make_variable_value (entry, value));
726f6388 1799 }
28ef6c31 1800 else if (entry->assign_func) /* array vars have assign functions now */
bb70624e
JA
1801 {
1802 INVALIDATE_EXPORTSTR (entry);
7117c2d2 1803 return ((*(entry->assign_func)) (entry, value, -1));
bb70624e 1804 }
726f6388
JA
1805 else
1806 {
28ef6c31 1807 if (readonly_p (entry) || noassign_p (entry))
726f6388 1808 {
28ef6c31 1809 if (readonly_p (entry))
7117c2d2 1810 err_readonly (name);
726f6388
JA
1811 return (entry);
1812 }
1813
1814 /* Variables which are bound are visible. */
bb70624e 1815 VUNSETATTR (entry, att_invisible);
726f6388 1816
ccc6cda3 1817 newval = make_variable_value (entry, value);
726f6388 1818
bb70624e
JA
1819 /* Invalidate any cached export string */
1820 INVALIDATE_EXPORTSTR (entry);
1821
ccc6cda3
JA
1822#if defined (ARRAY_VARS)
1823 /* XXX -- this bears looking at again -- XXX */
1824 /* If an existing array variable x is being assigned to with x=b or
1825 `read x' or something of that nature, silently convert it to
1826 x[0]=b or `read x[0]'. */
1827 if (array_p (entry))
d166f048 1828 {
7117c2d2 1829 array_insert (array_cell (entry), 0, newval);
d166f048
JA
1830 free (newval);
1831 }
726f6388 1832 else
f73dda09 1833#endif
726f6388 1834 {
7117c2d2
JA
1835 FREE (value_cell (entry));
1836 var_setvalue (entry, newval);
726f6388
JA
1837 }
1838 }
1839
1840 if (mark_modified_vars)
bb70624e 1841 VSETATTR (entry, att_exported);
726f6388
JA
1842
1843 if (exported_p (entry))
1844 array_needs_making = 1;
1845
1846 return (entry);
1847}
7117c2d2
JA
1848
1849/* Bind a variable NAME to VALUE. This conses up the name
1850 and value strings. If we have a temporary environment, we bind there
1851 first, then we bind into shell_variables. */
1852
1853SHELL_VAR *
1854bind_variable (name, value)
1855 const char *name;
1856 char *value;
1857{
1858 SHELL_VAR *v;
1859 VAR_CONTEXT *vc;
1860
1861 if (shell_variables == 0)
1862 {
1863 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
1864 shell_variables->scope = 0;
1865 shell_variables->table = hash_create (0);
1866 }
1867
1868 /* If we have a temporary environment, look there first for the variable,
1869 and, if found, modify the value there before modifying it in the
1870 shell_variables table. This allows sourced scripts to modify values
1871 given to them in a temporary environment while modifying the variable
1872 value that the caller sees. */
1873 if (temporary_env)
1874 bind_tempenv_variable (name, value);
1875
1876 /* XXX -- handle local variables here. */
1877 for (vc = shell_variables; vc; vc = vc->down)
1878 {
1879 if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
1880 {
1881 v = hash_lookup (name, vc->table);
1882 if (v)
1883 return (bind_variable_internal (name, value, vc->table, 0));
1884 }
1885 }
1886 return (bind_variable_internal (name, value, global_variables->table, 0));
1887}
726f6388 1888
bb70624e
JA
1889/* Make VAR, a simple shell variable, have value VALUE. Once assigned a
1890 value, variables are no longer invisible. This is a duplicate of part
1891 of the internals of bind_variable. If the variable is exported, or
1892 all modified variables should be exported, mark the variable for export
1893 and note that the export environment needs to be recreated. */
1894SHELL_VAR *
1895bind_variable_value (var, value)
1896 SHELL_VAR *var;
1897 char *value;
1898{
1899 char *t;
1900
1901 VUNSETATTR (var, att_invisible);
1902
1903 t = make_variable_value (var, value);
7117c2d2
JA
1904 FREE (value_cell (var));
1905 var_setvalue (var, t);
bb70624e
JA
1906
1907 INVALIDATE_EXPORTSTR (var);
1908
1909 if (mark_modified_vars)
1910 VSETATTR (var, att_exported);
1911
1912 if (exported_p (var))
1913 array_needs_making = 1;
1914
1915 return (var);
1916}
1917
1918/* Bind/create a shell variable with the name LHS to the RHS.
1919 This creates or modifies a variable such that it is an integer.
1920
1921 This used to be in expr.c, but it is here so that all of the
1922 variable binding stuff is localized. Since we don't want any
1923 recursive evaluation from bind_variable() (possible without this code,
1924 since bind_variable() calls the evaluator for variables with the integer
1925 attribute set), we temporarily turn off the integer attribute for each
1926 variable we set here, then turn it back on after binding as necessary. */
1927
1928SHELL_VAR *
1929bind_int_variable (lhs, rhs)
1930 char *lhs, *rhs;
1931{
1932 register SHELL_VAR *v;
7117c2d2
JA
1933 char *t;
1934 int isint, isarr;
1935
1936 isint = isarr = 0;
1937#if defined (ARRAY_VARS)
d3a24ed2 1938# if 0
7117c2d2 1939 if (t = xstrchr (lhs, '[')) /*]*/
d3a24ed2
CR
1940# else
1941 if (valid_array_reference (lhs))
1942# endif
7117c2d2
JA
1943 {
1944 isarr = 1;
1945 v = array_variable_part (lhs, (char **)0, (int *)0);
1946 }
1947 else
1948#endif
1949 v = find_variable (lhs);
bb70624e 1950
bb70624e
JA
1951 if (v)
1952 {
1953 isint = integer_p (v);
1954 VUNSETATTR (v, att_integer);
1955 }
1956
7117c2d2
JA
1957#if defined (ARRAY_VARS)
1958 if (isarr)
1959 v = assign_array_element (lhs, rhs);
1960 else
1961#endif
1962 v = bind_variable (lhs, rhs);
1963
bb70624e
JA
1964 if (isint)
1965 VSETATTR (v, att_integer);
1966
1967 return (v);
1968}
1969
ccc6cda3 1970SHELL_VAR *
f73dda09
JA
1971bind_var_to_int (var, val)
1972 char *var;
7117c2d2 1973 intmax_t val;
ccc6cda3 1974{
7117c2d2 1975 char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
ccc6cda3 1976
f73dda09
JA
1977 p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
1978 return (bind_int_variable (var, p));
ccc6cda3
JA
1979}
1980
7117c2d2
JA
1981/* Do a function binding to a variable. You pass the name and
1982 the command to bind to. This conses the name and command. */
1983SHELL_VAR *
1984bind_function (name, value)
1985 const char *name;
1986 COMMAND *value;
1987{
1988 SHELL_VAR *entry;
1989
1990 entry = find_function (name);
1991 if (entry == 0)
1992 {
1993 BUCKET_CONTENTS *elt;
1994
1995 elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
1996 entry = new_shell_variable (name);
1997 elt->data = (PTR_T)entry;
1998 }
1999 else
2000 INVALIDATE_EXPORTSTR (entry);
2001
2002 if (var_isset (entry))
2003 dispose_command (function_cell (entry));
2004
2005 if (value)
2006 var_setfunc (entry, copy_command (value));
2007 else
2008 var_setfunc (entry, 0);
2009
2010 VSETATTR (entry, att_function);
2011
2012 if (mark_modified_vars)
2013 VSETATTR (entry, att_exported);
2014
2015 VUNSETATTR (entry, att_invisible); /* Just to be sure */
2016
2017 if (exported_p (entry))
2018 array_needs_making = 1;
2019
2020#if defined (PROGRAMMABLE_COMPLETION)
2021 set_itemlist_dirty (&it_functions);
2022#endif
2023
2024 return (entry);
2025}
2026
d3a24ed2
CR
2027/* Bind a function definition, which includes source file and line number
2028 information in addition to the command, into the FUNCTION_DEF hash table.*/
2029void
2030bind_function_def (name, value)
2031 const char *name;
2032 FUNCTION_DEF *value;
2033{
2034 FUNCTION_DEF *entry;
2035 BUCKET_CONTENTS *elt;
2036
2037 entry = find_function_def (name);
2038 if (entry)
2039 {
2040 dispose_function_def_contents (entry);
2041 entry = copy_function_def_contents (value, entry);
2042 }
2043 else
2044 {
2045 entry = copy_function_def (value);
2046
2047 elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2048 elt->data = (PTR_T *)entry;
2049 }
2050}
2051
7117c2d2
JA
2052/* Add STRING, which is of the form foo=bar, to the temporary environment
2053 HASH_TABLE (temporary_env). The functions in execute_cmd.c are
2054 responsible for moving the main temporary env to one of the other
2055 temporary environments. The expansion code in subst.c calls this. */
2056int
2057assign_in_env (string)
2058 const char *string;
2059{
2060 int offset;
2061 char *name, *temp, *value;
2062 SHELL_VAR *var;
2063
2064 offset = assignment (string);
2065 name = savestring (string);
2066 value = (char *)NULL;
2067
2068 if (name[offset] == '=')
2069 {
2070 name[offset] = 0;
2071
2072 var = find_variable (name);
2073 if (var && (readonly_p (var) || noassign_p (var)))
2074 {
2075 if (readonly_p (var))
2076 err_readonly (name);
2077 free (name);
2078 return (0);
2079 }
2080
2081 temp = name + offset + 1;
2082 temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
2083
2084 value = expand_string_unsplit_to_string (temp, 0);
2085 free (temp);
2086 }
2087
2088 if (temporary_env == 0)
2089 temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2090
2091 var = hash_lookup (name, temporary_env);
2092 if (var == 0)
2093 var = make_new_variable (name, temporary_env);
2094 else
2095 FREE (value_cell (var));
2096
2097 if (value == 0)
2098 {
2099 value = (char *)xmalloc (1); /* like do_assignment_internal */
2100 value[0] = '\0';
2101 }
2102
2103 var_setvalue (var, value);
2104 var->attributes |= (att_exported|att_tempvar);
2105 var->context = variable_context; /* XXX */
2106
2107 INVALIDATE_EXPORTSTR (var);
2108 var->exportstr = mk_env_string (name, value);
2109
2110 array_needs_making = 1;
2111
2112 if (ifsname (name))
2113 setifs (var);
2114
2115 if (echo_command_at_execute)
2116 {
2117 /* The Korn shell prints the `+ ' in front of assignment statements,
2118 so we do too. */
2119 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
2120 fflush (stderr);
2121 }
2122
2123 return 1;
2124}
2125
2126/* **************************************************************** */
2127/* */
2128/* Copying variables */
2129/* */
2130/* **************************************************************** */
2131
2132#ifdef INCLUDE_UNUSED
2133/* Copy VAR to a new data structure and return that structure. */
2134SHELL_VAR *
2135copy_variable (var)
2136 SHELL_VAR *var;
2137{
2138 SHELL_VAR *copy = (SHELL_VAR *)NULL;
2139
2140 if (var)
2141 {
2142 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2143
2144 copy->attributes = var->attributes;
2145 copy->name = savestring (var->name);
2146
2147 if (function_p (var))
2148 var_setfunc (copy, copy_command (function_cell (var)));
2149#if defined (ARRAY_VARS)
2150 else if (array_p (var))
2151 var_setarray (copy, dup_array (array_cell (var)));
2152#endif
2153 else if (value_cell (var))
2154 var_setvalue (copy, savestring (value_cell (var)));
2155 else
2156 var_setvalue (copy, (char *)NULL);
2157
2158 copy->dynamic_value = var->dynamic_value;
2159 copy->assign_func = var->assign_func;
2160
2161 copy->exportstr = COPY_EXPORTSTR (var);
2162
2163 copy->context = var->context;
2164 }
2165 return (copy);
2166}
2167#endif
2168
2169/* **************************************************************** */
2170/* */
2171/* Deleting and unsetting variables */
2172/* */
2173/* **************************************************************** */
2174
726f6388
JA
2175/* Dispose of the information attached to VAR. */
2176void
2177dispose_variable (var)
2178 SHELL_VAR *var;
2179{
7117c2d2 2180 if (var == 0)
726f6388
JA
2181 return;
2182
2183 if (function_p (var))
ccc6cda3
JA
2184 dispose_command (function_cell (var));
2185#if defined (ARRAY_VARS)
2186 else if (array_p (var))
7117c2d2 2187 array_dispose (array_cell (var));
ccc6cda3
JA
2188#endif
2189 else
2190 FREE (value_cell (var));
726f6388 2191
bb70624e
JA
2192 FREE_EXPORTSTR (var);
2193
726f6388
JA
2194 free (var->name);
2195
2196 if (exported_p (var))
2197 array_needs_making = 1;
2198
2199 free (var);
2200}
2201
7117c2d2 2202/* Unset the shell variable referenced by NAME. */
ccc6cda3 2203int
726f6388 2204unbind_variable (name)
f73dda09 2205 const char *name;
726f6388 2206{
7117c2d2
JA
2207 return makunbound (name, shell_variables);
2208}
726f6388 2209
7117c2d2
JA
2210/* Unset the shell function named NAME. */
2211int
2212unbind_func (name)
2213 const char *name;
2214{
2215 BUCKET_CONTENTS *elt;
2216 SHELL_VAR *func;
726f6388 2217
7117c2d2
JA
2218 elt = hash_remove (name, shell_functions, 0);
2219
2220 if (elt == 0)
2221 return -1;
2222
2223#if defined (PROGRAMMABLE_COMPLETION)
2224 set_itemlist_dirty (&it_functions);
ccc6cda3 2225#endif
7117c2d2
JA
2226
2227 func = (SHELL_VAR *)elt->data;
2228 if (func)
726f6388 2229 {
7117c2d2
JA
2230 if (exported_p (func))
2231 array_needs_making++;
2232 dispose_variable (func);
726f6388
JA
2233 }
2234
7117c2d2
JA
2235 free (elt->key);
2236 free (elt);
726f6388 2237
7117c2d2 2238 return 0;
726f6388
JA
2239}
2240
d3a24ed2
CR
2241int
2242unbind_function_def (name)
2243 const char *name;
2244{
2245 BUCKET_CONTENTS *elt;
2246 FUNCTION_DEF *funcdef;
2247
2248 elt = hash_remove (name, shell_function_defs, 0);
2249
2250 if (elt == 0)
2251 return -1;
2252
2253 funcdef = (FUNCTION_DEF *)elt->data;
2254 if (funcdef)
2255 dispose_function_def (funcdef);
2256
2257 free (elt->key);
2258 free (elt);
2259
2260 return 0;
2261}
2262
726f6388
JA
2263/* Make the variable associated with NAME go away. HASH_LIST is the
2264 hash table from which this variable should be deleted (either
2265 shell_variables or shell_functions).
2266 Returns non-zero if the variable couldn't be found. */
ccc6cda3 2267int
7117c2d2 2268makunbound (name, vc)
f73dda09 2269 const char *name;
7117c2d2 2270 VAR_CONTEXT *vc;
726f6388 2271{
d166f048 2272 BUCKET_CONTENTS *elt, *new_elt;
7117c2d2
JA
2273 SHELL_VAR *old_var;
2274 VAR_CONTEXT *v;
726f6388
JA
2275 char *t;
2276
7117c2d2
JA
2277 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2278 if (elt = hash_remove (name, v->table, 0))
2279 break;
726f6388 2280
d166f048 2281 if (elt == 0)
726f6388
JA
2282 return (-1);
2283
2284 old_var = (SHELL_VAR *)elt->data;
726f6388
JA
2285
2286 if (old_var && exported_p (old_var))
2287 array_needs_making++;
2288
ccc6cda3 2289 /* If we're unsetting a local variable and we're still executing inside
7117c2d2
JA
2290 the function, just mark the variable as invisible. The function
2291 eventually called by pop_var_context() will clean it up later. This
2292 must be done so that if the variable is subsequently assigned a new
2293 value inside the function, the `local' attribute is still present.
2294 We also need to add it back into the correct hash table. */
ccc6cda3
JA
2295 if (old_var && local_p (old_var) && variable_context == old_var->context)
2296 {
bb70624e 2297 VSETATTR (old_var, att_invisible);
7117c2d2
JA
2298 FREE (value_cell (old_var));
2299 var_setvalue (old_var, (char *)NULL);
bb70624e 2300 INVALIDATE_EXPORTSTR (old_var);
7117c2d2
JA
2301
2302 new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2303 new_elt->data = (PTR_T)old_var;
ccc6cda3 2304 stupidly_hack_special_variables (old_var->name);
7117c2d2 2305
d166f048
JA
2306 free (elt->key);
2307 free (elt);
ccc6cda3
JA
2308 return (0);
2309 }
2310
726f6388
JA
2311 /* Have to save a copy of name here, because it might refer to
2312 old_var->name. If so, stupidly_hack_special_variables will
2313 reference freed memory. */
2314 t = savestring (name);
2315
2316 free (elt->key);
2317 free (elt);
2318
2319 dispose_variable (old_var);
2320 stupidly_hack_special_variables (t);
2321 free (t);
7117c2d2 2322
726f6388
JA
2323 return (0);
2324}
2325
7117c2d2
JA
2326/* Get rid of all of the variables in the current context. */
2327void
2328kill_all_local_variables ()
726f6388 2329{
7117c2d2
JA
2330 VAR_CONTEXT *vc;
2331
2332 for (vc = shell_variables; vc; vc = vc->down)
2333 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2334 break;
2335 if (vc == 0)
2336 return; /* XXX */
726f6388 2337
7117c2d2 2338 if (vc->table && vc_haslocals (vc))
726f6388 2339 {
7117c2d2
JA
2340 delete_all_variables (vc->table);
2341 hash_dispose (vc->table);
726f6388 2342 }
7117c2d2 2343 vc->table = (HASH_TABLE *)NULL;
726f6388
JA
2344}
2345
ccc6cda3
JA
2346static void
2347free_variable_hash_data (data)
f73dda09 2348 PTR_T data;
ccc6cda3 2349{
7117c2d2 2350 SHELL_VAR *var;
ccc6cda3
JA
2351
2352 var = (SHELL_VAR *)data;
7117c2d2 2353 dispose_variable (var);
ccc6cda3
JA
2354}
2355
726f6388
JA
2356/* Delete the entire contents of the hash table. */
2357void
2358delete_all_variables (hashed_vars)
2359 HASH_TABLE *hashed_vars;
2360{
7117c2d2 2361 hash_flush (hashed_vars, free_variable_hash_data);
726f6388
JA
2362}
2363
7117c2d2
JA
2364/* **************************************************************** */
2365/* */
2366/* Setting variable attributes */
2367/* */
2368/* **************************************************************** */
726f6388 2369
ccc6cda3
JA
2370#define FIND_OR_MAKE_VARIABLE(name, entry) \
2371 do \
2372 { \
2373 entry = find_variable (name); \
2374 if (!entry) \
2375 { \
2376 entry = bind_variable (name, ""); \
2377 if (!no_invisible_vars) entry->attributes |= att_invisible; \
2378 } \
2379 } \
2380 while (0)
2381
2382/* Make the variable associated with NAME be readonly.
726f6388
JA
2383 If NAME does not exist yet, create it. */
2384void
2385set_var_read_only (name)
2386 char *name;
2387{
ccc6cda3 2388 SHELL_VAR *entry;
726f6388 2389
ccc6cda3 2390 FIND_OR_MAKE_VARIABLE (name, entry);
bb70624e 2391 VSETATTR (entry, att_readonly);
726f6388
JA
2392}
2393
cce855bc 2394#ifdef INCLUDE_UNUSED
ccc6cda3 2395/* Make the function associated with NAME be readonly.
726f6388
JA
2396 If NAME does not exist, we just punt, like auto_export code below. */
2397void
2398set_func_read_only (name)
f73dda09 2399 const char *name;
726f6388 2400{
d166f048 2401 SHELL_VAR *entry;
726f6388 2402
d166f048 2403 entry = find_function (name);
726f6388 2404 if (entry)
bb70624e 2405 VSETATTR (entry, att_readonly);
726f6388
JA
2406}
2407
2408/* Make the variable associated with NAME be auto-exported.
2409 If NAME does not exist yet, create it. */
2410void
2411set_var_auto_export (name)
2412 char *name;
2413{
ccc6cda3 2414 SHELL_VAR *entry;
726f6388 2415
ccc6cda3 2416 FIND_OR_MAKE_VARIABLE (name, entry);
726f6388
JA
2417 set_auto_export (entry);
2418}
2419
2420/* Make the function associated with NAME be auto-exported. */
2421void
2422set_func_auto_export (name)
f73dda09 2423 const char *name;
726f6388 2424{
ccc6cda3 2425 SHELL_VAR *entry;
726f6388 2426
ccc6cda3 2427 entry = find_function (name);
726f6388 2428 if (entry)
ccc6cda3
JA
2429 set_auto_export (entry);
2430}
cce855bc 2431#endif
ccc6cda3 2432
7117c2d2
JA
2433/* **************************************************************** */
2434/* */
2435/* Creating lists of variables */
2436/* */
2437/* **************************************************************** */
2438
2439static VARLIST *
2440vlist_alloc (nentries)
2441 int nentries;
726f6388 2442{
7117c2d2 2443 VARLIST *vlist;
726f6388 2444
7117c2d2
JA
2445 vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2446 vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2447 vlist->list_size = nentries;
2448 vlist->list_len = 0;
2449 vlist->list[0] = (SHELL_VAR *)NULL;
726f6388 2450
7117c2d2
JA
2451 return vlist;
2452}
726f6388 2453
7117c2d2
JA
2454static VARLIST *
2455vlist_realloc (vlist, n)
2456 VARLIST *vlist;
2457 int n;
2458{
2459 if (vlist == 0)
2460 return (vlist = vlist_alloc (n));
2461 if (n > vlist->list_size)
726f6388 2462 {
7117c2d2
JA
2463 vlist->list_size = n;
2464 vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2465 }
2466 return vlist;
2467}
726f6388 2468
7117c2d2
JA
2469static void
2470vlist_add (vlist, var, flags)
2471 VARLIST *vlist;
2472 SHELL_VAR *var;
2473 int flags;
2474{
2475 register int i;
ccc6cda3 2476
7117c2d2
JA
2477 for (i = 0; i < vlist->list_len; i++)
2478 if (STREQ (var->name, vlist->list[i]->name))
2479 break;
2480 if (i < vlist->list_len)
2481 return;
2482
2483 if (i >= vlist->list_size)
2484 vlist = vlist_realloc (vlist, vlist->list_size + 16);
726f6388 2485
7117c2d2
JA
2486 vlist->list[vlist->list_len++] = var;
2487 vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2488}
2489
2490/* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
2491 variables for which FUNCTION returns a non-zero value. A NULL value
2492 for FUNCTION means to use all variables. */
2493SHELL_VAR **
2494map_over (function, vc)
2495 sh_var_map_func_t *function;
2496 VAR_CONTEXT *vc;
2497{
2498 VAR_CONTEXT *v;
2499 VARLIST *vlist;
2500 SHELL_VAR **ret;
2501 int nentries;
2502
2503 for (nentries = 0, v = vc; v; v = v->down)
2504 nentries += HASH_ENTRIES (v->table);
2505
2506 if (nentries == 0)
2507 return (SHELL_VAR **)NULL;
2508
2509 vlist = vlist_alloc (nentries);
2510
2511 for (v = vc; v; v = v->down)
2512 flatten (v->table, function, vlist, 0);
2513
2514 ret = vlist->list;
2515 free (vlist);
2516 return ret;
2517}
2518
2519SHELL_VAR **
2520map_over_funcs (function)
2521 sh_var_map_func_t *function;
2522{
2523 VARLIST *vlist;
2524 SHELL_VAR **ret;
2525
2526 if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2527 return ((SHELL_VAR **)NULL);
2528
2529 vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2530
2531 flatten (shell_functions, function, vlist, 0);
2532
2533 ret = vlist->list;
2534 free (vlist);
2535 return ret;
2536}
2537
2538/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2539 elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
2540 for future use. Only unique names are added to VLIST. If FUNC is
2541 NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
2542 NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
2543 and FUNC are both NULL, nothing happens. */
2544static void
2545flatten (var_hash_table, func, vlist, flags)
2546 HASH_TABLE *var_hash_table;
2547 sh_var_map_func_t *func;
2548 VARLIST *vlist;
2549 int flags;
2550{
2551 register int i;
2552 register BUCKET_CONTENTS *tlist;
2553 int r;
2554 SHELL_VAR *var;
2555
2556 if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
2557 return;
2558
2559 for (i = 0; i < var_hash_table->nbuckets; i++)
2560 {
2561 for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
2562 {
2563 var = (SHELL_VAR *)tlist->data;
2564
2565 r = func ? (*func) (var) : 1;
2566 if (r && vlist)
2567 vlist_add (vlist, var, flags);
2568 }
726f6388 2569 }
7117c2d2
JA
2570}
2571
2572void
2573sort_variables (array)
2574 SHELL_VAR **array;
2575{
2576 qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
726f6388
JA
2577}
2578
2579static int
7117c2d2
JA
2580qsort_var_comp (var1, var2)
2581 SHELL_VAR **var1, **var2;
726f6388 2582{
7117c2d2
JA
2583 int result;
2584
2585 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
2586 result = strcmp ((*var1)->name, (*var2)->name);
2587
2588 return (result);
726f6388
JA
2589}
2590
7117c2d2
JA
2591/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
2592 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
ccc6cda3 2593static SHELL_VAR **
7117c2d2
JA
2594vapply (func)
2595 sh_var_map_func_t *func;
726f6388
JA
2596{
2597 SHELL_VAR **list;
2598
7117c2d2 2599 list = map_over (func, shell_variables);
d166f048 2600 if (list /* && posixly_correct */)
726f6388 2601 sort_variables (list);
7117c2d2
JA
2602 return (list);
2603}
726f6388 2604
7117c2d2
JA
2605/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
2606 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
2607static SHELL_VAR **
2608fapply (func)
2609 sh_var_map_func_t *func;
2610{
2611 SHELL_VAR **list;
2612
2613 list = map_over_funcs (func);
2614 if (list /* && posixly_correct */)
2615 sort_variables (list);
726f6388
JA
2616 return (list);
2617}
2618
7117c2d2
JA
2619/* Create a NULL terminated array of all the shell variables. */
2620SHELL_VAR **
2621all_shell_variables ()
2622{
2623 return (vapply ((sh_var_map_func_t *)NULL));
2624}
2625
2626/* Create a NULL terminated array of all the shell functions. */
2627SHELL_VAR **
2628all_shell_functions ()
2629{
2630 return (fapply ((sh_var_map_func_t *)NULL));
2631}
2632
2633static int
2634visible_var (var)
2635 SHELL_VAR *var;
2636{
2637 return (invisible_p (var) == 0);
2638}
2639
726f6388 2640SHELL_VAR **
bb70624e 2641all_visible_functions ()
726f6388 2642{
7117c2d2 2643 return (fapply (visible_var));
ccc6cda3 2644}
726f6388 2645
ccc6cda3 2646SHELL_VAR **
bb70624e 2647all_visible_variables ()
ccc6cda3 2648{
7117c2d2 2649 return (vapply (visible_var));
726f6388
JA
2650}
2651
ccc6cda3
JA
2652/* Return non-zero if the variable VAR is visible and exported. Array
2653 variables cannot be exported. */
726f6388
JA
2654static int
2655visible_and_exported (var)
2656 SHELL_VAR *var;
2657{
ccc6cda3 2658 return (invisible_p (var) == 0 && exported_p (var));
726f6388
JA
2659}
2660
7117c2d2
JA
2661/* Return non-zero if VAR is a local variable in the current context and
2662 is exported. */
2663static int
2664local_and_exported (var)
2665 SHELL_VAR *var;
2666{
2667 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
2668}
2669
bb70624e
JA
2670SHELL_VAR **
2671all_exported_variables ()
2672{
7117c2d2
JA
2673 return (vapply (visible_and_exported));
2674}
bb70624e 2675
7117c2d2
JA
2676SHELL_VAR **
2677local_exported_variables ()
2678{
2679 return (vapply (local_and_exported));
2680}
2681
2682static int
2683variable_in_context (var)
2684 SHELL_VAR *var;
2685{
2686 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
2687}
2688
2689SHELL_VAR **
2690all_local_variables ()
2691{
2692 VARLIST *vlist;
2693 SHELL_VAR **ret;
2694 VAR_CONTEXT *vc;
2695
2696 vc = shell_variables;
2697 for (vc = shell_variables; vc; vc = vc->down)
2698 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2699 break;
2700
2701 if (vc == 0)
2702 {
2703 internal_error ("all_local_variables: no function context at current scope found");
2704 return (SHELL_VAR **)NULL;
2705 }
2706 if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
2707 return (SHELL_VAR **)NULL;
2708
2709 vlist = vlist_alloc (HASH_ENTRIES (vc->table));
2710
2711 flatten (vc->table, variable_in_context, vlist, 0);
2712
2713 ret = vlist->list;
2714 free (vlist);
2715 if (ret)
2716 sort_variables (ret);
2717 return ret;
bb70624e
JA
2718}
2719
2720#if defined (ARRAY_VARS)
2721/* Return non-zero if the variable VAR is visible and an array. */
2722static int
2723visible_array_vars (var)
2724 SHELL_VAR *var;
2725{
2726 return (invisible_p (var) == 0 && array_p (var));
2727}
2728
2729SHELL_VAR **
2730all_array_variables ()
2731{
7117c2d2 2732 return (vapply (visible_array_vars));
bb70624e
JA
2733}
2734#endif /* ARRAY_VARS */
2735
2736char **
2737all_variables_matching_prefix (prefix)
f73dda09 2738 const char *prefix;
bb70624e
JA
2739{
2740 SHELL_VAR **varlist;
2741 char **rlist;
2742 int vind, rind, plen;
2743
2744 plen = STRLEN (prefix);
2745 varlist = all_visible_variables ();
2746 for (vind = 0; varlist && varlist[vind]; vind++)
2747 ;
2748 if (varlist == 0 || vind == 0)
2749 return ((char **)NULL);
7117c2d2 2750 rlist = strvec_create (vind + 1);
bb70624e
JA
2751 for (vind = rind = 0; varlist[vind]; vind++)
2752 {
2753 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
28ef6c31 2754 rlist[rind++] = savestring (varlist[vind]->name);
bb70624e
JA
2755 }
2756 rlist[rind] = (char *)0;
2757 free (varlist);
2758
2759 return rlist;
2760}
2761
7117c2d2
JA
2762/* **************************************************************** */
2763/* */
2764/* Managing temporary variable scopes */
2765/* */
2766/* **************************************************************** */
2767
2768/* Make variable NAME have VALUE in the temporary environment. */
2769static SHELL_VAR *
2770bind_tempenv_variable (name, value)
2771 const char *name;
2772 char *value;
2773{
2774 SHELL_VAR *var;
2775
2776 var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
2777
2778 if (var)
2779 {
2780 FREE (value_cell (var));
2781 var_setvalue (var, savestring (value));
2782 INVALIDATE_EXPORTSTR (var);
2783 }
2784
2785 return (var);
2786}
2787
2788/* Find a variable in the temporary environment that is named NAME.
2789 Return the SHELL_VAR *, or NULL if not found. */
2790SHELL_VAR *
2791find_tempenv_variable (name)
2792 const char *name;
2793{
2794 return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
2795}
2796
2797/* Push the variable described by (SHELL_VAR *)DATA down to the next
2798 variable context from the temporary environment. */
2799static void
2800push_temp_var (data)
2801 PTR_T data;
2802{
2803 SHELL_VAR *var, *v;
2804 HASH_TABLE *binding_table;
2805
2806 var = (SHELL_VAR *)data;
2807
2808 binding_table = shell_variables->table;
2809 if (binding_table == 0)
2810 {
2811 if (shell_variables == global_variables)
2812 /* shouldn't happen */
2813 binding_table = shell_variables->table = global_variables->table = hash_create (0);
2814 else
2815 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
2816 }
2817
2818 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0);
2819
2820 /* XXX - should we set the context here? It shouldn't matter because of how
2821 assign_in_env works, but might want to check. */
2822 if (binding_table == global_variables->table) /* XXX */
2823 var->attributes &= ~(att_tempvar|att_propagate);
2824 else
2825 {
2826 var->attributes |= att_propagate;
2827 if (binding_table == shell_variables->table)
2828 shell_variables->flags |= VC_HASTMPVAR;
2829 }
2830 v->attributes |= var->attributes;
2831
2832 dispose_variable (var);
2833}
2834
2835static void
2836propagate_temp_var (data)
2837 PTR_T data;
2838{
2839 SHELL_VAR *var;
2840
2841 var = (SHELL_VAR *)data;
2842 if (tempvar_p (var) && (var->attributes & att_propagate))
2843 push_temp_var (data);
2844 else
2845 dispose_variable (var);
2846}
2847
2848/* Free the storage used in the hash table for temporary
2849 environment variables. PUSHF is a function to be called
2850 to free each hash table entry. It takes care of pushing variables
2851 to previous scopes if appropriate. */
2852static void
2853dispose_temporary_env (pushf)
2854 sh_free_func_t *pushf;
2855{
2856 hash_flush (temporary_env, pushf);
2857 hash_dispose (temporary_env);
2858 temporary_env = (HASH_TABLE *)NULL;
2859
2860 array_needs_making = 1;
2861
2862 sv_ifs ("IFS"); /* XXX here for now */
2863}
2864
2865void
2866dispose_used_env_vars ()
2867{
2868 if (temporary_env)
2869 dispose_temporary_env (propagate_temp_var);
2870}
2871
2872/* Take all of the shell variables in the temporary environment HASH_TABLE
2873 and make shell variables from them at the current variable context. */
2874void
2875merge_temporary_env ()
2876{
2877 if (temporary_env)
2878 dispose_temporary_env (push_temp_var);
2879}
2880
2881/* **************************************************************** */
2882/* */
2883/* Creating and manipulating the environment */
2884/* */
2885/* **************************************************************** */
2886
bb70624e
JA
2887static inline char *
2888mk_env_string (name, value)
f73dda09 2889 const char *name, *value;
bb70624e
JA
2890{
2891 int name_len, value_len;
2892 char *p;
2893
2894 name_len = strlen (name);
2895 value_len = STRLEN (value);
f73dda09 2896 p = (char *)xmalloc (2 + name_len + value_len);
bb70624e
JA
2897 strcpy (p, name);
2898 p[name_len] = '=';
2899 if (value && *value)
2900 strcpy (p + name_len + 1, value);
2901 else
2902 p[name_len + 1] = '\0';
2903 return (p);
2904}
2905
f73dda09 2906#ifdef DEBUG
bb70624e
JA
2907/* Debugging */
2908static int
2909valid_exportstr (v)
2910 SHELL_VAR *v;
2911{
2912 char *s;
2913
2914 s = v->exportstr;
f73dda09 2915 if (legal_variable_starter ((unsigned char)*s) == 0)
bb70624e
JA
2916 {
2917 internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2918 return (0);
2919 }
2920 for (s = v->exportstr + 1; s && *s; s++)
2921 {
2922 if (*s == '=')
28ef6c31 2923 break;
f73dda09 2924 if (legal_variable_char ((unsigned char)*s) == 0)
bb70624e
JA
2925 {
2926 internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2927 return (0);
2928 }
2929 }
2930 if (*s != '=')
2931 {
2932 internal_error ("no `=' in exportstr for %s", v->name);
2933 return (0);
2934 }
2935 return (1);
2936}
f73dda09 2937#endif
bb70624e 2938
7117c2d2
JA
2939static char **
2940make_env_array_from_var_list (vars)
2941 SHELL_VAR **vars;
726f6388
JA
2942{
2943 register int i, list_index;
2944 register SHELL_VAR *var;
ccc6cda3 2945 char **list, *value;
726f6388 2946
7117c2d2 2947 list = strvec_create ((1 + strvec_len ((char **)vars)));
bb70624e
JA
2948
2949#define USE_EXPORTSTR (value == var->exportstr)
726f6388
JA
2950
2951 for (i = 0, list_index = 0; var = vars[i]; i++)
2952 {
28ef6c31
JA
2953#if defined (__CYGWIN__)
2954 /* We don't use the exportstr stuff on Cygwin at all. */
2955 INVALIDATE_EXPORTSTR (var);
bb70624e 2956#endif
28ef6c31
JA
2957 if (var->exportstr)
2958 value = var->exportstr;
bb70624e 2959 else if (function_p (var))
ccc6cda3
JA
2960 value = named_function_string ((char *)NULL, function_cell (var), 0);
2961#if defined (ARRAY_VARS)
2962 else if (array_p (var))
2963# if 0
2964 value = array_to_assignment_string (array_cell (var));
2965# else
2966 continue; /* XXX array vars cannot yet be exported */
2967# endif
2968#endif
726f6388
JA
2969 else
2970 value = value_cell (var);
2971
2972 if (value)
2973 {
bb70624e
JA
2974 /* Gee, I'd like to get away with not using savestring() if we're
2975 using the cached exportstr... */
2976 list[list_index] = USE_EXPORTSTR ? savestring (value)
2977 : mk_env_string (var->name, value);
2978
7117c2d2
JA
2979 if (USE_EXPORTSTR == 0)
2980 SAVE_EXPORTSTR (var, list[list_index]);
2981
726f6388 2982 list_index++;
bb70624e
JA
2983#undef USE_EXPORTSTR
2984
2985#if 0 /* not yet */
ccc6cda3
JA
2986#if defined (ARRAY_VARS)
2987 if (array_p (var))
2988 free (value);
bb70624e 2989#endif
ccc6cda3 2990#endif
726f6388
JA
2991 }
2992 }
2993
726f6388
JA
2994 list[list_index] = (char *)NULL;
2995 return (list);
2996}
2997
7117c2d2
JA
2998/* Make an array of assignment statements from the hash table
2999 HASHED_VARS which contains SHELL_VARs. Only visible, exported
3000 variables are eligible. */
3001static char **
3002make_var_export_array (vcxt)
3003 VAR_CONTEXT *vcxt;
726f6388 3004{
7117c2d2
JA
3005 char **list;
3006 SHELL_VAR **vars;
726f6388 3007
7117c2d2 3008 vars = map_over (visible_and_exported, vcxt);
726f6388 3009
7117c2d2
JA
3010 if (vars == 0)
3011 return (char **)NULL;
ccc6cda3 3012
7117c2d2 3013 list = make_env_array_from_var_list (vars);
ccc6cda3 3014
7117c2d2
JA
3015 free (vars);
3016 return (list);
ccc6cda3
JA
3017}
3018
7117c2d2
JA
3019static char **
3020make_func_export_array ()
726f6388 3021{
7117c2d2
JA
3022 char **list;
3023 SHELL_VAR **vars;
ccc6cda3 3024
7117c2d2
JA
3025 vars = map_over_funcs (visible_and_exported);
3026 if (vars == 0)
3027 return (char **)NULL;
726f6388 3028
7117c2d2 3029 list = make_env_array_from_var_list (vars);
28ef6c31 3030
7117c2d2
JA
3031 free (vars);
3032 return (list);
bb70624e
JA
3033}
3034
d166f048
JA
3035/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3036#define add_to_export_env(envstr,do_alloc) \
3037do \
3038 { \
3039 if (export_env_index >= (export_env_size - 1)) \
3040 { \
3041 export_env_size += 16; \
7117c2d2 3042 export_env = strvec_resize (export_env, export_env_size); \
d166f048
JA
3043 } \
3044 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3045 export_env[export_env_index] = (char *)NULL; \
3046 } while (0)
3047
d166f048
JA
3048/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3049 array with the same left-hand side. Return the new EXPORT_ENV. */
726f6388 3050char **
d166f048 3051add_or_supercede_exported_var (assign, do_alloc)
726f6388 3052 char *assign;
d166f048 3053 int do_alloc;
726f6388
JA
3054{
3055 register int i;
d166f048 3056 int equal_offset;
726f6388 3057
d166f048
JA
3058 equal_offset = assignment (assign);
3059 if (equal_offset == 0)
3060 return (export_env);
726f6388 3061
7117c2d2
JA
3062 /* If this is a function, then only supersede the function definition.
3063 We do this by including the `=() {' in the comparison, like
3064 initialize_shell_variables does. */
3065 if (assign[equal_offset + 1] == '(' &&
3066 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
3067 equal_offset += 4;
726f6388 3068
d166f048 3069 for (i = 0; i < export_env_index; i++)
726f6388 3070 {
d166f048 3071 if (STREQN (assign, export_env[i], equal_offset + 1))
726f6388 3072 {
d166f048
JA
3073 free (export_env[i]);
3074 export_env[i] = do_alloc ? savestring (assign) : assign;
3075 return (export_env);
726f6388
JA
3076 }
3077 }
d166f048
JA
3078 add_to_export_env (assign, do_alloc);
3079 return (export_env);
726f6388
JA
3080}
3081
7117c2d2
JA
3082static void
3083add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3084 char **temp_array;
3085 int do_alloc, do_supercede;
3086{
3087 register int i;
3088
3089 if (temp_array == 0)
3090 return;
3091
3092 for (i = 0; temp_array[i]; i++)
3093 {
3094 if (do_supercede)
3095 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3096 else
3097 add_to_export_env (temp_array[i], do_alloc);
3098 }
3099
3100 free (temp_array);
3101}
3102
d166f048 3103/* Make the environment array for the command about to be executed, if the
726f6388
JA
3104 array needs making. Otherwise, do nothing. If a shell action could
3105 change the array that commands receive for their environment, then the
7117c2d2
JA
3106 code should `array_needs_making++'.
3107
3108 The order to add to the array is:
3109 temporary_env
3110 list of var contexts whose head is shell_variables
3111 shell_functions
3112
3113 This is the shell variable lookup order. We add only new variable
3114 names at each step, which allows local variables and variables in
3115 the temporary environments to shadow variables in the global (or
3116 any previous) scope.
3117*/
3118
3119static int
3120n_shell_variables ()
3121{
3122 VAR_CONTEXT *vc;
3123 int n;
3124
3125 for (n = 0, vc = shell_variables; vc; vc = vc->down)
3126 n += HASH_ENTRIES (vc->table);
3127 return n;
3128}
3129
726f6388
JA
3130void
3131maybe_make_export_env ()
3132{
726f6388 3133 register char **temp_array;
d166f048 3134 int new_size;
7117c2d2 3135 VAR_CONTEXT *tcxt;
726f6388
JA
3136
3137 if (array_needs_making)
3138 {
3139 if (export_env)
7117c2d2 3140 strvec_flush (export_env);
d166f048
JA
3141
3142 /* Make a guess based on how many shell variables and functions we
3143 have. Since there will always be array variables, and array
3144 variables are not (yet) exported, this will always be big enough
7117c2d2
JA
3145 for the exported variables and functions. */
3146 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3147 HASH_ENTRIES (temporary_env);
d166f048
JA
3148 if (new_size > export_env_size)
3149 {
3150 export_env_size = new_size;
7117c2d2 3151 export_env = strvec_resize (export_env, export_env_size);
d166f048
JA
3152 }
3153 export_env[export_env_index = 0] = (char *)NULL;
726f6388 3154
7117c2d2
JA
3155 /* Make a dummy variable context from the temporary_env, stick it on
3156 the front of shell_variables, call make_var_export_array on the
3157 whole thing to flatten it, and convert the list of SHELL_VAR *s
3158 to the form needed by the environment. */
3159 if (temporary_env)
3160 {
3161 tcxt = new_var_context ((char *)NULL, 0);
3162 tcxt->table = temporary_env;
3163 tcxt->down = shell_variables;
3164 }
3165 else
3166 tcxt = shell_variables;
3167
3168 temp_array = make_var_export_array (tcxt);
d166f048 3169 if (temp_array)
7117c2d2
JA
3170 add_temp_array_to_env (temp_array, 0, 0);
3171
3172 if (tcxt != shell_variables)
3173 free (tcxt);
726f6388 3174
f73dda09
JA
3175#if defined (RESTRICTED_SHELL)
3176 /* Restricted shells may not export shell functions. */
7117c2d2 3177 temp_array = restricted ? (char **)0 : make_func_export_array ();
f73dda09 3178#else
7117c2d2 3179 temp_array = make_func_export_array ();
f73dda09 3180#endif
d166f048 3181 if (temp_array)
7117c2d2 3182 add_temp_array_to_env (temp_array, 0, 0);
726f6388
JA
3183
3184 array_needs_making = 0;
3185 }
3186}
3187
b72432fd
JA
3188/* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
3189 we will need to remake the exported environment every time we
3190 change directories. `_' is always put into the environment for
3191 every external command, so without special treatment it will always
3192 cause the environment to be remade.
3193
3194 If there is no other reason to make the exported environment, we can
3195 just update the variables in place and mark the exported environment
3196 as no longer needing a remake. */
3197void
3198update_export_env_inplace (env_prefix, preflen, value)
3199 char *env_prefix;
3200 int preflen;
3201 char *value;
3202{
3203 char *evar;
3204
f73dda09 3205 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
b72432fd
JA
3206 strcpy (evar, env_prefix);
3207 if (value)
3208 strcpy (evar + preflen, value);
3209 export_env = add_or_supercede_exported_var (evar, 0);
3210}
3211
726f6388
JA
3212/* We always put _ in the environment as the name of this command. */
3213void
3214put_command_name_into_env (command_name)
3215 char *command_name;
3216{
b72432fd 3217 update_export_env_inplace ("_=", 2, command_name);
726f6388
JA
3218}
3219
cce855bc 3220#if 0 /* UNUSED -- it caused too many problems */
ccc6cda3
JA
3221void
3222put_gnu_argv_flags_into_env (pid, flags_string)
7117c2d2 3223 intmax_t pid;
ccc6cda3
JA
3224 char *flags_string;
3225{
3226 char *dummy, *pbuf;
3227 int l, fl;
3228
3229 pbuf = itos (pid);
3230 l = strlen (pbuf);
3231
3232 fl = strlen (flags_string);
3233
f73dda09 3234 dummy = (char *)xmalloc (l + fl + 30);
ccc6cda3
JA
3235 dummy[0] = '_';
3236 strcpy (dummy + 1, pbuf);
3237 strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3238 dummy[l + 27] = '=';
3239 strcpy (dummy + l + 28, flags_string);
3240
3241 free (pbuf);
3242
d166f048 3243 export_env = add_or_supercede_exported_var (dummy, 0);
ccc6cda3 3244}
cce855bc 3245#endif
726f6388 3246
7117c2d2
JA
3247/* **************************************************************** */
3248/* */
3249/* Managing variable contexts */
3250/* */
3251/* **************************************************************** */
3252
3253/* Allocate and return a new variable context with NAME and FLAGS.
3254 NAME can be NULL. */
726f6388 3255
7117c2d2
JA
3256VAR_CONTEXT *
3257new_var_context (name, flags)
3258 char *name;
3259 int flags;
3260{
3261 VAR_CONTEXT *vc;
3262
3263 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3264 vc->name = name ? savestring (name) : (char *)NULL;
3265 vc->scope = variable_context;
3266 vc->flags = flags;
3267
3268 vc->up = vc->down = (VAR_CONTEXT *)NULL;
3269 vc->table = (HASH_TABLE *)NULL;
3270
3271 return vc;
3272}
3273
3274/* Free a variable context and its data, including the hash table. Dispose
3275 all of the variables. */
3276void
3277dispose_var_context (vc)
3278 VAR_CONTEXT *vc;
3279{
3280 FREE (vc->name);
3281
3282 if (vc->table)
3283 {
3284 delete_all_variables (vc->table);
3285 hash_dispose (vc->table);
3286 }
3287
3288 free (vc);
3289}
3290
3291/* Set VAR's scope level to the current variable context. */
3292static int
3293set_context (var)
3294 SHELL_VAR *var;
3295{
3296 return (var->context = variable_context);
3297}
3298
3299/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3300 temporary variables, and push it onto shell_variables. This is
3301 for shell functions. */
3302VAR_CONTEXT *
3303push_var_context (name, flags, tempvars)
3304 char *name;
3305 int flags;
3306 HASH_TABLE *tempvars;
3307{
3308 VAR_CONTEXT *vc;
3309
3310 vc = new_var_context (name, flags);
3311 vc->table = tempvars;
3312 if (tempvars)
3313 {
3314 /* Have to do this because the temp environment was created before
3315 variable_context was incremented. */
3316 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3317 vc->flags |= VC_HASTMPVAR;
3318 }
3319 vc->down = shell_variables;
3320 shell_variables->up = vc;
3321
3322 return (shell_variables = vc);
3323}
3324
3325static void
3326push_func_var (data)
3327 PTR_T data;
3328{
3329 SHELL_VAR *var, *v;
3330
3331 var = (SHELL_VAR *)data;
3332
3333 if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3334 {
3335 /* XXX - should we set v->context here? */
3336 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
3337 if (shell_variables == global_variables)
3338 var->attributes &= ~(att_tempvar|att_propagate);
3339 else
3340 shell_variables->flags |= VC_HASTMPVAR;
3341 v->attributes |= var->attributes;
3342 }
3343
3344 dispose_variable (var);
3345}
3346
3347/* Pop the top context off of VCXT and dispose of it, returning the rest of
3348 the stack. */
3349void
3350pop_var_context ()
3351{
3352 VAR_CONTEXT *ret, *vcxt;
3353
3354 vcxt = shell_variables;
3355 if (vc_isfuncenv (vcxt) == 0)
3356 {
3357 internal_error ("pop_var_context: head of shell_variables not a function context");
3358 return;
3359 }
3360
3361 if (ret = vcxt->down)
3362 {
3363 ret->up = (VAR_CONTEXT *)NULL;
3364 shell_variables = ret;
3365 if (vcxt->table)
3366 hash_flush (vcxt->table, push_func_var);
3367 dispose_var_context (vcxt);
3368 }
3369 else
3370 internal_error ("pop_var_context: no global_variables context");
3371}
3372
3373/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3374 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3375void
3376delete_all_contexts (vcxt)
3377 VAR_CONTEXT *vcxt;
3378{
3379 VAR_CONTEXT *v, *t;
3380
3381 for (v = vcxt; v != global_variables; v = t)
3382 {
3383 t = v->down;
3384 dispose_var_context (v);
3385 }
3386
3387 delete_all_variables (global_variables->table);
3388 shell_variables = global_variables;
3389}
3390
3391/* **************************************************************** */
3392/* */
3393/* Pushing and Popping temporary variable scopes */
3394/* */
3395/* **************************************************************** */
3396
3397VAR_CONTEXT *
3398push_scope (flags, tmpvars)
3399 int flags;
3400 HASH_TABLE *tmpvars;
3401{
3402 return (push_var_context ((char *)NULL, flags, tmpvars));
3403}
3404
3405static void
3406push_exported_var (data)
3407 PTR_T data;
3408{
3409 SHELL_VAR *var, *v;
3410
3411 var = (SHELL_VAR *)data;
3412
3413 /* If a temp var had its export attribute set, or it's marked to be
3414 propagated, bind it in the previous scope before disposing it. */
3415 if (exported_p (var) || (var->attributes & att_propagate))
3416 {
3417 var->attributes &= ~att_tempvar; /* XXX */
3418 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
3419 if (shell_variables == global_variables)
3420 var->attributes &= ~att_propagate;
3421 v->attributes |= var->attributes;
3422 }
3423
3424 dispose_variable (var);
3425}
3426
3427void
3428pop_scope (is_special)
3429 int is_special;
3430{
3431 VAR_CONTEXT *vcxt, *ret;
3432
3433 vcxt = shell_variables;
3434 if (vc_istempscope (vcxt) == 0)
3435 {
3436 internal_error ("pop_scope: head of shell_variables not a temporary environment scope");
3437 return;
3438 }
3439
3440 ret = vcxt->down;
3441 if (ret)
3442 ret->up = (VAR_CONTEXT *)NULL;
3443
3444 shell_variables = ret;
3445
3446 /* Now we can take care of merging variables in VCXT into set of scopes
3447 whose head is RET (shell_variables). */
3448 FREE (vcxt->name);
3449 if (vcxt->table)
3450 {
3451 if (is_special)
3452 hash_flush (vcxt->table, push_func_var);
3453 else
3454 hash_flush (vcxt->table, push_exported_var);
3455 hash_dispose (vcxt->table);
3456 }
3457 free (vcxt);
3458
3459 sv_ifs ("IFS"); /* XXX here for now */
3460}
3461
3462/* **************************************************************** */
3463/* */
3464/* Pushing and Popping function contexts */
3465/* */
3466/* **************************************************************** */
3467
3468static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3469static int dollar_arg_stack_slots;
3470static int dollar_arg_stack_index;
3471
3472/* XXX - we might want to consider pushing and popping the `getopts' state
3473 when we modify the positional parameters. */
3474void
3475push_context (name, is_subshell, tempvars)
3476 char *name; /* function name */
3477 int is_subshell;
3478 HASH_TABLE *tempvars;
3479{
3480 if (is_subshell == 0)
3481 push_dollar_vars ();
3482 variable_context++;
3483 push_var_context (name, VC_FUNCENV, tempvars);
3484}
3485
3486/* Only called when subshell == 0, so we don't need to check, and can
3487 unconditionally pop the dollar vars off the stack. */
3488void
3489pop_context ()
726f6388 3490{
7117c2d2
JA
3491 pop_dollar_vars ();
3492 variable_context--;
3493 pop_var_context ();
726f6388 3494
7117c2d2
JA
3495 sv_ifs ("IFS"); /* XXX here for now */
3496}
726f6388 3497
7117c2d2
JA
3498/* Save the existing positional parameters on a stack. */
3499void
3500push_dollar_vars ()
3501{
3502 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3503 {
3504 dollar_arg_stack = (WORD_LIST **)
3505 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3506 * sizeof (WORD_LIST **));
3507 }
3508 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3509 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3510}
726f6388 3511
7117c2d2
JA
3512/* Restore the positional parameters from our stack. */
3513void
3514pop_dollar_vars ()
3515{
3516 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3517 return;
726f6388 3518
7117c2d2
JA
3519 remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
3520 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3521 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3522 set_dollar_vars_unchanged ();
3523}
ccc6cda3 3524
7117c2d2
JA
3525void
3526dispose_saved_dollar_vars ()
3527{
3528 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3529 return;
726f6388 3530
7117c2d2
JA
3531 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3532 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
726f6388 3533}
cce855bc 3534
d3a24ed2
CR
3535/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
3536
3537void
3538push_args (list)
3539 WORD_LIST *list;
3540{
3541#if defined (ARRAY_VARS) && defined (DEBUGGER)
3542 SHELL_VAR *bash_argv_v, *bash_argc_v;
3543 ARRAY *bash_argv_a, *bash_argc_a;
3544 WORD_LIST *l;
3545 arrayind_t i;
3546 char *t;
3547
3548 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3549 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3550
3551 for (l = list, i = 0; l; l = l->next, i++)
3552 array_push (bash_argv_a, l->word->word);
3553
3554 t = itos (i);
3555 array_push (bash_argc_a, t);
3556 free (t);
3557#endif /* ARRAY_VARS && DEBUGGER */
3558}
3559
3560/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
3561 array and use that value as the count of elements to remove from
3562 BASH_ARGV. */
3563void
3564pop_args ()
3565{
3566#if defined (ARRAY_VARS) && defined (DEBUGGER)
3567 SHELL_VAR *bash_argv_v, *bash_argc_v;
3568 ARRAY *bash_argv_a, *bash_argc_a;
3569 ARRAY_ELEMENT *ce;
3570 intmax_t i;
3571
3572 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3573 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3574
3575 ce = array_shift (bash_argc_a, 1, 0);
3576 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
3577 i = 0;
3578
3579 for ( ; i > 0; i--)
3580 array_pop (bash_argv_a);
3581 array_dispose_element (ce);
3582#endif /* ARRAY_VARS && DEBUGGER */
3583}
3584
cce855bc
JA
3585/*************************************************
3586 * *
3587 * Functions to manage special variables *
3588 * *
3589 *************************************************/
3590
3591/* Extern declarations for variables this code has to manage. */
3592extern int eof_encountered, eof_encountered_limit, ignoreeof;
3593
3594#if defined (READLINE)
3595extern int no_line_editing;
3596extern int hostname_list_initialized;
3597#endif
3598
3599/* An alist of name.function for each special variable. Most of the
3600 functions don't do much, and in fact, this would be faster with a
3601 switch statement, but by the end of this file, I am sick of switch
3602 statements. */
3603
3604#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
3605
7117c2d2 3606/* This table will be sorted with qsort() the first time it's accessed. */
cce855bc
JA
3607struct name_and_function {
3608 char *name;
f73dda09 3609 sh_sv_func_t *function;
7117c2d2 3610};
cce855bc 3611
7117c2d2 3612static struct name_and_function special_vars[] = {
cce855bc
JA
3613 { "GLOBIGNORE", sv_globignore },
3614
cce855bc 3615#if defined (HISTORY)
7117c2d2
JA
3616 { "HISTCONTROL", sv_history_control },
3617 { "HISTFILESIZE", sv_histsize },
cce855bc
JA
3618 { "HISTIGNORE", sv_histignore },
3619 { "HISTSIZE", sv_histsize },
d3a24ed2 3620 { "HISTTIMEFORMAT", sv_histtimefmt },
7117c2d2 3621#endif
cce855bc 3622
7117c2d2
JA
3623#if defined (READLINE)
3624 { "HOSTFILE", sv_hostfile },
3625#endif
cce855bc 3626
7117c2d2
JA
3627 { "IFS", sv_ifs },
3628 { "IGNOREEOF", sv_ignoreeof },
cce855bc 3629
7117c2d2 3630 { "LANG", sv_locale },
cce855bc
JA
3631 { "LC_ALL", sv_locale },
3632 { "LC_COLLATE", sv_locale },
3633 { "LC_CTYPE", sv_locale },
3634 { "LC_MESSAGES", sv_locale },
bb70624e 3635 { "LC_NUMERIC", sv_locale },
7117c2d2
JA
3636
3637 { "MAIL", sv_mail },
3638 { "MAILCHECK", sv_mail },
3639 { "MAILPATH", sv_mail },
3640
3641 { "OPTERR", sv_opterr },
3642 { "OPTIND", sv_optind },
3643
3644 { "PATH", sv_path },
3645 { "POSIXLY_CORRECT", sv_strict_posix },
3646
3647#if defined (READLINE)
3648 { "TERM", sv_terminal },
3649 { "TERMCAP", sv_terminal },
3650 { "TERMINFO", sv_terminal },
3651#endif /* READLINE */
3652
3653 { "TEXTDOMAIN", sv_locale },
3654 { "TEXTDOMAINDIR", sv_locale },
cce855bc
JA
3655
3656#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3657 { "TZ", sv_tz },
3658#endif
3659
7117c2d2
JA
3660#if defined (HISTORY) && defined (BANG_HISTORY)
3661 { "histchars", sv_histchars },
3662#endif /* HISTORY && BANG_HISTORY */
3663
3664 { "ignoreeof", sv_ignoreeof },
3665
f73dda09 3666 { (char *)0, (sh_sv_func_t *)0 }
cce855bc
JA
3667};
3668
7117c2d2
JA
3669#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
3670
3671static int
3672sv_compare (sv1, sv2)
3673 struct name_and_function *sv1, *sv2;
3674{
3675 int r;
3676
3677 if ((r = sv1->name[0] - sv2->name[0]) == 0)
3678 r = strcmp (sv1->name, sv2->name);
3679 return r;
3680}
3681
3682static inline int
3683find_special_var (name)
3684 const char *name;
3685{
3686 register int i, r;
3687
3688 for (i = 0; special_vars[i].name; i++)
3689 {
3690 r = special_vars[i].name[0] - name[0];
3691 if (r == 0)
3692 r = strcmp (special_vars[i].name, name);
3693 if (r == 0)
3694 return i;
3695 else if (r > 0)
3696 /* Can't match any of rest of elements in sorted list. Take this out
3697 if it causes problems in certain environments. */
3698 break;
3699 }
3700 return -1;
3701}
3702
cce855bc
JA
3703/* The variable in NAME has just had its state changed. Check to see if it
3704 is one of the special ones where something special happens. */
3705void
3706stupidly_hack_special_variables (name)
3707 char *name;
3708{
7117c2d2 3709 static int sv_sorted = 0;
cce855bc
JA
3710 int i;
3711
7117c2d2 3712 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
cce855bc 3713 {
7117c2d2
JA
3714 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
3715 (QSFUNC *)sv_compare);
3716 sv_sorted = 1;
cce855bc 3717 }
7117c2d2
JA
3718
3719 i = find_special_var (name);
3720 if (i != -1)
3721 (*(special_vars[i].function)) (name);
3722}
3723
3724void
3725sv_ifs (name)
3726 char *name;
3727{
3728 SHELL_VAR *v;
3729
3730 v = find_variable ("IFS");
3731 setifs (v);
cce855bc
JA
3732}
3733
3734/* What to do just after the PATH variable has changed. */
3735void
3736sv_path (name)
3737 char *name;
3738{
3739 /* hash -r */
7117c2d2 3740 phash_flush ();
cce855bc
JA
3741}
3742
3743/* What to do just after one of the MAILxxxx variables has changed. NAME
3744 is the name of the variable. This is called with NAME set to one of
3745 MAIL, MAILCHECK, or MAILPATH. */
3746void
3747sv_mail (name)
3748 char *name;
3749{
3750 /* If the time interval for checking the files has changed, then
3751 reset the mail timer. Otherwise, one of the pathname vars
3752 to the users mailbox has changed, so rebuild the array of
3753 filenames. */
3754 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
3755 reset_mail_timer ();
3756 else
3757 {
3758 free_mail_files ();
3759 remember_mail_dates ();
3760 }
3761}
3762
3763/* What to do when GLOBIGNORE changes. */
3764void
3765sv_globignore (name)
3766 char *name;
3767{
3768 setup_glob_ignore (name);
3769}
3770
3771#if defined (READLINE)
3772/* What to do just after one of the TERMxxx variables has changed.
3773 If we are an interactive shell, then try to reset the terminal
3774 information in readline. */
3775void
3776sv_terminal (name)
3777 char *name;
3778{
3779 if (interactive_shell && no_line_editing == 0)
3780 rl_reset_terminal (get_string_value ("TERM"));
3781}
3782
3783void
3784sv_hostfile (name)
3785 char *name;
3786{
bb70624e
JA
3787 SHELL_VAR *v;
3788
3789 v = find_variable (name);
3790 if (v == 0)
3791 clear_hostname_list ();
3792 else
3793 hostname_list_initialized = 0;
cce855bc
JA
3794}
3795#endif /* READLINE */
3796
3797#if defined (HISTORY)
3798/* What to do after the HISTSIZE or HISTFILESIZE variables change.
3799 If there is a value for this HISTSIZE (and it is numeric), then stifle
3800 the history. Otherwise, if there is NO value for this variable,
3801 unstifle the history. If name is HISTFILESIZE, and its value is
3802 numeric, truncate the history file to hold no more than that many
3803 lines. */
3804void
3805sv_histsize (name)
3806 char *name;
3807{
3808 char *temp;
7117c2d2 3809 intmax_t num;
cce855bc
JA
3810
3811 temp = get_string_value (name);
3812
3813 if (temp && *temp)
3814 {
3815 if (legal_number (temp, &num))
28ef6c31 3816 {
cce855bc
JA
3817 if (name[4] == 'S')
3818 {
3819 stifle_history (num);
3820 num = where_history ();
3821 if (history_lines_this_session > num)
3822 history_lines_this_session = num;
3823 }
3824 else
3825 {
3826 history_truncate_file (get_string_value ("HISTFILE"), (int)num);
3827 if (num <= history_lines_in_file)
3828 history_lines_in_file = num;
3829 }
3830 }
3831 }
3832 else if (name[4] == 'S')
3833 unstifle_history ();
3834}
3835
3836/* What to do after the HISTIGNORE variable changes. */
3837void
3838sv_histignore (name)
3839 char *name;
3840{
3841 setup_history_ignore (name);
3842}
3843
3844/* What to do after the HISTCONTROL variable changes. */
3845void
3846sv_history_control (name)
3847 char *name;
3848{
3849 char *temp;
d3a24ed2
CR
3850 char *val;
3851 int tptr;
cce855bc
JA
3852
3853 history_control = 0;
3854 temp = get_string_value (name);
3855
d3a24ed2
CR
3856 if (temp == 0 || *temp == 0)
3857 return;
3858
3859 tptr = 0;
3860 while (val = extract_colon_unit (temp, &tptr))
cce855bc 3861 {
d3a24ed2
CR
3862 if (STREQ (val, "ignorespace"))
3863 history_control |= HC_IGNSPACE;
3864 else if (STREQ (val, "ignoredups"))
3865 history_control |= HC_IGNDUPS;
3866 else if (STREQ (val, "ignoreboth"))
3867 history_control |= HC_IGNBOTH;
3868 else if (STREQ (val, "erasedups"))
3869 history_control |= HC_ERASEDUPS;
3870
3871 free (val);
cce855bc
JA
3872 }
3873}
3874
3875#if defined (BANG_HISTORY)
3876/* Setting/unsetting of the history expansion character. */
3877void
3878sv_histchars (name)
3879 char *name;
3880{
3881 char *temp;
3882
3883 temp = get_string_value (name);
3884 if (temp)
3885 {
3886 history_expansion_char = *temp;
3887 if (temp[0] && temp[1])
3888 {
3889 history_subst_char = temp[1];
3890 if (temp[2])
3891 history_comment_char = temp[2];
3892 }
3893 }
3894 else
3895 {
3896 history_expansion_char = '!';
3897 history_subst_char = '^';
3898 history_comment_char = '#';
3899 }
3900}
3901#endif /* BANG_HISTORY */
d3a24ed2
CR
3902
3903void
3904sv_histtimefmt (name)
3905 char *name;
3906{
3907 SHELL_VAR *v;
3908
3909 v = find_variable (name);
3910 history_write_timestamps = (v != 0);
3911}
cce855bc
JA
3912#endif /* HISTORY */
3913
3914#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3915void
3916sv_tz (name)
3917 char *name;
3918{
3919 tzset ();
3920}
3921#endif
3922
3923/* If the variable exists, then the value of it can be the number
3924 of times we actually ignore the EOF. The default is small,
3925 (smaller than csh, anyway). */
3926void
3927sv_ignoreeof (name)
3928 char *name;
3929{
3930 SHELL_VAR *tmp_var;
3931 char *temp;
3932
3933 eof_encountered = 0;
3934
3935 tmp_var = find_variable (name);
3936 ignoreeof = tmp_var != 0;
3937 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
3938 if (temp)
3939 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
3940 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
3941}
3942
3943void
3944sv_optind (name)
3945 char *name;
3946{
3947 char *tt;
3948 int s;
3949
3950 tt = get_string_value ("OPTIND");
3951 if (tt && *tt)
3952 {
3953 s = atoi (tt);
3954
3955 /* According to POSIX, setting OPTIND=1 resets the internal state
3956 of getopt (). */
3957 if (s < 0 || s == 1)
3958 s = 0;
3959 }
3960 else
3961 s = 0;
3962 getopts_reset (s);
3963}
3964
3965void
3966sv_opterr (name)
3967 char *name;
3968{
3969 char *tt;
3970
3971 tt = get_string_value ("OPTERR");
3972 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
3973}
3974
3975void
3976sv_strict_posix (name)
3977 char *name;
3978{
3979 SET_INT_VAR (name, posixly_correct);
3980 posix_initialize (posixly_correct);
3981#if defined (READLINE)
3982 if (interactive_shell)
3983 posix_readline_initialize (posixly_correct);
3984#endif /* READLINE */
3985 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
3986}
3987
3988void
3989sv_locale (name)
3990 char *name;
3991{
3992 char *v;
3993
3994 v = get_string_value (name);
3995 if (name[0] == 'L' && name[1] == 'A') /* LANG */
3996 set_lang (name, v);
3997 else
3998 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
3999}
4000
4001#if defined (ARRAY_VARS)
4002void
7117c2d2 4003set_pipestatus_array (ps, nproc)
cce855bc 4004 int *ps;
7117c2d2 4005 int nproc;
cce855bc
JA
4006{
4007 SHELL_VAR *v;
4008 ARRAY *a;
7117c2d2 4009 ARRAY_ELEMENT *ae;
cce855bc 4010 register int i;
f73dda09 4011 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
cce855bc
JA
4012
4013 v = find_variable ("PIPESTATUS");
4014 if (v == 0)
4015 v = make_new_array_variable ("PIPESTATUS");
4016 if (array_p (v) == 0)
4017 return; /* Do nothing if not an array variable. */
4018 a = array_cell (v);
7117c2d2
JA
4019
4020 if (a == 0 || array_num_elements (a) == 0)
cce855bc 4021 {
7117c2d2
JA
4022 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
4023 {
4024 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4025 array_insert (a, i, t);
4026 }
4027 return;
4028 }
4029
4030 /* Fast case */
4031 if (array_num_elements (a) == nproc && nproc == 1)
4032 {
4033 ae = element_forw (a->head);
4034 free (element_value (ae));
4035 ae->value = itos (ps[0]);
4036 }
4037 else if (array_num_elements (a) <= nproc)
4038 {
4039 /* modify in array_num_elements members in place, then add */
4040 ae = a->head;
4041 for (i = 0; i < array_num_elements (a); i++)
4042 {
4043 ae = element_forw (ae);
4044 free (element_value (ae));
4045 ae->value = itos (ps[i]);
4046 }
4047 /* add any more */
4048 for ( ; i < nproc; i++)
4049 {
4050 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4051 array_insert (a, i, t);
4052 }
4053 }
4054 else
4055 {
4056 /* deleting elements. it's faster to rebuild the array. */
4057 array_flush (a);
4058 for (i = 0; ps[i] != -1; i++)
4059 {
4060 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4061 array_insert (a, i, t);
4062 }
cce855bc
JA
4063 }
4064}
4065#endif
4066
4067void
4068set_pipestatus_from_exit (s)
4069 int s;
4070{
4071#if defined (ARRAY_VARS)
4072 static int v[2] = { 0, -1 };
4073
4074 v[0] = s;
7117c2d2 4075 set_pipestatus_array (v, 1);
cce855bc
JA
4076#endif
4077}