| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* variables.c -- Functions for hacking shell variables. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "bashtypes.h"
 | 
					
						
							|  |  |  | #include "posixstat.h"
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "posixtime.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (__QNX__)
 | 
					
						
							|  |  |  | #  if defined (__QNXNTO__)
 | 
					
						
							|  |  |  | #    include <sys/netmgr.h>
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #  else
 | 
					
						
							|  |  |  | #    include <sys/vc.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #  endif /* !__QNXNTO__ */
 | 
					
						
							|  |  |  | #endif /* __QNX__ */
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "chartypes.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (HAVE_PWD_H)
 | 
					
						
							|  |  |  | #  include <pwd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "bashansi.h"
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "bashintl.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #define NEED_XTRACE_SET_DECL
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "shell.h"
 | 
					
						
							|  |  |  | #include "flags.h"
 | 
					
						
							|  |  |  | #include "execute_cmd.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #include "findcmd.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "mailcheck.h"
 | 
					
						
							|  |  |  | #include "input.h"
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "hashcmd.h"
 | 
					
						
							|  |  |  | #include "pathexp.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #include "alias.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include "jobs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "version.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #include "builtins/getopt.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "builtins/common.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include "builtins/builtext.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | #  include "bashline.h"
 | 
					
						
							|  |  |  | #  include <readline/readline.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  include <tilde/tilde.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | #  include "bashhist.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  include <readline/history.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (PROGRAMMABLE_COMPLETION)
 | 
					
						
							|  |  |  | #  include "pcomplete.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #define TEMPENV_HASH_BUCKETS	4	/* must be power of two */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ifsname(s)	((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | #define BASHFUNC_PREFIX		"BASH_FUNC_"
 | 
					
						
							|  |  |  | #define BASHFUNC_PREFLEN	10	/* == strlen(BASHFUNC_PREFIX */
 | 
					
						
							|  |  |  | #define BASHFUNC_SUFFIX		"%%"
 | 
					
						
							|  |  |  | #define BASHFUNC_SUFFLEN	2	/* == strlen(BASHFUNC_SUFFIX) */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | extern char **environ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Variables used here and defined in other files. */ | 
					
						
							|  |  |  | extern int posixly_correct; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | extern int line_number, line_number_base; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | extern int subshell_environment, indirection_level, subshell_level; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern int build_version, patch_level; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | extern int expanding_redir; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | extern int last_command_exit_value; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern char *dist_version, *release_status; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | extern char *shell_name; | 
					
						
							|  |  |  | extern char *primary_prompt, *secondary_prompt; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern char *current_host_name; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | extern sh_builtin_func_t *this_shell_builtin; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | extern SHELL_VAR *this_shell_function; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | extern char *the_printed_command_except_trap; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern char *this_command_name; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | extern char *command_execution_string; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | extern time_t shell_start_time; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | extern int assigning_in_environment; | 
					
						
							|  |  |  | extern int executing_builtin; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | extern int funcnest_max; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | extern int no_line_editing; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | extern int perform_hostname_completion; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* The list of shell variables that the user has created at the global
 | 
					
						
							|  |  |  |    scope, or that came from the environment. */ | 
					
						
							|  |  |  | VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The current list of shell variables, including function scopes */ | 
					
						
							|  |  |  | VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* The list of shell functions that the user has created, or that came from
 | 
					
						
							|  |  |  |    the environment. */ | 
					
						
							|  |  |  | HASH_TABLE *shell_functions = (HASH_TABLE *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (DEBUGGER)
 | 
					
						
							|  |  |  | /* The table of shell function definitions that the user defined or that
 | 
					
						
							|  |  |  |    came from the environment. */ | 
					
						
							|  |  |  | HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* The current variable context.  This is really a count of how deep into
 | 
					
						
							|  |  |  |    executing functions we are. */ | 
					
						
							|  |  |  | int variable_context = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* The set of shell assignments which are made only in the environment
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    for a single command. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | HASH_TABLE *temporary_env = (HASH_TABLE *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Set to non-zero if an assignment error occurs while putting variables
 | 
					
						
							|  |  |  |    into the temporary environment. */ | 
					
						
							|  |  |  | int tempenv_assign_error; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Some funky variables which are known about specially.  Here is where
 | 
					
						
							|  |  |  |    "$*", "$1", and all the cruft is kept. */ | 
					
						
							|  |  |  | char *dollar_vars[10]; | 
					
						
							|  |  |  | WORD_LIST *rest_of_args = (WORD_LIST *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The value of $$. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | pid_t dollar_dollar_pid; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Non-zero means that we have to remake EXPORT_ENV. */ | 
					
						
							|  |  |  | int array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The number of times BASH has been executed.  This is set
 | 
					
						
							|  |  |  |    by initialize_variables (). */ | 
					
						
							|  |  |  | int shell_level = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* An array which is passed to commands as their environment.  It is
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |    manufactured from the union of the initial environment and the | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    shell variables that are marked for export. */ | 
					
						
							|  |  |  | char **export_env = (char **)NULL; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | static int export_env_index; | 
					
						
							|  |  |  | static int export_env_size; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | static int winsize_assignment;		/* currently assigning to LINES or COLUMNS */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static HASH_TABLE *last_table_searched;	/* hash_lookup sets this */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Some forward declarations. */ | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | static void create_variable_tables __P((void)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static void set_machine_vars __P((void)); | 
					
						
							|  |  |  | static void set_home_var __P((void)); | 
					
						
							|  |  |  | static void set_shell_var __P((void)); | 
					
						
							|  |  |  | static char *get_bash_name __P((void)); | 
					
						
							|  |  |  | static void initialize_shell_level __P((void)); | 
					
						
							|  |  |  | static void uidset __P((void)); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static void make_vers_array __P((void)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static SHELL_VAR *get_self __P((SHELL_VAR *)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *init_dynamic_assoc_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *get_seconds __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *init_seconds_var __P((void)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int brand __P((void)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static void sbrand __P((unsigned long));		/* set bash random number generator. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static void seedrand __P((void));			/* seed generator randomly */ | 
					
						
							|  |  |  | static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *get_random __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *get_lineno __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static SHELL_VAR *get_subshell __P((SHELL_VAR *)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *get_bashpid __P((SHELL_VAR *)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | static SHELL_VAR *get_histcmd __P((SHELL_VAR *)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | static SHELL_VAR *get_comp_wordbreaks __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *assign_comp_wordbreaks __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *get_dirstack __P((SHELL_VAR *)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static SHELL_VAR *get_groupset __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR *build_hashcmd __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *get_hashcmd __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *assign_hashcmd __P((SHELL_VAR *,  char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #  if defined (ALIAS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR *build_aliasvar __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *get_aliasvar __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *assign_aliasvar __P((SHELL_VAR *,  char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR *get_funcname __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static SHELL_VAR *init_funcname_var __P((void)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void initialize_dynamic_variables __P((void)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static SHELL_VAR *new_shell_variable __P((const char *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static void dispose_variable_value __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void free_variable_hash_data __P((PTR_T)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static VARLIST *vlist_alloc __P((int)); | 
					
						
							|  |  |  | static VARLIST *vlist_realloc __P((VARLIST *, int)); | 
					
						
							|  |  |  | static void vlist_add __P((VARLIST *, SHELL_VAR *, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR **vapply __P((sh_var_map_func_t *)); | 
					
						
							|  |  |  | static SHELL_VAR **fapply __P((sh_var_map_func_t *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int visible_var __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static int visible_and_exported __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | static int export_environment_candidate __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static int local_and_exported __P((SHELL_VAR *)); | 
					
						
							|  |  |  | static int variable_in_context __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static int visible_array_vars __P((SHELL_VAR *)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static SHELL_VAR *find_nameref_at_context __P((SHELL_VAR *, VAR_CONTEXT *)); | 
					
						
							|  |  |  | static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **)); | 
					
						
							|  |  |  | static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR *bind_tempenv_variable __P((const char *, char *)); | 
					
						
							|  |  |  | static void push_temp_var __P((PTR_T)); | 
					
						
							|  |  |  | static void propagate_temp_var __P((PTR_T)); | 
					
						
							|  |  |  | static void dispose_temporary_env __P((sh_free_func_t *));      | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | static inline char *mk_env_string __P((const char *, const char *, int)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static char **make_env_array_from_var_list __P((SHELL_VAR **)); | 
					
						
							|  |  |  | static char **make_var_export_array __P((VAR_CONTEXT *)); | 
					
						
							|  |  |  | static char **make_func_export_array __P((void)); | 
					
						
							|  |  |  | static void add_temp_array_to_env __P((char **, int, int)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static int n_shell_variables __P((void)); | 
					
						
							|  |  |  | static int set_context __P((SHELL_VAR *)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void push_func_var __P((PTR_T)); | 
					
						
							|  |  |  | static void push_exported_var __P((PTR_T)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static inline int find_special_var __P((const char *)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | create_variable_tables () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   if (shell_variables == 0) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       shell_variables = global_variables = new_var_context ((char *)NULL, 0); | 
					
						
							|  |  |  |       shell_variables->scope = 0; | 
					
						
							|  |  |  |       shell_variables->table = hash_create (0); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   if (shell_functions == 0) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     shell_functions = hash_create (0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (DEBUGGER)
 | 
					
						
							|  |  |  |   if (shell_function_defs == 0) | 
					
						
							|  |  |  |     shell_function_defs = hash_create (0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Initialize the shell variables from the current environment.
 | 
					
						
							|  |  |  |    If PRIVMODE is nonzero, don't import functions from ENV or | 
					
						
							|  |  |  |    parse $SHELLOPTS. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | initialize_shell_variables (env, privmode) | 
					
						
							|  |  |  |      char **env; | 
					
						
							|  |  |  |      int privmode; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *name, *string, *temp_string; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int c, char_index, string_index, string_length, ro; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   SHELL_VAR *temp_var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   create_variable_tables (); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   for (string_index = 0; string = env[string_index++]; ) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       char_index = 0; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       name = string; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       while ((c = *string++) && c != '=') | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	; | 
					
						
							|  |  |  |       if (string[-1] == '=') | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	char_index = string - name - 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       /* If there are weird things in the environment, like `=xxx' or a
 | 
					
						
							|  |  |  | 	 string without an `=', just skip them. */ | 
					
						
							|  |  |  |       if (char_index == 0) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	continue; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* ASSERT(name[char_index] == '=') */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       name[char_index] = '\0'; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       /* Now, name = env variable name, string = env variable value, and
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	 char_index == strlen (name) */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       temp_var = (SHELL_VAR *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       /* If exported function, define it now.  Don't import functions from
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	 the environment in privileged mode. */ | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |       if (privmode == 0 && read_but_dont_execute == 0 &&  | 
					
						
							|  |  |  |           STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) && | 
					
						
							|  |  |  |           STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) && | 
					
						
							|  |  |  | 	  STREQN ("() {", string, 4)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	  size_t namelen; | 
					
						
							|  |  |  | 	  char *tname;		/* desired imported function name */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  namelen = char_index - BASHFUNC_PREFLEN - BASHFUNC_SUFFLEN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  tname = name + BASHFUNC_PREFLEN;	/* start of func name */ | 
					
						
							|  |  |  | 	  tname[namelen] = '\0';		/* now tname == func name */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	  string_length = strlen (string); | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	  temp_string = (char *)xmalloc (namelen + string_length + 2); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	  memcpy (temp_string, tname, namelen); | 
					
						
							|  |  |  | 	  temp_string[namelen] = ' '; | 
					
						
							|  |  |  | 	  memcpy (temp_string + namelen + 1, string, string_length + 1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-25 08:45:07 -04:00
										 |  |  | 	  /* Don't import function names that are invalid identifiers from the
 | 
					
						
							|  |  |  | 	     environment, though we still allow them to be defined as shell | 
					
						
							|  |  |  | 	     variables. */ | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	  if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname))) | 
					
						
							|  |  |  | 	    parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	  if (temp_var = find_function (tname)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	      VSETATTR (temp_var, (att_exported|att_imported)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      array_needs_making = 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      if (temp_var = bind_variable (name, string, 0)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  VSETATTR (temp_var, (att_exported | att_imported | att_invisible)); | 
					
						
							|  |  |  | 		  array_needs_making = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      last_command_exit_value = 1; | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 	      report_error (_("error importing function definition for `%s'"), tname); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  /* Restore original suffix */ | 
					
						
							|  |  |  | 	  tname[namelen] = BASHFUNC_SUFFIX[0]; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #  if ARRAY_EXPORT
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* Array variables may not yet be exported. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')') | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  string_length = 1; | 
					
						
							|  |  |  | 	  temp_string = extract_array_assignment_list (string, &string_length); | 
					
						
							|  |  |  | 	  temp_var = assign_array_from_string (name, temp_string); | 
					
						
							|  |  |  | 	  FREE (temp_string); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	  VSETATTR (temp_var, (att_exported | att_imported)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  array_needs_making = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #  endif /* ARRAY_EXPORT */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else if (legal_identifier (name)) | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | #else
 | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  ro = 0; | 
					
						
							|  |  |  | 	  if (posixly_correct && STREQ (name, "SHELLOPTS")) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      temp_var = find_variable ("SHELLOPTS"); | 
					
						
							|  |  |  | 	      ro = temp_var && readonly_p (temp_var); | 
					
						
							|  |  |  | 	      if (temp_var) | 
					
						
							|  |  |  | 		VUNSETATTR (temp_var, att_readonly); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  temp_var = bind_variable (name, string, 0); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	  if (temp_var) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (legal_identifier (name)) | 
					
						
							|  |  |  | 		VSETATTR (temp_var, (att_exported | att_imported)); | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		VSETATTR (temp_var, (att_exported | att_imported | att_invisible)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      if (ro) | 
					
						
							|  |  |  | 		VSETATTR (temp_var, att_readonly); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	      array_needs_making = 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       name[char_index] = '='; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       /* temp_var can be NULL if it was an exported function with a syntax
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	 error (a different bug, but it still shouldn't dump core). */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       if (temp_var && function_p (temp_var) == 0)	/* XXX not yet */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  CACHE_IMPORTSTR (temp_var, name); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   set_pwd (); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Set up initial value of $_ */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = set_if_not ("_", dollar_vars[0]); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* Remember this pid. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   dollar_dollar_pid = getpid (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Now make our own defaults in case the vars that we think are
 | 
					
						
							|  |  |  |      important are missing. */ | 
					
						
							|  |  |  |   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |   set_auto_export (temp_var);	/* XXX */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   temp_var = set_if_not ("TERM", "dumb"); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |   set_auto_export (temp_var);	/* XXX */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (__QNX__)
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   /* set node id -- don't import it from the environment */ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     char node_name[22]; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #  if defined (__QNXNTO__)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name)); | 
					
						
							|  |  |  | #  else
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     qnx_nidtostr (getnid (), node_name, sizeof (node_name)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #  endif
 | 
					
						
							|  |  |  |     temp_var = bind_variable ("NODE", node_name, 0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     set_auto_export (temp_var); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* set up the prompts. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (interactive_shell) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | #if defined (PROMPT_STRING_DECODE)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       set_if_not ("PS1", primary_prompt); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |       if (current_user.uid == -1) | 
					
						
							|  |  |  | 	get_current_user_info (); | 
					
						
							|  |  |  |       set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       set_if_not ("PS2", secondary_prompt); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   set_if_not ("PS4", "+ "); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Don't allow IFS to be imported from the environment. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("IFS", " \t\n", 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   setifs (temp_var); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Magic machine types.  Pretty convenient. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   set_machine_vars (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Default MAILCHECK for interactive shells.  Defer the creation of a
 | 
					
						
							|  |  |  |      default MAILPATH until the startup files are read, because MAIL | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      names a mail file if MAILPATH is not set, and we should provide a | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      default only if neither is set. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (interactive_shell) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60"); | 
					
						
							|  |  |  |       VSETATTR (temp_var, att_integer); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Do some things with shell level. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   initialize_shell_level (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   set_ppid (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Initialize the `getopts' stuff. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("OPTIND", "1", 0); | 
					
						
							|  |  |  |   VSETATTR (temp_var, att_integer); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   getopts_reset (0); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   bind_variable ("OPTERR", "1", 0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   sh_opterr = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   if (login_shell == 1 && posixly_correct == 0) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     set_home_var (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Get the full pathname to THIS shell, and set the BASH variable
 | 
					
						
							|  |  |  |      to it. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   name = get_bash_name (); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("BASH", name, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   free (name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Make the exported environment variable SHELL be the user's login
 | 
					
						
							|  |  |  |      shell.  Note that the `tset' command looks at this variable | 
					
						
							|  |  |  |      to determine what style of commands to output; if it ends in "csh", | 
					
						
							|  |  |  |      then C-shell commands are output, else Bourne shell commands. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   set_shell_var (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Make a variable called BASH_VERSION which contains the version info. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   bind_variable ("BASH_VERSION", shell_version_string (), 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   make_vers_array (); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   if (command_execution_string) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* Find out if we're supposed to be in Posix.2 mode via an
 | 
					
						
							|  |  |  |      environment variable. */ | 
					
						
							|  |  |  |   temp_var = find_variable ("POSIXLY_CORRECT"); | 
					
						
							|  |  |  |   if (!temp_var) | 
					
						
							|  |  |  |     temp_var = find_variable ("POSIX_PEDANTIC"); | 
					
						
							|  |  |  |   if (temp_var && imported_p (temp_var)) | 
					
						
							|  |  |  |     sv_strict_posix (temp_var->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  |   /* Set history variables to defaults, and then do whatever we would
 | 
					
						
							|  |  |  |      do if the variable had just been set.  Do this only in the case | 
					
						
							|  |  |  |      that we are remembering commands on the history list. */ | 
					
						
							|  |  |  |   if (remember_on_history) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       set_if_not ("HISTFILE", name); | 
					
						
							|  |  |  |       free (name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Seed the random number generator. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   seedrand (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Handle some "special" variables that we may have inherited from a
 | 
					
						
							|  |  |  |      parent shell. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (interactive_shell) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp_var = find_variable ("IGNOREEOF"); | 
					
						
							|  |  |  |       if (!temp_var) | 
					
						
							|  |  |  | 	temp_var = find_variable ("ignoreeof"); | 
					
						
							|  |  |  |       if (temp_var && imported_p (temp_var)) | 
					
						
							|  |  |  | 	sv_ignoreeof (temp_var->name); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  |   if (interactive_shell && remember_on_history) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       sv_history_control ("HISTCONTROL"); | 
					
						
							|  |  |  |       sv_histignore ("HISTIGNORE"); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       sv_histtimefmt ("HISTTIMEFORMAT"); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (READLINE) && defined (STRICT_POSIX)
 | 
					
						
							|  |  |  |   /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
 | 
					
						
							|  |  |  |      -DSTRICT_POSIX */ | 
					
						
							|  |  |  |   if (interactive_shell && posixly_correct && no_line_editing == 0) | 
					
						
							|  |  |  |     rl_prefer_env_winsize = 1; | 
					
						
							|  |  |  | #endif /* READLINE && STRICT_POSIX */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      /*
 | 
					
						
							|  |  |  |       * 24 October 2001 | 
					
						
							|  |  |  |       * | 
					
						
							|  |  |  |       * I'm tired of the arguing and bug reports.  Bash now leaves SSH_CLIENT | 
					
						
							|  |  |  |       * and SSH2_CLIENT alone.  I'm going to rely on the shell_level check in | 
					
						
							|  |  |  |       * isnetconn() to avoid running the startup files more often than wanted. | 
					
						
							|  |  |  |       * That will, of course, only work if the user's login shell is bash, so | 
					
						
							|  |  |  |       * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined | 
					
						
							|  |  |  |       * in config-top.h. | 
					
						
							|  |  |  |       */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   temp_var = find_variable ("SSH_CLIENT"); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (temp_var && imported_p (temp_var)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       VUNSETATTR (temp_var, att_exported); | 
					
						
							|  |  |  |       array_needs_making = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   temp_var = find_variable ("SSH2_CLIENT"); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   if (temp_var && imported_p (temp_var)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       VUNSETATTR (temp_var, att_exported); | 
					
						
							|  |  |  |       array_needs_making = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Get the user's real and effective user ids. */ | 
					
						
							|  |  |  |   uidset (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   temp_var = find_variable ("BASH_XTRACEFD"); | 
					
						
							|  |  |  |   if (temp_var && imported_p (temp_var)) | 
					
						
							|  |  |  |     sv_xtracefd (temp_var->name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* Initialize the dynamic variables, and seed their values. */ | 
					
						
							|  |  |  |   initialize_dynamic_variables (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     Setting values for special shell variables		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | set_machine_vars () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *temp_var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE); | 
					
						
							|  |  |  |   temp_var = set_if_not ("OSTYPE", OSTYPE); | 
					
						
							|  |  |  |   temp_var = set_if_not ("MACHTYPE", MACHTYPE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_var = set_if_not ("HOSTNAME", current_host_name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Set $HOME to the information in the password file if we didn't get
 | 
					
						
							|  |  |  |    it from the environment. */ | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* This function is not static so the tilde and readline libraries can
 | 
					
						
							|  |  |  |    use it. */ | 
					
						
							|  |  |  | char * | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | sh_get_home_dir () | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   if (current_user.home_dir == 0) | 
					
						
							|  |  |  |     get_current_user_info (); | 
					
						
							|  |  |  |   return current_user.home_dir; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | set_home_var () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *temp_var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_var = find_variable ("HOME"); | 
					
						
							|  |  |  |   if (temp_var == 0) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     temp_var = bind_variable ("HOME", sh_get_home_dir (), 0); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (temp_var, att_exported); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set $SHELL to the user's login shell if it is not already set.  Call
 | 
					
						
							|  |  |  |    get_current_user_info if we haven't already fetched the shell. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | set_shell_var () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *temp_var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_var = find_variable ("SHELL"); | 
					
						
							|  |  |  |   if (temp_var == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (current_user.shell == 0) | 
					
						
							|  |  |  | 	get_current_user_info (); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       temp_var = bind_variable ("SHELL", current_user.shell, 0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (temp_var, att_exported); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char * | 
					
						
							|  |  |  | get_bash_name () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if ((login_shell == 1) && RELPATH(shell_name)) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (current_user.shell == 0) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	get_current_user_info (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       name = savestring (current_user.shell); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   else if (ABSPATH(shell_name)) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     name = savestring (shell_name); | 
					
						
							|  |  |  |   else if (shell_name[0] == '.' && shell_name[1] == '/') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Fast path for common case. */ | 
					
						
							|  |  |  |       char *cdir; | 
					
						
							|  |  |  |       int len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       cdir = get_string_value ("PWD"); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (cdir) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  len = strlen (cdir); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  name = (char *)xmalloc (len + strlen (shell_name) + 1); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  strcpy (name, cdir); | 
					
						
							|  |  |  | 	  strcpy (name + len, shell_name + 1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	name = savestring (shell_name); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       char *tname; | 
					
						
							|  |  |  |       int s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       tname = find_user_command (shell_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (tname == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* Try the current directory.  If there is not an executable
 | 
					
						
							|  |  |  | 	     there, just punt and use the login shell. */ | 
					
						
							|  |  |  | 	  s = file_status (shell_name); | 
					
						
							|  |  |  | 	  if (s & FS_EXECABLE) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      tname = make_absolute (shell_name, get_string_value ("PWD")); | 
					
						
							|  |  |  | 	      if (*shell_name == '.') | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		  name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 		  if (name == 0) | 
					
						
							|  |  |  | 		    name = tname; | 
					
						
							|  |  |  | 		  else | 
					
						
							|  |  |  | 		    free (tname); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	     else | 
					
						
							|  |  |  | 		name = tname; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (current_user.shell == 0) | 
					
						
							|  |  |  | 		get_current_user_info (); | 
					
						
							|  |  |  | 	      name = savestring (current_user.shell); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  name = full_pathname (tname); | 
					
						
							|  |  |  | 	  free (tname); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | void | 
					
						
							|  |  |  | adjust_shell_level (change) | 
					
						
							|  |  |  |      int change; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char new_level[5], *old_SHLVL; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t old_level; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   SHELL_VAR *temp_var; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   old_SHLVL = get_string_value ("SHLVL"); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0) | 
					
						
							|  |  |  |     old_level = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   shell_level = old_level + change; | 
					
						
							|  |  |  |   if (shell_level < 0) | 
					
						
							|  |  |  |     shell_level = 0; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   else if (shell_level > 1000) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       shell_level = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* We don't need the full generality of itos here. */ | 
					
						
							|  |  |  |   if (shell_level < 10) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       new_level[0] = shell_level + '0'; | 
					
						
							|  |  |  |       new_level[1] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (shell_level < 100) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       new_level[0] = (shell_level / 10) + '0'; | 
					
						
							|  |  |  |       new_level[1] = (shell_level % 10) + '0'; | 
					
						
							|  |  |  |       new_level[2] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (shell_level < 1000) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       new_level[0] = (shell_level / 100) + '0'; | 
					
						
							|  |  |  |       old_level = shell_level % 100; | 
					
						
							|  |  |  |       new_level[1] = (old_level / 10) + '0'; | 
					
						
							|  |  |  |       new_level[2] = (old_level % 10) + '0'; | 
					
						
							|  |  |  |       new_level[3] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("SHLVL", new_level, 0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   set_auto_export (temp_var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | initialize_shell_level () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   adjust_shell_level (1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | /* If we got PWD from the environment, update our idea of the current
 | 
					
						
							|  |  |  |    working directory.  In any case, make sure that PWD exists before | 
					
						
							|  |  |  |    checking it.  It is possible for getcwd () to fail on shell startup, | 
					
						
							|  |  |  |    and in that case, PWD would be undefined.  If this is an interactive | 
					
						
							|  |  |  |    login shell, see if $HOME is the current working directory, and if | 
					
						
							|  |  |  |    that's not the same string as $PWD, set PWD=$HOME. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_pwd () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *temp_var, *home_var; | 
					
						
							|  |  |  |   char *temp_string, *home_string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   home_var = find_variable ("HOME"); | 
					
						
							|  |  |  |   home_string = home_var ? value_cell (home_var) : (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_var = find_variable ("PWD"); | 
					
						
							|  |  |  |   if (temp_var && imported_p (temp_var) && | 
					
						
							|  |  |  |       (temp_string = value_cell (temp_var)) && | 
					
						
							|  |  |  |       same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL)) | 
					
						
							|  |  |  |     set_working_directory (temp_string); | 
					
						
							|  |  |  |   else if (home_string && interactive_shell && login_shell && | 
					
						
							|  |  |  | 	   same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       set_working_directory (home_string); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       temp_var = bind_variable ("PWD", home_string, 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       set_auto_export (temp_var); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp_string = get_working_directory ("shell-init"); | 
					
						
							|  |  |  |       if (temp_string) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  temp_var = bind_variable ("PWD", temp_string, 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  set_auto_export (temp_var); | 
					
						
							|  |  |  | 	  free (temp_string); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* According to the Single Unix Specification, v2, $OLDPWD is an
 | 
					
						
							|  |  |  |      `environment variable' and therefore should be auto-exported. | 
					
						
							|  |  |  |      Make a dummy invisible variable for OLDPWD, and mark it as exported. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("OLDPWD", (char *)NULL, 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   VSETATTR (temp_var, (att_exported | att_invisible)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* Make a variable $PPID, which holds the pid of the shell's parent.  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_ppid () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   SHELL_VAR *temp_var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   name = inttostr (getppid (), namebuf, sizeof(namebuf)); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   temp_var = find_variable ("PPID"); | 
					
						
							|  |  |  |   if (temp_var) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     VUNSETATTR (temp_var, (att_readonly | att_exported)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   temp_var = bind_variable ("PPID", name, 0); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (temp_var, (att_readonly | att_integer)); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | uidset () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char buff[INT_STRLEN_BOUND(uid_t) + 1], *b; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   register SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   b = inttostr (current_user.uid, buff, sizeof (buff)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   v = find_variable ("UID"); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (v == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       v = bind_variable ("UID", b, 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       VSETATTR (v, (att_readonly | att_integer)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (current_user.euid != current_user.uid) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |     b = inttostr (current_user.euid, buff, sizeof (buff)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   v = find_variable ("EUID"); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   if (v == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       v = bind_variable ("EUID", b, 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       VSETATTR (v, (att_readonly | att_integer)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | make_vers_array () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *vv; | 
					
						
							|  |  |  |   ARRAY *av; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char *s, d[32], b[INT_STRLEN_BOUND(int) + 1]; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   unbind_variable ("BASH_VERSINFO"); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   vv = make_new_array_variable ("BASH_VERSINFO"); | 
					
						
							|  |  |  |   av = array_cell (vv); | 
					
						
							|  |  |  |   strcpy (d, dist_version); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   s = strchr (d, '.'); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (s) | 
					
						
							|  |  |  |     *s++ = '\0'; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   array_insert (av, 0, d); | 
					
						
							|  |  |  |   array_insert (av, 1, s); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   s = inttostr (patch_level, b, sizeof (b)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   array_insert (av, 2, s); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   s = inttostr (build_version, b, sizeof (b)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   array_insert (av, 3, s); | 
					
						
							|  |  |  |   array_insert (av, 4, release_status); | 
					
						
							|  |  |  |   array_insert (av, 5, MACHTYPE); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (vv, att_readonly); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set the environment variables $LINES and $COLUMNS in response to
 | 
					
						
							|  |  |  |    a window size change. */ | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | sh_set_lines_and_columns (lines, cols) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      int lines, cols; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char val[INT_STRLEN_BOUND(int) + 1], *v; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   /* If we are currently assigning to LINES or COLUMNS, don't do anything. */ | 
					
						
							|  |  |  |   if (winsize_assignment) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   v = inttostr (lines, val, sizeof (val)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   bind_variable ("LINES", v, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   v = inttostr (cols, val, sizeof (val)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   bind_variable ("COLUMNS", v, 0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		   Printing variables and values		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | /* Print LIST (a list of shell variables) to stdout in such a way that
 | 
					
						
							|  |  |  |    they can be read back in. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | void | 
					
						
							|  |  |  | print_var_list (list) | 
					
						
							|  |  |  |      register SHELL_VAR **list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   register SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; list && (var = list[i]); i++) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     if (invisible_p (var) == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       print_assignment (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | /* Print LIST (a list of shell functions) to stdout in such a way that
 | 
					
						
							|  |  |  |    they can be read back in. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | print_func_list (list) | 
					
						
							|  |  |  |      register SHELL_VAR **list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   register SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; list && (var = list[i]); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf ("%s ", var->name); | 
					
						
							|  |  |  |       print_var_function (var); | 
					
						
							|  |  |  |       printf ("\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Print the value of a single SHELL_VAR.  No newline is
 | 
					
						
							|  |  |  |    output, but the variable is printed in such a way that | 
					
						
							|  |  |  |    it can be read back in. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | print_assignment (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (var_isset (var) == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (function_p (var)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       printf ("%s", var->name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       print_var_function (var); | 
					
						
							|  |  |  |       printf ("\n"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else if (array_p (var)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     print_array_assignment (var, 0); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   else if (assoc_p (var)) | 
					
						
							|  |  |  |     print_assoc_assignment (var, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       printf ("%s=", var->name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       print_var_value (var, 1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       printf ("\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Print the value cell of VAR, a shell variable.  Do not print
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    the name, nor leading/trailing newline.  If QUOTE is non-zero, | 
					
						
							|  |  |  |    and the value contains shell metacharacters, quote the value | 
					
						
							|  |  |  |    in such a way that it can be read back in. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | print_var_value (var, quote) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      int quote; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (var_isset (var) == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var))) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       t = ansic_quote (value_cell (var), 0, (int *)0); | 
					
						
							|  |  |  |       printf ("%s", t); | 
					
						
							|  |  |  |       free (t); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (quote && sh_contains_shell_metas (value_cell (var))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = sh_single_quote (value_cell (var)); | 
					
						
							|  |  |  |       printf ("%s", t); | 
					
						
							|  |  |  |       free (t); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     printf ("%s", value_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Print the function cell of VAR, a shell variable.  Do not
 | 
					
						
							|  |  |  |    print the name, nor leading/trailing newline. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | print_var_function (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   char *x; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (function_p (var) && var_isset (var)) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL); | 
					
						
							|  |  |  |       printf ("%s", x); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /*								    */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /*		 	Dynamic Variables			    */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /*								    */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* DYNAMIC VARIABLES
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    These are variables whose values are generated anew each time they are | 
					
						
							|  |  |  |    referenced.  These are implemented using a pair of function pointers | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    in the struct variable: assign_func, which is called from bind_variable | 
					
						
							|  |  |  |    and, if arrays are compiled into the shell, some of the functions in | 
					
						
							|  |  |  |    arrayfunc.c, and dynamic_value, which is called from find_variable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    assign_func is called from bind_variable_internal, if | 
					
						
							|  |  |  |    bind_variable_internal discovers that the variable being assigned to | 
					
						
							|  |  |  |    has such a function.  The function is called as | 
					
						
							|  |  |  | 	SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    is usually ENTRY (self).  IND is an index for an array variable, and | 
					
						
							|  |  |  |    unused otherwise. | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    dynamic_value is called from find_variable_internal to return a `new' | 
					
						
							|  |  |  |    value for the specified dynamic varible.  If this function is NULL, | 
					
						
							|  |  |  |    the variable is treated as a `normal' shell variable.  If it is not, | 
					
						
							|  |  |  |    however, then this function is called like this: | 
					
						
							|  |  |  | 	tempvar = (*(var->dynamic_value)) (var); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    Sometimes `tempvar' will replace the value of `var'.  Other times, the | 
					
						
							|  |  |  |    shell will simply use the string value.  Pretty object-oriented, huh? | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    Be warned, though: if you `unset' a special variable, it loses its | 
					
						
							|  |  |  |    special meaning, even if you subsequently set it. | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    The special assignment code would probably have been better put in | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    subst.c: do_assignment_internal, in the same style as | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    stupidly_hack_special_variables, but I wanted the changes as | 
					
						
							|  |  |  |    localized as possible.  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
 | 
					
						
							|  |  |  |   do \ | 
					
						
							|  |  |  |     { \ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       v = bind_variable (var, (val), 0); \ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       v->dynamic_value = gfunc; \ | 
					
						
							|  |  |  |       v->assign_func = afunc; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
 | 
					
						
							|  |  |  |   do \ | 
					
						
							|  |  |  |     { \ | 
					
						
							|  |  |  |       v = make_new_array_variable (var); \ | 
					
						
							|  |  |  |       v->dynamic_value = gfunc; \ | 
					
						
							|  |  |  |       v->assign_func = afunc; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #define INIT_DYNAMIC_ASSOC_VAR(var, gfunc, afunc) \
 | 
					
						
							|  |  |  |   do \ | 
					
						
							|  |  |  |     { \ | 
					
						
							|  |  |  |       v = make_new_assoc_variable (var); \ | 
					
						
							|  |  |  |       v->dynamic_value = gfunc; \ | 
					
						
							|  |  |  |       v->assign_func = afunc; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | null_assign (self, value, unused, key) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | null_array_assign (self, value, ind, key) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      arrayind_t ind; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Degenerate `dynamic_value' function; just returns what's passed without
 | 
					
						
							|  |  |  |    manipulation. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_self (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* A generic dynamic array variable initializer.  Initialize array variable
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |    NAME with dynamic value function GETFUNC and assignment function SETFUNC. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | init_dynamic_array_var (name, getfunc, setfunc, attrs) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      sh_var_value_func_t *getfunc; | 
					
						
							|  |  |  |      sh_var_assign_func_t *setfunc; | 
					
						
							|  |  |  |      int attrs; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v) | 
					
						
							|  |  |  |     return (v); | 
					
						
							|  |  |  |   INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc); | 
					
						
							|  |  |  |   if (attrs) | 
					
						
							|  |  |  |     VSETATTR (v, attrs); | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | init_dynamic_assoc_var (name, getfunc, setfunc, attrs) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      sh_var_value_func_t *getfunc; | 
					
						
							|  |  |  |      sh_var_assign_func_t *setfunc; | 
					
						
							|  |  |  |      int attrs; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v) | 
					
						
							|  |  |  |     return (v); | 
					
						
							|  |  |  |   INIT_DYNAMIC_ASSOC_VAR (name, getfunc, setfunc); | 
					
						
							|  |  |  |   if (attrs) | 
					
						
							|  |  |  |     VSETATTR (v, attrs); | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* The value of $SECONDS.  This is the number of seconds since shell
 | 
					
						
							|  |  |  |    invocation, or, the number of seconds since the last assignment + the | 
					
						
							|  |  |  |    value of the last assignment. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t seconds_value_assigned; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_seconds (self, value, unused, key) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   if (legal_number (value, &seconds_value_assigned) == 0) | 
					
						
							|  |  |  |     seconds_value_assigned = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   shell_start_time = NOW; | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_seconds (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   time_t time_since_start; | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   time_since_start = NOW - shell_start_time; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   p = itos(seconds_value_assigned + time_since_start); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (var, att_integer); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   var_setvalue (var, p); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | init_seconds_var () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable ("SECONDS"); | 
					
						
							|  |  |  |   if (v) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (legal_number (value_cell(v), &seconds_value_assigned) == 0) | 
					
						
							|  |  |  | 	seconds_value_assigned = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   return v;       | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  |       | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* The random number seed.  You can change this by setting RANDOM. */ | 
					
						
							|  |  |  | static unsigned long rseed = 1; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static int last_random_value; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | static int seeded_subshell = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | /* A linear congruential random number generator based on the example
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    one in the ANSI C standard.  This one isn't very good, but a more | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |    complicated one is overkill. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Returns a pseudo-random number between 0 and 32767. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | brand () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   /* From "Random number generators: good ones are hard to find",
 | 
					
						
							|  |  |  |      Park and Miller, Communications of the ACM, vol. 31, no. 10, | 
					
						
							|  |  |  |      October 1988, p. 1195. filtered through FreeBSD */ | 
					
						
							|  |  |  |   long h, l; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   /* Can't seed with 0. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (rseed == 0) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     rseed = 123459876; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   h = rseed / 127773; | 
					
						
							|  |  |  |   l = rseed % 127773; | 
					
						
							|  |  |  |   rseed = 16807 * l - 2836 * h; | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |   if (rseed < 0) | 
					
						
							|  |  |  |     rseed += 0x7fffffff; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   return ((unsigned int)(rseed & 32767));	/* was % 32768 */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set the random number generator seed to SEED. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | sbrand (seed) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      unsigned long seed; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   rseed = seed; | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  |   last_random_value = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | seedrand () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct timeval tv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   gettimeofday (&tv, NULL); | 
					
						
							|  |  |  |   sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_random (self, value, unused, key) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   sbrand (strtoul (value, (char **)NULL, 10)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (subshell_environment) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     seeded_subshell = getpid (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | int | 
					
						
							|  |  |  | get_random_number () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int rv, pid; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Reset for command and process substitution. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   pid = getpid (); | 
					
						
							|  |  |  |   if (subshell_environment && seeded_subshell != pid) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       seedrand (); | 
					
						
							|  |  |  |       seeded_subshell = pid; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   do | 
					
						
							|  |  |  |     rv = brand (); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   while (rv == last_random_value); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   return rv; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_random (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int rv; | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rv = get_random_number (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   last_random_value = rv; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   p = itos (rv); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (var, att_integer); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   var_setvalue (var, p); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_lineno (var, value, unused, key) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   intmax_t new_value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0) | 
					
						
							|  |  |  |     new_value = 0; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   line_number = line_number_base = new_value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return var; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Function which returns the current line number. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_lineno (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *p; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   int ln; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   ln = executing_line_number (); | 
					
						
							|  |  |  |   p = itos (ln); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   var_setvalue (var, p); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_subshell (var, value, unused, key) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   intmax_t new_value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0) | 
					
						
							|  |  |  |     new_value = 0; | 
					
						
							|  |  |  |   subshell_level = new_value; | 
					
						
							|  |  |  |   return var; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_subshell (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   p = itos (subshell_level); | 
					
						
							|  |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   var_setvalue (var, p); | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_bashpid (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int pid; | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pid = getpid (); | 
					
						
							|  |  |  |   p = itos (pid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   VSETATTR (var, att_integer|att_readonly); | 
					
						
							|  |  |  |   var_setvalue (var, p); | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_bash_command (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (the_printed_command_except_trap) | 
					
						
							|  |  |  |     p = savestring (the_printed_command_except_trap); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       p = (char *)xmalloc (1); | 
					
						
							|  |  |  |       p[0] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   var_setvalue (var, p); | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_histcmd (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   p = itos (history_number ()); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   var_setvalue (var, p); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | /* When this function returns, VAR->value points to malloced memory. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_comp_wordbreaks (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* If we don't have anything yet, assign a default value. */ | 
					
						
							|  |  |  |   if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0) | 
					
						
							|  |  |  |     enable_hostname_completion (perform_hostname_completion); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   FREE (value_cell (var)); | 
					
						
							|  |  |  |   var_setvalue (var, savestring (rl_completer_word_break_characters)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* When this function returns, rl_completer_word_break_characters points to
 | 
					
						
							|  |  |  |    malloced memory. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_comp_wordbreaks (self, value, unused, key) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t unused; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   if (rl_completer_word_break_characters && | 
					
						
							|  |  |  |       rl_completer_word_break_characters != rl_basic_word_break_characters) | 
					
						
							|  |  |  |     free (rl_completer_word_break_characters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rl_completer_word_break_characters = savestring (value); | 
					
						
							|  |  |  |   return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* READLINE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | assign_dirstack (self, value, ind, key) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t ind; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *key; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   set_dirstack_element (ind, 1, value); | 
					
						
							|  |  |  |   return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_dirstack (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   ARRAY *a; | 
					
						
							|  |  |  |   WORD_LIST *l; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   l = get_directory_stack (0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   a = array_from_word_list (l); | 
					
						
							|  |  |  |   array_dispose (array_cell (self)); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   dispose_words (l); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   var_setarray (self, a); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* PUSHD AND POPD && ARRAY_VARS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | /* We don't want to initialize the group set with a call to getgroups()
 | 
					
						
							|  |  |  |    unless we're asked to, but we only want to do it once. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_groupset (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   int ng; | 
					
						
							|  |  |  |   ARRAY *a; | 
					
						
							|  |  |  |   static char **group_set = (char **)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (group_set == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       group_set = get_group_list (&ng); | 
					
						
							|  |  |  |       a = array_cell (self); | 
					
						
							|  |  |  |       for (i = 0; i < ng; i++) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	array_insert (a, i, group_set[i]); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | build_hashcmd (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   HASH_TABLE *h; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   char *k, *v; | 
					
						
							|  |  |  |   BUCKET_CONTENTS *item; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   h = assoc_cell (self); | 
					
						
							|  |  |  |   if (h) | 
					
						
							|  |  |  |     assoc_dispose (h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       var_setvalue (self, (char *)NULL); | 
					
						
							|  |  |  |       return self; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   h = assoc_create (hashed_filenames->nbuckets); | 
					
						
							|  |  |  |   for (i = 0; i < hashed_filenames->nbuckets; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (item = hash_items (i, hashed_filenames); item; item = item->next) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  k = savestring (item->key); | 
					
						
							|  |  |  | 	  v = pathdata(item)->path; | 
					
						
							|  |  |  | 	  assoc_insert (h, k, v); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var_setvalue (self, (char *)h); | 
					
						
							|  |  |  |   return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_hashcmd (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   build_hashcmd (self); | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | assign_hashcmd (self, value, ind, key) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t ind; | 
					
						
							|  |  |  |      char *key; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   phash_insert (key, value, 0, 0); | 
					
						
							|  |  |  |   return (build_hashcmd (self)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #if defined (ALIAS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | build_aliasvar (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   HASH_TABLE *h; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   char *k, *v; | 
					
						
							|  |  |  |   BUCKET_CONTENTS *item; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   h = assoc_cell (self); | 
					
						
							|  |  |  |   if (h) | 
					
						
							|  |  |  |     assoc_dispose (h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (aliases == 0 || HASH_ENTRIES (aliases) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       var_setvalue (self, (char *)NULL); | 
					
						
							|  |  |  |       return self; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   h = assoc_create (aliases->nbuckets); | 
					
						
							|  |  |  |   for (i = 0; i < aliases->nbuckets; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (item = hash_items (i, aliases); item; item = item->next) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  k = savestring (item->key); | 
					
						
							|  |  |  | 	  v = ((alias_t *)(item->data))->value; | 
					
						
							|  |  |  | 	  assoc_insert (h, k, v); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var_setvalue (self, (char *)h); | 
					
						
							|  |  |  |   return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_aliasvar (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   build_aliasvar (self); | 
					
						
							|  |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | assign_aliasvar (self, value, ind, key) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      arrayind_t ind; | 
					
						
							|  |  |  |      char *key; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   add_alias (key, value); | 
					
						
							|  |  |  |   return (build_aliasvar (self)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #endif /* ALIAS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* If ARRAY_VARS is not defined, this just returns the name of any
 | 
					
						
							|  |  |  |    currently-executing function.  If we have arrays, it's a call stack. */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | get_funcname (self) | 
					
						
							|  |  |  |      SHELL_VAR *self; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if ! defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char *t; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   if (variable_context && this_shell_function) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       FREE (value_cell (self)); | 
					
						
							|  |  |  |       t = savestring (this_shell_function->name); | 
					
						
							|  |  |  |       var_setvalue (self, t); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   return (self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | make_funcname_visible (on_or_off) | 
					
						
							|  |  |  |      int on_or_off; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   v = find_variable ("FUNCNAME"); | 
					
						
							|  |  |  |   if (v == 0 || v->dynamic_value == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (on_or_off) | 
					
						
							|  |  |  |     VUNSETATTR (v, att_invisible); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     VSETATTR (v, att_invisible); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | init_funcname_var () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   v = find_variable ("FUNCNAME"); | 
					
						
							|  |  |  |   if (v) | 
					
						
							|  |  |  |     return v; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   VSETATTR (v, att_invisible|att_noassign); | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | initialize_dynamic_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   v = init_seconds_var (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL); | 
					
						
							|  |  |  |   INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   VSETATTR (v, att_integer); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   VSETATTR (v, att_integer); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign); | 
					
						
							|  |  |  |   VSETATTR (v, att_integer|att_readonly); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   VSETATTR (v, att_integer); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* PUSHD_AND_POPD && ARRAY_VARS */
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if defined (DEBUGGER)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset); | 
					
						
							|  |  |  |   v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #  endif /* DEBUGGER */
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset); | 
					
						
							|  |  |  |   v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #  if defined (ALIAS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   v = init_funcname_var (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		Retrieving variables and values			    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* How to get a pointer to the shell variable or function named NAME.
 | 
					
						
							|  |  |  |    HASHED_VARS is a pointer to the hash table containing the list | 
					
						
							|  |  |  |    of interest (either variables or functions). */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | hash_lookup (name, hashed_vars) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      HASH_TABLE *hashed_vars; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BUCKET_CONTENTS *bucket; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   bucket = hash_search (name, hashed_vars, 0); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* If we find the name in HASHED_VARS, set LAST_TABLE_SEARCHED to that
 | 
					
						
							|  |  |  |      table. */ | 
					
						
							|  |  |  |   if (bucket) | 
					
						
							|  |  |  |     last_table_searched = hashed_vars; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | SHELL_VAR * | 
					
						
							|  |  |  | var_lookup (name, vcontext) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      VAR_CONTEXT *vcontext; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = (SHELL_VAR *)NULL; | 
					
						
							|  |  |  |   for (vc = vcontext; vc; vc = vc->down) | 
					
						
							|  |  |  |     if (v = hash_lookup (name, vc->table)) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    then also search the temporarily built list of exported variables. | 
					
						
							|  |  |  |    The lookup order is: | 
					
						
							|  |  |  | 	temporary_env | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	shell_variables list | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | find_variable_internal (name, force_tempenv) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |      int force_tempenv; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   SHELL_VAR *var; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int search_tempenv; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   VAR_CONTEXT *vc; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If explicitly requested, first look in the temporary environment for
 | 
					
						
							|  |  |  |      the variable.  This allows constructs such as "foo=x eval 'echo $foo'" | 
					
						
							|  |  |  |      to get the `exported' value of $foo.  This happens if we are executing | 
					
						
							|  |  |  |      a function or builtin, or if we are looking up a variable in a | 
					
						
							|  |  |  |      "subshell environment". */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (search_tempenv && temporary_env)		 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     var = hash_lookup (name, temporary_env); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   vc = shell_variables; | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | if (search_tempenv == 0 && /* (subshell_environment & SUBSHELL_COMSUB) && */ | 
					
						
							|  |  |  |     expanding_redir && | 
					
						
							|  |  |  |     (this_shell_builtin == eval_builtin || this_shell_builtin == command_builtin)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   itrace("find_variable_internal: search_tempenv == 0: skipping VC_BLTNENV"); | 
					
						
							|  |  |  |   while (vc && (vc->flags & VC_BLTNENV)) | 
					
						
							|  |  |  |     vc = vc->down; | 
					
						
							|  |  |  |   if (vc == 0) | 
					
						
							|  |  |  |     vc = shell_variables; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (var == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     var = var_lookup (name, vc); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (var == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Look up and resolve the chain of nameref variables starting at V all the
 | 
					
						
							|  |  |  |    way to NULL or non-nameref. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable_nameref (v) | 
					
						
							|  |  |  |      SHELL_VAR *v; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int level; | 
					
						
							|  |  |  |   char *newname; | 
					
						
							|  |  |  |   SHELL_VAR *orig, *oldv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   level = 0; | 
					
						
							|  |  |  |   orig = v; | 
					
						
							|  |  |  |   while (v && nameref_p (v)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       level++; | 
					
						
							|  |  |  |       if (level > NAMEREF_MAX) | 
					
						
							|  |  |  | 	return ((SHELL_VAR *)0);	/* error message here? */ | 
					
						
							|  |  |  |       newname = nameref_cell (v); | 
					
						
							|  |  |  |       if (newname == 0 || *newname == '\0') | 
					
						
							|  |  |  | 	return ((SHELL_VAR *)0); | 
					
						
							|  |  |  |       oldv = v; | 
					
						
							|  |  |  |       v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))); | 
					
						
							|  |  |  |       if (v == orig || v == oldv) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  internal_warning (_("%s: circular name reference"), orig->name); | 
					
						
							|  |  |  | 	  return ((SHELL_VAR *)0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Resolve the chain of nameref variables for NAME.  XXX - could change later */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable_last_nameref (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v, *nv; | 
					
						
							|  |  |  |   char *newname; | 
					
						
							|  |  |  |   int level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   nv = v = find_variable_noref (name); | 
					
						
							|  |  |  |   level = 0; | 
					
						
							|  |  |  |   while (v && nameref_p (v)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       level++; | 
					
						
							|  |  |  |       if (level > NAMEREF_MAX) | 
					
						
							|  |  |  |         return ((SHELL_VAR *)0);	/* error message here? */ | 
					
						
							|  |  |  |       newname = nameref_cell (v); | 
					
						
							|  |  |  |       if (newname == 0 || *newname == '\0') | 
					
						
							|  |  |  | 	return ((SHELL_VAR *)0); | 
					
						
							|  |  |  |       nv = v; | 
					
						
							|  |  |  |       v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return nv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Resolve the chain of nameref variables for NAME.  XXX - could change later */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_global_variable_last_nameref (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v, *nv; | 
					
						
							|  |  |  |   char *newname; | 
					
						
							|  |  |  |   int level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   nv = v = find_global_variable_noref (name); | 
					
						
							|  |  |  |   level = 0; | 
					
						
							|  |  |  |   while (v && nameref_p (v)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       level++; | 
					
						
							|  |  |  |       if (level > NAMEREF_MAX) | 
					
						
							|  |  |  |         return ((SHELL_VAR *)0);	/* error message here? */ | 
					
						
							|  |  |  |       newname = nameref_cell (v); | 
					
						
							|  |  |  |       if (newname == 0 || *newname == '\0') | 
					
						
							|  |  |  | 	return ((SHELL_VAR *)0); | 
					
						
							|  |  |  |       nv = v; | 
					
						
							|  |  |  |       v = find_global_variable_noref (newname); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return nv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | find_nameref_at_context (v, vc) | 
					
						
							|  |  |  |      SHELL_VAR *v; | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *nv, *nv2; | 
					
						
							|  |  |  |   VAR_CONTEXT *nvc; | 
					
						
							|  |  |  |   char *newname; | 
					
						
							|  |  |  |   int level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   nv = v; | 
					
						
							|  |  |  |   level = 1; | 
					
						
							|  |  |  |   while (nv && nameref_p (nv)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       level++; | 
					
						
							|  |  |  |       if (level > NAMEREF_MAX) | 
					
						
							|  |  |  |         return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  |       newname = nameref_cell (nv); | 
					
						
							|  |  |  |       if (newname == 0 || *newname == '\0') | 
					
						
							|  |  |  |         return ((SHELL_VAR *)NULL);       | 
					
						
							|  |  |  |       nv2 = hash_lookup (newname, vc->table); | 
					
						
							|  |  |  |       if (nv2 == 0) | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       nv = nv2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return nv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Do nameref resolution from the VC, which is the local context for some
 | 
					
						
							|  |  |  |    function or builtin, `up' the chain to the global variables context.  If | 
					
						
							|  |  |  |    NVCP is not NULL, return the variable context where we finally ended the | 
					
						
							|  |  |  |    nameref resolution (so the bind_variable_internal can use the correct | 
					
						
							|  |  |  |    variable context and hash table). */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | find_variable_nameref_context (v, vc, nvcp) | 
					
						
							|  |  |  |      SHELL_VAR *v; | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  |      VAR_CONTEXT **nvcp; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *nv, *nv2; | 
					
						
							|  |  |  |   VAR_CONTEXT *nvc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Look starting at the current context all the way `up' */ | 
					
						
							|  |  |  |   for (nv = v, nvc = vc; nvc; nvc = nvc->down) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       nv2 = find_nameref_at_context (nv, nvc); | 
					
						
							|  |  |  |       if (nv2 == 0) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  |       nv = nv2; | 
					
						
							|  |  |  |       if (*nvcp) | 
					
						
							|  |  |  |         *nvcp = nvc; | 
					
						
							|  |  |  |       if (nameref_p (nv) == 0) | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (nameref_p (nv) ? (SHELL_VAR *)NULL : nv); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Do nameref resolution from the VC, which is the local context for some
 | 
					
						
							|  |  |  |    function or builtin, `up' the chain to the global variables context.  If | 
					
						
							|  |  |  |    NVCP is not NULL, return the variable context where we finally ended the | 
					
						
							|  |  |  |    nameref resolution (so the bind_variable_internal can use the correct | 
					
						
							|  |  |  |    variable context and hash table). */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | find_variable_last_nameref_context (v, vc, nvcp) | 
					
						
							|  |  |  |      SHELL_VAR *v; | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  |      VAR_CONTEXT **nvcp; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *nv, *nv2; | 
					
						
							|  |  |  |   VAR_CONTEXT *nvc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Look starting at the current context all the way `up' */ | 
					
						
							|  |  |  |   for (nv = v, nvc = vc; nvc; nvc = nvc->down) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       nv2 = find_nameref_at_context (nv, nvc); | 
					
						
							|  |  |  |       if (nv2 == 0) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       nv = nv2; | 
					
						
							|  |  |  |       if (*nvcp) | 
					
						
							|  |  |  |         *nvcp = nvc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (nameref_p (nv) ? nv : (SHELL_VAR *)NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a variable, forcing a search of the temporary environment first */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable_tempenv (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = find_variable_internal (name, 1); | 
					
						
							|  |  |  |   if (var && nameref_p (var)) | 
					
						
							|  |  |  |     var = find_variable_nameref (var); | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a variable, not forcing a search of the temporary environment first */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable_notempenv (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = find_variable_internal (name, 0); | 
					
						
							|  |  |  |   if (var && nameref_p (var)) | 
					
						
							|  |  |  |     var = find_variable_nameref (var); | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_global_variable (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   var = var_lookup (name, global_variables); | 
					
						
							|  |  |  |   if (var && nameref_p (var)) | 
					
						
							|  |  |  |     var = find_variable_nameref (var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_global_variable_noref (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   var = var_lookup (name, global_variables); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_shell_variable (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = var_lookup (name, shell_variables); | 
					
						
							|  |  |  |   if (var && nameref_p (var)) | 
					
						
							|  |  |  |     var = find_variable_nameref (var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Look up the variable entry named NAME.  Returns the entry or NULL. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   last_table_searched = 0; | 
					
						
							|  |  |  |   v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))); | 
					
						
							|  |  |  |   if (v && nameref_p (v)) | 
					
						
							|  |  |  |     v = find_variable_nameref (v); | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_variable_noref (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))); | 
					
						
							|  |  |  |   return v; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Look up the function entry whose name matches STRING.
 | 
					
						
							|  |  |  |    Returns the entry or NULL. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_function (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (hash_lookup (name, shell_functions)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Find the function definition for the shell function named NAME.  Returns
 | 
					
						
							|  |  |  |    the entry or NULL. */ | 
					
						
							|  |  |  | FUNCTION_DEF * | 
					
						
							|  |  |  | find_function_def (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (DEBUGGER)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   return ((FUNCTION_DEF *)0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Return the value of VAR.  VAR is assumed to have been the result of a
 | 
					
						
							|  |  |  |    lookup without any subscript, if arrays are compiled into the shell. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | get_variable_value (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     return ((char *)NULL); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   else if (array_p (var)) | 
					
						
							|  |  |  |     return (array_reference (array_cell (var), 0)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   else if (assoc_p (var)) | 
					
						
							|  |  |  |     return (assoc_reference (assoc_cell (var), "0")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return (value_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return the string value of a variable.  Return NULL if the variable
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    doesn't exist.  Don't cons a new string.  This is a potential memory | 
					
						
							|  |  |  |    leak if the variable is found in the temporary environment.  Since | 
					
						
							|  |  |  |    functions and variables have separate name spaces, returns NULL if | 
					
						
							|  |  |  |    var_name is a shell function only. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | char * | 
					
						
							|  |  |  | get_string_value (var_name) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      const char *var_name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   var = find_variable (var_name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return ((var) ? get_variable_value (var) : (char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* This is present for use by the tilde and readline libraries. */ | 
					
						
							|  |  |  | char * | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | sh_get_env_value (v) | 
					
						
							|  |  |  |      const char *v; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return get_string_value (v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		  Creating and setting variables		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set NAME to VALUE if NAME has no value. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | set_if_not (name, value) | 
					
						
							|  |  |  |      char *name, *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   if (shell_variables == 0) | 
					
						
							|  |  |  |     create_variable_tables (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Create a local variable referenced by NAME. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | make_local_variable (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *new_var, *old_var; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  |   int was_tmpvar; | 
					
						
							|  |  |  |   char *tmp_value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* local foo; local foo;  is a no-op. */ | 
					
						
							|  |  |  |   old_var = find_variable (name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (old_var && local_p (old_var) && old_var->context == variable_context) | 
					
						
							| 
									
										
										
										
											2014-05-16 14:18:57 -04:00
										 |  |  |     return (old_var); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   was_tmpvar = old_var && tempvar_p (old_var); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* If we're making a local variable in a shell function, the temporary env
 | 
					
						
							|  |  |  |      has already been merged into the function's variable context stack.  We | 
					
						
							|  |  |  |      can assume that a temporary var in the same context appears in the same | 
					
						
							|  |  |  |      VAR_CONTEXT and can safely be returned without creating a new variable | 
					
						
							|  |  |  |      (which results in duplicate names in the same VAR_CONTEXT->table */ | 
					
						
							|  |  |  |   /* We can't just test tmpvar_p because variables in the temporary env given
 | 
					
						
							|  |  |  |      to a shell function appear in the function's local variable VAR_CONTEXT | 
					
						
							|  |  |  |      but retain their tempvar attribute.  We want temporary variables that are | 
					
						
							|  |  |  |      found in temporary_env, hence the test for last_table_searched, which is | 
					
						
							|  |  |  |      set in hash_lookup and only (so far) checked here. */ | 
					
						
							|  |  |  |   if (was_tmpvar && old_var->context == variable_context && last_table_searched != temporary_env) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       VUNSETATTR (old_var, att_invisible); | 
					
						
							|  |  |  |       return (old_var); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (was_tmpvar) | 
					
						
							|  |  |  |     tmp_value = value_cell (old_var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (vc = shell_variables; vc; vc = vc->down) | 
					
						
							|  |  |  |     if (vc_isfuncenv (vc) && vc->scope == variable_context) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (vc == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("make_local_variable: no function context at current scope")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (vc->table == 0) | 
					
						
							|  |  |  |     vc->table = hash_create (TEMPENV_HASH_BUCKETS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   /* Since this is called only from the local/declare/typeset code, we can
 | 
					
						
							|  |  |  |      call builtin_error here without worry (of course, it will also work | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      for anything that sets this_command_name).  Variables with the `noassign' | 
					
						
							|  |  |  |      attribute may not be made local.  The test against old_var's context | 
					
						
							|  |  |  |      level is to disallow local copies of readonly global variables (since I | 
					
						
							|  |  |  |      believe that this could be a security hole).  Readonly copies of calling | 
					
						
							|  |  |  |      function local variables are OK. */ | 
					
						
							|  |  |  |   if (old_var && (noassign_p (old_var) || | 
					
						
							|  |  |  | 		 (readonly_p (old_var) && old_var->context == 0))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (readonly_p (old_var)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	sh_readonly (name); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (noassign_p (old_var)) | 
					
						
							|  |  |  | 	builtin_error (_("%s: variable may not be assigned value"), name); | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |       /* Let noassign variables through with a warning */ | 
					
						
							|  |  |  |       if (readonly_p (old_var)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return ((SHELL_VAR *)NULL); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (old_var == 0) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     new_var = make_new_variable (name, vc->table); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       new_var = make_new_variable (name, vc->table); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* If we found this variable in one of the temporary environments,
 | 
					
						
							|  |  |  | 	 inherit its value.  Watch to see if this causes problems with | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	 things like `x=4 local x'. XXX - see above for temporary env | 
					
						
							|  |  |  | 	 variables with the same context level as variable_context */ | 
					
						
							|  |  |  |       /* XXX - we should only do this if the variable is not an array. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (was_tmpvar) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	var_setvalue (new_var, savestring (tmp_value)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       new_var->attributes = exported_p (old_var) ? att_exported : 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vc->flags |= VC_HASLOCAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   new_var->context = variable_context; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (new_var, att_local); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (ifsname (name)) | 
					
						
							|  |  |  |     setifs (new_var); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (was_tmpvar == 0) | 
					
						
							|  |  |  |     VSETATTR (new_var, att_invisible);	/* XXX */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (new_var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Create a new shell variable with name NAME. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | new_shell_variable (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   entry->name = savestring (name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   var_setvalue (entry, (char *)NULL); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   CLEAR_EXPORTSTR (entry); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   entry->dynamic_value = (sh_var_value_func_t *)NULL; | 
					
						
							|  |  |  |   entry->assign_func = (sh_var_assign_func_t *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   entry->attributes = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Always assume variables are to be made at toplevel!
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |      make_local_variable has the responsibility of changing the | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      variable context. */ | 
					
						
							|  |  |  |   entry->context = 0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return (entry); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Create a new shell variable with name NAME and add it to the hash table
 | 
					
						
							|  |  |  |    TABLE. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | make_new_variable (name, table) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      HASH_TABLE *table; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *entry; | 
					
						
							|  |  |  |   BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   entry = new_shell_variable (name); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* Make sure we have a shell_variables hash table to add to. */ | 
					
						
							|  |  |  |   if (shell_variables == 0) | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |     create_variable_tables (); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   elt = hash_insert (savestring (name), table, HASH_NOSRCH); | 
					
						
							|  |  |  |   elt->data = (PTR_T)entry; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return entry; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | make_new_array_variable (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *entry; | 
					
						
							|  |  |  |   ARRAY *array; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   entry = make_new_variable (name, global_variables->table); | 
					
						
							|  |  |  |   array = array_create (); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   var_setarray (entry, array); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (entry, att_array); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return entry; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | make_local_array_variable (name, assoc_ok) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      char *name; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |      int assoc_ok; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  |   ARRAY *array; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = make_local_variable (name); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (var == 0 || array_p (var) || (assoc_ok && assoc_p (var))) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     return var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   array = array_create (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable_value (var); | 
					
						
							|  |  |  |   var_setarray (var, array); | 
					
						
							|  |  |  |   VSETATTR (var, att_array); | 
					
						
							|  |  |  |   return var; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | make_new_assoc_variable (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *entry; | 
					
						
							|  |  |  |   HASH_TABLE *hash; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   entry = make_new_variable (name, global_variables->table); | 
					
						
							|  |  |  |   hash = assoc_create (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var_setassoc (entry, hash); | 
					
						
							|  |  |  |   VSETATTR (entry, att_assoc); | 
					
						
							|  |  |  |   return entry; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | make_local_assoc_variable (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  |   HASH_TABLE *hash; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = make_local_variable (name); | 
					
						
							|  |  |  |   if (var == 0 || assoc_p (var)) | 
					
						
							|  |  |  |     return var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable_value (var); | 
					
						
							|  |  |  |   hash = assoc_create (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var_setassoc (var, hash); | 
					
						
							|  |  |  |   VSETATTR (var, att_assoc); | 
					
						
							|  |  |  |   return var; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | make_variable_value (var, value, flags) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   char *retval, *oval; | 
					
						
							|  |  |  |   intmax_t lval, rval; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int expok, olen, op; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If this variable has had its type set to integer (via `declare -i'),
 | 
					
						
							|  |  |  |      then do expression evaluation on it and store the result.  The | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      functions in expr.c (evalexp()) and bind_int_variable() are responsible | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      for turning off the integer flag if they don't want further | 
					
						
							|  |  |  |      evaluation done. */ | 
					
						
							|  |  |  |   if (integer_p (var)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (flags & ASS_APPEND) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  oval = value_cell (var); | 
					
						
							|  |  |  | 	  lval = evalexp (oval, &expok);	/* ksh93 seems to do this */ | 
					
						
							|  |  |  | 	  if (expok == 0) | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      top_level_cleanup (); | 
					
						
							|  |  |  | 	      jump_to_top_level (DISCARD); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       rval = evalexp (value, &expok); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (expok == 0) | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  top_level_cleanup (); | 
					
						
							|  |  |  | 	  jump_to_top_level (DISCARD); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* This can be fooled if the variable's value changes while evaluating
 | 
					
						
							|  |  |  | 	 `rval'.  We can change it if we move the evaluation of lval to here. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (flags & ASS_APPEND) | 
					
						
							|  |  |  | 	rval += lval; | 
					
						
							|  |  |  |       retval = itos (rval); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (CASEMOD_ATTRS)
 | 
					
						
							|  |  |  |   else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (flags & ASS_APPEND) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  oval = get_variable_value (var); | 
					
						
							|  |  |  | 	  if (oval == 0)	/* paranoia */ | 
					
						
							|  |  |  | 	    oval = ""; | 
					
						
							|  |  |  | 	  olen = STRLEN (oval); | 
					
						
							|  |  |  | 	  retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1); | 
					
						
							|  |  |  | 	  strcpy (retval, oval); | 
					
						
							|  |  |  | 	  if (value) | 
					
						
							|  |  |  | 	    strcpy (retval+olen, value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if (*value) | 
					
						
							|  |  |  | 	retval = savestring (value); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  retval = (char *)xmalloc (1); | 
					
						
							|  |  |  | 	  retval[0] = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       op = capcase_p (var) ? CASE_CAPITALIZE | 
					
						
							|  |  |  | 			 : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER); | 
					
						
							|  |  |  |       oval = sh_modcase (retval, (char *)0, op); | 
					
						
							|  |  |  |       free (retval); | 
					
						
							|  |  |  |       retval = oval; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif /* CASEMOD_ATTRS */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else if (value) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (flags & ASS_APPEND) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  oval = get_variable_value (var); | 
					
						
							|  |  |  | 	  if (oval == 0)	/* paranoia */ | 
					
						
							|  |  |  | 	    oval = ""; | 
					
						
							|  |  |  | 	  olen = STRLEN (oval); | 
					
						
							|  |  |  | 	  retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1); | 
					
						
							|  |  |  | 	  strcpy (retval, oval); | 
					
						
							|  |  |  | 	  if (value) | 
					
						
							|  |  |  | 	    strcpy (retval+olen, value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if (*value) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	retval = savestring (value); | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  retval = (char *)xmalloc (1); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  retval[0] = '\0'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     retval = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return retval; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
 | 
					
						
							|  |  |  |    temporary environment (but usually is not). */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | bind_variable_internal (name, value, table, hflags, aflags) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      HASH_TABLE *table; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |      int hflags, aflags; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  |   char *newname, *newval; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   arrayind_t ind; | 
					
						
							|  |  |  |   char *subp; | 
					
						
							|  |  |  |   int sublen; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  |   newname = 0; | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   if ((aflags & ASS_FROMREF) && (hflags & HASH_NOSRCH) == 0 && valid_array_reference (name)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       newname = array_variable_name (name, &subp, &sublen); | 
					
						
							|  |  |  |       if (newname == 0) | 
					
						
							|  |  |  | 	return (SHELL_VAR *)NULL;	/* XXX */ | 
					
						
							|  |  |  |       entry = hash_lookup (newname, table); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table); | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* Follow the nameref chain here if this is the global variables table */ | 
					
						
							|  |  |  |   if (entry && nameref_p (entry) && (invisible_p (entry) == 0) && table == global_variables->table) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       entry = find_global_variable (entry->name); | 
					
						
							|  |  |  |       /* Let's see if we have a nameref referencing a variable that hasn't yet
 | 
					
						
							|  |  |  | 	 been created. */ | 
					
						
							|  |  |  |       if (entry == 0) | 
					
						
							|  |  |  | 	entry = find_variable_last_nameref (name);	/* XXX */ | 
					
						
							|  |  |  |       if (entry == 0)					/* just in case */ | 
					
						
							|  |  |  |         return (entry); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* The first clause handles `declare -n ref; ref=x;' */ | 
					
						
							|  |  |  |   if (entry && invisible_p (entry) && nameref_p (entry)) | 
					
						
							|  |  |  |     goto assign_value; | 
					
						
							|  |  |  |   else if (entry && nameref_p (entry)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       newval = nameref_cell (entry); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       /* declare -n foo=x[2] */ | 
					
						
							|  |  |  |       if (valid_array_reference (newval)) | 
					
						
							|  |  |  |         /* XXX - should it be aflags? */ | 
					
						
							|  |  |  | 	entry = assign_array_element (newval, make_variable_value (entry, value, 0), aflags); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |       entry = make_new_variable (newval, table); | 
					
						
							|  |  |  |       var_setvalue (entry, make_variable_value (entry, value, 0)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   else if (entry == 0 && newname) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       entry = make_new_array_variable (newname);	/* indexed array by default */ | 
					
						
							|  |  |  |       if (entry == 0) | 
					
						
							|  |  |  | 	return entry; | 
					
						
							|  |  |  |       ind = array_expand_index (name, subp, sublen); | 
					
						
							|  |  |  |       bind_array_element (entry, ind, value, aflags); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   else if (entry == 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       entry = make_new_variable (name, table); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   else if (entry->assign_func)	/* array vars have assign functions now */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       INVALIDATE_EXPORTSTR (entry); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |       if (assoc_p (entry)) | 
					
						
							|  |  |  | 	entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0")); | 
					
						
							|  |  |  |       else if (array_p (entry)) | 
					
						
							|  |  |  | 	entry = (*(entry->assign_func)) (entry, newval, 0, 0); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	entry = (*(entry->assign_func)) (entry, newval, -1, 0); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (newval != value) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	free (newval); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       return (entry); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | assign_value: | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (readonly_p (entry) || noassign_p (entry)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  if (readonly_p (entry)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	    err_readonly (name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  return (entry); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Variables which are bound are visible. */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       VUNSETATTR (entry, att_invisible); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       if (assoc_p (entry) || array_p (entry)) | 
					
						
							|  |  |  |         newval = make_array_variable_value (entry, 0, "0", value, aflags); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       newval = make_variable_value (entry, value, aflags);	/* XXX */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       /* Invalidate any cached export string */ | 
					
						
							|  |  |  |       INVALIDATE_EXPORTSTR (entry); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       /* XXX -- this bears looking at again -- XXX */ | 
					
						
							|  |  |  |       /* If an existing array variable x is being assigned to with x=b or
 | 
					
						
							|  |  |  | 	 `read x' or something of that nature, silently convert it to | 
					
						
							|  |  |  | 	 x[0]=b or `read x[0]'. */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (assoc_p (entry)) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  assoc_insert (assoc_cell (entry), savestring ("0"), newval); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	  free (newval); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (array_p (entry)) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  array_insert (array_cell (entry), 0, newval); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  free (newval); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  FREE (value_cell (entry)); | 
					
						
							|  |  |  | 	  var_setvalue (entry, newval); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (mark_modified_vars) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     VSETATTR (entry, att_exported); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (exported_p (entry)) | 
					
						
							|  |  |  |     array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (entry); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | /* Bind a variable NAME to VALUE.  This conses up the name
 | 
					
						
							|  |  |  |    and value strings.  If we have a temporary environment, we bind there | 
					
						
							|  |  |  |    first, then we bind into shell_variables. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | bind_variable (name, value, flags) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      const char *name; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   SHELL_VAR *v, *nv; | 
					
						
							|  |  |  |   VAR_CONTEXT *vc, *nvc; | 
					
						
							|  |  |  |   int level; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (shell_variables == 0) | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |     create_variable_tables (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If we have a temporary environment, look there first for the variable,
 | 
					
						
							|  |  |  |      and, if found, modify the value there before modifying it in the | 
					
						
							|  |  |  |      shell_variables table.  This allows sourced scripts to modify values | 
					
						
							|  |  |  |      given to them in a temporary environment while modifying the variable | 
					
						
							|  |  |  |      value that the caller sees. */ | 
					
						
							|  |  |  |   if (temporary_env) | 
					
						
							|  |  |  |     bind_tempenv_variable (name, value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* XXX -- handle local variables here. */ | 
					
						
							|  |  |  |   for (vc = shell_variables; vc; vc = vc->down) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (vc_isfuncenv (vc) || vc_isbltnenv (vc)) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  v = hash_lookup (name, vc->table); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  nvc = vc; | 
					
						
							|  |  |  | 	  if (v && nameref_p (v)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      nv = find_variable_nameref_context (v, vc, &nvc); | 
					
						
							|  |  |  | 	      if (nv == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  nv = find_variable_last_nameref_context (v, vc, &nvc); | 
					
						
							|  |  |  | 		  if (nv && nameref_p (nv)) | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		      /* If this nameref variable doesn't have a value yet,
 | 
					
						
							|  |  |  | 			 set the value.  Otherwise, assign using the value as | 
					
						
							|  |  |  | 			 normal. */ | 
					
						
							|  |  |  | 		      if (nameref_cell (nv) == 0) | 
					
						
							|  |  |  | 			return (bind_variable_internal (nv->name, value, nvc->table, 0, flags)); | 
					
						
							| 
									
										
										
										
											2015-01-15 10:20:04 -05:00
										 |  |  | 		      /* XXX - bug here with ref=array[index] */ | 
					
						
							|  |  |  | 		      return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags|ASS_FROMREF)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 		    } | 
					
						
							|  |  |  | 		  else | 
					
						
							|  |  |  | 		    v = nv; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 	        v = nv; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  if (v) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	    return (bind_variable_internal (v->name, value, nvc->table, 0, flags)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   /* bind_variable_internal will handle nameref resolution in this case */ | 
					
						
							|  |  |  |   return (bind_variable_internal (name, value, global_variables->table, 0, flags)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | bind_global_variable (name, value, flags) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v, *nv; | 
					
						
							|  |  |  |   VAR_CONTEXT *vc, *nvc; | 
					
						
							|  |  |  |   int level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (shell_variables == 0) | 
					
						
							|  |  |  |     create_variable_tables (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* bind_variable_internal will handle nameref resolution in this case */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   return (bind_variable_internal (name, value, global_variables->table, 0, flags)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | /* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
 | 
					
						
							|  |  |  |    value, variables are no longer invisible.  This is a duplicate of part | 
					
						
							|  |  |  |    of the internals of bind_variable.  If the variable is exported, or | 
					
						
							|  |  |  |    all modified variables should be exported, mark the variable for export | 
					
						
							|  |  |  |    and note that the export environment needs to be recreated. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | bind_variable_value (var, value, aflags) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  |      char *value; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |      int aflags; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char *t; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int invis; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   invis = invisible_p (var); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VUNSETATTR (var, att_invisible); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (var->assign_func) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* If we're appending, we need the old value, so use
 | 
					
						
							|  |  |  | 	 make_variable_value */ | 
					
						
							|  |  |  |       t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       (*(var->assign_func)) (var, t, -1, 0); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (t != value && t) | 
					
						
							|  |  |  | 	free (t);       | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = make_variable_value (var, value, aflags); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || (legal_identifier (t) == 0 && valid_array_reference (t) == 0))) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || legal_identifier (t) == 0)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (t); | 
					
						
							|  |  |  | 	  if (invis) | 
					
						
							|  |  |  | 	    VSETATTR (var, att_invisible);	/* XXX */ | 
					
						
							|  |  |  | 	  return ((SHELL_VAR *)NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       FREE (value_cell (var)); | 
					
						
							|  |  |  |       var_setvalue (var, t); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   INVALIDATE_EXPORTSTR (var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (mark_modified_vars) | 
					
						
							|  |  |  |     VSETATTR (var, att_exported); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (exported_p (var)) | 
					
						
							|  |  |  |     array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Bind/create a shell variable with the name LHS to the RHS.
 | 
					
						
							|  |  |  |    This creates or modifies a variable such that it is an integer. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This used to be in expr.c, but it is here so that all of the | 
					
						
							|  |  |  |    variable binding stuff is localized.  Since we don't want any | 
					
						
							|  |  |  |    recursive evaluation from bind_variable() (possible without this code, | 
					
						
							|  |  |  |    since bind_variable() calls the evaluator for variables with the integer | 
					
						
							|  |  |  |    attribute set), we temporarily turn off the integer attribute for each | 
					
						
							|  |  |  |    variable we set here, then turn it back on after binding as necessary. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | bind_int_variable (lhs, rhs) | 
					
						
							|  |  |  |      char *lhs, *rhs; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register SHELL_VAR *v; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int isint, isarr, implicitarray; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   isint = isarr = implicitarray = 0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   if (valid_array_reference (lhs)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       isarr = 1; | 
					
						
							|  |  |  |       v = array_variable_part (lhs, (char **)0, (int *)0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     v = find_variable (lhs); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (v) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       isint = integer_p (v); | 
					
						
							|  |  |  |       VUNSETATTR (v, att_integer); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       if (array_p (v) && isarr == 0) | 
					
						
							|  |  |  | 	implicitarray = 1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   if (isarr) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     v = assign_array_element (lhs, rhs, 0); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   else if (implicitarray) | 
					
						
							|  |  |  |     v = bind_array_variable (lhs, 0, rhs, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |     v = bind_variable (lhs, rhs, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 14:55:37 -04:00
										 |  |  |   if (v) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (isint) | 
					
						
							|  |  |  | 	VSETATTR (v, att_integer); | 
					
						
							|  |  |  |       VUNSETATTR (v, att_invisible); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   return (v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | SHELL_VAR * | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | bind_var_to_int (var, val) | 
					
						
							|  |  |  |      char *var; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      intmax_t val; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0); | 
					
						
							|  |  |  |   return (bind_int_variable (var, p)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Do a function binding to a variable.  You pass the name and
 | 
					
						
							|  |  |  |    the command to bind to.  This conses the name and command. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | bind_function (name, value) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      COMMAND *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *entry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   entry = find_function (name); | 
					
						
							|  |  |  |   if (entry == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH); | 
					
						
							|  |  |  |       entry = new_shell_variable (name); | 
					
						
							|  |  |  |       elt->data = (PTR_T)entry; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     INVALIDATE_EXPORTSTR (entry); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var_isset (entry)) | 
					
						
							|  |  |  |     dispose_command (function_cell (entry)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value) | 
					
						
							|  |  |  |     var_setfunc (entry, copy_command (value)); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     var_setfunc (entry, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VSETATTR (entry, att_function); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (mark_modified_vars) | 
					
						
							|  |  |  |     VSETATTR (entry, att_exported); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VUNSETATTR (entry, att_invisible);		/* Just to be sure */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (exported_p (entry)) | 
					
						
							|  |  |  |     array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (PROGRAMMABLE_COMPLETION)
 | 
					
						
							|  |  |  |   set_itemlist_dirty (&it_functions); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (entry); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (DEBUGGER)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Bind a function definition, which includes source file and line number
 | 
					
						
							|  |  |  |    information in addition to the command, into the FUNCTION_DEF hash table.*/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | bind_function_def (name, value) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      FUNCTION_DEF *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   FUNCTION_DEF *entry; | 
					
						
							|  |  |  |   BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  |   COMMAND *cmd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   entry = find_function_def (name); | 
					
						
							|  |  |  |   if (entry) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       dispose_function_def_contents (entry); | 
					
						
							|  |  |  |       entry = copy_function_def_contents (value, entry); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       cmd = value->command; | 
					
						
							|  |  |  |       value->command = 0; | 
					
						
							|  |  |  |       entry = copy_function_def (value); | 
					
						
							|  |  |  |       value->command = cmd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH); | 
					
						
							|  |  |  |       elt->data = (PTR_T *)entry; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #endif /* DEBUGGER */
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Add STRING, which is of the form foo=bar, to the temporary environment
 | 
					
						
							|  |  |  |    HASH_TABLE (temporary_env).  The functions in execute_cmd.c are | 
					
						
							|  |  |  |    responsible for moving the main temporary env to one of the other | 
					
						
							|  |  |  |    temporary environments.  The expansion code in subst.c calls this. */ | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | assign_in_env (word, flags) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |      WORD_DESC *word; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int offset, aflags; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char *name, *temp, *value; | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   const char *string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   string = word->word; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   aflags = 0; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   offset = assignment (string, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   name = savestring (string); | 
					
						
							|  |  |  |   value = (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (name[offset] == '=') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       name[offset] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* don't ignore the `+' when assigning temporary environment */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       if (name[offset - 1] == '+') | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  name[offset - 1] = '\0'; | 
					
						
							|  |  |  | 	  aflags |= ASS_APPEND; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       var = find_variable (name); | 
					
						
							|  |  |  |       if (var && (readonly_p (var) || noassign_p (var))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (readonly_p (var)) | 
					
						
							|  |  |  | 	    err_readonly (name); | 
					
						
							|  |  |  | 	  free (name); | 
					
						
							|  |  |  |   	  return (0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       temp = name + offset + 1; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       value = expand_assignment_string_to_string (temp, 0); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (var && (aflags & ASS_APPEND)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  temp = make_variable_value (var, value, aflags); | 
					
						
							|  |  |  | 	  FREE (value); | 
					
						
							|  |  |  | 	  value = temp; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (temporary_env == 0) | 
					
						
							|  |  |  |     temporary_env = hash_create (TEMPENV_HASH_BUCKETS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = hash_lookup (name, temporary_env); | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     var = make_new_variable (name, temporary_env); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     FREE (value_cell (var)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       value = (char *)xmalloc (1);	/* like do_assignment_internal */ | 
					
						
							|  |  |  |       value[0] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var_setvalue (var, value); | 
					
						
							|  |  |  |   var->attributes |= (att_exported|att_tempvar); | 
					
						
							|  |  |  |   var->context = variable_context;	/* XXX */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   INVALIDATE_EXPORTSTR (var); | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |   var->exportstr = mk_env_string (name, value, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (flags) | 
					
						
							|  |  |  |     stupidly_hack_special_variables (name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (echo_command_at_execute) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     /* The Korn shell prints the `+ ' in front of assignment statements,
 | 
					
						
							|  |  |  | 	so we do too. */ | 
					
						
							|  |  |  |     xtrace_print_assignment (name, value, 0, 1); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   free (name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*			Copying variables			    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef INCLUDE_UNUSED
 | 
					
						
							|  |  |  | /* Copy VAR to a new data structure and return that structure. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | copy_variable (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *copy = (SHELL_VAR *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy->attributes = var->attributes; | 
					
						
							|  |  |  |       copy->name = savestring (var->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (function_p (var)) | 
					
						
							|  |  |  | 	var_setfunc (copy, copy_command (function_cell (var))); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       else if (array_p (var)) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	var_setarray (copy, array_copy (array_cell (var))); | 
					
						
							|  |  |  |       else if (assoc_p (var)) | 
					
						
							|  |  |  | 	var_setassoc (copy, assoc_copy (assoc_cell (var))); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (nameref_cell (var))	/* XXX - nameref */ | 
					
						
							|  |  |  | 	var_setref (copy, savestring (nameref_cell (var))); | 
					
						
							|  |  |  |       else if (value_cell (var))	/* XXX - nameref */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	var_setvalue (copy, savestring (value_cell (var))); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	var_setvalue (copy, (char *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy->dynamic_value = var->dynamic_value; | 
					
						
							|  |  |  |       copy->assign_func = var->assign_func; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy->exportstr = COPY_EXPORTSTR (var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy->context = var->context; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (copy); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		  Deleting and unsetting variables		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Dispose of the information attached to VAR. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | dispose_variable_value (var) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (function_p (var)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     dispose_command (function_cell (var)); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   else if (array_p (var)) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     array_dispose (array_cell (var)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   else if (assoc_p (var)) | 
					
						
							|  |  |  |     assoc_dispose (assoc_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   else if (nameref_p (var)) | 
					
						
							|  |  |  |     FREE (nameref_cell (var)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     FREE (value_cell (var)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | dispose_variable (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (var == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (nofree_p (var) == 0) | 
					
						
							|  |  |  |     dispose_variable_value (var); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   FREE_EXPORTSTR (var); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   free (var->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (exported_p (var)) | 
					
						
							|  |  |  |     array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Unset the shell variable referenced by NAME.  Unsetting a nameref variable
 | 
					
						
							|  |  |  |    unsets the variable it resolves to but leaves the nameref alone. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | unbind_variable (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   SHELL_VAR *v, *nv; | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = var_lookup (name, shell_variables); | 
					
						
							|  |  |  |   nv = (v && nameref_p (v)) ? find_variable_nameref (v) : (SHELL_VAR *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   r = nv ? makunbound (nv->name, shell_variables) : makunbound (name, shell_variables); | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Unbind NAME, where NAME is assumed to be a nameref variable */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | unbind_nameref (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = var_lookup (name, shell_variables); | 
					
						
							|  |  |  |   if (v && nameref_p (v)) | 
					
						
							|  |  |  |     return makunbound (name, shell_variables); | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Unset the shell function named NAME. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | unbind_func (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  |   SHELL_VAR *func; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   elt = hash_remove (name, shell_functions, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (elt == 0) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (PROGRAMMABLE_COMPLETION)
 | 
					
						
							|  |  |  |   set_itemlist_dirty (&it_functions); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   func = (SHELL_VAR *)elt->data; | 
					
						
							|  |  |  |   if (func) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (exported_p (func)) | 
					
						
							|  |  |  | 	array_needs_making++; | 
					
						
							|  |  |  |       dispose_variable (func); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   free (elt->key); | 
					
						
							|  |  |  |   free (elt); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return 0;   | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #if defined (DEBUGGER)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | int | 
					
						
							|  |  |  | unbind_function_def (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  |   FUNCTION_DEF *funcdef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elt = hash_remove (name, shell_function_defs, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (elt == 0) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   funcdef = (FUNCTION_DEF *)elt->data; | 
					
						
							|  |  |  |   if (funcdef) | 
					
						
							|  |  |  |     dispose_function_def (funcdef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (elt->key); | 
					
						
							|  |  |  |   free (elt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0;   | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #endif /* DEBUGGER */
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | int | 
					
						
							|  |  |  | delete_var (name, vc) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BUCKET_CONTENTS *elt; | 
					
						
							|  |  |  |   SHELL_VAR *old_var; | 
					
						
							|  |  |  |   VAR_CONTEXT *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down) | 
					
						
							|  |  |  |     if (elt = hash_remove (name, v->table, 0)) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (elt == 0) | 
					
						
							|  |  |  |     return (-1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   old_var = (SHELL_VAR *)elt->data; | 
					
						
							|  |  |  |   free (elt->key); | 
					
						
							|  |  |  |   free (elt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable (old_var); | 
					
						
							|  |  |  |   return (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Make the variable associated with NAME go away.  HASH_LIST is the
 | 
					
						
							|  |  |  |    hash table from which this variable should be deleted (either | 
					
						
							|  |  |  |    shell_variables or shell_functions). | 
					
						
							|  |  |  |    Returns non-zero if the variable couldn't be found. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | makunbound (name, vc) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      VAR_CONTEXT *vc; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   BUCKET_CONTENTS *elt, *new_elt; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   SHELL_VAR *old_var; | 
					
						
							|  |  |  |   VAR_CONTEXT *v; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   char *t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down) | 
					
						
							|  |  |  |     if (elt = hash_remove (name, v->table, 0)) | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (elt == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     return (-1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   old_var = (SHELL_VAR *)elt->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (old_var && exported_p (old_var)) | 
					
						
							|  |  |  |     array_needs_making++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* If we're unsetting a local variable and we're still executing inside
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      the function, just mark the variable as invisible.  The function | 
					
						
							|  |  |  |      eventually called by pop_var_context() will clean it up later.  This | 
					
						
							|  |  |  |      must be done so that if the variable is subsequently assigned a new | 
					
						
							|  |  |  |      value inside the function, the `local' attribute is still present. | 
					
						
							|  |  |  |      We also need to add it back into the correct hash table. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (old_var && local_p (old_var) && variable_context == old_var->context) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       if (nofree_p (old_var)) | 
					
						
							|  |  |  | 	var_setvalue (old_var, (char *)NULL); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else if (array_p (old_var)) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	array_dispose (array_cell (old_var)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else if (assoc_p (old_var)) | 
					
						
							|  |  |  | 	assoc_dispose (assoc_cell (old_var)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (nameref_p (old_var)) | 
					
						
							|  |  |  | 	FREE (nameref_cell (old_var)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	FREE (value_cell (old_var)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       /* Reset the attributes.  Preserve the export attribute if the variable
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	 came from a temporary environment.  Make sure it stays local, and | 
					
						
							|  |  |  | 	 make it invisible. */  | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0; | 
					
						
							|  |  |  |       VSETATTR (old_var, att_local); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       VSETATTR (old_var, att_invisible); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       var_setvalue (old_var, (char *)NULL); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       INVALIDATE_EXPORTSTR (old_var); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       new_elt = hash_insert (savestring (old_var->name), v->table, 0); | 
					
						
							|  |  |  |       new_elt->data = (PTR_T)old_var; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       stupidly_hack_special_variables (old_var->name); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       free (elt->key); | 
					
						
							|  |  |  |       free (elt); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* Have to save a copy of name here, because it might refer to
 | 
					
						
							|  |  |  |      old_var->name.  If so, stupidly_hack_special_variables will | 
					
						
							|  |  |  |      reference freed memory. */ | 
					
						
							|  |  |  |   t = savestring (name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (elt->key); | 
					
						
							|  |  |  |   free (elt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable (old_var); | 
					
						
							|  |  |  |   stupidly_hack_special_variables (t); | 
					
						
							|  |  |  |   free (t); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Get rid of all of the variables in the current context. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | kill_all_local_variables () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (vc = shell_variables; vc; vc = vc->down) | 
					
						
							|  |  |  |     if (vc_isfuncenv (vc) && vc->scope == variable_context) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   if (vc == 0) | 
					
						
							|  |  |  |     return;		/* XXX */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (vc->table && vc_haslocals (vc)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       delete_all_variables (vc->table); | 
					
						
							|  |  |  |       hash_dispose (vc->table); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vc->table = (HASH_TABLE *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | free_variable_hash_data (data) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      PTR_T data; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   SHELL_VAR *var; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)data; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   dispose_variable (var); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Delete the entire contents of the hash table. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | delete_all_variables (hashed_vars) | 
					
						
							|  |  |  |      HASH_TABLE *hashed_vars; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   hash_flush (hashed_vars, free_variable_hash_data); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		     Setting variable attributes		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #define FIND_OR_MAKE_VARIABLE(name, entry) \
 | 
					
						
							|  |  |  |   do \ | 
					
						
							|  |  |  |     { \ | 
					
						
							|  |  |  |       entry = find_variable (name); \ | 
					
						
							|  |  |  |       if (!entry) \ | 
					
						
							|  |  |  | 	{ \ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  entry = bind_variable (name, "", 0); \ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	  if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |   while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make the variable associated with NAME be readonly.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    If NAME does not exist yet, create it. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_var_read_only (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   FIND_OR_MAKE_VARIABLE (name, entry); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   VSETATTR (entry, att_readonly); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #ifdef INCLUDE_UNUSED
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Make the function associated with NAME be readonly.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    If NAME does not exist, we just punt, like auto_export code below. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_func_read_only (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   entry = find_function (name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (entry) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     VSETATTR (entry, att_readonly); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make the variable associated with NAME be auto-exported.
 | 
					
						
							|  |  |  |    If NAME does not exist yet, create it. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_var_auto_export (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   FIND_OR_MAKE_VARIABLE (name, entry); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   set_auto_export (entry); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make the function associated with NAME be auto-exported. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_func_auto_export (name) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   SHELL_VAR *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   entry = find_function (name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (entry) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     set_auto_export (entry); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		     Creating lists of variables		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static VARLIST * | 
					
						
							|  |  |  | vlist_alloc (nentries) | 
					
						
							|  |  |  |      int nentries; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   VARLIST  *vlist; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vlist = (VARLIST *)xmalloc (sizeof (VARLIST)); | 
					
						
							|  |  |  |   vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *)); | 
					
						
							|  |  |  |   vlist->list_size = nentries; | 
					
						
							|  |  |  |   vlist->list_len = 0; | 
					
						
							|  |  |  |   vlist->list[0] = (SHELL_VAR *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return vlist; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static VARLIST * | 
					
						
							|  |  |  | vlist_realloc (vlist, n) | 
					
						
							|  |  |  |      VARLIST *vlist; | 
					
						
							|  |  |  |      int n; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (vlist == 0) | 
					
						
							|  |  |  |     return (vlist = vlist_alloc (n)); | 
					
						
							|  |  |  |   if (n > vlist->list_size) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       vlist->list_size = n; | 
					
						
							|  |  |  |       vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return vlist; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | vlist_add (vlist, var, flags) | 
					
						
							|  |  |  |      VARLIST *vlist; | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   for (i = 0; i < vlist->list_len; i++) | 
					
						
							|  |  |  |     if (STREQ (var->name, vlist->list[i]->name)) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   if (i < vlist->list_len) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (i >= vlist->list_size) | 
					
						
							|  |  |  |     vlist = vlist_realloc (vlist, vlist->list_size + 16); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vlist->list[vlist->list_len++] = var; | 
					
						
							|  |  |  |   vlist->list[vlist->list_len] = (SHELL_VAR *)NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
 | 
					
						
							|  |  |  |    variables for which FUNCTION returns a non-zero value.  A NULL value | 
					
						
							|  |  |  |    for FUNCTION means to use all variables. */ | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | map_over (function, vc) | 
					
						
							|  |  |  |      sh_var_map_func_t *function; | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *v; | 
					
						
							|  |  |  |   VARLIST *vlist; | 
					
						
							|  |  |  |   SHELL_VAR **ret; | 
					
						
							|  |  |  |   int nentries; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (nentries = 0, v = vc; v; v = v->down) | 
					
						
							|  |  |  |     nentries += HASH_ENTRIES (v->table); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (nentries == 0) | 
					
						
							|  |  |  |     return (SHELL_VAR **)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vlist = vlist_alloc (nentries); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (v = vc; v; v = v->down) | 
					
						
							|  |  |  |     flatten (v->table, function, vlist, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = vlist->list; | 
					
						
							|  |  |  |   free (vlist); | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | map_over_funcs (function) | 
					
						
							|  |  |  |      sh_var_map_func_t *function; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VARLIST *vlist; | 
					
						
							|  |  |  |   SHELL_VAR **ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0) | 
					
						
							|  |  |  |     return ((SHELL_VAR **)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vlist = vlist_alloc (HASH_ENTRIES (shell_functions)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   flatten (shell_functions, function, vlist, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = vlist->list; | 
					
						
							|  |  |  |   free (vlist); | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
 | 
					
						
							|  |  |  |    elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved | 
					
						
							|  |  |  |    for future use.  Only unique names are added to VLIST.  If FUNC is | 
					
						
							|  |  |  |    NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is | 
					
						
							|  |  |  |    NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST | 
					
						
							|  |  |  |    and FUNC are both NULL, nothing happens. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | flatten (var_hash_table, func, vlist, flags) | 
					
						
							|  |  |  |      HASH_TABLE *var_hash_table; | 
					
						
							|  |  |  |      sh_var_map_func_t *func; | 
					
						
							|  |  |  |      VARLIST *vlist; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   register BUCKET_CONTENTS *tlist; | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0)) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < var_hash_table->nbuckets; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  var = (SHELL_VAR *)tlist->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  r = func ? (*func) (var) : 1; | 
					
						
							|  |  |  | 	  if (r && vlist) | 
					
						
							|  |  |  | 	    vlist_add (vlist, var, flags); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sort_variables (array) | 
					
						
							|  |  |  |      SHELL_VAR **array; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | qsort_var_comp (var1, var2) | 
					
						
							|  |  |  |      SHELL_VAR **var1, **var2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0) | 
					
						
							|  |  |  |     result = strcmp ((*var1)->name, (*var2)->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (result); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
 | 
					
						
							|  |  |  |    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static SHELL_VAR ** | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | vapply (func) | 
					
						
							|  |  |  |      sh_var_map_func_t *func; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR **list; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   list = map_over (func, shell_variables); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (list /* && posixly_correct */) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     sort_variables (list); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (list); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
 | 
					
						
							|  |  |  |    which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */ | 
					
						
							|  |  |  | static SHELL_VAR ** | 
					
						
							|  |  |  | fapply (func) | 
					
						
							|  |  |  |      sh_var_map_func_t *func; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR **list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   list = map_over_funcs (func); | 
					
						
							|  |  |  |   if (list /* && posixly_correct */) | 
					
						
							|  |  |  |     sort_variables (list); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (list); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Create a NULL terminated array of all the shell variables. */ | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | all_shell_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (vapply ((sh_var_map_func_t *)NULL)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Create a NULL terminated array of all the shell functions. */ | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | all_shell_functions () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (fapply ((sh_var_map_func_t *)NULL)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | visible_var (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (invisible_p (var) == 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | SHELL_VAR ** | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | all_visible_functions () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (fapply (visible_var)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | SHELL_VAR ** | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | all_visible_variables () | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (vapply (visible_var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Return non-zero if the variable VAR is visible and exported.  Array
 | 
					
						
							|  |  |  |    variables cannot be exported. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | visible_and_exported (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (invisible_p (var) == 0 && exported_p (var)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | /* Candidate variables for the export environment are either valid variables
 | 
					
						
							|  |  |  |    with the export attribute or invalid variables inherited from the initial | 
					
						
							|  |  |  |    environment and simply passed through. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | export_environment_candidate (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Return non-zero if VAR is a local variable in the current context and
 | 
					
						
							|  |  |  |    is exported. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | local_and_exported (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | all_exported_variables () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (vapply (visible_and_exported)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | local_exported_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (vapply (local_and_exported)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | variable_in_context (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | all_local_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VARLIST *vlist; | 
					
						
							|  |  |  |   SHELL_VAR **ret; | 
					
						
							|  |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vc = shell_variables; | 
					
						
							|  |  |  |   for (vc = shell_variables; vc; vc = vc->down) | 
					
						
							|  |  |  |     if (vc_isfuncenv (vc) && vc->scope == variable_context) | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (vc == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("all_local_variables: no function context at current scope")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return (SHELL_VAR **)NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0) | 
					
						
							|  |  |  |     return (SHELL_VAR **)NULL; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |   vlist = vlist_alloc (HASH_ENTRIES (vc->table)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   flatten (vc->table, variable_in_context, vlist, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = vlist->list; | 
					
						
							|  |  |  |   free (vlist); | 
					
						
							|  |  |  |   if (ret) | 
					
						
							|  |  |  |     sort_variables (ret); | 
					
						
							|  |  |  |   return ret; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | /* Return non-zero if the variable VAR is visible and an array. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | visible_array_vars (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (invisible_p (var) == 0 && array_p (var)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR ** | 
					
						
							|  |  |  | all_array_variables () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (vapply (visible_array_vars)); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char ** | 
					
						
							|  |  |  | all_variables_matching_prefix (prefix) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *prefix; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR **varlist; | 
					
						
							|  |  |  |   char **rlist; | 
					
						
							|  |  |  |   int vind, rind, plen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   plen = STRLEN (prefix); | 
					
						
							|  |  |  |   varlist = all_visible_variables (); | 
					
						
							|  |  |  |   for (vind = 0; varlist && varlist[vind]; vind++) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  |   if (varlist == 0 || vind == 0) | 
					
						
							|  |  |  |     return ((char **)NULL); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   rlist = strvec_create (vind + 1); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   for (vind = rind = 0; varlist[vind]; vind++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	rlist[rind++] = savestring (varlist[vind]->name); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   rlist[rind] = (char *)0; | 
					
						
							|  |  |  |   free (varlist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return rlist; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		 Managing temporary variable scopes		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make variable NAME have VALUE in the temporary environment. */ | 
					
						
							|  |  |  | static SHELL_VAR * | 
					
						
							|  |  |  | bind_tempenv_variable (name, value) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (var) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       FREE (value_cell (var)); | 
					
						
							|  |  |  |       var_setvalue (var, savestring (value)); | 
					
						
							|  |  |  |       INVALIDATE_EXPORTSTR (var); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a variable in the temporary environment that is named NAME.
 | 
					
						
							|  |  |  |    Return the SHELL_VAR *, or NULL if not found. */ | 
					
						
							|  |  |  | SHELL_VAR * | 
					
						
							|  |  |  | find_tempenv_variable (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | char **tempvar_list; | 
					
						
							|  |  |  | int tvlist_ind; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Push the variable described by (SHELL_VAR *)DATA down to the next
 | 
					
						
							|  |  |  |    variable context from the temporary environment. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | push_temp_var (data) | 
					
						
							|  |  |  |      PTR_T data; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var, *v; | 
					
						
							|  |  |  |   HASH_TABLE *binding_table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   binding_table = shell_variables->table; | 
					
						
							|  |  |  |   if (binding_table == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (shell_variables == global_variables) | 
					
						
							|  |  |  | 	/* shouldn't happen */ | 
					
						
							|  |  |  | 	binding_table = shell_variables->table = global_variables->table = hash_create (0); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* XXX - should we set the context here?  It shouldn't matter because of how
 | 
					
						
							|  |  |  |      assign_in_env works, but might want to check. */ | 
					
						
							|  |  |  |   if (binding_table == global_variables->table)		/* XXX */ | 
					
						
							|  |  |  |     var->attributes &= ~(att_tempvar|att_propagate); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       var->attributes |= att_propagate; | 
					
						
							|  |  |  |       if  (binding_table == shell_variables->table) | 
					
						
							|  |  |  | 	shell_variables->flags |= VC_HASTMPVAR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   v->attributes |= var->attributes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (find_special_var (var->name) >= 0) | 
					
						
							|  |  |  |     tempvar_list[tvlist_ind++] = savestring (var->name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   dispose_variable (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | propagate_temp_var (data) | 
					
						
							|  |  |  |      PTR_T data; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)data; | 
					
						
							|  |  |  |   if (tempvar_p (var) && (var->attributes & att_propagate)) | 
					
						
							|  |  |  |     push_temp_var (data); | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (find_special_var (var->name) >= 0) | 
					
						
							|  |  |  | 	tempvar_list[tvlist_ind++] = savestring (var->name); | 
					
						
							|  |  |  |       dispose_variable (var); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free the storage used in the hash table for temporary
 | 
					
						
							|  |  |  |    environment variables.  PUSHF is a function to be called | 
					
						
							|  |  |  |    to free each hash table entry.  It takes care of pushing variables | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |    to previous scopes if appropriate.  PUSHF stores names of variables | 
					
						
							|  |  |  |    that require special handling (e.g., IFS) on tempvar_list, so this | 
					
						
							|  |  |  |    function can call stupidly_hack_special_variables on all the | 
					
						
							|  |  |  |    variables in the list when the temporary hash table is destroyed. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | dispose_temporary_env (pushf) | 
					
						
							|  |  |  |      sh_free_func_t *pushf; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1); | 
					
						
							|  |  |  |   tempvar_list[tvlist_ind = 0] = 0; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   hash_flush (temporary_env, pushf); | 
					
						
							|  |  |  |   hash_dispose (temporary_env); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   temporary_env = (HASH_TABLE *)NULL; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   tempvar_list[tvlist_ind] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   array_needs_making = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |   sv_ifs ("IFS");		/* XXX here for now -- check setifs in assign_in_env */   | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   for (i = 0; i < tvlist_ind; i++) | 
					
						
							|  |  |  |     stupidly_hack_special_variables (tempvar_list[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   strvec_dispose (tempvar_list); | 
					
						
							|  |  |  |   tempvar_list = 0; | 
					
						
							|  |  |  |   tvlist_ind = 0; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | dispose_used_env_vars () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (temporary_env) | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       dispose_temporary_env (propagate_temp_var); | 
					
						
							|  |  |  |       maybe_make_export_env (); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Take all of the shell variables in the temporary environment HASH_TABLE
 | 
					
						
							|  |  |  |    and make shell variables from them at the current variable context. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | merge_temporary_env () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (temporary_env) | 
					
						
							|  |  |  |     dispose_temporary_env (push_temp_var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	     Creating and manipulating the environment		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | static inline char * | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | mk_env_string (name, value, isfunc) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *name, *value; | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |      int isfunc; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |   size_t name_len, value_len; | 
					
						
							|  |  |  |   char	*p, *q; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   name_len = strlen (name); | 
					
						
							|  |  |  |   value_len = STRLEN (value); | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If we are exporting a shell function, construct the encoded function
 | 
					
						
							|  |  |  |      name. */ | 
					
						
							|  |  |  |   if (isfunc && value) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2); | 
					
						
							|  |  |  |       q = p; | 
					
						
							|  |  |  |       memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN); | 
					
						
							|  |  |  |       q += BASHFUNC_PREFLEN; | 
					
						
							|  |  |  |       memcpy (q, name, name_len); | 
					
						
							|  |  |  |       q += name_len; | 
					
						
							|  |  |  |       memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN); | 
					
						
							|  |  |  |       q += BASHFUNC_SUFFLEN; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       p = (char *)xmalloc (2 + name_len + value_len); | 
					
						
							|  |  |  |       memcpy (p, name, name_len); | 
					
						
							|  |  |  |       q = p + name_len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   q[0] = '='; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   if (value && *value) | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |     memcpy (q + 1, value, value_len + 1); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  |     q[1] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   return (p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | /* Debugging */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | valid_exportstr (v) | 
					
						
							|  |  |  |      SHELL_VAR *v; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s = v->exportstr; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   if (s == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       internal_error (_("%s has null exportstr"), v->name); | 
					
						
							|  |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   if (legal_variable_starter ((unsigned char)*s) == 0) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("invalid character %d in exportstr for %s"), *s, v->name); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   for (s = v->exportstr + 1; s && *s; s++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (*s == '=') | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	break; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       if (legal_variable_char ((unsigned char)*s) == 0) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  internal_error (_("invalid character %d in exportstr for %s"), *s, v->name); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	  return (0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (*s != '=') | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("no `=' in exportstr for %s"), v->name); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static char ** | 
					
						
							|  |  |  | make_env_array_from_var_list (vars) | 
					
						
							|  |  |  |      SHELL_VAR **vars; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   register int i, list_index; | 
					
						
							|  |  |  |   register SHELL_VAR *var; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char **list, *value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   list = strvec_create ((1 + strvec_len ((char **)vars))); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define USE_EXPORTSTR (value == var->exportstr)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0, list_index = 0; var = vars[i]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #if defined (__CYGWIN__)
 | 
					
						
							|  |  |  |       /* We don't use the exportstr stuff on Cygwin at all. */ | 
					
						
							|  |  |  |       INVALIDATE_EXPORTSTR (var); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (var->exportstr) | 
					
						
							|  |  |  | 	value = var->exportstr; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       else if (function_p (var)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	value = named_function_string ((char *)NULL, function_cell (var), 0); | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       else if (array_p (var)) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #  if ARRAY_EXPORT
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	value = array_to_assignment_string (array_cell (var)); | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | 	continue;	/* XXX array vars cannot yet be exported */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #  endif /* ARRAY_EXPORT */
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       else if (assoc_p (var)) | 
					
						
							|  |  |  | #  if 0
 | 
					
						
							|  |  |  | 	value = assoc_to_assignment_string (assoc_cell (var)); | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | 	continue;	/* XXX associative array vars cannot yet be exported */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	value = value_cell (var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (value) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	  /* Gee, I'd like to get away with not using savestring() if we're
 | 
					
						
							|  |  |  | 	     using the cached exportstr... */ | 
					
						
							|  |  |  | 	  list[list_index] = USE_EXPORTSTR ? savestring (value) | 
					
						
							| 
									
										
										
										
											2014-09-27 22:58:05 -04:00
										 |  |  | 					   : mk_env_string (var->name, value, function_p (var)); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  if (USE_EXPORTSTR == 0) | 
					
						
							|  |  |  | 	    SAVE_EXPORTSTR (var, list[list_index]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  list_index++; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #undef USE_EXPORTSTR
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0	/* not yet */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  if (array_p (var) || assoc_p (var)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    free (value); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   list[list_index] = (char *)NULL; | 
					
						
							|  |  |  |   return (list); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Make an array of assignment statements from the hash table
 | 
					
						
							|  |  |  |    HASHED_VARS which contains SHELL_VARs.  Only visible, exported | 
					
						
							|  |  |  |    variables are eligible. */ | 
					
						
							|  |  |  | static char ** | 
					
						
							|  |  |  | make_var_export_array (vcxt) | 
					
						
							|  |  |  |      VAR_CONTEXT *vcxt; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char **list; | 
					
						
							|  |  |  |   SHELL_VAR **vars; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vars = map_over (visible_and_exported, vcxt); | 
					
						
							| 
									
										
										
										
											2011-11-21 20:49:12 -05:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   vars = map_over (export_environment_candidate, vcxt); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (vars == 0) | 
					
						
							|  |  |  |     return (char **)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   list = make_env_array_from_var_list (vars); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   free (vars); | 
					
						
							|  |  |  |   return (list); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static char ** | 
					
						
							|  |  |  | make_func_export_array () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char **list; | 
					
						
							|  |  |  |   SHELL_VAR **vars; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   vars = map_over_funcs (visible_and_exported); | 
					
						
							|  |  |  |   if (vars == 0) | 
					
						
							|  |  |  |     return (char **)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   list = make_env_array_from_var_list (vars); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   free (vars); | 
					
						
							|  |  |  |   return (list); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */ | 
					
						
							|  |  |  | #define add_to_export_env(envstr,do_alloc) \
 | 
					
						
							|  |  |  | do \ | 
					
						
							|  |  |  |   { \ | 
					
						
							|  |  |  |     if (export_env_index >= (export_env_size - 1)) \ | 
					
						
							|  |  |  |       { \ | 
					
						
							|  |  |  | 	export_env_size += 16; \ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	export_env = strvec_resize (export_env, export_env_size); \ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	environ = export_env; \ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       } \ | 
					
						
							|  |  |  |     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \ | 
					
						
							|  |  |  |     export_env[export_env_index] = (char *)NULL; \ | 
					
						
							|  |  |  |   } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
 | 
					
						
							|  |  |  |    array with the same left-hand side.  Return the new EXPORT_ENV. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | char ** | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | add_or_supercede_exported_var (assign, do_alloc) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *assign; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int do_alloc; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int equal_offset; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   equal_offset = assignment (assign, 0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (equal_offset == 0) | 
					
						
							|  |  |  |     return (export_env); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   /* If this is a function, then only supersede the function definition.
 | 
					
						
							|  |  |  |      We do this by including the `=() {' in the comparison, like | 
					
						
							|  |  |  |      initialize_shell_variables does. */ | 
					
						
							|  |  |  |   if (assign[equal_offset + 1] == '(' && | 
					
						
							|  |  |  |      strncmp (assign + equal_offset + 2, ") {", 3) == 0)		/* } */ | 
					
						
							|  |  |  |     equal_offset += 4; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   for (i = 0; i < export_env_index; i++) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (STREQN (assign, export_env[i], equal_offset + 1)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	  free (export_env[i]); | 
					
						
							|  |  |  | 	  export_env[i] = do_alloc ? savestring (assign) : assign; | 
					
						
							|  |  |  | 	  return (export_env); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   add_to_export_env (assign, do_alloc); | 
					
						
							|  |  |  |   return (export_env); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | add_temp_array_to_env (temp_array, do_alloc, do_supercede) | 
					
						
							|  |  |  |      char **temp_array; | 
					
						
							|  |  |  |      int do_alloc, do_supercede; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (temp_array == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; temp_array[i]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (do_supercede) | 
					
						
							|  |  |  | 	export_env = add_or_supercede_exported_var (temp_array[i], do_alloc); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	add_to_export_env (temp_array[i], do_alloc); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (temp_array); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Make the environment array for the command about to be executed, if the
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    array needs making.  Otherwise, do nothing.  If a shell action could | 
					
						
							|  |  |  |    change the array that commands receive for their environment, then the | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    code should `array_needs_making++'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The order to add to the array is: | 
					
						
							|  |  |  |    	temporary_env | 
					
						
							|  |  |  |    	list of var contexts whose head is shell_variables | 
					
						
							|  |  |  |   	shell_functions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This is the shell variable lookup order.  We add only new variable | 
					
						
							|  |  |  |   names at each step, which allows local variables and variables in | 
					
						
							|  |  |  |   the temporary environments to shadow variables in the global (or | 
					
						
							|  |  |  |   any previous) scope. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | n_shell_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  |   int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (n = 0, vc = shell_variables; vc; vc = vc->down) | 
					
						
							|  |  |  |     n += HASH_ENTRIES (vc->table); | 
					
						
							|  |  |  |   return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:19 -05:00
										 |  |  | int | 
					
						
							|  |  |  | chkexport (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:31 -05:00
										 |  |  |   if (v && exported_p (v)) | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:19 -05:00
										 |  |  |     { | 
					
						
							|  |  |  |       array_needs_making = 1; | 
					
						
							|  |  |  |       maybe_make_export_env (); | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | void | 
					
						
							|  |  |  | maybe_make_export_env () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register char **temp_array; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int new_size; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   VAR_CONTEXT *tcxt; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (array_needs_making) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (export_env) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	strvec_flush (export_env); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Make a guess based on how many shell variables and functions we
 | 
					
						
							|  |  |  | 	 have.  Since there will always be array variables, and array | 
					
						
							|  |  |  | 	 variables are not (yet) exported, this will always be big enough | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	 for the exported variables and functions. */ | 
					
						
							|  |  |  |       new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 + | 
					
						
							|  |  |  | 		 HASH_ENTRIES (temporary_env); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (new_size > export_env_size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  export_env_size = new_size; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  export_env = strvec_resize (export_env, export_env_size); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  environ = export_env; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       export_env[export_env_index = 0] = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |       /* Make a dummy variable context from the temporary_env, stick it on
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	 the front of shell_variables, call make_var_export_array on the | 
					
						
							|  |  |  | 	 whole thing to flatten it, and convert the list of SHELL_VAR *s | 
					
						
							|  |  |  | 	 to the form needed by the environment. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (temporary_env) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  tcxt = new_var_context ((char *)NULL, 0); | 
					
						
							|  |  |  | 	  tcxt->table = temporary_env; | 
					
						
							|  |  |  | 	  tcxt->down = shell_variables; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	tcxt = shell_variables; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |        | 
					
						
							|  |  |  |       temp_array = make_var_export_array (tcxt); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (temp_array) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	add_temp_array_to_env (temp_array, 0, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (tcxt != shell_variables) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	free (tcxt); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #if defined (RESTRICTED_SHELL)
 | 
					
						
							|  |  |  |       /* Restricted shells may not export shell functions. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       temp_array = restricted ? (char **)0 : make_func_export_array (); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       temp_array = make_func_export_array (); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (temp_array) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	add_temp_array_to_env (temp_array, 0, 0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       array_needs_making = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
 | 
					
						
							|  |  |  |    we will need to remake the exported environment every time we | 
					
						
							|  |  |  |    change directories.  `_' is always put into the environment for | 
					
						
							|  |  |  |    every external command, so without special treatment it will always | 
					
						
							|  |  |  |    cause the environment to be remade. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    If there is no other reason to make the exported environment, we can | 
					
						
							|  |  |  |    just update the variables in place and mark the exported environment | 
					
						
							|  |  |  |    as no longer needing a remake. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | update_export_env_inplace (env_prefix, preflen, value) | 
					
						
							|  |  |  |      char *env_prefix; | 
					
						
							|  |  |  |      int preflen; | 
					
						
							|  |  |  |      char *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *evar; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   evar = (char *)xmalloc (STRLEN (value) + preflen + 1); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   strcpy (evar, env_prefix); | 
					
						
							|  |  |  |   if (value) | 
					
						
							|  |  |  |     strcpy (evar + preflen, value); | 
					
						
							|  |  |  |   export_env = add_or_supercede_exported_var (evar, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* We always put _ in the environment as the name of this command. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | put_command_name_into_env (command_name) | 
					
						
							|  |  |  |      char *command_name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   update_export_env_inplace ("_=", 2, command_name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		      Managing variable contexts		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Allocate and return a new variable context with NAME and FLAGS.
 | 
					
						
							|  |  |  |    NAME can be NULL. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | VAR_CONTEXT * | 
					
						
							|  |  |  | new_var_context (name, flags) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT)); | 
					
						
							|  |  |  |   vc->name = name ? savestring (name) : (char *)NULL; | 
					
						
							|  |  |  |   vc->scope = variable_context; | 
					
						
							|  |  |  |   vc->flags = flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vc->up = vc->down = (VAR_CONTEXT *)NULL; | 
					
						
							|  |  |  |   vc->table = (HASH_TABLE *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return vc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free a variable context and its data, including the hash table.  Dispose
 | 
					
						
							|  |  |  |    all of the variables. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | dispose_var_context (vc) | 
					
						
							|  |  |  |      VAR_CONTEXT *vc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   FREE (vc->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (vc->table) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       delete_all_variables (vc->table); | 
					
						
							|  |  |  |       hash_dispose (vc->table); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (vc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set VAR's scope level to the current variable context. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | set_context (var) | 
					
						
							|  |  |  |      SHELL_VAR *var; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (var->context = variable_context); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
 | 
					
						
							|  |  |  |    temporary variables, and push it onto shell_variables.  This is | 
					
						
							|  |  |  |    for shell functions. */ | 
					
						
							|  |  |  | VAR_CONTEXT * | 
					
						
							|  |  |  | push_var_context (name, flags, tempvars) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  |      HASH_TABLE *tempvars; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *vc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vc = new_var_context (name, flags); | 
					
						
							|  |  |  |   vc->table = tempvars; | 
					
						
							|  |  |  |   if (tempvars) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Have to do this because the temp environment was created before
 | 
					
						
							|  |  |  | 	 variable_context was incremented. */ | 
					
						
							|  |  |  |       flatten (tempvars, set_context, (VARLIST *)NULL, 0); | 
					
						
							|  |  |  |       vc->flags |= VC_HASTMPVAR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   vc->down = shell_variables; | 
					
						
							|  |  |  |   shell_variables->up = vc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (shell_variables = vc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | push_func_var (data) | 
					
						
							|  |  |  |      PTR_T data; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var, *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate))) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-11-21 20:57:16 -05:00
										 |  |  |       /* Make sure we have a hash table to store the variable in while it is
 | 
					
						
							|  |  |  | 	 being propagated down to the global variables table.  Create one if | 
					
						
							|  |  |  | 	 we have to */ | 
					
						
							|  |  |  |       if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0) | 
					
						
							|  |  |  | 	shell_variables->table = hash_create (0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* XXX - should we set v->context here? */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (shell_variables == global_variables) | 
					
						
							|  |  |  | 	var->attributes &= ~(att_tempvar|att_propagate); | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 	shell_variables->flags |= VC_HASTMPVAR; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       v->attributes |= var->attributes; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     stupidly_hack_special_variables (var->name);	/* XXX */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Pop the top context off of VCXT and dispose of it, returning the rest of
 | 
					
						
							|  |  |  |    the stack. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | pop_var_context () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *ret, *vcxt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vcxt = shell_variables; | 
					
						
							|  |  |  |   if (vc_isfuncenv (vcxt) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("pop_var_context: head of shell_variables not a function context")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ret = vcxt->down) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ret->up = (VAR_CONTEXT *)NULL; | 
					
						
							|  |  |  |       shell_variables = ret; | 
					
						
							|  |  |  |       if (vcxt->table) | 
					
						
							|  |  |  | 	hash_flush (vcxt->table, push_func_var); | 
					
						
							|  |  |  |       dispose_var_context (vcxt); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     internal_error (_("pop_var_context: no global_variables context")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
 | 
					
						
							|  |  |  |    all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | delete_all_contexts (vcxt) | 
					
						
							|  |  |  |      VAR_CONTEXT *vcxt; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *v, *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (v = vcxt; v != global_variables; v = t) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = v->down; | 
					
						
							|  |  |  |       dispose_var_context (v); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     }     | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   delete_all_variables (global_variables->table); | 
					
						
							|  |  |  |   shell_variables = global_variables; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	   Pushing and Popping temporary variable scopes	    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VAR_CONTEXT * | 
					
						
							|  |  |  | push_scope (flags, tmpvars) | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  |      HASH_TABLE *tmpvars; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (push_var_context ((char *)NULL, flags, tmpvars)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | push_exported_var (data) | 
					
						
							|  |  |  |      PTR_T data; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *var, *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var = (SHELL_VAR *)data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If a temp var had its export attribute set, or it's marked to be
 | 
					
						
							|  |  |  |      propagated, bind it in the previous scope before disposing it. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   /* XXX - This isn't exactly right, because all tempenv variables have the
 | 
					
						
							|  |  |  |     export attribute set. */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (exported_p (var) || (var->attributes & att_propagate)) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       var->attributes &= ~att_tempvar;		/* XXX */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (shell_variables == global_variables) | 
					
						
							|  |  |  | 	var->attributes &= ~att_propagate; | 
					
						
							|  |  |  |       v->attributes |= var->attributes; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     stupidly_hack_special_variables (var->name);	/* XXX */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   dispose_variable (var); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | pop_scope (is_special) | 
					
						
							|  |  |  |      int is_special; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   VAR_CONTEXT *vcxt, *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vcxt = shell_variables; | 
					
						
							|  |  |  |   if (vc_istempscope (vcxt) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       internal_error (_("pop_scope: head of shell_variables not a temporary environment scope")); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = vcxt->down; | 
					
						
							|  |  |  |   if (ret) | 
					
						
							|  |  |  |     ret->up = (VAR_CONTEXT *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   shell_variables = ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Now we can take care of merging variables in VCXT into set of scopes
 | 
					
						
							|  |  |  |      whose head is RET (shell_variables). */ | 
					
						
							|  |  |  |   FREE (vcxt->name); | 
					
						
							|  |  |  |   if (vcxt->table) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (is_special) | 
					
						
							|  |  |  | 	hash_flush (vcxt->table, push_func_var); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	hash_flush (vcxt->table, push_exported_var); | 
					
						
							|  |  |  |       hash_dispose (vcxt->table); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   free (vcxt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sv_ifs ("IFS");	/* XXX here for now */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		 Pushing and Popping function contexts		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL; | 
					
						
							|  |  |  | static int dollar_arg_stack_slots; | 
					
						
							|  |  |  | static int dollar_arg_stack_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* XXX - we might want to consider pushing and popping the `getopts' state
 | 
					
						
							|  |  |  |    when we modify the positional parameters. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | push_context (name, is_subshell, tempvars) | 
					
						
							|  |  |  |      char *name;	/* function name */ | 
					
						
							|  |  |  |      int is_subshell; | 
					
						
							|  |  |  |      HASH_TABLE *tempvars; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (is_subshell == 0) | 
					
						
							|  |  |  |     push_dollar_vars (); | 
					
						
							|  |  |  |   variable_context++; | 
					
						
							|  |  |  |   push_var_context (name, VC_FUNCENV, tempvars); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Only called when subshell == 0, so we don't need to check, and can
 | 
					
						
							|  |  |  |    unconditionally pop the dollar vars off the stack. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | pop_context () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   pop_dollar_vars (); | 
					
						
							|  |  |  |   variable_context--; | 
					
						
							|  |  |  |   pop_var_context (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   sv_ifs ("IFS");		/* XXX here for now */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Save the existing positional parameters on a stack. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | push_dollar_vars () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       dollar_arg_stack = (WORD_LIST **) | 
					
						
							|  |  |  | 	xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 		  * sizeof (WORD_LIST *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args (); | 
					
						
							|  |  |  |   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Restore the positional parameters from our stack. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | pop_dollar_vars () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!dollar_arg_stack || dollar_arg_stack_index == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1); | 
					
						
							|  |  |  |   dispose_words (dollar_arg_stack[dollar_arg_stack_index]); | 
					
						
							|  |  |  |   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL; | 
					
						
							|  |  |  |   set_dollar_vars_unchanged (); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | void | 
					
						
							|  |  |  | dispose_saved_dollar_vars () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!dollar_arg_stack || dollar_arg_stack_index == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   dispose_words (dollar_arg_stack[dollar_arg_stack_index]); | 
					
						
							|  |  |  |   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Manipulate the special BASH_ARGV and BASH_ARGC variables. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | push_args (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (ARRAY_VARS) && defined (DEBUGGER)
 | 
					
						
							|  |  |  |   SHELL_VAR *bash_argv_v, *bash_argc_v; | 
					
						
							|  |  |  |   ARRAY *bash_argv_a, *bash_argc_a; | 
					
						
							|  |  |  |   WORD_LIST *l; | 
					
						
							|  |  |  |   arrayind_t i; | 
					
						
							|  |  |  |   char *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a); | 
					
						
							|  |  |  |   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (l = list, i = 0; l; l = l->next, i++) | 
					
						
							|  |  |  |     array_push (bash_argv_a, l->word->word); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   t = itos (i); | 
					
						
							|  |  |  |   array_push (bash_argc_a, t); | 
					
						
							|  |  |  |   free (t); | 
					
						
							|  |  |  | #endif /* ARRAY_VARS && DEBUGGER */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
 | 
					
						
							|  |  |  |    array and use that value as the count of elements to remove from | 
					
						
							|  |  |  |    BASH_ARGV. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | pop_args () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (ARRAY_VARS) && defined (DEBUGGER)
 | 
					
						
							|  |  |  |   SHELL_VAR *bash_argv_v, *bash_argc_v; | 
					
						
							|  |  |  |   ARRAY *bash_argv_a, *bash_argc_a; | 
					
						
							|  |  |  |   ARRAY_ELEMENT *ce; | 
					
						
							|  |  |  |   intmax_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a); | 
					
						
							|  |  |  |   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ce = array_shift (bash_argc_a, 1, 0); | 
					
						
							|  |  |  |   if (ce == 0 || legal_number (element_value (ce), &i) == 0) | 
					
						
							|  |  |  |     i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for ( ; i > 0; i--) | 
					
						
							|  |  |  |     array_pop (bash_argv_a); | 
					
						
							|  |  |  |   array_dispose_element (ce); | 
					
						
							|  |  |  | #endif /* ARRAY_VARS && DEBUGGER */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /*************************************************
 | 
					
						
							|  |  |  |  *						 * | 
					
						
							|  |  |  |  *	Functions to manage special variables	 * | 
					
						
							|  |  |  |  *						 * | 
					
						
							|  |  |  |  *************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Extern declarations for variables this code has to manage. */ | 
					
						
							|  |  |  | extern int eof_encountered, eof_encountered_limit, ignoreeof; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | extern int hostname_list_initialized; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* An alist of name.function for each special variable.  Most of the
 | 
					
						
							|  |  |  |    functions don't do much, and in fact, this would be faster with a | 
					
						
							|  |  |  |    switch statement, but by the end of this file, I am sick of switch | 
					
						
							|  |  |  |    statements. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* This table will be sorted with qsort() the first time it's accessed. */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | struct name_and_function { | 
					
						
							|  |  |  |   char *name; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   sh_sv_func_t *function; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static struct name_and_function special_vars[] = { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   { "BASH_COMPAT", sv_shcompat }, | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |   { "BASH_XTRACEFD", sv_xtracefd }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  |   { "CHILD_MAX", sv_childmax }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | #  if defined (STRICT_POSIX)
 | 
					
						
							|  |  |  |   { "COLUMNS", sv_winsize }, | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  |   { "COMP_WORDBREAKS", sv_comp_wordbreaks }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   { "FUNCNEST", sv_funcnest }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   { "GLOBIGNORE", sv_globignore }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   { "HISTCONTROL", sv_history_control }, | 
					
						
							|  |  |  |   { "HISTFILESIZE", sv_histsize }, | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   { "HISTIGNORE", sv_histignore }, | 
					
						
							|  |  |  |   { "HISTSIZE", sv_histsize }, | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   { "HISTTIMEFORMAT", sv_histtimefmt }, | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (__CYGWIN__)
 | 
					
						
							|  |  |  |   { "HOME", sv_home }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   { "HOSTFILE", sv_hostfile }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   { "IFS", sv_ifs }, | 
					
						
							|  |  |  |   { "IGNOREEOF", sv_ignoreeof }, | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   { "LANG", sv_locale }, | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   { "LC_ALL", sv_locale }, | 
					
						
							|  |  |  |   { "LC_COLLATE", sv_locale }, | 
					
						
							|  |  |  |   { "LC_CTYPE", sv_locale }, | 
					
						
							|  |  |  |   { "LC_MESSAGES", sv_locale }, | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   { "LC_NUMERIC", sv_locale }, | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   { "LC_TIME", sv_locale }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE) && defined (STRICT_POSIX)
 | 
					
						
							|  |  |  |   { "LINES", sv_winsize }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   { "MAIL", sv_mail }, | 
					
						
							|  |  |  |   { "MAILCHECK", sv_mail }, | 
					
						
							|  |  |  |   { "MAILPATH", sv_mail }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { "OPTERR", sv_opterr }, | 
					
						
							|  |  |  |   { "OPTIND", sv_optind }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { "PATH", sv_path }, | 
					
						
							|  |  |  |   { "POSIXLY_CORRECT", sv_strict_posix }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   { "TERM", sv_terminal }, | 
					
						
							|  |  |  |   { "TERMCAP", sv_terminal }, | 
					
						
							|  |  |  |   { "TERMINFO", sv_terminal }, | 
					
						
							|  |  |  | #endif /* READLINE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { "TEXTDOMAIN", sv_locale }, | 
					
						
							|  |  |  |   { "TEXTDOMAINDIR", sv_locale }, | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:19 -05:00
										 |  |  | #if defined (HAVE_TZSET)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   { "TZ", sv_tz }, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HISTORY) && defined (BANG_HISTORY)
 | 
					
						
							|  |  |  |   { "histchars", sv_histchars }, | 
					
						
							|  |  |  | #endif /* HISTORY && BANG_HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { "ignoreeof", sv_ignoreeof }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   { (char *)0, (sh_sv_func_t *)0 } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #define N_SPECIAL_VARS	(sizeof (special_vars) / sizeof (special_vars[0]) - 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | sv_compare (sv1, sv2) | 
					
						
							|  |  |  |      struct name_and_function *sv1, *sv2; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((r = sv1->name[0] - sv2->name[0]) == 0) | 
					
						
							|  |  |  |     r = strcmp (sv1->name, sv2->name); | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | find_special_var (name) | 
					
						
							|  |  |  |      const char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i, r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; special_vars[i].name; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       r = special_vars[i].name[0] - name[0]; | 
					
						
							|  |  |  |       if (r == 0) | 
					
						
							|  |  |  | 	r = strcmp (special_vars[i].name, name); | 
					
						
							|  |  |  |       if (r == 0) | 
					
						
							|  |  |  | 	return i; | 
					
						
							|  |  |  |       else if (r > 0) | 
					
						
							|  |  |  | 	/* Can't match any of rest of elements in sorted list.  Take this out
 | 
					
						
							|  |  |  | 	   if it causes problems in certain environments. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	break; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* The variable in NAME has just had its state changed.  Check to see if it
 | 
					
						
							|  |  |  |    is one of the special ones where something special happens. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | stupidly_hack_special_variables (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   static int sv_sorted = 0; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (sv_sorted == 0)	/* shouldn't need, but it's fairly cheap. */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]), | 
					
						
							|  |  |  | 		(QSFUNC *)sv_compare); | 
					
						
							|  |  |  |       sv_sorted = 1; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   i = find_special_var (name); | 
					
						
							|  |  |  |   if (i != -1) | 
					
						
							|  |  |  |     (*(special_vars[i].function)) (name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Special variables that need hooks to be run when they are unset as part
 | 
					
						
							|  |  |  |    of shell reinitialization should have their sv_ functions run here. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | reinit_special_variables () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   sv_comp_wordbreaks ("COMP_WORDBREAKS"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   sv_globignore ("GLOBIGNORE"); | 
					
						
							|  |  |  |   sv_opterr ("OPTERR"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sv_ifs (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable ("IFS"); | 
					
						
							|  |  |  |   setifs (v); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What to do just after the PATH variable has changed. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_path (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* hash -r */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   phash_flush (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What to do just after one of the MAILxxxx variables has changed.  NAME
 | 
					
						
							|  |  |  |    is the name of the variable.  This is called with NAME set to one of | 
					
						
							|  |  |  |    MAIL, MAILCHECK, or MAILPATH.  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_mail (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* If the time interval for checking the files has changed, then
 | 
					
						
							|  |  |  |      reset the mail timer.  Otherwise, one of the pathname vars | 
					
						
							|  |  |  |      to the users mailbox has changed, so rebuild the array of | 
					
						
							|  |  |  |      filenames. */ | 
					
						
							|  |  |  |   if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */ | 
					
						
							|  |  |  |     reset_mail_timer (); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free_mail_files (); | 
					
						
							|  |  |  |       remember_mail_dates (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | void | 
					
						
							|  |  |  | sv_funcnest (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   intmax_t num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							|  |  |  |     funcnest_max = 0; | 
					
						
							|  |  |  |   else if (legal_number (value_cell (v), &num) == 0) | 
					
						
							|  |  |  |     funcnest_max = 0; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     funcnest_max = num; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* What to do when GLOBIGNORE changes. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_globignore (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (privileged_mode == 0) | 
					
						
							|  |  |  |     setup_glob_ignore (name); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sv_comp_wordbreaks (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *sv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sv = find_variable (name); | 
					
						
							|  |  |  |   if (sv == 0) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |     reset_completer_word_break_chars (); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* What to do just after one of the TERMxxx variables has changed.
 | 
					
						
							|  |  |  |    If we are an interactive shell, then try to reset the terminal | 
					
						
							|  |  |  |    information in readline. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_terminal (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (interactive_shell && no_line_editing == 0) | 
					
						
							|  |  |  |     rl_reset_terminal (get_string_value ("TERM")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_hostfile (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							|  |  |  |     clear_hostname_list (); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     hostname_list_initialized = 0; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (STRICT_POSIX)
 | 
					
						
							|  |  |  | /* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
 | 
					
						
							|  |  |  |    found in the initial environment) to override the terminal size reported by | 
					
						
							|  |  |  |    the kernel. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_winsize (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   intmax_t xd; | 
					
						
							|  |  |  |   int d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0 || var_isnull (v)) | 
					
						
							|  |  |  |     rl_reset_screen_size (); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (legal_number (value_cell (v), &xd) == 0) | 
					
						
							|  |  |  | 	return; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       winsize_assignment = 1; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       d = xd;			/* truncate */ | 
					
						
							|  |  |  |       if (name[0] == 'L')	/* LINES */ | 
					
						
							|  |  |  | 	rl_set_screen_size (d, -1); | 
					
						
							|  |  |  |       else			/* COLUMNS */ | 
					
						
							|  |  |  | 	rl_set_screen_size (-1, d); | 
					
						
							|  |  |  |       winsize_assignment = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* STRICT_POSIX */
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif /* READLINE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | /* Update the value of HOME in the export environment so tilde expansion will
 | 
					
						
							|  |  |  |    work on cygwin. */ | 
					
						
							|  |  |  | #if defined (__CYGWIN__)
 | 
					
						
							|  |  |  | sv_home (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   array_needs_making = 1; | 
					
						
							|  |  |  |   maybe_make_export_env (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | /* What to do after the HISTSIZE or HISTFILESIZE variables change.
 | 
					
						
							|  |  |  |    If there is a value for this HISTSIZE (and it is numeric), then stifle | 
					
						
							|  |  |  |    the history.  Otherwise, if there is NO value for this variable, | 
					
						
							|  |  |  |    unstifle the history.  If name is HISTFILESIZE, and its value is | 
					
						
							|  |  |  |    numeric, truncate the history file to hold no more than that many | 
					
						
							|  |  |  |    lines. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_histsize (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *temp; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t num; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   int hmax; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   temp = get_string_value (name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (temp && *temp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (legal_number (temp, &num)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	  hmax = num; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  if (hmax < 0 && name[4] == 'S') | 
					
						
							|  |  |  | 	    unstifle_history ();	/* unstifle history if HISTSIZE < 0 */ | 
					
						
							|  |  |  | 	  else if (name[4] == 'S') | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	      stifle_history (hmax); | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	      hmax = where_history (); | 
					
						
							|  |  |  | 	      if (history_lines_this_session > hmax) | 
					
						
							|  |  |  | 		history_lines_this_session = hmax; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	  else if (hmax >= 0)	/* truncate HISTFILE if HISTFILESIZE >= 0 */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	      history_truncate_file (get_string_value ("HISTFILE"), hmax); | 
					
						
							|  |  |  | 	      if (hmax <= history_lines_in_file) | 
					
						
							|  |  |  | 		history_lines_in_file = hmax; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (name[4] == 'S') | 
					
						
							|  |  |  |     unstifle_history (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What to do after the HISTIGNORE variable changes. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_histignore (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   setup_history_ignore (name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What to do after the HISTCONTROL variable changes. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_history_control (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *temp; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   char *val; | 
					
						
							|  |  |  |   int tptr; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   history_control = 0; | 
					
						
							|  |  |  |   temp = get_string_value (name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   if (temp == 0 || *temp == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tptr = 0; | 
					
						
							|  |  |  |   while (val = extract_colon_unit (temp, &tptr)) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (STREQ (val, "ignorespace")) | 
					
						
							|  |  |  | 	history_control |= HC_IGNSPACE; | 
					
						
							|  |  |  |       else if (STREQ (val, "ignoredups")) | 
					
						
							|  |  |  | 	history_control |= HC_IGNDUPS; | 
					
						
							|  |  |  |       else if (STREQ (val, "ignoreboth")) | 
					
						
							|  |  |  | 	history_control |= HC_IGNBOTH; | 
					
						
							|  |  |  |       else if (STREQ (val, "erasedups")) | 
					
						
							|  |  |  | 	history_control |= HC_ERASEDUPS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       free (val); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (BANG_HISTORY)
 | 
					
						
							|  |  |  | /* Setting/unsetting of the history expansion character. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_histchars (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp = get_string_value (name); | 
					
						
							|  |  |  |   if (temp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       history_expansion_char = *temp; | 
					
						
							|  |  |  |       if (temp[0] && temp[1]) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  history_subst_char = temp[1]; | 
					
						
							|  |  |  | 	  if (temp[2]) | 
					
						
							|  |  |  | 	      history_comment_char = temp[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       history_expansion_char = '!'; | 
					
						
							|  |  |  |       history_subst_char = '^'; | 
					
						
							|  |  |  |       history_comment_char = '#'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* BANG_HISTORY */
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_histtimefmt (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   if (v = find_variable (name)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (history_comment_char == 0) | 
					
						
							|  |  |  | 	history_comment_char = '#'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   history_write_timestamps = (v != 0); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:19 -05:00
										 |  |  | #if defined (HAVE_TZSET)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | void | 
					
						
							|  |  |  | sv_tz (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-22 20:00:19 -05:00
										 |  |  |   if (chkexport (name)) | 
					
						
							|  |  |  |     tzset (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* If the variable exists, then the value of it can be the number
 | 
					
						
							|  |  |  |    of times we actually ignore the EOF.  The default is small, | 
					
						
							|  |  |  |    (smaller than csh, anyway). */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_ignoreeof (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *tmp_var; | 
					
						
							|  |  |  |   char *temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   eof_encountered = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tmp_var = find_variable (name); | 
					
						
							|  |  |  |   ignoreeof = tmp_var != 0; | 
					
						
							|  |  |  |   temp = tmp_var ? value_cell (tmp_var) : (char *)NULL; | 
					
						
							|  |  |  |   if (temp) | 
					
						
							|  |  |  |     eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10; | 
					
						
							|  |  |  |   set_shellopts ();	/* make sure `ignoreeof' is/is not in $SHELLOPTS */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_optind (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *tt; | 
					
						
							|  |  |  |   int s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tt = get_string_value ("OPTIND"); | 
					
						
							|  |  |  |   if (tt && *tt) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       s = atoi (tt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* According to POSIX, setting OPTIND=1 resets the internal state
 | 
					
						
							|  |  |  | 	 of getopt (). */ | 
					
						
							|  |  |  |       if (s < 0 || s == 1) | 
					
						
							|  |  |  | 	s = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     s = 0; | 
					
						
							|  |  |  |   getopts_reset (s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_opterr (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *tt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tt = get_string_value ("OPTERR"); | 
					
						
							|  |  |  |   sh_opterr = (tt && *tt) ? atoi (tt) : 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_strict_posix (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SET_INT_VAR (name, posixly_correct); | 
					
						
							|  |  |  |   posix_initialize (posixly_correct); | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   if (interactive_shell) | 
					
						
							|  |  |  |     posix_readline_initialize (posixly_correct); | 
					
						
							|  |  |  | #endif /* READLINE */
 | 
					
						
							|  |  |  |   set_shellopts ();	/* make sure `posix' is/is not in $SHELLOPTS */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_locale (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *v; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   int r; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   v = get_string_value (name); | 
					
						
							|  |  |  |   if (name[0] == 'L' && name[1] == 'A')	/* LANG */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     r = set_lang (name, v); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     r = set_locale_var (name, v);		/* LC_*, TEXTDOMAIN* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 1
 | 
					
						
							|  |  |  |   if (r == 0 && posixly_correct) | 
					
						
							|  |  |  |     last_command_exit_value = 1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | set_pipestatus_array (ps, nproc) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |      int *ps; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int nproc; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   ARRAY *a; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   ARRAY_ELEMENT *ae; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   char *t, tbuf[INT_STRLEN_BOUND(int) + 1]; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable ("PIPESTATUS"); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							|  |  |  |     v = make_new_array_variable ("PIPESTATUS"); | 
					
						
							|  |  |  |   if (array_p (v) == 0) | 
					
						
							|  |  |  |     return;		/* Do nothing if not an array variable. */ | 
					
						
							|  |  |  |   a = array_cell (v); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (a == 0 || array_num_elements (a) == 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       for (i = 0; i < nproc; i++)	/* was ps[i] != -1, not i < nproc */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  t = inttostr (ps[i], tbuf, sizeof (tbuf)); | 
					
						
							|  |  |  | 	  array_insert (a, i, t); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Fast case */ | 
					
						
							|  |  |  |   if (array_num_elements (a) == nproc && nproc == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ae = element_forw (a->head); | 
					
						
							|  |  |  |       free (element_value (ae)); | 
					
						
							|  |  |  |       ae->value = itos (ps[0]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (array_num_elements (a) <= nproc) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* modify in array_num_elements members in place, then add */ | 
					
						
							|  |  |  |       ae = a->head; | 
					
						
							|  |  |  |       for (i = 0; i < array_num_elements (a); i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  ae = element_forw (ae); | 
					
						
							|  |  |  | 	  free (element_value (ae)); | 
					
						
							|  |  |  | 	  ae->value = itos (ps[i]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       /* add any more */ | 
					
						
							|  |  |  |       for ( ; i < nproc; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  t = inttostr (ps[i], tbuf, sizeof (tbuf)); | 
					
						
							|  |  |  | 	  array_insert (a, i, t); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* deleting elements.  it's faster to rebuild the array. */	   | 
					
						
							|  |  |  |       array_flush (a); | 
					
						
							|  |  |  |       for (i = 0; ps[i] != -1; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  t = inttostr (ps[i], tbuf, sizeof (tbuf)); | 
					
						
							|  |  |  | 	  array_insert (a, i, t); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ARRAY * | 
					
						
							|  |  |  | save_pipestatus_array () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   ARRAY *a, *a2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable ("PIPESTATUS"); | 
					
						
							|  |  |  |   if (v == 0 || array_p (v) == 0 || array_cell (v) == 0) | 
					
						
							|  |  |  |     return ((ARRAY *)NULL); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |   a = array_cell (v); | 
					
						
							|  |  |  |   a2 = array_copy (array_cell (v)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return a2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | restore_pipestatus_array (a) | 
					
						
							|  |  |  |      ARRAY *a; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   ARRAY *a2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable ("PIPESTATUS"); | 
					
						
							|  |  |  |   /* XXX - should we still assign even if existing value is NULL? */ | 
					
						
							|  |  |  |   if (v == 0 || array_p (v) == 0 || array_cell (v) == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   a2 = array_cell (v); | 
					
						
							|  |  |  |   var_setarray (v, a);  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   array_dispose (a2); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | set_pipestatus_from_exit (s) | 
					
						
							|  |  |  |      int s; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   static int v[2] = { 0, -1 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v[0] = s; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   set_pipestatus_array (v, 1); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_xtracefd (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   char *t, *e; | 
					
						
							|  |  |  |   int fd; | 
					
						
							|  |  |  |   FILE *fp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       xtrace_reset (); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   t = value_cell (v); | 
					
						
							|  |  |  |   if (t == 0 || *t == 0) | 
					
						
							|  |  |  |     xtrace_reset (); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       fd = (int)strtol (t, &e, 10); | 
					
						
							|  |  |  |       if (e != t && *e == '\0' && sh_validfd (fd)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  fp = fdopen (fd, "w"); | 
					
						
							|  |  |  | 	  if (fp == 0) | 
					
						
							|  |  |  | 	    internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v)); | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    xtrace_set (fd, fp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MIN_COMPAT_LEVEL 31
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_shcompat (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   char *val; | 
					
						
							|  |  |  |   int tens, ones, compatval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = find_variable (name); | 
					
						
							|  |  |  |   if (v == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       shell_compatibility_level = DEFAULT_COMPAT_LEVEL; | 
					
						
							|  |  |  |       set_compatibility_opts (); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   val = value_cell (v); | 
					
						
							|  |  |  |   if (val == 0 || *val == '\0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       shell_compatibility_level = DEFAULT_COMPAT_LEVEL; | 
					
						
							|  |  |  |       set_compatibility_opts (); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   /* Handle decimal-like compatibility version specifications: 4.2 */ | 
					
						
							|  |  |  |   if (isdigit (val[0]) && val[1] == '.' && isdigit (val[2]) && val[3] == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       tens = val[0] - '0'; | 
					
						
							|  |  |  |       ones = val[2] - '0'; | 
					
						
							|  |  |  |       compatval = tens*10 + ones; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   /* Handle integer-like compatibility version specifications: 42 */ | 
					
						
							|  |  |  |   else if (isdigit (val[0]) && isdigit (val[1]) && val[2] == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       tens = val[0] - '0'; | 
					
						
							|  |  |  |       ones = val[1] - '0'; | 
					
						
							|  |  |  |       compatval = tens*10 + ones; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | compat_error: | 
					
						
							|  |  |  |       internal_error (_("%s: %s: compatibility value out of range"), name, val); | 
					
						
							|  |  |  |       shell_compatibility_level = DEFAULT_COMPAT_LEVEL; | 
					
						
							|  |  |  |       set_compatibility_opts (); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL) | 
					
						
							|  |  |  |     goto compat_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   shell_compatibility_level = compatval; | 
					
						
							|  |  |  |   set_compatibility_opts (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sv_childmax (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *tt; | 
					
						
							|  |  |  |   int s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tt = get_string_value (name); | 
					
						
							|  |  |  |   s = (tt && *tt) ? atoi (tt) : 0; | 
					
						
							|  |  |  |   set_maxchild (s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |