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