16318Swnj #ifndef lint 2*18029Sbloom static char *sccsid = "@(#)script.c 4.7 (Berkeley) 85/02/21"; 31089Sbill #endif 412990Ssam 51089Sbill /* 66318Swnj * script 71089Sbill */ 86318Swnj #include <stdio.h> 96318Swnj #include <signal.h> 106318Swnj #include <sys/types.h> 116318Swnj #include <sys/stat.h> 126318Swnj #include <sys/ioctl.h> 136318Swnj #include <sgtty.h> 1413621Ssam #include <sys/time.h> 1517589Ssam #include <sys/file.h> 161089Sbill 176318Swnj char *getenv(); 186318Swnj char *ctime(); 196318Swnj char *shell; 206318Swnj FILE *fscript; 216318Swnj int master; 226318Swnj int slave; 236318Swnj int child; 246318Swnj char *fname = "typescript"; 256318Swnj int finish(); 261089Sbill 276318Swnj struct sgttyb b; 286318Swnj struct tchars tc; 296318Swnj struct ltchars lc; 30*18029Sbloom struct winsize win; 316318Swnj int lb; 326318Swnj int l; 336318Swnj char *line = "/dev/ptyXX"; 346318Swnj int aflg; 351089Sbill 366318Swnj main(argc, argv) 376318Swnj int argc; 386318Swnj char *argv[]; 396318Swnj { 406318Swnj int f; 411089Sbill 421089Sbill shell = getenv("SHELL"); 436318Swnj if (shell == 0) 446318Swnj shell = "/bin/sh"; 456318Swnj argc--, argv++; 466318Swnj while (argc > 0 && argv[0][0] == '-') { 476318Swnj switch (argv[0][1]) { 481089Sbill 496318Swnj case 'a': 506318Swnj aflg++; 516318Swnj break; 521089Sbill 536318Swnj default: 546318Swnj fprintf(stderr, 556318Swnj "usage: script [ -a ] [ typescript ]\n"); 566318Swnj exit(1); 571089Sbill } 586318Swnj argc--, argv++; 591089Sbill } 606318Swnj if (argc > 0) 616318Swnj fname = argv[0]; 626318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 636318Swnj perror(fname); 641089Sbill fail(); 651089Sbill } 666318Swnj getmaster(); 676318Swnj printf("Script started, file is %s\n", fname); 686318Swnj fixtty(); 691089Sbill 706318Swnj (void) signal(SIGCHLD, finish); 716318Swnj child = fork(); 726318Swnj if (child < 0) { 736318Swnj perror("fork"); 746318Swnj fail(); 751089Sbill } 766318Swnj if (child == 0) { 776318Swnj f = fork(); 786318Swnj if (f < 0) { 796318Swnj perror("fork"); 806318Swnj fail(); 816318Swnj } 826318Swnj if (f) 831089Sbill dooutput(); 846318Swnj else 856318Swnj doshell(); 861089Sbill } 876318Swnj doinput(); 881089Sbill } 891089Sbill 901089Sbill doinput() 911089Sbill { 926318Swnj char ibuf[BUFSIZ]; 936318Swnj int cc; 941089Sbill 956318Swnj (void) fclose(fscript); 966318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 976318Swnj (void) write(master, ibuf, cc); 986318Swnj done(); 996318Swnj } 1001089Sbill 10113621Ssam #include <sys/wait.h> 1021089Sbill 1036318Swnj finish() 1046318Swnj { 1056318Swnj union wait status; 1061089Sbill 1076318Swnj if (wait3(&status, WNOHANG, 0) != child) 1086318Swnj return; 1091089Sbill done(); 1101089Sbill } 1111089Sbill 1121089Sbill dooutput() 1131089Sbill { 1146318Swnj time_t tvec; 1156318Swnj char obuf[BUFSIZ]; 1166318Swnj int cc; 1171089Sbill 1186318Swnj (void) close(0); 1196318Swnj tvec = time((time_t *)0); 1206318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1216318Swnj for (;;) { 1226318Swnj cc = read(master, obuf, sizeof (obuf)); 1236318Swnj if (cc <= 0) 1246318Swnj break; 1256318Swnj (void) write(1, obuf, cc); 1266318Swnj (void) fwrite(obuf, 1, cc, fscript); 1271089Sbill } 1286318Swnj tvec = time((time_t *)0); 1296318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 1306318Swnj (void) fclose(fscript); 1316318Swnj (void) close(master); 1321089Sbill exit(0); 1331089Sbill } 1341089Sbill 1351089Sbill doshell() 1361089Sbill { 1376318Swnj int t; 1381089Sbill 13917589Ssam t = open("/dev/tty", O_RDWR); 1406318Swnj if (t >= 0) { 1416318Swnj ioctl(t, TIOCNOTTY, (char *)0); 1426318Swnj (void) close(t); 1436318Swnj } 1446318Swnj getslave(); 1456318Swnj (void) close(master); 1466318Swnj (void) fclose(fscript); 1476318Swnj dup2(slave, 0); 1486318Swnj dup2(slave, 1); 1496318Swnj dup2(slave, 2); 1506318Swnj (void) close(slave); 1511089Sbill execl(shell, "sh", "-i", 0); 1526318Swnj perror(shell); 1531089Sbill fail(); 1541089Sbill } 1551089Sbill 1561089Sbill fixtty() 1571089Sbill { 1586318Swnj struct sgttyb sbuf; 1591089Sbill 1606318Swnj sbuf = b; 1616318Swnj sbuf.sg_flags |= RAW; 1626318Swnj sbuf.sg_flags &= ~ECHO; 1636318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1641089Sbill } 1651089Sbill 1661089Sbill fail() 1671089Sbill { 1681089Sbill 1696318Swnj (void) kill(0, SIGTERM); 1701089Sbill done(); 1711089Sbill } 1721089Sbill 1731089Sbill done() 1741089Sbill { 1751089Sbill 1766318Swnj ioctl(0, TIOCSETP, (char *)&b); 1776318Swnj printf("Script done, file is %s\n", fname); 1786318Swnj exit(0); 1791089Sbill } 1801089Sbill 1816318Swnj getmaster() 1826318Swnj { 18317589Ssam char *pty, *bank, *cp; 1846318Swnj struct stat stb; 1856318Swnj int i; 1866318Swnj 18717589Ssam pty = &line[strlen("/dev/ptyp")]; 18817589Ssam for (bank = "pqrs"; *bank; bank++) { 18917589Ssam line[strlen("/dev/pty")] = *bank; 19017589Ssam *pty = '0'; 1916318Swnj if (stat(line, &stb) < 0) 1926318Swnj break; 19317589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 19417589Ssam *pty = *cp; 19517589Ssam master = open(line, O_RDWR); 1966318Swnj if (master >= 0) { 19717589Ssam char *tp = &line[strlen("/dev/")]; 19817589Ssam int ok; 19917589Ssam 20017589Ssam /* verify slave side is usable */ 20117589Ssam *tp = 't'; 20217589Ssam ok = access(line, R_OK|W_OK) == 0; 20317589Ssam *tp = 'p'; 20417589Ssam if (ok) { 20517589Ssam ioctl(0, TIOCGETP, (char *)&b); 20617589Ssam ioctl(0, TIOCGETC, (char *)&tc); 20717589Ssam ioctl(0, TIOCGETD, (char *)&l); 20817589Ssam ioctl(0, TIOCGLTC, (char *)&lc); 20917589Ssam ioctl(0, TIOCLGET, (char *)&lb); 210*18029Sbloom ioctl(0, TIOCGWINSZ, (char *)&win); 21117589Ssam return; 21217589Ssam } 21317589Ssam close(master); 2146318Swnj } 2156318Swnj } 2166318Swnj } 2176318Swnj fprintf(stderr, "Out of pty's\n"); 2186318Swnj fail(); 2191089Sbill } 2201089Sbill 2216318Swnj getslave() 2221089Sbill { 2236318Swnj 2246318Swnj line[strlen("/dev/")] = 't'; 22517589Ssam slave = open(line, O_RDWR); 2266318Swnj if (slave < 0) { 2276318Swnj perror(line); 2286318Swnj fail(); 2291089Sbill } 2306318Swnj ioctl(slave, TIOCSETP, (char *)&b); 2316318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 2326318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 2336318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 2346318Swnj ioctl(slave, TIOCSETD, (char *)&l); 235*18029Sbloom ioctl(slave, TIOCSWINSZ, (char *)&win); 2361089Sbill } 237