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