1This file is source.def, from which is created source.c. 2It implements the builtins "." and "source" in Bash. 3 4Copyright (C) 1987-2020 Free Software Foundation, Inc. 5 6This file is part of GNU Bash, the Bourne Again SHell. 7 8Bash is free software: you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation, either version 3 of the License, or 11(at your option) any later version. 12 13Bash is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with Bash. If not, see <http://www.gnu.org/licenses/>. 20 21$PRODUCES source.c 22 23$BUILTIN source 24$FUNCTION source_builtin 25$SHORT_DOC source filename [arguments] 26Execute commands from a file in the current shell. 27 28Read and execute commands from FILENAME in the current shell. The 29entries in $PATH are used to find the directory containing FILENAME. 30If any ARGUMENTS are supplied, they become the positional parameters 31when FILENAME is executed. 32 33Exit Status: 34Returns the status of the last command executed in FILENAME; fails if 35FILENAME cannot be read. 36$END 37 38$BUILTIN . 39$DOCNAME dot 40$FUNCTION source_builtin 41$SHORT_DOC . filename [arguments] 42Execute commands from a file in the current shell. 43 44Read and execute commands from FILENAME in the current shell. The 45entries in $PATH are used to find the directory containing FILENAME. 46If any ARGUMENTS are supplied, they become the positional parameters 47when FILENAME is executed. 48 49Exit Status: 50Returns the status of the last command executed in FILENAME; fails if 51FILENAME cannot be read. 52$END 53 54#include <config.h> 55 56#include "../bashtypes.h" 57#include "posixstat.h" 58#include "filecntl.h" 59#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H) 60# include <sys/file.h> 61#endif 62#include <errno.h> 63 64#if defined (HAVE_UNISTD_H) 65# include <unistd.h> 66#endif 67 68#include "../bashansi.h" 69#include "../bashintl.h" 70 71#include "../shell.h" 72#include "../execute_cmd.h" 73#include "../flags.h" 74#include "../findcmd.h" 75#include "common.h" 76#include "bashgetopt.h" 77#include "../trap.h" 78 79#if !defined (errno) 80extern int errno; 81#endif /* !errno */ 82 83static void maybe_pop_dollar_vars PARAMS((void)); 84 85/* If non-zero, `.' uses $PATH to look up the script to be sourced. */ 86int source_uses_path = 1; 87 88/* If non-zero, `.' looks in the current directory if the filename argument 89 is not found in the $PATH. */ 90int source_searches_cwd = 1; 91 92/* If this . script is supplied arguments, we save the dollar vars and 93 replace them with the script arguments for the duration of the script's 94 execution. If the script does not change the dollar vars, we restore 95 what we saved. If the dollar vars are changed in the script, and we are 96 not executing a shell function, we leave the new values alone and free 97 the saved values. */ 98static void 99maybe_pop_dollar_vars () 100{ 101 if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN)) 102 dispose_saved_dollar_vars (); 103 else 104 pop_dollar_vars (); 105 if (debugging_mode) 106 pop_args (); /* restore BASH_ARGC and BASH_ARGV */ 107 set_dollar_vars_unchanged (); 108 invalidate_cached_quoted_dollar_at (); /* just invalidate to be safe */ 109} 110 111/* Read and execute commands from the file passed as argument. Guess what. 112 This cannot be done in a subshell, since things like variable assignments 113 take place in there. So, I open the file, place it into a large string, 114 close the file, and then execute the string. */ 115int 116source_builtin (list) 117 WORD_LIST *list; 118{ 119 int result; 120 char *filename, *debug_trap, *x; 121 122 if (no_options (list)) 123 return (EX_USAGE); 124 list = loptend; 125 126 if (list == 0) 127 { 128 builtin_error (_("filename argument required")); 129 builtin_usage (); 130 return (EX_USAGE); 131 } 132 133#if defined (RESTRICTED_SHELL) 134 if (restricted && strchr (list->word->word, '/')) 135 { 136 sh_restricted (list->word->word); 137 return (EXECUTION_FAILURE); 138 } 139#endif 140 141 filename = (char *)NULL; 142 /* XXX -- should this be absolute_pathname? */ 143 if (posixly_correct && strchr (list->word->word, '/')) 144 filename = savestring (list->word->word); 145 else if (absolute_pathname (list->word->word)) 146 filename = savestring (list->word->word); 147 else if (source_uses_path) 148 filename = find_path_file (list->word->word); 149 if (filename == 0) 150 { 151 if (source_searches_cwd == 0) 152 { 153 x = printable_filename (list->word->word, 0); 154 builtin_error (_("%s: file not found"), x); 155 if (x != list->word->word) 156 free (x); 157 if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0) 158 { 159 last_command_exit_value = EXECUTION_FAILURE; 160 jump_to_top_level (EXITPROG); 161 } 162 return (EXECUTION_FAILURE); 163 } 164 else 165 filename = savestring (list->word->word); 166 } 167 168 begin_unwind_frame ("source"); 169 add_unwind_protect (xfree, filename); 170 171 if (list->next) 172 { 173 push_dollar_vars (); 174 add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL); 175 if (debugging_mode || shell_compatibility_level <= 44) 176 init_bash_argv (); /* Initialize BASH_ARGV and BASH_ARGC */ 177 remember_args (list->next, 1); 178 if (debugging_mode) 179 push_args (list->next); /* Update BASH_ARGV and BASH_ARGC */ 180 } 181 set_dollar_vars_unchanged (); 182 183 /* Don't inherit the DEBUG trap unless function_trace_mode (overloaded) 184 is set. XXX - should sourced files inherit the RETURN trap? Functions 185 don't. */ 186 debug_trap = TRAP_STRING (DEBUG_TRAP); 187 if (debug_trap && function_trace_mode == 0) 188 { 189 debug_trap = savestring (debug_trap); 190 add_unwind_protect (xfree, debug_trap); 191 add_unwind_protect (maybe_set_debug_trap, debug_trap); 192 restore_default_signal (DEBUG_TRAP); 193 } 194 195 result = source_file (filename, (list && list->next)); 196 197 run_unwind_frame ("source"); 198 199 return (result); 200} 201