1*21575Sdist /* 2*21575Sdist * Copyright (c) 1980 Regents of the University of California. 3*21575Sdist * All rights reserved. The Berkeley software License Agreement 4*21575Sdist * specifies the terms and conditions for redistribution. 5*21575Sdist */ 6*21575Sdist 76318Swnj #ifndef lint 8*21575Sdist char copyright[] = 9*21575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*21575Sdist All rights reserved.\n"; 11*21575Sdist #endif not lint 1212990Ssam 13*21575Sdist #ifndef lint 14*21575Sdist static char sccsid[] = "@(#)script.c 5.1 (Berkeley) 05/31/85"; 15*21575Sdist #endif not lint 16*21575Sdist 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; 366318Swnj char *fname = "typescript"; 376318Swnj int finish(); 381089Sbill 396318Swnj struct sgttyb b; 406318Swnj struct tchars tc; 416318Swnj struct ltchars lc; 4218029Sbloom struct winsize win; 436318Swnj int lb; 446318Swnj int l; 456318Swnj char *line = "/dev/ptyXX"; 466318Swnj int aflg; 471089Sbill 486318Swnj main(argc, argv) 496318Swnj int argc; 506318Swnj char *argv[]; 516318Swnj { 526318Swnj int f; 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) { 896318Swnj f = fork(); 906318Swnj if (f < 0) { 916318Swnj perror("fork"); 926318Swnj fail(); 936318Swnj } 946318Swnj if (f) 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; 1181089Sbill 1196318Swnj if (wait3(&status, WNOHANG, 0) != child) 1206318Swnj return; 1211089Sbill done(); 1221089Sbill } 1231089Sbill 1241089Sbill dooutput() 1251089Sbill { 1266318Swnj time_t tvec; 1276318Swnj char obuf[BUFSIZ]; 1286318Swnj int cc; 1291089Sbill 1306318Swnj (void) close(0); 1316318Swnj tvec = time((time_t *)0); 1326318Swnj fprintf(fscript, "Script started on %s", ctime(&tvec)); 1336318Swnj for (;;) { 1346318Swnj cc = read(master, obuf, sizeof (obuf)); 1356318Swnj if (cc <= 0) 1366318Swnj break; 1376318Swnj (void) write(1, obuf, cc); 1386318Swnj (void) fwrite(obuf, 1, cc, fscript); 1391089Sbill } 1406318Swnj tvec = time((time_t *)0); 1416318Swnj fprintf(fscript,"\nscript done on %s", ctime(&tvec)); 1426318Swnj (void) fclose(fscript); 1436318Swnj (void) close(master); 1441089Sbill exit(0); 1451089Sbill } 1461089Sbill 1471089Sbill doshell() 1481089Sbill { 1496318Swnj int t; 1501089Sbill 15117589Ssam t = open("/dev/tty", O_RDWR); 1526318Swnj if (t >= 0) { 1536318Swnj ioctl(t, TIOCNOTTY, (char *)0); 1546318Swnj (void) close(t); 1556318Swnj } 1566318Swnj getslave(); 1576318Swnj (void) close(master); 1586318Swnj (void) fclose(fscript); 1596318Swnj dup2(slave, 0); 1606318Swnj dup2(slave, 1); 1616318Swnj dup2(slave, 2); 1626318Swnj (void) close(slave); 1631089Sbill execl(shell, "sh", "-i", 0); 1646318Swnj perror(shell); 1651089Sbill fail(); 1661089Sbill } 1671089Sbill 1681089Sbill fixtty() 1691089Sbill { 1706318Swnj struct sgttyb sbuf; 1711089Sbill 1726318Swnj sbuf = b; 1736318Swnj sbuf.sg_flags |= RAW; 1746318Swnj sbuf.sg_flags &= ~ECHO; 1756318Swnj ioctl(0, TIOCSETP, (char *)&sbuf); 1761089Sbill } 1771089Sbill 1781089Sbill fail() 1791089Sbill { 1801089Sbill 1816318Swnj (void) kill(0, SIGTERM); 1821089Sbill done(); 1831089Sbill } 1841089Sbill 1851089Sbill done() 1861089Sbill { 1871089Sbill 1886318Swnj ioctl(0, TIOCSETP, (char *)&b); 1896318Swnj printf("Script done, file is %s\n", fname); 1906318Swnj exit(0); 1911089Sbill } 1921089Sbill 1936318Swnj getmaster() 1946318Swnj { 19517589Ssam char *pty, *bank, *cp; 1966318Swnj struct stat stb; 1976318Swnj int i; 1986318Swnj 19917589Ssam pty = &line[strlen("/dev/ptyp")]; 20017589Ssam for (bank = "pqrs"; *bank; bank++) { 20117589Ssam line[strlen("/dev/pty")] = *bank; 20217589Ssam *pty = '0'; 2036318Swnj if (stat(line, &stb) < 0) 2046318Swnj break; 20517589Ssam for (cp = "0123456789abcdef"; *cp; cp++) { 20617589Ssam *pty = *cp; 20717589Ssam master = open(line, O_RDWR); 2086318Swnj if (master >= 0) { 20917589Ssam char *tp = &line[strlen("/dev/")]; 21017589Ssam int ok; 21117589Ssam 21217589Ssam /* verify slave side is usable */ 21317589Ssam *tp = 't'; 21417589Ssam ok = access(line, R_OK|W_OK) == 0; 21517589Ssam *tp = 'p'; 21617589Ssam if (ok) { 21717589Ssam ioctl(0, TIOCGETP, (char *)&b); 21817589Ssam ioctl(0, TIOCGETC, (char *)&tc); 21917589Ssam ioctl(0, TIOCGETD, (char *)&l); 22017589Ssam ioctl(0, TIOCGLTC, (char *)&lc); 22117589Ssam ioctl(0, TIOCLGET, (char *)&lb); 22218029Sbloom ioctl(0, TIOCGWINSZ, (char *)&win); 22317589Ssam return; 22417589Ssam } 22517589Ssam close(master); 2266318Swnj } 2276318Swnj } 2286318Swnj } 2296318Swnj fprintf(stderr, "Out of pty's\n"); 2306318Swnj fail(); 2311089Sbill } 2321089Sbill 2336318Swnj getslave() 2341089Sbill { 2356318Swnj 2366318Swnj line[strlen("/dev/")] = 't'; 23717589Ssam slave = open(line, O_RDWR); 2386318Swnj if (slave < 0) { 2396318Swnj perror(line); 2406318Swnj fail(); 2411089Sbill } 2426318Swnj ioctl(slave, TIOCSETP, (char *)&b); 2436318Swnj ioctl(slave, TIOCSETC, (char *)&tc); 2446318Swnj ioctl(slave, TIOCSLTC, (char *)&lc); 2456318Swnj ioctl(slave, TIOCLSET, (char *)&lb); 2466318Swnj ioctl(slave, TIOCSETD, (char *)&l); 24718029Sbloom ioctl(slave, TIOCSWINSZ, (char *)&win); 2481089Sbill } 249