summaryrefslogtreecommitdiffstats
path: root/usr.bin/script/script.c
diff options
context:
space:
mode:
authortrociny <trociny@FreeBSD.org>2011-09-27 18:14:04 +0000
committertrociny <trociny@FreeBSD.org>2011-09-27 18:14:04 +0000
commit49d59b07385eea8e7512006f40a73580d4cef33a (patch)
tree72bc761ace1637d1fb035fc7bf1a0ab4c9fe17d8 /usr.bin/script/script.c
parent43a4fd1bbd77bcc9aa1d36d874dcf151b4f08554 (diff)
downloadFreeBSD-src-49d59b07385eea8e7512006f40a73580d4cef33a.zip
FreeBSD-src-49d59b07385eea8e7512006f40a73580d4cef33a.tar.gz
When script(1) reads EOF from input it starts spinning on zero-byte
reads eating 100% CPU. Fix this by skipping select on STDIN after reading EOF -- permanently if STDIN is not terminal and for one second if it is. Also after reading EOF from STDIN we have to pass it to the program being scripted. The previous approach was to write zero bytes into the pseudo-terminal. This does not work because zero-byte write does not have any effect on read. Fix this by sending VEOF instead. Submitted by: Ronald Klop <ronald-freebsd8@klop.yi.org> Discussed with: kib, Chris Torek <chris.torek@gmail.com> Approved by: kib MFC after: 1 week
Diffstat (limited to 'usr.bin/script/script.c')
-rw-r--r--usr.bin/script/script.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c
index ad99721..ea5a1f6 100644
--- a/usr.bin/script/script.c
+++ b/usr.bin/script/script.c
@@ -86,6 +86,7 @@ main(int argc, char *argv[])
char ibuf[BUFSIZ];
fd_set rfd;
int flushtime = 30;
+ int readstdin;
aflg = kflg = 0;
while ((ch = getopt(argc, argv, "aqkt:")) != -1)
@@ -155,19 +156,21 @@ main(int argc, char *argv[])
doshell(argv);
close(slave);
- if (flushtime > 0)
- tvp = &tv;
- else
- tvp = NULL;
-
- start = time(0);
- FD_ZERO(&rfd);
+ start = tvec = time(0);
+ readstdin = 1;
for (;;) {
+ FD_ZERO(&rfd);
FD_SET(master, &rfd);
- FD_SET(STDIN_FILENO, &rfd);
- if (flushtime > 0) {
- tv.tv_sec = flushtime;
+ if (readstdin)
+ FD_SET(STDIN_FILENO, &rfd);
+ if ((!readstdin && ttyflg) || flushtime > 0) {
+ tv.tv_sec = !readstdin && ttyflg ? 1 :
+ flushtime - (tvec - start);
tv.tv_usec = 0;
+ tvp = &tv;
+ readstdin = 1;
+ } else {
+ tvp = NULL;
}
n = select(master + 1, &rfd, 0, 0, tvp);
if (n < 0 && errno != EINTR)
@@ -176,8 +179,13 @@ main(int argc, char *argv[])
cc = read(STDIN_FILENO, ibuf, BUFSIZ);
if (cc < 0)
break;
- if (cc == 0)
- (void)write(master, ibuf, 0);
+ if (cc == 0) {
+ if (tcgetattr(master, &stt) == 0 &&
+ (stt.c_lflag & ICANON) != 0) {
+ (void)write(master, &stt.c_cc[VEOF], 1);
+ }
+ readstdin = 0;
+ }
if (cc > 0) {
(void)write(master, ibuf, cc);
if (kflg && tcgetattr(master, &stt) >= 0 &&
OpenPOWER on IntegriCloud