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