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*38683Sbostic static char sccsid[] = "@(#)script.c 5.9 (Berkeley) 08/21/89"; 2634628Sbostic #endif /* not lint */ 2721575Sdist 281089Sbill /* 296318Swnj * script 301089Sbill */ 316318Swnj #include <sys/types.h> 326318Swnj #include <sys/stat.h> 3337141Smarc #include <termios.h> 346318Swnj #include <sys/ioctl.h> 3513621Ssam #include <sys/time.h> 3617589Ssam #include <sys/file.h> 3737874Sbostic #include <sys/signal.h> 3834628Sbostic #include <stdio.h> 3937874Sbostic #include <paths.h> 401089Sbill 416318Swnj char *shell; 426318Swnj FILE *fscript; 436318Swnj int master; 446318Swnj int slave; 456318Swnj int child; 4624450Sbloom int subchild; 4734628Sbostic char *fname; 481089Sbill 4937141Smarc struct termios tt; 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) 9037874Sbostic shell = _PATH_BSHELL; 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 16637141Smarc /*** 16737874Sbostic t = open(_PATH_TTY, O_RDWR); 1686318Swnj if (t >= 0) { 16924451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1706318Swnj (void) close(t); 1716318Swnj } 17237141Smarc ***/ 1736318Swnj getslave(); 1746318Swnj (void) close(master); 1756318Swnj (void) fclose(fscript); 17624451Sbloom (void) dup2(slave, 0); 17724451Sbloom (void) dup2(slave, 1); 17824451Sbloom (void) dup2(slave, 2); 1796318Swnj (void) close(slave); 1801089Sbill execl(shell, "sh", "-i", 0); 1816318Swnj perror(shell); 1821089Sbill fail(); 1831089Sbill } 1841089Sbill 1851089Sbill fixtty() 1861089Sbill { 18737141Smarc struct termios rtt; 1881089Sbill 18937141Smarc rtt = tt; 19037141Smarc cfmakeraw(&rtt); 19137141Smarc rtt.c_lflag &= ~ECHO; 19237141Smarc (void) tcsetattr(0, TCSADFLUSH, &rtt); 1931089Sbill } 1941089Sbill 1951089Sbill fail() 1961089Sbill { 1971089Sbill 1986318Swnj (void) kill(0, SIGTERM); 1991089Sbill done(); 2001089Sbill } 2011089Sbill 2021089Sbill done() 2031089Sbill { 20434628Sbostic time_t tvec, time(); 20534628Sbostic char *ctime(); 2061089Sbill 20725473Sserge if (subchild) { 20834628Sbostic tvec = time((time_t *)NULL); 209*38683Sbostic fprintf(fscript,"\nScript done on %s", ctime(&tvec)); 21025473Sserge (void) fclose(fscript); 21125473Sserge (void) close(master); 21225473Sserge } else { 21337141Smarc (void) tcsetattr(0, TCSADFLUSH, &tt); 21424450Sbloom printf("Script done, file is %s\n", fname); 21524450Sbloom } 2166318Swnj exit(0); 2171089Sbill } 2181089Sbill 2196318Swnj getmaster() 2206318Swnj { 22117589Ssam char *pty, *bank, *cp; 2226318Swnj struct stat stb; 2236318Swnj 22417589Ssam pty = &line[strlen("/dev/ptyp")]; 22517589Ssam for (bank = "pqrs"; *bank; bank++) { 22617589Ssam line[strlen("/dev/pty")] = *bank; 22717589Ssam *pty = '0'; 2286318Swnj if (stat(line, &stb) < 0) 2296318Swnj break; 23017589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 23117589Ssam *pty = *cp; 23217589Ssam master = open(line, O_RDWR); 2336318Swnj if (master >= 0) { 23417589Ssam char *tp = &line[strlen("/dev/")]; 23517589Ssam int ok; 23617589Ssam 23717589Ssam /* verify slave side is usable */ 23817589Ssam *tp = 't'; 23917589Ssam ok = access(line, R_OK|W_OK) == 0; 24017589Ssam *tp = 'p'; 24117589Ssam if (ok) { 24237141Smarc (void) tcgetattr(0, &tt); 24337141Smarc (void) ioctl(0, TIOCGWINSZ, 24437141Smarc (char *)&win); 24517589Ssam return; 24617589Ssam } 24724451Sbloom (void) close(master); 2486318Swnj } 2496318Swnj } 2506318Swnj } 2516318Swnj fprintf(stderr, "Out of pty's\n"); 2526318Swnj fail(); 2531089Sbill } 2541089Sbill 2556318Swnj getslave() 2561089Sbill { 2576318Swnj 2586318Swnj line[strlen("/dev/")] = 't'; 25917589Ssam slave = open(line, O_RDWR); 2606318Swnj if (slave < 0) { 2616318Swnj perror(line); 2626318Swnj fail(); 2631089Sbill } 26437141Smarc (void) tcsetattr(slave, TCSADFLUSH, &tt); 26524451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 26637141Smarc (void) setsid(); 26737141Smarc (void) ioctl(slave, TIOCSCTTY, 0); 2681089Sbill } 269