Chet Ramey | 495aee4 | 2011-11-22 19:11:26 -0500 | [diff] [blame] | 1 | /* evalstring.c - evaluate a string as one or more shell commands. */ |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 2 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 3 | /* Copyright (C) 1996-2012 Free Software Foundation, Inc. |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 4 | |
| 5 | This file is part of GNU Bash, the Bourne Again SHell. |
| 6 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 7 | Bash is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 11 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 12 | Bash is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with Bash. If not, see <http://www.gnu.org/licenses/>. |
| 19 | */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 20 | |
| 21 | #include <config.h> |
| 22 | |
| 23 | #if defined (HAVE_UNISTD_H) |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 24 | # ifdef _MINIX |
| 25 | # include <sys/types.h> |
| 26 | # endif |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 27 | # include <unistd.h> |
| 28 | #endif |
| 29 | |
| 30 | #include <stdio.h> |
| 31 | #include <signal.h> |
| 32 | |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 33 | #include <errno.h> |
| 34 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 35 | #include "filecntl.h" |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 36 | #include "../bashansi.h" |
| 37 | |
| 38 | #include "../shell.h" |
| 39 | #include "../jobs.h" |
| 40 | #include "../builtins.h" |
| 41 | #include "../flags.h" |
| 42 | #include "../input.h" |
| 43 | #include "../execute_cmd.h" |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 44 | #include "../redir.h" |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 45 | #include "../trap.h" |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 46 | #include "../bashintl.h" |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 47 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 48 | #include <y.tab.h> |
| 49 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 50 | #if defined (HISTORY) |
| 51 | # include "../bashhist.h" |
| 52 | #endif |
| 53 | |
| 54 | #include "common.h" |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 55 | #include "builtext.h" |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 56 | |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 57 | #if !defined (errno) |
Ricardo Cerqueira | a02fbff | 2013-07-25 22:35:34 +0100 | [diff] [blame] | 58 | #include <errno.h> |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 59 | #endif |
| 60 | |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 61 | #define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL) |
| 62 | |
Jari Aalto | 0628567 | 2006-10-10 14:15:34 +0000 | [diff] [blame] | 63 | extern int indirection_level, subshell_environment; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 64 | extern int line_number, line_number_for_err_trap; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 65 | extern int current_token, shell_eof_token; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 66 | extern int last_command_exit_value; |
| 67 | extern int running_trap; |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 68 | extern int loop_level; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 69 | extern int executing_list; |
| 70 | extern int comsub_ignore_return; |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 71 | extern int posixly_correct; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 72 | extern int return_catch_flag, return_catch_value; |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 73 | extern sh_builtin_func_t *this_shell_builtin; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 74 | extern char *the_printed_command_except_trap; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 75 | |
| 76 | int parse_and_execute_level = 0; |
| 77 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 78 | static int cat_file __P((REDIRECT *)); |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 79 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 80 | #define PE_TAG "parse_and_execute top" |
| 81 | #define PS_TAG "parse_string top" |
| 82 | |
Jari Aalto | f1be666 | 2008-11-18 13:15:12 +0000 | [diff] [blame] | 83 | #if defined (HISTORY) |
| 84 | static void |
| 85 | set_history_remembering () |
| 86 | { |
| 87 | remember_on_history = enable_history_list; |
| 88 | } |
| 89 | #endif |
| 90 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 91 | static void |
| 92 | restore_lastcom (x) |
| 93 | char *x; |
| 94 | { |
| 95 | FREE (the_printed_command_except_trap); |
| 96 | the_printed_command_except_trap = x; |
| 97 | } |
| 98 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 99 | /* How to force parse_and_execute () to clean up after itself. */ |
| 100 | void |
| 101 | parse_and_execute_cleanup () |
| 102 | { |
| 103 | if (running_trap) |
| 104 | { |
| 105 | run_trap_cleanup (running_trap - 1); |
| 106 | unfreeze_jobs_list (); |
| 107 | } |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 108 | |
| 109 | if (have_unwind_protects ()) |
| 110 | run_unwind_frame (PE_TAG); |
| 111 | else |
| 112 | parse_and_execute_level = 0; /* XXX */ |
| 113 | } |
| 114 | |
| 115 | static void |
| 116 | parse_prologue (string, flags, tag) |
| 117 | char *string; |
| 118 | int flags; |
| 119 | char *tag; |
| 120 | { |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 121 | char *orig_string, *lastcom; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 122 | int x; |
| 123 | |
| 124 | orig_string = string; |
| 125 | /* Unwind protect this invocation of parse_and_execute (). */ |
| 126 | begin_unwind_frame (tag); |
| 127 | unwind_protect_int (parse_and_execute_level); |
| 128 | unwind_protect_jmp_buf (top_level); |
| 129 | unwind_protect_int (indirection_level); |
| 130 | unwind_protect_int (line_number); |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 131 | unwind_protect_int (line_number_for_err_trap); |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 132 | unwind_protect_int (loop_level); |
| 133 | unwind_protect_int (executing_list); |
| 134 | unwind_protect_int (comsub_ignore_return); |
| 135 | if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) |
| 136 | unwind_protect_int (interactive); |
| 137 | |
| 138 | #if defined (HISTORY) |
| 139 | if (parse_and_execute_level == 0) |
| 140 | add_unwind_protect (set_history_remembering, (char *)NULL); |
| 141 | else |
| 142 | unwind_protect_int (remember_on_history); /* can be used in scripts */ |
| 143 | # if defined (BANG_HISTORY) |
| 144 | if (interactive_shell) |
| 145 | unwind_protect_int (history_expansion_inhibited); |
| 146 | # endif /* BANG_HISTORY */ |
| 147 | #endif /* HISTORY */ |
| 148 | |
| 149 | if (interactive_shell) |
| 150 | { |
| 151 | x = get_current_prompt_level (); |
| 152 | add_unwind_protect (set_current_prompt_level, x); |
| 153 | } |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 154 | |
| 155 | if (the_printed_command_except_trap) |
| 156 | { |
| 157 | lastcom = savestring (the_printed_command_except_trap); |
| 158 | add_unwind_protect (restore_lastcom, lastcom); |
| 159 | } |
| 160 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 161 | add_unwind_protect (pop_stream, (char *)NULL); |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 162 | if (parser_expanding_alias ()) |
| 163 | add_unwind_protect (parser_restore_alias, (char *)NULL); |
| 164 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 165 | if (orig_string && ((flags & SEVAL_NOFREE) == 0)) |
| 166 | add_unwind_protect (xfree, orig_string); |
| 167 | end_unwind_frame (); |
| 168 | |
| 169 | if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) |
| 170 | interactive = (flags & SEVAL_NONINT) ? 0 : 1; |
| 171 | |
| 172 | #if defined (HISTORY) |
| 173 | if (flags & SEVAL_NOHIST) |
| 174 | bash_history_disable (); |
| 175 | #endif /* HISTORY */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | /* Parse and execute the commands in STRING. Returns whatever |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 179 | execute_command () returns. This frees STRING. FLAGS is a |
| 180 | flags word; look in common.h for the possible values. Actions |
| 181 | are: |
| 182 | (flags & SEVAL_NONINT) -> interactive = 0; |
| 183 | (flags & SEVAL_INTERACT) -> interactive = 1; |
| 184 | (flags & SEVAL_NOHIST) -> call bash_history_disable () |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 185 | (flags & SEVAL_NOFREE) -> don't free STRING when finished |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 186 | (flags & SEVAL_RESETLINE) -> reset line_number to 1 |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 187 | */ |
| 188 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 189 | int |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 190 | parse_and_execute (string, from_file, flags) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 191 | char *string; |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 192 | const char *from_file; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 193 | int flags; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 194 | { |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 195 | int code, lreset; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 196 | volatile int should_jump_to_top_level, last_result; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 197 | COMMAND *volatile command; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 198 | volatile sigset_t pe_sigmask; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 199 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 200 | parse_prologue (string, flags, PE_TAG); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 201 | |
| 202 | parse_and_execute_level++; |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 203 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 204 | lreset = flags & SEVAL_RESETLINE; |
| 205 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 206 | #if defined (HAVE_POSIX_SIGNALS) |
| 207 | /* If we longjmp and are going to go on, use this to restore signal mask */ |
| 208 | sigemptyset (&pe_sigmask); |
| 209 | sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &pe_sigmask); |
| 210 | #endif |
| 211 | |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 212 | /* Reset the line number if the caller wants us to. If we don't reset the |
| 213 | line number, we have to subtract one, because we will add one just |
| 214 | before executing the next command (resetting the line number sets it to |
| 215 | 0; the first line number is 1). */ |
| 216 | push_stream (lreset); |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 217 | if (parser_expanding_alias ()) |
| 218 | /* push current shell_input_line */ |
| 219 | parser_save_alias (); |
| 220 | |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 221 | if (lreset == 0) |
| 222 | line_number--; |
| 223 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 224 | indirection_level++; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 225 | |
| 226 | code = should_jump_to_top_level = 0; |
| 227 | last_result = EXECUTION_SUCCESS; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 228 | |
| 229 | with_input_from_string (string, from_file); |
| 230 | while (*(bash_input.location.string)) |
| 231 | { |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 232 | command = (COMMAND *)NULL; |
| 233 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 234 | if (interrupt_state) |
| 235 | { |
| 236 | last_result = EXECUTION_FAILURE; |
| 237 | break; |
| 238 | } |
| 239 | |
| 240 | /* Provide a location for functions which `longjmp (top_level)' to |
| 241 | jump to. This prevents errors in substitution from restarting |
| 242 | the reader loop directly, for example. */ |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 243 | code = setjmp_nosigs (top_level); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 244 | |
| 245 | if (code) |
| 246 | { |
| 247 | should_jump_to_top_level = 0; |
| 248 | switch (code) |
| 249 | { |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 250 | case ERREXIT: |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 251 | /* variable_context -> 0 is what eval.c:reader_loop() does in |
| 252 | these circumstances. Don't bother with cleanup here because |
| 253 | we don't want to run the function execution cleanup stuff |
| 254 | that will cause pop_context and other functions to run. |
| 255 | XXX - change that if we want the function context to be |
| 256 | unwound. */ |
| 257 | if (exit_immediately_on_error && variable_context) |
| 258 | { |
| 259 | discard_unwind_frame ("pe_dispose"); |
| 260 | variable_context = 0; /* not in a function */ |
| 261 | } |
| 262 | should_jump_to_top_level = 1; |
| 263 | goto out; |
| 264 | case FORCE_EOF: |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 265 | case EXITPROG: |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 266 | if (command) |
| 267 | run_unwind_frame ("pe_dispose"); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 268 | /* Remember to call longjmp (top_level) after the old |
| 269 | value for it is restored. */ |
| 270 | should_jump_to_top_level = 1; |
| 271 | goto out; |
| 272 | |
| 273 | case DISCARD: |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 274 | if (command) |
| 275 | run_unwind_frame ("pe_dispose"); |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 276 | last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 277 | if (subshell_environment) |
| 278 | { |
| 279 | should_jump_to_top_level = 1; |
| 280 | goto out; |
| 281 | } |
| 282 | else |
| 283 | { |
Jari Aalto | e8ce775 | 1997-09-22 20:22:27 +0000 | [diff] [blame] | 284 | #if 0 |
| 285 | dispose_command (command); /* pe_dispose does this */ |
| 286 | #endif |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 287 | #if defined (HAVE_POSIX_SIGNALS) |
| 288 | sigprocmask (SIG_SETMASK, &pe_sigmask, (sigset_t *)NULL); |
| 289 | #endif |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 290 | continue; |
| 291 | } |
| 292 | |
| 293 | default: |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 294 | command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 295 | break; |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | if (parse_command () == 0) |
| 300 | { |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 301 | if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute)) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 302 | { |
| 303 | last_result = EXECUTION_SUCCESS; |
| 304 | dispose_command (global_command); |
| 305 | global_command = (COMMAND *)NULL; |
| 306 | } |
| 307 | else if (command = global_command) |
| 308 | { |
| 309 | struct fd_bitmap *bitmap; |
| 310 | |
Chet Ramey | 80b4d71 | 2014-10-05 19:12:20 -0400 | [diff] [blame] | 311 | if (flags & SEVAL_FUNCDEF) |
Chet Ramey | b64a0e1 | 2014-09-25 08:45:07 -0400 | [diff] [blame] | 312 | { |
Chet Ramey | 80b4d71 | 2014-10-05 19:12:20 -0400 | [diff] [blame] | 313 | char *x; |
| 314 | |
| 315 | /* If the command parses to something other than a straight |
| 316 | function definition, or if we have not consumed the entire |
| 317 | string, or if the parser has transformed the function |
| 318 | name (as parsing will if it begins or ends with shell |
| 319 | whitespace, for example), reject the attempt */ |
| 320 | if (command->type != cm_function_def || |
| 321 | ((x = parser_remaining_input ()) && *x) || |
| 322 | (STREQ (from_file, command->value.Function_def->name->word) == 0)) |
| 323 | { |
| 324 | internal_warning (_("%s: ignoring function definition attempt"), from_file); |
| 325 | should_jump_to_top_level = 0; |
| 326 | last_result = last_command_exit_value = EX_BADUSAGE; |
| 327 | reset_parser (); |
| 328 | break; |
| 329 | } |
Chet Ramey | b64a0e1 | 2014-09-25 08:45:07 -0400 | [diff] [blame] | 330 | } |
| 331 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 332 | bitmap = new_fd_bitmap (FD_BITMAP_SIZE); |
| 333 | begin_unwind_frame ("pe_dispose"); |
| 334 | add_unwind_protect (dispose_fd_bitmap, bitmap); |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 335 | add_unwind_protect (dispose_command, command); /* XXX */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 336 | |
| 337 | global_command = (COMMAND *)NULL; |
| 338 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 339 | if ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return) |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 340 | command->flags |= CMD_IGNORE_RETURN; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 341 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 342 | #if defined (ONESHOT) |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 343 | /* |
| 344 | * IF |
| 345 | * we were invoked as `bash -c' (startup_state == 2) AND |
| 346 | * parse_and_execute has not been called recursively AND |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 347 | * we're not running a trap AND |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 348 | * we have parsed the full command (string == '\0') AND |
Jari Aalto | f1be666 | 2008-11-18 13:15:12 +0000 | [diff] [blame] | 349 | * we're not going to run the exit trap AND |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 350 | * we have a simple command without redirections AND |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 351 | * the command is not being timed AND |
| 352 | * the command's return status is not being inverted |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 353 | * THEN |
| 354 | * tell the execution code that we don't need to fork |
| 355 | */ |
| 356 | if (startup_state == 2 && parse_and_execute_level == 1 && |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 357 | running_trap == 0 && |
Jari Aalto | b72432f | 1999-02-19 17:11:39 +0000 | [diff] [blame] | 358 | *bash_input.location.string == '\0' && |
| 359 | command->type == cm_simple && |
Jari Aalto | f1be666 | 2008-11-18 13:15:12 +0000 | [diff] [blame] | 360 | signal_is_trapped (EXIT_TRAP) == 0 && |
| 361 | command->redirects == 0 && command->value.Simple->redirects == 0 && |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 362 | ((command->flags & CMD_TIME_PIPELINE) == 0) && |
| 363 | ((command->flags & CMD_INVERT_RETURN) == 0)) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 364 | { |
| 365 | command->flags |= CMD_NO_FORK; |
| 366 | command->value.Simple->flags |= CMD_NO_FORK; |
| 367 | } |
| 368 | #endif /* ONESHOT */ |
| 369 | |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 370 | /* See if this is a candidate for $( <file ). */ |
| 371 | if (startup_state == 2 && |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 372 | (subshell_environment & SUBSHELL_COMSUB) && |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 373 | *bash_input.location.string == '\0' && |
| 374 | command->type == cm_simple && !command->redirects && |
| 375 | (command->flags & CMD_TIME_PIPELINE) == 0 && |
| 376 | command->value.Simple->words == 0 && |
| 377 | command->value.Simple->redirects && |
| 378 | command->value.Simple->redirects->next == 0 && |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 379 | command->value.Simple->redirects->instruction == r_input_direction && |
| 380 | command->value.Simple->redirects->redirector.dest == 0) |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 381 | { |
| 382 | int r; |
| 383 | r = cat_file (command->value.Simple->redirects); |
| 384 | last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; |
| 385 | } |
| 386 | else |
| 387 | last_result = execute_command_internal |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 388 | (command, 0, NO_PIPE, NO_PIPE, bitmap); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 389 | dispose_command (command); |
| 390 | dispose_fd_bitmap (bitmap); |
| 391 | discard_unwind_frame ("pe_dispose"); |
Chet Ramey | b64a0e1 | 2014-09-25 08:45:07 -0400 | [diff] [blame] | 392 | |
| 393 | if (flags & SEVAL_ONECMD) |
Chet Ramey | 80b4d71 | 2014-10-05 19:12:20 -0400 | [diff] [blame] | 394 | { |
| 395 | reset_parser (); |
| 396 | break; |
| 397 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 398 | } |
| 399 | } |
| 400 | else |
| 401 | { |
| 402 | last_result = EXECUTION_FAILURE; |
| 403 | |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 404 | if (interactive_shell == 0 && this_shell_builtin && |
| 405 | (this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) && |
| 406 | last_command_exit_value == EX_BADSYNTAX && posixly_correct) |
| 407 | { |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 408 | should_jump_to_top_level = 1; |
| 409 | code = ERREXIT; |
| 410 | last_command_exit_value = EX_BADUSAGE; |
Chet Ramey | 0001803 | 2011-11-21 20:51:19 -0500 | [diff] [blame] | 411 | } |
| 412 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 413 | /* Since we are shell compatible, syntax errors in a script |
| 414 | abort the execution of the script. Right? */ |
| 415 | break; |
| 416 | } |
| 417 | } |
| 418 | |
| 419 | out: |
| 420 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 421 | run_unwind_frame (PE_TAG); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 422 | |
| 423 | if (interrupt_state && parse_and_execute_level == 0) |
| 424 | { |
| 425 | /* An interrupt during non-interactive execution in an |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 426 | interactive shell (e.g. via $PROMPT_COMMAND) should |
| 427 | not cause the shell to exit. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 428 | interactive = interactive_shell; |
| 429 | throw_to_top_level (); |
| 430 | } |
| 431 | |
| 432 | if (should_jump_to_top_level) |
| 433 | jump_to_top_level (code); |
| 434 | |
| 435 | return (last_result); |
| 436 | } |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 437 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 438 | /* Parse a command contained in STRING according to FLAGS and return the |
| 439 | number of characters consumed from the string. If non-NULL, set *ENDP |
| 440 | to the position in the string where the parse ended. Used to validate |
| 441 | command substitutions during parsing to obey Posix rules about finding |
| 442 | the end of the command and balancing parens. */ |
| 443 | int |
| 444 | parse_string (string, from_file, flags, endp) |
| 445 | char *string; |
| 446 | const char *from_file; |
| 447 | int flags; |
| 448 | char **endp; |
| 449 | { |
| 450 | int code, nc; |
| 451 | volatile int should_jump_to_top_level; |
| 452 | COMMAND *volatile command, *oglobal; |
| 453 | char *ostring; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 454 | volatile sigset_t ps_sigmask; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 455 | |
| 456 | parse_prologue (string, flags, PS_TAG); |
| 457 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 458 | #if defined (HAVE_POSIX_SIGNALS) |
| 459 | /* If we longjmp and are going to go on, use this to restore signal mask */ |
| 460 | sigemptyset (&ps_sigmask); |
| 461 | sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &ps_sigmask); |
| 462 | #endif |
| 463 | |
| 464 | /* itrace("parse_string: `%s'", string); */ |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 465 | /* Reset the line number if the caller wants us to. If we don't reset the |
| 466 | line number, we have to subtract one, because we will add one just |
| 467 | before executing the next command (resetting the line number sets it to |
| 468 | 0; the first line number is 1). */ |
| 469 | push_stream (0); |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 470 | if (parser_expanding_alias ()) |
| 471 | /* push current shell_input_line */ |
| 472 | parser_save_alias (); |
| 473 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 474 | code = should_jump_to_top_level = 0; |
| 475 | oglobal = global_command; |
| 476 | ostring = string; |
| 477 | |
| 478 | with_input_from_string (string, from_file); |
| 479 | while (*(bash_input.location.string)) |
| 480 | { |
| 481 | command = (COMMAND *)NULL; |
| 482 | |
| 483 | #if 0 |
| 484 | if (interrupt_state) |
| 485 | break; |
| 486 | #endif |
| 487 | |
| 488 | /* Provide a location for functions which `longjmp (top_level)' to |
| 489 | jump to. */ |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 490 | code = setjmp_nosigs (top_level); |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 491 | |
| 492 | if (code) |
| 493 | { |
| 494 | #if defined (DEBUG) |
| 495 | itrace("parse_string: longjmp executed: code = %d", code); |
| 496 | #endif |
| 497 | should_jump_to_top_level = 0; |
| 498 | switch (code) |
| 499 | { |
| 500 | case FORCE_EOF: |
| 501 | case ERREXIT: |
| 502 | case EXITPROG: |
| 503 | case DISCARD: /* XXX */ |
| 504 | if (command) |
| 505 | dispose_command (command); |
| 506 | /* Remember to call longjmp (top_level) after the old |
| 507 | value for it is restored. */ |
| 508 | should_jump_to_top_level = 1; |
| 509 | goto out; |
| 510 | |
| 511 | default: |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 512 | #if defined (HAVE_POSIX_SIGNALS) |
| 513 | sigprocmask (SIG_SETMASK, &ps_sigmask, (sigset_t *)NULL); |
| 514 | #endif |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 515 | command_error ("parse_string", CMDERR_BADJUMP, code, 0); |
| 516 | break; |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | if (parse_command () == 0) |
| 521 | { |
| 522 | dispose_command (global_command); |
| 523 | global_command = (COMMAND *)NULL; |
| 524 | } |
| 525 | else |
| 526 | { |
| 527 | if ((flags & SEVAL_NOLONGJMP) == 0) |
| 528 | { |
| 529 | should_jump_to_top_level = 1; |
| 530 | code = DISCARD; |
| 531 | } |
| 532 | else |
| 533 | reset_parser (); /* XXX - sets token_to_read */ |
| 534 | break; |
| 535 | } |
| 536 | |
| 537 | if (current_token == yacc_EOF || current_token == shell_eof_token) |
| 538 | break; |
| 539 | } |
| 540 | |
| 541 | out: |
| 542 | |
| 543 | global_command = oglobal; |
| 544 | nc = bash_input.location.string - ostring; |
| 545 | if (endp) |
| 546 | *endp = bash_input.location.string; |
| 547 | |
| 548 | run_unwind_frame (PS_TAG); |
| 549 | |
| 550 | if (should_jump_to_top_level) |
| 551 | jump_to_top_level (code); |
| 552 | |
| 553 | return (nc); |
| 554 | } |
| 555 | |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 556 | /* Handle a $( < file ) command substitution. This expands the filename, |
| 557 | returning errors as appropriate, then just cats the file to the standard |
| 558 | output. */ |
| 559 | static int |
| 560 | cat_file (r) |
| 561 | REDIRECT *r; |
| 562 | { |
Jari Aalto | 0628567 | 2006-10-10 14:15:34 +0000 | [diff] [blame] | 563 | char *fn; |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 564 | int fd, rval; |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 565 | |
| 566 | if (r->instruction != r_input_direction) |
| 567 | return -1; |
| 568 | |
| 569 | /* Get the filename. */ |
| 570 | if (posixly_correct && !interactive_shell) |
| 571 | disallow_filename_globbing++; |
| 572 | fn = redirection_expand (r->redirectee.filename); |
| 573 | if (posixly_correct && !interactive_shell) |
| 574 | disallow_filename_globbing--; |
| 575 | |
| 576 | if (fn == 0) |
| 577 | { |
| 578 | redirection_error (r, AMBIGUOUS_REDIRECT); |
| 579 | return -1; |
| 580 | } |
| 581 | |
| 582 | fd = open(fn, O_RDONLY); |
| 583 | if (fd < 0) |
| 584 | { |
| 585 | file_error (fn); |
| 586 | free (fn); |
| 587 | return -1; |
| 588 | } |
| 589 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 590 | rval = zcatfd (fd, 1, fn); |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 591 | |
| 592 | free (fn); |
| 593 | close (fd); |
| 594 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 595 | return (rval); |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 596 | } |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 597 | |
| 598 | int |
| 599 | evalstring (string, from_file, flags) |
| 600 | char *string; |
| 601 | const char *from_file; |
| 602 | int flags; |
| 603 | { |
| 604 | volatile int r, rflag, rcatch; |
| 605 | |
| 606 | rcatch = 0; |
| 607 | rflag = return_catch_flag; |
| 608 | /* If we are in a place where `return' is valid, we have to catch |
| 609 | `eval "... return"' and make sure parse_and_execute cleans up. Then |
| 610 | we can trampoline to the previous saved return_catch location. */ |
| 611 | if (rflag) |
| 612 | { |
| 613 | begin_unwind_frame ("evalstring"); |
| 614 | |
| 615 | unwind_protect_int (return_catch_flag); |
| 616 | unwind_protect_jmp_buf (return_catch); |
| 617 | |
| 618 | return_catch_flag++; /* increment so we have a counter */ |
| 619 | rcatch = setjmp_nosigs (return_catch); |
| 620 | } |
| 621 | |
| 622 | if (rcatch) |
| 623 | { |
| 624 | parse_and_execute_cleanup (); |
| 625 | r = return_catch_value; |
| 626 | } |
| 627 | else |
| 628 | /* Note that parse_and_execute () frees the string it is passed. */ |
| 629 | r = parse_and_execute (string, from_file, flags); |
| 630 | |
| 631 | if (rflag) |
| 632 | { |
| 633 | run_unwind_frame ("evalstring"); |
| 634 | if (rcatch && return_catch_flag) |
| 635 | { |
| 636 | return_catch_value = r; |
| 637 | longjmp (return_catch, 1); |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | return (r); |
| 642 | } |