source: vendor/bash/3.1-p17/variables.c@ 3532

Last change on this file since 3532 was 3238, checked in by bird, 18 years ago

Applied bash31-003

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