Patch-ID: bash32-010
[bash.git] / variables.c
blob5fd9d0e992e30ff419df63af981d1081770f732e
1 /* variables.c -- Functions for hacking shell variables. */
3 /* Copyright (C) 1987-2005 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21 #include "config.h"
23 #include "bashtypes.h"
24 #include "posixstat.h"
25 #include "posixtime.h"
27 #if defined (qnx)
28 # if defined (qnx6)
29 # include <sy/netmgr.h>
30 # else
31 # include <sys/vc.h>
32 # endif /* !qnx6 */
33 #endif /* qnx */
35 #if defined (HAVE_UNISTD_H)
36 # include <unistd.h>
37 #endif
39 #include <stdio.h>
40 #include "chartypes.h"
41 #include <pwd.h>
42 #include "bashansi.h"
43 #include "bashintl.h"
45 #include "shell.h"
46 #include "flags.h"
47 #include "execute_cmd.h"
48 #include "findcmd.h"
49 #include "mailcheck.h"
50 #include "input.h"
51 #include "hashcmd.h"
52 #include "pathexp.h"
54 #include "builtins/getopt.h"
55 #include "builtins/common.h"
57 #if defined (READLINE)
58 # include "bashline.h"
59 # include <readline/readline.h>
60 #else
61 # include <tilde/tilde.h>
62 #endif
64 #if defined (HISTORY)
65 # include "bashhist.h"
66 # include <readline/history.h>
67 #endif /* HISTORY */
69 #if defined (PROGRAMMABLE_COMPLETION)
70 # include "pcomplete.h"
71 #endif
73 #define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
75 #define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
77 extern char **environ;
79 /* Variables used here and defined in other files. */
80 extern int posixly_correct;
81 extern int line_number;
82 extern int subshell_environment, indirection_level, subshell_level;
83 extern int build_version, patch_level;
84 extern int expanding_redir;
85 extern char *dist_version, *release_status;
86 extern char *shell_name;
87 extern char *primary_prompt, *secondary_prompt;
88 extern char *current_host_name;
89 extern sh_builtin_func_t *this_shell_builtin;
90 extern SHELL_VAR *this_shell_function;
91 extern char *the_printed_command_except_trap;
92 extern char *this_command_name;
93 extern char *command_execution_string;
94 extern time_t shell_start_time;
96 #if defined (READLINE)
97 extern int no_line_editing;
98 extern int perform_hostname_completion;
99 #endif
101 /* The list of shell variables that the user has created at the global
102 scope, or that came from the environment. */
103 VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
105 /* The current list of shell variables, including function scopes */
106 VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
108 /* The list of shell functions that the user has created, or that came from
109 the environment. */
110 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
112 #if defined (DEBUGGER)
113 /* The table of shell function definitions that the user defined or that
114 came from the environment. */
115 HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
116 #endif
118 /* The current variable context. This is really a count of how deep into
119 executing functions we are. */
120 int variable_context = 0;
122 /* The set of shell assignments which are made only in the environment
123 for a single command. */
124 HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
126 /* Set to non-zero if an assignment error occurs while putting variables
127 into the temporary environment. */
128 int tempenv_assign_error;
130 /* Some funky variables which are known about specially. Here is where
131 "$*", "$1", and all the cruft is kept. */
132 char *dollar_vars[10];
133 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
135 /* The value of $$. */
136 pid_t dollar_dollar_pid;
138 /* An array which is passed to commands as their environment. It is
139 manufactured from the union of the initial environment and the
140 shell variables that are marked for export. */
141 char **export_env = (char **)NULL;
142 static int export_env_index;
143 static int export_env_size;
145 #if defined (READLINE)
146 static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
147 static int winsize_assigned; /* assigned to LINES or COLUMNS */
148 #endif
150 /* Non-zero means that we have to remake EXPORT_ENV. */
151 int array_needs_making = 1;
153 /* The number of times BASH has been executed. This is set
154 by initialize_variables (). */
155 int shell_level = 0;
157 /* Some forward declarations. */
158 static void create_variable_tables __P((void));
160 static void set_machine_vars __P((void));
161 static void set_home_var __P((void));
162 static void set_shell_var __P((void));
163 static char *get_bash_name __P((void));
164 static void initialize_shell_level __P((void));
165 static void uidset __P((void));
166 #if defined (ARRAY_VARS)
167 static void make_vers_array __P((void));
168 #endif
170 static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
171 #if defined (ARRAY_VARS)
172 static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
173 #endif
174 static SHELL_VAR *get_self __P((SHELL_VAR *));
176 #if defined (ARRAY_VARS)
177 static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
178 #endif
180 static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
181 static SHELL_VAR *get_seconds __P((SHELL_VAR *));
182 static SHELL_VAR *init_seconds_var __P((void));
184 static int brand __P((void));
185 static void sbrand __P((unsigned long)); /* set bash random number generator. */
186 static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
187 static SHELL_VAR *get_random __P((SHELL_VAR *));
189 static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
190 static SHELL_VAR *get_lineno __P((SHELL_VAR *));
192 static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
193 static SHELL_VAR *get_subshell __P((SHELL_VAR *));
195 #if defined (HISTORY)
196 static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
197 #endif
199 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
200 static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
201 static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
202 #endif
204 #if defined (ARRAY_VARS)
205 static SHELL_VAR *get_groupset __P((SHELL_VAR *));
206 #endif
208 static SHELL_VAR *get_funcname __P((SHELL_VAR *));
209 static SHELL_VAR *init_funcname_var __P((void));
211 static void initialize_dynamic_variables __P((void));
213 static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
214 static SHELL_VAR *new_shell_variable __P((const char *));
215 static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
216 static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
218 static void free_variable_hash_data __P((PTR_T));
220 static VARLIST *vlist_alloc __P((int));
221 static VARLIST *vlist_realloc __P((VARLIST *, int));
222 static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
224 static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
226 static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
228 static SHELL_VAR **vapply __P((sh_var_map_func_t *));
229 static SHELL_VAR **fapply __P((sh_var_map_func_t *));
231 static int visible_var __P((SHELL_VAR *));
232 static int visible_and_exported __P((SHELL_VAR *));
233 static int local_and_exported __P((SHELL_VAR *));
234 static int variable_in_context __P((SHELL_VAR *));
235 #if defined (ARRAY_VARS)
236 static int visible_array_vars __P((SHELL_VAR *));
237 #endif
239 static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
240 static void push_temp_var __P((PTR_T));
241 static void propagate_temp_var __P((PTR_T));
242 static void dispose_temporary_env __P((sh_free_func_t *));
244 static inline char *mk_env_string __P((const char *, const char *));
245 static char **make_env_array_from_var_list __P((SHELL_VAR **));
246 static char **make_var_export_array __P((VAR_CONTEXT *));
247 static char **make_func_export_array __P((void));
248 static void add_temp_array_to_env __P((char **, int, int));
250 static int n_shell_variables __P((void));
251 static int set_context __P((SHELL_VAR *));
253 static void push_func_var __P((PTR_T));
254 static void push_exported_var __P((PTR_T));
256 static inline int find_special_var __P((const char *));
258 static void
259 create_variable_tables ()
261 if (shell_variables == 0)
263 shell_variables = global_variables = new_var_context ((char *)NULL, 0);
264 shell_variables->scope = 0;
265 shell_variables->table = hash_create (0);
268 if (shell_functions == 0)
269 shell_functions = hash_create (0);
271 #if defined (DEBUGGER)
272 if (shell_function_defs == 0)
273 shell_function_defs = hash_create (0);
274 #endif
277 /* Initialize the shell variables from the current environment.
278 If PRIVMODE is nonzero, don't import functions from ENV or
279 parse $SHELLOPTS. */
280 void
281 initialize_shell_variables (env, privmode)
282 char **env;
283 int privmode;
285 char *name, *string, *temp_string;
286 int c, char_index, string_index, string_length;
287 SHELL_VAR *temp_var;
289 create_variable_tables ();
291 for (string_index = 0; string = env[string_index++]; )
293 char_index = 0;
294 name = string;
295 while ((c = *string++) && c != '=')
297 if (string[-1] == '=')
298 char_index = string - name - 1;
300 /* If there are weird things in the environment, like `=xxx' or a
301 string without an `=', just skip them. */
302 if (char_index == 0)
303 continue;
305 /* ASSERT(name[char_index] == '=') */
306 name[char_index] = '\0';
307 /* Now, name = env variable name, string = env variable value, and
308 char_index == strlen (name) */
310 /* If exported function, define it now. Don't import functions from
311 the environment in privileged mode. */
312 if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
314 string_length = strlen (string);
315 temp_string = (char *)xmalloc (3 + string_length + char_index);
317 strcpy (temp_string, name);
318 temp_string[char_index] = ' ';
319 strcpy (temp_string + char_index + 1, string);
321 parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
323 /* Ancient backwards compatibility. Old versions of bash exported
324 functions like name()=() {...} */
325 if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
326 name[char_index - 2] = '\0';
328 if (temp_var = find_function (name))
330 VSETATTR (temp_var, (att_exported|att_imported));
331 array_needs_making = 1;
333 else
334 report_error (_("error importing function definition for `%s'"), name);
336 /* ( */
337 if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
338 name[char_index - 2] = '('; /* ) */
340 #if defined (ARRAY_VARS)
341 # if 0
342 /* Array variables may not yet be exported. */
343 else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
345 string_length = 1;
346 temp_string = extract_array_assignment_list (string, &string_length);
347 temp_var = assign_array_from_string (name, temp_string);
348 FREE (temp_string);
349 VSETATTR (temp_var, (att_exported | att_imported));
350 array_needs_making = 1;
352 # endif
353 #endif
354 else
356 temp_var = bind_variable (name, string, 0);
357 VSETATTR (temp_var, (att_exported | att_imported));
358 array_needs_making = 1;
361 name[char_index] = '=';
362 /* temp_var can be NULL if it was an exported function with a syntax
363 error (a different bug, but it still shouldn't dump core). */
364 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
366 CACHE_IMPORTSTR (temp_var, name);
370 set_pwd ();
372 /* Set up initial value of $_ */
373 temp_var = set_if_not ("_", dollar_vars[0]);
375 /* Remember this pid. */
376 dollar_dollar_pid = getpid ();
378 /* Now make our own defaults in case the vars that we think are
379 important are missing. */
380 temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
381 #if 0
382 set_auto_export (temp_var); /* XXX */
383 #endif
385 temp_var = set_if_not ("TERM", "dumb");
386 #if 0
387 set_auto_export (temp_var); /* XXX */
388 #endif
390 #if defined (qnx)
391 /* set node id -- don't import it from the environment */
393 char node_name[22];
394 # if defined (qnx6)
395 netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
396 # else
397 qnx_nidtostr (getnid (), node_name, sizeof (node_name));
398 # endif
399 temp_var = bind_variable ("NODE", node_name, 0);
400 set_auto_export (temp_var);
402 #endif
404 /* set up the prompts. */
405 if (interactive_shell)
407 #if defined (PROMPT_STRING_DECODE)
408 set_if_not ("PS1", primary_prompt);
409 #else
410 if (current_user.uid == -1)
411 get_current_user_info ();
412 set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
413 #endif
414 set_if_not ("PS2", secondary_prompt);
416 set_if_not ("PS4", "+ ");
418 /* Don't allow IFS to be imported from the environment. */
419 temp_var = bind_variable ("IFS", " \t\n", 0);
420 setifs (temp_var);
422 /* Magic machine types. Pretty convenient. */
423 set_machine_vars ();
425 /* Default MAILCHECK for interactive shells. Defer the creation of a
426 default MAILPATH until the startup files are read, because MAIL
427 names a mail file if MAILPATH is not set, and we should provide a
428 default only if neither is set. */
429 if (interactive_shell)
431 temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
432 VSETATTR (temp_var, att_integer);
435 /* Do some things with shell level. */
436 initialize_shell_level ();
438 set_ppid ();
440 /* Initialize the `getopts' stuff. */
441 temp_var = bind_variable ("OPTIND", "1", 0);
442 VSETATTR (temp_var, att_integer);
443 getopts_reset (0);
444 bind_variable ("OPTERR", "1", 0);
445 sh_opterr = 1;
447 if (login_shell == 1 && posixly_correct == 0)
448 set_home_var ();
450 /* Get the full pathname to THIS shell, and set the BASH variable
451 to it. */
452 name = get_bash_name ();
453 temp_var = bind_variable ("BASH", name, 0);
454 free (name);
456 /* Make the exported environment variable SHELL be the user's login
457 shell. Note that the `tset' command looks at this variable
458 to determine what style of commands to output; if it ends in "csh",
459 then C-shell commands are output, else Bourne shell commands. */
460 set_shell_var ();
462 /* Make a variable called BASH_VERSION which contains the version info. */
463 bind_variable ("BASH_VERSION", shell_version_string (), 0);
464 #if defined (ARRAY_VARS)
465 make_vers_array ();
466 #endif
468 if (command_execution_string)
469 bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
471 /* Find out if we're supposed to be in Posix.2 mode via an
472 environment variable. */
473 temp_var = find_variable ("POSIXLY_CORRECT");
474 if (!temp_var)
475 temp_var = find_variable ("POSIX_PEDANTIC");
476 if (temp_var && imported_p (temp_var))
477 sv_strict_posix (temp_var->name);
479 #if defined (HISTORY)
480 /* Set history variables to defaults, and then do whatever we would
481 do if the variable had just been set. Do this only in the case
482 that we are remembering commands on the history list. */
483 if (remember_on_history)
485 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
487 set_if_not ("HISTFILE", name);
488 free (name);
490 #if 0
491 set_if_not ("HISTSIZE", "500");
492 sv_histsize ("HISTSIZE");
493 #endif
495 #endif /* HISTORY */
497 /* Seed the random number generator. */
498 sbrand (dollar_dollar_pid + shell_start_time);
500 /* Handle some "special" variables that we may have inherited from a
501 parent shell. */
502 if (interactive_shell)
504 temp_var = find_variable ("IGNOREEOF");
505 if (!temp_var)
506 temp_var = find_variable ("ignoreeof");
507 if (temp_var && imported_p (temp_var))
508 sv_ignoreeof (temp_var->name);
511 #if defined (HISTORY)
512 if (interactive_shell && remember_on_history)
514 sv_history_control ("HISTCONTROL");
515 sv_histignore ("HISTIGNORE");
517 #endif /* HISTORY */
519 #if defined (READLINE) && defined (STRICT_POSIX)
520 /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
521 -DSTRICT_POSIX */
522 if (interactive_shell && posixly_correct && no_line_editing == 0)
523 rl_prefer_env_winsize = 1;
524 #endif /* READLINE && STRICT_POSIX */
527 * 24 October 2001
529 * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
530 * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
531 * isnetconn() to avoid running the startup files more often than wanted.
532 * That will, of course, only work if the user's login shell is bash, so
533 * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
534 * in config-top.h.
536 #if 0
537 temp_var = find_variable ("SSH_CLIENT");
538 if (temp_var && imported_p (temp_var))
540 VUNSETATTR (temp_var, att_exported);
541 array_needs_making = 1;
543 temp_var = find_variable ("SSH2_CLIENT");
544 if (temp_var && imported_p (temp_var))
546 VUNSETATTR (temp_var, att_exported);
547 array_needs_making = 1;
549 #endif
551 /* Get the user's real and effective user ids. */
552 uidset ();
554 /* Initialize the dynamic variables, and seed their values. */
555 initialize_dynamic_variables ();
558 /* **************************************************************** */
559 /* */
560 /* Setting values for special shell variables */
561 /* */
562 /* **************************************************************** */
564 static void
565 set_machine_vars ()
567 SHELL_VAR *temp_var;
569 temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
570 temp_var = set_if_not ("OSTYPE", OSTYPE);
571 temp_var = set_if_not ("MACHTYPE", MACHTYPE);
573 temp_var = set_if_not ("HOSTNAME", current_host_name);
576 /* Set $HOME to the information in the password file if we didn't get
577 it from the environment. */
579 /* This function is not static so the tilde and readline libraries can
580 use it. */
581 char *
582 sh_get_home_dir ()
584 if (current_user.home_dir == 0)
585 get_current_user_info ();
586 return current_user.home_dir;
589 static void
590 set_home_var ()
592 SHELL_VAR *temp_var;
594 temp_var = find_variable ("HOME");
595 if (temp_var == 0)
596 temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
597 #if 0
598 VSETATTR (temp_var, att_exported);
599 #endif
602 /* Set $SHELL to the user's login shell if it is not already set. Call
603 get_current_user_info if we haven't already fetched the shell. */
604 static void
605 set_shell_var ()
607 SHELL_VAR *temp_var;
609 temp_var = find_variable ("SHELL");
610 if (temp_var == 0)
612 if (current_user.shell == 0)
613 get_current_user_info ();
614 temp_var = bind_variable ("SHELL", current_user.shell, 0);
616 #if 0
617 VSETATTR (temp_var, att_exported);
618 #endif
621 static char *
622 get_bash_name ()
624 char *name;
626 if ((login_shell == 1) && RELPATH(shell_name))
628 if (current_user.shell == 0)
629 get_current_user_info ();
630 name = savestring (current_user.shell);
632 else if (ABSPATH(shell_name))
633 name = savestring (shell_name);
634 else if (shell_name[0] == '.' && shell_name[1] == '/')
636 /* Fast path for common case. */
637 char *cdir;
638 int len;
640 cdir = get_string_value ("PWD");
641 if (cdir)
643 len = strlen (cdir);
644 name = (char *)xmalloc (len + strlen (shell_name) + 1);
645 strcpy (name, cdir);
646 strcpy (name + len, shell_name + 1);
648 else
649 name = savestring (shell_name);
651 else
653 char *tname;
654 int s;
656 tname = find_user_command (shell_name);
658 if (tname == 0)
660 /* Try the current directory. If there is not an executable
661 there, just punt and use the login shell. */
662 s = file_status (shell_name);
663 if (s & FS_EXECABLE)
665 tname = make_absolute (shell_name, get_string_value ("PWD"));
666 if (*shell_name == '.')
668 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
669 if (name == 0)
670 name = tname;
671 else
672 free (tname);
674 else
675 name = tname;
677 else
679 if (current_user.shell == 0)
680 get_current_user_info ();
681 name = savestring (current_user.shell);
684 else
686 name = full_pathname (tname);
687 free (tname);
691 return (name);
694 void
695 adjust_shell_level (change)
696 int change;
698 char new_level[5], *old_SHLVL;
699 intmax_t old_level;
700 SHELL_VAR *temp_var;
702 old_SHLVL = get_string_value ("SHLVL");
703 if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
704 old_level = 0;
706 shell_level = old_level + change;
707 if (shell_level < 0)
708 shell_level = 0;
709 else if (shell_level > 1000)
711 internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
712 shell_level = 1;
715 /* We don't need the full generality of itos here. */
716 if (shell_level < 10)
718 new_level[0] = shell_level + '0';
719 new_level[1] = '\0';
721 else if (shell_level < 100)
723 new_level[0] = (shell_level / 10) + '0';
724 new_level[1] = (shell_level % 10) + '0';
725 new_level[2] = '\0';
727 else if (shell_level < 1000)
729 new_level[0] = (shell_level / 100) + '0';
730 old_level = shell_level % 100;
731 new_level[1] = (old_level / 10) + '0';
732 new_level[2] = (old_level % 10) + '0';
733 new_level[3] = '\0';
736 temp_var = bind_variable ("SHLVL", new_level, 0);
737 set_auto_export (temp_var);
740 static void
741 initialize_shell_level ()
743 adjust_shell_level (1);
746 /* If we got PWD from the environment, update our idea of the current
747 working directory. In any case, make sure that PWD exists before
748 checking it. It is possible for getcwd () to fail on shell startup,
749 and in that case, PWD would be undefined. If this is an interactive
750 login shell, see if $HOME is the current working directory, and if
751 that's not the same string as $PWD, set PWD=$HOME. */
753 void
754 set_pwd ()
756 SHELL_VAR *temp_var, *home_var;
757 char *temp_string, *home_string;
759 home_var = find_variable ("HOME");
760 home_string = home_var ? value_cell (home_var) : (char *)NULL;
762 temp_var = find_variable ("PWD");
763 if (temp_var && imported_p (temp_var) &&
764 (temp_string = value_cell (temp_var)) &&
765 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
766 set_working_directory (temp_string);
767 else if (home_string && interactive_shell && login_shell &&
768 same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
770 set_working_directory (home_string);
771 temp_var = bind_variable ("PWD", home_string, 0);
772 set_auto_export (temp_var);
774 else
776 temp_string = get_working_directory ("shell-init");
777 if (temp_string)
779 temp_var = bind_variable ("PWD", temp_string, 0);
780 set_auto_export (temp_var);
781 free (temp_string);
785 /* According to the Single Unix Specification, v2, $OLDPWD is an
786 `environment variable' and therefore should be auto-exported.
787 Make a dummy invisible variable for OLDPWD, and mark it as exported. */
788 temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
789 VSETATTR (temp_var, (att_exported | att_invisible));
792 /* Make a variable $PPID, which holds the pid of the shell's parent. */
793 void
794 set_ppid ()
796 char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
797 SHELL_VAR *temp_var;
799 name = inttostr (getppid (), namebuf, sizeof(namebuf));
800 temp_var = find_variable ("PPID");
801 if (temp_var)
802 VUNSETATTR (temp_var, (att_readonly | att_exported));
803 temp_var = bind_variable ("PPID", name, 0);
804 VSETATTR (temp_var, (att_readonly | att_integer));
807 static void
808 uidset ()
810 char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
811 register SHELL_VAR *v;
813 b = inttostr (current_user.uid, buff, sizeof (buff));
814 v = find_variable ("UID");
815 if (v == 0)
817 v = bind_variable ("UID", b, 0);
818 VSETATTR (v, (att_readonly | att_integer));
821 if (current_user.euid != current_user.uid)
822 b = inttostr (current_user.euid, buff, sizeof (buff));
824 v = find_variable ("EUID");
825 if (v == 0)
827 v = bind_variable ("EUID", b, 0);
828 VSETATTR (v, (att_readonly | att_integer));
832 #if defined (ARRAY_VARS)
833 static void
834 make_vers_array ()
836 SHELL_VAR *vv;
837 ARRAY *av;
838 char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
840 unbind_variable ("BASH_VERSINFO");
842 vv = make_new_array_variable ("BASH_VERSINFO");
843 av = array_cell (vv);
844 strcpy (d, dist_version);
845 s = xstrchr (d, '.');
846 if (s)
847 *s++ = '\0';
848 array_insert (av, 0, d);
849 array_insert (av, 1, s);
850 s = inttostr (patch_level, b, sizeof (b));
851 array_insert (av, 2, s);
852 s = inttostr (build_version, b, sizeof (b));
853 array_insert (av, 3, s);
854 array_insert (av, 4, release_status);
855 array_insert (av, 5, MACHTYPE);
857 VSETATTR (vv, att_readonly);
859 #endif /* ARRAY_VARS */
861 /* Set the environment variables $LINES and $COLUMNS in response to
862 a window size change. */
863 void
864 sh_set_lines_and_columns (lines, cols)
865 int lines, cols;
867 char val[INT_STRLEN_BOUND(int) + 1], *v;
869 #if defined (READLINE)
870 /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
871 if (winsize_assignment)
872 return;
873 #endif
875 v = inttostr (lines, val, sizeof (val));
876 bind_variable ("LINES", v, 0);
878 v = inttostr (cols, val, sizeof (val));
879 bind_variable ("COLUMNS", v, 0);
882 /* **************************************************************** */
883 /* */
884 /* Printing variables and values */
885 /* */
886 /* **************************************************************** */
888 /* Print LIST (a list of shell variables) to stdout in such a way that
889 they can be read back in. */
890 void
891 print_var_list (list)
892 register SHELL_VAR **list;
894 register int i;
895 register SHELL_VAR *var;
897 for (i = 0; list && (var = list[i]); i++)
898 if (invisible_p (var) == 0)
899 print_assignment (var);
902 /* Print LIST (a list of shell functions) to stdout in such a way that
903 they can be read back in. */
904 void
905 print_func_list (list)
906 register SHELL_VAR **list;
908 register int i;
909 register SHELL_VAR *var;
911 for (i = 0; list && (var = list[i]); i++)
913 printf ("%s ", var->name);
914 print_var_function (var);
915 printf ("\n");
919 /* Print the value of a single SHELL_VAR. No newline is
920 output, but the variable is printed in such a way that
921 it can be read back in. */
922 void
923 print_assignment (var)
924 SHELL_VAR *var;
926 if (var_isset (var) == 0)
927 return;
929 if (function_p (var))
931 printf ("%s", var->name);
932 print_var_function (var);
933 printf ("\n");
935 #if defined (ARRAY_VARS)
936 else if (array_p (var))
937 print_array_assignment (var, 0);
938 #endif /* ARRAY_VARS */
939 else
941 printf ("%s=", var->name);
942 print_var_value (var, 1);
943 printf ("\n");
947 /* Print the value cell of VAR, a shell variable. Do not print
948 the name, nor leading/trailing newline. If QUOTE is non-zero,
949 and the value contains shell metacharacters, quote the value
950 in such a way that it can be read back in. */
951 void
952 print_var_value (var, quote)
953 SHELL_VAR *var;
954 int quote;
956 char *t;
958 if (var_isset (var) == 0)
959 return;
961 if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
963 t = ansic_quote (value_cell (var), 0, (int *)0);
964 printf ("%s", t);
965 free (t);
967 else if (quote && sh_contains_shell_metas (value_cell (var)))
969 t = sh_single_quote (value_cell (var));
970 printf ("%s", t);
971 free (t);
973 else
974 printf ("%s", value_cell (var));
977 /* Print the function cell of VAR, a shell variable. Do not
978 print the name, nor leading/trailing newline. */
979 void
980 print_var_function (var)
981 SHELL_VAR *var;
983 if (function_p (var) && var_isset (var))
984 printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
987 /* **************************************************************** */
988 /* */
989 /* Dynamic Variables */
990 /* */
991 /* **************************************************************** */
993 /* DYNAMIC VARIABLES
995 These are variables whose values are generated anew each time they are
996 referenced. These are implemented using a pair of function pointers
997 in the struct variable: assign_func, which is called from bind_variable
998 and, if arrays are compiled into the shell, some of the functions in
999 arrayfunc.c, and dynamic_value, which is called from find_variable.
1001 assign_func is called from bind_variable_internal, if
1002 bind_variable_internal discovers that the variable being assigned to
1003 has such a function. The function is called as
1004 SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
1005 and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
1006 is usually ENTRY (self). IND is an index for an array variable, and
1007 unused otherwise.
1009 dynamic_value is called from find_variable_internal to return a `new'
1010 value for the specified dynamic varible. If this function is NULL,
1011 the variable is treated as a `normal' shell variable. If it is not,
1012 however, then this function is called like this:
1013 tempvar = (*(var->dynamic_value)) (var);
1015 Sometimes `tempvar' will replace the value of `var'. Other times, the
1016 shell will simply use the string value. Pretty object-oriented, huh?
1018 Be warned, though: if you `unset' a special variable, it loses its
1019 special meaning, even if you subsequently set it.
1021 The special assignment code would probably have been better put in
1022 subst.c: do_assignment_internal, in the same style as
1023 stupidly_hack_special_variables, but I wanted the changes as
1024 localized as possible. */
1026 #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1027 do \
1029 v = bind_variable (var, (val), 0); \
1030 v->dynamic_value = gfunc; \
1031 v->assign_func = afunc; \
1033 while (0)
1035 #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1036 do \
1038 v = make_new_array_variable (var); \
1039 v->dynamic_value = gfunc; \
1040 v->assign_func = afunc; \
1042 while (0)
1044 static SHELL_VAR *
1045 null_assign (self, value, unused)
1046 SHELL_VAR *self;
1047 char *value;
1048 arrayind_t unused;
1050 return (self);
1053 #if defined (ARRAY_VARS)
1054 static SHELL_VAR *
1055 null_array_assign (self, value, ind)
1056 SHELL_VAR *self;
1057 char *value;
1058 arrayind_t ind;
1060 return (self);
1062 #endif
1064 /* Degenerate `dynamic_value' function; just returns what's passed without
1065 manipulation. */
1066 static SHELL_VAR *
1067 get_self (self)
1068 SHELL_VAR *self;
1070 return (self);
1073 #if defined (ARRAY_VARS)
1074 /* A generic dynamic array variable initializer. Intialize array variable
1075 NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
1076 static SHELL_VAR *
1077 init_dynamic_array_var (name, getfunc, setfunc, attrs)
1078 char *name;
1079 sh_var_value_func_t *getfunc;
1080 sh_var_assign_func_t *setfunc;
1081 int attrs;
1083 SHELL_VAR *v;
1085 v = find_variable (name);
1086 if (v)
1087 return (v);
1088 INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
1089 if (attrs)
1090 VSETATTR (v, attrs);
1091 return v;
1093 #endif
1096 /* The value of $SECONDS. This is the number of seconds since shell
1097 invocation, or, the number of seconds since the last assignment + the
1098 value of the last assignment. */
1099 static intmax_t seconds_value_assigned;
1101 static SHELL_VAR *
1102 assign_seconds (self, value, unused)
1103 SHELL_VAR *self;
1104 char *value;
1105 arrayind_t unused;
1107 if (legal_number (value, &seconds_value_assigned) == 0)
1108 seconds_value_assigned = 0;
1109 shell_start_time = NOW;
1110 return (self);
1113 static SHELL_VAR *
1114 get_seconds (var)
1115 SHELL_VAR *var;
1117 time_t time_since_start;
1118 char *p;
1120 time_since_start = NOW - shell_start_time;
1121 p = itos(seconds_value_assigned + time_since_start);
1123 FREE (value_cell (var));
1125 VSETATTR (var, att_integer);
1126 var_setvalue (var, p);
1127 return (var);
1130 static SHELL_VAR *
1131 init_seconds_var ()
1133 SHELL_VAR *v;
1135 v = find_variable ("SECONDS");
1136 if (v)
1138 if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
1139 seconds_value_assigned = 0;
1141 INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
1142 return v;
1145 /* The random number seed. You can change this by setting RANDOM. */
1146 static unsigned long rseed = 1;
1147 static int last_random_value;
1148 static int seeded_subshell = 0;
1150 /* A linear congruential random number generator based on the example
1151 one in the ANSI C standard. This one isn't very good, but a more
1152 complicated one is overkill. */
1154 /* Returns a pseudo-random number between 0 and 32767. */
1155 static int
1156 brand ()
1158 rseed = rseed * 1103515245 + 12345;
1159 return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
1162 /* Set the random number generator seed to SEED. */
1163 static void
1164 sbrand (seed)
1165 unsigned long seed;
1167 rseed = seed;
1168 last_random_value = 0;
1171 static SHELL_VAR *
1172 assign_random (self, value, unused)
1173 SHELL_VAR *self;
1174 char *value;
1175 arrayind_t unused;
1177 sbrand (strtoul (value, (char **)NULL, 10));
1178 if (subshell_environment)
1179 seeded_subshell = 1;
1180 return (self);
1184 get_random_number ()
1186 int rv;
1188 /* Reset for command and process substitution. */
1189 if (subshell_environment && seeded_subshell == 0)
1191 sbrand (rseed + getpid() + NOW);
1192 seeded_subshell = 1;
1196 rv = brand ();
1197 while (rv == last_random_value);
1198 return rv;
1201 static SHELL_VAR *
1202 get_random (var)
1203 SHELL_VAR *var;
1205 int rv;
1206 char *p;
1208 rv = get_random_number ();
1209 last_random_value = rv;
1210 p = itos (rv);
1212 FREE (value_cell (var));
1214 VSETATTR (var, att_integer);
1215 var_setvalue (var, p);
1216 return (var);
1219 static SHELL_VAR *
1220 assign_lineno (var, value, unused)
1221 SHELL_VAR *var;
1222 char *value;
1223 arrayind_t unused;
1225 intmax_t new_value;
1227 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1228 new_value = 0;
1229 line_number = new_value;
1230 return var;
1233 /* Function which returns the current line number. */
1234 static SHELL_VAR *
1235 get_lineno (var)
1236 SHELL_VAR *var;
1238 char *p;
1239 int ln;
1241 ln = executing_line_number ();
1242 p = itos (ln);
1243 FREE (value_cell (var));
1244 var_setvalue (var, p);
1245 return (var);
1248 static SHELL_VAR *
1249 assign_subshell (var, value, unused)
1250 SHELL_VAR *var;
1251 char *value;
1252 arrayind_t unused;
1254 intmax_t new_value;
1256 if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
1257 new_value = 0;
1258 subshell_level = new_value;
1259 return var;
1262 static SHELL_VAR *
1263 get_subshell (var)
1264 SHELL_VAR *var;
1266 char *p;
1268 p = itos (subshell_level);
1269 FREE (value_cell (var));
1270 var_setvalue (var, p);
1271 return (var);
1274 static SHELL_VAR *
1275 get_bash_command (var)
1276 SHELL_VAR *var;
1278 char *p;
1281 if (the_printed_command_except_trap)
1282 p = savestring (the_printed_command_except_trap);
1283 else
1285 p = (char *)xmalloc (1);
1286 p[0] = '\0';
1288 FREE (value_cell (var));
1289 var_setvalue (var, p);
1290 return (var);
1293 #if defined (HISTORY)
1294 static SHELL_VAR *
1295 get_histcmd (var)
1296 SHELL_VAR *var;
1298 char *p;
1300 p = itos (history_number ());
1301 FREE (value_cell (var));
1302 var_setvalue (var, p);
1303 return (var);
1305 #endif
1307 #if defined (READLINE)
1308 /* When this function returns, VAR->value points to malloced memory. */
1309 static SHELL_VAR *
1310 get_comp_wordbreaks (var)
1311 SHELL_VAR *var;
1313 /* If we don't have anything yet, assign a default value. */
1314 if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
1315 enable_hostname_completion (perform_hostname_completion);
1317 var_setvalue (var, rl_completer_word_break_characters);
1319 return (var);
1322 /* When this function returns, rl_completer_word_break_characters points to
1323 malloced memory. */
1324 static SHELL_VAR *
1325 assign_comp_wordbreaks (self, value, unused)
1326 SHELL_VAR *self;
1327 char *value;
1328 arrayind_t unused;
1330 if (rl_completer_word_break_characters &&
1331 rl_completer_word_break_characters != rl_basic_word_break_characters)
1332 free (rl_completer_word_break_characters);
1334 rl_completer_word_break_characters = savestring (value);
1335 return self;
1337 #endif /* READLINE */
1339 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1340 static SHELL_VAR *
1341 assign_dirstack (self, value, ind)
1342 SHELL_VAR *self;
1343 char *value;
1344 arrayind_t ind;
1346 set_dirstack_element (ind, 1, value);
1347 return self;
1350 static SHELL_VAR *
1351 get_dirstack (self)
1352 SHELL_VAR *self;
1354 ARRAY *a;
1355 WORD_LIST *l;
1357 l = get_directory_stack (0);
1358 a = array_from_word_list (l);
1359 array_dispose (array_cell (self));
1360 dispose_words (l);
1361 var_setarray (self, a);
1362 return self;
1364 #endif /* PUSHD AND POPD && ARRAY_VARS */
1366 #if defined (ARRAY_VARS)
1367 /* We don't want to initialize the group set with a call to getgroups()
1368 unless we're asked to, but we only want to do it once. */
1369 static SHELL_VAR *
1370 get_groupset (self)
1371 SHELL_VAR *self;
1373 register int i;
1374 int ng;
1375 ARRAY *a;
1376 static char **group_set = (char **)NULL;
1378 if (group_set == 0)
1380 group_set = get_group_list (&ng);
1381 a = array_cell (self);
1382 for (i = 0; i < ng; i++)
1383 array_insert (a, i, group_set[i]);
1385 return (self);
1387 #endif /* ARRAY_VARS */
1389 /* If ARRAY_VARS is not defined, this just returns the name of any
1390 currently-executing function. If we have arrays, it's a call stack. */
1391 static SHELL_VAR *
1392 get_funcname (self)
1393 SHELL_VAR *self;
1395 #if ! defined (ARRAY_VARS)
1396 char *t;
1397 if (variable_context && this_shell_function)
1399 FREE (value_cell (self));
1400 t = savestring (this_shell_function->name);
1401 var_setvalue (self, t);
1403 #endif
1404 return (self);
1407 void
1408 make_funcname_visible (on_or_off)
1409 int on_or_off;
1411 SHELL_VAR *v;
1413 v = find_variable ("FUNCNAME");
1414 if (v == 0 || v->dynamic_value == 0)
1415 return;
1417 if (on_or_off)
1418 VUNSETATTR (v, att_invisible);
1419 else
1420 VSETATTR (v, att_invisible);
1423 static SHELL_VAR *
1424 init_funcname_var ()
1426 SHELL_VAR *v;
1428 v = find_variable ("FUNCNAME");
1429 if (v)
1430 return v;
1431 #if defined (ARRAY_VARS)
1432 INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
1433 #else
1434 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1435 #endif
1436 VSETATTR (v, att_invisible|att_noassign);
1437 return v;
1440 static void
1441 initialize_dynamic_variables ()
1443 SHELL_VAR *v;
1445 v = init_seconds_var ();
1447 INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
1448 INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
1450 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1451 VSETATTR (v, att_integer);
1452 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1453 VSETATTR (v, att_integer);
1455 #if defined (HISTORY)
1456 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
1457 VSETATTR (v, att_integer);
1458 #endif
1460 #if defined (READLINE)
1461 INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
1462 #endif
1464 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1465 v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
1466 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1468 #if defined (ARRAY_VARS)
1469 v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
1471 # if defined (DEBUGGER)
1472 v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
1473 v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
1474 # endif /* DEBUGGER */
1475 v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
1476 v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
1477 #endif
1479 v = init_funcname_var ();
1482 /* **************************************************************** */
1483 /* */
1484 /* Retrieving variables and values */
1485 /* */
1486 /* **************************************************************** */
1488 /* How to get a pointer to the shell variable or function named NAME.
1489 HASHED_VARS is a pointer to the hash table containing the list
1490 of interest (either variables or functions). */
1492 static SHELL_VAR *
1493 hash_lookup (name, hashed_vars)
1494 const char *name;
1495 HASH_TABLE *hashed_vars;
1497 BUCKET_CONTENTS *bucket;
1499 bucket = hash_search (name, hashed_vars, 0);
1500 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1503 SHELL_VAR *
1504 var_lookup (name, vcontext)
1505 const char *name;
1506 VAR_CONTEXT *vcontext;
1508 VAR_CONTEXT *vc;
1509 SHELL_VAR *v;
1511 v = (SHELL_VAR *)NULL;
1512 for (vc = vcontext; vc; vc = vc->down)
1513 if (v = hash_lookup (name, vc->table))
1514 break;
1516 return v;
1519 /* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
1520 then also search the temporarily built list of exported variables.
1521 The lookup order is:
1522 temporary_env
1523 shell_variables list
1526 SHELL_VAR *
1527 find_variable_internal (name, force_tempenv)
1528 const char *name;
1529 int force_tempenv;
1531 SHELL_VAR *var;
1532 int search_tempenv;
1534 var = (SHELL_VAR *)NULL;
1536 /* If explicitly requested, first look in the temporary environment for
1537 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
1538 to get the `exported' value of $foo. This happens if we are executing
1539 a function or builtin, or if we are looking up a variable in a
1540 "subshell environment". */
1541 search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
1543 if (search_tempenv && temporary_env)
1544 var = hash_lookup (name, temporary_env);
1546 if (var == 0)
1547 var = var_lookup (name, shell_variables);
1549 if (var == 0)
1550 return ((SHELL_VAR *)NULL);
1552 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1555 /* Look up the variable entry named NAME. Returns the entry or NULL. */
1556 SHELL_VAR *
1557 find_variable (name)
1558 const char *name;
1560 return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
1563 /* Look up the function entry whose name matches STRING.
1564 Returns the entry or NULL. */
1565 SHELL_VAR *
1566 find_function (name)
1567 const char *name;
1569 return (hash_lookup (name, shell_functions));
1572 /* Find the function definition for the shell function named NAME. Returns
1573 the entry or NULL. */
1574 FUNCTION_DEF *
1575 find_function_def (name)
1576 const char *name;
1578 return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
1581 /* Return the value of VAR. VAR is assumed to have been the result of a
1582 lookup without any subscript, if arrays are compiled into the shell. */
1583 char *
1584 get_variable_value (var)
1585 SHELL_VAR *var;
1587 if (var == 0)
1588 return ((char *)NULL);
1589 #if defined (ARRAY_VARS)
1590 else if (array_p (var))
1591 return (array_reference (array_cell (var), 0));
1592 #endif
1593 else
1594 return (value_cell (var));
1597 /* Return the string value of a variable. Return NULL if the variable
1598 doesn't exist. Don't cons a new string. This is a potential memory
1599 leak if the variable is found in the temporary environment. Since
1600 functions and variables have separate name spaces, returns NULL if
1601 var_name is a shell function only. */
1602 char *
1603 get_string_value (var_name)
1604 const char *var_name;
1606 SHELL_VAR *var;
1608 var = find_variable (var_name);
1609 return ((var) ? get_variable_value (var) : (char *)NULL);
1612 /* This is present for use by the tilde and readline libraries. */
1613 char *
1614 sh_get_env_value (v)
1615 const char *v;
1617 return get_string_value (v);
1620 /* **************************************************************** */
1621 /* */
1622 /* Creating and setting variables */
1623 /* */
1624 /* **************************************************************** */
1626 /* Set NAME to VALUE if NAME has no value. */
1627 SHELL_VAR *
1628 set_if_not (name, value)
1629 char *name, *value;
1631 SHELL_VAR *v;
1633 if (shell_variables == 0)
1634 create_variable_tables ();
1636 v = find_variable (name);
1637 if (v == 0)
1638 v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
1639 return (v);
1642 /* Create a local variable referenced by NAME. */
1643 SHELL_VAR *
1644 make_local_variable (name)
1645 const char *name;
1647 SHELL_VAR *new_var, *old_var;
1648 VAR_CONTEXT *vc;
1649 int was_tmpvar;
1650 char *tmp_value;
1652 /* local foo; local foo; is a no-op. */
1653 old_var = find_variable (name);
1654 if (old_var && local_p (old_var) && old_var->context == variable_context)
1656 VUNSETATTR (old_var, att_invisible);
1657 return (old_var);
1660 was_tmpvar = old_var && tempvar_p (old_var);
1661 if (was_tmpvar)
1662 tmp_value = value_cell (old_var);
1664 for (vc = shell_variables; vc; vc = vc->down)
1665 if (vc_isfuncenv (vc) && vc->scope == variable_context)
1666 break;
1668 if (vc == 0)
1670 internal_error (_("make_local_variable: no function context at current scope"));
1671 return ((SHELL_VAR *)NULL);
1673 else if (vc->table == 0)
1674 vc->table = hash_create (TEMPENV_HASH_BUCKETS);
1676 /* Since this is called only from the local/declare/typeset code, we can
1677 call builtin_error here without worry (of course, it will also work
1678 for anything that sets this_command_name). Variables with the `noassign'
1679 attribute may not be made local. The test against old_var's context
1680 level is to disallow local copies of readonly global variables (since I
1681 believe that this could be a security hole). Readonly copies of calling
1682 function local variables are OK. */
1683 if (old_var && (noassign_p (old_var) ||
1684 (readonly_p (old_var) && old_var->context == 0)))
1686 if (readonly_p (old_var))
1687 sh_readonly (name);
1688 return ((SHELL_VAR *)NULL);
1691 if (old_var == 0)
1692 new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH, 0);
1693 else
1695 new_var = make_new_variable (name, vc->table);
1697 /* If we found this variable in one of the temporary environments,
1698 inherit its value. Watch to see if this causes problems with
1699 things like `x=4 local x'. */
1700 if (was_tmpvar)
1701 var_setvalue (new_var, savestring (tmp_value));
1703 new_var->attributes = exported_p (old_var) ? att_exported : 0;
1706 vc->flags |= VC_HASLOCAL;
1708 new_var->context = variable_context;
1709 VSETATTR (new_var, att_local);
1711 if (ifsname (name))
1712 setifs (new_var);
1714 return (new_var);
1717 #if defined (ARRAY_VARS)
1718 SHELL_VAR *
1719 make_local_array_variable (name)
1720 char *name;
1722 SHELL_VAR *var;
1723 ARRAY *array;
1725 var = make_local_variable (name);
1726 if (var == 0 || array_p (var))
1727 return var;
1729 array = array_create ();
1731 FREE (value_cell(var));
1732 var_setarray (var, array);
1733 VSETATTR (var, att_array);
1734 return var;
1736 #endif /* ARRAY_VARS */
1738 /* Create a new shell variable with name NAME. */
1739 static SHELL_VAR *
1740 new_shell_variable (name)
1741 const char *name;
1743 SHELL_VAR *entry;
1745 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1747 entry->name = savestring (name);
1748 var_setvalue (entry, (char *)NULL);
1749 CLEAR_EXPORTSTR (entry);
1751 entry->dynamic_value = (sh_var_value_func_t *)NULL;
1752 entry->assign_func = (sh_var_assign_func_t *)NULL;
1754 entry->attributes = 0;
1756 /* Always assume variables are to be made at toplevel!
1757 make_local_variable has the responsibilty of changing the
1758 variable context. */
1759 entry->context = 0;
1761 return (entry);
1764 /* Create a new shell variable with name NAME and add it to the hash table
1765 TABLE. */
1766 static SHELL_VAR *
1767 make_new_variable (name, table)
1768 const char *name;
1769 HASH_TABLE *table;
1771 SHELL_VAR *entry;
1772 BUCKET_CONTENTS *elt;
1774 entry = new_shell_variable (name);
1776 /* Make sure we have a shell_variables hash table to add to. */
1777 if (shell_variables == 0)
1778 create_variable_tables ();
1780 elt = hash_insert (savestring (name), table, HASH_NOSRCH);
1781 elt->data = (PTR_T)entry;
1783 return entry;
1786 #if defined (ARRAY_VARS)
1787 SHELL_VAR *
1788 make_new_array_variable (name)
1789 char *name;
1791 SHELL_VAR *entry;
1792 ARRAY *array;
1794 entry = make_new_variable (name, global_variables->table);
1795 array = array_create ();
1796 var_setarray (entry, array);
1797 VSETATTR (entry, att_array);
1798 return entry;
1800 #endif
1802 char *
1803 make_variable_value (var, value, flags)
1804 SHELL_VAR *var;
1805 char *value;
1806 int flags;
1808 char *retval, *oval;
1809 intmax_t lval, rval;
1810 int expok, olen;
1812 /* If this variable has had its type set to integer (via `declare -i'),
1813 then do expression evaluation on it and store the result. The
1814 functions in expr.c (evalexp()) and bind_int_variable() are responsible
1815 for turning off the integer flag if they don't want further
1816 evaluation done. */
1817 if (integer_p (var))
1819 if (flags & ASS_APPEND)
1821 oval = value_cell (var);
1822 lval = evalexp (oval, &expok); /* ksh93 seems to do this */
1823 if (expok == 0)
1824 jump_to_top_level (DISCARD);
1826 rval = evalexp (value, &expok);
1827 if (expok == 0)
1828 jump_to_top_level (DISCARD);
1829 if (flags & ASS_APPEND)
1830 rval += lval;
1831 retval = itos (rval);
1833 else if (value)
1835 if (flags & ASS_APPEND)
1837 oval = get_variable_value (var);
1838 if (oval == 0) /* paranoia */
1839 oval = "";
1840 olen = STRLEN (oval);
1841 retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
1842 strcpy (retval, oval);
1843 if (value)
1844 strcpy (retval+olen, value);
1846 else if (*value)
1847 retval = savestring (value);
1848 else
1850 retval = (char *)xmalloc (1);
1851 retval[0] = '\0';
1854 else
1855 retval = (char *)NULL;
1857 return retval;
1860 /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
1861 temporary environment (but usually is not). */
1862 static SHELL_VAR *
1863 bind_variable_internal (name, value, table, hflags, aflags)
1864 const char *name;
1865 char *value;
1866 HASH_TABLE *table;
1867 int hflags, aflags;
1869 char *newval;
1870 SHELL_VAR *entry;
1872 entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
1874 if (entry == 0)
1876 entry = make_new_variable (name, table);
1877 var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
1879 else if (entry->assign_func) /* array vars have assign functions now */
1881 INVALIDATE_EXPORTSTR (entry);
1882 newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
1883 entry = (*(entry->assign_func)) (entry, newval, -1);
1884 if (newval != value)
1885 free (newval);
1886 return (entry);
1888 else
1890 if (readonly_p (entry) || noassign_p (entry))
1892 if (readonly_p (entry))
1893 err_readonly (name);
1894 return (entry);
1897 /* Variables which are bound are visible. */
1898 VUNSETATTR (entry, att_invisible);
1900 newval = make_variable_value (entry, value, aflags); /* XXX */
1902 /* Invalidate any cached export string */
1903 INVALIDATE_EXPORTSTR (entry);
1905 #if defined (ARRAY_VARS)
1906 /* XXX -- this bears looking at again -- XXX */
1907 /* If an existing array variable x is being assigned to with x=b or
1908 `read x' or something of that nature, silently convert it to
1909 x[0]=b or `read x[0]'. */
1910 if (array_p (entry))
1912 array_insert (array_cell (entry), 0, newval);
1913 free (newval);
1915 else
1916 #endif
1918 FREE (value_cell (entry));
1919 var_setvalue (entry, newval);
1923 if (mark_modified_vars)
1924 VSETATTR (entry, att_exported);
1926 if (exported_p (entry))
1927 array_needs_making = 1;
1929 return (entry);
1932 /* Bind a variable NAME to VALUE. This conses up the name
1933 and value strings. If we have a temporary environment, we bind there
1934 first, then we bind into shell_variables. */
1936 SHELL_VAR *
1937 bind_variable (name, value, flags)
1938 const char *name;
1939 char *value;
1940 int flags;
1942 SHELL_VAR *v;
1943 VAR_CONTEXT *vc;
1945 if (shell_variables == 0)
1946 create_variable_tables ();
1948 /* If we have a temporary environment, look there first for the variable,
1949 and, if found, modify the value there before modifying it in the
1950 shell_variables table. This allows sourced scripts to modify values
1951 given to them in a temporary environment while modifying the variable
1952 value that the caller sees. */
1953 if (temporary_env)
1954 bind_tempenv_variable (name, value);
1956 /* XXX -- handle local variables here. */
1957 for (vc = shell_variables; vc; vc = vc->down)
1959 if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
1961 v = hash_lookup (name, vc->table);
1962 if (v)
1963 return (bind_variable_internal (name, value, vc->table, 0, flags));
1966 return (bind_variable_internal (name, value, global_variables->table, 0, flags));
1969 /* Make VAR, a simple shell variable, have value VALUE. Once assigned a
1970 value, variables are no longer invisible. This is a duplicate of part
1971 of the internals of bind_variable. If the variable is exported, or
1972 all modified variables should be exported, mark the variable for export
1973 and note that the export environment needs to be recreated. */
1974 SHELL_VAR *
1975 bind_variable_value (var, value, aflags)
1976 SHELL_VAR *var;
1977 char *value;
1978 int aflags;
1980 char *t;
1982 VUNSETATTR (var, att_invisible);
1984 if (var->assign_func)
1986 /* If we're appending, we need the old value, so use
1987 make_variable_value */
1988 t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
1989 (*(var->assign_func)) (var, t, -1);
1990 if (t != value && t)
1991 free (t);
1993 else
1995 t = make_variable_value (var, value, aflags);
1996 FREE (value_cell (var));
1997 var_setvalue (var, t);
2000 INVALIDATE_EXPORTSTR (var);
2002 if (mark_modified_vars)
2003 VSETATTR (var, att_exported);
2005 if (exported_p (var))
2006 array_needs_making = 1;
2008 return (var);
2011 /* Bind/create a shell variable with the name LHS to the RHS.
2012 This creates or modifies a variable such that it is an integer.
2014 This used to be in expr.c, but it is here so that all of the
2015 variable binding stuff is localized. Since we don't want any
2016 recursive evaluation from bind_variable() (possible without this code,
2017 since bind_variable() calls the evaluator for variables with the integer
2018 attribute set), we temporarily turn off the integer attribute for each
2019 variable we set here, then turn it back on after binding as necessary. */
2021 SHELL_VAR *
2022 bind_int_variable (lhs, rhs)
2023 char *lhs, *rhs;
2025 register SHELL_VAR *v;
2026 int isint, isarr;
2028 isint = isarr = 0;
2029 #if defined (ARRAY_VARS)
2030 if (valid_array_reference (lhs))
2032 isarr = 1;
2033 v = array_variable_part (lhs, (char **)0, (int *)0);
2035 else
2036 #endif
2037 v = find_variable (lhs);
2039 if (v)
2041 isint = integer_p (v);
2042 VUNSETATTR (v, att_integer);
2045 #if defined (ARRAY_VARS)
2046 if (isarr)
2047 v = assign_array_element (lhs, rhs, 0);
2048 else
2049 #endif
2050 v = bind_variable (lhs, rhs, 0);
2052 if (isint)
2053 VSETATTR (v, att_integer);
2055 return (v);
2058 SHELL_VAR *
2059 bind_var_to_int (var, val)
2060 char *var;
2061 intmax_t val;
2063 char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
2065 p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
2066 return (bind_int_variable (var, p));
2069 /* Do a function binding to a variable. You pass the name and
2070 the command to bind to. This conses the name and command. */
2071 SHELL_VAR *
2072 bind_function (name, value)
2073 const char *name;
2074 COMMAND *value;
2076 SHELL_VAR *entry;
2078 entry = find_function (name);
2079 if (entry == 0)
2081 BUCKET_CONTENTS *elt;
2083 elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
2084 entry = new_shell_variable (name);
2085 elt->data = (PTR_T)entry;
2087 else
2088 INVALIDATE_EXPORTSTR (entry);
2090 if (var_isset (entry))
2091 dispose_command (function_cell (entry));
2093 if (value)
2094 var_setfunc (entry, copy_command (value));
2095 else
2096 var_setfunc (entry, 0);
2098 VSETATTR (entry, att_function);
2100 if (mark_modified_vars)
2101 VSETATTR (entry, att_exported);
2103 VUNSETATTR (entry, att_invisible); /* Just to be sure */
2105 if (exported_p (entry))
2106 array_needs_making = 1;
2108 #if defined (PROGRAMMABLE_COMPLETION)
2109 set_itemlist_dirty (&it_functions);
2110 #endif
2112 return (entry);
2115 /* Bind a function definition, which includes source file and line number
2116 information in addition to the command, into the FUNCTION_DEF hash table.*/
2117 void
2118 bind_function_def (name, value)
2119 const char *name;
2120 FUNCTION_DEF *value;
2122 FUNCTION_DEF *entry;
2123 BUCKET_CONTENTS *elt;
2124 COMMAND *cmd;
2126 entry = find_function_def (name);
2127 if (entry)
2129 dispose_function_def_contents (entry);
2130 entry = copy_function_def_contents (value, entry);
2132 else
2134 cmd = value->command;
2135 value->command = 0;
2136 entry = copy_function_def (value);
2137 value->command = cmd;
2139 elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
2140 elt->data = (PTR_T *)entry;
2144 /* Add STRING, which is of the form foo=bar, to the temporary environment
2145 HASH_TABLE (temporary_env). The functions in execute_cmd.c are
2146 responsible for moving the main temporary env to one of the other
2147 temporary environments. The expansion code in subst.c calls this. */
2149 assign_in_env (word)
2150 WORD_DESC *word;
2152 int offset;
2153 char *name, *temp, *value;
2154 SHELL_VAR *var;
2155 const char *string;
2157 string = word->word;
2159 offset = assignment (string, 0);
2160 name = savestring (string);
2161 value = (char *)NULL;
2163 if (name[offset] == '=')
2165 name[offset] = 0;
2167 /* ignore the `+' when assigning temporary environment */
2168 if (name[offset - 1] == '+')
2169 name[offset - 1] = '\0';
2171 var = find_variable (name);
2172 if (var && (readonly_p (var) || noassign_p (var)))
2174 if (readonly_p (var))
2175 err_readonly (name);
2176 free (name);
2177 return (0);
2180 temp = name + offset + 1;
2181 #if 0
2182 temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
2183 value = expand_string_unsplit_to_string (temp, 0);
2184 free (temp);
2185 #else
2186 value = expand_assignment_string_to_string (temp, 0);
2187 #endif
2190 if (temporary_env == 0)
2191 temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
2193 var = hash_lookup (name, temporary_env);
2194 if (var == 0)
2195 var = make_new_variable (name, temporary_env);
2196 else
2197 FREE (value_cell (var));
2199 if (value == 0)
2201 value = (char *)xmalloc (1); /* like do_assignment_internal */
2202 value[0] = '\0';
2205 var_setvalue (var, value);
2206 var->attributes |= (att_exported|att_tempvar);
2207 var->context = variable_context; /* XXX */
2209 INVALIDATE_EXPORTSTR (var);
2210 var->exportstr = mk_env_string (name, value);
2212 array_needs_making = 1;
2214 if (ifsname (name))
2215 setifs (var);
2217 if (echo_command_at_execute)
2218 /* The Korn shell prints the `+ ' in front of assignment statements,
2219 so we do too. */
2220 xtrace_print_assignment (name, value, 0, 1);
2222 free (name);
2223 return 1;
2226 /* **************************************************************** */
2227 /* */
2228 /* Copying variables */
2229 /* */
2230 /* **************************************************************** */
2232 #ifdef INCLUDE_UNUSED
2233 /* Copy VAR to a new data structure and return that structure. */
2234 SHELL_VAR *
2235 copy_variable (var)
2236 SHELL_VAR *var;
2238 SHELL_VAR *copy = (SHELL_VAR *)NULL;
2240 if (var)
2242 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2244 copy->attributes = var->attributes;
2245 copy->name = savestring (var->name);
2247 if (function_p (var))
2248 var_setfunc (copy, copy_command (function_cell (var)));
2249 #if defined (ARRAY_VARS)
2250 else if (array_p (var))
2251 var_setarray (copy, dup_array (array_cell (var)));
2252 #endif
2253 else if (value_cell (var))
2254 var_setvalue (copy, savestring (value_cell (var)));
2255 else
2256 var_setvalue (copy, (char *)NULL);
2258 copy->dynamic_value = var->dynamic_value;
2259 copy->assign_func = var->assign_func;
2261 copy->exportstr = COPY_EXPORTSTR (var);
2263 copy->context = var->context;
2265 return (copy);
2267 #endif
2269 /* **************************************************************** */
2270 /* */
2271 /* Deleting and unsetting variables */
2272 /* */
2273 /* **************************************************************** */
2275 /* Dispose of the information attached to VAR. */
2276 void
2277 dispose_variable (var)
2278 SHELL_VAR *var;
2280 if (var == 0)
2281 return;
2283 if (function_p (var))
2284 dispose_command (function_cell (var));
2285 #if defined (ARRAY_VARS)
2286 else if (array_p (var))
2287 array_dispose (array_cell (var));
2288 #endif
2289 else
2290 FREE (value_cell (var));
2292 FREE_EXPORTSTR (var);
2294 free (var->name);
2296 if (exported_p (var))
2297 array_needs_making = 1;
2299 free (var);
2302 /* Unset the shell variable referenced by NAME. */
2304 unbind_variable (name)
2305 const char *name;
2307 return makunbound (name, shell_variables);
2310 /* Unset the shell function named NAME. */
2312 unbind_func (name)
2313 const char *name;
2315 BUCKET_CONTENTS *elt;
2316 SHELL_VAR *func;
2318 elt = hash_remove (name, shell_functions, 0);
2320 if (elt == 0)
2321 return -1;
2323 #if defined (PROGRAMMABLE_COMPLETION)
2324 set_itemlist_dirty (&it_functions);
2325 #endif
2327 func = (SHELL_VAR *)elt->data;
2328 if (func)
2330 if (exported_p (func))
2331 array_needs_making++;
2332 dispose_variable (func);
2335 free (elt->key);
2336 free (elt);
2338 return 0;
2342 unbind_function_def (name)
2343 const char *name;
2345 BUCKET_CONTENTS *elt;
2346 FUNCTION_DEF *funcdef;
2348 elt = hash_remove (name, shell_function_defs, 0);
2350 if (elt == 0)
2351 return -1;
2353 funcdef = (FUNCTION_DEF *)elt->data;
2354 if (funcdef)
2355 dispose_function_def (funcdef);
2357 free (elt->key);
2358 free (elt);
2360 return 0;
2363 /* Make the variable associated with NAME go away. HASH_LIST is the
2364 hash table from which this variable should be deleted (either
2365 shell_variables or shell_functions).
2366 Returns non-zero if the variable couldn't be found. */
2368 makunbound (name, vc)
2369 const char *name;
2370 VAR_CONTEXT *vc;
2372 BUCKET_CONTENTS *elt, *new_elt;
2373 SHELL_VAR *old_var;
2374 VAR_CONTEXT *v;
2375 char *t;
2377 for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
2378 if (elt = hash_remove (name, v->table, 0))
2379 break;
2381 if (elt == 0)
2382 return (-1);
2384 old_var = (SHELL_VAR *)elt->data;
2386 if (old_var && exported_p (old_var))
2387 array_needs_making++;
2389 /* If we're unsetting a local variable and we're still executing inside
2390 the function, just mark the variable as invisible. The function
2391 eventually called by pop_var_context() will clean it up later. This
2392 must be done so that if the variable is subsequently assigned a new
2393 value inside the function, the `local' attribute is still present.
2394 We also need to add it back into the correct hash table. */
2395 if (old_var && local_p (old_var) && variable_context == old_var->context)
2397 #if defined (ARRAY_VARS)
2398 if (array_p (old_var))
2399 array_dispose (array_cell (old_var));
2400 else
2401 #endif
2402 FREE (value_cell (old_var));
2403 /* Reset the attributes. Preserve the export attribute if the variable
2404 came from a temporary environment. Make sure it stays local, and
2405 make it invisible. */
2406 old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
2407 VSETATTR (old_var, att_local);
2408 VSETATTR (old_var, att_invisible);
2409 var_setvalue (old_var, (char *)NULL);
2410 INVALIDATE_EXPORTSTR (old_var);
2412 new_elt = hash_insert (savestring (old_var->name), v->table, 0);
2413 new_elt->data = (PTR_T)old_var;
2414 stupidly_hack_special_variables (old_var->name);
2416 free (elt->key);
2417 free (elt);
2418 return (0);
2421 /* Have to save a copy of name here, because it might refer to
2422 old_var->name. If so, stupidly_hack_special_variables will
2423 reference freed memory. */
2424 t = savestring (name);
2426 free (elt->key);
2427 free (elt);
2429 dispose_variable (old_var);
2430 stupidly_hack_special_variables (t);
2431 free (t);
2433 return (0);
2436 /* Get rid of all of the variables in the current context. */
2437 void
2438 kill_all_local_variables ()
2440 VAR_CONTEXT *vc;
2442 for (vc = shell_variables; vc; vc = vc->down)
2443 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2444 break;
2445 if (vc == 0)
2446 return; /* XXX */
2448 if (vc->table && vc_haslocals (vc))
2450 delete_all_variables (vc->table);
2451 hash_dispose (vc->table);
2453 vc->table = (HASH_TABLE *)NULL;
2456 static void
2457 free_variable_hash_data (data)
2458 PTR_T data;
2460 SHELL_VAR *var;
2462 var = (SHELL_VAR *)data;
2463 dispose_variable (var);
2466 /* Delete the entire contents of the hash table. */
2467 void
2468 delete_all_variables (hashed_vars)
2469 HASH_TABLE *hashed_vars;
2471 hash_flush (hashed_vars, free_variable_hash_data);
2474 /* **************************************************************** */
2475 /* */
2476 /* Setting variable attributes */
2477 /* */
2478 /* **************************************************************** */
2480 #define FIND_OR_MAKE_VARIABLE(name, entry) \
2481 do \
2483 entry = find_variable (name); \
2484 if (!entry) \
2486 entry = bind_variable (name, "", 0); \
2487 if (!no_invisible_vars) entry->attributes |= att_invisible; \
2490 while (0)
2492 /* Make the variable associated with NAME be readonly.
2493 If NAME does not exist yet, create it. */
2494 void
2495 set_var_read_only (name)
2496 char *name;
2498 SHELL_VAR *entry;
2500 FIND_OR_MAKE_VARIABLE (name, entry);
2501 VSETATTR (entry, att_readonly);
2504 #ifdef INCLUDE_UNUSED
2505 /* Make the function associated with NAME be readonly.
2506 If NAME does not exist, we just punt, like auto_export code below. */
2507 void
2508 set_func_read_only (name)
2509 const char *name;
2511 SHELL_VAR *entry;
2513 entry = find_function (name);
2514 if (entry)
2515 VSETATTR (entry, att_readonly);
2518 /* Make the variable associated with NAME be auto-exported.
2519 If NAME does not exist yet, create it. */
2520 void
2521 set_var_auto_export (name)
2522 char *name;
2524 SHELL_VAR *entry;
2526 FIND_OR_MAKE_VARIABLE (name, entry);
2527 set_auto_export (entry);
2530 /* Make the function associated with NAME be auto-exported. */
2531 void
2532 set_func_auto_export (name)
2533 const char *name;
2535 SHELL_VAR *entry;
2537 entry = find_function (name);
2538 if (entry)
2539 set_auto_export (entry);
2541 #endif
2543 /* **************************************************************** */
2544 /* */
2545 /* Creating lists of variables */
2546 /* */
2547 /* **************************************************************** */
2549 static VARLIST *
2550 vlist_alloc (nentries)
2551 int nentries;
2553 VARLIST *vlist;
2555 vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
2556 vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
2557 vlist->list_size = nentries;
2558 vlist->list_len = 0;
2559 vlist->list[0] = (SHELL_VAR *)NULL;
2561 return vlist;
2564 static VARLIST *
2565 vlist_realloc (vlist, n)
2566 VARLIST *vlist;
2567 int n;
2569 if (vlist == 0)
2570 return (vlist = vlist_alloc (n));
2571 if (n > vlist->list_size)
2573 vlist->list_size = n;
2574 vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
2576 return vlist;
2579 static void
2580 vlist_add (vlist, var, flags)
2581 VARLIST *vlist;
2582 SHELL_VAR *var;
2583 int flags;
2585 register int i;
2587 for (i = 0; i < vlist->list_len; i++)
2588 if (STREQ (var->name, vlist->list[i]->name))
2589 break;
2590 if (i < vlist->list_len)
2591 return;
2593 if (i >= vlist->list_size)
2594 vlist = vlist_realloc (vlist, vlist->list_size + 16);
2596 vlist->list[vlist->list_len++] = var;
2597 vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
2600 /* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
2601 variables for which FUNCTION returns a non-zero value. A NULL value
2602 for FUNCTION means to use all variables. */
2603 SHELL_VAR **
2604 map_over (function, vc)
2605 sh_var_map_func_t *function;
2606 VAR_CONTEXT *vc;
2608 VAR_CONTEXT *v;
2609 VARLIST *vlist;
2610 SHELL_VAR **ret;
2611 int nentries;
2613 for (nentries = 0, v = vc; v; v = v->down)
2614 nentries += HASH_ENTRIES (v->table);
2616 if (nentries == 0)
2617 return (SHELL_VAR **)NULL;
2619 vlist = vlist_alloc (nentries);
2621 for (v = vc; v; v = v->down)
2622 flatten (v->table, function, vlist, 0);
2624 ret = vlist->list;
2625 free (vlist);
2626 return ret;
2629 SHELL_VAR **
2630 map_over_funcs (function)
2631 sh_var_map_func_t *function;
2633 VARLIST *vlist;
2634 SHELL_VAR **ret;
2636 if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
2637 return ((SHELL_VAR **)NULL);
2639 vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
2641 flatten (shell_functions, function, vlist, 0);
2643 ret = vlist->list;
2644 free (vlist);
2645 return ret;
2648 /* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
2649 elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
2650 for future use. Only unique names are added to VLIST. If FUNC is
2651 NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
2652 NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
2653 and FUNC are both NULL, nothing happens. */
2654 static void
2655 flatten (var_hash_table, func, vlist, flags)
2656 HASH_TABLE *var_hash_table;
2657 sh_var_map_func_t *func;
2658 VARLIST *vlist;
2659 int flags;
2661 register int i;
2662 register BUCKET_CONTENTS *tlist;
2663 int r;
2664 SHELL_VAR *var;
2666 if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
2667 return;
2669 for (i = 0; i < var_hash_table->nbuckets; i++)
2671 for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
2673 var = (SHELL_VAR *)tlist->data;
2675 r = func ? (*func) (var) : 1;
2676 if (r && vlist)
2677 vlist_add (vlist, var, flags);
2682 void
2683 sort_variables (array)
2684 SHELL_VAR **array;
2686 qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
2689 static int
2690 qsort_var_comp (var1, var2)
2691 SHELL_VAR **var1, **var2;
2693 int result;
2695 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
2696 result = strcmp ((*var1)->name, (*var2)->name);
2698 return (result);
2701 /* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
2702 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
2703 static SHELL_VAR **
2704 vapply (func)
2705 sh_var_map_func_t *func;
2707 SHELL_VAR **list;
2709 list = map_over (func, shell_variables);
2710 if (list /* && posixly_correct */)
2711 sort_variables (list);
2712 return (list);
2715 /* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
2716 which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
2717 static SHELL_VAR **
2718 fapply (func)
2719 sh_var_map_func_t *func;
2721 SHELL_VAR **list;
2723 list = map_over_funcs (func);
2724 if (list /* && posixly_correct */)
2725 sort_variables (list);
2726 return (list);
2729 /* Create a NULL terminated array of all the shell variables. */
2730 SHELL_VAR **
2731 all_shell_variables ()
2733 return (vapply ((sh_var_map_func_t *)NULL));
2736 /* Create a NULL terminated array of all the shell functions. */
2737 SHELL_VAR **
2738 all_shell_functions ()
2740 return (fapply ((sh_var_map_func_t *)NULL));
2743 static int
2744 visible_var (var)
2745 SHELL_VAR *var;
2747 return (invisible_p (var) == 0);
2750 SHELL_VAR **
2751 all_visible_functions ()
2753 return (fapply (visible_var));
2756 SHELL_VAR **
2757 all_visible_variables ()
2759 return (vapply (visible_var));
2762 /* Return non-zero if the variable VAR is visible and exported. Array
2763 variables cannot be exported. */
2764 static int
2765 visible_and_exported (var)
2766 SHELL_VAR *var;
2768 return (invisible_p (var) == 0 && exported_p (var));
2771 /* Return non-zero if VAR is a local variable in the current context and
2772 is exported. */
2773 static int
2774 local_and_exported (var)
2775 SHELL_VAR *var;
2777 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
2780 SHELL_VAR **
2781 all_exported_variables ()
2783 return (vapply (visible_and_exported));
2786 SHELL_VAR **
2787 local_exported_variables ()
2789 return (vapply (local_and_exported));
2792 static int
2793 variable_in_context (var)
2794 SHELL_VAR *var;
2796 return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
2799 SHELL_VAR **
2800 all_local_variables ()
2802 VARLIST *vlist;
2803 SHELL_VAR **ret;
2804 VAR_CONTEXT *vc;
2806 vc = shell_variables;
2807 for (vc = shell_variables; vc; vc = vc->down)
2808 if (vc_isfuncenv (vc) && vc->scope == variable_context)
2809 break;
2811 if (vc == 0)
2813 internal_error (_("all_local_variables: no function context at current scope"));
2814 return (SHELL_VAR **)NULL;
2816 if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
2817 return (SHELL_VAR **)NULL;
2819 vlist = vlist_alloc (HASH_ENTRIES (vc->table));
2821 flatten (vc->table, variable_in_context, vlist, 0);
2823 ret = vlist->list;
2824 free (vlist);
2825 if (ret)
2826 sort_variables (ret);
2827 return ret;
2830 #if defined (ARRAY_VARS)
2831 /* Return non-zero if the variable VAR is visible and an array. */
2832 static int
2833 visible_array_vars (var)
2834 SHELL_VAR *var;
2836 return (invisible_p (var) == 0 && array_p (var));
2839 SHELL_VAR **
2840 all_array_variables ()
2842 return (vapply (visible_array_vars));
2844 #endif /* ARRAY_VARS */
2846 char **
2847 all_variables_matching_prefix (prefix)
2848 const char *prefix;
2850 SHELL_VAR **varlist;
2851 char **rlist;
2852 int vind, rind, plen;
2854 plen = STRLEN (prefix);
2855 varlist = all_visible_variables ();
2856 for (vind = 0; varlist && varlist[vind]; vind++)
2858 if (varlist == 0 || vind == 0)
2859 return ((char **)NULL);
2860 rlist = strvec_create (vind + 1);
2861 for (vind = rind = 0; varlist[vind]; vind++)
2863 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
2864 rlist[rind++] = savestring (varlist[vind]->name);
2866 rlist[rind] = (char *)0;
2867 free (varlist);
2869 return rlist;
2872 /* **************************************************************** */
2873 /* */
2874 /* Managing temporary variable scopes */
2875 /* */
2876 /* **************************************************************** */
2878 /* Make variable NAME have VALUE in the temporary environment. */
2879 static SHELL_VAR *
2880 bind_tempenv_variable (name, value)
2881 const char *name;
2882 char *value;
2884 SHELL_VAR *var;
2886 var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
2888 if (var)
2890 FREE (value_cell (var));
2891 var_setvalue (var, savestring (value));
2892 INVALIDATE_EXPORTSTR (var);
2895 return (var);
2898 /* Find a variable in the temporary environment that is named NAME.
2899 Return the SHELL_VAR *, or NULL if not found. */
2900 SHELL_VAR *
2901 find_tempenv_variable (name)
2902 const char *name;
2904 return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
2907 /* Push the variable described by (SHELL_VAR *)DATA down to the next
2908 variable context from the temporary environment. */
2909 static void
2910 push_temp_var (data)
2911 PTR_T data;
2913 SHELL_VAR *var, *v;
2914 HASH_TABLE *binding_table;
2916 var = (SHELL_VAR *)data;
2918 binding_table = shell_variables->table;
2919 if (binding_table == 0)
2921 if (shell_variables == global_variables)
2922 /* shouldn't happen */
2923 binding_table = shell_variables->table = global_variables->table = hash_create (0);
2924 else
2925 binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
2928 v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
2930 /* XXX - should we set the context here? It shouldn't matter because of how
2931 assign_in_env works, but might want to check. */
2932 if (binding_table == global_variables->table) /* XXX */
2933 var->attributes &= ~(att_tempvar|att_propagate);
2934 else
2936 var->attributes |= att_propagate;
2937 if (binding_table == shell_variables->table)
2938 shell_variables->flags |= VC_HASTMPVAR;
2940 v->attributes |= var->attributes;
2942 dispose_variable (var);
2945 static void
2946 propagate_temp_var (data)
2947 PTR_T data;
2949 SHELL_VAR *var;
2951 var = (SHELL_VAR *)data;
2952 if (tempvar_p (var) && (var->attributes & att_propagate))
2953 push_temp_var (data);
2954 else
2955 dispose_variable (var);
2958 /* Free the storage used in the hash table for temporary
2959 environment variables. PUSHF is a function to be called
2960 to free each hash table entry. It takes care of pushing variables
2961 to previous scopes if appropriate. */
2962 static void
2963 dispose_temporary_env (pushf)
2964 sh_free_func_t *pushf;
2966 hash_flush (temporary_env, pushf);
2967 hash_dispose (temporary_env);
2968 temporary_env = (HASH_TABLE *)NULL;
2970 array_needs_making = 1;
2972 sv_ifs ("IFS"); /* XXX here for now */
2975 void
2976 dispose_used_env_vars ()
2978 if (temporary_env)
2980 dispose_temporary_env (propagate_temp_var);
2981 maybe_make_export_env ();
2985 /* Take all of the shell variables in the temporary environment HASH_TABLE
2986 and make shell variables from them at the current variable context. */
2987 void
2988 merge_temporary_env ()
2990 if (temporary_env)
2991 dispose_temporary_env (push_temp_var);
2994 /* **************************************************************** */
2995 /* */
2996 /* Creating and manipulating the environment */
2997 /* */
2998 /* **************************************************************** */
3000 static inline char *
3001 mk_env_string (name, value)
3002 const char *name, *value;
3004 int name_len, value_len;
3005 char *p;
3007 name_len = strlen (name);
3008 value_len = STRLEN (value);
3009 p = (char *)xmalloc (2 + name_len + value_len);
3010 strcpy (p, name);
3011 p[name_len] = '=';
3012 if (value && *value)
3013 strcpy (p + name_len + 1, value);
3014 else
3015 p[name_len + 1] = '\0';
3016 return (p);
3019 #ifdef DEBUG
3020 /* Debugging */
3021 static int
3022 valid_exportstr (v)
3023 SHELL_VAR *v;
3025 char *s;
3027 s = v->exportstr;
3028 if (legal_variable_starter ((unsigned char)*s) == 0)
3030 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3031 return (0);
3033 for (s = v->exportstr + 1; s && *s; s++)
3035 if (*s == '=')
3036 break;
3037 if (legal_variable_char ((unsigned char)*s) == 0)
3039 internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
3040 return (0);
3043 if (*s != '=')
3045 internal_error (_("no `=' in exportstr for %s"), v->name);
3046 return (0);
3048 return (1);
3050 #endif
3052 static char **
3053 make_env_array_from_var_list (vars)
3054 SHELL_VAR **vars;
3056 register int i, list_index;
3057 register SHELL_VAR *var;
3058 char **list, *value;
3060 list = strvec_create ((1 + strvec_len ((char **)vars)));
3062 #define USE_EXPORTSTR (value == var->exportstr)
3064 for (i = 0, list_index = 0; var = vars[i]; i++)
3066 #if defined (__CYGWIN__)
3067 /* We don't use the exportstr stuff on Cygwin at all. */
3068 INVALIDATE_EXPORTSTR (var);
3069 #endif
3070 if (var->exportstr)
3071 value = var->exportstr;
3072 else if (function_p (var))
3073 value = named_function_string ((char *)NULL, function_cell (var), 0);
3074 #if defined (ARRAY_VARS)
3075 else if (array_p (var))
3076 # if 0
3077 value = array_to_assignment_string (array_cell (var));
3078 # else
3079 continue; /* XXX array vars cannot yet be exported */
3080 # endif
3081 #endif
3082 else
3083 value = value_cell (var);
3085 if (value)
3087 /* Gee, I'd like to get away with not using savestring() if we're
3088 using the cached exportstr... */
3089 list[list_index] = USE_EXPORTSTR ? savestring (value)
3090 : mk_env_string (var->name, value);
3092 if (USE_EXPORTSTR == 0)
3093 SAVE_EXPORTSTR (var, list[list_index]);
3095 list_index++;
3096 #undef USE_EXPORTSTR
3098 #if 0 /* not yet */
3099 #if defined (ARRAY_VARS)
3100 if (array_p (var))
3101 free (value);
3102 #endif
3103 #endif
3107 list[list_index] = (char *)NULL;
3108 return (list);
3111 /* Make an array of assignment statements from the hash table
3112 HASHED_VARS which contains SHELL_VARs. Only visible, exported
3113 variables are eligible. */
3114 static char **
3115 make_var_export_array (vcxt)
3116 VAR_CONTEXT *vcxt;
3118 char **list;
3119 SHELL_VAR **vars;
3121 vars = map_over (visible_and_exported, vcxt);
3123 if (vars == 0)
3124 return (char **)NULL;
3126 list = make_env_array_from_var_list (vars);
3128 free (vars);
3129 return (list);
3132 static char **
3133 make_func_export_array ()
3135 char **list;
3136 SHELL_VAR **vars;
3138 vars = map_over_funcs (visible_and_exported);
3139 if (vars == 0)
3140 return (char **)NULL;
3142 list = make_env_array_from_var_list (vars);
3144 free (vars);
3145 return (list);
3148 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
3149 #define add_to_export_env(envstr,do_alloc) \
3150 do \
3152 if (export_env_index >= (export_env_size - 1)) \
3154 export_env_size += 16; \
3155 export_env = strvec_resize (export_env, export_env_size); \
3156 environ = export_env; \
3158 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
3159 export_env[export_env_index] = (char *)NULL; \
3160 } while (0)
3162 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
3163 array with the same left-hand side. Return the new EXPORT_ENV. */
3164 char **
3165 add_or_supercede_exported_var (assign, do_alloc)
3166 char *assign;
3167 int do_alloc;
3169 register int i;
3170 int equal_offset;
3172 equal_offset = assignment (assign, 0);
3173 if (equal_offset == 0)
3174 return (export_env);
3176 /* If this is a function, then only supersede the function definition.
3177 We do this by including the `=() {' in the comparison, like
3178 initialize_shell_variables does. */
3179 if (assign[equal_offset + 1] == '(' &&
3180 strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
3181 equal_offset += 4;
3183 for (i = 0; i < export_env_index; i++)
3185 if (STREQN (assign, export_env[i], equal_offset + 1))
3187 free (export_env[i]);
3188 export_env[i] = do_alloc ? savestring (assign) : assign;
3189 return (export_env);
3192 add_to_export_env (assign, do_alloc);
3193 return (export_env);
3196 static void
3197 add_temp_array_to_env (temp_array, do_alloc, do_supercede)
3198 char **temp_array;
3199 int do_alloc, do_supercede;
3201 register int i;
3203 if (temp_array == 0)
3204 return;
3206 for (i = 0; temp_array[i]; i++)
3208 if (do_supercede)
3209 export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
3210 else
3211 add_to_export_env (temp_array[i], do_alloc);
3214 free (temp_array);
3217 /* Make the environment array for the command about to be executed, if the
3218 array needs making. Otherwise, do nothing. If a shell action could
3219 change the array that commands receive for their environment, then the
3220 code should `array_needs_making++'.
3222 The order to add to the array is:
3223 temporary_env
3224 list of var contexts whose head is shell_variables
3225 shell_functions
3227 This is the shell variable lookup order. We add only new variable
3228 names at each step, which allows local variables and variables in
3229 the temporary environments to shadow variables in the global (or
3230 any previous) scope.
3233 static int
3234 n_shell_variables ()
3236 VAR_CONTEXT *vc;
3237 int n;
3239 for (n = 0, vc = shell_variables; vc; vc = vc->down)
3240 n += HASH_ENTRIES (vc->table);
3241 return n;
3244 void
3245 maybe_make_export_env ()
3247 register char **temp_array;
3248 int new_size;
3249 VAR_CONTEXT *tcxt;
3251 if (array_needs_making)
3253 if (export_env)
3254 strvec_flush (export_env);
3256 /* Make a guess based on how many shell variables and functions we
3257 have. Since there will always be array variables, and array
3258 variables are not (yet) exported, this will always be big enough
3259 for the exported variables and functions. */
3260 new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
3261 HASH_ENTRIES (temporary_env);
3262 if (new_size > export_env_size)
3264 export_env_size = new_size;
3265 export_env = strvec_resize (export_env, export_env_size);
3266 environ = export_env;
3268 export_env[export_env_index = 0] = (char *)NULL;
3270 /* Make a dummy variable context from the temporary_env, stick it on
3271 the front of shell_variables, call make_var_export_array on the
3272 whole thing to flatten it, and convert the list of SHELL_VAR *s
3273 to the form needed by the environment. */
3274 if (temporary_env)
3276 tcxt = new_var_context ((char *)NULL, 0);
3277 tcxt->table = temporary_env;
3278 tcxt->down = shell_variables;
3280 else
3281 tcxt = shell_variables;
3283 temp_array = make_var_export_array (tcxt);
3284 if (temp_array)
3285 add_temp_array_to_env (temp_array, 0, 0);
3287 if (tcxt != shell_variables)
3288 free (tcxt);
3290 #if defined (RESTRICTED_SHELL)
3291 /* Restricted shells may not export shell functions. */
3292 temp_array = restricted ? (char **)0 : make_func_export_array ();
3293 #else
3294 temp_array = make_func_export_array ();
3295 #endif
3296 if (temp_array)
3297 add_temp_array_to_env (temp_array, 0, 0);
3299 array_needs_making = 0;
3303 /* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
3304 we will need to remake the exported environment every time we
3305 change directories. `_' is always put into the environment for
3306 every external command, so without special treatment it will always
3307 cause the environment to be remade.
3309 If there is no other reason to make the exported environment, we can
3310 just update the variables in place and mark the exported environment
3311 as no longer needing a remake. */
3312 void
3313 update_export_env_inplace (env_prefix, preflen, value)
3314 char *env_prefix;
3315 int preflen;
3316 char *value;
3318 char *evar;
3320 evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
3321 strcpy (evar, env_prefix);
3322 if (value)
3323 strcpy (evar + preflen, value);
3324 export_env = add_or_supercede_exported_var (evar, 0);
3327 /* We always put _ in the environment as the name of this command. */
3328 void
3329 put_command_name_into_env (command_name)
3330 char *command_name;
3332 update_export_env_inplace ("_=", 2, command_name);
3335 #if 0 /* UNUSED -- it caused too many problems */
3336 void
3337 put_gnu_argv_flags_into_env (pid, flags_string)
3338 intmax_t pid;
3339 char *flags_string;
3341 char *dummy, *pbuf;
3342 int l, fl;
3344 pbuf = itos (pid);
3345 l = strlen (pbuf);
3347 fl = strlen (flags_string);
3349 dummy = (char *)xmalloc (l + fl + 30);
3350 dummy[0] = '_';
3351 strcpy (dummy + 1, pbuf);
3352 strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
3353 dummy[l + 27] = '=';
3354 strcpy (dummy + l + 28, flags_string);
3356 free (pbuf);
3358 export_env = add_or_supercede_exported_var (dummy, 0);
3360 #endif
3362 /* **************************************************************** */
3363 /* */
3364 /* Managing variable contexts */
3365 /* */
3366 /* **************************************************************** */
3368 /* Allocate and return a new variable context with NAME and FLAGS.
3369 NAME can be NULL. */
3371 VAR_CONTEXT *
3372 new_var_context (name, flags)
3373 char *name;
3374 int flags;
3376 VAR_CONTEXT *vc;
3378 vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
3379 vc->name = name ? savestring (name) : (char *)NULL;
3380 vc->scope = variable_context;
3381 vc->flags = flags;
3383 vc->up = vc->down = (VAR_CONTEXT *)NULL;
3384 vc->table = (HASH_TABLE *)NULL;
3386 return vc;
3389 /* Free a variable context and its data, including the hash table. Dispose
3390 all of the variables. */
3391 void
3392 dispose_var_context (vc)
3393 VAR_CONTEXT *vc;
3395 FREE (vc->name);
3397 if (vc->table)
3399 delete_all_variables (vc->table);
3400 hash_dispose (vc->table);
3403 free (vc);
3406 /* Set VAR's scope level to the current variable context. */
3407 static int
3408 set_context (var)
3409 SHELL_VAR *var;
3411 return (var->context = variable_context);
3414 /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
3415 temporary variables, and push it onto shell_variables. This is
3416 for shell functions. */
3417 VAR_CONTEXT *
3418 push_var_context (name, flags, tempvars)
3419 char *name;
3420 int flags;
3421 HASH_TABLE *tempvars;
3423 VAR_CONTEXT *vc;
3425 vc = new_var_context (name, flags);
3426 vc->table = tempvars;
3427 if (tempvars)
3429 /* Have to do this because the temp environment was created before
3430 variable_context was incremented. */
3431 flatten (tempvars, set_context, (VARLIST *)NULL, 0);
3432 vc->flags |= VC_HASTMPVAR;
3434 vc->down = shell_variables;
3435 shell_variables->up = vc;
3437 return (shell_variables = vc);
3440 static void
3441 push_func_var (data)
3442 PTR_T data;
3444 SHELL_VAR *var, *v;
3446 var = (SHELL_VAR *)data;
3448 if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
3450 /* XXX - should we set v->context here? */
3451 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3452 if (shell_variables == global_variables)
3453 var->attributes &= ~(att_tempvar|att_propagate);
3454 else
3455 shell_variables->flags |= VC_HASTMPVAR;
3456 v->attributes |= var->attributes;
3459 dispose_variable (var);
3462 /* Pop the top context off of VCXT and dispose of it, returning the rest of
3463 the stack. */
3464 void
3465 pop_var_context ()
3467 VAR_CONTEXT *ret, *vcxt;
3469 vcxt = shell_variables;
3470 if (vc_isfuncenv (vcxt) == 0)
3472 internal_error (_("pop_var_context: head of shell_variables not a function context"));
3473 return;
3476 if (ret = vcxt->down)
3478 ret->up = (VAR_CONTEXT *)NULL;
3479 shell_variables = ret;
3480 if (vcxt->table)
3481 hash_flush (vcxt->table, push_func_var);
3482 dispose_var_context (vcxt);
3484 else
3485 internal_error (_("pop_var_context: no global_variables context"));
3488 /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
3489 all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
3490 void
3491 delete_all_contexts (vcxt)
3492 VAR_CONTEXT *vcxt;
3494 VAR_CONTEXT *v, *t;
3496 for (v = vcxt; v != global_variables; v = t)
3498 t = v->down;
3499 dispose_var_context (v);
3502 delete_all_variables (global_variables->table);
3503 shell_variables = global_variables;
3506 /* **************************************************************** */
3507 /* */
3508 /* Pushing and Popping temporary variable scopes */
3509 /* */
3510 /* **************************************************************** */
3512 VAR_CONTEXT *
3513 push_scope (flags, tmpvars)
3514 int flags;
3515 HASH_TABLE *tmpvars;
3517 return (push_var_context ((char *)NULL, flags, tmpvars));
3520 static void
3521 push_exported_var (data)
3522 PTR_T data;
3524 SHELL_VAR *var, *v;
3526 var = (SHELL_VAR *)data;
3528 /* If a temp var had its export attribute set, or it's marked to be
3529 propagated, bind it in the previous scope before disposing it. */
3530 /* XXX - This isn't exactly right, because all tempenv variables have the
3531 export attribute set. */
3532 #if 0
3533 if (exported_p (var) || (var->attributes & att_propagate))
3534 #else
3535 if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
3536 #endif
3538 var->attributes &= ~att_tempvar; /* XXX */
3539 v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
3540 if (shell_variables == global_variables)
3541 var->attributes &= ~att_propagate;
3542 v->attributes |= var->attributes;
3545 dispose_variable (var);
3548 void
3549 pop_scope (is_special)
3550 int is_special;
3552 VAR_CONTEXT *vcxt, *ret;
3554 vcxt = shell_variables;
3555 if (vc_istempscope (vcxt) == 0)
3557 internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
3558 return;
3561 ret = vcxt->down;
3562 if (ret)
3563 ret->up = (VAR_CONTEXT *)NULL;
3565 shell_variables = ret;
3567 /* Now we can take care of merging variables in VCXT into set of scopes
3568 whose head is RET (shell_variables). */
3569 FREE (vcxt->name);
3570 if (vcxt->table)
3572 if (is_special)
3573 hash_flush (vcxt->table, push_func_var);
3574 else
3575 hash_flush (vcxt->table, push_exported_var);
3576 hash_dispose (vcxt->table);
3578 free (vcxt);
3580 sv_ifs ("IFS"); /* XXX here for now */
3583 /* **************************************************************** */
3584 /* */
3585 /* Pushing and Popping function contexts */
3586 /* */
3587 /* **************************************************************** */
3589 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
3590 static int dollar_arg_stack_slots;
3591 static int dollar_arg_stack_index;
3593 /* XXX - we might want to consider pushing and popping the `getopts' state
3594 when we modify the positional parameters. */
3595 void
3596 push_context (name, is_subshell, tempvars)
3597 char *name; /* function name */
3598 int is_subshell;
3599 HASH_TABLE *tempvars;
3601 if (is_subshell == 0)
3602 push_dollar_vars ();
3603 variable_context++;
3604 push_var_context (name, VC_FUNCENV, tempvars);
3607 /* Only called when subshell == 0, so we don't need to check, and can
3608 unconditionally pop the dollar vars off the stack. */
3609 void
3610 pop_context ()
3612 pop_dollar_vars ();
3613 variable_context--;
3614 pop_var_context ();
3616 sv_ifs ("IFS"); /* XXX here for now */
3619 /* Save the existing positional parameters on a stack. */
3620 void
3621 push_dollar_vars ()
3623 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
3625 dollar_arg_stack = (WORD_LIST **)
3626 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
3627 * sizeof (WORD_LIST **));
3629 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
3630 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3633 /* Restore the positional parameters from our stack. */
3634 void
3635 pop_dollar_vars ()
3637 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3638 return;
3640 remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
3641 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3642 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3643 set_dollar_vars_unchanged ();
3646 void
3647 dispose_saved_dollar_vars ()
3649 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
3650 return;
3652 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
3653 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
3656 /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
3658 void
3659 push_args (list)
3660 WORD_LIST *list;
3662 #if defined (ARRAY_VARS) && defined (DEBUGGER)
3663 SHELL_VAR *bash_argv_v, *bash_argc_v;
3664 ARRAY *bash_argv_a, *bash_argc_a;
3665 WORD_LIST *l;
3666 arrayind_t i;
3667 char *t;
3669 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3670 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3672 for (l = list, i = 0; l; l = l->next, i++)
3673 array_push (bash_argv_a, l->word->word);
3675 t = itos (i);
3676 array_push (bash_argc_a, t);
3677 free (t);
3678 #endif /* ARRAY_VARS && DEBUGGER */
3681 /* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
3682 array and use that value as the count of elements to remove from
3683 BASH_ARGV. */
3684 void
3685 pop_args ()
3687 #if defined (ARRAY_VARS) && defined (DEBUGGER)
3688 SHELL_VAR *bash_argv_v, *bash_argc_v;
3689 ARRAY *bash_argv_a, *bash_argc_a;
3690 ARRAY_ELEMENT *ce;
3691 intmax_t i;
3693 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
3694 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
3696 ce = array_shift (bash_argc_a, 1, 0);
3697 if (ce == 0 || legal_number (element_value (ce), &i) == 0)
3698 i = 0;
3700 for ( ; i > 0; i--)
3701 array_pop (bash_argv_a);
3702 array_dispose_element (ce);
3703 #endif /* ARRAY_VARS && DEBUGGER */
3706 /*************************************************
3708 * Functions to manage special variables *
3710 *************************************************/
3712 /* Extern declarations for variables this code has to manage. */
3713 extern int eof_encountered, eof_encountered_limit, ignoreeof;
3715 #if defined (READLINE)
3716 extern int hostname_list_initialized;
3717 #endif
3719 /* An alist of name.function for each special variable. Most of the
3720 functions don't do much, and in fact, this would be faster with a
3721 switch statement, but by the end of this file, I am sick of switch
3722 statements. */
3724 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
3726 /* This table will be sorted with qsort() the first time it's accessed. */
3727 struct name_and_function {
3728 char *name;
3729 sh_sv_func_t *function;
3732 static struct name_and_function special_vars[] = {
3733 #if defined (READLINE)
3734 # if defined (STRICT_POSIX)
3735 { "COLUMNS", sv_winsize },
3736 # endif
3737 { "COMP_WORDBREAKS", sv_comp_wordbreaks },
3738 #endif
3740 { "GLOBIGNORE", sv_globignore },
3742 #if defined (HISTORY)
3743 { "HISTCONTROL", sv_history_control },
3744 { "HISTFILESIZE", sv_histsize },
3745 { "HISTIGNORE", sv_histignore },
3746 { "HISTSIZE", sv_histsize },
3747 { "HISTTIMEFORMAT", sv_histtimefmt },
3748 #endif
3750 #if defined (__CYGWIN__)
3751 { "HOME", sv_home },
3752 #endif
3754 #if defined (READLINE)
3755 { "HOSTFILE", sv_hostfile },
3756 #endif
3758 { "IFS", sv_ifs },
3759 { "IGNOREEOF", sv_ignoreeof },
3761 { "LANG", sv_locale },
3762 { "LC_ALL", sv_locale },
3763 { "LC_COLLATE", sv_locale },
3764 { "LC_CTYPE", sv_locale },
3765 { "LC_MESSAGES", sv_locale },
3766 { "LC_NUMERIC", sv_locale },
3767 { "LC_TIME", sv_locale },
3769 #if defined (READLINE) && defined (STRICT_POSIX)
3770 { "LINES", sv_winsize },
3771 #endif
3773 { "MAIL", sv_mail },
3774 { "MAILCHECK", sv_mail },
3775 { "MAILPATH", sv_mail },
3777 { "OPTERR", sv_opterr },
3778 { "OPTIND", sv_optind },
3780 { "PATH", sv_path },
3781 { "POSIXLY_CORRECT", sv_strict_posix },
3783 #if defined (READLINE)
3784 { "TERM", sv_terminal },
3785 { "TERMCAP", sv_terminal },
3786 { "TERMINFO", sv_terminal },
3787 #endif /* READLINE */
3789 { "TEXTDOMAIN", sv_locale },
3790 { "TEXTDOMAINDIR", sv_locale },
3792 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3793 { "TZ", sv_tz },
3794 #endif
3796 #if defined (HISTORY) && defined (BANG_HISTORY)
3797 { "histchars", sv_histchars },
3798 #endif /* HISTORY && BANG_HISTORY */
3800 { "ignoreeof", sv_ignoreeof },
3802 { (char *)0, (sh_sv_func_t *)0 }
3805 #define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
3807 static int
3808 sv_compare (sv1, sv2)
3809 struct name_and_function *sv1, *sv2;
3811 int r;
3813 if ((r = sv1->name[0] - sv2->name[0]) == 0)
3814 r = strcmp (sv1->name, sv2->name);
3815 return r;
3818 static inline int
3819 find_special_var (name)
3820 const char *name;
3822 register int i, r;
3824 for (i = 0; special_vars[i].name; i++)
3826 r = special_vars[i].name[0] - name[0];
3827 if (r == 0)
3828 r = strcmp (special_vars[i].name, name);
3829 if (r == 0)
3830 return i;
3831 else if (r > 0)
3832 /* Can't match any of rest of elements in sorted list. Take this out
3833 if it causes problems in certain environments. */
3834 break;
3836 return -1;
3839 /* The variable in NAME has just had its state changed. Check to see if it
3840 is one of the special ones where something special happens. */
3841 void
3842 stupidly_hack_special_variables (name)
3843 char *name;
3845 static int sv_sorted = 0;
3846 int i;
3848 if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
3850 qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
3851 (QSFUNC *)sv_compare);
3852 sv_sorted = 1;
3855 i = find_special_var (name);
3856 if (i != -1)
3857 (*(special_vars[i].function)) (name);
3860 void
3861 sv_ifs (name)
3862 char *name;
3864 SHELL_VAR *v;
3866 v = find_variable ("IFS");
3867 setifs (v);
3870 /* What to do just after the PATH variable has changed. */
3871 void
3872 sv_path (name)
3873 char *name;
3875 /* hash -r */
3876 phash_flush ();
3879 /* What to do just after one of the MAILxxxx variables has changed. NAME
3880 is the name of the variable. This is called with NAME set to one of
3881 MAIL, MAILCHECK, or MAILPATH. */
3882 void
3883 sv_mail (name)
3884 char *name;
3886 /* If the time interval for checking the files has changed, then
3887 reset the mail timer. Otherwise, one of the pathname vars
3888 to the users mailbox has changed, so rebuild the array of
3889 filenames. */
3890 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
3891 reset_mail_timer ();
3892 else
3894 free_mail_files ();
3895 remember_mail_dates ();
3899 /* What to do when GLOBIGNORE changes. */
3900 void
3901 sv_globignore (name)
3902 char *name;
3904 setup_glob_ignore (name);
3907 #if defined (READLINE)
3908 void
3909 sv_comp_wordbreaks (name)
3910 char *name;
3912 SHELL_VAR *sv;
3914 sv = find_variable (name);
3915 if (sv == 0)
3916 rl_completer_word_break_characters = (char *)NULL;
3919 /* What to do just after one of the TERMxxx variables has changed.
3920 If we are an interactive shell, then try to reset the terminal
3921 information in readline. */
3922 void
3923 sv_terminal (name)
3924 char *name;
3926 if (interactive_shell && no_line_editing == 0)
3927 rl_reset_terminal (get_string_value ("TERM"));
3930 void
3931 sv_hostfile (name)
3932 char *name;
3934 SHELL_VAR *v;
3936 v = find_variable (name);
3937 if (v == 0)
3938 clear_hostname_list ();
3939 else
3940 hostname_list_initialized = 0;
3943 #if defined (STRICT_POSIX)
3944 /* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
3945 found in the initial environment) to override the terminal size reported by
3946 the kernel. */
3947 void
3948 sv_winsize (name)
3949 char *name;
3951 SHELL_VAR *v;
3952 intmax_t xd;
3953 int d;
3955 if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
3956 return;
3958 v = find_variable (name);
3959 if (v == 0 || var_isnull (v))
3960 rl_reset_screen_size ();
3961 else
3963 if (legal_number (value_cell (v), &xd) == 0)
3964 return;
3965 winsize_assignment = winsize_assigned = 1;
3966 d = xd; /* truncate */
3967 if (name[0] == 'L') /* LINES */
3968 rl_set_screen_size (d, -1);
3969 else /* COLUMNS */
3970 rl_set_screen_size (-1, d);
3971 winsize_assignment = 0;
3974 #endif /* STRICT_POSIX */
3975 #endif /* READLINE */
3977 /* Update the value of HOME in the export environment so tilde expansion will
3978 work on cygwin. */
3979 #if defined (__CYGWIN__)
3980 sv_home (name)
3981 char *name;
3983 array_needs_making = 1;
3984 maybe_make_export_env ();
3986 #endif
3988 #if defined (HISTORY)
3989 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
3990 If there is a value for this HISTSIZE (and it is numeric), then stifle
3991 the history. Otherwise, if there is NO value for this variable,
3992 unstifle the history. If name is HISTFILESIZE, and its value is
3993 numeric, truncate the history file to hold no more than that many
3994 lines. */
3995 void
3996 sv_histsize (name)
3997 char *name;
3999 char *temp;
4000 intmax_t num;
4001 int hmax;
4003 temp = get_string_value (name);
4005 if (temp && *temp)
4007 if (legal_number (temp, &num))
4009 hmax = num;
4010 if (name[4] == 'S')
4012 stifle_history (hmax);
4013 hmax = where_history ();
4014 if (history_lines_this_session > hmax)
4015 history_lines_this_session = hmax;
4017 else
4019 history_truncate_file (get_string_value ("HISTFILE"), hmax);
4020 if (hmax <= history_lines_in_file)
4021 history_lines_in_file = hmax;
4025 else if (name[4] == 'S')
4026 unstifle_history ();
4029 /* What to do after the HISTIGNORE variable changes. */
4030 void
4031 sv_histignore (name)
4032 char *name;
4034 setup_history_ignore (name);
4037 /* What to do after the HISTCONTROL variable changes. */
4038 void
4039 sv_history_control (name)
4040 char *name;
4042 char *temp;
4043 char *val;
4044 int tptr;
4046 history_control = 0;
4047 temp = get_string_value (name);
4049 if (temp == 0 || *temp == 0)
4050 return;
4052 tptr = 0;
4053 while (val = extract_colon_unit (temp, &tptr))
4055 if (STREQ (val, "ignorespace"))
4056 history_control |= HC_IGNSPACE;
4057 else if (STREQ (val, "ignoredups"))
4058 history_control |= HC_IGNDUPS;
4059 else if (STREQ (val, "ignoreboth"))
4060 history_control |= HC_IGNBOTH;
4061 else if (STREQ (val, "erasedups"))
4062 history_control |= HC_ERASEDUPS;
4064 free (val);
4068 #if defined (BANG_HISTORY)
4069 /* Setting/unsetting of the history expansion character. */
4070 void
4071 sv_histchars (name)
4072 char *name;
4074 char *temp;
4076 temp = get_string_value (name);
4077 if (temp)
4079 history_expansion_char = *temp;
4080 if (temp[0] && temp[1])
4082 history_subst_char = temp[1];
4083 if (temp[2])
4084 history_comment_char = temp[2];
4087 else
4089 history_expansion_char = '!';
4090 history_subst_char = '^';
4091 history_comment_char = '#';
4094 #endif /* BANG_HISTORY */
4096 void
4097 sv_histtimefmt (name)
4098 char *name;
4100 SHELL_VAR *v;
4102 v = find_variable (name);
4103 history_write_timestamps = (v != 0);
4105 #endif /* HISTORY */
4107 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
4108 void
4109 sv_tz (name)
4110 char *name;
4112 tzset ();
4114 #endif
4116 /* If the variable exists, then the value of it can be the number
4117 of times we actually ignore the EOF. The default is small,
4118 (smaller than csh, anyway). */
4119 void
4120 sv_ignoreeof (name)
4121 char *name;
4123 SHELL_VAR *tmp_var;
4124 char *temp;
4126 eof_encountered = 0;
4128 tmp_var = find_variable (name);
4129 ignoreeof = tmp_var != 0;
4130 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4131 if (temp)
4132 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
4133 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
4136 void
4137 sv_optind (name)
4138 char *name;
4140 char *tt;
4141 int s;
4143 tt = get_string_value ("OPTIND");
4144 if (tt && *tt)
4146 s = atoi (tt);
4148 /* According to POSIX, setting OPTIND=1 resets the internal state
4149 of getopt (). */
4150 if (s < 0 || s == 1)
4151 s = 0;
4153 else
4154 s = 0;
4155 getopts_reset (s);
4158 void
4159 sv_opterr (name)
4160 char *name;
4162 char *tt;
4164 tt = get_string_value ("OPTERR");
4165 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
4168 void
4169 sv_strict_posix (name)
4170 char *name;
4172 SET_INT_VAR (name, posixly_correct);
4173 posix_initialize (posixly_correct);
4174 #if defined (READLINE)
4175 if (interactive_shell)
4176 posix_readline_initialize (posixly_correct);
4177 #endif /* READLINE */
4178 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
4181 void
4182 sv_locale (name)
4183 char *name;
4185 char *v;
4187 v = get_string_value (name);
4188 if (name[0] == 'L' && name[1] == 'A') /* LANG */
4189 set_lang (name, v);
4190 else
4191 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
4194 #if defined (ARRAY_VARS)
4195 void
4196 set_pipestatus_array (ps, nproc)
4197 int *ps;
4198 int nproc;
4200 SHELL_VAR *v;
4201 ARRAY *a;
4202 ARRAY_ELEMENT *ae;
4203 register int i;
4204 char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
4206 v = find_variable ("PIPESTATUS");
4207 if (v == 0)
4208 v = make_new_array_variable ("PIPESTATUS");
4209 if (array_p (v) == 0)
4210 return; /* Do nothing if not an array variable. */
4211 a = array_cell (v);
4213 if (a == 0 || array_num_elements (a) == 0)
4215 for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
4217 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4218 array_insert (a, i, t);
4220 return;
4223 /* Fast case */
4224 if (array_num_elements (a) == nproc && nproc == 1)
4226 ae = element_forw (a->head);
4227 free (element_value (ae));
4228 ae->value = itos (ps[0]);
4230 else if (array_num_elements (a) <= nproc)
4232 /* modify in array_num_elements members in place, then add */
4233 ae = a->head;
4234 for (i = 0; i < array_num_elements (a); i++)
4236 ae = element_forw (ae);
4237 free (element_value (ae));
4238 ae->value = itos (ps[i]);
4240 /* add any more */
4241 for ( ; i < nproc; i++)
4243 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4244 array_insert (a, i, t);
4247 else
4249 /* deleting elements. it's faster to rebuild the array. */
4250 array_flush (a);
4251 for (i = 0; ps[i] != -1; i++)
4253 t = inttostr (ps[i], tbuf, sizeof (tbuf));
4254 array_insert (a, i, t);
4258 #endif
4260 void
4261 set_pipestatus_from_exit (s)
4262 int s;
4264 #if defined (ARRAY_VARS)
4265 static int v[2] = { 0, -1 };
4267 v[0] = s;
4268 set_pipestatus_array (v, 1);
4269 #endif