121575Sdist /* 221575Sdist * Copyright (c) 1980 Regents of the University of California. 3*34628Sbostic * All rights reserved. 4*34628Sbostic * 5*34628Sbostic * Redistribution and use in source and binary forms are permitted 6*34628Sbostic * provided that this notice is preserved and that due credit is given 7*34628Sbostic * to the University of California at Berkeley. The name of the University 8*34628Sbostic * may not be used to endorse or promote products derived from this 9*34628Sbostic * software without specific prior written permission. This software 10*34628Sbostic * is provided ``as is'' without express or implied warranty. 1121575Sdist */ 1221575Sdist 136318Swnj #ifndef lint 1421575Sdist char copyright[] = 1521575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1621575Sdist All rights reserved.\n"; 17*34628Sbostic #endif /* not lint */ 1812990Ssam 1921575Sdist #ifndef lint 20*34628Sbostic static char sccsid[] = "@(#)script.c 5.5 (Berkeley) 06/03/88"; 21*34628Sbostic #endif /* not lint */ 2221575Sdist 231089Sbill /* 246318Swnj * script 251089Sbill */ 266318Swnj #include <sys/types.h> 276318Swnj #include <sys/stat.h> 286318Swnj #include <sys/ioctl.h> 2913621Ssam #include <sys/time.h> 3017589Ssam #include <sys/file.h> 31*34628Sbostic #include <stdio.h> 32*34628Sbostic #include <signal.h> 331089Sbill 346318Swnj char *shell; 356318Swnj FILE *fscript; 366318Swnj int master; 376318Swnj int slave; 386318Swnj int child; 3924450Sbloom int subchild; 40*34628Sbostic char *fname; 411089Sbill 426318Swnj struct sgttyb b; 436318Swnj struct tchars tc; 446318Swnj struct ltchars lc; 4518029Sbloom struct winsize win; 466318Swnj int lb; 476318Swnj int l; 486318Swnj char *line = "/dev/ptyXX"; 496318Swnj int aflg; 501089Sbill 516318Swnj main(argc, argv) 526318Swnj int argc; 536318Swnj char *argv[]; 546318Swnj { 55*34628Sbostic extern char *optarg; 56*34628Sbostic extern int optind; 57*34628Sbostic int ch; 58*34628Sbostic int finish(); 59*34628Sbostic char *getenv(); 601089Sbill 61*34628Sbostic while ((ch = getopt(argc, argv, "a")) != EOF) 62*34628Sbostic switch((char)ch) { 636318Swnj case 'a': 646318Swnj aflg++; 656318Swnj break; 66*34628Sbostic case '?': 676318Swnj default: 68*34628Sbostic fprintf(stderr, "usage: script [-a] [file]\n"); 696318Swnj exit(1); 701089Sbill } 71*34628Sbostic argc -= optind; 72*34628Sbostic argv += optind; 73*34628Sbostic 746318Swnj if (argc > 0) 756318Swnj fname = argv[0]; 76*34628Sbostic else 77*34628Sbostic fname = "typescript"; 786318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 796318Swnj perror(fname); 801089Sbill fail(); 811089Sbill } 82*34628Sbostic 83*34628Sbostic shell = getenv("SHELL"); 84*34628Sbostic if (shell == NULL) 85*34628Sbostic shell = "/bin/sh"; 86*34628Sbostic 876318Swnj getmaster(); 886318Swnj printf("Script started, file is %s\n", fname); 896318Swnj fixtty(); 901089Sbill 916318Swnj (void) signal(SIGCHLD, finish); 926318Swnj child = fork(); 936318Swnj if (child < 0) { 946318Swnj perror("fork"); 956318Swnj fail(); 961089Sbill } 976318Swnj if (child == 0) { 9824450Sbloom subchild = child = fork(); 9924450Sbloom if (child < 0) { 1006318Swnj perror("fork"); 1016318Swnj fail(); 1026318Swnj } 10324450Sbloom if (child) 1041089Sbill dooutput(); 1056318Swnj else 1066318Swnj doshell(); 1071089Sbill } 1086318Swnj doinput(); 1091089Sbill } 1101089Sbill 1111089Sbill doinput() 1121089Sbill { 113*34628Sbostic register int cc; 1146318Swnj char ibuf[BUFSIZ]; 1151089Sbill 1166318Swnj (void) fclose(fscript); 1176318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1186318Swnj (void) write(master, ibuf, cc); 1196318Swnj done(); 1206318Swnj } 1211089Sbill 12213621Ssam #include <sys/wait.h> 1231089Sbill 1246318Swnj finish() 1256318Swnj { 1266318Swnj union wait status; 12724450Sbloom register int pid; 12824450Sbloom register int die = 0; 1291089Sbill 13024450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 13124450Sbloom if (pid == child) 13224450Sbloom die = 1; 13324450Sbloom 13424450Sbloom if (die) 13524450Sbloom done(); 1361089Sbill } 1371089Sbill 1381089Sbill dooutput() 1391089Sbill { 140*34628Sbostic register int cc; 141*34628Sbostic time_t tvec, time(); 142*34628Sbostic char obuf[BUFSIZ], *ctime(); 1431089Sbill 1446318Swnj (void) close(0); 145*34628Sbostic tvec = time((time_t *)NULL); 1466318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1476318Swnj for (;;) { 1486318Swnj cc = read(master, obuf, sizeof (obuf)); 1496318Swnj if (cc <= 0) 1506318Swnj break; 1516318Swnj (void) write(1, obuf, cc); 1526318Swnj (void) fwrite(obuf, 1, cc, fscript); 1531089Sbill } 15425473Sserge done(); 1551089Sbill } 1561089Sbill 1571089Sbill doshell() 1581089Sbill { 1596318Swnj int t; 1601089Sbill 16117589Ssam t = open("/dev/tty", O_RDWR); 1626318Swnj if (t >= 0) { 16324451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1646318Swnj (void) close(t); 1656318Swnj } 1666318Swnj getslave(); 1676318Swnj (void) close(master); 1686318Swnj (void) fclose(fscript); 16924451Sbloom (void) dup2(slave, 0); 17024451Sbloom (void) dup2(slave, 1); 17124451Sbloom (void) dup2(slave, 2); 1726318Swnj (void) close(slave); 1731089Sbill execl(shell, "sh", "-i", 0); 1746318Swnj perror(shell); 1751089Sbill fail(); 1761089Sbill } 1771089Sbill 1781089Sbill fixtty() 1791089Sbill { 1806318Swnj struct sgttyb sbuf; 1811089Sbill 1826318Swnj sbuf = b; 1836318Swnj sbuf.sg_flags |= RAW; 1846318Swnj sbuf.sg_flags &= ~ECHO; 18524451Sbloom (void) ioctl(0, TIOCSETP, (char *)&sbuf); 1861089Sbill } 1871089Sbill 1881089Sbill fail() 1891089Sbill { 1901089Sbill 1916318Swnj (void) kill(0, SIGTERM); 1921089Sbill done(); 1931089Sbill } 1941089Sbill 1951089Sbill done() 1961089Sbill { 197*34628Sbostic time_t tvec, time(); 198*34628Sbostic char *ctime(); 1991089Sbill 20025473Sserge if (subchild) { 201*34628Sbostic tvec = time((time_t *)NULL); 20225473Sserge fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 20325473Sserge (void) fclose(fscript); 20425473Sserge (void) close(master); 20525473Sserge } else { 20624451Sbloom (void) ioctl(0, TIOCSETP, (char *)&b); 20724450Sbloom printf("Script done, file is %s\n", fname); 20824450Sbloom } 2096318Swnj exit(0); 2101089Sbill } 2111089Sbill 2126318Swnj getmaster() 2136318Swnj { 21417589Ssam char *pty, *bank, *cp; 2156318Swnj struct stat stb; 2166318Swnj 21717589Ssam pty = &line[strlen("/dev/ptyp")]; 21817589Ssam for (bank = "pqrs"; *bank; bank++) { 21917589Ssam line[strlen("/dev/pty")] = *bank; 22017589Ssam *pty = '0'; 2216318Swnj if (stat(line, &stb) < 0) 2226318Swnj break; 22317589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 22417589Ssam *pty = *cp; 22517589Ssam master = open(line, O_RDWR); 2266318Swnj if (master >= 0) { 22717589Ssam char *tp = &line[strlen("/dev/")]; 22817589Ssam int ok; 22917589Ssam 23017589Ssam /* verify slave side is usable */ 23117589Ssam *tp = 't'; 23217589Ssam ok = access(line, R_OK|W_OK) == 0; 23317589Ssam *tp = 'p'; 23417589Ssam if (ok) { 23524451Sbloom (void) ioctl(0, TIOCGETP, (char *)&b); 23624451Sbloom (void) ioctl(0, TIOCGETC, (char *)&tc); 23724451Sbloom (void) ioctl(0, TIOCGETD, (char *)&l); 23824451Sbloom (void) ioctl(0, TIOCGLTC, (char *)&lc); 23924451Sbloom (void) ioctl(0, TIOCLGET, (char *)&lb); 24024451Sbloom (void) ioctl(0, TIOCGWINSZ, (char *)&win); 24117589Ssam return; 24217589Ssam } 24324451Sbloom (void) close(master); 2446318Swnj } 2456318Swnj } 2466318Swnj } 2476318Swnj fprintf(stderr, "Out of pty's\n"); 2486318Swnj fail(); 2491089Sbill } 2501089Sbill 2516318Swnj getslave() 2521089Sbill { 2536318Swnj 2546318Swnj line[strlen("/dev/")] = 't'; 25517589Ssam slave = open(line, O_RDWR); 2566318Swnj if (slave < 0) { 2576318Swnj perror(line); 2586318Swnj fail(); 2591089Sbill } 26024451Sbloom (void) ioctl(slave, TIOCSETP, (char *)&b); 26124451Sbloom (void) ioctl(slave, TIOCSETC, (char *)&tc); 26224451Sbloom (void) ioctl(slave, TIOCSLTC, (char *)&lc); 26324451Sbloom (void) ioctl(slave, TIOCLSET, (char *)&lb); 26424451Sbloom (void) ioctl(slave, TIOCSETD, (char *)&l); 26524451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 2661089Sbill } 267