source: trunk/essentials/app-shells/bash/variables.c

Last change on this file was 3285, checked in by bird, 18 years ago

Implemented set special *LIBPATH* variables.

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