121575Sdist /* 221575Sdist * Copyright (c) 1980 Regents of the University of California. 334628Sbostic * All rights reserved. 434628Sbostic * 534628Sbostic * Redistribution and use in source and binary forms are permitted 634911Sbostic * provided that the above copyright notice and this paragraph are 734911Sbostic * duplicated in all such forms and that any documentation, 834911Sbostic * advertising materials, and other materials related to such 934911Sbostic * distribution and use acknowledge that the software was developed 1034911Sbostic * by the University of California, Berkeley. The name of the 1134911Sbostic * University may not be used to endorse or promote products derived 1234911Sbostic * from this software without specific prior written permission. 1334911Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434911Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534911Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621575Sdist */ 1721575Sdist 186318Swnj #ifndef lint 1921575Sdist char copyright[] = 2021575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 2121575Sdist All rights reserved.\n"; 2234628Sbostic #endif /* not lint */ 2312990Ssam 2421575Sdist #ifndef lint 25*37141Smarc static char sccsid[] = "@(#)script.c 5.7 (Berkeley) 03/13/89"; 2634628Sbostic #endif /* not lint */ 2721575Sdist 281089Sbill /* 296318Swnj * script 301089Sbill */ 316318Swnj #include <sys/types.h> 326318Swnj #include <sys/stat.h> 33*37141Smarc #include <termios.h> 346318Swnj #include <sys/ioctl.h> 3513621Ssam #include <sys/time.h> 3617589Ssam #include <sys/file.h> 3734628Sbostic #include <stdio.h> 3834628Sbostic #include <signal.h> 391089Sbill 406318Swnj char *shell; 416318Swnj FILE *fscript; 426318Swnj int master; 436318Swnj int slave; 446318Swnj int child; 4524450Sbloom int subchild; 4634628Sbostic char *fname; 471089Sbill 48*37141Smarc struct termios tt; 4918029Sbloom struct winsize win; 506318Swnj int lb; 516318Swnj int l; 526318Swnj char *line = "/dev/ptyXX"; 536318Swnj int aflg; 541089Sbill 556318Swnj main(argc, argv) 566318Swnj int argc; 576318Swnj char *argv[]; 586318Swnj { 5934628Sbostic extern char *optarg; 6034628Sbostic extern int optind; 6134628Sbostic int ch; 6234628Sbostic int finish(); 6334628Sbostic char *getenv(); 641089Sbill 6534628Sbostic while ((ch = getopt(argc, argv, "a")) != EOF) 6634628Sbostic switch((char)ch) { 676318Swnj case 'a': 686318Swnj aflg++; 696318Swnj break; 7034628Sbostic case '?': 716318Swnj default: 7234628Sbostic fprintf(stderr, "usage: script [-a] [file]\n"); 736318Swnj exit(1); 741089Sbill } 7534628Sbostic argc -= optind; 7634628Sbostic argv += optind; 7734628Sbostic 786318Swnj if (argc > 0) 796318Swnj fname = argv[0]; 8034628Sbostic else 8134628Sbostic fname = "typescript"; 826318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 836318Swnj perror(fname); 841089Sbill fail(); 851089Sbill } 8634628Sbostic 8734628Sbostic shell = getenv("SHELL"); 8834628Sbostic if (shell == NULL) 8934628Sbostic shell = "/bin/sh"; 9034628Sbostic 916318Swnj getmaster(); 926318Swnj printf("Script started, file is %s\n", fname); 936318Swnj fixtty(); 941089Sbill 956318Swnj (void) signal(SIGCHLD, finish); 966318Swnj child = fork(); 976318Swnj if (child < 0) { 986318Swnj perror("fork"); 996318Swnj fail(); 1001089Sbill } 1016318Swnj if (child == 0) { 10224450Sbloom subchild = child = fork(); 10324450Sbloom if (child < 0) { 1046318Swnj perror("fork"); 1056318Swnj fail(); 1066318Swnj } 10724450Sbloom if (child) 1081089Sbill dooutput(); 1096318Swnj else 1106318Swnj doshell(); 1111089Sbill } 1126318Swnj doinput(); 1131089Sbill } 1141089Sbill 1151089Sbill doinput() 1161089Sbill { 11734628Sbostic register int cc; 1186318Swnj char ibuf[BUFSIZ]; 1191089Sbill 1206318Swnj (void) fclose(fscript); 1216318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1226318Swnj (void) write(master, ibuf, cc); 1236318Swnj done(); 1246318Swnj } 1251089Sbill 12613621Ssam #include <sys/wait.h> 1271089Sbill 1286318Swnj finish() 1296318Swnj { 1306318Swnj union wait status; 13124450Sbloom register int pid; 13224450Sbloom register int die = 0; 1331089Sbill 13424450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 13524450Sbloom if (pid == child) 13624450Sbloom die = 1; 13724450Sbloom 13824450Sbloom if (die) 13924450Sbloom done(); 1401089Sbill } 1411089Sbill 1421089Sbill dooutput() 1431089Sbill { 14434628Sbostic register int cc; 14534628Sbostic time_t tvec, time(); 14634628Sbostic char obuf[BUFSIZ], *ctime(); 1471089Sbill 1486318Swnj (void) close(0); 14934628Sbostic tvec = time((time_t *)NULL); 1506318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1516318Swnj for (;;) { 1526318Swnj cc = read(master, obuf, sizeof (obuf)); 1536318Swnj if (cc <= 0) 1546318Swnj break; 1556318Swnj (void) write(1, obuf, cc); 1566318Swnj (void) fwrite(obuf, 1, cc, fscript); 1571089Sbill } 15825473Sserge done(); 1591089Sbill } 1601089Sbill 1611089Sbill doshell() 1621089Sbill { 1636318Swnj int t; 1641089Sbill 165*37141Smarc /*** 16617589Ssam t = open("/dev/tty", O_RDWR); 1676318Swnj if (t >= 0) { 16824451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1696318Swnj (void) close(t); 1706318Swnj } 171*37141Smarc ***/ 1726318Swnj getslave(); 1736318Swnj (void) close(master); 1746318Swnj (void) fclose(fscript); 17524451Sbloom (void) dup2(slave, 0); 17624451Sbloom (void) dup2(slave, 1); 17724451Sbloom (void) dup2(slave, 2); 1786318Swnj (void) close(slave); 1791089Sbill execl(shell, "sh", "-i", 0); 1806318Swnj perror(shell); 1811089Sbill fail(); 1821089Sbill } 1831089Sbill 1841089Sbill fixtty() 1851089Sbill { 186*37141Smarc struct termios rtt; 1871089Sbill 188*37141Smarc rtt = tt; 189*37141Smarc cfmakeraw(&rtt); 190*37141Smarc rtt.c_lflag &= ~ECHO; 191*37141Smarc (void) tcsetattr(0, TCSADFLUSH, &rtt); 1921089Sbill } 1931089Sbill 1941089Sbill fail() 1951089Sbill { 1961089Sbill 1976318Swnj (void) kill(0, SIGTERM); 1981089Sbill done(); 1991089Sbill } 2001089Sbill 2011089Sbill done() 2021089Sbill { 20334628Sbostic time_t tvec, time(); 20434628Sbostic char *ctime(); 2051089Sbill 20625473Sserge if (subchild) { 20734628Sbostic tvec = time((time_t *)NULL); 20825473Sserge fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 20925473Sserge (void) fclose(fscript); 21025473Sserge (void) close(master); 21125473Sserge } else { 212*37141Smarc (void) tcsetattr(0, TCSADFLUSH, &tt); 21324450Sbloom printf("Script done, file is %s\n", fname); 21424450Sbloom } 2156318Swnj exit(0); 2161089Sbill } 2171089Sbill 2186318Swnj getmaster() 2196318Swnj { 22017589Ssam char *pty, *bank, *cp; 2216318Swnj struct stat stb; 2226318Swnj 22317589Ssam pty = &line[strlen("/dev/ptyp")]; 22417589Ssam for (bank = "pqrs"; *bank; bank++) { 22517589Ssam line[strlen("/dev/pty")] = *bank; 22617589Ssam *pty = '0'; 2276318Swnj if (stat(line, &stb) < 0) 2286318Swnj break; 22917589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 23017589Ssam *pty = *cp; 23117589Ssam master = open(line, O_RDWR); 2326318Swnj if (master >= 0) { 23317589Ssam char *tp = &line[strlen("/dev/")]; 23417589Ssam int ok; 23517589Ssam 23617589Ssam /* verify slave side is usable */ 23717589Ssam *tp = 't'; 23817589Ssam ok = access(line, R_OK|W_OK) == 0; 23917589Ssam *tp = 'p'; 24017589Ssam if (ok) { 241*37141Smarc (void) tcgetattr(0, &tt); 242*37141Smarc (void) ioctl(0, TIOCGWINSZ, 243*37141Smarc (char *)&win); 24417589Ssam return; 24517589Ssam } 24624451Sbloom (void) close(master); 2476318Swnj } 2486318Swnj } 2496318Swnj } 2506318Swnj fprintf(stderr, "Out of pty's\n"); 2516318Swnj fail(); 2521089Sbill } 2531089Sbill 2546318Swnj getslave() 2551089Sbill { 2566318Swnj 2576318Swnj line[strlen("/dev/")] = 't'; 25817589Ssam slave = open(line, O_RDWR); 2596318Swnj if (slave < 0) { 2606318Swnj perror(line); 2616318Swnj fail(); 2621089Sbill } 263*37141Smarc (void) tcsetattr(slave, TCSADFLUSH, &tt); 26424451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 265*37141Smarc (void) setsid(); 266*37141Smarc (void) ioctl(slave, TIOCSCTTY, 0); 2671089Sbill } 268