1*6318Swnj #ifndef lint 2*6318Swnj static char *sccsid = "@(#)script.c 4.3 82/03/26"; 31089Sbill #endif 41089Sbill /* 5*6318Swnj * script 61089Sbill */ 7*6318Swnj #include <stdio.h> 8*6318Swnj #include <signal.h> 9*6318Swnj #include <sys/types.h> 10*6318Swnj #include <sys/stat.h> 11*6318Swnj #include <sys/ioctl.h> 12*6318Swnj #include <sgtty.h> 13*6318Swnj #include <time.h> 141089Sbill 15*6318Swnj char *getenv(); 16*6318Swnj char *ctime(); 17*6318Swnj char *shell; 18*6318Swnj FILE *fscript; 19*6318Swnj int master; 20*6318Swnj int slave; 21*6318Swnj int child; 22*6318Swnj char *fname = "typescript"; 23*6318Swnj int finish(); 241089Sbill 25*6318Swnj struct sgttyb b; 26*6318Swnj struct tchars tc; 27*6318Swnj struct ltchars lc; 28*6318Swnj int lb; 29*6318Swnj int l; 30*6318Swnj char *line = "/dev/ptyXX"; 31*6318Swnj int aflg; 321089Sbill 33*6318Swnj main(argc, argv) 34*6318Swnj int argc; 35*6318Swnj char *argv[]; 36*6318Swnj { 37*6318Swnj int f; 381089Sbill 391089Sbill shell = getenv("SHELL"); 40*6318Swnj if (shell == 0) 41*6318Swnj shell = "/bin/sh"; 42*6318Swnj argc--, argv++; 43*6318Swnj while (argc > 0 && argv[0][0] == '-') { 44*6318Swnj switch (argv[0][1]) { 451089Sbill 46*6318Swnj case 'a': 47*6318Swnj aflg++; 48*6318Swnj break; 491089Sbill 50*6318Swnj default: 51*6318Swnj fprintf(stderr, 52*6318Swnj "usage: script [ -a ] [ typescript ]\n"); 53*6318Swnj exit(1); 541089Sbill } 55*6318Swnj argc--, argv++; 561089Sbill } 57*6318Swnj if (argc > 0) 58*6318Swnj fname = argv[0]; 59*6318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 60*6318Swnj perror(fname); 611089Sbill fail(); 621089Sbill } 63*6318Swnj getmaster(); 64*6318Swnj printf("Script started, file is %s\n", fname); 65*6318Swnj fixtty(); 661089Sbill 67*6318Swnj (void) signal(SIGCHLD, finish); 68*6318Swnj child = fork(); 69*6318Swnj if (child < 0) { 70*6318Swnj perror("fork"); 71*6318Swnj fail(); 721089Sbill } 73*6318Swnj if (child == 0) { 74*6318Swnj f = fork(); 75*6318Swnj if (f < 0) { 76*6318Swnj perror("fork"); 77*6318Swnj fail(); 78*6318Swnj } 79*6318Swnj if (f) 801089Sbill dooutput(); 81*6318Swnj else 82*6318Swnj doshell(); 831089Sbill } 84*6318Swnj doinput(); 851089Sbill } 861089Sbill 871089Sbill doinput() 881089Sbill { 89*6318Swnj char ibuf[BUFSIZ]; 90*6318Swnj int cc; 911089Sbill 92*6318Swnj (void) fclose(fscript); 93*6318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 94*6318Swnj (void) write(master, ibuf, cc); 95*6318Swnj done(); 96*6318Swnj } 971089Sbill 98*6318Swnj #include <wait.h> 991089Sbill 100*6318Swnj finish() 101*6318Swnj { 102*6318Swnj union wait status; 1031089Sbill 104*6318Swnj if (wait3(&status, WNOHANG, 0) != child) 105*6318Swnj return; 1061089Sbill done(); 1071089Sbill } 1081089Sbill 1091089Sbill dooutput() 1101089Sbill { 111*6318Swnj time_t tvec; 112*6318Swnj char obuf[BUFSIZ]; 113*6318Swnj int cc; 1141089Sbill 115*6318Swnj (void) close(0); 116*6318Swnj tvec = time((time_t *)0); 117*6318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 118*6318Swnj for (;;) { 119*6318Swnj cc = read(master, obuf, sizeof (obuf)); 120*6318Swnj if (cc <= 0) 121*6318Swnj break; 122*6318Swnj (void) write(1, obuf, cc); 123*6318Swnj (void) fwrite(obuf, 1, cc, fscript); 1241089Sbill } 125*6318Swnj tvec = time((time_t *)0); 126*6318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 127*6318Swnj (void) fclose(fscript); 128*6318Swnj (void) close(master); 1291089Sbill exit(0); 1301089Sbill } 1311089Sbill 1321089Sbill doshell() 1331089Sbill { 134*6318Swnj int t; 1351089Sbill 136*6318Swnj t = open("/dev/tty", 2); 137*6318Swnj if (t >= 0) { 138*6318Swnj ioctl(t, TIOCNOTTY, (char *)0); 139*6318Swnj (void) close(t); 140*6318Swnj } 141*6318Swnj getslave(); 142*6318Swnj (void) close(master); 143*6318Swnj (void) fclose(fscript); 144*6318Swnj dup2(slave, 0); 145*6318Swnj dup2(slave, 1); 146*6318Swnj dup2(slave, 2); 147*6318Swnj (void) close(slave); 1481089Sbill execl(shell, "sh", "-i", 0); 149*6318Swnj perror(shell); 1501089Sbill fail(); 1511089Sbill } 1521089Sbill 1531089Sbill fixtty() 1541089Sbill { 155*6318Swnj struct sgttyb sbuf; 1561089Sbill 157*6318Swnj sbuf = b; 158*6318Swnj sbuf.sg_flags |= RAW; 159*6318Swnj sbuf.sg_flags &= ~ECHO; 160*6318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1611089Sbill } 1621089Sbill 1631089Sbill fail() 1641089Sbill { 1651089Sbill 166*6318Swnj (void) kill(0, SIGTERM); 1671089Sbill done(); 1681089Sbill } 1691089Sbill 1701089Sbill done() 1711089Sbill { 1721089Sbill 173*6318Swnj ioctl(0, TIOCSETP, (char *)&b); 174*6318Swnj printf("Script done, file is %s\n", fname); 175*6318Swnj exit(0); 1761089Sbill } 1771089Sbill 178*6318Swnj getmaster() 179*6318Swnj { 180*6318Swnj char c; 181*6318Swnj struct stat stb; 182*6318Swnj int i; 183*6318Swnj 184*6318Swnj for (c = 'p'; c <= 's'; c++) { 185*6318Swnj line[strlen("/dev/pty")] = c; 186*6318Swnj line[strlen("/dev/ptyp")] = '0'; 187*6318Swnj if (stat(line, &stb) < 0) 188*6318Swnj break; 189*6318Swnj for (i = 0; i < 16; i++) { 190*6318Swnj line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 191*6318Swnj master = open(line, 2); 192*6318Swnj if (master >= 0) { 193*6318Swnj ioctl(0, TIOCGETP, (char *)&b); 194*6318Swnj ioctl(0, TIOCGETC, (char *)&tc); 195*6318Swnj ioctl(0, TIOCGETD, (char *)&l); 196*6318Swnj ioctl(0, TIOCGLTC, (char *)&lc); 197*6318Swnj ioctl(0, TIOCLGET, (char *)&lb); 198*6318Swnj return; 199*6318Swnj } 200*6318Swnj } 201*6318Swnj } 202*6318Swnj fprintf(stderr, "Out of pty's\n"); 203*6318Swnj fail(); 2041089Sbill } 2051089Sbill 206*6318Swnj getslave() 2071089Sbill { 208*6318Swnj 209*6318Swnj line[strlen("/dev/")] = 't'; 210*6318Swnj slave = open(line, 2); 211*6318Swnj if (slave < 0) { 212*6318Swnj perror(line); 213*6318Swnj fail(); 2141089Sbill } 215*6318Swnj ioctl(slave, TIOCSETP, (char *)&b); 216*6318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 217*6318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 218*6318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 219*6318Swnj ioctl(slave, TIOCSETD, (char *)&l); 2201089Sbill } 221