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