19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1980, 1992, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 35236d2f55SPhilippe Charnier static const char copyright[] = 369b50d902SRodney W. Grimes "@(#) Copyright (c) 1980, 1992, 1993\n\ 379b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 389b50d902SRodney W. Grimes #endif /* not lint */ 399b50d902SRodney W. Grimes 409b50d902SRodney W. Grimes #ifndef lint 41236d2f55SPhilippe Charnier #if 0 429b50d902SRodney W. Grimes static char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93"; 43236d2f55SPhilippe Charnier #endif 44236d2f55SPhilippe Charnier static const char rcsid[] = 4551afb8dfSPeter Wemm "$Id: script.c,v 1.5 1997/08/08 12:24:49 charnier Exp $"; 469b50d902SRodney W. Grimes #endif /* not lint */ 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes #include <sys/types.h> 499b50d902SRodney W. Grimes #include <sys/wait.h> 509b50d902SRodney W. Grimes #include <sys/stat.h> 519b50d902SRodney W. Grimes #include <sys/ioctl.h> 529b50d902SRodney W. Grimes #include <sys/time.h> 539b50d902SRodney W. Grimes 54236d2f55SPhilippe Charnier #include <err.h> 559b50d902SRodney W. Grimes #include <fcntl.h> 56236d2f55SPhilippe Charnier #include <libutil.h> 579b50d902SRodney W. Grimes #include <paths.h> 589b50d902SRodney W. Grimes #include <signal.h> 599b50d902SRodney W. Grimes #include <stdio.h> 609b50d902SRodney W. Grimes #include <stdlib.h> 619b50d902SRodney W. Grimes #include <string.h> 629b50d902SRodney W. Grimes #include <termios.h> 639b50d902SRodney W. Grimes #include <unistd.h> 649b50d902SRodney W. Grimes 659b50d902SRodney W. Grimes FILE *fscript; 669b50d902SRodney W. Grimes int master, slave; 679b50d902SRodney W. Grimes int child, subchild; 689b50d902SRodney W. Grimes int outcc; 699b50d902SRodney W. Grimes char *fname; 7051afb8dfSPeter Wemm int qflg; 719b50d902SRodney W. Grimes 729b50d902SRodney W. Grimes struct termios tt; 739b50d902SRodney W. Grimes 74eaa86f9dSBruce Evans void done __P((void)) __dead2; 759b50d902SRodney W. Grimes void dooutput __P((void)); 7651afb8dfSPeter Wemm void doshell __P((char **)); 779b50d902SRodney W. Grimes void fail __P((void)); 789b50d902SRodney W. Grimes void finish __P((int)); 799b50d902SRodney W. Grimes void scriptflush __P((int)); 80236d2f55SPhilippe Charnier static void usage __P((void)); 819b50d902SRodney W. Grimes 829b50d902SRodney W. Grimes int 839b50d902SRodney W. Grimes main(argc, argv) 849b50d902SRodney W. Grimes int argc; 859b50d902SRodney W. Grimes char *argv[]; 869b50d902SRodney W. Grimes { 879b50d902SRodney W. Grimes register int cc; 889b50d902SRodney W. Grimes struct termios rtt; 899b50d902SRodney W. Grimes struct winsize win; 909b50d902SRodney W. Grimes int aflg, ch; 919b50d902SRodney W. Grimes char ibuf[BUFSIZ]; 929b50d902SRodney W. Grimes 939b50d902SRodney W. Grimes aflg = 0; 9451afb8dfSPeter Wemm while ((ch = getopt(argc, argv, "aq")) != -1) 959b50d902SRodney W. Grimes switch(ch) { 969b50d902SRodney W. Grimes case 'a': 979b50d902SRodney W. Grimes aflg = 1; 989b50d902SRodney W. Grimes break; 9951afb8dfSPeter Wemm case 'q': 10051afb8dfSPeter Wemm aflg = 1; 10151afb8dfSPeter Wemm break; 1029b50d902SRodney W. Grimes case '?': 1039b50d902SRodney W. Grimes default: 104236d2f55SPhilippe Charnier usage(); 1059b50d902SRodney W. Grimes } 1069b50d902SRodney W. Grimes argc -= optind; 1079b50d902SRodney W. Grimes argv += optind; 1089b50d902SRodney W. Grimes 10951afb8dfSPeter Wemm if (argc > 0) { 1109b50d902SRodney W. Grimes fname = argv[0]; 11151afb8dfSPeter Wemm argv++; 11251afb8dfSPeter Wemm argc--; 11351afb8dfSPeter Wemm } else 1149b50d902SRodney W. Grimes fname = "typescript"; 1159b50d902SRodney W. Grimes 1169b50d902SRodney W. Grimes if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) 117236d2f55SPhilippe Charnier err(1, "%s", fname); 1189b50d902SRodney W. Grimes 1199b50d902SRodney W. Grimes (void)tcgetattr(STDIN_FILENO, &tt); 1209b50d902SRodney W. Grimes (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win); 1219b50d902SRodney W. Grimes if (openpty(&master, &slave, NULL, &tt, &win) == -1) 122236d2f55SPhilippe Charnier err(1, "openpty"); 1239b50d902SRodney W. Grimes 12451afb8dfSPeter Wemm if (!qflg) 1259b50d902SRodney W. Grimes (void)printf("Script started, output file is %s\n", fname); 1269b50d902SRodney W. Grimes rtt = tt; 1279b50d902SRodney W. Grimes cfmakeraw(&rtt); 1289b50d902SRodney W. Grimes rtt.c_lflag &= ~ECHO; 1299b50d902SRodney W. Grimes (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); 1309b50d902SRodney W. Grimes 1319b50d902SRodney W. Grimes (void)signal(SIGCHLD, finish); 1329b50d902SRodney W. Grimes child = fork(); 1339b50d902SRodney W. Grimes if (child < 0) { 134236d2f55SPhilippe Charnier warn("fork"); 1359b50d902SRodney W. Grimes fail(); 1369b50d902SRodney W. Grimes } 1379b50d902SRodney W. Grimes if (child == 0) { 1389b50d902SRodney W. Grimes subchild = child = fork(); 1399b50d902SRodney W. Grimes if (child < 0) { 140236d2f55SPhilippe Charnier warn("fork"); 1419b50d902SRodney W. Grimes fail(); 1429b50d902SRodney W. Grimes } 1439b50d902SRodney W. Grimes if (child) 1449b50d902SRodney W. Grimes dooutput(); 1459b50d902SRodney W. Grimes else 14651afb8dfSPeter Wemm doshell(argv); 1479b50d902SRodney W. Grimes } 1489b50d902SRodney W. Grimes 1499b50d902SRodney W. Grimes (void)fclose(fscript); 1509b50d902SRodney W. Grimes while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) 1519b50d902SRodney W. Grimes (void)write(master, ibuf, cc); 1529b50d902SRodney W. Grimes done(); 1539b50d902SRodney W. Grimes } 1549b50d902SRodney W. Grimes 155236d2f55SPhilippe Charnier static void 156236d2f55SPhilippe Charnier usage() 157236d2f55SPhilippe Charnier { 15851afb8dfSPeter Wemm (void)fprintf(stderr, "usage: script [-a] [-q] [file] [command]\n"); 159236d2f55SPhilippe Charnier exit(1); 160236d2f55SPhilippe Charnier } 161236d2f55SPhilippe Charnier 1629b50d902SRodney W. Grimes void 1639b50d902SRodney W. Grimes finish(signo) 1649b50d902SRodney W. Grimes int signo; 1659b50d902SRodney W. Grimes { 1669b50d902SRodney W. Grimes register int die, pid; 1679b50d902SRodney W. Grimes union wait status; 1689b50d902SRodney W. Grimes 1699b50d902SRodney W. Grimes die = 0; 1709b50d902SRodney W. Grimes while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) 1719b50d902SRodney W. Grimes if (pid == child) 1729b50d902SRodney W. Grimes die = 1; 1739b50d902SRodney W. Grimes 1749b50d902SRodney W. Grimes if (die) 1759b50d902SRodney W. Grimes done(); 1769b50d902SRodney W. Grimes } 1779b50d902SRodney W. Grimes 1789b50d902SRodney W. Grimes void 1799b50d902SRodney W. Grimes dooutput() 1809b50d902SRodney W. Grimes { 1819b50d902SRodney W. Grimes struct itimerval value; 1829b50d902SRodney W. Grimes register int cc; 1839b50d902SRodney W. Grimes time_t tvec; 1849b50d902SRodney W. Grimes char obuf[BUFSIZ]; 1859b50d902SRodney W. Grimes 1869b50d902SRodney W. Grimes (void)close(STDIN_FILENO); 1879b50d902SRodney W. Grimes tvec = time(NULL); 18851afb8dfSPeter Wemm if (!qflg) 1899b50d902SRodney W. Grimes (void)fprintf(fscript, "Script started on %s", ctime(&tvec)); 1909b50d902SRodney W. Grimes 1919b50d902SRodney W. Grimes (void)signal(SIGALRM, scriptflush); 192656dcd43SGarrett Wollman value.it_interval.tv_sec = 60 / 2; 1939b50d902SRodney W. Grimes value.it_interval.tv_usec = 0; 1949b50d902SRodney W. Grimes value.it_value = value.it_interval; 1959b50d902SRodney W. Grimes (void)setitimer(ITIMER_REAL, &value, NULL); 1969b50d902SRodney W. Grimes for (;;) { 1979b50d902SRodney W. Grimes cc = read(master, obuf, sizeof (obuf)); 1989b50d902SRodney W. Grimes if (cc <= 0) 1999b50d902SRodney W. Grimes break; 2009b50d902SRodney W. Grimes (void)write(1, obuf, cc); 2019b50d902SRodney W. Grimes (void)fwrite(obuf, 1, cc, fscript); 2029b50d902SRodney W. Grimes outcc += cc; 2039b50d902SRodney W. Grimes } 2049b50d902SRodney W. Grimes done(); 2059b50d902SRodney W. Grimes } 2069b50d902SRodney W. Grimes 2079b50d902SRodney W. Grimes void 2089b50d902SRodney W. Grimes scriptflush(signo) 2099b50d902SRodney W. Grimes int signo; 2109b50d902SRodney W. Grimes { 2119b50d902SRodney W. Grimes if (outcc) { 2129b50d902SRodney W. Grimes (void)fflush(fscript); 2139b50d902SRodney W. Grimes outcc = 0; 2149b50d902SRodney W. Grimes } 2159b50d902SRodney W. Grimes } 2169b50d902SRodney W. Grimes 2179b50d902SRodney W. Grimes void 21851afb8dfSPeter Wemm doshell(av) 21951afb8dfSPeter Wemm char **av; 2209b50d902SRodney W. Grimes { 2219b50d902SRodney W. Grimes char *shell; 2229b50d902SRodney W. Grimes 2239b50d902SRodney W. Grimes shell = getenv("SHELL"); 2249b50d902SRodney W. Grimes if (shell == NULL) 2259b50d902SRodney W. Grimes shell = _PATH_BSHELL; 2269b50d902SRodney W. Grimes 2279b50d902SRodney W. Grimes (void)close(master); 2289b50d902SRodney W. Grimes (void)fclose(fscript); 2299b50d902SRodney W. Grimes login_tty(slave); 23051afb8dfSPeter Wemm if (av[0]) 23151afb8dfSPeter Wemm execv(av[0], av); 23251afb8dfSPeter Wemm else 2339b50d902SRodney W. Grimes execl(shell, "sh", "-i", NULL); 234236d2f55SPhilippe Charnier warn(shell); 2359b50d902SRodney W. Grimes fail(); 2369b50d902SRodney W. Grimes } 2379b50d902SRodney W. Grimes 2389b50d902SRodney W. Grimes void 2399b50d902SRodney W. Grimes fail() 2409b50d902SRodney W. Grimes { 2419b50d902SRodney W. Grimes 2429b50d902SRodney W. Grimes (void)kill(0, SIGTERM); 2439b50d902SRodney W. Grimes done(); 2449b50d902SRodney W. Grimes } 2459b50d902SRodney W. Grimes 2469b50d902SRodney W. Grimes void 2479b50d902SRodney W. Grimes done() 2489b50d902SRodney W. Grimes { 2499b50d902SRodney W. Grimes time_t tvec; 2509b50d902SRodney W. Grimes 2519b50d902SRodney W. Grimes if (subchild) { 2529b50d902SRodney W. Grimes tvec = time(NULL); 25351afb8dfSPeter Wemm if (!qflg) 2549b50d902SRodney W. Grimes (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 2559b50d902SRodney W. Grimes (void)fclose(fscript); 2569b50d902SRodney W. Grimes (void)close(master); 2579b50d902SRodney W. Grimes } else { 2589b50d902SRodney W. Grimes (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt); 25951afb8dfSPeter Wemm if (!qflg) 2609b50d902SRodney W. Grimes (void)printf("Script done, output file is %s\n", fname); 2619b50d902SRodney W. Grimes } 2629b50d902SRodney W. Grimes exit(0); 2639b50d902SRodney W. Grimes } 264