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