121575Sdist /* 221575Sdist * Copyright (c) 1980 Regents of the University of California. 321575Sdist * All rights reserved. The Berkeley software License Agreement 421575Sdist * specifies the terms and conditions for redistribution. 521575Sdist */ 621575Sdist 76318Swnj #ifndef lint 821575Sdist char copyright[] = 921575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021575Sdist All rights reserved.\n"; 1121575Sdist #endif not lint 1212990Ssam 1321575Sdist #ifndef lint 14*24450Sbloom static char sccsid[] = "@(#)script.c 5.2 (Berkeley) 08/28/85"; 1521575Sdist #endif not lint 1621575Sdist 171089Sbill /* 186318Swnj * script 191089Sbill */ 206318Swnj #include <stdio.h> 216318Swnj #include <signal.h> 226318Swnj #include <sys/types.h> 236318Swnj #include <sys/stat.h> 246318Swnj #include <sys/ioctl.h> 256318Swnj #include <sgtty.h> 2613621Ssam #include <sys/time.h> 2717589Ssam #include <sys/file.h> 281089Sbill 296318Swnj char *getenv(); 306318Swnj char *ctime(); 316318Swnj char *shell; 326318Swnj FILE *fscript; 336318Swnj int master; 346318Swnj int slave; 356318Swnj int child; 36*24450Sbloom int subchild; 376318Swnj char *fname = "typescript"; 386318Swnj int finish(); 391089Sbill 406318Swnj struct sgttyb b; 416318Swnj struct tchars tc; 426318Swnj struct ltchars lc; 4318029Sbloom struct winsize win; 446318Swnj int lb; 456318Swnj int l; 466318Swnj char *line = "/dev/ptyXX"; 476318Swnj int aflg; 481089Sbill 496318Swnj main(argc, argv) 506318Swnj int argc; 516318Swnj char *argv[]; 526318Swnj { 531089Sbill 541089Sbill shell = getenv("SHELL"); 556318Swnj if (shell == 0) 566318Swnj shell = "/bin/sh"; 576318Swnj argc--, argv++; 586318Swnj while (argc > 0 && argv[0][0] == '-') { 596318Swnj switch (argv[0][1]) { 601089Sbill 616318Swnj case 'a': 626318Swnj aflg++; 636318Swnj break; 641089Sbill 656318Swnj default: 666318Swnj fprintf(stderr, 676318Swnj "usage: script [ -a ] [ typescript ]\n"); 686318Swnj exit(1); 691089Sbill } 706318Swnj argc--, argv++; 711089Sbill } 726318Swnj if (argc > 0) 736318Swnj fname = argv[0]; 746318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 756318Swnj perror(fname); 761089Sbill fail(); 771089Sbill } 786318Swnj getmaster(); 796318Swnj printf("Script started, file is %s\n", fname); 806318Swnj fixtty(); 811089Sbill 826318Swnj (void) signal(SIGCHLD, finish); 836318Swnj child = fork(); 846318Swnj if (child < 0) { 856318Swnj perror("fork"); 866318Swnj fail(); 871089Sbill } 886318Swnj if (child == 0) { 89*24450Sbloom subchild = child = fork(); 90*24450Sbloom if (child < 0) { 916318Swnj perror("fork"); 926318Swnj fail(); 936318Swnj } 94*24450Sbloom if (child) 951089Sbill dooutput(); 966318Swnj else 976318Swnj doshell(); 981089Sbill } 996318Swnj doinput(); 1001089Sbill } 1011089Sbill 1021089Sbill doinput() 1031089Sbill { 1046318Swnj char ibuf[BUFSIZ]; 1056318Swnj int cc; 1061089Sbill 1076318Swnj (void) fclose(fscript); 1086318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1096318Swnj (void) write(master, ibuf, cc); 1106318Swnj done(); 1116318Swnj } 1121089Sbill 11313621Ssam #include <sys/wait.h> 1141089Sbill 1156318Swnj finish() 1166318Swnj { 1176318Swnj union wait status; 118*24450Sbloom register int pid; 119*24450Sbloom register int die = 0; 1201089Sbill 121*24450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 122*24450Sbloom if (pid == child) 123*24450Sbloom die = 1; 124*24450Sbloom 125*24450Sbloom if (die) 126*24450Sbloom done(); 1271089Sbill } 1281089Sbill 1291089Sbill dooutput() 1301089Sbill { 1316318Swnj time_t tvec; 1326318Swnj char obuf[BUFSIZ]; 1336318Swnj int cc; 1341089Sbill 1356318Swnj (void) close(0); 1366318Swnj tvec = time((time_t *)0); 1376318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1386318Swnj for (;;) { 1396318Swnj cc = read(master, obuf, sizeof (obuf)); 1406318Swnj if (cc <= 0) 1416318Swnj break; 1426318Swnj (void) write(1, obuf, cc); 1436318Swnj (void) fwrite(obuf, 1, cc, fscript); 1441089Sbill } 1456318Swnj tvec = time((time_t *)0); 1466318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 1476318Swnj (void) fclose(fscript); 1486318Swnj (void) close(master); 1491089Sbill exit(0); 1501089Sbill } 1511089Sbill 1521089Sbill doshell() 1531089Sbill { 1546318Swnj int t; 1551089Sbill 15617589Ssam t = open("/dev/tty", O_RDWR); 1576318Swnj if (t >= 0) { 1586318Swnj ioctl(t, TIOCNOTTY, (char *)0); 1596318Swnj (void) close(t); 1606318Swnj } 1616318Swnj getslave(); 1626318Swnj (void) close(master); 1636318Swnj (void) fclose(fscript); 1646318Swnj dup2(slave, 0); 1656318Swnj dup2(slave, 1); 1666318Swnj dup2(slave, 2); 1676318Swnj (void) close(slave); 1681089Sbill execl(shell, "sh", "-i", 0); 1696318Swnj perror(shell); 1701089Sbill fail(); 1711089Sbill } 1721089Sbill 1731089Sbill fixtty() 1741089Sbill { 1756318Swnj struct sgttyb sbuf; 1761089Sbill 1776318Swnj sbuf = b; 1786318Swnj sbuf.sg_flags |= RAW; 1796318Swnj sbuf.sg_flags &= ~ECHO; 1806318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1811089Sbill } 1821089Sbill 1831089Sbill fail() 1841089Sbill { 1851089Sbill 1866318Swnj (void) kill(0, SIGTERM); 1871089Sbill done(); 1881089Sbill } 1891089Sbill 1901089Sbill done() 1911089Sbill { 1921089Sbill 193*24450Sbloom if (!subchild) { 194*24450Sbloom ioctl(0, TIOCSETP, (char *)&b); 195*24450Sbloom printf("Script done, file is %s\n", fname); 196*24450Sbloom } 1976318Swnj exit(0); 1981089Sbill } 1991089Sbill 2006318Swnj getmaster() 2016318Swnj { 20217589Ssam char *pty, *bank, *cp; 2036318Swnj struct stat stb; 2046318Swnj int i; 2056318Swnj 20617589Ssam pty = &line[strlen("/dev/ptyp")]; 20717589Ssam for (bank = "pqrs"; *bank; bank++) { 20817589Ssam line[strlen("/dev/pty")] = *bank; 20917589Ssam *pty = '0'; 2106318Swnj if (stat(line, &stb) < 0) 2116318Swnj break; 21217589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 21317589Ssam *pty = *cp; 21417589Ssam master = open(line, O_RDWR); 2156318Swnj if (master >= 0) { 21617589Ssam char *tp = &line[strlen("/dev/")]; 21717589Ssam int ok; 21817589Ssam 21917589Ssam /* verify slave side is usable */ 22017589Ssam *tp = 't'; 22117589Ssam ok = access(line, R_OK|W_OK) == 0; 22217589Ssam *tp = 'p'; 22317589Ssam if (ok) { 22417589Ssam ioctl(0, TIOCGETP, (char *)&b); 22517589Ssam ioctl(0, TIOCGETC, (char *)&tc); 22617589Ssam ioctl(0, TIOCGETD, (char *)&l); 22717589Ssam ioctl(0, TIOCGLTC, (char *)&lc); 22817589Ssam ioctl(0, TIOCLGET, (char *)&lb); 22918029Sbloom ioctl(0, TIOCGWINSZ, (char *)&win); 23017589Ssam return; 23117589Ssam } 23217589Ssam close(master); 2336318Swnj } 2346318Swnj } 2356318Swnj } 2366318Swnj fprintf(stderr, "Out of pty's\n"); 2376318Swnj fail(); 2381089Sbill } 2391089Sbill 2406318Swnj getslave() 2411089Sbill { 2426318Swnj 2436318Swnj line[strlen("/dev/")] = 't'; 24417589Ssam slave = open(line, O_RDWR); 2456318Swnj if (slave < 0) { 2466318Swnj perror(line); 2476318Swnj fail(); 2481089Sbill } 2496318Swnj ioctl(slave, TIOCSETP, (char *)&b); 2506318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 2516318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 2526318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 2536318Swnj ioctl(slave, TIOCSETD, (char *)&l); 25418029Sbloom ioctl(slave, TIOCSWINSZ, (char *)&win); 2551089Sbill } 256