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