sh: Improve error handling in read builtin:
* If read -t times out, return status as if interrupted by SIGALRM (formerly 1). * If a trapped signal interrupts read, return status 128+sig (formerly 1). * If [EINTR] occurs but there is no trap, retry the read (for example because of a SIGWINCH in interactive mode). * If a read error occurs, write an error message and return status 2. As before, a variable assignment error returns 2 and discards the remaining data read.
This commit is contained in:
parent
6c21893360
commit
c4539460e3
@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "syntax.h"
|
||||
#include "trap.h"
|
||||
|
||||
#undef eflag
|
||||
|
||||
@ -102,6 +103,8 @@ readcmd(int argc __unused, char **argv __unused)
|
||||
struct timeval tv;
|
||||
char *tvptr;
|
||||
fd_set ifds;
|
||||
ssize_t nread;
|
||||
int sig;
|
||||
|
||||
rflag = 0;
|
||||
prompt = NULL;
|
||||
@ -156,8 +159,10 @@ readcmd(int argc __unused, char **argv __unused)
|
||||
/*
|
||||
* If there's nothing ready, return an error.
|
||||
*/
|
||||
if (status <= 0)
|
||||
return(1);
|
||||
if (status <= 0) {
|
||||
sig = pendingsig;
|
||||
return (128 + (sig != 0 ? sig : SIGALRM));
|
||||
}
|
||||
}
|
||||
|
||||
status = 0;
|
||||
@ -165,7 +170,19 @@ readcmd(int argc __unused, char **argv __unused)
|
||||
backslash = 0;
|
||||
STARTSTACKSTR(p);
|
||||
for (;;) {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
nread = read(STDIN_FILENO, &c, 1);
|
||||
if (nread == -1) {
|
||||
if (errno == EINTR) {
|
||||
sig = pendingsig;
|
||||
if (sig == 0)
|
||||
continue;
|
||||
status = 128 + sig;
|
||||
break;
|
||||
}
|
||||
warning("read error: %s", strerror(errno));
|
||||
status = 2;
|
||||
break;
|
||||
} else if (nread != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
|
11
bin/sh/sh.1
11
bin/sh/sh.1
@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 21, 2013
|
||||
.Dd May 3, 2013
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -2372,7 +2372,9 @@ option is specified and the
|
||||
elapses before a complete line of input is supplied,
|
||||
the
|
||||
.Ic read
|
||||
command will return an exit status of 1 without assigning any values.
|
||||
command will return an exit status as if terminated by
|
||||
.Dv SIGALRM
|
||||
without assigning any values.
|
||||
The
|
||||
.Ar timeout
|
||||
value may optionally be followed by one of
|
||||
@ -2388,6 +2390,11 @@ is assumed.
|
||||
The
|
||||
.Fl e
|
||||
option exists only for backward compatibility with older scripts.
|
||||
.Pp
|
||||
The exit status is 0 on success, 1 on end of file,
|
||||
between 2 and 128 if an error occurs
|
||||
and greater than 128 if a trapped signal interrupts
|
||||
.Ic read .
|
||||
.It Ic readonly Oo Fl p Oc Op Ar name ...
|
||||
Each specified
|
||||
.Ar name
|
||||
|
5
tools/regression/bin/sh/builtins/read7.0
Normal file
5
tools/regression/bin/sh/builtins/read7.0
Normal file
@ -0,0 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
{ errmsg=`read x <&- 2>&1 >&3`; } 3>&1
|
||||
r=$?
|
||||
[ "$r" -ge 2 ] && [ "$r" -le 128 ] && [ -n "$errmsg" ]
|
13
tools/regression/bin/sh/builtins/read8.0
Normal file
13
tools/regression/bin/sh/builtins/read8.0
Normal file
@ -0,0 +1,13 @@
|
||||
# $FreeBSD$
|
||||
|
||||
T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
|
||||
trap 'rm -rf $T' 0
|
||||
cd $T || exit 3
|
||||
mkfifo fifo1
|
||||
trapped=
|
||||
trap trapped=1 QUIT
|
||||
{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 &
|
||||
read dummy <fifo1
|
||||
r=$?
|
||||
kill $!
|
||||
[ "$r" -gt 128 ] && [ -n "$trapped" ]
|
Loading…
x
Reference in New Issue
Block a user