source: vendor/bash/3.1/variables.c@ 3741

Last change on this file since 3741 was 3228, checked in by bird, 18 years ago

bash 3.1

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