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