diff options
Diffstat (limited to 'usr.bin/script/script.c')
-rw-r--r-- | usr.bin/script/script.c | 152 |
1 files changed, 104 insertions, 48 deletions
diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c index 972a1cf405a..f530a6cdd73 100644 --- a/usr.bin/script/script.c +++ b/usr.bin/script/script.c @@ -1,7 +1,32 @@ -/* $OpenBSD: script.c,v 1.15 2001/07/09 07:04:52 deraadt Exp $ */ +/* $OpenBSD: script.c,v 1.16 2001/11/18 23:51:57 deraadt Exp $ */ /* $NetBSD: script.c,v 1.3 1994/12/21 08:55:43 jtc Exp $ */ /* + * Copyright (c) 2001 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -44,7 +69,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93"; #endif -static char rcsid[] = "$OpenBSD: script.c,v 1.15 2001/07/09 07:04:52 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: script.c,v 1.16 2001/11/18 23:51:57 deraadt Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -69,31 +94,34 @@ static char rcsid[] = "$OpenBSD: script.c,v 1.15 2001/07/09 07:04:52 deraadt Exp FILE *fscript; int master, slave; -int child, subchild; -int outcc; +pid_t child, subchild; char *fname; -struct termios tt; +volatile sig_atomic_t dead; +volatile sig_atomic_t sigdeadstatus; +volatile sig_atomic_t flush; -__dead void done __P((int)); - void dooutput __P((void)); - void doshell __P((void)); - void fail __P((void)); - void finish __P((int)); - void scriptflush __P((int)); - void handlesigwinch __P((int)); +struct termios tt; +__dead void done __P((int)); +void dooutput __P((void)); +void doshell __P((void)); +void fail __P((void)); +void finish __P((int)); +void scriptflush __P((int)); +void handlesigwinch __P((int)); int main(argc, argv) int argc; char *argv[]; { - register int cc; + struct sigaction sa; struct termios rtt; struct winsize win; - int aflg, ch; char ibuf[BUFSIZ]; + ssize_t cc, off; + int aflg, ch; aflg = 0; while ((ch = getopt(argc, argv, "a")) != -1) @@ -101,7 +129,6 @@ main(argc, argv) case 'a': aflg = 1; break; - case '?': default: (void)fprintf(stderr, "usage: script [-a] [file]\n"); exit(1); @@ -128,8 +155,15 @@ main(argc, argv) rtt.c_lflag &= ~ECHO; (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); - (void)signal(SIGWINCH, handlesigwinch); - (void)signal(SIGCHLD, finish); + bzero(&sa, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = finish; + (void)sigaction(SIGCHLD, &sa, NULL); + + sa.sa_handler = handlesigwinch; + sa.sa_flags = SA_RESTART; + (void)sigaction(SIGWINCH, &sa, NULL); + child = fork(); if (child < 0) { perror("fork"); @@ -148,31 +182,41 @@ main(argc, argv) } (void)fclose(fscript); - while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) - (void)write(master, ibuf, cc); - done(0); + while (1) { + if (dead) + break; + cc = read(STDIN_FILENO, ibuf, BUFSIZ); + if (cc == -1 && errno == EINTR) + continue; + if (cc <= 0) + break; + for (off = 0; off < cc; ) { + ssize_t n = write(master, ibuf + off, cc - off); + if (n == 0) + break; /* skip writing */ + if (n > 0) + off += n; + } + } + done(sigdeadstatus); } void finish(signo) int signo; { - register int die, pid; int save_errno = errno; - int status, e; + int status, e = 1; + pid_t pid; - die = e = 0; - while ((pid = wait3(&status, WNOHANG, 0)) > 0) + while ((pid = wait3(&status, WNOHANG, 0)) > 0) { if (pid == child) { - die = 1; if (WIFEXITED(status)) - e = WEXITSTATUS(status); - else - e = 1; + e = WEXITSTATUS(status); } - - if (die) - done(e); + } + dead = 1; + sigdeadstatus = e; errno = save_errno; } @@ -180,14 +224,14 @@ void handlesigwinch(signo) int signo; { + int save_errno = errno; struct winsize win; pid_t pgrp; - int save_errno = errno; if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1) { - ioctl(slave, TIOCSWINSZ, &win); - if (ioctl(slave, TIOCGPGRP, &pgrp) != -1) - killpg(pgrp, SIGWINCH); + ioctl(slave, TIOCSWINSZ, &win); + if (ioctl(slave, TIOCGPGRP, &pgrp) != -1) + killpg(pgrp, SIGWINCH); } errno = save_errno; } @@ -195,43 +239,56 @@ handlesigwinch(signo) void dooutput() { + struct sigaction sa; struct itimerval value; - register int cc; - time_t tvec; char obuf[BUFSIZ]; + time_t tvec; + ssize_t outcc = 0, cc, off; (void)close(STDIN_FILENO); tvec = time(NULL); (void)fprintf(fscript, "Script started on %s", ctime(&tvec)); - (void)signal(SIGALRM, scriptflush); + bzero(&sa, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = scriptflush; + (void)sigaction(SIGALRM, &sa, NULL); + value.it_interval.tv_sec = SECSPERMIN / 2; value.it_interval.tv_usec = 0; value.it_value = value.it_interval; (void)setitimer(ITIMER_REAL, &value, NULL); for (;;) { + if (flush) { + if (outcc) { + (void)fflush(fscript); + outcc = 0; + } + flush = 0; + } cc = read(master, obuf, sizeof (obuf)); + if (cc == -1 && errno == EINTR) + continue; if (cc <= 0) break; - (void)write(1, obuf, cc); + for (off = 0; off < cc; ) { + ssize_t n = write(1, obuf + off, cc - off); + if (n == 0) + break; /* skip writing */ + if (n > 0) + off += n; + } (void)fwrite(obuf, 1, cc, fscript); outcc += cc; } done(0); } -/* XXX totally illegal race */ void scriptflush(signo) int signo; { - int save_errno = errno; - - if (outcc) { - (void)fflush(fscript); - outcc = 0; - } - errno = save_errno; + flush = 1; } void @@ -276,4 +333,3 @@ done(eval) } exit(eval); } - |