summaryrefslogtreecommitdiffstats
path: root/usr.bin/script/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/script/script.c')
-rw-r--r--usr.bin/script/script.c152
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);
}
-