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*46853Sbostic static char sccsid[] = "@(#)script.c 5.12 (Berkeley) 03/01/91"; 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; 53*46853Sbostic void 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 119*46853Sbostic void 1206318Swnj finish() 1216318Swnj { 1226318Swnj union wait status; 12324450Sbloom register int pid; 12424450Sbloom register int die = 0; 1251089Sbill 126*46853Sbostic while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) 12724450Sbloom if (pid == child) 12824450Sbloom die = 1; 12924450Sbloom 13024450Sbloom if (die) 13124450Sbloom done(); 1321089Sbill } 1331089Sbill 1341089Sbill dooutput() 1351089Sbill { 13634628Sbostic register int cc; 13734628Sbostic time_t tvec, time(); 13834628Sbostic char obuf[BUFSIZ], *ctime(); 1391089Sbill 1406318Swnj (void) close(0); 14134628Sbostic tvec = time((time_t *)NULL); 1426318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1436318Swnj for (;;) { 1446318Swnj cc = read(master, obuf, sizeof (obuf)); 1456318Swnj if (cc <= 0) 1466318Swnj break; 1476318Swnj (void) write(1, obuf, cc); 1486318Swnj (void) fwrite(obuf, 1, cc, fscript); 1491089Sbill } 15025473Sserge done(); 1511089Sbill } 1521089Sbill 1531089Sbill doshell() 1541089Sbill { 1556318Swnj int t; 1561089Sbill 15737141Smarc /*** 15837874Sbostic t = open(_PATH_TTY, O_RDWR); 1596318Swnj if (t >= 0) { 16024451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1616318Swnj (void) close(t); 1626318Swnj } 16337141Smarc ***/ 1646318Swnj getslave(); 1656318Swnj (void) close(master); 1666318Swnj (void) fclose(fscript); 16724451Sbloom (void) dup2(slave, 0); 16824451Sbloom (void) dup2(slave, 1); 16924451Sbloom (void) dup2(slave, 2); 1706318Swnj (void) close(slave); 1711089Sbill execl(shell, "sh", "-i", 0); 1726318Swnj perror(shell); 1731089Sbill fail(); 1741089Sbill } 1751089Sbill 1761089Sbill fixtty() 1771089Sbill { 17837141Smarc struct termios rtt; 1791089Sbill 18037141Smarc rtt = tt; 18137141Smarc cfmakeraw(&rtt); 18237141Smarc rtt.c_lflag &= ~ECHO; 18343236Sbostic (void) tcsetattr(0, TCSAFLUSH, &rtt); 1841089Sbill } 1851089Sbill 1861089Sbill fail() 1871089Sbill { 1881089Sbill 1896318Swnj (void) kill(0, SIGTERM); 1901089Sbill done(); 1911089Sbill } 1921089Sbill 1931089Sbill done() 1941089Sbill { 19534628Sbostic time_t tvec, time(); 19634628Sbostic char *ctime(); 1971089Sbill 19825473Sserge if (subchild) { 19934628Sbostic tvec = time((time_t *)NULL); 20038683Sbostic fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 20125473Sserge (void) fclose(fscript); 20225473Sserge (void) close(master); 20325473Sserge } else { 20443236Sbostic (void) tcsetattr(0, TCSAFLUSH, &tt); 20524450Sbloom printf("Script done, file is %s\n", fname); 20624450Sbloom } 2076318Swnj exit(0); 2081089Sbill } 2091089Sbill 2106318Swnj getmaster() 2116318Swnj { 21217589Ssam char *pty, *bank, *cp; 2136318Swnj struct stat stb; 2146318Swnj 21517589Ssam pty = &line[strlen("/dev/ptyp")]; 21617589Ssam for (bank = "pqrs"; *bank; bank++) { 21717589Ssam line[strlen("/dev/pty")] = *bank; 21817589Ssam *pty = '0'; 2196318Swnj if (stat(line, &stb) < 0) 2206318Swnj break; 22117589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 22217589Ssam *pty = *cp; 22317589Ssam master = open(line, O_RDWR); 2246318Swnj if (master >= 0) { 22517589Ssam char *tp = &line[strlen("/dev/")]; 22617589Ssam int ok; 22717589Ssam 22817589Ssam /* verify slave side is usable */ 22917589Ssam *tp = 't'; 23017589Ssam ok = access(line, R_OK|W_OK) == 0; 23117589Ssam *tp = 'p'; 23217589Ssam if (ok) { 23337141Smarc (void) tcgetattr(0, &tt); 23437141Smarc (void) ioctl(0, TIOCGWINSZ, 23537141Smarc (char *)&win); 23617589Ssam return; 23717589Ssam } 23824451Sbloom (void) close(master); 2396318Swnj } 2406318Swnj } 2416318Swnj } 2426318Swnj fprintf(stderr, "Out of pty's\n"); 2436318Swnj fail(); 2441089Sbill } 2451089Sbill 2466318Swnj getslave() 2471089Sbill { 2486318Swnj 2496318Swnj line[strlen("/dev/")] = 't'; 25017589Ssam slave = open(line, O_RDWR); 2516318Swnj if (slave < 0) { 2526318Swnj perror(line); 2536318Swnj fail(); 2541089Sbill } 25543236Sbostic (void) tcsetattr(slave, TCSAFLUSH, &tt); 25624451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 25737141Smarc (void) setsid(); 25837141Smarc (void) ioctl(slave, TIOCSCTTY, 0); 2591089Sbill } 260