]> git.ipfire.org Git - thirdparty/bash.git/blob - variables.c
commit bash-20100115 snapshot
[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 fprintf(stderr, "get_random: rv = %d\n", rv);
1313 p = itos (rv);
1314
1315 FREE (value_cell (var));
1316
1317 VSETATTR (var, att_integer);
1318 var_setvalue (var, p);
1319 return (var);
1320 }
1321
1322 static SHELL_VAR *
1323 assign_lineno (var, value, unused, key)
1324 SHELL_VAR *var;
1325 char *value;
1326 arrayind_t unused;
1327 char *key;
1328 {
1329 intmax_t new_value;
1330
1331 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1332 new_value = 0;
1333 line_number = new_value;
1334 return var;
1335 }
1336
1337 /* Function which returns the current line number. */
1338 static SHELL_VAR *
1339 get_lineno (var)
1340 SHELL_VAR *var;
1341 {
1342 char *p;
1343 int ln;
1344
1345 ln = executing_line_number ();
1346 p = itos (ln);
1347 FREE (value_cell (var));
1348 var_setvalue (var, p);
1349 return (var);
1350 }
1351
1352 static SHELL_VAR *
1353 assign_subshell (var, value, unused, key)
1354 SHELL_VAR *var;
1355 char *value;
1356 arrayind_t unused;
1357 char *key;
1358 {
1359 intmax_t new_value;
1360
1361 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1362 new_value = 0;
1363 subshell_level = new_value;
1364 return var;
1365 }
1366
1367 static SHELL_VAR *
1368 get_subshell (var)
1369 SHELL_VAR *var;
1370 {
1371 char *p;
1372
1373 p = itos (subshell_level);
1374 FREE (value_cell (var));
1375 var_setvalue (var, p);
1376 return (var);
1377 }
1378
1379 static SHELL_VAR *
1380 get_bashpid (var)
1381 SHELL_VAR *var;
1382 {
1383 int pid;
1384 char *p;
1385
1386 pid = getpid ();
1387 p = itos (pid);
1388
1389 FREE (value_cell (var));
1390 VSETATTR (var, att_integer|att_readonly);
1391 var_setvalue (var, p);
1392 return (var);
1393 }
1394
1395 static SHELL_VAR *
1396 get_bash_command (var)
1397 SHELL_VAR *var;
1398 {
1399 char *p;
1400
1401 if (the_printed_command_except_trap)
1402 p = savestring (the_printed_command_except_trap);
1403 else
1404 {
1405 p = (char *)xmalloc (1);
1406 p[0] = '\0';
1407 }
1408 FREE (value_cell (var));
1409 var_setvalue (var, p);
1410 return (var);
1411 }
1412
1413 #if defined (HISTORY)
1414 static SHELL_VAR *
1415 get_histcmd (var)
1416 SHELL_VAR *var;
1417 {
1418 char *p;
1419
1420 p = itos (history_number ());
1421 FREE (value_cell (var));
1422 var_setvalue (var, p);
1423 return (var);
1424 }
1425 #endif
1426
1427 #if defined (READLINE)
1428 /* When this function returns, VAR->value points to malloced memory. */
1429 static SHELL_VAR *
1430 get_comp_wordbreaks (var)
1431 SHELL_VAR *var;
1432 {
1433 /* If we don't have anything yet, assign a default value. */
1434 if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1435 enable_hostname_completion (perform_hostname_completion);
1436
1437 FREE (value_cell (var));
1438 var_setvalue (var, savestring (rl_completer_word_break_characters));
1439
1440 return (var);
1441 }
1442
1443 /* When this function returns, rl_completer_word_break_characters points to
1444 malloced memory. */
1445 static SHELL_VAR *
1446 assign_comp_wordbreaks (self, value, unused, key)
1447 SHELL_VAR *self;
1448 char *value;
1449 arrayind_t unused;
1450 char *key;
1451 {
1452 if (rl_completer_word_break_characters &&
1453 rl_completer_word_break_characters != rl_basic_word_break_characters)
1454 free (rl_completer_word_break_characters);
1455
1456 rl_completer_word_break_characters = savestring (value);
1457 return self;
1458 }
1459 #endif /* READLINE */
1460
1461 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1462 static SHELL_VAR *
1463 assign_dirstack (self, value, ind, key)
1464 SHELL_VAR *self;
1465 char *value;
1466 arrayind_t ind;
1467 char *key;
1468 {
1469 set_dirstack_element (ind, 1, value);
1470 return self;
1471 }
1472
1473 static SHELL_VAR *
1474 get_dirstack (self)
1475 SHELL_VAR *self;
1476 {
1477 ARRAY *a;
1478 WORD_LIST *l;
1479
1480 l = get_directory_stack (0);
1481 a = array_from_word_list (l);
1482 array_dispose (array_cell (self));
1483 dispose_words (l);
1484 var_setarray (self, a);
1485 return self;
1486 }
1487 #endif /* PUSHD AND POPD && ARRAY_VARS */
1488
1489 #if defined (ARRAY_VARS)
1490 /* We don't want to initialize the group set with a call to getgroups()
1491 unless we're asked to, but we only want to do it once. */
1492 static SHELL_VAR *
1493 get_groupset (self)
1494 SHELL_VAR *self;
1495 {
1496 register int i;
1497 int ng;
1498 ARRAY *a;
1499 static char **group_set = (char **)NULL;
1500
1501 if (group_set == 0)
1502 {
1503 group_set = get_group_list (&ng);
1504 a = array_cell (self);
1505 for (i = 0; i < ng; i++)
1506 array_insert (a, i, group_set[i]);
1507 }
1508 return (self);
1509 }
1510
1511 static SHELL_VAR *
1512 build_hashcmd (self)
1513 SHELL_VAR *self;
1514 {
1515 HASH_TABLE *h;
1516 int i;
1517 char *k, *v;
1518 BUCKET_CONTENTS *item;
1519
1520 h = assoc_cell (self);
1521 if (h)
1522 assoc_dispose (h);
1523
1524 if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
1525 {
1526 var_setvalue (self, (char *)NULL);
1527 return self;
1528 }
1529
1530 h = assoc_create (hashed_filenames->nbuckets);
1531 for (i = 0; i < hashed_filenames->nbuckets; i++)
1532 {
1533 for (item = hash_items (i, hashed_filenames); item; item = item->next)
1534 {
1535 k = savestring (item->key);
1536 v = pathdata(item)->path;
1537 assoc_insert (h, k, v);
1538 }
1539 }
1540
1541 var_setvalue (self, (char *)h);
1542 return self;
1543 }
1544
1545 static SHELL_VAR *
1546 get_hashcmd (self)
1547 SHELL_VAR *self;
1548 {
1549 build_hashcmd (self);
1550 return (self);
1551 }
1552
1553 static SHELL_VAR *
1554 assign_hashcmd (self, value, ind, key)
1555 SHELL_VAR *self;
1556 char *value;
1557 arrayind_t ind;
1558 char *key;
1559 {
1560 phash_insert (key, value, 0, 0);
1561 return (build_hashcmd (self));
1562 }
1563
1564 #if defined (ALIAS)
1565 static SHELL_VAR *
1566 build_aliasvar (self)
1567 SHELL_VAR *self;
1568 {
1569 HASH_TABLE *h;
1570 int i;
1571 char *k, *v;
1572 BUCKET_CONTENTS *item;
1573
1574 h = assoc_cell (self);
1575 if (h)
1576 assoc_dispose (h);
1577
1578 if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
1579 {
1580 var_setvalue (self, (char *)NULL);
1581 return self;
1582 }
1583
1584 h = assoc_create (aliases->nbuckets);
1585 for (i = 0; i < aliases->nbuckets; i++)
1586 {
1587 for (item = hash_items (i, aliases); item; item = item->next)
1588 {
1589 k = savestring (item->key);
1590 v = ((alias_t *)(item->data))->value;
1591 assoc_insert (h, k, v);
1592 }
1593 }
1594
1595 var_setvalue (self, (char *)h);
1596 return self;
1597 }
1598
1599 static SHELL_VAR *
1600 get_aliasvar (self)
1601 SHELL_VAR *self;
1602 {
1603 build_aliasvar (self);
1604 return (self);
1605 }
1606
1607 static SHELL_VAR *
1608 assign_aliasvar (self, value, ind, key)
1609 SHELL_VAR *self;
1610 char *value;
1611 arrayind_t ind;
1612 char *key;
1613 {
1614 add_alias (key, value);
1615 return (build_aliasvar (self));
1616 }
1617 #endif /* ALIAS */
1618
1619 #endif /* ARRAY_VARS */
1620
1621 /* If ARRAY_VARS is not defined, this just returns the name of any
1622 currently-executing function. If we have arrays, it's a call stack. */
1623 static SHELL_VAR *
1624 get_funcname (self)
1625 SHELL_VAR *self;
1626 {
1627 #if ! defined (ARRAY_VARS)
1628 char *t;
1629 if (variable_context && this_shell_function)
1630 {
1631 FREE (value_cell (self));
1632 t = savestring (this_shell_function->name);
1633 var_setvalue (self, t);
1634 }
1635 #endif
1636 return (self);
1637 }
1638
1639 void
1640 make_funcname_visible (on_or_off)
1641 int on_or_off;
1642 {
1643 SHELL_VAR *v;
1644
1645 v = find_variable ("FUNCNAME");
1646 if (v == 0 || v->dynamic_value == 0)
1647 return;
1648
1649 if (on_or_off)
1650 VUNSETATTR (v, att_invisible);
1651 else
1652 VSETATTR (v, att_invisible);
1653 }
1654
1655 static SHELL_VAR *
1656 init_funcname_var ()
1657 {
1658 SHELL_VAR *v;
1659
1660 v = find_variable ("FUNCNAME");
1661 if (v)
1662 return v;
1663 #if defined (ARRAY_VARS)
1664 INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1665 #else
1666 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1667 #endif
1668 VSETATTR (v, att_invisible|att_noassign);
1669 return v;
1670 }
1671
1672 static void
1673 initialize_dynamic_variables ()
1674 {
1675 SHELL_VAR *v;
1676
1677 v = init_seconds_var ();
1678
1679 INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1680 INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1681
1682 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1683 VSETATTR (v, att_integer);
1684 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1685 VSETATTR (v, att_integer);
1686
1687 INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
1688 VSETATTR (v, att_integer|att_readonly);
1689
1690 #if defined (HISTORY)
1691 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
1692 VSETATTR (v, att_integer);
1693 #endif
1694
1695 #if defined (READLINE)
1696 INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1697 #endif
1698
1699 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1700 v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
1701 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1702
1703 #if defined (ARRAY_VARS)
1704 v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1705
1706 # if defined (DEBUGGER)
1707 v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
1708 v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
1709 # endif /* DEBUGGER */
1710 v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
1711 v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
1712
1713 v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree);
1714 # if defined (ALIAS)
1715 v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree);
1716 # endif
1717 #endif
1718
1719 v = init_funcname_var ();
1720 }
1721
1722 /* **************************************************************** */
1723 /* */
1724 /* Retrieving variables and values */
1725 /* */
1726 /* **************************************************************** */
1727
1728 /* How to get a pointer to the shell variable or function named NAME.
1729 HASHED_VARS is a pointer to the hash table containing the list
1730 of interest (either variables or functions). */
1731
1732 static SHELL_VAR *
1733 hash_lookup (name, hashed_vars)
1734 const char *name;
1735 HASH_TABLE *hashed_vars;
1736 {
1737 BUCKET_CONTENTS *bucket;
1738
1739 bucket = hash_search (name, hashed_vars, 0);
1740 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1741 }
1742
1743 SHELL_VAR *
1744 var_lookup (name, vcontext)
1745 const char *name;
1746 VAR_CONTEXT *vcontext;
1747 {
1748 VAR_CONTEXT *vc;
1749 SHELL_VAR *v;
1750
1751 v = (SHELL_VAR *)NULL;
1752 for (vc = vcontext; vc; vc = vc->down)
1753 if (v = hash_lookup (name, vc->table))
1754 break;
1755
1756 return v;
1757 }
1758
1759 /* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
1760 then also search the temporarily built list of exported variables.
1761 The lookup order is:
1762 temporary_env
1763 shell_variables list
1764 */
1765
1766 SHELL_VAR *
1767 find_variable_internal (name, force_tempenv)
1768 const char *name;
1769 int force_tempenv;
1770 {
1771 SHELL_VAR *var;
1772 int search_tempenv;
1773
1774 var = (SHELL_VAR *)NULL;
1775
1776 /* If explicitly requested, first look in the temporary environment for
1777 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
1778 to get the `exported' value of $foo. This happens if we are executing
1779 a function or builtin, or if we are looking up a variable in a
1780 "subshell environment". */
1781 search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1782
1783 if (search_tempenv && temporary_env)
1784 var = hash_lookup (name, temporary_env);
1785
1786 if (var == 0)
1787 var = var_lookup (name, shell_variables);
1788
1789 if (var == 0)
1790 return ((SHELL_VAR *)NULL);
1791
1792 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1793 }
1794
1795 /* Look up the variable entry named NAME. Returns the entry or NULL. */
1796 SHELL_VAR *
1797 find_variable (name)
1798 const char *name;
1799 {
1800 return (find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))));
1801 }
1802
1803 /* Look up the function entry whose name matches STRING.
1804 Returns the entry or NULL. */
1805 SHELL_VAR *
1806 find_function (name)
1807 const char *name;
1808 {
1809 return (hash_lookup (name, shell_functions));
1810 }
1811
1812 /* Find the function definition for the shell function named NAME. Returns
1813 the entry or NULL. */
1814 FUNCTION_DEF *
1815 find_function_def (name)
1816 const char *name;
1817 {
1818 #if defined (DEBUGGER)
1819 return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
1820 #else
1821 return ((FUNCTION_DEF *)0);
1822 #endif
1823 }
1824
1825 /* Return the value of VAR. VAR is assumed to have been the result of a
1826 lookup without any subscript, if arrays are compiled into the shell. */
1827 char *
1828 get_variable_value (var)
1829 SHELL_VAR *var;
1830 {
1831 if (var == 0)
1832 return ((char *)NULL);
1833 #if defined (ARRAY_VARS)
1834 else if (array_p (var))
1835 return (array_reference (array_cell (var), 0));
1836 else if (assoc_p (var))
1837 return (assoc_reference (assoc_cell (var), "0"));
1838 #endif
1839 else
1840 return (value_cell (var));
1841 }
1842
1843 /* Return the string value of a variable. Return NULL if the variable
1844 doesn't exist. Don't cons a new string. This is a potential memory
1845 leak if the variable is found in the temporary environment. Since
1846 functions and variables have separate name spaces, returns NULL if
1847 var_name is a shell function only. */
1848 char *
1849 get_string_value (var_name)
1850 const char *var_name;
1851 {
1852 SHELL_VAR *var;
1853
1854 var = find_variable (var_name);
1855 return ((var) ? get_variable_value (var) : (char *)NULL);
1856 }
1857
1858 /* This is present for use by the tilde and readline libraries. */
1859 char *
1860 sh_get_env_value (v)
1861 const char *v;
1862 {
1863 return get_string_value (v);
1864 }
1865
1866 /* **************************************************************** */
1867 /* */
1868 /* Creating and setting variables */
1869 /* */
1870 /* **************************************************************** */
1871
1872 /* Set NAME to VALUE if NAME has no value. */
1873 SHELL_VAR *
1874 set_if_not (name, value)
1875 char *name, *value;
1876 {
1877 SHELL_VAR *v;
1878
1879 if (shell_variables == 0)
1880 create_variable_tables ();
1881
1882 v = find_variable (name);
1883 if (v == 0)
1884 v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
1885 return (v);
1886 }
1887
1888 /* Create a local variable referenced by NAME. */
1889 SHELL_VAR *
1890 make_local_variable (name)
1891 const char *name;
1892 {
1893 SHELL_VAR *new_var, *old_var;
1894 VAR_CONTEXT *vc;
1895 int was_tmpvar;
1896 char *tmp_value;
1897
1898 /* local foo; local foo; is a no-op. */
1899 old_var = find_variable (name);
1900 if (old_var && local_p (old_var) && old_var->context == variable_context)
1901 {
1902 VUNSETATTR (old_var, att_invisible);
1903 return (old_var);
1904 }
1905
1906 was_tmpvar = old_var && tempvar_p (old_var);
1907 if (was_tmpvar)
1908 tmp_value = value_cell (old_var);
1909
1910 for (vc = shell_variables; vc; vc = vc->down)
1911 if (vc_isfuncenv (vc) && vc->scope == variable_context)
1912 break;
1913
1914 if (vc == 0)
1915 {
1916 internal_error (_("make_local_variable: no function context at current scope"));
1917 return ((SHELL_VAR *)NULL);
1918 }
1919 else if (vc->table == 0)
1920 vc->table = hash_create (TEMPENV_HASH_BUCKETS);
1921
1922 /* Since this is called only from the local/declare/typeset code, we can
1923 call builtin_error here without worry (of course, it will also work
1924 for anything that sets this_command_name). Variables with the `noassign'
1925 attribute may not be made local. The test against old_var's context
1926 level is to disallow local copies of readonly global variables (since I
1927 believe that this could be a security hole). Readonly copies of calling
1928 function local variables are OK. */
1929 if (old_var && (noassign_p (old_var) ||
1930 (readonly_p (old_var) && old_var->context == 0)))
1931 {
1932 if (readonly_p (old_var))
1933 sh_readonly (name);
1934 return ((SHELL_VAR *)NULL);
1935 }
1936
1937 if (old_var == 0)
1938 new_var = make_new_variable (name, vc->table);
1939 else
1940 {
1941 new_var = make_new_variable (name, vc->table);
1942
1943 /* If we found this variable in one of the temporary environments,
1944 inherit its value. Watch to see if this causes problems with
1945 things like `x=4 local x'. */
1946 if (was_tmpvar)
1947 var_setvalue (new_var, savestring (tmp_value));
1948
1949 new_var->attributes = exported_p (old_var) ? att_exported : 0;
1950 }
1951
1952 vc->flags |= VC_HASLOCAL;
1953
1954 new_var->context = variable_context;
1955 VSETATTR (new_var, att_local);
1956
1957 if (ifsname (name))
1958 setifs (new_var);
1959
1960 return (new_var);
1961 }
1962
1963 /* Create a new shell variable with name NAME. */
1964 static SHELL_VAR *
1965 new_shell_variable (name)
1966 const char *name;
1967 {
1968 SHELL_VAR *entry;
1969
1970 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1971
1972 entry->name = savestring (name);
1973 var_setvalue (entry, (char *)NULL);
1974 CLEAR_EXPORTSTR (entry);
1975
1976 entry->dynamic_value = (sh_var_value_func_t *)NULL;
1977 entry->assign_func = (sh_var_assign_func_t *)NULL;
1978
1979 entry->attributes = 0;
1980
1981 /* Always assume variables are to be made at toplevel!
1982 make_local_variable has the responsibilty of changing the
1983 variable context. */
1984 entry->context = 0;
1985
1986 return (entry);
1987 }
1988
1989 /* Create a new shell variable with name NAME and add it to the hash table
1990 TABLE. */
1991 static SHELL_VAR *
1992 make_new_variable (name, table)
1993 const char *name;
1994 HASH_TABLE *table;
1995 {
1996 SHELL_VAR *entry;
1997 BUCKET_CONTENTS *elt;
1998
1999 entry = new_shell_variable (name);
2000
2001 /* Make sure we have a shell_variables hash table to add to. */
2002 if (shell_variables == 0)
2003 create_variable_tables ();
2004
2005 elt = hash_insert (savestring (name), table, HASH_NOSRCH);
2006 elt->data = (PTR_T)entry;
2007
2008 return entry;
2009 }
2010
2011 #if defined (ARRAY_VARS)
2012 SHELL_VAR *
2013 make_new_array_variable (name)
2014 char *name;
2015 {
2016 SHELL_VAR *entry;
2017 ARRAY *array;
2018
2019 entry = make_new_variable (name, global_variables->table);
2020 array = array_create ();
2021
2022 var_setarray (entry, array);
2023 VSETATTR (entry, att_array);
2024 return entry;
2025 }
2026
2027 SHELL_VAR *
2028 make_local_array_variable (name)
2029 char *name;
2030 {
2031 SHELL_VAR *var;
2032 ARRAY *array;
2033
2034 var = make_local_variable (name);
2035 if (var == 0 || array_p (var))
2036 return var;
2037
2038 array = array_create ();
2039
2040 dispose_variable_value (var);
2041 var_setarray (var, array);
2042 VSETATTR (var, att_array);
2043 return var;
2044 }
2045
2046 SHELL_VAR *
2047 make_new_assoc_variable (name)
2048 char *name;
2049 {
2050 SHELL_VAR *entry;
2051 HASH_TABLE *hash;
2052
2053 entry = make_new_variable (name, global_variables->table);
2054 hash = assoc_create (0);
2055
2056 var_setassoc (entry, hash);
2057 VSETATTR (entry, att_assoc);
2058 return entry;
2059 }
2060
2061 SHELL_VAR *
2062 make_local_assoc_variable (name)
2063 char *name;
2064 {
2065 SHELL_VAR *var;
2066 HASH_TABLE *hash;
2067
2068 var = make_local_variable (name);
2069 if (var == 0 || assoc_p (var))
2070 return var;
2071
2072 dispose_variable_value (var);
2073 hash = assoc_create (0);
2074
2075 var_setassoc (var, hash);
2076 VSETATTR (var, att_assoc);
2077 return var;
2078 }
2079 #endif
2080
2081 char *
2082 make_variable_value (var, value, flags)
2083 SHELL_VAR *var;
2084 char *value;
2085 int flags;
2086 {
2087 char *retval, *oval;
2088 intmax_t lval, rval;
2089 int expok, olen, op;
2090
2091 /* If this variable has had its type set to integer (via `declare -i'),
2092 then do expression evaluation on it and store the result. The
2093 functions in expr.c (evalexp()) and bind_int_variable() are responsible
2094 for turning off the integer flag if they don't want further
2095 evaluation done. */
2096 if (integer_p (var))
2097 {
2098 if (flags & ASS_APPEND)
2099 {
2100 oval = value_cell (var);
2101 lval = evalexp (oval, &expok); /* ksh93 seems to do this */
2102 if (expok == 0)
2103 {
2104 top_level_cleanup ();
2105 jump_to_top_level (DISCARD);
2106 }
2107 }
2108 rval = evalexp (value, &expok);
2109 if (expok == 0)
2110 {
2111 top_level_cleanup ();
2112 jump_to_top_level (DISCARD);
2113 }
2114 if (flags & ASS_APPEND)
2115 rval += lval;
2116 retval = itos (rval);
2117 }
2118 #if defined (CASEMOD_ATTRS)
2119 else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var))
2120 {
2121 if (flags & ASS_APPEND)
2122 {
2123 oval = get_variable_value (var);
2124 if (oval == 0) /* paranoia */
2125 oval = "";
2126 olen = STRLEN (oval);
2127 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2128 strcpy (retval, oval);
2129 if (value)
2130 strcpy (retval+olen, value);
2131 }
2132 else if (*value)
2133 retval = savestring (value);
2134 else
2135 {
2136 retval = (char *)xmalloc (1);
2137 retval[0] = '\0';
2138 }
2139 op = capcase_p (var) ? CASE_CAPITALIZE
2140 : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER);
2141 oval = sh_modcase (retval, (char *)0, op);
2142 free (retval);
2143 retval = oval;
2144 }
2145 #endif /* CASEMOD_ATTRS */
2146 else if (value)
2147 {
2148 if (flags & ASS_APPEND)
2149 {
2150 oval = get_variable_value (var);
2151 if (oval == 0) /* paranoia */
2152 oval = "";
2153 olen = STRLEN (oval);
2154 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
2155 strcpy (retval, oval);
2156 if (value)
2157 strcpy (retval+olen, value);
2158 }
2159 else if (*value)
2160 retval = savestring (value);
2161 else
2162 {
2163 retval = (char *)xmalloc (1);
2164 retval[0] = '\0';
2165 }
2166 }
2167 else
2168 retval = (char *)NULL;
2169
2170 return retval;
2171 }
2172
2173 /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
2174 temporary environment (but usually is not). */
2175 static SHELL_VAR *
2176 bind_variable_internal (name, value, table, hflags, aflags)
2177 const char *name;
2178 char *value;
2179 HASH_TABLE *table;
2180 int hflags, aflags;
2181 {
2182 char *newval;
2183 SHELL_VAR *entry;
2184
2185 entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
2186
2187 if (entry == 0)
2188 {
2189 entry = make_new_variable (name, table);
2190 var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
2191 }
2192 else if (entry->assign_func) /* array vars have assign functions now */
2193 {
2194 INVALIDATE_EXPORTSTR (entry);
2195 newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
2196 if (assoc_p (entry))
2197 entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0"));
2198 else if (array_p (entry))
2199 entry = (*(entry->assign_func)) (entry, newval, 0, 0);
2200 else
2201 entry = (*(entry->assign_func)) (entry, newval, -1, 0);
2202 if (newval != value)
2203 free (newval);
2204 return (entry);
2205 }
2206 else
2207 {
2208 if (readonly_p (entry) || noassign_p (entry))
2209 {
2210 if (readonly_p (entry))
2211 err_readonly (name);
2212 return (entry);
2213 }
2214
2215 /* Variables which are bound are visible. */
2216 VUNSETATTR (entry, att_invisible);
2217
2218 newval = make_variable_value (entry, value, aflags); /* XXX */
2219
2220 /* Invalidate any cached export string */
2221 INVALIDATE_EXPORTSTR (entry);
2222
2223 #if defined (ARRAY_VARS)
2224 /* XXX -- this bears looking at again -- XXX */
2225 /* If an existing array variable x is being assigned to with x=b or
2226 `read x' or something of that nature, silently convert it to
2227 x[0]=b or `read x[0]'. */
2228 if (array_p (entry))
2229 {
2230 array_insert (array_cell (entry), 0, newval);
2231 free (newval);
2232 }
2233 else if (assoc_p (entry))
2234 {
2235 assoc_insert (assoc_cell (entry), savestring ("0"), newval);
2236 free (newval);
2237 }
2238 else
2239 #endif
2240 {
2241 FREE (value_cell (entry));
2242 var_setvalue (entry, newval);
2243 }
2244 }
2245
2246 if (mark_modified_vars)
2247 VSETATTR (entry, att_exported);
2248
2249 if (exported_p (entry))
2250 array_needs_making = 1;
2251
2252 return (entry);
2253 }
2254
2255 /* Bind a variable NAME to VALUE. This conses up the name
2256 and value strings. If we have a temporary environment, we bind there
2257 first, then we bind into shell_variables. */
2258
2259 SHELL_VAR *
2260 bind_variable (name, value, flags)
2261 const char *name;
2262 char *value;
2263 int flags;
2264 {
2265 SHELL_VAR *v;
2266 VAR_CONTEXT *vc;
2267
2268 if (shell_variables == 0)
2269 create_variable_tables ();
2270
2271 /* If we have a temporary environment, look there first for the variable,
2272 and, if found, modify the value there before modifying it in the
2273 shell_variables table. This allows sourced scripts to modify values
2274 given to them in a temporary environment while modifying the variable
2275 value that the caller sees. */
2276 if (temporary_env)
2277 bind_tempenv_variable (name, value);
2278
2279 /* XXX -- handle local variables here. */
2280 for (vc = shell_variables; vc; vc = vc->down)
2281 {
2282 if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
2283 {
2284 v = hash_lookup (name, vc->table);
2285 if (v)
2286 return (bind_variable_internal (name, value, vc->table, 0, flags));
2287 }
2288 }
2289 return (bind_variable_internal (name, value, global_variables->table, 0, flags));
2290 }
2291
2292 /* Make VAR, a simple shell variable, have value VALUE. Once assigned a
2293 value, variables are no longer invisible. This is a duplicate of part
2294 of the internals of bind_variable. If the variable is exported, or
2295 all modified variables should be exported, mark the variable for export
2296 and note that the export environment needs to be recreated. */
2297 SHELL_VAR *
2298 bind_variable_value (var, value, aflags)
2299 SHELL_VAR *var;
2300 char *value;
2301 int aflags;
2302 {
2303 char *t;
2304
2305 VUNSETATTR (var, att_invisible);
2306
2307 if (var->assign_func)
2308 {
2309 /* If we're appending, we need the old value, so use
2310 make_variable_value */
2311 t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
2312 (*(var->assign_func)) (var, t, -1, 0);
2313 if (t != value && t)
2314 free (t);
2315 }
2316 else
2317 {
2318 t = make_variable_value (var, value, aflags);
2319 FREE (value_cell (var));
2320 var_setvalue (var, t);
2321 }
2322
2323 INVALIDATE_EXPORTSTR (var);
2324
2325 if (mark_modified_vars)
2326 VSETATTR (var, att_exported);
2327
2328 if (exported_p (var))
2329 array_needs_making = 1;
2330
2331 return (var);
2332 }
2333
2334 /* Bind/create a shell variable with the name LHS to the RHS.
2335 This creates or modifies a variable such that it is an integer.
2336
2337 This used to be in expr.c, but it is here so that all of the
2338 variable binding stuff is localized. Since we don't want any
2339 recursive evaluation from bind_variable() (possible without this code,
2340 since bind_variable() calls the evaluator for variables with the integer
2341 attribute set), we temporarily turn off the integer attribute for each
2342 variable we set here, then turn it back on after binding as necessary. */
2343
2344 SHELL_VAR *
2345 bind_int_variable (lhs, rhs)
2346 char *lhs, *rhs;
2347 {
2348 register SHELL_VAR *v;
2349 int isint, isarr;
2350
2351 isint = isarr = 0;
2352 #if defined (ARRAY_VARS)
2353 if (valid_array_reference (lhs))
2354 {
2355 isarr = 1;
2356 v = array_variable_part (lhs, (char **)0, (int *)0);
2357 }
2358 else
2359 #endif
2360 v = find_variable (lhs);
2361
2362 if (v)
2363 {
2364 isint = integer_p (v);
2365 VUNSETATTR (v, att_integer);
2366 }
2367
2368 #if defined (ARRAY_VARS)
2369 if (isarr)
2370 v = assign_array_element (lhs, rhs, 0);
2371 else
2372 #endif
2373 v = bind_variable (lhs, rhs, 0);
2374
2375 if (isint)
2376 VSETATTR (v, att_integer);
2377
2378 return (v);
2379 }
2380
2381 SHELL_VAR *
2382 bind_var_to_int (var, val)
2383 char *var;
2384 intmax_t val;
2385 {
2386 char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
2387
2388 p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
2389 return (bind_int_variable (var, p));
2390 }
2391
2392 /* Do a function binding to a variable. You pass the name and
2393 the command to bind to. This conses the name and command. */
2394 SHELL_VAR *
2395 bind_function (name, value)
2396 const char *name;
2397 COMMAND *value;
2398 {
2399 SHELL_VAR *entry;
2400
2401 entry = find_function (name);
2402 if (entry == 0)
2403 {
2404 BUCKET_CONTENTS *elt;
2405
2406 elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2407 entry = new_shell_variable (name);
2408 elt->data = (PTR_T)entry;
2409 }
2410 else
2411 INVALIDATE_EXPORTSTR (entry);
2412
2413 if (var_isset (entry))
2414 dispose_command (function_cell (entry));
2415
2416 if (value)
2417 var_setfunc (entry, copy_command (value));
2418 else
2419 var_setfunc (entry, 0);
2420
2421 VSETATTR (entry, att_function);
2422
2423 if (mark_modified_vars)
2424 VSETATTR (entry, att_exported);
2425
2426 VUNSETATTR (entry, att_invisible); /* Just to be sure */
2427
2428 if (exported_p (entry))
2429 array_needs_making = 1;
2430
2431 #if defined (PROGRAMMABLE_COMPLETION)
2432 set_itemlist_dirty (&it_functions);
2433 #endif
2434
2435 return (entry);
2436 }
2437
2438 #if defined (DEBUGGER)
2439 /* Bind a function definition, which includes source file and line number
2440 information in addition to the command, into the FUNCTION_DEF hash table.*/
2441 void
2442 bind_function_def (name, value)
2443 const char *name;
2444 FUNCTION_DEF *value;
2445 {
2446 FUNCTION_DEF *entry;
2447 BUCKET_CONTENTS *elt;
2448 COMMAND *cmd;
2449
2450 entry = find_function_def (name);
2451 if (entry)
2452 {
2453 dispose_function_def_contents (entry);
2454 entry = copy_function_def_contents (value, entry);
2455 }
2456 else
2457 {
2458 cmd = value->command;
2459 value->command = 0;
2460 entry = copy_function_def (value);
2461 value->command = cmd;
2462
2463 elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2464 elt->data = (PTR_T *)entry;
2465 }
2466 }
2467 #endif /* DEBUGGER */
2468
2469 /* Add STRING, which is of the form foo=bar, to the temporary environment
2470 HASH_TABLE (temporary_env). The functions in execute_cmd.c are
2471 responsible for moving the main temporary env to one of the other
2472 temporary environments. The expansion code in subst.c calls this. */
2473 int
2474 assign_in_env (word)
2475 WORD_DESC *word;
2476 {
2477 int offset;
2478 char *name, *temp, *value;
2479 SHELL_VAR *var;
2480 const char *string;
2481
2482 string = word->word;
2483
2484 offset = assignment (string, 0);
2485 name = savestring (string);
2486 value = (char *)NULL;
2487
2488 if (name[offset] == '=')
2489 {
2490 name[offset] = 0;
2491
2492 /* ignore the `+' when assigning temporary environment */
2493 if (name[offset - 1] == '+')
2494 name[offset - 1] = '\0';
2495
2496 var = find_variable (name);
2497 if (var && (readonly_p (var) || noassign_p (var)))
2498 {
2499 if (readonly_p (var))
2500 err_readonly (name);
2501 free (name);
2502 return (0);
2503 }
2504
2505 temp = name + offset + 1;
2506 value = expand_assignment_string_to_string (temp, 0);
2507 }
2508
2509 if (temporary_env == 0)
2510 temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2511
2512 var = hash_lookup (name, temporary_env);
2513 if (var == 0)
2514 var = make_new_variable (name, temporary_env);
2515 else
2516 FREE (value_cell (var));
2517
2518 if (value == 0)
2519 {
2520 value = (char *)xmalloc (1); /* like do_assignment_internal */
2521 value[0] = '\0';
2522 }
2523
2524 var_setvalue (var, value);
2525 var->attributes |= (att_exported|att_tempvar);
2526 var->context = variable_context; /* XXX */
2527
2528 INVALIDATE_EXPORTSTR (var);
2529 var->exportstr = mk_env_string (name, value);
2530
2531 array_needs_making = 1;
2532
2533 if (ifsname (name))
2534 setifs (var);
2535
2536 if (echo_command_at_execute)
2537 /* The Korn shell prints the `+ ' in front of assignment statements,
2538 so we do too. */
2539 xtrace_print_assignment (name, value, 0, 1);
2540
2541 free (name);
2542 return 1;
2543 }
2544
2545 /* **************************************************************** */
2546 /* */
2547 /* Copying variables */
2548 /* */
2549 /* **************************************************************** */
2550
2551 #ifdef INCLUDE_UNUSED
2552 /* Copy VAR to a new data structure and return that structure. */
2553 SHELL_VAR *
2554 copy_variable (var)
2555 SHELL_VAR *var;
2556 {
2557 SHELL_VAR *copy = (SHELL_VAR *)NULL;
2558
2559 if (var)
2560 {
2561 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2562
2563 copy->attributes = var->attributes;
2564 copy->name = savestring (var->name);
2565
2566 if (function_p (var))
2567 var_setfunc (copy, copy_command (function_cell (var)));
2568 #if defined (ARRAY_VARS)
2569 else if (array_p (var))
2570 var_setarray (copy, array_copy (array_cell (var)));
2571 else if (assoc_p (var))
2572 var_setassoc (copy, assoc_copy (assoc_cell (var)));
2573 #endif
2574 else if (value_cell (var))
2575 var_setvalue (copy, savestring (value_cell (var)));
2576 else
2577 var_setvalue (copy, (char *)NULL);
2578
2579 copy->dynamic_value = var->dynamic_value;
2580 copy->assign_func = var->assign_func;
2581
2582 copy->exportstr = COPY_EXPORTSTR (var);
2583
2584 copy->context = var->context;
2585 }
2586 return (copy);
2587 }
2588 #endif
2589
2590 /* **************************************************************** */
2591 /* */
2592 /* Deleting and unsetting variables */
2593 /* */
2594 /* **************************************************************** */
2595
2596 /* Dispose of the information attached to VAR. */
2597 static void
2598 dispose_variable_value (var)
2599 SHELL_VAR *var;
2600 {
2601 if (function_p (var))
2602 dispose_command (function_cell (var));
2603 #if defined (ARRAY_VARS)
2604 else if (array_p (var))
2605 array_dispose (array_cell (var));
2606 else if (assoc_p (var))
2607 assoc_dispose (assoc_cell (var));
2608 #endif
2609 else
2610 FREE (value_cell (var));
2611 }
2612
2613 void
2614 dispose_variable (var)
2615 SHELL_VAR *var;
2616 {
2617 if (var == 0)
2618 return;
2619
2620 if (nofree_p (var) == 0)
2621 dispose_variable_value (var);
2622
2623 FREE_EXPORTSTR (var);
2624
2625 free (var->name);
2626
2627 if (exported_p (var))
2628 array_needs_making = 1;
2629
2630 free (var);
2631 }
2632
2633 /* Unset the shell variable referenced by NAME. */
2634 int
2635 unbind_variable (name)
2636 const char *name;
2637 {
2638 return makunbound (name, shell_variables);
2639 }
2640
2641 /* Unset the shell function named NAME. */
2642 int
2643 unbind_func (name)
2644 const char *name;
2645 {
2646 BUCKET_CONTENTS *elt;
2647 SHELL_VAR *func;
2648
2649 elt = hash_remove (name, shell_functions, 0);
2650
2651 if (elt == 0)
2652 return -1;
2653
2654 #if defined (PROGRAMMABLE_COMPLETION)
2655 set_itemlist_dirty (&it_functions);
2656 #endif
2657
2658 func = (SHELL_VAR *)elt->data;
2659 if (func)
2660 {
2661 if (exported_p (func))
2662 array_needs_making++;
2663 dispose_variable (func);
2664 }
2665
2666 free (elt->key);
2667 free (elt);
2668
2669 return 0;
2670 }
2671
2672 #if defined (DEBUGGER)
2673 int
2674 unbind_function_def (name)
2675 const char *name;
2676 {
2677 BUCKET_CONTENTS *elt;
2678 FUNCTION_DEF *funcdef;
2679
2680 elt = hash_remove (name, shell_function_defs, 0);
2681
2682 if (elt == 0)
2683 return -1;
2684
2685 funcdef = (FUNCTION_DEF *)elt->data;
2686 if (funcdef)
2687 dispose_function_def (funcdef);
2688
2689 free (elt->key);
2690 free (elt);
2691
2692 return 0;
2693 }
2694 #endif /* DEBUGGER */
2695
2696 /* Make the variable associated with NAME go away. HASH_LIST is the
2697 hash table from which this variable should be deleted (either
2698 shell_variables or shell_functions).
2699 Returns non-zero if the variable couldn't be found. */
2700 int
2701 makunbound (name, vc)
2702 const char *name;
2703 VAR_CONTEXT *vc;
2704 {
2705 BUCKET_CONTENTS *elt, *new_elt;
2706 SHELL_VAR *old_var;
2707 VAR_CONTEXT *v;
2708 char *t;
2709
2710 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2711 if (elt = hash_remove (name, v->table, 0))
2712 break;
2713
2714 if (elt == 0)
2715 return (-1);
2716
2717 old_var = (SHELL_VAR *)elt->data;
2718
2719 if (old_var && exported_p (old_var))
2720 array_needs_making++;
2721
2722 /* If we're unsetting a local variable and we're still executing inside
2723 the function, just mark the variable as invisible. The function
2724 eventually called by pop_var_context() will clean it up later. This
2725 must be done so that if the variable is subsequently assigned a new
2726 value inside the function, the `local' attribute is still present.
2727 We also need to add it back into the correct hash table. */
2728 if (old_var && local_p (old_var) && variable_context == old_var->context)
2729 {
2730 if (nofree_p (old_var))
2731 var_setvalue (old_var, (char *)NULL);
2732 #if defined (ARRAY_VARS)
2733 else if (array_p (old_var))
2734 array_dispose (array_cell (old_var));
2735 else if (assoc_p (old_var))
2736 assoc_dispose (assoc_cell (old_var));
2737 #endif
2738 else
2739 FREE (value_cell (old_var));
2740 /* Reset the attributes. Preserve the export attribute if the variable
2741 came from a temporary environment. Make sure it stays local, and
2742 make it invisible. */
2743 old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
2744 VSETATTR (old_var, att_local);
2745 VSETATTR (old_var, att_invisible);
2746 var_setvalue (old_var, (char *)NULL);
2747 INVALIDATE_EXPORTSTR (old_var);
2748
2749 new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2750 new_elt->data = (PTR_T)old_var;
2751 stupidly_hack_special_variables (old_var->name);
2752
2753 free (elt->key);
2754 free (elt);
2755 return (0);
2756 }
2757
2758 /* Have to save a copy of name here, because it might refer to
2759 old_var->name. If so, stupidly_hack_special_variables will
2760 reference freed memory. */
2761 t = savestring (name);
2762
2763 free (elt->key);
2764 free (elt);
2765
2766 dispose_variable (old_var);
2767 stupidly_hack_special_variables (t);
2768 free (t);
2769
2770 return (0);
2771 }
2772
2773 /* Get rid of all of the variables in the current context. */
2774 void
2775 kill_all_local_variables ()
2776 {
2777 VAR_CONTEXT *vc;
2778
2779 for (vc = shell_variables; vc; vc = vc->down)
2780 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2781 break;
2782 if (vc == 0)
2783 return; /* XXX */
2784
2785 if (vc->table && vc_haslocals (vc))
2786 {
2787 delete_all_variables (vc->table);
2788 hash_dispose (vc->table);
2789 }
2790 vc->table = (HASH_TABLE *)NULL;
2791 }
2792
2793 static void
2794 free_variable_hash_data (data)
2795 PTR_T data;
2796 {
2797 SHELL_VAR *var;
2798
2799 var = (SHELL_VAR *)data;
2800 dispose_variable (var);
2801 }
2802
2803 /* Delete the entire contents of the hash table. */
2804 void
2805 delete_all_variables (hashed_vars)
2806 HASH_TABLE *hashed_vars;
2807 {
2808 hash_flush (hashed_vars, free_variable_hash_data);
2809 }
2810
2811 /* **************************************************************** */
2812 /* */
2813 /* Setting variable attributes */
2814 /* */
2815 /* **************************************************************** */
2816
2817 #define FIND_OR_MAKE_VARIABLE(name, entry) \
2818 do \
2819 { \
2820 entry = find_variable (name); \
2821 if (!entry) \
2822 { \
2823 entry = bind_variable (name, "", 0); \
2824 if (!no_invisible_vars) entry->attributes |= att_invisible; \
2825 } \
2826 } \
2827 while (0)
2828
2829 /* Make the variable associated with NAME be readonly.
2830 If NAME does not exist yet, create it. */
2831 void
2832 set_var_read_only (name)
2833 char *name;
2834 {
2835 SHELL_VAR *entry;
2836
2837 FIND_OR_MAKE_VARIABLE (name, entry);
2838 VSETATTR (entry, att_readonly);
2839 }
2840
2841 #ifdef INCLUDE_UNUSED
2842 /* Make the function associated with NAME be readonly.
2843 If NAME does not exist, we just punt, like auto_export code below. */
2844 void
2845 set_func_read_only (name)
2846 const char *name;
2847 {
2848 SHELL_VAR *entry;
2849
2850 entry = find_function (name);
2851 if (entry)
2852 VSETATTR (entry, att_readonly);
2853 }
2854
2855 /* Make the variable associated with NAME be auto-exported.
2856 If NAME does not exist yet, create it. */
2857 void
2858 set_var_auto_export (name)
2859 char *name;
2860 {
2861 SHELL_VAR *entry;
2862
2863 FIND_OR_MAKE_VARIABLE (name, entry);
2864 set_auto_export (entry);
2865 }
2866
2867 /* Make the function associated with NAME be auto-exported. */
2868 void
2869 set_func_auto_export (name)
2870 const char *name;
2871 {
2872 SHELL_VAR *entry;
2873
2874 entry = find_function (name);
2875 if (entry)
2876 set_auto_export (entry);
2877 }
2878 #endif
2879
2880 /* **************************************************************** */
2881 /* */
2882 /* Creating lists of variables */
2883 /* */
2884 /* **************************************************************** */
2885
2886 static VARLIST *
2887 vlist_alloc (nentries)
2888 int nentries;
2889 {
2890 VARLIST *vlist;
2891
2892 vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2893 vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2894 vlist->list_size = nentries;
2895 vlist->list_len = 0;
2896 vlist->list[0] = (SHELL_VAR *)NULL;
2897
2898 return vlist;
2899 }
2900
2901 static VARLIST *
2902 vlist_realloc (vlist, n)
2903 VARLIST *vlist;
2904 int n;
2905 {
2906 if (vlist == 0)
2907 return (vlist = vlist_alloc (n));
2908 if (n > vlist->list_size)
2909 {
2910 vlist->list_size = n;
2911 vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2912 }
2913 return vlist;
2914 }
2915
2916 static void
2917 vlist_add (vlist, var, flags)
2918 VARLIST *vlist;
2919 SHELL_VAR *var;
2920 int flags;
2921 {
2922 register int i;
2923
2924 for (i = 0; i < vlist->list_len; i++)
2925 if (STREQ (var->name, vlist->list[i]->name))
2926 break;
2927 if (i < vlist->list_len)
2928 return;
2929
2930 if (i >= vlist->list_size)
2931 vlist = vlist_realloc (vlist, vlist->list_size + 16);
2932
2933 vlist->list[vlist->list_len++] = var;
2934 vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2935 }
2936
2937 /* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
2938 variables for which FUNCTION returns a non-zero value. A NULL value
2939 for FUNCTION means to use all variables. */
2940 SHELL_VAR **
2941 map_over (function, vc)
2942 sh_var_map_func_t *function;
2943 VAR_CONTEXT *vc;
2944 {
2945 VAR_CONTEXT *v;
2946 VARLIST *vlist;
2947 SHELL_VAR **ret;
2948 int nentries;
2949
2950 for (nentries = 0, v = vc; v; v = v->down)
2951 nentries += HASH_ENTRIES (v->table);
2952
2953 if (nentries == 0)
2954 return (SHELL_VAR **)NULL;
2955
2956 vlist = vlist_alloc (nentries);
2957
2958 for (v = vc; v; v = v->down)
2959 flatten (v->table, function, vlist, 0);
2960
2961 ret = vlist->list;
2962 free (vlist);
2963 return ret;
2964 }
2965
2966 SHELL_VAR **
2967 map_over_funcs (function)
2968 sh_var_map_func_t *function;
2969 {
2970 VARLIST *vlist;
2971 SHELL_VAR **ret;
2972
2973 if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2974 return ((SHELL_VAR **)NULL);
2975
2976 vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2977
2978 flatten (shell_functions, function, vlist, 0);
2979
2980 ret = vlist->list;
2981 free (vlist);
2982 return ret;
2983 }
2984
2985 /* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2986 elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
2987 for future use. Only unique names are added to VLIST. If FUNC is
2988 NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
2989 NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
2990 and FUNC are both NULL, nothing happens. */
2991 static void
2992 flatten (var_hash_table, func, vlist, flags)
2993 HASH_TABLE *var_hash_table;
2994 sh_var_map_func_t *func;
2995 VARLIST *vlist;
2996 int flags;
2997 {
2998 register int i;
2999 register BUCKET_CONTENTS *tlist;
3000 int r;
3001 SHELL_VAR *var;
3002
3003 if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
3004 return;
3005
3006 for (i = 0; i < var_hash_table->nbuckets; i++)
3007 {
3008 for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
3009 {
3010 var = (SHELL_VAR *)tlist->data;
3011
3012 r = func ? (*func) (var) : 1;
3013 if (r && vlist)
3014 vlist_add (vlist, var, flags);
3015 }
3016 }
3017 }
3018
3019 void
3020 sort_variables (array)
3021 SHELL_VAR **array;
3022 {
3023 qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
3024 }
3025
3026 static int
3027 qsort_var_comp (var1, var2)
3028 SHELL_VAR **var1, **var2;
3029 {
3030 int result;
3031
3032 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
3033 result = strcmp ((*var1)->name, (*var2)->name);
3034
3035 return (result);
3036 }
3037
3038 /* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
3039 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
3040 static SHELL_VAR **
3041 vapply (func)
3042 sh_var_map_func_t *func;
3043 {
3044 SHELL_VAR **list;
3045
3046 list = map_over (func, shell_variables);
3047 if (list /* && posixly_correct */)
3048 sort_variables (list);
3049 return (list);
3050 }
3051
3052 /* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
3053 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
3054 static SHELL_VAR **
3055 fapply (func)
3056 sh_var_map_func_t *func;
3057 {
3058 SHELL_VAR **list;
3059
3060 list = map_over_funcs (func);
3061 if (list /* && posixly_correct */)
3062 sort_variables (list);
3063 return (list);
3064 }
3065
3066 /* Create a NULL terminated array of all the shell variables. */
3067 SHELL_VAR **
3068 all_shell_variables ()
3069 {
3070 return (vapply ((sh_var_map_func_t *)NULL));
3071 }
3072
3073 /* Create a NULL terminated array of all the shell functions. */
3074 SHELL_VAR **
3075 all_shell_functions ()
3076 {
3077 return (fapply ((sh_var_map_func_t *)NULL));
3078 }
3079
3080 static int
3081 visible_var (var)
3082 SHELL_VAR *var;
3083 {
3084 return (invisible_p (var) == 0);
3085 }
3086
3087 SHELL_VAR **
3088 all_visible_functions ()
3089 {
3090 return (fapply (visible_var));
3091 }
3092
3093 SHELL_VAR **
3094 all_visible_variables ()
3095 {
3096 return (vapply (visible_var));
3097 }
3098
3099 /* Return non-zero if the variable VAR is visible and exported. Array
3100 variables cannot be exported. */
3101 static int
3102 visible_and_exported (var)
3103 SHELL_VAR *var;
3104 {
3105 return (invisible_p (var) == 0 && exported_p (var));
3106 }
3107
3108 /* Candidate variables for the export environment are either valid variables
3109 with the export attribute or invalid variables inherited from the initial
3110 environment and simply passed through. */
3111 static int
3112 export_environment_candidate (var)
3113 SHELL_VAR *var;
3114 {
3115 return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
3116 }
3117
3118 /* Return non-zero if VAR is a local variable in the current context and
3119 is exported. */
3120 static int
3121 local_and_exported (var)
3122 SHELL_VAR *var;
3123 {
3124 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
3125 }
3126
3127 SHELL_VAR **
3128 all_exported_variables ()
3129 {
3130 return (vapply (visible_and_exported));
3131 }
3132
3133 SHELL_VAR **
3134 local_exported_variables ()
3135 {
3136 return (vapply (local_and_exported));
3137 }
3138
3139 static int
3140 variable_in_context (var)
3141 SHELL_VAR *var;
3142 {
3143 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
3144 }
3145
3146 SHELL_VAR **
3147 all_local_variables ()
3148 {
3149 VARLIST *vlist;
3150 SHELL_VAR **ret;
3151 VAR_CONTEXT *vc;
3152
3153 vc = shell_variables;
3154 for (vc = shell_variables; vc; vc = vc->down)
3155 if (vc_isfuncenv (vc) && vc->scope == variable_context)
3156 break;
3157
3158 if (vc == 0)
3159 {
3160 internal_error (_("all_local_variables: no function context at current scope"));
3161 return (SHELL_VAR **)NULL;
3162 }
3163 if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
3164 return (SHELL_VAR **)NULL;
3165
3166 vlist = vlist_alloc (HASH_ENTRIES (vc->table));
3167
3168 flatten (vc->table, variable_in_context, vlist, 0);
3169
3170 ret = vlist->list;
3171 free (vlist);
3172 if (ret)
3173 sort_variables (ret);
3174 return ret;
3175 }
3176
3177 #if defined (ARRAY_VARS)
3178 /* Return non-zero if the variable VAR is visible and an array. */
3179 static int
3180 visible_array_vars (var)
3181 SHELL_VAR *var;
3182 {
3183 return (invisible_p (var) == 0 && array_p (var));
3184 }
3185
3186 SHELL_VAR **
3187 all_array_variables ()
3188 {
3189 return (vapply (visible_array_vars));
3190 }
3191 #endif /* ARRAY_VARS */
3192
3193 char **
3194 all_variables_matching_prefix (prefix)
3195 const char *prefix;
3196 {
3197 SHELL_VAR **varlist;
3198 char **rlist;
3199 int vind, rind, plen;
3200
3201 plen = STRLEN (prefix);
3202 varlist = all_visible_variables ();
3203 for (vind = 0; varlist && varlist[vind]; vind++)
3204 ;
3205 if (varlist == 0 || vind == 0)
3206 return ((char **)NULL);
3207 rlist = strvec_create (vind + 1);
3208 for (vind = rind = 0; varlist[vind]; vind++)
3209 {
3210 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
3211 rlist[rind++] = savestring (varlist[vind]->name);
3212 }
3213 rlist[rind] = (char *)0;
3214 free (varlist);
3215
3216 return rlist;
3217 }
3218
3219 /* **************************************************************** */
3220 /* */
3221 /* Managing temporary variable scopes */
3222 /* */
3223 /* **************************************************************** */
3224
3225 /* Make variable NAME have VALUE in the temporary environment. */
3226 static SHELL_VAR *
3227 bind_tempenv_variable (name, value)
3228 const char *name;
3229 char *value;
3230 {
3231 SHELL_VAR *var;
3232
3233 var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
3234
3235 if (var)
3236 {
3237 FREE (value_cell (var));
3238 var_setvalue (var, savestring (value));
3239 INVALIDATE_EXPORTSTR (var);
3240 }
3241
3242 return (var);
3243 }
3244
3245 /* Find a variable in the temporary environment that is named NAME.
3246 Return the SHELL_VAR *, or NULL if not found. */
3247 SHELL_VAR *
3248 find_tempenv_variable (name)
3249 const char *name;
3250 {
3251 return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
3252 }
3253
3254 /* Push the variable described by (SHELL_VAR *)DATA down to the next
3255 variable context from the temporary environment. */
3256 static void
3257 push_temp_var (data)
3258 PTR_T data;
3259 {
3260 SHELL_VAR *var, *v;
3261 HASH_TABLE *binding_table;
3262
3263 var = (SHELL_VAR *)data;
3264
3265 binding_table = shell_variables->table;
3266 if (binding_table == 0)
3267 {
3268 if (shell_variables == global_variables)
3269 /* shouldn't happen */
3270 binding_table = shell_variables->table = global_variables->table = hash_create (0);
3271 else
3272 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
3273 }
3274
3275 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
3276
3277 /* XXX - should we set the context here? It shouldn't matter because of how
3278 assign_in_env works, but might want to check. */
3279 if (binding_table == global_variables->table) /* XXX */
3280 var->attributes &= ~(att_tempvar|att_propagate);
3281 else
3282 {
3283 var->attributes |= att_propagate;
3284 if (binding_table == shell_variables->table)
3285 shell_variables->flags |= VC_HASTMPVAR;
3286 }
3287 v->attributes |= var->attributes;
3288
3289 dispose_variable (var);
3290 }
3291
3292 static void
3293 propagate_temp_var (data)
3294 PTR_T data;
3295 {
3296 SHELL_VAR *var;
3297
3298 var = (SHELL_VAR *)data;
3299 if (tempvar_p (var) && (var->attributes & att_propagate))
3300 push_temp_var (data);
3301 else
3302 dispose_variable (var);
3303 }
3304
3305 /* Free the storage used in the hash table for temporary
3306 environment variables. PUSHF is a function to be called
3307 to free each hash table entry. It takes care of pushing variables
3308 to previous scopes if appropriate. */
3309 static void
3310 dispose_temporary_env (pushf)
3311 sh_free_func_t *pushf;
3312 {
3313 hash_flush (temporary_env, pushf);
3314 hash_dispose (temporary_env);
3315 temporary_env = (HASH_TABLE *)NULL;
3316
3317 array_needs_making = 1;
3318
3319 sv_ifs ("IFS"); /* XXX here for now */
3320 }
3321
3322 void
3323 dispose_used_env_vars ()
3324 {
3325 if (temporary_env)
3326 {
3327 dispose_temporary_env (propagate_temp_var);
3328 maybe_make_export_env ();
3329 }
3330 }
3331
3332 /* Take all of the shell variables in the temporary environment HASH_TABLE
3333 and make shell variables from them at the current variable context. */
3334 void
3335 merge_temporary_env ()
3336 {
3337 if (temporary_env)
3338 dispose_temporary_env (push_temp_var);
3339 }
3340
3341 /* **************************************************************** */
3342 /* */
3343 /* Creating and manipulating the environment */
3344 /* */
3345 /* **************************************************************** */
3346
3347 static inline char *
3348 mk_env_string (name, value)
3349 const char *name, *value;
3350 {
3351 int name_len, value_len;
3352 char *p;
3353
3354 name_len = strlen (name);
3355 value_len = STRLEN (value);
3356 p = (char *)xmalloc (2 + name_len + value_len);
3357 strcpy (p, name);
3358 p[name_len] = '=';
3359 if (value && *value)
3360 strcpy (p + name_len + 1, value);
3361 else
3362 p[name_len + 1] = '\0';
3363 return (p);
3364 }
3365
3366 #ifdef DEBUG
3367 /* Debugging */
3368 static int
3369 valid_exportstr (v)
3370 SHELL_VAR *v;
3371 {
3372 char *s;
3373
3374 s = v->exportstr;
3375 if (s == 0)
3376 {
3377 internal_error (_("%s has null exportstr"), v->name);
3378 return (0);
3379 }
3380 if (legal_variable_starter ((unsigned char)*s) == 0)
3381 {
3382 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3383 return (0);
3384 }
3385 for (s = v->exportstr + 1; s && *s; s++)
3386 {
3387 if (*s == '=')
3388 break;
3389 if (legal_variable_char ((unsigned char)*s) == 0)
3390 {
3391 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3392 return (0);
3393 }
3394 }
3395 if (*s != '=')
3396 {
3397 internal_error (_("no `=' in exportstr for %s"), v->name);
3398 return (0);
3399 }
3400 return (1);
3401 }
3402 #endif
3403
3404 static char **
3405 make_env_array_from_var_list (vars)
3406 SHELL_VAR **vars;
3407 {
3408 register int i, list_index;
3409 register SHELL_VAR *var;
3410 char **list, *value;
3411
3412 list = strvec_create ((1 + strvec_len ((char **)vars)));
3413
3414 #define USE_EXPORTSTR (value == var->exportstr)
3415
3416 for (i = 0, list_index = 0; var = vars[i]; i++)
3417 {
3418 #if defined (__CYGWIN__)
3419 /* We don't use the exportstr stuff on Cygwin at all. */
3420 INVALIDATE_EXPORTSTR (var);
3421 #endif
3422 if (var->exportstr)
3423 value = var->exportstr;
3424 else if (function_p (var))
3425 value = named_function_string ((char *)NULL, function_cell (var), 0);
3426 #if defined (ARRAY_VARS)
3427 else if (array_p (var))
3428 # if 0
3429 value = array_to_assignment_string (array_cell (var));
3430 # else
3431 continue; /* XXX array vars cannot yet be exported */
3432 # endif
3433 else if (assoc_p (var))
3434 # if 0
3435 value = assoc_to_assignment_string (assoc_cell (var));
3436 # else
3437 continue; /* XXX associative array vars cannot yet be exported */
3438 # endif
3439 #endif
3440 else
3441 value = value_cell (var);
3442
3443 if (value)
3444 {
3445 /* Gee, I'd like to get away with not using savestring() if we're
3446 using the cached exportstr... */
3447 list[list_index] = USE_EXPORTSTR ? savestring (value)
3448 : mk_env_string (var->name, value);
3449
3450 if (USE_EXPORTSTR == 0)
3451 SAVE_EXPORTSTR (var, list[list_index]);
3452
3453 list_index++;
3454 #undef USE_EXPORTSTR
3455
3456 #if 0 /* not yet */
3457 #if defined (ARRAY_VARS)
3458 if (array_p (var) || assoc_p (var))
3459 free (value);
3460 #endif
3461 #endif
3462 }
3463 }
3464
3465 list[list_index] = (char *)NULL;
3466 return (list);
3467 }
3468
3469 /* Make an array of assignment statements from the hash table
3470 HASHED_VARS which contains SHELL_VARs. Only visible, exported
3471 variables are eligible. */
3472 static char **
3473 make_var_export_array (vcxt)
3474 VAR_CONTEXT *vcxt;
3475 {
3476 char **list;
3477 SHELL_VAR **vars;
3478
3479 #if 0
3480 vars = map_over (visible_and_exported, vcxt);
3481 #else
3482 vars = map_over (export_environment_candidate, vcxt);
3483 #endif
3484
3485 if (vars == 0)
3486 return (char **)NULL;
3487
3488 list = make_env_array_from_var_list (vars);
3489
3490 free (vars);
3491 return (list);
3492 }
3493
3494 static char **
3495 make_func_export_array ()
3496 {
3497 char **list;
3498 SHELL_VAR **vars;
3499
3500 vars = map_over_funcs (visible_and_exported);
3501 if (vars == 0)
3502 return (char **)NULL;
3503
3504 list = make_env_array_from_var_list (vars);
3505
3506 free (vars);
3507 return (list);
3508 }
3509
3510 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3511 #define add_to_export_env(envstr,do_alloc) \
3512 do \
3513 { \
3514 if (export_env_index >= (export_env_size - 1)) \
3515 { \
3516 export_env_size += 16; \
3517 export_env = strvec_resize (export_env, export_env_size); \
3518 environ = export_env; \
3519 } \
3520 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3521 export_env[export_env_index] = (char *)NULL; \
3522 } while (0)
3523
3524 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3525 array with the same left-hand side. Return the new EXPORT_ENV. */
3526 char **
3527 add_or_supercede_exported_var (assign, do_alloc)
3528 char *assign;
3529 int do_alloc;
3530 {
3531 register int i;
3532 int equal_offset;
3533
3534 equal_offset = assignment (assign, 0);
3535 if (equal_offset == 0)
3536 return (export_env);
3537
3538 /* If this is a function, then only supersede the function definition.
3539 We do this by including the `=() {' in the comparison, like
3540 initialize_shell_variables does. */
3541 if (assign[equal_offset + 1] == '(' &&
3542 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
3543 equal_offset += 4;
3544
3545 for (i = 0; i < export_env_index; i++)
3546 {
3547 if (STREQN (assign, export_env[i], equal_offset + 1))
3548 {
3549 free (export_env[i]);
3550 export_env[i] = do_alloc ? savestring (assign) : assign;
3551 return (export_env);
3552 }
3553 }
3554 add_to_export_env (assign, do_alloc);
3555 return (export_env);
3556 }
3557
3558 static void
3559 add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3560 char **temp_array;
3561 int do_alloc, do_supercede;
3562 {
3563 register int i;
3564
3565 if (temp_array == 0)
3566 return;
3567
3568 for (i = 0; temp_array[i]; i++)
3569 {
3570 if (do_supercede)
3571 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3572 else
3573 add_to_export_env (temp_array[i], do_alloc);
3574 }
3575
3576 free (temp_array);
3577 }
3578
3579 /* Make the environment array for the command about to be executed, if the
3580 array needs making. Otherwise, do nothing. If a shell action could
3581 change the array that commands receive for their environment, then the
3582 code should `array_needs_making++'.
3583
3584 The order to add to the array is:
3585 temporary_env
3586 list of var contexts whose head is shell_variables
3587 shell_functions
3588
3589 This is the shell variable lookup order. We add only new variable
3590 names at each step, which allows local variables and variables in
3591 the temporary environments to shadow variables in the global (or
3592 any previous) scope.
3593 */
3594
3595 static int
3596 n_shell_variables ()
3597 {
3598 VAR_CONTEXT *vc;
3599 int n;
3600
3601 for (n = 0, vc = shell_variables; vc; vc = vc->down)
3602 n += HASH_ENTRIES (vc->table);
3603 return n;
3604 }
3605
3606 void
3607 maybe_make_export_env ()
3608 {
3609 register char **temp_array;
3610 int new_size;
3611 VAR_CONTEXT *tcxt;
3612
3613 if (array_needs_making)
3614 {
3615 if (export_env)
3616 strvec_flush (export_env);
3617
3618 /* Make a guess based on how many shell variables and functions we
3619 have. Since there will always be array variables, and array
3620 variables are not (yet) exported, this will always be big enough
3621 for the exported variables and functions. */
3622 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3623 HASH_ENTRIES (temporary_env);
3624 if (new_size > export_env_size)
3625 {
3626 export_env_size = new_size;
3627 export_env = strvec_resize (export_env, export_env_size);
3628 environ = export_env;
3629 }
3630 export_env[export_env_index = 0] = (char *)NULL;
3631
3632 /* Make a dummy variable context from the temporary_env, stick it on
3633 the front of shell_variables, call make_var_export_array on the
3634 whole thing to flatten it, and convert the list of SHELL_VAR *s
3635 to the form needed by the environment. */
3636 if (temporary_env)
3637 {
3638 tcxt = new_var_context ((char *)NULL, 0);
3639 tcxt->table = temporary_env;
3640 tcxt->down = shell_variables;
3641 }
3642 else
3643 tcxt = shell_variables;
3644
3645 temp_array = make_var_export_array (tcxt);
3646 if (temp_array)
3647 add_temp_array_to_env (temp_array, 0, 0);
3648
3649 if (tcxt != shell_variables)
3650 free (tcxt);
3651
3652 #if defined (RESTRICTED_SHELL)
3653 /* Restricted shells may not export shell functions. */
3654 temp_array = restricted ? (char **)0 : make_func_export_array ();
3655 #else
3656 temp_array = make_func_export_array ();
3657 #endif
3658 if (temp_array)
3659 add_temp_array_to_env (temp_array, 0, 0);
3660
3661 array_needs_making = 0;
3662 }
3663 }
3664
3665 /* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
3666 we will need to remake the exported environment every time we
3667 change directories. `_' is always put into the environment for
3668 every external command, so without special treatment it will always
3669 cause the environment to be remade.
3670
3671 If there is no other reason to make the exported environment, we can
3672 just update the variables in place and mark the exported environment
3673 as no longer needing a remake. */
3674 void
3675 update_export_env_inplace (env_prefix, preflen, value)
3676 char *env_prefix;
3677 int preflen;
3678 char *value;
3679 {
3680 char *evar;
3681
3682 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
3683 strcpy (evar, env_prefix);
3684 if (value)
3685 strcpy (evar + preflen, value);
3686 export_env = add_or_supercede_exported_var (evar, 0);
3687 }
3688
3689 /* We always put _ in the environment as the name of this command. */
3690 void
3691 put_command_name_into_env (command_name)
3692 char *command_name;
3693 {
3694 update_export_env_inplace ("_=", 2, command_name);
3695 }
3696
3697 #if 0 /* UNUSED -- it caused too many problems */
3698 void
3699 put_gnu_argv_flags_into_env (pid, flags_string)
3700 intmax_t pid;
3701 char *flags_string;
3702 {
3703 char *dummy, *pbuf;
3704 int l, fl;
3705
3706 pbuf = itos (pid);
3707 l = strlen (pbuf);
3708
3709 fl = strlen (flags_string);
3710
3711 dummy = (char *)xmalloc (l + fl + 30);
3712 dummy[0] = '_';
3713 strcpy (dummy + 1, pbuf);
3714 strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3715 dummy[l + 27] = '=';
3716 strcpy (dummy + l + 28, flags_string);
3717
3718 free (pbuf);
3719
3720 export_env = add_or_supercede_exported_var (dummy, 0);
3721 }
3722 #endif
3723
3724 /* **************************************************************** */
3725 /* */
3726 /* Managing variable contexts */
3727 /* */
3728 /* **************************************************************** */
3729
3730 /* Allocate and return a new variable context with NAME and FLAGS.
3731 NAME can be NULL. */
3732
3733 VAR_CONTEXT *
3734 new_var_context (name, flags)
3735 char *name;
3736 int flags;
3737 {
3738 VAR_CONTEXT *vc;
3739
3740 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3741 vc->name = name ? savestring (name) : (char *)NULL;
3742 vc->scope = variable_context;
3743 vc->flags = flags;
3744
3745 vc->up = vc->down = (VAR_CONTEXT *)NULL;
3746 vc->table = (HASH_TABLE *)NULL;
3747
3748 return vc;
3749 }
3750
3751 /* Free a variable context and its data, including the hash table. Dispose
3752 all of the variables. */
3753 void
3754 dispose_var_context (vc)
3755 VAR_CONTEXT *vc;
3756 {
3757 FREE (vc->name);
3758
3759 if (vc->table)
3760 {
3761 delete_all_variables (vc->table);
3762 hash_dispose (vc->table);
3763 }
3764
3765 free (vc);
3766 }
3767
3768 /* Set VAR's scope level to the current variable context. */
3769 static int
3770 set_context (var)
3771 SHELL_VAR *var;
3772 {
3773 return (var->context = variable_context);
3774 }
3775
3776 /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3777 temporary variables, and push it onto shell_variables. This is
3778 for shell functions. */
3779 VAR_CONTEXT *
3780 push_var_context (name, flags, tempvars)
3781 char *name;
3782 int flags;
3783 HASH_TABLE *tempvars;
3784 {
3785 VAR_CONTEXT *vc;
3786
3787 vc = new_var_context (name, flags);
3788 vc->table = tempvars;
3789 if (tempvars)
3790 {
3791 /* Have to do this because the temp environment was created before
3792 variable_context was incremented. */
3793 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3794 vc->flags |= VC_HASTMPVAR;
3795 }
3796 vc->down = shell_variables;
3797 shell_variables->up = vc;
3798
3799 return (shell_variables = vc);
3800 }
3801
3802 static void
3803 push_func_var (data)
3804 PTR_T data;
3805 {
3806 SHELL_VAR *var, *v;
3807
3808 var = (SHELL_VAR *)data;
3809
3810 if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3811 {
3812 /* XXX - should we set v->context here? */
3813 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3814 if (shell_variables == global_variables)
3815 var->attributes &= ~(att_tempvar|att_propagate);
3816 else
3817 shell_variables->flags |= VC_HASTMPVAR;
3818 v->attributes |= var->attributes;
3819 }
3820 else
3821 stupidly_hack_special_variables (var->name); /* XXX */
3822
3823 dispose_variable (var);
3824 }
3825
3826 /* Pop the top context off of VCXT and dispose of it, returning the rest of
3827 the stack. */
3828 void
3829 pop_var_context ()
3830 {
3831 VAR_CONTEXT *ret, *vcxt;
3832
3833 vcxt = shell_variables;
3834 if (vc_isfuncenv (vcxt) == 0)
3835 {
3836 internal_error (_("pop_var_context: head of shell_variables not a function context"));
3837 return;
3838 }
3839
3840 if (ret = vcxt->down)
3841 {
3842 ret->up = (VAR_CONTEXT *)NULL;
3843 shell_variables = ret;
3844 if (vcxt->table)
3845 hash_flush (vcxt->table, push_func_var);
3846 dispose_var_context (vcxt);
3847 }
3848 else
3849 internal_error (_("pop_var_context: no global_variables context"));
3850 }
3851
3852 /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3853 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3854 void
3855 delete_all_contexts (vcxt)
3856 VAR_CONTEXT *vcxt;
3857 {
3858 VAR_CONTEXT *v, *t;
3859
3860 for (v = vcxt; v != global_variables; v = t)
3861 {
3862 t = v->down;
3863 dispose_var_context (v);
3864 }
3865
3866 delete_all_variables (global_variables->table);
3867 shell_variables = global_variables;
3868 }
3869
3870 /* **************************************************************** */
3871 /* */
3872 /* Pushing and Popping temporary variable scopes */
3873 /* */
3874 /* **************************************************************** */
3875
3876 VAR_CONTEXT *
3877 push_scope (flags, tmpvars)
3878 int flags;
3879 HASH_TABLE *tmpvars;
3880 {
3881 return (push_var_context ((char *)NULL, flags, tmpvars));
3882 }
3883
3884 static void
3885 push_exported_var (data)
3886 PTR_T data;
3887 {
3888 SHELL_VAR *var, *v;
3889
3890 var = (SHELL_VAR *)data;
3891
3892 /* If a temp var had its export attribute set, or it's marked to be
3893 propagated, bind it in the previous scope before disposing it. */
3894 /* XXX - This isn't exactly right, because all tempenv variables have the
3895 export attribute set. */
3896 #if 0
3897 if (exported_p (var) || (var->attributes & att_propagate))
3898 #else
3899 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
3900 #endif
3901 {
3902 var->attributes &= ~att_tempvar; /* XXX */
3903 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3904 if (shell_variables == global_variables)
3905 var->attributes &= ~att_propagate;
3906 v->attributes |= var->attributes;
3907 }
3908 else
3909 stupidly_hack_special_variables (var->name); /* XXX */
3910
3911 dispose_variable (var);
3912 }
3913
3914 void
3915 pop_scope (is_special)
3916 int is_special;
3917 {
3918 VAR_CONTEXT *vcxt, *ret;
3919
3920 vcxt = shell_variables;
3921 if (vc_istempscope (vcxt) == 0)
3922 {
3923 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
3924 return;
3925 }
3926
3927 ret = vcxt->down;
3928 if (ret)
3929 ret->up = (VAR_CONTEXT *)NULL;
3930
3931 shell_variables = ret;
3932
3933 /* Now we can take care of merging variables in VCXT into set of scopes
3934 whose head is RET (shell_variables). */
3935 FREE (vcxt->name);
3936 if (vcxt->table)
3937 {
3938 if (is_special)
3939 hash_flush (vcxt->table, push_func_var);
3940 else
3941 hash_flush (vcxt->table, push_exported_var);
3942 hash_dispose (vcxt->table);
3943 }
3944 free (vcxt);
3945
3946 sv_ifs ("IFS"); /* XXX here for now */
3947 }
3948
3949 /* **************************************************************** */
3950 /* */
3951 /* Pushing and Popping function contexts */
3952 /* */
3953 /* **************************************************************** */
3954
3955 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3956 static int dollar_arg_stack_slots;
3957 static int dollar_arg_stack_index;
3958
3959 /* XXX - we might want to consider pushing and popping the `getopts' state
3960 when we modify the positional parameters. */
3961 void
3962 push_context (name, is_subshell, tempvars)
3963 char *name; /* function name */
3964 int is_subshell;
3965 HASH_TABLE *tempvars;
3966 {
3967 if (is_subshell == 0)
3968 push_dollar_vars ();
3969 variable_context++;
3970 push_var_context (name, VC_FUNCENV, tempvars);
3971 }
3972
3973 /* Only called when subshell == 0, so we don't need to check, and can
3974 unconditionally pop the dollar vars off the stack. */
3975 void
3976 pop_context ()
3977 {
3978 pop_dollar_vars ();
3979 variable_context--;
3980 pop_var_context ();
3981
3982 sv_ifs ("IFS"); /* XXX here for now */
3983 }
3984
3985 /* Save the existing positional parameters on a stack. */
3986 void
3987 push_dollar_vars ()
3988 {
3989 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3990 {
3991 dollar_arg_stack = (WORD_LIST **)
3992 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3993 * sizeof (WORD_LIST **));
3994 }
3995 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3996 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3997 }
3998
3999 /* Restore the positional parameters from our stack. */
4000 void
4001 pop_dollar_vars ()
4002 {
4003 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
4004 return;
4005
4006 remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
4007 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
4008 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
4009 set_dollar_vars_unchanged ();
4010 }
4011
4012 void
4013 dispose_saved_dollar_vars ()
4014 {
4015 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
4016 return;
4017
4018 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
4019 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
4020 }
4021
4022 /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
4023
4024 void
4025 push_args (list)
4026 WORD_LIST *list;
4027 {
4028 #if defined (ARRAY_VARS) && defined (DEBUGGER)
4029 SHELL_VAR *bash_argv_v, *bash_argc_v;
4030 ARRAY *bash_argv_a, *bash_argc_a;
4031 WORD_LIST *l;
4032 arrayind_t i;
4033 char *t;
4034
4035 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
4036 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
4037
4038 for (l = list, i = 0; l; l = l->next, i++)
4039 array_push (bash_argv_a, l->word->word);
4040
4041 t = itos (i);
4042 array_push (bash_argc_a, t);
4043 free (t);
4044 #endif /* ARRAY_VARS && DEBUGGER */
4045 }
4046
4047 /* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
4048 array and use that value as the count of elements to remove from
4049 BASH_ARGV. */
4050 void
4051 pop_args ()
4052 {
4053 #if defined (ARRAY_VARS) && defined (DEBUGGER)
4054 SHELL_VAR *bash_argv_v, *bash_argc_v;
4055 ARRAY *bash_argv_a, *bash_argc_a;
4056 ARRAY_ELEMENT *ce;
4057 intmax_t i;
4058
4059 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
4060 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
4061
4062 ce = array_shift (bash_argc_a, 1, 0);
4063 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
4064 i = 0;
4065
4066 for ( ; i > 0; i--)
4067 array_pop (bash_argv_a);
4068 array_dispose_element (ce);
4069 #endif /* ARRAY_VARS && DEBUGGER */
4070 }
4071
4072 /*************************************************
4073 * *
4074 * Functions to manage special variables *
4075 * *
4076 *************************************************/
4077
4078 /* Extern declarations for variables this code has to manage. */
4079 extern int eof_encountered, eof_encountered_limit, ignoreeof;
4080
4081 #if defined (READLINE)
4082 extern int hostname_list_initialized;
4083 #endif
4084
4085 /* An alist of name.function for each special variable. Most of the
4086 functions don't do much, and in fact, this would be faster with a
4087 switch statement, but by the end of this file, I am sick of switch
4088 statements. */
4089
4090 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
4091
4092 /* This table will be sorted with qsort() the first time it's accessed. */
4093 struct name_and_function {
4094 char *name;
4095 sh_sv_func_t *function;
4096 };
4097
4098 static struct name_and_function special_vars[] = {
4099 { "BASH_XTRACEFD", sv_xtracefd },
4100
4101 #if defined (READLINE)
4102 # if defined (STRICT_POSIX)
4103 { "COLUMNS", sv_winsize },
4104 # endif
4105 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
4106 #endif
4107
4108 { "GLOBIGNORE", sv_globignore },
4109
4110 #if defined (HISTORY)
4111 { "HISTCONTROL", sv_history_control },
4112 { "HISTFILESIZE", sv_histsize },
4113 { "HISTIGNORE", sv_histignore },
4114 { "HISTSIZE", sv_histsize },
4115 { "HISTTIMEFORMAT", sv_histtimefmt },
4116 #endif
4117
4118 #if defined (__CYGWIN__)
4119 { "HOME", sv_home },
4120 #endif
4121
4122 #if defined (READLINE)
4123 { "HOSTFILE", sv_hostfile },
4124 #endif
4125
4126 { "IFS", sv_ifs },
4127 { "IGNOREEOF", sv_ignoreeof },
4128
4129 { "LANG", sv_locale },
4130 { "LC_ALL", sv_locale },
4131 { "LC_COLLATE", sv_locale },
4132 { "LC_CTYPE", sv_locale },
4133 { "LC_MESSAGES", sv_locale },
4134 { "LC_NUMERIC", sv_locale },
4135 { "LC_TIME", sv_locale },
4136
4137 #if defined (READLINE) && defined (STRICT_POSIX)
4138 { "LINES", sv_winsize },
4139 #endif
4140
4141 { "MAIL", sv_mail },
4142 { "MAILCHECK", sv_mail },
4143 { "MAILPATH", sv_mail },
4144
4145 { "OPTERR", sv_opterr },
4146 { "OPTIND", sv_optind },
4147
4148 { "PATH", sv_path },
4149 { "POSIXLY_CORRECT", sv_strict_posix },
4150
4151 #if defined (READLINE)
4152 { "TERM", sv_terminal },
4153 { "TERMCAP", sv_terminal },
4154 { "TERMINFO", sv_terminal },
4155 #endif /* READLINE */
4156
4157 { "TEXTDOMAIN", sv_locale },
4158 { "TEXTDOMAINDIR", sv_locale },
4159
4160 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
4161 { "TZ", sv_tz },
4162 #endif
4163
4164 #if defined (HISTORY) && defined (BANG_HISTORY)
4165 { "histchars", sv_histchars },
4166 #endif /* HISTORY && BANG_HISTORY */
4167
4168 { "ignoreeof", sv_ignoreeof },
4169
4170 { (char *)0, (sh_sv_func_t *)0 }
4171 };
4172
4173 #define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
4174
4175 static int
4176 sv_compare (sv1, sv2)
4177 struct name_and_function *sv1, *sv2;
4178 {
4179 int r;
4180
4181 if ((r = sv1->name[0] - sv2->name[0]) == 0)
4182 r = strcmp (sv1->name, sv2->name);
4183 return r;
4184 }
4185
4186 static inline int
4187 find_special_var (name)
4188 const char *name;
4189 {
4190 register int i, r;
4191
4192 for (i = 0; special_vars[i].name; i++)
4193 {
4194 r = special_vars[i].name[0] - name[0];
4195 if (r == 0)
4196 r = strcmp (special_vars[i].name, name);
4197 if (r == 0)
4198 return i;
4199 else if (r > 0)
4200 /* Can't match any of rest of elements in sorted list. Take this out
4201 if it causes problems in certain environments. */
4202 break;
4203 }
4204 return -1;
4205 }
4206
4207 /* The variable in NAME has just had its state changed. Check to see if it
4208 is one of the special ones where something special happens. */
4209 void
4210 stupidly_hack_special_variables (name)
4211 char *name;
4212 {
4213 static int sv_sorted = 0;
4214 int i;
4215
4216 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
4217 {
4218 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
4219 (QSFUNC *)sv_compare);
4220 sv_sorted = 1;
4221 }
4222
4223 i = find_special_var (name);
4224 if (i != -1)
4225 (*(special_vars[i].function)) (name);
4226 }
4227
4228 /* Special variables that need hooks to be run when they are unset as part
4229 of shell reinitialization should have their sv_ functions run here. */
4230 void
4231 reinit_special_variables ()
4232 {
4233 #if defined (READLINE)
4234 sv_comp_wordbreaks ("COMP_WORDBREAKS");
4235 #endif
4236 sv_globignore ("GLOBIGNORE");
4237 sv_opterr ("OPTERR");
4238 }
4239
4240 void
4241 sv_ifs (name)
4242 char *name;
4243 {
4244 SHELL_VAR *v;
4245
4246 v = find_variable ("IFS");
4247 setifs (v);
4248 }
4249
4250 /* What to do just after the PATH variable has changed. */
4251 void
4252 sv_path (name)
4253 char *name;
4254 {
4255 /* hash -r */
4256 phash_flush ();
4257 }
4258
4259 /* What to do just after one of the MAILxxxx variables has changed. NAME
4260 is the name of the variable. This is called with NAME set to one of
4261 MAIL, MAILCHECK, or MAILPATH. */
4262 void
4263 sv_mail (name)
4264 char *name;
4265 {
4266 /* If the time interval for checking the files has changed, then
4267 reset the mail timer. Otherwise, one of the pathname vars
4268 to the users mailbox has changed, so rebuild the array of
4269 filenames. */
4270 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
4271 reset_mail_timer ();
4272 else
4273 {
4274 free_mail_files ();
4275 remember_mail_dates ();
4276 }
4277 }
4278
4279 /* What to do when GLOBIGNORE changes. */
4280 void
4281 sv_globignore (name)
4282 char *name;
4283 {
4284 if (privileged_mode == 0)
4285 setup_glob_ignore (name);
4286 }
4287
4288 #if defined (READLINE)
4289 void
4290 sv_comp_wordbreaks (name)
4291 char *name;
4292 {
4293 SHELL_VAR *sv;
4294
4295 sv = find_variable (name);
4296 if (sv == 0)
4297 reset_completer_word_break_chars ();
4298 }
4299
4300 /* What to do just after one of the TERMxxx variables has changed.
4301 If we are an interactive shell, then try to reset the terminal
4302 information in readline. */
4303 void
4304 sv_terminal (name)
4305 char *name;
4306 {
4307 if (interactive_shell && no_line_editing == 0)
4308 rl_reset_terminal (get_string_value ("TERM"));
4309 }
4310
4311 void
4312 sv_hostfile (name)
4313 char *name;
4314 {
4315 SHELL_VAR *v;
4316
4317 v = find_variable (name);
4318 if (v == 0)
4319 clear_hostname_list ();
4320 else
4321 hostname_list_initialized = 0;
4322 }
4323
4324 #if defined (STRICT_POSIX)
4325 /* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
4326 found in the initial environment) to override the terminal size reported by
4327 the kernel. */
4328 void
4329 sv_winsize (name)
4330 char *name;
4331 {
4332 SHELL_VAR *v;
4333 intmax_t xd;
4334 int d;
4335
4336 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
4337 return;
4338
4339 v = find_variable (name);
4340 if (v == 0 || var_isnull (v))
4341 rl_reset_screen_size ();
4342 else
4343 {
4344 if (legal_number (value_cell (v), &xd) == 0)
4345 return;
4346 winsize_assignment = winsize_assigned = 1;
4347 d = xd; /* truncate */
4348 if (name[0] == 'L') /* LINES */
4349 rl_set_screen_size (d, -1);
4350 else /* COLUMNS */
4351 rl_set_screen_size (-1, d);
4352 winsize_assignment = 0;
4353 }
4354 }
4355 #endif /* STRICT_POSIX */
4356 #endif /* READLINE */
4357
4358 /* Update the value of HOME in the export environment so tilde expansion will
4359 work on cygwin. */
4360 #if defined (__CYGWIN__)
4361 sv_home (name)
4362 char *name;
4363 {
4364 array_needs_making = 1;
4365 maybe_make_export_env ();
4366 }
4367 #endif
4368
4369 #if defined (HISTORY)
4370 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
4371 If there is a value for this HISTSIZE (and it is numeric), then stifle
4372 the history. Otherwise, if there is NO value for this variable,
4373 unstifle the history. If name is HISTFILESIZE, and its value is
4374 numeric, truncate the history file to hold no more than that many
4375 lines. */
4376 void
4377 sv_histsize (name)
4378 char *name;
4379 {
4380 char *temp;
4381 intmax_t num;
4382 int hmax;
4383
4384 temp = get_string_value (name);
4385
4386 if (temp && *temp)
4387 {
4388 if (legal_number (temp, &num))
4389 {
4390 hmax = num;
4391 if (name[4] == 'S')
4392 {
4393 stifle_history (hmax);
4394 hmax = where_history ();
4395 if (history_lines_this_session > hmax)
4396 history_lines_this_session = hmax;
4397 }
4398 else
4399 {
4400 history_truncate_file (get_string_value ("HISTFILE"), hmax);
4401 if (hmax <= history_lines_in_file)
4402 history_lines_in_file = hmax;
4403 }
4404 }
4405 }
4406 else if (name[4] == 'S')
4407 unstifle_history ();
4408 }
4409
4410 /* What to do after the HISTIGNORE variable changes. */
4411 void
4412 sv_histignore (name)
4413 char *name;
4414 {
4415 setup_history_ignore (name);
4416 }
4417
4418 /* What to do after the HISTCONTROL variable changes. */
4419 void
4420 sv_history_control (name)
4421 char *name;
4422 {
4423 char *temp;
4424 char *val;
4425 int tptr;
4426
4427 history_control = 0;
4428 temp = get_string_value (name);
4429
4430 if (temp == 0 || *temp == 0)
4431 return;
4432
4433 tptr = 0;
4434 while (val = extract_colon_unit (temp, &tptr))
4435 {
4436 if (STREQ (val, "ignorespace"))
4437 history_control |= HC_IGNSPACE;
4438 else if (STREQ (val, "ignoredups"))
4439 history_control |= HC_IGNDUPS;
4440 else if (STREQ (val, "ignoreboth"))
4441 history_control |= HC_IGNBOTH;
4442 else if (STREQ (val, "erasedups"))
4443 history_control |= HC_ERASEDUPS;
4444
4445 free (val);
4446 }
4447 }
4448
4449 #if defined (BANG_HISTORY)
4450 /* Setting/unsetting of the history expansion character. */
4451 void
4452 sv_histchars (name)
4453 char *name;
4454 {
4455 char *temp;
4456
4457 temp = get_string_value (name);
4458 if (temp)
4459 {
4460 history_expansion_char = *temp;
4461 if (temp[0] && temp[1])
4462 {
4463 history_subst_char = temp[1];
4464 if (temp[2])
4465 history_comment_char = temp[2];
4466 }
4467 }
4468 else
4469 {
4470 history_expansion_char = '!';
4471 history_subst_char = '^';
4472 history_comment_char = '#';
4473 }
4474 }
4475 #endif /* BANG_HISTORY */
4476
4477 void
4478 sv_histtimefmt (name)
4479 char *name;
4480 {
4481 SHELL_VAR *v;
4482
4483 v = find_variable (name);
4484 history_write_timestamps = (v != 0);
4485 }
4486 #endif /* HISTORY */
4487
4488 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
4489 void
4490 sv_tz (name)
4491 char *name;
4492 {
4493 tzset ();
4494 }
4495 #endif
4496
4497 /* If the variable exists, then the value of it can be the number
4498 of times we actually ignore the EOF. The default is small,
4499 (smaller than csh, anyway). */
4500 void
4501 sv_ignoreeof (name)
4502 char *name;
4503 {
4504 SHELL_VAR *tmp_var;
4505 char *temp;
4506
4507 eof_encountered = 0;
4508
4509 tmp_var = find_variable (name);
4510 ignoreeof = tmp_var != 0;
4511 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4512 if (temp)
4513 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
4514 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
4515 }
4516
4517 void
4518 sv_optind (name)
4519 char *name;
4520 {
4521 char *tt;
4522 int s;
4523
4524 tt = get_string_value ("OPTIND");
4525 if (tt && *tt)
4526 {
4527 s = atoi (tt);
4528
4529 /* According to POSIX, setting OPTIND=1 resets the internal state
4530 of getopt (). */
4531 if (s < 0 || s == 1)
4532 s = 0;
4533 }
4534 else
4535 s = 0;
4536 getopts_reset (s);
4537 }
4538
4539 void
4540 sv_opterr (name)
4541 char *name;
4542 {
4543 char *tt;
4544
4545 tt = get_string_value ("OPTERR");
4546 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
4547 }
4548
4549 void
4550 sv_strict_posix (name)
4551 char *name;
4552 {
4553 SET_INT_VAR (name, posixly_correct);
4554 posix_initialize (posixly_correct);
4555 #if defined (READLINE)
4556 if (interactive_shell)
4557 posix_readline_initialize (posixly_correct);
4558 #endif /* READLINE */
4559 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
4560 }
4561
4562 void
4563 sv_locale (name)
4564 char *name;
4565 {
4566 char *v;
4567
4568 v = get_string_value (name);
4569 if (name[0] == 'L' && name[1] == 'A') /* LANG */
4570 set_lang (name, v);
4571 else
4572 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
4573 }
4574
4575 #if defined (ARRAY_VARS)
4576 void
4577 set_pipestatus_array (ps, nproc)
4578 int *ps;
4579 int nproc;
4580 {
4581 SHELL_VAR *v;
4582 ARRAY *a;
4583 ARRAY_ELEMENT *ae;
4584 register int i;
4585 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
4586
4587 v = find_variable ("PIPESTATUS");
4588 if (v == 0)
4589 v = make_new_array_variable ("PIPESTATUS");
4590 if (array_p (v) == 0)
4591 return; /* Do nothing if not an array variable. */
4592 a = array_cell (v);
4593
4594 if (a == 0 || array_num_elements (a) == 0)
4595 {
4596 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
4597 {
4598 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4599 array_insert (a, i, t);
4600 }
4601 return;
4602 }
4603
4604 /* Fast case */
4605 if (array_num_elements (a) == nproc && nproc == 1)
4606 {
4607 ae = element_forw (a->head);
4608 free (element_value (ae));
4609 ae->value = itos (ps[0]);
4610 }
4611 else if (array_num_elements (a) <= nproc)
4612 {
4613 /* modify in array_num_elements members in place, then add */
4614 ae = a->head;
4615 for (i = 0; i < array_num_elements (a); i++)
4616 {
4617 ae = element_forw (ae);
4618 free (element_value (ae));
4619 ae->value = itos (ps[i]);
4620 }
4621 /* add any more */
4622 for ( ; i < nproc; i++)
4623 {
4624 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4625 array_insert (a, i, t);
4626 }
4627 }
4628 else
4629 {
4630 /* deleting elements. it's faster to rebuild the array. */
4631 array_flush (a);
4632 for (i = 0; ps[i] != -1; i++)
4633 {
4634 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4635 array_insert (a, i, t);
4636 }
4637 }
4638 }
4639 #endif
4640
4641 void
4642 set_pipestatus_from_exit (s)
4643 int s;
4644 {
4645 #if defined (ARRAY_VARS)
4646 static int v[2] = { 0, -1 };
4647
4648 v[0] = s;
4649 set_pipestatus_array (v, 1);
4650 #endif
4651 }
4652
4653 void
4654 sv_xtracefd (name)
4655 char *name;
4656 {
4657 SHELL_VAR *v;
4658 char *t, *e;
4659 int fd;
4660 FILE *fp;
4661
4662 v = find_variable (name);
4663 if (v == 0)
4664 {
4665 xtrace_reset ();
4666 return;
4667 }
4668
4669 t = value_cell (v);
4670 if (t == 0 || *t == 0)
4671 xtrace_reset ();
4672 else
4673 {
4674 fd = (int)strtol (t, &e, 10);
4675 if (e != t && *e == '\0' && sh_validfd (fd))
4676 {
4677 fp = fdopen (fd, "w");
4678 if (fp == 0)
4679 internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
4680 else
4681 xtrace_set (fd, fp);
4682 }
4683 else
4684 internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
4685 }
4686 }