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