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