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