121575Sdist /* 2*56926Sbostic * Copyright (c) 1980, 1992 Regents of the University of California. 334628Sbostic * All rights reserved. 434628Sbostic * 542765Sbostic * %sccs.include.redist.c% 621575Sdist */ 721575Sdist 86318Swnj #ifndef lint 921575Sdist char copyright[] = 10*56926Sbostic "@(#) Copyright (c) 1980, 1992 Regents of the University of California.\n\ 1121575Sdist All rights reserved.\n"; 1234628Sbostic #endif /* not lint */ 1312990Ssam 1421575Sdist #ifndef lint 15*56926Sbostic static char sccsid[] = "@(#)script.c 5.15 (Berkeley) 11/30/92"; 1634628Sbostic #endif /* not lint */ 1721575Sdist 186318Swnj #include <sys/types.h> 19*56926Sbostic #include <sys/wait.h> 206318Swnj #include <sys/stat.h> 216318Swnj #include <sys/ioctl.h> 2213621Ssam #include <sys/time.h> 23*56926Sbostic 24*56926Sbostic #include <errno.h> 25*56926Sbostic #include <fcntl.h> 26*56926Sbostic #include <paths.h> 27*56926Sbostic #include <signal.h> 2834628Sbostic #include <stdio.h> 29*56926Sbostic #include <stdlib.h> 30*56926Sbostic #include <string.h> 31*56926Sbostic #include <termios.h> 32*56926Sbostic #include <tzfile.h> 33*56926Sbostic #include <unistd.h> 341089Sbill 356318Swnj FILE *fscript; 36*56926Sbostic int master, slave; 37*56926Sbostic int child, subchild; 38*56926Sbostic int outcc; 3934628Sbostic char *fname; 401089Sbill 4137141Smarc struct termios tt; 421089Sbill 43*56926Sbostic __dead void done __P((void)); 44*56926Sbostic void dooutput __P((void)); 45*56926Sbostic void doshell __P((void)); 46*56926Sbostic void err __P((const char *, ...)); 47*56926Sbostic void fail __P((void)); 48*56926Sbostic void finish __P((int)); 49*56926Sbostic void scriptflush __P((int)); 50*56926Sbostic 51*56926Sbostic int 526318Swnj main(argc, argv) 536318Swnj int argc; 546318Swnj char *argv[]; 556318Swnj { 56*56926Sbostic register int cc; 57*56926Sbostic struct termios rtt; 58*56926Sbostic struct winsize win; 59*56926Sbostic int aflg, ch; 60*56926Sbostic char ibuf[BUFSIZ]; 611089Sbill 62*56926Sbostic aflg = 0; 6334628Sbostic while ((ch = getopt(argc, argv, "a")) != EOF) 64*56926Sbostic switch(ch) { 656318Swnj case 'a': 66*56926Sbostic aflg = 1; 676318Swnj break; 6834628Sbostic case '?': 696318Swnj default: 70*56926Sbostic (void)fprintf(stderr, "usage: script [-a] [file]\n"); 716318Swnj exit(1); 721089Sbill } 7334628Sbostic argc -= optind; 7434628Sbostic argv += optind; 7534628Sbostic 766318Swnj if (argc > 0) 776318Swnj fname = argv[0]; 7834628Sbostic else 7934628Sbostic fname = "typescript"; 8034628Sbostic 81*56926Sbostic if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) 82*56926Sbostic err("%s: %s", fname, strerror(errno)); 8334628Sbostic 84*56926Sbostic (void)tcgetattr(STDIN_FILENO, &tt); 85*56926Sbostic (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win); 86*56926Sbostic if (openpty(&master, &slave, NULL, &tt, &win) == -1) 87*56926Sbostic err("openpty: %s", strerror(errno)); 8850403Smarc 89*56926Sbostic (void)printf("Script started, output file is %s\n", fname); 90*56926Sbostic rtt = tt; 91*56926Sbostic cfmakeraw(&rtt); 92*56926Sbostic rtt.c_lflag &= ~ECHO; 93*56926Sbostic (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); 941089Sbill 95*56926Sbostic (void)signal(SIGCHLD, finish); 966318Swnj child = fork(); 976318Swnj if (child < 0) { 986318Swnj perror("fork"); 996318Swnj fail(); 1001089Sbill } 1016318Swnj if (child == 0) { 10224450Sbloom subchild = child = fork(); 10324450Sbloom if (child < 0) { 1046318Swnj perror("fork"); 1056318Swnj fail(); 1066318Swnj } 10724450Sbloom if (child) 1081089Sbill dooutput(); 1096318Swnj else 1106318Swnj doshell(); 1111089Sbill } 1121089Sbill 113*56926Sbostic (void)fclose(fscript); 114*56926Sbostic while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) 115*56926Sbostic (void)write(master, ibuf, cc); 1166318Swnj done(); 1176318Swnj } 1181089Sbill 11946853Sbostic void 120*56926Sbostic finish(signo) 121*56926Sbostic int signo; 1226318Swnj { 123*56926Sbostic register int die, pid; 1246318Swnj union wait status; 1251089Sbill 126*56926Sbostic die = 0; 12746853Sbostic while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) 12824450Sbloom if (pid == child) 12924450Sbloom die = 1; 13024450Sbloom 13124450Sbloom if (die) 13224450Sbloom done(); 1331089Sbill } 1341089Sbill 135*56926Sbostic void 1361089Sbill dooutput() 1371089Sbill { 138*56926Sbostic struct itimerval value; 13934628Sbostic register int cc; 140*56926Sbostic time_t tvec; 141*56926Sbostic char obuf[BUFSIZ]; 1421089Sbill 143*56926Sbostic (void)close(STDIN_FILENO); 144*56926Sbostic tvec = time(NULL); 145*56926Sbostic (void)fprintf(fscript, "Script started on %s", ctime(&tvec)); 146*56926Sbostic 147*56926Sbostic (void)signal(SIGALRM, scriptflush); 148*56926Sbostic value.it_interval.tv_sec = SECSPERMIN / 2; 149*56926Sbostic value.it_interval.tv_usec = 0; 150*56926Sbostic value.it_value = value.it_interval; 151*56926Sbostic (void)setitimer(ITIMER_REAL, &value, NULL); 1526318Swnj for (;;) { 1536318Swnj cc = read(master, obuf, sizeof (obuf)); 1546318Swnj if (cc <= 0) 1556318Swnj break; 156*56926Sbostic (void)write(1, obuf, cc); 157*56926Sbostic (void)fwrite(obuf, 1, cc, fscript); 158*56926Sbostic outcc += cc; 1591089Sbill } 16025473Sserge done(); 1611089Sbill } 1621089Sbill 163*56926Sbostic void 164*56926Sbostic scriptflush(signo) 165*56926Sbostic int signo; 166*56926Sbostic { 167*56926Sbostic if (outcc) { 168*56926Sbostic (void)fflush(fscript); 169*56926Sbostic outcc = 0; 170*56926Sbostic } 171*56926Sbostic } 172*56926Sbostic 173*56926Sbostic void 1741089Sbill doshell() 1751089Sbill { 176*56926Sbostic char *shell; 1771089Sbill 178*56926Sbostic shell = getenv("SHELL"); 179*56926Sbostic if (shell == NULL) 180*56926Sbostic shell = _PATH_BSHELL; 181*56926Sbostic 182*56926Sbostic (void)close(master); 183*56926Sbostic (void)fclose(fscript); 18450403Smarc login_tty(slave); 185*56926Sbostic execl(shell, "sh", "-i", NULL); 1866318Swnj perror(shell); 1871089Sbill fail(); 1881089Sbill } 1891089Sbill 190*56926Sbostic void 1911089Sbill fail() 1921089Sbill { 1931089Sbill 194*56926Sbostic (void)kill(0, SIGTERM); 1951089Sbill done(); 1961089Sbill } 1971089Sbill 198*56926Sbostic void 1991089Sbill done() 2001089Sbill { 201*56926Sbostic time_t tvec; 2021089Sbill 20325473Sserge if (subchild) { 204*56926Sbostic tvec = time(NULL); 205*56926Sbostic (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 206*56926Sbostic (void)fclose(fscript); 207*56926Sbostic (void)close(master); 20825473Sserge } else { 209*56926Sbostic (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt); 210*56926Sbostic (void)printf("Script done, output file is %s\n", fname); 21124450Sbloom } 2126318Swnj exit(0); 2131089Sbill } 214*56926Sbostic 215*56926Sbostic #if __STDC__ 216*56926Sbostic #include <stdarg.h> 217*56926Sbostic #else 218*56926Sbostic #include <varargs.h> 219*56926Sbostic #endif 220*56926Sbostic 221*56926Sbostic void 222*56926Sbostic #if __STDC__ 223*56926Sbostic err(const char *fmt, ...) 224*56926Sbostic #else 225*56926Sbostic err(fmt, va_alist) 226*56926Sbostic char *fmt; 227*56926Sbostic va_dcl 228*56926Sbostic #endif 229*56926Sbostic { 230*56926Sbostic va_list ap; 231*56926Sbostic #if __STDC__ 232*56926Sbostic va_start(ap, fmt); 233*56926Sbostic #else 234*56926Sbostic va_start(ap); 235*56926Sbostic #endif 236*56926Sbostic (void)fprintf(stderr, "script: "); 237*56926Sbostic (void)vfprintf(stderr, fmt, ap); 238*56926Sbostic va_end(ap); 239*56926Sbostic (void)fprintf(stderr, "\n"); 240*56926Sbostic exit(1); 241*56926Sbostic /* NOTREACHED */ 242*56926Sbostic } 243