16318Swnj #ifndef lint 2*17589Ssam static char *sccsid = "@(#)script.c 4.6 (Berkeley) 84/12/23"; 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> 15*17589Ssam #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; 306318Swnj int lb; 316318Swnj int l; 326318Swnj char *line = "/dev/ptyXX"; 336318Swnj int aflg; 341089Sbill 356318Swnj main(argc, argv) 366318Swnj int argc; 376318Swnj char *argv[]; 386318Swnj { 396318Swnj int f; 401089Sbill 411089Sbill shell = getenv("SHELL"); 426318Swnj if (shell == 0) 436318Swnj shell = "/bin/sh"; 446318Swnj argc--, argv++; 456318Swnj while (argc > 0 && argv[0][0] == '-') { 466318Swnj switch (argv[0][1]) { 471089Sbill 486318Swnj case 'a': 496318Swnj aflg++; 506318Swnj break; 511089Sbill 526318Swnj default: 536318Swnj fprintf(stderr, 546318Swnj "usage: script [ -a ] [ typescript ]\n"); 556318Swnj exit(1); 561089Sbill } 576318Swnj argc--, argv++; 581089Sbill } 596318Swnj if (argc > 0) 606318Swnj fname = argv[0]; 616318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 626318Swnj perror(fname); 631089Sbill fail(); 641089Sbill } 656318Swnj getmaster(); 666318Swnj printf("Script started, file is %s\n", fname); 676318Swnj fixtty(); 681089Sbill 696318Swnj (void) signal(SIGCHLD, finish); 706318Swnj child = fork(); 716318Swnj if (child < 0) { 726318Swnj perror("fork"); 736318Swnj fail(); 741089Sbill } 756318Swnj if (child == 0) { 766318Swnj f = fork(); 776318Swnj if (f < 0) { 786318Swnj perror("fork"); 796318Swnj fail(); 806318Swnj } 816318Swnj if (f) 821089Sbill dooutput(); 836318Swnj else 846318Swnj doshell(); 851089Sbill } 866318Swnj doinput(); 871089Sbill } 881089Sbill 891089Sbill doinput() 901089Sbill { 916318Swnj char ibuf[BUFSIZ]; 926318Swnj int cc; 931089Sbill 946318Swnj (void) fclose(fscript); 956318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 966318Swnj (void) write(master, ibuf, cc); 976318Swnj done(); 986318Swnj } 991089Sbill 10013621Ssam #include <sys/wait.h> 1011089Sbill 1026318Swnj finish() 1036318Swnj { 1046318Swnj union wait status; 1051089Sbill 1066318Swnj if (wait3(&status, WNOHANG, 0) != child) 1076318Swnj return; 1081089Sbill done(); 1091089Sbill } 1101089Sbill 1111089Sbill dooutput() 1121089Sbill { 1136318Swnj time_t tvec; 1146318Swnj char obuf[BUFSIZ]; 1156318Swnj int cc; 1161089Sbill 1176318Swnj (void) close(0); 1186318Swnj tvec = time((time_t *)0); 1196318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1206318Swnj for (;;) { 1216318Swnj cc = read(master, obuf, sizeof (obuf)); 1226318Swnj if (cc <= 0) 1236318Swnj break; 1246318Swnj (void) write(1, obuf, cc); 1256318Swnj (void) fwrite(obuf, 1, cc, fscript); 1261089Sbill } 1276318Swnj tvec = time((time_t *)0); 1286318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 1296318Swnj (void) fclose(fscript); 1306318Swnj (void) close(master); 1311089Sbill exit(0); 1321089Sbill } 1331089Sbill 1341089Sbill doshell() 1351089Sbill { 1366318Swnj int t; 1371089Sbill 138*17589Ssam t = open("/dev/tty", O_RDWR); 1396318Swnj if (t >= 0) { 1406318Swnj ioctl(t, TIOCNOTTY, (char *)0); 1416318Swnj (void) close(t); 1426318Swnj } 1436318Swnj getslave(); 1446318Swnj (void) close(master); 1456318Swnj (void) fclose(fscript); 1466318Swnj dup2(slave, 0); 1476318Swnj dup2(slave, 1); 1486318Swnj dup2(slave, 2); 1496318Swnj (void) close(slave); 1501089Sbill execl(shell, "sh", "-i", 0); 1516318Swnj perror(shell); 1521089Sbill fail(); 1531089Sbill } 1541089Sbill 1551089Sbill fixtty() 1561089Sbill { 1576318Swnj struct sgttyb sbuf; 1581089Sbill 1596318Swnj sbuf = b; 1606318Swnj sbuf.sg_flags |= RAW; 1616318Swnj sbuf.sg_flags &= ~ECHO; 1626318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1631089Sbill } 1641089Sbill 1651089Sbill fail() 1661089Sbill { 1671089Sbill 1686318Swnj (void) kill(0, SIGTERM); 1691089Sbill done(); 1701089Sbill } 1711089Sbill 1721089Sbill done() 1731089Sbill { 1741089Sbill 1756318Swnj ioctl(0, TIOCSETP, (char *)&b); 1766318Swnj printf("Script done, file is %s\n", fname); 1776318Swnj exit(0); 1781089Sbill } 1791089Sbill 1806318Swnj getmaster() 1816318Swnj { 182*17589Ssam char *pty, *bank, *cp; 1836318Swnj struct stat stb; 1846318Swnj int i; 1856318Swnj 186*17589Ssam pty = &line[strlen("/dev/ptyp")]; 187*17589Ssam for (bank = "pqrs"; *bank; bank++) { 188*17589Ssam line[strlen("/dev/pty")] = *bank; 189*17589Ssam *pty = '0'; 1906318Swnj if (stat(line, &stb) < 0) 1916318Swnj break; 192*17589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 193*17589Ssam *pty = *cp; 194*17589Ssam master = open(line, O_RDWR); 1956318Swnj if (master >= 0) { 196*17589Ssam char *tp = &line[strlen("/dev/")]; 197*17589Ssam int ok; 198*17589Ssam 199*17589Ssam /* verify slave side is usable */ 200*17589Ssam *tp = 't'; 201*17589Ssam ok = access(line, R_OK|W_OK) == 0; 202*17589Ssam *tp = 'p'; 203*17589Ssam if (ok) { 204*17589Ssam ioctl(0, TIOCGETP, (char *)&b); 205*17589Ssam ioctl(0, TIOCGETC, (char *)&tc); 206*17589Ssam ioctl(0, TIOCGETD, (char *)&l); 207*17589Ssam ioctl(0, TIOCGLTC, (char *)&lc); 208*17589Ssam ioctl(0, TIOCLGET, (char *)&lb); 209*17589Ssam return; 210*17589Ssam } 211*17589Ssam close(master); 2126318Swnj } 2136318Swnj } 2146318Swnj } 2156318Swnj fprintf(stderr, "Out of pty's\n"); 2166318Swnj fail(); 2171089Sbill } 2181089Sbill 2196318Swnj getslave() 2201089Sbill { 2216318Swnj 2226318Swnj line[strlen("/dev/")] = 't'; 223*17589Ssam slave = open(line, O_RDWR); 2246318Swnj if (slave < 0) { 2256318Swnj perror(line); 2266318Swnj fail(); 2271089Sbill } 2286318Swnj ioctl(slave, TIOCSETP, (char *)&b); 2296318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 2306318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 2316318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 2326318Swnj ioctl(slave, TIOCSETD, (char *)&l); 2331089Sbill } 234