]> git.ipfire.org Git - thirdparty/bash.git/blob - variables.c
Bash-5.2 patch 26: fix typo when specifying readline's custom color prefix
[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 global variable from it. This
4464 is called from merge_temporary_env, which is only called when in posix
4465 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 binding_table = global_variables->table;
4476 if (binding_table == 0)
4477 binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
4478
4479 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
4480
4481 /* global variables are no longer temporary and don't need propagating. */
4482 var->attributes &= ~(att_tempvar|att_propagate);
4483 if (v)
4484 v->attributes |= var->attributes;
4485
4486 if (find_special_var (var->name) >= 0)
4487 tempvar_list[tvlist_ind++] = savestring (var->name);
4488
4489 dispose_variable (var);
4490 }
4491
4492 /* Push the variable described by (SHELL_VAR *)DATA down to the next
4493 variable context from the temporary environment. This can be called
4494 from one context:
4495 1. propagate_temp_var: which is called to propagate variables in
4496 assignments like `var=value declare -x var' to the surrounding
4497 scope.
4498
4499 In this case, the variable should have the att_propagate flag set and
4500 we can create variables in the current scope.
4501 */
4502 static void
4503 push_temp_var (data)
4504 PTR_T data;
4505 {
4506 SHELL_VAR *var, *v;
4507 HASH_TABLE *binding_table;
4508
4509 var = (SHELL_VAR *)data;
4510
4511 binding_table = shell_variables->table;
4512 if (binding_table == 0)
4513 {
4514 if (shell_variables == global_variables)
4515 /* shouldn't happen */
4516 binding_table = shell_variables->table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
4517 else
4518 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
4519 }
4520
4521 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
4522
4523 /* XXX - should we set the context here? It shouldn't matter because of how
4524 assign_in_env works, but we do it anyway. */
4525 if (v)
4526 v->context = shell_variables->scope;
4527
4528 if (binding_table == global_variables->table) /* XXX */
4529 var->attributes &= ~(att_tempvar|att_propagate);
4530 else
4531 {
4532 var->attributes |= att_propagate;
4533 if (binding_table == shell_variables->table)
4534 shell_variables->flags |= VC_HASTMPVAR;
4535 }
4536 if (v)
4537 v->attributes |= var->attributes;
4538
4539 if (find_special_var (var->name) >= 0)
4540 tempvar_list[tvlist_ind++] = savestring (var->name);
4541
4542 dispose_variable (var);
4543 }
4544
4545 /* Take a variable described by DATA and push it to the surrounding scope if
4546 the PROPAGATE attribute is set. That gets set by push_temp_var if we are
4547 taking a variable like `var=value declare -x var' and propagating it to
4548 the enclosing scope. */
4549 static void
4550 propagate_temp_var (data)
4551 PTR_T data;
4552 {
4553 SHELL_VAR *var;
4554
4555 var = (SHELL_VAR *)data;
4556 if (tempvar_p (var) && (var->attributes & att_propagate))
4557 push_temp_var (data);
4558 else
4559 {
4560 if (find_special_var (var->name) >= 0)
4561 tempvar_list[tvlist_ind++] = savestring (var->name);
4562 dispose_variable (var);
4563 }
4564 }
4565
4566 /* Free the storage used in the hash table for temporary
4567 environment variables. PUSHF is a function to be called
4568 to free each hash table entry. It takes care of pushing variables
4569 to previous scopes if appropriate. PUSHF stores names of variables
4570 that require special handling (e.g., IFS) on tempvar_list, so this
4571 function can call stupidly_hack_special_variables on all the
4572 variables in the list when the temporary hash table is destroyed. */
4573 static void
4574 dispose_temporary_env (pushf)
4575 sh_free_func_t *pushf;
4576 {
4577 int i;
4578
4579 tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
4580 tempvar_list[tvlist_ind = 0] = 0;
4581
4582 hash_flush (temporary_env, pushf);
4583 hash_dispose (temporary_env);
4584 temporary_env = (HASH_TABLE *)NULL;
4585
4586 tempvar_list[tvlist_ind] = 0;
4587
4588 array_needs_making = 1;
4589
4590 for (i = 0; i < tvlist_ind; i++)
4591 stupidly_hack_special_variables (tempvar_list[i]);
4592
4593 strvec_dispose (tempvar_list);
4594 tempvar_list = 0;
4595 tvlist_ind = 0;
4596 }
4597
4598 void
4599 dispose_used_env_vars ()
4600 {
4601 if (temporary_env)
4602 {
4603 dispose_temporary_env (propagate_temp_var);
4604 maybe_make_export_env ();
4605 }
4606 }
4607
4608 /* Take all of the shell variables in the temporary environment HASH_TABLE
4609 and make shell variables from them at the current variable context.
4610 Right now, this is only called in Posix mode to implement the historical
4611 accident of creating global variables from assignment statements preceding
4612 special builtins, but we check in case this acquires another caller later. */
4613 void
4614 merge_temporary_env ()
4615 {
4616 if (temporary_env)
4617 dispose_temporary_env (posixly_correct ? push_posix_temp_var : push_temp_var);
4618 }
4619
4620 void
4621 flush_temporary_env ()
4622 {
4623 if (temporary_env)
4624 {
4625 hash_flush (temporary_env, free_variable_hash_data);
4626 hash_dispose (temporary_env);
4627 temporary_env = (HASH_TABLE *)NULL;
4628 }
4629 }
4630
4631 /* **************************************************************** */
4632 /* */
4633 /* Creating and manipulating the environment */
4634 /* */
4635 /* **************************************************************** */
4636
4637 static inline char *
4638 mk_env_string (name, value, isfunc)
4639 const char *name, *value;
4640 int isfunc;
4641 {
4642 size_t name_len, value_len;
4643 char *p, *q, *t;
4644
4645 name_len = strlen (name);
4646 value_len = STRLEN (value);
4647
4648 /* If we are exporting a shell function, construct the encoded function
4649 name. */
4650 if (isfunc && value)
4651 {
4652 p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2);
4653 q = p;
4654 memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN);
4655 q += BASHFUNC_PREFLEN;
4656 memcpy (q, name, name_len);
4657 q += name_len;
4658 memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN);
4659 q += BASHFUNC_SUFFLEN;
4660 }
4661 else
4662 {
4663 p = (char *)xmalloc (2 + name_len + value_len);
4664 memcpy (p, name, name_len);
4665 q = p + name_len;
4666 }
4667
4668 q[0] = '=';
4669 if (value && *value)
4670 {
4671 if (isfunc)
4672 {
4673 t = dequote_escapes (value);
4674 value_len = STRLEN (t);
4675 memcpy (q + 1, t, value_len + 1);
4676 free (t);
4677 }
4678 else
4679 memcpy (q + 1, value, value_len + 1);
4680 }
4681 else
4682 q[1] = '\0';
4683
4684 return (p);
4685 }
4686
4687 #ifdef DEBUG
4688 /* Debugging */
4689 static int
4690 valid_exportstr (v)
4691 SHELL_VAR *v;
4692 {
4693 char *s;
4694
4695 s = v->exportstr;
4696 if (s == 0)
4697 {
4698 internal_error (_("%s has null exportstr"), v->name);
4699 return (0);
4700 }
4701 if (legal_variable_starter ((unsigned char)*s) == 0)
4702 {
4703 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
4704 return (0);
4705 }
4706 for (s = v->exportstr + 1; s && *s; s++)
4707 {
4708 if (*s == '=')
4709 break;
4710 if (legal_variable_char ((unsigned char)*s) == 0)
4711 {
4712 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
4713 return (0);
4714 }
4715 }
4716 if (*s != '=')
4717 {
4718 internal_error (_("no `=' in exportstr for %s"), v->name);
4719 return (0);
4720 }
4721 return (1);
4722 }
4723 #endif
4724
4725 static char **
4726 make_env_array_from_var_list (vars)
4727 SHELL_VAR **vars;
4728 {
4729 register int i, list_index;
4730 register SHELL_VAR *var;
4731 char **list, *value;
4732
4733 list = strvec_create ((1 + strvec_len ((char **)vars)));
4734
4735 #define USE_EXPORTSTR (value == var->exportstr)
4736
4737 for (i = 0, list_index = 0; var = vars[i]; i++)
4738 {
4739 #if defined (__CYGWIN__)
4740 /* We don't use the exportstr stuff on Cygwin at all. */
4741 INVALIDATE_EXPORTSTR (var);
4742 #endif
4743
4744 /* If the value is generated dynamically, generate it here. */
4745 if (regen_p (var) && var->dynamic_value)
4746 {
4747 var = (*(var->dynamic_value)) (var);
4748 INVALIDATE_EXPORTSTR (var);
4749 }
4750
4751 if (var->exportstr)
4752 value = var->exportstr;
4753 else if (function_p (var))
4754 value = named_function_string ((char *)NULL, function_cell (var), 0);
4755 #if defined (ARRAY_VARS)
4756 else if (array_p (var))
4757 # if ARRAY_EXPORT
4758 value = array_to_assign (array_cell (var), 0);
4759 # else
4760 continue; /* XXX array vars cannot yet be exported */
4761 # endif /* ARRAY_EXPORT */
4762 else if (assoc_p (var))
4763 # if 0
4764 value = assoc_to_assign (assoc_cell (var), 0);
4765 # else
4766 continue; /* XXX associative array vars cannot yet be exported */
4767 # endif
4768 #endif
4769 else
4770 value = value_cell (var);
4771
4772 if (value)
4773 {
4774 /* Gee, I'd like to get away with not using savestring() if we're
4775 using the cached exportstr... */
4776 list[list_index] = USE_EXPORTSTR ? savestring (value)
4777 : mk_env_string (var->name, value, function_p (var));
4778
4779 if (USE_EXPORTSTR == 0)
4780 SAVE_EXPORTSTR (var, list[list_index]);
4781
4782 list_index++;
4783 #undef USE_EXPORTSTR
4784
4785 #if 0 /* not yet */
4786 #if defined (ARRAY_VARS)
4787 if (array_p (var) || assoc_p (var))
4788 free (value);
4789 #endif
4790 #endif
4791 }
4792 }
4793
4794 list[list_index] = (char *)NULL;
4795 return (list);
4796 }
4797
4798 /* Make an array of assignment statements from the hash table
4799 HASHED_VARS which contains SHELL_VARs. Only visible, exported
4800 variables are eligible. */
4801 static char **
4802 make_var_export_array (vcxt)
4803 VAR_CONTEXT *vcxt;
4804 {
4805 char **list;
4806 SHELL_VAR **vars;
4807
4808 #if 0
4809 vars = map_over (visible_and_exported, vcxt);
4810 #else
4811 vars = map_over (export_environment_candidate, vcxt);
4812 #endif
4813
4814 if (vars == 0)
4815 return (char **)NULL;
4816
4817 list = make_env_array_from_var_list (vars);
4818
4819 free (vars);
4820 return (list);
4821 }
4822
4823 static char **
4824 make_func_export_array ()
4825 {
4826 char **list;
4827 SHELL_VAR **vars;
4828
4829 vars = map_over_funcs (visible_and_exported);
4830 if (vars == 0)
4831 return (char **)NULL;
4832
4833 list = make_env_array_from_var_list (vars);
4834
4835 free (vars);
4836 return (list);
4837 }
4838
4839 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
4840 #define add_to_export_env(envstr,do_alloc) \
4841 do \
4842 { \
4843 if (export_env_index >= (export_env_size - 1)) \
4844 { \
4845 export_env_size += 16; \
4846 export_env = strvec_resize (export_env, export_env_size); \
4847 environ = export_env; \
4848 } \
4849 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
4850 export_env[export_env_index] = (char *)NULL; \
4851 } while (0)
4852
4853 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
4854 array with the same left-hand side. Return the new EXPORT_ENV. */
4855 char **
4856 add_or_supercede_exported_var (assign, do_alloc)
4857 char *assign;
4858 int do_alloc;
4859 {
4860 register int i;
4861 int equal_offset;
4862
4863 equal_offset = assignment (assign, 0);
4864 if (equal_offset == 0)
4865 return (export_env);
4866
4867 /* If this is a function, then only supersede the function definition.
4868 We do this by including the `=() {' in the comparison, like
4869 initialize_shell_variables does. */
4870 if (assign[equal_offset + 1] == '(' &&
4871 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
4872 equal_offset += 4;
4873
4874 for (i = 0; i < export_env_index; i++)
4875 {
4876 if (STREQN (assign, export_env[i], equal_offset + 1))
4877 {
4878 free (export_env[i]);
4879 export_env[i] = do_alloc ? savestring (assign) : assign;
4880 return (export_env);
4881 }
4882 }
4883 add_to_export_env (assign, do_alloc);
4884 return (export_env);
4885 }
4886
4887 static void
4888 add_temp_array_to_env (temp_array, do_alloc, do_supercede)
4889 char **temp_array;
4890 int do_alloc, do_supercede;
4891 {
4892 register int i;
4893
4894 if (temp_array == 0)
4895 return;
4896
4897 for (i = 0; temp_array[i]; i++)
4898 {
4899 if (do_supercede)
4900 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
4901 else
4902 add_to_export_env (temp_array[i], do_alloc);
4903 }
4904
4905 free (temp_array);
4906 }
4907
4908 /* Make the environment array for the command about to be executed, if the
4909 array needs making. Otherwise, do nothing. If a shell action could
4910 change the array that commands receive for their environment, then the
4911 code should `array_needs_making++'.
4912
4913 The order to add to the array is:
4914 temporary_env
4915 list of var contexts whose head is shell_variables
4916 shell_functions
4917
4918 This is the shell variable lookup order. We add only new variable
4919 names at each step, which allows local variables and variables in
4920 the temporary environments to shadow variables in the global (or
4921 any previous) scope.
4922 */
4923
4924 static int
4925 n_shell_variables ()
4926 {
4927 VAR_CONTEXT *vc;
4928 int n;
4929
4930 for (n = 0, vc = shell_variables; vc; vc = vc->down)
4931 n += HASH_ENTRIES (vc->table);
4932 return n;
4933 }
4934
4935 int
4936 chkexport (name)
4937 char *name;
4938 {
4939 SHELL_VAR *v;
4940
4941 v = find_variable (name);
4942 if (v && exported_p (v))
4943 {
4944 array_needs_making = 1;
4945 maybe_make_export_env ();
4946 return 1;
4947 }
4948 return 0;
4949 }
4950
4951 void
4952 maybe_make_export_env ()
4953 {
4954 register char **temp_array;
4955 int new_size;
4956 VAR_CONTEXT *tcxt, *icxt;
4957
4958 if (array_needs_making)
4959 {
4960 if (export_env)
4961 strvec_flush (export_env);
4962
4963 /* Make a guess based on how many shell variables and functions we
4964 have. Since there will always be array variables, and array
4965 variables are not (yet) exported, this will always be big enough
4966 for the exported variables and functions. */
4967 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
4968 HASH_ENTRIES (temporary_env) + HASH_ENTRIES (invalid_env);
4969 if (new_size > export_env_size)
4970 {
4971 export_env_size = new_size;
4972 export_env = strvec_resize (export_env, export_env_size);
4973 environ = export_env;
4974 }
4975 export_env[export_env_index = 0] = (char *)NULL;
4976
4977 /* Make a dummy variable context from the temporary_env, stick it on
4978 the front of shell_variables, call make_var_export_array on the
4979 whole thing to flatten it, and convert the list of SHELL_VAR *s
4980 to the form needed by the environment. */
4981 if (temporary_env)
4982 {
4983 tcxt = new_var_context ((char *)NULL, 0);
4984 tcxt->table = temporary_env;
4985 tcxt->down = shell_variables;
4986 }
4987 else
4988 tcxt = shell_variables;
4989
4990 if (invalid_env)
4991 {
4992 icxt = new_var_context ((char *)NULL, 0);
4993 icxt->table = invalid_env;
4994 icxt->down = tcxt;
4995 }
4996 else
4997 icxt = tcxt;
4998
4999 temp_array = make_var_export_array (icxt);
5000 if (temp_array)
5001 add_temp_array_to_env (temp_array, 0, 0);
5002
5003 if (icxt != tcxt)
5004 free (icxt);
5005
5006 if (tcxt != shell_variables)
5007 free (tcxt);
5008
5009 #if defined (RESTRICTED_SHELL)
5010 /* Restricted shells may not export shell functions. */
5011 temp_array = restricted ? (char **)0 : make_func_export_array ();
5012 #else
5013 temp_array = make_func_export_array ();
5014 #endif
5015 if (temp_array)
5016 add_temp_array_to_env (temp_array, 0, 0);
5017
5018 array_needs_making = 0;
5019 }
5020 }
5021
5022 /* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
5023 we will need to remake the exported environment every time we
5024 change directories. `_' is always put into the environment for
5025 every external command, so without special treatment it will always
5026 cause the environment to be remade.
5027
5028 If there is no other reason to make the exported environment, we can
5029 just update the variables in place and mark the exported environment
5030 as no longer needing a remake. */
5031 void
5032 update_export_env_inplace (env_prefix, preflen, value)
5033 char *env_prefix;
5034 int preflen;
5035 char *value;
5036 {
5037 char *evar;
5038
5039 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
5040 strcpy (evar, env_prefix);
5041 if (value)
5042 strcpy (evar + preflen, value);
5043 export_env = add_or_supercede_exported_var (evar, 0);
5044 }
5045
5046 /* We always put _ in the environment as the name of this command. */
5047 void
5048 put_command_name_into_env (command_name)
5049 char *command_name;
5050 {
5051 update_export_env_inplace ("_=", 2, command_name);
5052 }
5053
5054 /* **************************************************************** */
5055 /* */
5056 /* Managing variable contexts */
5057 /* */
5058 /* **************************************************************** */
5059
5060 /* Allocate and return a new variable context with NAME and FLAGS.
5061 NAME can be NULL. */
5062
5063 VAR_CONTEXT *
5064 new_var_context (name, flags)
5065 char *name;
5066 int flags;
5067 {
5068 VAR_CONTEXT *vc;
5069
5070 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
5071 vc->name = name ? savestring (name) : (char *)NULL;
5072 vc->scope = variable_context;
5073 vc->flags = flags;
5074
5075 vc->up = vc->down = (VAR_CONTEXT *)NULL;
5076 vc->table = (HASH_TABLE *)NULL;
5077
5078 return vc;
5079 }
5080
5081 /* Free a variable context and its data, including the hash table. Dispose
5082 all of the variables. */
5083 void
5084 dispose_var_context (vc)
5085 VAR_CONTEXT *vc;
5086 {
5087 FREE (vc->name);
5088
5089 if (vc->table)
5090 {
5091 delete_all_variables (vc->table);
5092 hash_dispose (vc->table);
5093 }
5094
5095 free (vc);
5096 }
5097
5098 /* Set VAR's scope level to the current variable context. */
5099 static int
5100 set_context (var)
5101 SHELL_VAR *var;
5102 {
5103 return (var->context = variable_context);
5104 }
5105
5106 /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
5107 temporary variables, and push it onto shell_variables. This is
5108 for shell functions. */
5109 VAR_CONTEXT *
5110 push_var_context (name, flags, tempvars)
5111 char *name;
5112 int flags;
5113 HASH_TABLE *tempvars;
5114 {
5115 VAR_CONTEXT *vc;
5116 int posix_func_behavior;
5117
5118 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5119 functions no longer behave like assignment statements preceding
5120 special builtins, and do not persist in the current shell environment.
5121 This is austin group interp #654, though nobody implements it yet. */
5122 #if 0 /* XXX - TAG: bash-5.1 */
5123 posix_func_behavior = 0;
5124 #else
5125 posix_func_behavior = posixly_correct;
5126 #endif
5127
5128 vc = new_var_context (name, flags);
5129 /* Posix interp 1009, temporary assignments preceding function calls modify
5130 the current environment *before* the command is executed. */
5131 if (posix_func_behavior && (flags & VC_FUNCENV) && tempvars == temporary_env)
5132 merge_temporary_env ();
5133 else if (tempvars)
5134 {
5135 vc->table = tempvars;
5136 /* Have to do this because the temp environment was created before
5137 variable_context was incremented. */
5138 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
5139 vc->flags |= VC_HASTMPVAR;
5140 }
5141 vc->down = shell_variables;
5142 shell_variables->up = vc;
5143
5144 return (shell_variables = vc);
5145 }
5146
5147 /* This can be called from one of two code paths:
5148 1. pop_scope, which implements the posix rules for propagating variable
5149 assignments preceding special builtins to the surrounding scope
5150 (push_builtin_var);
5151 2. pop_var_context, which is called from pop_context and implements the
5152 posix rules for propagating variable assignments preceding function
5153 calls to the surrounding scope (push_func_var).
5154
5155 It takes variables out of a temporary environment hash table. We take the
5156 variable in data.
5157 */
5158
5159 static inline void
5160 push_posix_tempvar_internal (var, isbltin)
5161 SHELL_VAR *var;
5162 int isbltin;
5163 {
5164 SHELL_VAR *v;
5165 int posix_var_behavior;
5166
5167 /* As of IEEE Std 1003.1-2017, assignment statements preceding shell
5168 functions no longer behave like assignment statements preceding
5169 special builtins, and do not persist in the current shell environment.
5170 This is austin group interp #654, though nobody implements it yet. */
5171 #if 0 /* XXX - TAG: bash-5.1 */
5172 posix_var_behavior = posixly_correct && isbltin;
5173 #else
5174 posix_var_behavior = posixly_correct;
5175 #endif
5176
5177 if (local_p (var) && STREQ (var->name, "-"))
5178 set_current_options (value_cell (var));
5179 else if (tempvar_p (var) && (posix_var_behavior || (var->attributes & att_propagate)))
5180 {
5181 /* Make sure we have a hash table to store the variable in while it is
5182 being propagated down to the global variables table. Create one if
5183 we have to */
5184 if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
5185 shell_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
5186 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
5187 /* XXX - should we set v->context here? */
5188 if (v)
5189 v->context = shell_variables->scope;
5190 #if defined (ARRAY_VARS)
5191 if (v && (array_p (var) || assoc_p (var)))
5192 {
5193 FREE (value_cell (v));
5194 if (array_p (var))
5195 var_setarray (v, array_copy (array_cell (var)));
5196 else
5197 var_setassoc (v, assoc_copy (assoc_cell (var)));
5198 }
5199 #endif
5200 if (shell_variables == global_variables)
5201 var->attributes &= ~(att_tempvar|att_propagate);
5202 else
5203 shell_variables->flags |= VC_HASTMPVAR;
5204 if (v)
5205 v->attributes |= var->attributes;
5206 }
5207 else
5208 stupidly_hack_special_variables (var->name); /* XXX */
5209
5210 dispose_variable (var);
5211 }
5212
5213 static void
5214 push_func_var (data)
5215 PTR_T data;
5216 {
5217 SHELL_VAR *var;
5218
5219 var = (SHELL_VAR *)data;
5220 push_posix_tempvar_internal (var, 0);
5221 }
5222
5223 static void
5224 push_builtin_var (data)
5225 PTR_T data;
5226 {
5227 SHELL_VAR *var;
5228
5229 var = (SHELL_VAR *)data;
5230 push_posix_tempvar_internal (var, 1);
5231 }
5232
5233 /* Pop the top context off of VCXT and dispose of it, returning the rest of
5234 the stack. */
5235 void
5236 pop_var_context ()
5237 {
5238 VAR_CONTEXT *ret, *vcxt;
5239
5240 vcxt = shell_variables;
5241 if (vc_isfuncenv (vcxt) == 0)
5242 {
5243 internal_error (_("pop_var_context: head of shell_variables not a function context"));
5244 return;
5245 }
5246
5247 if (ret = vcxt->down)
5248 {
5249 ret->up = (VAR_CONTEXT *)NULL;
5250 shell_variables = ret;
5251 if (vcxt->table)
5252 hash_flush (vcxt->table, push_func_var);
5253 dispose_var_context (vcxt);
5254 }
5255 else
5256 internal_error (_("pop_var_context: no global_variables context"));
5257 }
5258
5259 /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
5260 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
5261 void
5262 delete_all_contexts (vcxt)
5263 VAR_CONTEXT *vcxt;
5264 {
5265 VAR_CONTEXT *v, *t;
5266
5267 for (v = vcxt; v != global_variables; v = t)
5268 {
5269 t = v->down;
5270 dispose_var_context (v);
5271 }
5272
5273 delete_all_variables (global_variables->table);
5274 shell_variables = global_variables;
5275 }
5276
5277 /* **************************************************************** */
5278 /* */
5279 /* Pushing and Popping temporary variable scopes */
5280 /* */
5281 /* **************************************************************** */
5282
5283 VAR_CONTEXT *
5284 push_scope (flags, tmpvars)
5285 int flags;
5286 HASH_TABLE *tmpvars;
5287 {
5288 return (push_var_context ((char *)NULL, flags, tmpvars));
5289 }
5290
5291 static void
5292 push_exported_var (data)
5293 PTR_T data;
5294 {
5295 SHELL_VAR *var, *v;
5296
5297 var = (SHELL_VAR *)data;
5298
5299 /* If a temp var had its export attribute set, or it's marked to be
5300 propagated, bind it in the previous scope before disposing it. */
5301 /* XXX - This isn't exactly right, because all tempenv variables have the
5302 export attribute set. */
5303 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
5304 {
5305 var->attributes &= ~att_tempvar; /* XXX */
5306 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
5307 if (shell_variables == global_variables)
5308 var->attributes &= ~att_propagate;
5309 if (v)
5310 {
5311 v->attributes |= var->attributes;
5312 v->context = shell_variables->scope;
5313 }
5314 }
5315 else
5316 stupidly_hack_special_variables (var->name); /* XXX */
5317
5318 dispose_variable (var);
5319 }
5320
5321 /* This is called to propagate variables in the temporary environment of a
5322 special builtin (if IS_SPECIAL != 0) or exported variables that are the
5323 result of a builtin like `source' or `command' that can operate on the
5324 variables in its temporary environment. In the first case, we call
5325 push_builtin_var, which does the right thing. */
5326 void
5327 pop_scope (is_special)
5328 int is_special;
5329 {
5330 VAR_CONTEXT *vcxt, *ret;
5331 int is_bltinenv;
5332
5333 vcxt = shell_variables;
5334 if (vc_istempscope (vcxt) == 0)
5335 {
5336 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
5337 return;
5338 }
5339 is_bltinenv = vc_isbltnenv (vcxt); /* XXX - for later */
5340
5341 ret = vcxt->down;
5342 if (ret)
5343 ret->up = (VAR_CONTEXT *)NULL;
5344
5345 shell_variables = ret;
5346
5347 /* Now we can take care of merging variables in VCXT into set of scopes
5348 whose head is RET (shell_variables). */
5349 FREE (vcxt->name);
5350 if (vcxt->table)
5351 {
5352 if (is_special)
5353 hash_flush (vcxt->table, push_builtin_var);
5354 else
5355 hash_flush (vcxt->table, push_exported_var);
5356 hash_dispose (vcxt->table);
5357 }
5358 free (vcxt);
5359
5360 sv_ifs ("IFS"); /* XXX here for now */
5361 }
5362
5363 /* **************************************************************** */
5364 /* */
5365 /* Pushing and Popping function contexts */
5366 /* */
5367 /* **************************************************************** */
5368
5369 struct saved_dollar_vars {
5370 char **first_ten;
5371 WORD_LIST *rest;
5372 };
5373
5374 static struct saved_dollar_vars *dollar_arg_stack = (struct saved_dollar_vars *)NULL;
5375 static int dollar_arg_stack_slots;
5376 static int dollar_arg_stack_index;
5377
5378 /* Functions to manipulate dollar_vars array. Need to keep these in sync with
5379 whatever remember_args() does. */
5380 static char **
5381 save_dollar_vars ()
5382 {
5383 char **ret;
5384 int i;
5385
5386 ret = strvec_create (10);
5387 for (i = 1; i < 10; i++)
5388 {
5389 ret[i] = dollar_vars[i];
5390 dollar_vars[i] = (char *)NULL;
5391 }
5392 return ret;
5393 }
5394
5395 static void
5396 restore_dollar_vars (args)
5397 char **args;
5398 {
5399 int i;
5400
5401 for (i = 1; i < 10; i++)
5402 dollar_vars[i] = args[i];
5403 }
5404
5405 static void
5406 free_dollar_vars ()
5407 {
5408 int i;
5409
5410 for (i = 1; i < 10; i++)
5411 {
5412 FREE (dollar_vars[i]);
5413 dollar_vars[i] = (char *)NULL;
5414 }
5415 }
5416
5417 static void
5418 free_saved_dollar_vars (args)
5419 char **args;
5420 {
5421 int i;
5422
5423 for (i = 1; i < 10; i++)
5424 FREE (args[i]);
5425 }
5426
5427 /* XXX - should always be followed by remember_args () */
5428 void
5429 push_context (name, is_subshell, tempvars)
5430 char *name; /* function name */
5431 int is_subshell;
5432 HASH_TABLE *tempvars;
5433 {
5434 if (is_subshell == 0)
5435 push_dollar_vars ();
5436 variable_context++;
5437 push_var_context (name, VC_FUNCENV, tempvars);
5438 }
5439
5440 /* Only called when subshell == 0, so we don't need to check, and can
5441 unconditionally pop the dollar vars off the stack. */
5442 void
5443 pop_context ()
5444 {
5445 pop_dollar_vars ();
5446 variable_context--;
5447 pop_var_context ();
5448
5449 sv_ifs ("IFS"); /* XXX here for now */
5450 }
5451
5452 /* Save the existing positional parameters on a stack. */
5453 void
5454 push_dollar_vars ()
5455 {
5456 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
5457 {
5458 dollar_arg_stack = (struct saved_dollar_vars *)
5459 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
5460 * sizeof (struct saved_dollar_vars));
5461 }
5462
5463 dollar_arg_stack[dollar_arg_stack_index].first_ten = save_dollar_vars ();
5464 dollar_arg_stack[dollar_arg_stack_index++].rest = rest_of_args;
5465 rest_of_args = (WORD_LIST *)NULL;
5466
5467 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5468 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5469 }
5470
5471 /* Restore the positional parameters from our stack. */
5472 void
5473 pop_dollar_vars ()
5474 {
5475 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
5476 return;
5477
5478 /* Do what remember_args (xxx, 1) would have done. */
5479 free_dollar_vars ();
5480 dispose_words (rest_of_args);
5481
5482 rest_of_args = dollar_arg_stack[--dollar_arg_stack_index].rest;
5483 restore_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5484 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5485
5486 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5487 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5488
5489 set_dollar_vars_unchanged ();
5490 invalidate_cached_quoted_dollar_at ();
5491 }
5492
5493 void
5494 dispose_saved_dollar_vars ()
5495 {
5496 if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
5497 return;
5498
5499 dispose_words (dollar_arg_stack[--dollar_arg_stack_index].rest);
5500 free_saved_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5501 free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
5502
5503 dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
5504 dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
5505 }
5506
5507 /* Initialize BASH_ARGV and BASH_ARGC after turning on extdebug after the
5508 shell is initialized */
5509 void
5510 init_bash_argv ()
5511 {
5512 if (bash_argv_initialized == 0)
5513 {
5514 save_bash_argv ();
5515 bash_argv_initialized = 1;
5516 }
5517 }
5518
5519 void
5520 save_bash_argv ()
5521 {
5522 WORD_LIST *list;
5523
5524 list = list_rest_of_args ();
5525 push_args (list);
5526 dispose_words (list);
5527 }
5528
5529 /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
5530
5531 void
5532 push_args (list)
5533 WORD_LIST *list;
5534 {
5535 #if defined (ARRAY_VARS) && defined (DEBUGGER)
5536 SHELL_VAR *bash_argv_v, *bash_argc_v;
5537 ARRAY *bash_argv_a, *bash_argc_a;
5538 WORD_LIST *l;
5539 arrayind_t i;
5540 char *t;
5541
5542 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5543 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5544
5545 for (l = list, i = 0; l; l = l->next, i++)
5546 array_push (bash_argv_a, l->word->word);
5547
5548 t = itos (i);
5549 array_push (bash_argc_a, t);
5550 free (t);
5551 #endif /* ARRAY_VARS && DEBUGGER */
5552 }
5553
5554 /* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
5555 array and use that value as the count of elements to remove from
5556 BASH_ARGV. */
5557 void
5558 pop_args ()
5559 {
5560 #if defined (ARRAY_VARS) && defined (DEBUGGER)
5561 SHELL_VAR *bash_argv_v, *bash_argc_v;
5562 ARRAY *bash_argv_a, *bash_argc_a;
5563 ARRAY_ELEMENT *ce;
5564 intmax_t i;
5565
5566 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
5567 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
5568
5569 ce = array_shift (bash_argc_a, 1, 0);
5570 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
5571 i = 0;
5572
5573 for ( ; i > 0; i--)
5574 array_pop (bash_argv_a);
5575 array_dispose_element (ce);
5576 #endif /* ARRAY_VARS && DEBUGGER */
5577 }
5578
5579 /*************************************************
5580 * *
5581 * Functions to manage special variables *
5582 * *
5583 *************************************************/
5584
5585 /* Extern declarations for variables this code has to manage. */
5586
5587 /* An alist of name.function for each special variable. Most of the
5588 functions don't do much, and in fact, this would be faster with a
5589 switch statement, but by the end of this file, I am sick of switch
5590 statements. */
5591
5592 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
5593
5594 /* This table will be sorted with qsort() the first time it's accessed. */
5595 struct name_and_function {
5596 char *name;
5597 sh_sv_func_t *function;
5598 };
5599
5600 static struct name_and_function special_vars[] = {
5601 { "BASH_COMPAT", sv_shcompat },
5602 { "BASH_XTRACEFD", sv_xtracefd },
5603
5604 #if defined (JOB_CONTROL)
5605 { "CHILD_MAX", sv_childmax },
5606 #endif
5607
5608 #if defined (READLINE)
5609 # if defined (STRICT_POSIX)
5610 { "COLUMNS", sv_winsize },
5611 # endif
5612 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
5613 #endif
5614
5615 { "EXECIGNORE", sv_execignore },
5616
5617 { "FUNCNEST", sv_funcnest },
5618
5619 { "GLOBIGNORE", sv_globignore },
5620
5621 #if defined (HISTORY)
5622 { "HISTCONTROL", sv_history_control },
5623 { "HISTFILESIZE", sv_histsize },
5624 { "HISTIGNORE", sv_histignore },
5625 { "HISTSIZE", sv_histsize },
5626 { "HISTTIMEFORMAT", sv_histtimefmt },
5627 #endif
5628
5629 #if defined (__CYGWIN__)
5630 { "HOME", sv_home },
5631 #endif
5632
5633 #if defined (READLINE)
5634 { "HOSTFILE", sv_hostfile },
5635 #endif
5636
5637 { "IFS", sv_ifs },
5638 { "IGNOREEOF", sv_ignoreeof },
5639
5640 { "LANG", sv_locale },
5641 { "LC_ALL", sv_locale },
5642 { "LC_COLLATE", sv_locale },
5643 { "LC_CTYPE", sv_locale },
5644 { "LC_MESSAGES", sv_locale },
5645 { "LC_NUMERIC", sv_locale },
5646 { "LC_TIME", sv_locale },
5647
5648 #if defined (READLINE) && defined (STRICT_POSIX)
5649 { "LINES", sv_winsize },
5650 #endif
5651
5652 { "MAIL", sv_mail },
5653 { "MAILCHECK", sv_mail },
5654 { "MAILPATH", sv_mail },
5655
5656 { "OPTERR", sv_opterr },
5657 { "OPTIND", sv_optind },
5658
5659 { "PATH", sv_path },
5660 { "POSIXLY_CORRECT", sv_strict_posix },
5661
5662 #if defined (READLINE)
5663 { "TERM", sv_terminal },
5664 { "TERMCAP", sv_terminal },
5665 { "TERMINFO", sv_terminal },
5666 #endif /* READLINE */
5667
5668 { "TEXTDOMAIN", sv_locale },
5669 { "TEXTDOMAINDIR", sv_locale },
5670
5671 #if defined (HAVE_TZSET)
5672 { "TZ", sv_tz },
5673 #endif
5674
5675 #if defined (HISTORY) && defined (BANG_HISTORY)
5676 { "histchars", sv_histchars },
5677 #endif /* HISTORY && BANG_HISTORY */
5678
5679 { "ignoreeof", sv_ignoreeof },
5680
5681 { (char *)0, (sh_sv_func_t *)0 }
5682 };
5683
5684 #define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
5685
5686 static int
5687 sv_compare (sv1, sv2)
5688 struct name_and_function *sv1, *sv2;
5689 {
5690 int r;
5691
5692 if ((r = sv1->name[0] - sv2->name[0]) == 0)
5693 r = strcmp (sv1->name, sv2->name);
5694 return r;
5695 }
5696
5697 static inline int
5698 find_special_var (name)
5699 const char *name;
5700 {
5701 register int i, r;
5702
5703 for (i = 0; special_vars[i].name; i++)
5704 {
5705 r = special_vars[i].name[0] - name[0];
5706 if (r == 0)
5707 r = strcmp (special_vars[i].name, name);
5708 if (r == 0)
5709 return i;
5710 else if (r > 0)
5711 /* Can't match any of rest of elements in sorted list. Take this out
5712 if it causes problems in certain environments. */
5713 break;
5714 }
5715 return -1;
5716 }
5717
5718 /* The variable in NAME has just had its state changed. Check to see if it
5719 is one of the special ones where something special happens. */
5720 void
5721 stupidly_hack_special_variables (name)
5722 char *name;
5723 {
5724 static int sv_sorted = 0;
5725 int i;
5726
5727 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
5728 {
5729 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
5730 (QSFUNC *)sv_compare);
5731 sv_sorted = 1;
5732 }
5733
5734 i = find_special_var (name);
5735 if (i != -1)
5736 (*(special_vars[i].function)) (name);
5737 }
5738
5739 /* Special variables that need hooks to be run when they are unset as part
5740 of shell reinitialization should have their sv_ functions run here. */
5741 void
5742 reinit_special_variables ()
5743 {
5744 #if defined (READLINE)
5745 sv_comp_wordbreaks ("COMP_WORDBREAKS");
5746 #endif
5747 sv_globignore ("GLOBIGNORE");
5748 sv_opterr ("OPTERR");
5749 }
5750
5751 void
5752 sv_ifs (name)
5753 char *name;
5754 {
5755 SHELL_VAR *v;
5756
5757 v = find_variable ("IFS");
5758 setifs (v);
5759 }
5760
5761 /* What to do just after the PATH variable has changed. */
5762 void
5763 sv_path (name)
5764 char *name;
5765 {
5766 /* hash -r */
5767 phash_flush ();
5768 }
5769
5770 /* What to do just after one of the MAILxxxx variables has changed. NAME
5771 is the name of the variable. This is called with NAME set to one of
5772 MAIL, MAILCHECK, or MAILPATH. */
5773 void
5774 sv_mail (name)
5775 char *name;
5776 {
5777 /* If the time interval for checking the files has changed, then
5778 reset the mail timer. Otherwise, one of the pathname vars
5779 to the users mailbox has changed, so rebuild the array of
5780 filenames. */
5781 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
5782 reset_mail_timer ();
5783 else
5784 {
5785 free_mail_files ();
5786 remember_mail_dates ();
5787 }
5788 }
5789
5790 void
5791 sv_funcnest (name)
5792 char *name;
5793 {
5794 SHELL_VAR *v;
5795 intmax_t num;
5796
5797 v = find_variable (name);
5798 if (v == 0)
5799 funcnest_max = 0;
5800 else if (legal_number (value_cell (v), &num) == 0)
5801 funcnest_max = 0;
5802 else
5803 funcnest_max = num;
5804 }
5805
5806 /* What to do when EXECIGNORE changes. */
5807 void
5808 sv_execignore (name)
5809 char *name;
5810 {
5811 setup_exec_ignore (name);
5812 }
5813
5814 /* What to do when GLOBIGNORE changes. */
5815 void
5816 sv_globignore (name)
5817 char *name;
5818 {
5819 if (privileged_mode == 0)
5820 setup_glob_ignore (name);
5821 }
5822
5823 #if defined (READLINE)
5824 void
5825 sv_comp_wordbreaks (name)
5826 char *name;
5827 {
5828 SHELL_VAR *sv;
5829
5830 sv = find_variable (name);
5831 if (sv == 0)
5832 reset_completer_word_break_chars ();
5833 }
5834
5835 /* What to do just after one of the TERMxxx variables has changed.
5836 If we are an interactive shell, then try to reset the terminal
5837 information in readline. */
5838 void
5839 sv_terminal (name)
5840 char *name;
5841 {
5842 if (interactive_shell && no_line_editing == 0)
5843 rl_reset_terminal (get_string_value ("TERM"));
5844 }
5845
5846 void
5847 sv_hostfile (name)
5848 char *name;
5849 {
5850 SHELL_VAR *v;
5851
5852 v = find_variable (name);
5853 if (v == 0)
5854 clear_hostname_list ();
5855 else
5856 hostname_list_initialized = 0;
5857 }
5858
5859 #if defined (STRICT_POSIX)
5860 /* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
5861 found in the initial environment) to override the terminal size reported by
5862 the kernel. */
5863 void
5864 sv_winsize (name)
5865 char *name;
5866 {
5867 SHELL_VAR *v;
5868 intmax_t xd;
5869 int d;
5870
5871 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
5872 return;
5873
5874 v = find_variable (name);
5875 if (v == 0 || var_isset (v) == 0)
5876 rl_reset_screen_size ();
5877 else
5878 {
5879 if (legal_number (value_cell (v), &xd) == 0)
5880 return;
5881 winsize_assignment = 1;
5882 d = xd; /* truncate */
5883 if (name[0] == 'L') /* LINES */
5884 rl_set_screen_size (d, -1);
5885 else /* COLUMNS */
5886 rl_set_screen_size (-1, d);
5887 winsize_assignment = 0;
5888 }
5889 }
5890 #endif /* STRICT_POSIX */
5891 #endif /* READLINE */
5892
5893 /* Update the value of HOME in the export environment so tilde expansion will
5894 work on cygwin. */
5895 #if defined (__CYGWIN__)
5896 sv_home (name)
5897 char *name;
5898 {
5899 array_needs_making = 1;
5900 maybe_make_export_env ();
5901 }
5902 #endif
5903
5904 #if defined (HISTORY)
5905 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
5906 If there is a value for this HISTSIZE (and it is numeric), then stifle
5907 the history. Otherwise, if there is NO value for this variable,
5908 unstifle the history. If name is HISTFILESIZE, and its value is
5909 numeric, truncate the history file to hold no more than that many
5910 lines. */
5911 void
5912 sv_histsize (name)
5913 char *name;
5914 {
5915 char *temp;
5916 intmax_t num;
5917 int hmax;
5918
5919 temp = get_string_value (name);
5920
5921 if (temp && *temp)
5922 {
5923 if (legal_number (temp, &num))
5924 {
5925 hmax = num;
5926 if (hmax < 0 && name[4] == 'S')
5927 unstifle_history (); /* unstifle history if HISTSIZE < 0 */
5928 else if (name[4] == 'S')
5929 {
5930 stifle_history (hmax);
5931 hmax = where_history ();
5932 if (history_lines_this_session > hmax)
5933 history_lines_this_session = hmax;
5934 }
5935 else if (hmax >= 0) /* truncate HISTFILE if HISTFILESIZE >= 0 */
5936 {
5937 history_truncate_file (get_string_value ("HISTFILE"), hmax);
5938 /* If we just shrank the history file to fewer lines than we've
5939 already read, make sure we adjust our idea of how many lines
5940 we have read from the file. */
5941 if (hmax < history_lines_in_file)
5942 history_lines_in_file = hmax;
5943 }
5944 }
5945 }
5946 else if (name[4] == 'S')
5947 unstifle_history ();
5948 }
5949
5950 /* What to do after the HISTIGNORE variable changes. */
5951 void
5952 sv_histignore (name)
5953 char *name;
5954 {
5955 setup_history_ignore (name);
5956 }
5957
5958 /* What to do after the HISTCONTROL variable changes. */
5959 void
5960 sv_history_control (name)
5961 char *name;
5962 {
5963 char *temp;
5964 char *val;
5965 int tptr;
5966
5967 history_control = 0;
5968 temp = get_string_value (name);
5969
5970 if (temp == 0 || *temp == 0)
5971 return;
5972
5973 tptr = 0;
5974 while (val = extract_colon_unit (temp, &tptr))
5975 {
5976 if (STREQ (val, "ignorespace"))
5977 history_control |= HC_IGNSPACE;
5978 else if (STREQ (val, "ignoredups"))
5979 history_control |= HC_IGNDUPS;
5980 else if (STREQ (val, "ignoreboth"))
5981 history_control |= HC_IGNBOTH;
5982 else if (STREQ (val, "erasedups"))
5983 history_control |= HC_ERASEDUPS;
5984
5985 free (val);
5986 }
5987 }
5988
5989 #if defined (BANG_HISTORY)
5990 /* Setting/unsetting of the history expansion character. */
5991 void
5992 sv_histchars (name)
5993 char *name;
5994 {
5995 char *temp;
5996
5997 temp = get_string_value (name);
5998 if (temp)
5999 {
6000 history_expansion_char = *temp;
6001 if (temp[0] && temp[1])
6002 {
6003 history_subst_char = temp[1];
6004 if (temp[2])
6005 history_comment_char = temp[2];
6006 }
6007 }
6008 else
6009 {
6010 history_expansion_char = '!';
6011 history_subst_char = '^';
6012 history_comment_char = '#';
6013 }
6014 }
6015 #endif /* BANG_HISTORY */
6016
6017 void
6018 sv_histtimefmt (name)
6019 char *name;
6020 {
6021 SHELL_VAR *v;
6022
6023 if (v = find_variable (name))
6024 {
6025 if (history_comment_char == 0)
6026 history_comment_char = '#';
6027 }
6028 history_write_timestamps = (v != 0);
6029 }
6030 #endif /* HISTORY */
6031
6032 #if defined (HAVE_TZSET)
6033 void
6034 sv_tz (name)
6035 char *name;
6036 {
6037 if (chkexport (name))
6038 tzset ();
6039 }
6040 #endif
6041
6042 /* If the variable exists, then the value of it can be the number
6043 of times we actually ignore the EOF. The default is small,
6044 (smaller than csh, anyway). */
6045 void
6046 sv_ignoreeof (name)
6047 char *name;
6048 {
6049 SHELL_VAR *tmp_var;
6050 char *temp;
6051
6052 eof_encountered = 0;
6053
6054 tmp_var = find_variable (name);
6055 ignoreeof = tmp_var && var_isset (tmp_var);
6056 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
6057 if (temp)
6058 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
6059 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
6060 }
6061
6062 void
6063 sv_optind (name)
6064 char *name;
6065 {
6066 SHELL_VAR *var;
6067 char *tt;
6068 int s;
6069
6070 var = find_variable ("OPTIND");
6071 tt = var ? get_variable_value (var) : (char *)NULL;
6072
6073 /* Assume that if var->context < variable_context and variable_context > 0
6074 then we are restoring the variables's previous state while returning
6075 from a function. */
6076 if (tt && *tt)
6077 {
6078 s = atoi (tt);
6079
6080 /* According to POSIX, setting OPTIND=1 resets the internal state
6081 of getopt (). */
6082 if (s < 0 || s == 1)
6083 s = 0;
6084 }
6085 else
6086 s = 0;
6087 getopts_reset (s);
6088 }
6089
6090 void
6091 sv_opterr (name)
6092 char *name;
6093 {
6094 char *tt;
6095
6096 tt = get_string_value ("OPTERR");
6097 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
6098 }
6099
6100 void
6101 sv_strict_posix (name)
6102 char *name;
6103 {
6104 SHELL_VAR *var;
6105
6106 var = find_variable (name);
6107 posixly_correct = var && var_isset (var);
6108 posix_initialize (posixly_correct);
6109 #if defined (READLINE)
6110 if (interactive_shell)
6111 posix_readline_initialize (posixly_correct);
6112 #endif /* READLINE */
6113 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
6114 }
6115
6116 void
6117 sv_locale (name)
6118 char *name;
6119 {
6120 char *v;
6121 int r;
6122
6123 v = get_string_value (name);
6124 if (name[0] == 'L' && name[1] == 'A') /* LANG */
6125 r = set_lang (name, v);
6126 else
6127 r = set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
6128
6129 #if 1
6130 if (r == 0 && posixly_correct)
6131 last_command_exit_value = 1;
6132 #endif
6133 }
6134
6135 #if defined (ARRAY_VARS)
6136 void
6137 set_pipestatus_array (ps, nproc)
6138 int *ps;
6139 int nproc;
6140 {
6141 SHELL_VAR *v;
6142 ARRAY *a;
6143 ARRAY_ELEMENT *ae;
6144 register int i;
6145 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
6146
6147 v = find_variable ("PIPESTATUS");
6148 if (v == 0)
6149 v = make_new_array_variable ("PIPESTATUS");
6150 if (array_p (v) == 0)
6151 return; /* Do nothing if not an array variable. */
6152 a = array_cell (v);
6153
6154 if (a == 0 || array_num_elements (a) == 0)
6155 {
6156 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
6157 {
6158 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6159 array_insert (a, i, t);
6160 }
6161 return;
6162 }
6163
6164 /* Fast case */
6165 if (array_num_elements (a) == nproc && nproc == 1)
6166 {
6167 ae = element_forw (a->head);
6168 free (element_value (ae));
6169 set_element_value (ae, itos (ps[0]));
6170 }
6171 else if (array_num_elements (a) <= nproc)
6172 {
6173 /* modify in array_num_elements members in place, then add */
6174 ae = a->head;
6175 for (i = 0; i < array_num_elements (a); i++)
6176 {
6177 ae = element_forw (ae);
6178 free (element_value (ae));
6179 set_element_value (ae, itos (ps[i]));
6180 }
6181 /* add any more */
6182 for ( ; i < nproc; i++)
6183 {
6184 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6185 array_insert (a, i, t);
6186 }
6187 }
6188 else
6189 {
6190 /* deleting elements. it's faster to rebuild the array. */
6191 array_flush (a);
6192 for (i = 0; ps[i] != -1; i++)
6193 {
6194 t = inttostr (ps[i], tbuf, sizeof (tbuf));
6195 array_insert (a, i, t);
6196 }
6197 }
6198 }
6199
6200 ARRAY *
6201 save_pipestatus_array ()
6202 {
6203 SHELL_VAR *v;
6204 ARRAY *a;
6205
6206 v = find_variable ("PIPESTATUS");
6207 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6208 return ((ARRAY *)NULL);
6209
6210 a = array_copy (array_cell (v));
6211
6212 return a;
6213 }
6214
6215 void
6216 restore_pipestatus_array (a)
6217 ARRAY *a;
6218 {
6219 SHELL_VAR *v;
6220 ARRAY *a2;
6221
6222 v = find_variable ("PIPESTATUS");
6223 /* XXX - should we still assign even if existing value is NULL? */
6224 if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
6225 return;
6226
6227 a2 = array_cell (v);
6228 var_setarray (v, a);
6229
6230 array_dispose (a2);
6231 }
6232 #endif
6233
6234 void
6235 set_pipestatus_from_exit (s)
6236 int s;
6237 {
6238 #if defined (ARRAY_VARS)
6239 static int v[2] = { 0, -1 };
6240
6241 v[0] = s;
6242 set_pipestatus_array (v, 1);
6243 #endif
6244 }
6245
6246 void
6247 sv_xtracefd (name)
6248 char *name;
6249 {
6250 SHELL_VAR *v;
6251 char *t, *e;
6252 int fd;
6253 FILE *fp;
6254
6255 v = find_variable (name);
6256 if (v == 0)
6257 {
6258 xtrace_reset ();
6259 return;
6260 }
6261
6262 t = value_cell (v);
6263 if (t == 0 || *t == 0)
6264 xtrace_reset ();
6265 else
6266 {
6267 fd = (int)strtol (t, &e, 10);
6268 if (e != t && *e == '\0' && sh_validfd (fd))
6269 {
6270 fp = fdopen (fd, "w");
6271 if (fp == 0)
6272 internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
6273 else
6274 xtrace_set (fd, fp);
6275 }
6276 else
6277 internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
6278 }
6279 }
6280
6281 #define MIN_COMPAT_LEVEL 31
6282
6283 void
6284 sv_shcompat (name)
6285 char *name;
6286 {
6287 SHELL_VAR *v;
6288 char *val;
6289 int tens, ones, compatval;
6290
6291 v = find_variable (name);
6292 if (v == 0)
6293 {
6294 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6295 set_compatibility_opts ();
6296 return;
6297 }
6298 val = value_cell (v);
6299 if (val == 0 || *val == '\0')
6300 {
6301 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6302 set_compatibility_opts ();
6303 return;
6304 }
6305 /* Handle decimal-like compatibility version specifications: 4.2 */
6306 if (ISDIGIT (val[0]) && val[1] == '.' && ISDIGIT (val[2]) && val[3] == 0)
6307 {
6308 tens = val[0] - '0';
6309 ones = val[2] - '0';
6310 compatval = tens*10 + ones;
6311 }
6312 /* Handle integer-like compatibility version specifications: 42 */
6313 else if (ISDIGIT (val[0]) && ISDIGIT (val[1]) && val[2] == 0)
6314 {
6315 tens = val[0] - '0';
6316 ones = val[1] - '0';
6317 compatval = tens*10 + ones;
6318 }
6319 else
6320 {
6321 compat_error:
6322 internal_error (_("%s: %s: compatibility value out of range"), name, val);
6323 shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
6324 set_compatibility_opts ();
6325 return;
6326 }
6327
6328 if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL)
6329 goto compat_error;
6330
6331 shell_compatibility_level = compatval;
6332 set_compatibility_opts ();
6333 }
6334
6335 #if defined (JOB_CONTROL)
6336 void
6337 sv_childmax (name)
6338 char *name;
6339 {
6340 char *tt;
6341 int s;
6342
6343 tt = get_string_value (name);
6344 s = (tt && *tt) ? atoi (tt) : 0;
6345 set_maxchild (s);
6346 }
6347 #endif