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