121575Sdist /* 221575Sdist * Copyright (c) 1980 Regents of the University of California. 334628Sbostic * All rights reserved. 434628Sbostic * 542765Sbostic * %sccs.include.redist.c% 621575Sdist */ 721575Sdist 86318Swnj #ifndef lint 921575Sdist char copyright[] = 1021575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1121575Sdist All rights reserved.\n"; 1234628Sbostic #endif /* not lint */ 1312990Ssam 1421575Sdist #ifndef lint 15*43236Sbostic static char sccsid[] = "@(#)script.c 5.11 (Berkeley) 06/18/90"; 1634628Sbostic #endif /* not lint */ 1721575Sdist 181089Sbill /* 196318Swnj * script 201089Sbill */ 216318Swnj #include <sys/types.h> 226318Swnj #include <sys/stat.h> 2337141Smarc #include <termios.h> 246318Swnj #include <sys/ioctl.h> 2513621Ssam #include <sys/time.h> 2617589Ssam #include <sys/file.h> 2737874Sbostic #include <sys/signal.h> 2834628Sbostic #include <stdio.h> 2937874Sbostic #include <paths.h> 301089Sbill 316318Swnj char *shell; 326318Swnj FILE *fscript; 336318Swnj int master; 346318Swnj int slave; 356318Swnj int child; 3624450Sbloom int subchild; 3734628Sbostic char *fname; 381089Sbill 3937141Smarc struct termios tt; 4018029Sbloom struct winsize win; 416318Swnj int lb; 426318Swnj int l; 436318Swnj char *line = "/dev/ptyXX"; 446318Swnj int aflg; 451089Sbill 466318Swnj main(argc, argv) 476318Swnj int argc; 486318Swnj char *argv[]; 496318Swnj { 5034628Sbostic extern char *optarg; 5134628Sbostic extern int optind; 5234628Sbostic int ch; 5334628Sbostic int finish(); 5434628Sbostic char *getenv(); 551089Sbill 5634628Sbostic while ((ch = getopt(argc, argv, "a")) != EOF) 5734628Sbostic switch((char)ch) { 586318Swnj case 'a': 596318Swnj aflg++; 606318Swnj break; 6134628Sbostic case '?': 626318Swnj default: 6334628Sbostic fprintf(stderr, "usage: script [-a] [file]\n"); 646318Swnj exit(1); 651089Sbill } 6634628Sbostic argc -= optind; 6734628Sbostic argv += optind; 6834628Sbostic 696318Swnj if (argc > 0) 706318Swnj fname = argv[0]; 7134628Sbostic else 7234628Sbostic fname = "typescript"; 736318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 746318Swnj perror(fname); 751089Sbill fail(); 761089Sbill } 7734628Sbostic 7834628Sbostic shell = getenv("SHELL"); 7934628Sbostic if (shell == NULL) 8037874Sbostic shell = _PATH_BSHELL; 8134628Sbostic 826318Swnj getmaster(); 836318Swnj printf("Script started, file is %s\n", fname); 846318Swnj fixtty(); 851089Sbill 866318Swnj (void) signal(SIGCHLD, finish); 876318Swnj child = fork(); 886318Swnj if (child < 0) { 896318Swnj perror("fork"); 906318Swnj fail(); 911089Sbill } 926318Swnj if (child == 0) { 9324450Sbloom subchild = child = fork(); 9424450Sbloom if (child < 0) { 956318Swnj perror("fork"); 966318Swnj fail(); 976318Swnj } 9824450Sbloom if (child) 991089Sbill dooutput(); 1006318Swnj else 1016318Swnj doshell(); 1021089Sbill } 1036318Swnj doinput(); 1041089Sbill } 1051089Sbill 1061089Sbill doinput() 1071089Sbill { 10834628Sbostic register int cc; 1096318Swnj char ibuf[BUFSIZ]; 1101089Sbill 1116318Swnj (void) fclose(fscript); 1126318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1136318Swnj (void) write(master, ibuf, cc); 1146318Swnj done(); 1156318Swnj } 1161089Sbill 11713621Ssam #include <sys/wait.h> 1181089Sbill 1196318Swnj finish() 1206318Swnj { 1216318Swnj union wait status; 12224450Sbloom register int pid; 12324450Sbloom register int die = 0; 1241089Sbill 12524450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 12624450Sbloom if (pid == child) 12724450Sbloom die = 1; 12824450Sbloom 12924450Sbloom if (die) 13024450Sbloom done(); 1311089Sbill } 1321089Sbill 1331089Sbill dooutput() 1341089Sbill { 13534628Sbostic register int cc; 13634628Sbostic time_t tvec, time(); 13734628Sbostic char obuf[BUFSIZ], *ctime(); 1381089Sbill 1396318Swnj (void) close(0); 14034628Sbostic tvec = time((time_t *)NULL); 1416318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1426318Swnj for (;;) { 1436318Swnj cc = read(master, obuf, sizeof (obuf)); 1446318Swnj if (cc <= 0) 1456318Swnj break; 1466318Swnj (void) write(1, obuf, cc); 1476318Swnj (void) fwrite(obuf, 1, cc, fscript); 1481089Sbill } 14925473Sserge done(); 1501089Sbill } 1511089Sbill 1521089Sbill doshell() 1531089Sbill { 1546318Swnj int t; 1551089Sbill 15637141Smarc /*** 15737874Sbostic t = open(_PATH_TTY, O_RDWR); 1586318Swnj if (t >= 0) { 15924451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1606318Swnj (void) close(t); 1616318Swnj } 16237141Smarc ***/ 1636318Swnj getslave(); 1646318Swnj (void) close(master); 1656318Swnj (void) fclose(fscript); 16624451Sbloom (void) dup2(slave, 0); 16724451Sbloom (void) dup2(slave, 1); 16824451Sbloom (void) dup2(slave, 2); 1696318Swnj (void) close(slave); 1701089Sbill execl(shell, "sh", "-i", 0); 1716318Swnj perror(shell); 1721089Sbill fail(); 1731089Sbill } 1741089Sbill 1751089Sbill fixtty() 1761089Sbill { 17737141Smarc struct termios rtt; 1781089Sbill 17937141Smarc rtt = tt; 18037141Smarc cfmakeraw(&rtt); 18137141Smarc rtt.c_lflag &= ~ECHO; 182*43236Sbostic (void) tcsetattr(0, TCSAFLUSH, &rtt); 1831089Sbill } 1841089Sbill 1851089Sbill fail() 1861089Sbill { 1871089Sbill 1886318Swnj (void) kill(0, SIGTERM); 1891089Sbill done(); 1901089Sbill } 1911089Sbill 1921089Sbill done() 1931089Sbill { 19434628Sbostic time_t tvec, time(); 19534628Sbostic char *ctime(); 1961089Sbill 19725473Sserge if (subchild) { 19834628Sbostic tvec = time((time_t *)NULL); 19938683Sbostic fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 20025473Sserge (void) fclose(fscript); 20125473Sserge (void) close(master); 20225473Sserge } else { 203*43236Sbostic (void) tcsetattr(0, TCSAFLUSH, &tt); 20424450Sbloom printf("Script done, file is %s\n", fname); 20524450Sbloom } 2066318Swnj exit(0); 2071089Sbill } 2081089Sbill 2096318Swnj getmaster() 2106318Swnj { 21117589Ssam char *pty, *bank, *cp; 2126318Swnj struct stat stb; 2136318Swnj 21417589Ssam pty = &line[strlen("/dev/ptyp")]; 21517589Ssam for (bank = "pqrs"; *bank; bank++) { 21617589Ssam line[strlen("/dev/pty")] = *bank; 21717589Ssam *pty = '0'; 2186318Swnj if (stat(line, &stb) < 0) 2196318Swnj break; 22017589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 22117589Ssam *pty = *cp; 22217589Ssam master = open(line, O_RDWR); 2236318Swnj if (master >= 0) { 22417589Ssam char *tp = &line[strlen("/dev/")]; 22517589Ssam int ok; 22617589Ssam 22717589Ssam /* verify slave side is usable */ 22817589Ssam *tp = 't'; 22917589Ssam ok = access(line, R_OK|W_OK) == 0; 23017589Ssam *tp = 'p'; 23117589Ssam if (ok) { 23237141Smarc (void) tcgetattr(0, &tt); 23337141Smarc (void) ioctl(0, TIOCGWINSZ, 23437141Smarc (char *)&win); 23517589Ssam return; 23617589Ssam } 23724451Sbloom (void) close(master); 2386318Swnj } 2396318Swnj } 2406318Swnj } 2416318Swnj fprintf(stderr, "Out of pty's\n"); 2426318Swnj fail(); 2431089Sbill } 2441089Sbill 2456318Swnj getslave() 2461089Sbill { 2476318Swnj 2486318Swnj line[strlen("/dev/")] = 't'; 24917589Ssam slave = open(line, O_RDWR); 2506318Swnj if (slave < 0) { 2516318Swnj perror(line); 2526318Swnj fail(); 2531089Sbill } 254*43236Sbostic (void) tcsetattr(slave, TCSAFLUSH, &tt); 25524451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 25637141Smarc (void) setsid(); 25737141Smarc (void) ioctl(slave, TIOCSCTTY, 0); 2581089Sbill } 259