From: Chet Ramey Date: Sat, 3 Dec 2011 18:44:37 +0000 (-0500) Subject: commit bash-20050310 snapshot X-Git-Tag: bash-3.1-alpha~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=af91506ad6aba8644310bb5825904c54599cb07a;p=thirdparty%2Fbash.git commit bash-20050310 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 439c0420a..18732f80e 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11166,3 +11166,20 @@ configure.in bashline.c - make bash_directory_expansion a void function, since it doesn't have any return value + + 3/9 + --- +builtins/read.def + - when testing for a pipe, use `fd' instead of hard-coding 0, since we + can read from other file descriptors now + +lib/sh/zread.c + - in zsyncfd, only set lind and lused to 0 if the lseek succeeds. + If the lseek fails, we might steal input from other programs, but + a failed lseek won't cause us to erroneously discard input + + 3/11 + ---- +builtins/evalstring.c + - don't allow parse_and_execute to short-circuit and call exec() if + the command's return value is being inverted diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index ae6ca9cd9..92ad7d5cc 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -11151,5 +11151,29 @@ builtins/read.def the input (including any trailing field delimiters), falling back to the previous behavior if it does not. This is what POSIX.2 specifies, I believe (and the consensus of the austin-group list). - This requires a few tests in read.tests to be changed + This requires a few tests in read.tests to be changed: backslashes + escaping IFS whitespace characters at the end of input cause the + whitespace characters to be preserved in the value assigned to the + variable, and the trailing non-whitespace field delimiter issue + 3/7 + --- +configure.in + - add -D_POSIX_SOURCE to the LOCAL_CFLAGS for Interix + + 3/8 + --- +bashline.c + - make bash_directory_expansion a void function, since it doesn't have + any return value + + 3/9 + --- +builtins/read.def + - when testing for a pipe, use `fd' instead of hard-coding 0, since we + can read from other file descriptors now + +lib/sh/zread.c + - in zsyncfd, only set lind and lused to 0 if the lseek succeeds. + If the lseek fails, we might steal input from other programs, but + a failed lseek won't cause us to erroneously discard input diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 88d6a9e5b..f9e161343 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -233,7 +233,8 @@ parse_and_execute (string, from_file, flags) * parse_and_execute has not been called recursively AND * we have parsed the full command (string == '\0') AND * we have a simple command without redirections AND - * the command is not being timed + * the command is not being timed AND + * the command's return status is not being inverted * THEN * tell the execution code that we don't need to fork */ @@ -241,7 +242,8 @@ parse_and_execute (string, from_file, flags) *bash_input.location.string == '\0' && command->type == cm_simple && !command->redirects && !command->value.Simple->redirects && - ((command->flags & CMD_TIME_PIPELINE) == 0)) + ((command->flags & CMD_TIME_PIPELINE) == 0) && + ((command->flags & CMD_INVERT_RETURN) == 0)) { command->flags |= CMD_NO_FORK; command->value.Simple->flags |= CMD_NO_FORK; diff --git a/builtins/evalstring.c~ b/builtins/evalstring.c~ new file mode 100644 index 000000000..9c8a4a2ab --- /dev/null +++ b/builtins/evalstring.c~ @@ -0,0 +1,346 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + 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 2, or (at your option) any later + version. + + 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. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include +#include + +#include + +#include "filecntl.h" +#include "../bashansi.h" + +#include "../shell.h" +#include "../jobs.h" +#include "../builtins.h" +#include "../flags.h" +#include "../input.h" +#include "../execute_cmd.h" +#include "../redir.h" +#include "../trap.h" + +#if defined (HISTORY) +# include "../bashhist.h" +#endif + +#include "common.h" + +#if !defined (errno) +extern int errno; +#endif + +#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL) + +extern int indirection_level, startup_state, subshell_environment; +extern int line_number; +extern int last_command_exit_value; +extern int running_trap; +extern int posixly_correct; + +int parse_and_execute_level = 0; + +static int cat_file __P((REDIRECT *)); + +/* How to force parse_and_execute () to clean up after itself. */ +void +parse_and_execute_cleanup () +{ + if (running_trap) + { + run_trap_cleanup (running_trap - 1); + unfreeze_jobs_list (); + } + run_unwind_frame ("parse_and_execute_top"); +} + +/* Parse and execute the commands in STRING. Returns whatever + execute_command () returns. This frees STRING. FLAGS is a + flags word; look in common.h for the possible values. Actions + are: + (flags & SEVAL_NONINT) -> interactive = 0; + (flags & SEVAL_INTERACT) -> interactive = 1; + (flags & SEVAL_NOHIST) -> call bash_history_disable () + (flags & SEVAL_NOFREE) -> don't free STRING when finished + (flags & SEVAL_RESETLINE) -> reset line_number to 1 +*/ + +int +parse_and_execute (string, from_file, flags) + char *string; + const char *from_file; + int flags; +{ + int code, x, lreset; + volatile int should_jump_to_top_level, last_result; + char *orig_string; + COMMAND *volatile command; + + orig_string = string; + /* Unwind protect this invocation of parse_and_execute (). */ + begin_unwind_frame ("parse_and_execute_top"); + unwind_protect_int (parse_and_execute_level); + unwind_protect_jmp_buf (top_level); + unwind_protect_int (indirection_level); + unwind_protect_int (line_number); + if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) + unwind_protect_int (interactive); + + lreset = flags & SEVAL_RESETLINE; + +#if defined (HISTORY) + unwind_protect_int (remember_on_history); /* can be used in scripts */ +# if defined (BANG_HISTORY) + if (interactive_shell) + { + unwind_protect_int (history_expansion_inhibited); + } +# endif /* BANG_HISTORY */ +#endif /* HISTORY */ + + if (interactive_shell) + { + x = get_current_prompt_level (); + add_unwind_protect (set_current_prompt_level, x); + } + + add_unwind_protect (pop_stream, (char *)NULL); + if (orig_string && ((flags & SEVAL_NOFREE) == 0)) + add_unwind_protect (xfree, orig_string); + end_unwind_frame (); + + parse_and_execute_level++; + + /* Reset the line number if the caller wants us to. If we don't reset the + line number, we have to subtract one, because we will add one just + before executing the next command (resetting the line number sets it to + 0; the first line number is 1). */ + push_stream (lreset); + if (lreset == 0) + line_number--; + + indirection_level++; + if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) + interactive = (flags & SEVAL_NONINT) ? 0 : 1; + +#if defined (HISTORY) + if (flags & SEVAL_NOHIST) + bash_history_disable (); +#endif /* HISTORY */ + + code = should_jump_to_top_level = 0; + last_result = EXECUTION_SUCCESS; + + with_input_from_string (string, from_file); + while (*(bash_input.location.string)) + { + command = (COMMAND *)NULL; + + if (interrupt_state) + { + last_result = EXECUTION_FAILURE; + break; + } + + /* Provide a location for functions which `longjmp (top_level)' to + jump to. This prevents errors in substitution from restarting + the reader loop directly, for example. */ + code = setjmp (top_level); + + if (code) + { + should_jump_to_top_level = 0; + switch (code) + { + case FORCE_EOF: + case ERREXIT: + case EXITPROG: + if (command) + run_unwind_frame ("pe_dispose"); + /* Remember to call longjmp (top_level) after the old + value for it is restored. */ + should_jump_to_top_level = 1; + goto out; + + case DISCARD: + if (command) + run_unwind_frame ("pe_dispose"); + last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */ + if (subshell_environment) + { + should_jump_to_top_level = 1; + goto out; + } + else + { +#if 0 + dispose_command (command); /* pe_dispose does this */ +#endif + continue; + } + + default: + command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0); + break; + } + } + + if (parse_command () == 0) + { + if (interactive_shell == 0 && read_but_dont_execute) + { + last_result = EXECUTION_SUCCESS; + dispose_command (global_command); + global_command = (COMMAND *)NULL; + } + else if (command = global_command) + { + struct fd_bitmap *bitmap; + + bitmap = new_fd_bitmap (FD_BITMAP_SIZE); + begin_unwind_frame ("pe_dispose"); + add_unwind_protect (dispose_fd_bitmap, bitmap); + add_unwind_protect (dispose_command, command); /* XXX */ + + global_command = (COMMAND *)NULL; + +#if defined (ONESHOT) + /* + * IF + * we were invoked as `bash -c' (startup_state == 2) AND + * parse_and_execute has not been called recursively AND + * we have parsed the full command (string == '\0') AND + * we have a simple command without redirections AND + * the command is not being timed + * THEN + * tell the execution code that we don't need to fork + */ + if (startup_state == 2 && parse_and_execute_level == 1 && + *bash_input.location.string == '\0' && + command->type == cm_simple && + !command->redirects && !command->value.Simple->redirects && + ((command->flags & CMD_TIME_PIPELINE) == 0) && + ((command->flags & CMD_INVERT_RETURN) == 0)) + { + command->flags |= CMD_NO_FORK; + command->value.Simple->flags |= CMD_NO_FORK; + } +#endif /* ONESHOT */ + + /* See if this is a candidate for $( type == cm_simple && !command->redirects && + (command->flags & CMD_TIME_PIPELINE) == 0 && + command->value.Simple->words == 0 && + command->value.Simple->redirects && + command->value.Simple->redirects->next == 0 && + command->value.Simple->redirects->instruction == r_input_direction) + { + int r; + r = cat_file (command->value.Simple->redirects); + last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; + } + else + last_result = execute_command_internal + (command, 0, NO_PIPE, NO_PIPE, bitmap); + + dispose_command (command); + dispose_fd_bitmap (bitmap); + discard_unwind_frame ("pe_dispose"); + } + } + else + { + last_result = EXECUTION_FAILURE; + + /* Since we are shell compatible, syntax errors in a script + abort the execution of the script. Right? */ + break; + } + } + + out: + + run_unwind_frame ("parse_and_execute_top"); + + if (interrupt_state && parse_and_execute_level == 0) + { + /* An interrupt during non-interactive execution in an + interactive shell (e.g. via $PROMPT_COMMAND) should + not cause the shell to exit. */ + interactive = interactive_shell; + throw_to_top_level (); + } + + if (should_jump_to_top_level) + jump_to_top_level (code); + + return (last_result); +} + +/* Handle a $( < file ) command substitution. This expands the filename, + returning errors as appropriate, then just cats the file to the standard + output. */ +static int +cat_file (r) + REDIRECT *r; +{ + char lbuf[128], *fn; + int fd, rval; + ssize_t nr; + + if (r->instruction != r_input_direction) + return -1; + + /* Get the filename. */ + if (posixly_correct && !interactive_shell) + disallow_filename_globbing++; + fn = redirection_expand (r->redirectee.filename); + if (posixly_correct && !interactive_shell) + disallow_filename_globbing--; + + if (fn == 0) + { + redirection_error (r, AMBIGUOUS_REDIRECT); + return -1; + } + + fd = open(fn, O_RDONLY); + if (fd < 0) + { + file_error (fn); + free (fn); + return -1; + } + + rval = zcatfd (fd, 1, fn); + + free (fn); + close (fd); + + return (rval); +} diff --git a/builtins/read.def b/builtins/read.def index 05e69e853..c5f658e94 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -276,7 +276,7 @@ read_builtin (list) input_is_tty = isatty (fd); if (input_is_tty == 0) #ifndef __CYGWIN__ - input_is_pipe = (lseek (0, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); + input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); #else input_is_pipe = 1; #endif diff --git a/lib/sh/zread.c b/lib/sh/zread.c index b5155488f..460234b99 100644 --- a/lib/sh/zread.c +++ b/lib/sh/zread.c @@ -124,9 +124,13 @@ zsyncfd (fd) int fd; { off_t off; + int r; off = lused - lind; + r = 0; if (off > 0) - lseek (fd, -off, SEEK_CUR); - lused = lind = 0; + r = lseek (fd, -off, SEEK_CUR); + + if (r >= 0) + lused = lind = 0; } diff --git a/tests/run-intl b/tests/run-intl index 48b1c8312..6a9234a3b 100644 --- a/tests/run-intl +++ b/tests/run-intl @@ -3,5 +3,6 @@ echo "warning: some of these tests will fail if you do not have UTF-8" >&2 echo "warning: locales installed on your system." >&2 +echo "warning: please ignore any differences consisting only of white space" >&2 ${THIS_SH} ./intl.tests > /tmp/xx diff $AFLAG /tmp/xx intl.right && rm -f /tmp/xx diff --git a/tests/run-intl~ b/tests/run-intl~ index c31a37933..48b1c8312 100644 --- a/tests/run-intl~ +++ b/tests/run-intl~ @@ -1,4 +1,7 @@ +# See whether or not we can use `diff -a' +( diff -a ./intl.right ./intl.right >/dev/null 2>&1 ) && AFLAG=-a + echo "warning: some of these tests will fail if you do not have UTF-8" >&2 echo "warning: locales installed on your system." >&2 ${THIS_SH} ./intl.tests > /tmp/xx -diff /tmp/xx intl.right && rm -f /tmp/xx +diff $AFLAG /tmp/xx intl.right && rm -f /tmp/xx diff --git a/tests/run-read b/tests/run-read index b7a426813..47e4188b9 100644 --- a/tests/run-read +++ b/tests/run-read @@ -1,4 +1,4 @@ -echo "warning: different versions of wc put differing amounts of whitespace" >&2 -echo "warning: before their output. Please do not consider this an error." >&2 +echo "warning: please do not consider output differing only in the amount of" >&2 +echo "warning: white space to be an error." >&2 ${THIS_SH} ./read.tests > /tmp/xx 2>&1 diff /tmp/xx read.right && rm -f /tmp/xx diff --git a/tests/run-read~ b/tests/run-read~ new file mode 100644 index 000000000..b7a426813 --- /dev/null +++ b/tests/run-read~ @@ -0,0 +1,4 @@ +echo "warning: different versions of wc put differing amounts of whitespace" >&2 +echo "warning: before their output. Please do not consider this an error." >&2 +${THIS_SH} ./read.tests > /tmp/xx 2>&1 +diff /tmp/xx read.right && rm -f /tmp/xx