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