diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 0997f559..d23f8404 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8456,3 +8456,29 @@ lib/malloc/malloc.c lib/malloc/stats.c - _print_malloc_stats: slight adjustment for better column alignment + + 6/1 + --- +execute_cmd.c + - execute_command_internal: treat a redirection failure with errexit + set as a command failure that exits the shell. Bug report from + Hyunho Cho + + 6/3 + --- +redir.c + - redirection_error: takes a new argument, FN, which if non-NULL is + the filename to be used in the error message. + +redir.[ch],builtins/evalstring.c + - redirection_error: changed extern declaration and callers + +redir.c + - do_redirection_internal: takes a new third parameter, FNP, a char ** + to use (*FNP, if non-NULL) to store and return the expanded filename + for those redirections that take one + - do_redirections: pass a char ** (&fn) to do_redirection_internal to + get a pointer to the expanded filename; pass it to redirection_error + if appropriate. Free FN in any case, since do_redirection_internal + won't. Fix for double expansion of filename in certain redirections + reported by OÄuz diff --git a/CWRU/changelog~ b/CWRU/changelog~ deleted file mode 120000 index d2d81b30..00000000 --- a/CWRU/changelog~ +++ /dev/null @@ -1 +0,0 @@ -CWRU.chlog \ No newline at end of file diff --git a/MANIFEST b/MANIFEST index 9f2e58d8..7a945e05 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1450,6 +1450,7 @@ tests/varenv16.sub f tests/varenv17.sub f tests/varenv18.sub f tests/varenv19.sub f +tests/varenv20.sub f tests/version f tests/version.mini f tests/vredir.tests f diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 84479f92..010d073f 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -656,7 +656,7 @@ cat_file (r) if (fn == 0) { - redirection_error (r, AMBIGUOUS_REDIRECT); + redirection_error (r, AMBIGUOUS_REDIRECT, fn); return -1; } diff --git a/execute_cmd.c b/execute_cmd.c index 17753b37..0542dbc8 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -768,6 +768,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, /* Handle WHILE FOR CASE etc. with redirections. (Also '&' input redirection.) */ + was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; + ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; + if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0) { undo_partial_redirects (); @@ -779,7 +782,25 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, discard_unwind_frame ("internal_fifos"); } #endif - return (last_command_exit_value = EXECUTION_FAILURE); + + /* Handle redirection error as command failure if errexit set. */ + last_command_exit_value = EXECUTION_FAILURE; + if (ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE) + { + if (was_error_trap) + { + save_line_number = line_number; + line_number = line_number_for_err_trap; + run_error_trap (); + line_number = save_line_number; + } + if (exit_immediately_on_error) + { + run_pending_traps (); + jump_to_top_level (ERREXIT); + } + } + return (last_command_exit_value); } my_undo_list = redirection_undo_list; @@ -797,8 +818,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, if (exec_undo_list) add_unwind_protect ((Function *)dispose_redirects, exec_undo_list); - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - QUIT; switch (command->type) diff --git a/lib/readline/posixdir.h~ b/lib/readline/posixdir.h~ deleted file mode 120000 index 8b163845..00000000 --- a/lib/readline/posixdir.h~ +++ /dev/null @@ -1 +0,0 @@ -../../include/posixdir.h \ No newline at end of file diff --git a/redir.c b/redir.c index 7de1aa03..9e596d3a 100644 --- a/redir.c +++ b/redir.c @@ -1,6 +1,6 @@ /* redir.c -- Functions to perform input and output redirection. */ -/* Copyright (C) 1997-2019 Free Software Foundation, Inc. +/* Copyright (C) 1997-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -87,24 +87,24 @@ extern REDIRECT *redirection_undo_list; extern REDIRECT *exec_redirection_undo_list; /* Static functions defined and used in this file. */ -static void add_exec_redirect __P((REDIRECT *)); -static int add_undo_redirect __P((int, enum r_instruction, int)); -static int add_undo_close_redirect __P((int)); -static int expandable_redirection_filename __P((REDIRECT *)); -static int stdin_redirection __P((enum r_instruction, int)); -static int undoablefd __P((int)); -static int do_redirection_internal __P((REDIRECT *, int)); +static void add_exec_redirect PARAMS((REDIRECT *)); +static int add_undo_redirect PARAMS((int, enum r_instruction, int)); +static int add_undo_close_redirect PARAMS((int)); +static int expandable_redirection_filename PARAMS((REDIRECT *)); +static int stdin_redirection PARAMS((enum r_instruction, int)); +static int undoablefd PARAMS((int)); +static int do_redirection_internal PARAMS((REDIRECT *, int, char **)); -static char *heredoc_expand __P((WORD_DESC *, enum r_instruction, size_t *)); -static int heredoc_write __P((int, char *, size_t)); -static int here_document_to_fd __P((WORD_DESC *, enum r_instruction)); +static char *heredoc_expand PARAMS((WORD_DESC *, enum r_instruction, size_t *)); +static int heredoc_write PARAMS((int, char *, size_t)); +static int here_document_to_fd PARAMS((WORD_DESC *, enum r_instruction)); -static int redir_special_open __P((int, char *, int, int, enum r_instruction)); -static int noclobber_open __P((char *, int, int, enum r_instruction)); -static int redir_open __P((char *, int, int, enum r_instruction)); +static int redir_special_open PARAMS((int, char *, int, int, enum r_instruction)); +static int noclobber_open PARAMS((char *, int, int, enum r_instruction)); +static int redir_open PARAMS((char *, int, int, enum r_instruction)); -static int redir_varassign __P((REDIRECT *, int)); -static int redir_varvalue __P((REDIRECT *)); +static int redir_varassign PARAMS((REDIRECT *, int)); +static int redir_varvalue PARAMS((REDIRECT *)); /* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to a new redirection and when creating the redirection undo list. */ @@ -126,9 +126,10 @@ do { \ } while (0) void -redirection_error (temp, error) +redirection_error (temp, error, fn) REDIRECT *temp; int error; + char *fn; /* already-expanded filename */ { char *filename, *allocname; int oflags; @@ -173,6 +174,8 @@ redirection_error (temp, error) } } #endif + else if (fn) + filename = fn; else if (expandable_redirection_filename (temp)) { oflags = temp->redirectee.filename->flags; @@ -234,6 +237,7 @@ do_redirections (list, flags) { int error; REDIRECT *temp; + char *fn; if (flags & RX_UNDOABLE) { @@ -248,12 +252,15 @@ do_redirections (list, flags) for (temp = list; temp; temp = temp->next) { - error = do_redirection_internal (temp, flags); + fn = 0; + error = do_redirection_internal (temp, flags, &fn); if (error) { - redirection_error (temp, error); + redirection_error (temp, error, fn); + FREE (fn); return (error); } + FREE (fn); } return (0); } @@ -763,11 +770,13 @@ undoablefd (fd) produce the appropriate side effects. flags & RX_UNDOABLE, if non-zero, says to remember how to undo each redirection. If flags & RX_CLEXEC is non-zero, then we set all file descriptors > 2 that we open to be - close-on-exec. */ + close-on-exec. FNP, if non-null is a pointer to a location where the + expanded filename is stored. The caller will free it. */ static int -do_redirection_internal (redirect, flags) +do_redirection_internal (redirect, flags, fnp) REDIRECT *redirect; int flags; + char **fnp; { WORD_DESC *redirectee; int redir_fd, fd, redirector, r, oflags; @@ -902,7 +911,10 @@ do_redirection_internal (redirect, flags) #endif /* RESTRICTED_SHELL */ fd = redir_open (redirectee_word, redirect->flags, 0666, ri); - free (redirectee_word); + if (fnp) + *fnp = redirectee_word; + else + free (redirectee_word); if (fd == NOCLOBBER_REDIRECT || fd == RESTRICTED_REDIRECT) return (fd); diff --git a/redir.h b/redir.h index 0e117840..64a3d266 100644 --- a/redir.h +++ b/redir.h @@ -1,6 +1,6 @@ /* redir.h - functions from redir.c. */ -/* Copyright (C) 1997, 2001, 2005, 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 1997, 2001, 2005, 2008, 2009-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -32,9 +32,9 @@ #define RX_SAVCLEXEC 0x20 /* set close-on-exec off in restored fd even though saved on has it on */ #define RX_SAVEFD 0x40 /* fd used to save another even if < SHELL_FD_BASE */ -extern void redirection_error __P((REDIRECT *, int)); -extern int do_redirections __P((REDIRECT *, int)); -extern char *redirection_expand __P((WORD_DESC *)); -extern int stdin_redirects __P((REDIRECT *)); +extern void redirection_error PARAMS((REDIRECT *, int, char *)); +extern int do_redirections PARAMS((REDIRECT *, int)); +extern char *redirection_expand PARAMS((WORD_DESC *)); +extern int stdin_redirects PARAMS((REDIRECT *)); #endif /* _REDIR_H_ */ diff --git a/support/copyright-script~ b/support/copyright-script~ deleted file mode 120000 index 9efbefcb..00000000 --- a/support/copyright-script~ +++ /dev/null @@ -1 +0,0 @@ -copyright-makefile \ No newline at end of file diff --git a/support/mk-takehome b/support/mk-takehome new file mode 100755 index 00000000..4f402607 --- /dev/null +++ b/support/mk-takehome @@ -0,0 +1,102 @@ +#! /bin/bash + +SRC=$HOME/src/bash/src +REMHOST=jenna +DROPBOX_FOLDER='Dropbox (Personal)' +DROPBOX_HOME=$HOME/$DROPBOX_FOLDER +GDRIVE_FOLDER='Google Drive personal' +GDRIVE_HOME=$HOME/$GDRIVE_FOLDER + +PARENT=/fs2/chet/bash +DATE=$(date +%Y%m%d) +fflag= sflag= dflag= gflag= + +while getopts "dfgsp:D:" opt +do + case $opt in + d) dflag=1 ;; + g) gflag=1 ;; + f) fflag=1 ;; + p) PARENT=$OPTARG + if [ ! -d "$PARENT" ]; then + echo "mk-takehome: $PARENT: directory does not exist" 2>&1 + exit 2 + fi ;; + s) sflag=1 ;; + D) DATE=$OPTARG ;; + *) echo "mk-takehome: usage: mk-takehome [-dfgs] [-p parent] [-D date] [directory]" 2>&1 + exit 2;; + esac +done +shift $(($OPTIND - 1)) + +FROOT=bash-$DATE +DIR=$PARENT/$FROOT + +if [ -n "$1" ]; then + DIR="$1" + PARENT="${DIR%/*}" + FROOT="${DIR##*/}" + if [ -z "$PARENT" ]; then PARENT=. ; fi + if [ "$PARENT" -ef "$DIR" ]; then PARENT=. ; fi +fi +TARF=${FROOT}.tar + +if [ -n "$fflag" ]; then + rm -rf "$DIR" +fi + +mkdir $DIR || exit 1 + +cd $DIR || exit 1 + +cd $SRC || exit 1 + +tar cf - . | (cd $DIR ; tar xvpf - ) + +cd $DIR || exit 1 + +find . -type f -name '*~' -print | xargs rm -f + +find . -type d -name 'savedir' -print | xargs rm -rf + +rm parser-built y.tab.c y.tab.h +# bison -y -d parse.y # make sure y.tab.h present for dependencies + +rm -f d d? ddd ddd? # convention for temp diff files + +cd $PARENT || exit 1 + +tar cvf ${TARF} $FROOT + +gzip -v ${TARF} + +if [ -n "$sflag" ]; then + scp ${TARF}.gz ${REMHOST}: +fi + +# dropbox +if [ -n "$dflag" ]; then + if [ ! -d "$DROPBOX_HOME" ]; then + HOME=~chet + DROPBOX_HOME=$HOME/$DROPBOX_FOLDER + fi + if [ ! -d "$DROPBOX_HOME" ]; then + echo "$DROPBOX_HOME: directory not found" >&2 + else + cp ${TARF}.gz "$DROPBOX_HOME" + fi +fi + +# google drive +if [ -n "$gflag" ]; then + if [ ! -d "$GDRIVE_HOME" ]; then + HOME=~chet + GDRIVE_HOME=$HOME/$GDRIVE_FOLDER + fi + if [ ! -d "$GDRIVE_HOME" ]; then + echo "$GDRIVE_HOME: directory not found" >&2 + else + cp ${TARF}.gz "$GDRIVE_HOME" + fi +fi diff --git a/tests/lastpipe.tests b/tests/lastpipe.tests index 66ebfe2b..775e81dd 100644 --- a/tests/lastpipe.tests +++ b/tests/lastpipe.tests @@ -28,7 +28,7 @@ if [ -x /usr/bin/false ]; then elif [ -x /bin/false ]; then binfalse=/bin/false else - binfalse=true + binfalse=false fi shopt -s lastpipe @@ -71,4 +71,3 @@ ${THIS_SH} ./lastpipe1.sub echo lastpipe1.sub returns $? ${THIS_SH} ./lastpipe2.sub - diff --git a/tests/redir.right b/tests/redir.right index 608d0044..8db10414 100644 --- a/tests/redir.right +++ b/tests/redir.right @@ -159,3 +159,5 @@ after: 42 a+=3 foo foo +./redir11.sub: line 75: 42: No such file or directory +42 diff --git a/tests/redir11.sub b/tests/redir11.sub index 8af4334f..d417cdb6 100644 --- a/tests/redir11.sub +++ b/tests/redir11.sub @@ -65,3 +65,12 @@ a=2 a=9 eval echo foo >&$(echo $a) a=2 a=9 eval echo foo '2>&1 >&$(echo $a)' | { grep -q 'Bad file' || echo 'redir11 bad 9'; } + +# double expansion of filenames when used in redirection error messages +# present in bash versions back to at least bash-1.13 +# this is executed in the tests subdirectory of the source directory, so there +# definitely should not be a file named `42' + +unset foo +: <$((foo+=42)) +echo $foo diff --git a/tests/varenv.right b/tests/varenv.right index 81cdd09f..90f3efc7 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -256,6 +256,10 @@ bbb 4 5 6 ccc 7 8 9 declare -a x=([0]="one" [1]="two" [2]="three") ./varenv19.sub: line 51: declare: x: not found +declare -x v="x" +declare -x v="t" +declare -- v +declare -x v a=z a=b a=z diff --git a/tests/varenv.tests b/tests/varenv.tests index 16371a85..42fb54db 100644 --- a/tests/varenv.tests +++ b/tests/varenv.tests @@ -257,6 +257,7 @@ ${THIS_SH} ./varenv16.sub ${THIS_SH} ./varenv17.sub ${THIS_SH} ./varenv18.sub ${THIS_SH} ./varenv19.sub +${THIS_SH} ./varenv20.sub # make sure variable scoping is done right tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv20.sub b/tests/varenv20.sub new file mode 100644 index 00000000..5fba8c4c --- /dev/null +++ b/tests/varenv20.sub @@ -0,0 +1,13 @@ +# tests of local variables with the same name as variables passed in the +# temporary environment + +f() { local v=x; local -p; } +v=t f + +f() { local v; declare -p v; } +v=t f + +f() { local v=x; unset v; declare -p v; } +v=g +f +v=t f