121575Sdist /* 221575Sdist * Copyright (c) 1980 Regents of the University of California. 321575Sdist * All rights reserved. The Berkeley software License Agreement 421575Sdist * specifies the terms and conditions for redistribution. 521575Sdist */ 621575Sdist 76318Swnj #ifndef lint 821575Sdist char copyright[] = 921575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021575Sdist All rights reserved.\n"; 1121575Sdist #endif not lint 1212990Ssam 1321575Sdist #ifndef lint 14*25473Sserge static char sccsid[] = "@(#)script.c 5.4 (Berkeley) 11/13/85"; 1521575Sdist #endif not lint 1621575Sdist 171089Sbill /* 186318Swnj * script 191089Sbill */ 206318Swnj #include <stdio.h> 216318Swnj #include <signal.h> 226318Swnj #include <sys/types.h> 236318Swnj #include <sys/stat.h> 246318Swnj #include <sys/ioctl.h> 256318Swnj #include <sgtty.h> 2613621Ssam #include <sys/time.h> 2717589Ssam #include <sys/file.h> 281089Sbill 296318Swnj char *getenv(); 306318Swnj char *ctime(); 316318Swnj char *shell; 326318Swnj FILE *fscript; 336318Swnj int master; 346318Swnj int slave; 356318Swnj int child; 3624450Sbloom int subchild; 376318Swnj char *fname = "typescript"; 386318Swnj int finish(); 391089Sbill 406318Swnj struct sgttyb b; 416318Swnj struct tchars tc; 426318Swnj struct ltchars lc; 4318029Sbloom struct winsize win; 446318Swnj int lb; 456318Swnj int l; 466318Swnj char *line = "/dev/ptyXX"; 476318Swnj int aflg; 481089Sbill 496318Swnj main(argc, argv) 506318Swnj int argc; 516318Swnj char *argv[]; 526318Swnj { 531089Sbill 541089Sbill shell = getenv("SHELL"); 556318Swnj if (shell == 0) 566318Swnj shell = "/bin/sh"; 576318Swnj argc--, argv++; 586318Swnj while (argc > 0 && argv[0][0] == '-') { 596318Swnj switch (argv[0][1]) { 601089Sbill 616318Swnj case 'a': 626318Swnj aflg++; 636318Swnj break; 641089Sbill 656318Swnj default: 666318Swnj fprintf(stderr, 676318Swnj "usage: script [ -a ] [ typescript ]\n"); 686318Swnj exit(1); 691089Sbill } 706318Swnj argc--, argv++; 711089Sbill } 726318Swnj if (argc > 0) 736318Swnj fname = argv[0]; 746318Swnj if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { 756318Swnj perror(fname); 761089Sbill fail(); 771089Sbill } 786318Swnj getmaster(); 796318Swnj printf("Script started, file is %s\n", fname); 806318Swnj fixtty(); 811089Sbill 826318Swnj (void) signal(SIGCHLD, finish); 836318Swnj child = fork(); 846318Swnj if (child < 0) { 856318Swnj perror("fork"); 866318Swnj fail(); 871089Sbill } 886318Swnj if (child == 0) { 8924450Sbloom subchild = child = fork(); 9024450Sbloom if (child < 0) { 916318Swnj perror("fork"); 926318Swnj fail(); 936318Swnj } 9424450Sbloom if (child) 951089Sbill dooutput(); 966318Swnj else 976318Swnj doshell(); 981089Sbill } 996318Swnj doinput(); 1001089Sbill } 1011089Sbill 1021089Sbill doinput() 1031089Sbill { 1046318Swnj char ibuf[BUFSIZ]; 1056318Swnj int cc; 1061089Sbill 1076318Swnj (void) fclose(fscript); 1086318Swnj while ((cc = read(0, ibuf, BUFSIZ)) > 0) 1096318Swnj (void) write(master, ibuf, cc); 1106318Swnj done(); 1116318Swnj } 1121089Sbill 11313621Ssam #include <sys/wait.h> 1141089Sbill 1156318Swnj finish() 1166318Swnj { 1176318Swnj union wait status; 11824450Sbloom register int pid; 11924450Sbloom register int die = 0; 1201089Sbill 12124450Sbloom while ((pid = wait3(&status, WNOHANG, 0)) > 0) 12224450Sbloom if (pid == child) 12324450Sbloom die = 1; 12424450Sbloom 12524450Sbloom if (die) 12624450Sbloom done(); 1271089Sbill } 1281089Sbill 1291089Sbill dooutput() 1301089Sbill { 1316318Swnj time_t tvec; 1326318Swnj char obuf[BUFSIZ]; 1336318Swnj int cc; 1341089Sbill 1356318Swnj (void) close(0); 1366318Swnj tvec = time((time_t *)0); 1376318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1386318Swnj for (;;) { 1396318Swnj cc = read(master, obuf, sizeof (obuf)); 1406318Swnj if (cc <= 0) 1416318Swnj break; 1426318Swnj (void) write(1, obuf, cc); 1436318Swnj (void) fwrite(obuf, 1, cc, fscript); 1441089Sbill } 145*25473Sserge done(); 1461089Sbill } 1471089Sbill 1481089Sbill doshell() 1491089Sbill { 1506318Swnj int t; 1511089Sbill 15217589Ssam t = open("/dev/tty", O_RDWR); 1536318Swnj if (t >= 0) { 15424451Sbloom (void) ioctl(t, TIOCNOTTY, (char *)0); 1556318Swnj (void) close(t); 1566318Swnj } 1576318Swnj getslave(); 1586318Swnj (void) close(master); 1596318Swnj (void) fclose(fscript); 16024451Sbloom (void) dup2(slave, 0); 16124451Sbloom (void) dup2(slave, 1); 16224451Sbloom (void) dup2(slave, 2); 1636318Swnj (void) close(slave); 1641089Sbill execl(shell, "sh", "-i", 0); 1656318Swnj perror(shell); 1661089Sbill fail(); 1671089Sbill } 1681089Sbill 1691089Sbill fixtty() 1701089Sbill { 1716318Swnj struct sgttyb sbuf; 1721089Sbill 1736318Swnj sbuf = b; 1746318Swnj sbuf.sg_flags |= RAW; 1756318Swnj sbuf.sg_flags &= ~ECHO; 17624451Sbloom (void) ioctl(0, TIOCSETP, (char *)&sbuf); 1771089Sbill } 1781089Sbill 1791089Sbill fail() 1801089Sbill { 1811089Sbill 1826318Swnj (void) kill(0, SIGTERM); 1831089Sbill done(); 1841089Sbill } 1851089Sbill 1861089Sbill done() 1871089Sbill { 188*25473Sserge time_t tvec; 1891089Sbill 190*25473Sserge if (subchild) { 191*25473Sserge tvec = time((time_t *)0); 192*25473Sserge fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 193*25473Sserge (void) fclose(fscript); 194*25473Sserge (void) close(master); 195*25473Sserge } else { 19624451Sbloom (void) ioctl(0, TIOCSETP, (char *)&b); 19724450Sbloom printf("Script done, file is %s\n", fname); 19824450Sbloom } 1996318Swnj exit(0); 2001089Sbill } 2011089Sbill 2026318Swnj getmaster() 2036318Swnj { 20417589Ssam char *pty, *bank, *cp; 2056318Swnj struct stat stb; 2066318Swnj 20717589Ssam pty = &line[strlen("/dev/ptyp")]; 20817589Ssam for (bank = "pqrs"; *bank; bank++) { 20917589Ssam line[strlen("/dev/pty")] = *bank; 21017589Ssam *pty = '0'; 2116318Swnj if (stat(line, &stb) < 0) 2126318Swnj break; 21317589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 21417589Ssam *pty = *cp; 21517589Ssam master = open(line, O_RDWR); 2166318Swnj if (master >= 0) { 21717589Ssam char *tp = &line[strlen("/dev/")]; 21817589Ssam int ok; 21917589Ssam 22017589Ssam /* verify slave side is usable */ 22117589Ssam *tp = 't'; 22217589Ssam ok = access(line, R_OK|W_OK) == 0; 22317589Ssam *tp = 'p'; 22417589Ssam if (ok) { 22524451Sbloom (void) ioctl(0, TIOCGETP, (char *)&b); 22624451Sbloom (void) ioctl(0, TIOCGETC, (char *)&tc); 22724451Sbloom (void) ioctl(0, TIOCGETD, (char *)&l); 22824451Sbloom (void) ioctl(0, TIOCGLTC, (char *)&lc); 22924451Sbloom (void) ioctl(0, TIOCLGET, (char *)&lb); 23024451Sbloom (void) ioctl(0, TIOCGWINSZ, (char *)&win); 23117589Ssam return; 23217589Ssam } 23324451Sbloom (void) close(master); 2346318Swnj } 2356318Swnj } 2366318Swnj } 2376318Swnj fprintf(stderr, "Out of pty's\n"); 2386318Swnj fail(); 2391089Sbill } 2401089Sbill 2416318Swnj getslave() 2421089Sbill { 2436318Swnj 2446318Swnj line[strlen("/dev/")] = 't'; 24517589Ssam slave = open(line, O_RDWR); 2466318Swnj if (slave < 0) { 2476318Swnj perror(line); 2486318Swnj fail(); 2491089Sbill } 25024451Sbloom (void) ioctl(slave, TIOCSETP, (char *)&b); 25124451Sbloom (void) ioctl(slave, TIOCSETC, (char *)&tc); 25224451Sbloom (void) ioctl(slave, TIOCSLTC, (char *)&lc); 25324451Sbloom (void) ioctl(slave, TIOCLSET, (char *)&lb); 25424451Sbloom (void) ioctl(slave, TIOCSETD, (char *)&l); 25524451Sbloom (void) ioctl(slave, TIOCSWINSZ, (char *)&win); 2561089Sbill } 257