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 6*34911Sbostic * provided that the above copyright notice and this paragraph are 7*34911Sbostic * duplicated in all such forms and that any documentation, 8*34911Sbostic * advertising materials, and other materials related to such 9*34911Sbostic * distribution and use acknowledge that the software was developed 10*34911Sbostic * by the University of California, Berkeley. The name of the 11*34911Sbostic * University may not be used to endorse or promote products derived 12*34911Sbostic * from this software without specific prior written permission. 13*34911Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34911Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34911Sbostic * 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*34911Sbostic static char sccsid[] = "@(#)script.c 5.6 (Berkeley) 06/29/88"; 2634628Sbostic #endif /* not lint */ 2721575Sdist 281089Sbill /* 296318Swnj * script 301089Sbill */ 316318Swnj #include <sys/types.h> 326318Swnj #include <sys/stat.h> 336318Swnj #include <sys/ioctl.h> 3413621Ssam #include <sys/time.h> 3517589Ssam #include <sys/file.h> 3634628Sbostic #include <stdio.h> 3734628Sbostic #include <signal.h> 381089Sbill 396318Swnj char *shell; 406318Swnj FILE *fscript; 416318Swnj int master; 426318Swnj int slave; 436318Swnj int child; 4424450Sbloom int subchild; 4534628Sbostic char *fname; 461089Sbill 476318Swnj struct sgttyb b; 486318Swnj struct tchars tc; 496318Swnj struct ltchars lc; 5018029Sbloom struct winsize win; 516318Swnj int lb; 526318Swnj int l; 536318Swnj char *line = "/dev/ptyXX"; 546318Swnj int aflg; 551089Sbill 566318Swnj main(argc, argv) 576318Swnj int argc; 586318Swnj char *argv[]; 596318Swnj { 6034628Sbostic extern char *optarg; 6134628Sbostic extern int optind; 6234628Sbostic int ch; 6334628Sbostic int finish(); 6434628Sbostic char *getenv(); 651089Sbill 6634628Sbostic while ((ch = getopt(argc, argv, "a")) != EOF) 6734628Sbostic switch((char)ch) { 686318Swnj case 'a': 696318Swnj aflg++; 706318Swnj break; 7134628Sbostic case '?': 726318Swnj default: 7334628Sbostic fprintf(stderr, "usage: script [-a] [file]\n"); 746318Swnj exit(1); 751089Sbill } 7634628Sbostic argc -= optind; 7734628Sbostic argv += optind; 7834628Sbostic 796318Swnj if (argc > 0) 806318Swnj fname = argv[0]; 8134628Sbostic else 8234628Sbostic fname = "typescript"; 836318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 846318Swnj perror(fname); 851089Sbill fail(); 861089Sbill } 8734628Sbostic 8834628Sbostic shell = getenv("SHELL"); 8934628Sbostic if (shell == NULL) 9034628Sbostic shell = "/bin/sh"; 9134628Sbostic 926318Swnj getmaster(); 936318Swnj printf("Script started, file is %s\n", fname); 946318Swnj fixtty(); 951089Sbill 966318Swnj (void) signal(SIGCHLD, finish); 976318Swnj child = fork(); 986318Swnj if (child < 0) { 996318Swnj perror("fork"); 1006318Swnj fail(); 1011089Sbill } 1026318Swnj if (child == 0) { 10324450Sbloom subchild = child = fork(); 10424450Sbloom if (child < 0) { 1056318Swnj perror("fork"); 1066318Swnj fail(); 1076318Swnj } 10824450Sbloom if (child) 1091089Sbill dooutput(); 1106318Swnj else 1116318Swnj doshell(); 1121089Sbill } 1136318Swnj doinput(); 1141089Sbill } 1151089Sbill 1161089Sbill doinput() 1171089Sbill { 11834628Sbostic register int cc; 1196318Swnj char ibuf[BUFSIZ]; 1201089Sbill 1216318Swnj (void) fclose(fscript); 1226318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1236318Swnj (void) write(master, ibuf, cc); 1246318Swnj done(); 1256318Swnj } 1261089Sbill 12713621Ssam #include <sys/wait.h> 1281089Sbill 1296318Swnj finish() 1306318Swnj { 1316318Swnj union wait status; 13224450Sbloom register int pid; 13324450Sbloom register int die = 0; 1341089Sbill 13524450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 13624450Sbloom if (pid == child) 13724450Sbloom die = 1; 13824450Sbloom 13924450Sbloom if (die) 14024450Sbloom done(); 1411089Sbill } 1421089Sbill 1431089Sbill dooutput() 1441089Sbill { 14534628Sbostic register int cc; 14634628Sbostic time_t tvec, time(); 14734628Sbostic char obuf[BUFSIZ], *ctime(); 1481089Sbill 1496318Swnj (void) close(0); 15034628Sbostic tvec = time((time_t *)NULL); 1516318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1526318Swnj for (;;) { 1536318Swnj cc = read(master, obuf, sizeof (obuf)); 1546318Swnj if (cc <= 0) 1556318Swnj break; 1566318Swnj (void) write(1, obuf, cc); 1576318Swnj (void) fwrite(obuf, 1, cc, fscript); 1581089Sbill } 15925473Sserge done(); 1601089Sbill } 1611089Sbill 1621089Sbill doshell() 1631089Sbill { 1646318Swnj int t; 1651089Sbill 16617589Ssam t = open("/dev/tty", O_RDWR); 1676318Swnj if (t >= 0) { 16824451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1696318Swnj (void) close(t); 1706318Swnj } 1716318Swnj getslave(); 1726318Swnj (void) close(master); 1736318Swnj (void) fclose(fscript); 17424451Sbloom (void) dup2(slave, 0); 17524451Sbloom (void) dup2(slave, 1); 17624451Sbloom (void) dup2(slave, 2); 1776318Swnj (void) close(slave); 1781089Sbill execl(shell, "sh", "-i", 0); 1796318Swnj perror(shell); 1801089Sbill fail(); 1811089Sbill } 1821089Sbill 1831089Sbill fixtty() 1841089Sbill { 1856318Swnj struct sgttyb sbuf; 1861089Sbill 1876318Swnj sbuf = b; 1886318Swnj sbuf.sg_flags |= RAW; 1896318Swnj sbuf.sg_flags &= ~ECHO; 19024451Sbloom (void) ioctl(0, TIOCSETP, (char *)&sbuf); 1911089Sbill } 1921089Sbill 1931089Sbill fail() 1941089Sbill { 1951089Sbill 1966318Swnj (void) kill(0, SIGTERM); 1971089Sbill done(); 1981089Sbill } 1991089Sbill 2001089Sbill done() 2011089Sbill { 20234628Sbostic time_t tvec, time(); 20334628Sbostic char *ctime(); 2041089Sbill 20525473Sserge if (subchild) { 20634628Sbostic tvec = time((time_t *)NULL); 20725473Sserge fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 20825473Sserge (void) fclose(fscript); 20925473Sserge (void) close(master); 21025473Sserge } else { 21124451Sbloom (void) ioctl(0, TIOCSETP, (char *)&b); 21224450Sbloom printf("Script done, file is %s\n", fname); 21324450Sbloom } 2146318Swnj exit(0); 2151089Sbill } 2161089Sbill 2176318Swnj getmaster() 2186318Swnj { 21917589Ssam char *pty, *bank, *cp; 2206318Swnj struct stat stb; 2216318Swnj 22217589Ssam pty = &line[strlen("/dev/ptyp")]; 22317589Ssam for (bank = "pqrs"; *bank; bank++) { 22417589Ssam line[strlen("/dev/pty")] = *bank; 22517589Ssam *pty = '0'; 2266318Swnj if (stat(line, &stb) < 0) 2276318Swnj break; 22817589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 22917589Ssam *pty = *cp; 23017589Ssam master = open(line, O_RDWR); 2316318Swnj if (master >= 0) { 23217589Ssam char *tp = &line[strlen("/dev/")]; 23317589Ssam int ok; 23417589Ssam 23517589Ssam /* verify slave side is usable */ 23617589Ssam *tp = 't'; 23717589Ssam ok = access(line, R_OK|W_OK) == 0; 23817589Ssam *tp = 'p'; 23917589Ssam if (ok) { 24024451Sbloom (void) ioctl(0, TIOCGETP, (char *)&b); 24124451Sbloom (void) ioctl(0, TIOCGETC, (char *)&tc); 24224451Sbloom (void) ioctl(0, TIOCGETD, (char *)&l); 24324451Sbloom (void) ioctl(0, TIOCGLTC, (char *)&lc); 24424451Sbloom (void) ioctl(0, TIOCLGET, (char *)&lb); 24524451Sbloom (void) ioctl(0, TIOCGWINSZ, (char *)&win); 24617589Ssam return; 24717589Ssam } 24824451Sbloom (void) close(master); 2496318Swnj } 2506318Swnj } 2516318Swnj } 2526318Swnj fprintf(stderr, "Out of pty's\n"); 2536318Swnj fail(); 2541089Sbill } 2551089Sbill 2566318Swnj getslave() 2571089Sbill { 2586318Swnj 2596318Swnj line[strlen("/dev/")] = 't'; 26017589Ssam slave = open(line, O_RDWR); 2616318Swnj if (slave < 0) { 2626318Swnj perror(line); 2636318Swnj fail(); 2641089Sbill } 26524451Sbloom (void) ioctl(slave, TIOCSETP, (char *)&b); 26624451Sbloom (void) ioctl(slave, TIOCSETC, (char *)&tc); 26724451Sbloom (void) ioctl(slave, TIOCSLTC, (char *)&lc); 26824451Sbloom (void) ioctl(slave, TIOCLSET, (char *)&lb); 26924451Sbloom (void) ioctl(slave, TIOCSETD, (char *)&l); 27024451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 2711089Sbill } 272