16318Swnj #ifndef lint 2*13621Ssam static char *sccsid = "@(#)script.c 4.5 (Berkeley) 83/07/02"; 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> 14*13621Ssam #include <sys/time.h> 151089Sbill 166318Swnj char *getenv(); 176318Swnj char *ctime(); 186318Swnj char *shell; 196318Swnj FILE *fscript; 206318Swnj int master; 216318Swnj int slave; 226318Swnj int child; 236318Swnj char *fname = "typescript"; 246318Swnj int finish(); 251089Sbill 266318Swnj struct sgttyb b; 276318Swnj struct tchars tc; 286318Swnj struct ltchars lc; 296318Swnj int lb; 306318Swnj int l; 316318Swnj char *line = "/dev/ptyXX"; 326318Swnj int aflg; 331089Sbill 346318Swnj main(argc, argv) 356318Swnj int argc; 366318Swnj char *argv[]; 376318Swnj { 386318Swnj int f; 391089Sbill 401089Sbill shell = getenv("SHELL"); 416318Swnj if (shell == 0) 426318Swnj shell = "/bin/sh"; 436318Swnj argc--, argv++; 446318Swnj while (argc > 0 && argv[0][0] == '-') { 456318Swnj switch (argv[0][1]) { 461089Sbill 476318Swnj case 'a': 486318Swnj aflg++; 496318Swnj break; 501089Sbill 516318Swnj default: 526318Swnj fprintf(stderr, 536318Swnj "usage: script [ -a ] [ typescript ]\n"); 546318Swnj exit(1); 551089Sbill } 566318Swnj argc--, argv++; 571089Sbill } 586318Swnj if (argc > 0) 596318Swnj fname = argv[0]; 606318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 616318Swnj perror(fname); 621089Sbill fail(); 631089Sbill } 646318Swnj getmaster(); 656318Swnj printf("Script started, file is %s\n", fname); 666318Swnj fixtty(); 671089Sbill 686318Swnj (void) signal(SIGCHLD, finish); 696318Swnj child = fork(); 706318Swnj if (child < 0) { 716318Swnj perror("fork"); 726318Swnj fail(); 731089Sbill } 746318Swnj if (child == 0) { 756318Swnj f = fork(); 766318Swnj if (f < 0) { 776318Swnj perror("fork"); 786318Swnj fail(); 796318Swnj } 806318Swnj if (f) 811089Sbill dooutput(); 826318Swnj else 836318Swnj doshell(); 841089Sbill } 856318Swnj doinput(); 861089Sbill } 871089Sbill 881089Sbill doinput() 891089Sbill { 906318Swnj char ibuf[BUFSIZ]; 916318Swnj int cc; 921089Sbill 936318Swnj (void) fclose(fscript); 946318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 956318Swnj (void) write(master, ibuf, cc); 966318Swnj done(); 976318Swnj } 981089Sbill 99*13621Ssam #include <sys/wait.h> 1001089Sbill 1016318Swnj finish() 1026318Swnj { 1036318Swnj union wait status; 1041089Sbill 1056318Swnj if (wait3(&status, WNOHANG, 0) != child) 1066318Swnj return; 1071089Sbill done(); 1081089Sbill } 1091089Sbill 1101089Sbill dooutput() 1111089Sbill { 1126318Swnj time_t tvec; 1136318Swnj char obuf[BUFSIZ]; 1146318Swnj int cc; 1151089Sbill 1166318Swnj (void) close(0); 1176318Swnj tvec = time((time_t *)0); 1186318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1196318Swnj for (;;) { 1206318Swnj cc = read(master, obuf, sizeof (obuf)); 1216318Swnj if (cc <= 0) 1226318Swnj break; 1236318Swnj (void) write(1, obuf, cc); 1246318Swnj (void) fwrite(obuf, 1, cc, fscript); 1251089Sbill } 1266318Swnj tvec = time((time_t *)0); 1276318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 1286318Swnj (void) fclose(fscript); 1296318Swnj (void) close(master); 1301089Sbill exit(0); 1311089Sbill } 1321089Sbill 1331089Sbill doshell() 1341089Sbill { 1356318Swnj int t; 1361089Sbill 1376318Swnj t = open("/dev/tty", 2); 1386318Swnj if (t >= 0) { 1396318Swnj ioctl(t, TIOCNOTTY, (char *)0); 1406318Swnj (void) close(t); 1416318Swnj } 1426318Swnj getslave(); 1436318Swnj (void) close(master); 1446318Swnj (void) fclose(fscript); 1456318Swnj dup2(slave, 0); 1466318Swnj dup2(slave, 1); 1476318Swnj dup2(slave, 2); 1486318Swnj (void) close(slave); 1491089Sbill execl(shell, "sh", "-i", 0); 1506318Swnj perror(shell); 1511089Sbill fail(); 1521089Sbill } 1531089Sbill 1541089Sbill fixtty() 1551089Sbill { 1566318Swnj struct sgttyb sbuf; 1571089Sbill 1586318Swnj sbuf = b; 1596318Swnj sbuf.sg_flags |= RAW; 1606318Swnj sbuf.sg_flags &= ~ECHO; 1616318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1621089Sbill } 1631089Sbill 1641089Sbill fail() 1651089Sbill { 1661089Sbill 1676318Swnj (void) kill(0, SIGTERM); 1681089Sbill done(); 1691089Sbill } 1701089Sbill 1711089Sbill done() 1721089Sbill { 1731089Sbill 1746318Swnj ioctl(0, TIOCSETP, (char *)&b); 1756318Swnj printf("Script done, file is %s\n", fname); 1766318Swnj exit(0); 1771089Sbill } 1781089Sbill 1796318Swnj getmaster() 1806318Swnj { 1816318Swnj char c; 1826318Swnj struct stat stb; 1836318Swnj int i; 1846318Swnj 1856318Swnj for (c = 'p'; c <= 's'; c++) { 1866318Swnj line[strlen("/dev/pty")] = c; 1876318Swnj line[strlen("/dev/ptyp")] = '0'; 1886318Swnj if (stat(line, &stb) < 0) 1896318Swnj break; 1906318Swnj for (i = 0; i < 16; i++) { 1916318Swnj line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 1926318Swnj master = open(line, 2); 1936318Swnj if (master >= 0) { 1946318Swnj ioctl(0, TIOCGETP, (char *)&b); 1956318Swnj ioctl(0, TIOCGETC, (char *)&tc); 1966318Swnj ioctl(0, TIOCGETD, (char *)&l); 1976318Swnj ioctl(0, TIOCGLTC, (char *)&lc); 1986318Swnj ioctl(0, TIOCLGET, (char *)&lb); 1996318Swnj return; 2006318Swnj } 2016318Swnj } 2026318Swnj } 2036318Swnj fprintf(stderr, "Out of pty's\n"); 2046318Swnj fail(); 2051089Sbill } 2061089Sbill 2076318Swnj getslave() 2081089Sbill { 2096318Swnj 2106318Swnj line[strlen("/dev/")] = 't'; 2116318Swnj slave = open(line, 2); 2126318Swnj if (slave < 0) { 2136318Swnj perror(line); 2146318Swnj fail(); 2151089Sbill } 2166318Swnj ioctl(slave, TIOCSETP, (char *)&b); 2176318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 2186318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 2196318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 2206318Swnj ioctl(slave, TIOCSETD, (char *)&l); 2211089Sbill } 222