Additional checks to make sure we don't close /dev/tty by mistake.

When flushing, sleep in select as long as we have buffers that need
to be written out.
This commit is contained in:
Todd C. Miller
2010-05-18 18:50:20 -04:00
parent 6a2a182e0f
commit 0eec7335af

View File

@@ -433,6 +433,7 @@ perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw)
break; break;
} else if (n == 0) { } else if (n == 0) {
/* got EOF */ /* got EOF */
if (iob->rfd != script_fds[SFD_USERTTY])
close(iob->rfd); close(iob->rfd);
iob->rfd = -1; iob->rfd = -1;
} else { } else {
@@ -450,9 +451,11 @@ perform_io(struct io_buffer *iobufs, fd_set *fdsr, fd_set *fdsw)
if (errno == EPIPE) { if (errno == EPIPE) {
/* other end of pipe closed */ /* other end of pipe closed */
if (iob->rfd != -1) { if (iob->rfd != -1) {
if (iob->rfd != script_fds[SFD_USERTTY])
close(iob->rfd); close(iob->rfd);
iob->rfd = -1; iob->rfd = -1;
} }
if (iob->wfd != script_fds[SFD_USERTTY])
close(iob->wfd); close(iob->wfd);
iob->wfd = -1; iob->wfd = -1;
continue; continue;
@@ -1173,7 +1176,7 @@ flush_output(struct io_buffer *iobufs)
struct io_buffer *iob; struct io_buffer *iob;
struct timeval tv; struct timeval tv;
fd_set *fdsr, *fdsw; fd_set *fdsr, *fdsw;
int nready, maxfd = -1; int nready, nwriters, maxfd = -1;
/* Determine maxfd */ /* Determine maxfd */
for (iob = iobufs; iob; iob = iob->next) { for (iob = iobufs; iob; iob = iob->next) {
@@ -1189,9 +1192,10 @@ flush_output(struct io_buffer *iobufs)
zero_bytes(fdsw, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask)); zero_bytes(fdsw, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
zero_bytes(fdsr, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask)); zero_bytes(fdsr, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
nwriters = 0;
for (iob = iobufs; iob; iob = iob->next) { for (iob = iobufs; iob; iob = iob->next) {
/* Don't read from /dev/tty while flushing. */ /* Don't read from /dev/tty while flushing. */
if (iob->rfd == script_fds[SFD_USERTTY]) if (script_fds[SFD_USERTTY] != -1 && iob->rfd == script_fds[SFD_USERTTY])
continue; continue;
if (iob->rfd == -1 && iob->wfd == -1) if (iob->rfd == -1 && iob->wfd == -1)
continue; continue;
@@ -1209,15 +1213,17 @@ flush_output(struct io_buffer *iobufs)
FD_SET(iob->rfd, fdsr); FD_SET(iob->rfd, fdsr);
} }
if (iob->wfd != -1) { if (iob->wfd != -1) {
if (iob->len > iob->off) if (iob->len > iob->off) {
nwriters++;
FD_SET(iob->wfd, fdsw); FD_SET(iob->wfd, fdsw);
} }
} }
}
/* Effect a poll (no sleeping in select) */ /* Don't sleep in select if there are no buffers that need writing. */
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
nready = select(maxfd + 1, fdsr, fdsw, NULL, &tv); nready = select(maxfd + 1, fdsr, fdsw, NULL, nwriters ? NULL : &tv);
if (nready <= 0) { if (nready <= 0) {
if (nready == 0) if (nready == 0)
break; /* all I/O flushed */ break; /* all I/O flushed */