1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)script.c	5.4 (Berkeley) 11/13/85";
  15: #endif not lint
  16: 
  17: /*
  18:  * script
  19:  */
  20: #include <stdio.h>
  21: #include <signal.h>
  22: #include <sys/types.h>
  23: #include <sys/stat.h>
  24: #include <sys/ioctl.h>
  25: #include <sgtty.h>
  26: #include <sys/time.h>
  27: #include <sys/file.h>
  28: 
  29: char    *getenv();
  30: char    *ctime();
  31: char    *shell;
  32: FILE    *fscript;
  33: int master;
  34: int slave;
  35: int child;
  36: int subchild;
  37: char    *fname = "typescript";
  38: int finish();
  39: 
  40: struct  sgttyb b;
  41: struct  tchars tc;
  42: struct  ltchars lc;
  43: struct  winsize win;
  44: int lb;
  45: int l;
  46: char    *line = "/dev/ptyXX";
  47: int aflg;
  48: 
  49: main(argc, argv)
  50:     int argc;
  51:     char *argv[];
  52: {
  53: 
  54:     shell = getenv("SHELL");
  55:     if (shell == 0)
  56:         shell = "/bin/sh";
  57:     argc--, argv++;
  58:     while (argc > 0 && argv[0][0] == '-') {
  59:         switch (argv[0][1]) {
  60: 
  61:         case 'a':
  62:             aflg++;
  63:             break;
  64: 
  65:         default:
  66:             fprintf(stderr,
  67:                 "usage: script [ -a ] [ typescript ]\n");
  68:             exit(1);
  69:         }
  70:         argc--, argv++;
  71:     }
  72:     if (argc > 0)
  73:         fname = argv[0];
  74:     if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
  75:         perror(fname);
  76:         fail();
  77:     }
  78:     getmaster();
  79:     printf("Script started, file is %s\n", fname);
  80:     fixtty();
  81: 
  82:     (void) signal(SIGCHLD, finish);
  83:     child = fork();
  84:     if (child < 0) {
  85:         perror("fork");
  86:         fail();
  87:     }
  88:     if (child == 0) {
  89:         subchild = child = fork();
  90:         if (child < 0) {
  91:             perror("fork");
  92:             fail();
  93:         }
  94:         if (child)
  95:             dooutput();
  96:         else
  97:             doshell();
  98:     }
  99:     doinput();
 100: }
 101: 
 102: doinput()
 103: {
 104:     char ibuf[BUFSIZ];
 105:     int cc;
 106: 
 107:     (void) fclose(fscript);
 108:     while ((cc = read(0, ibuf, BUFSIZ)) > 0)
 109:         (void) write(master, ibuf, cc);
 110:     done();
 111: }
 112: 
 113: #include <sys/wait.h>
 114: 
 115: finish()
 116: {
 117:     union wait status;
 118:     register int pid;
 119:     register int die = 0;
 120: 
 121:     while ((pid = wait3(&status, WNOHANG, 0)) > 0)
 122:         if (pid == child)
 123:             die = 1;
 124: 
 125:     if (die)
 126:         done();
 127: }
 128: 
 129: dooutput()
 130: {
 131:     time_t tvec;
 132:     char obuf[BUFSIZ];
 133:     int cc;
 134: 
 135:     (void) close(0);
 136:     tvec = time((time_t *)0);
 137:     fprintf(fscript, "Script started on %s", ctime(&tvec));
 138:     for (;;) {
 139:         cc = read(master, obuf, sizeof (obuf));
 140:         if (cc <= 0)
 141:             break;
 142:         (void) write(1, obuf, cc);
 143:         (void) fwrite(obuf, 1, cc, fscript);
 144:     }
 145:     done();
 146: }
 147: 
 148: doshell()
 149: {
 150:     int t;
 151: 
 152:     t = open("/dev/tty", O_RDWR);
 153:     if (t >= 0) {
 154:         (void) ioctl(t, TIOCNOTTY, (char *)0);
 155:         (void) close(t);
 156:     }
 157:     getslave();
 158:     (void) close(master);
 159:     (void) fclose(fscript);
 160:     (void) dup2(slave, 0);
 161:     (void) dup2(slave, 1);
 162:     (void) dup2(slave, 2);
 163:     (void) close(slave);
 164:     execl(shell, "sh", "-i", 0);
 165:     perror(shell);
 166:     fail();
 167: }
 168: 
 169: fixtty()
 170: {
 171:     struct sgttyb sbuf;
 172: 
 173:     sbuf = b;
 174:     sbuf.sg_flags |= RAW;
 175:     sbuf.sg_flags &= ~ECHO;
 176:     (void) ioctl(0, TIOCSETP, (char *)&sbuf);
 177: }
 178: 
 179: fail()
 180: {
 181: 
 182:     (void) kill(0, SIGTERM);
 183:     done();
 184: }
 185: 
 186: done()
 187: {
 188:     time_t tvec;
 189: 
 190:     if (subchild) {
 191:         tvec = time((time_t *)0);
 192:         fprintf(fscript,"\nscript done on %s", ctime(&tvec));
 193:         (void) fclose(fscript);
 194:         (void) close(master);
 195:     } else {
 196:         (void) ioctl(0, TIOCSETP, (char *)&b);
 197:         printf("Script done, file is %s\n", fname);
 198:     }
 199:     exit(0);
 200: }
 201: 
 202: getmaster()
 203: {
 204:     char *pty, *bank, *cp;
 205:     struct stat stb;
 206: 
 207:     pty = &line[strlen("/dev/ptyp")];
 208:     for (bank = "pqrs"; *bank; bank++) {
 209:         line[strlen("/dev/pty")] = *bank;
 210:         *pty = '0';
 211:         if (stat(line, &stb) < 0)
 212:             break;
 213:         for (cp = "0123456789abcdef"; *cp; cp++) {
 214:             *pty = *cp;
 215:             master = open(line, O_RDWR);
 216:             if (master >= 0) {
 217:                 char *tp = &line[strlen("/dev/")];
 218:                 int ok;
 219: 
 220:                 /* verify slave side is usable */
 221:                 *tp = 't';
 222:                 ok = access(line, R_OK|W_OK) == 0;
 223:                 *tp = 'p';
 224:                 if (ok) {
 225:                     (void) ioctl(0, TIOCGETP, (char *)&b);
 226:                     (void) ioctl(0, TIOCGETC, (char *)&tc);
 227:                     (void) ioctl(0, TIOCGETD, (char *)&l);
 228:                     (void) ioctl(0, TIOCGLTC, (char *)&lc);
 229:                     (void) ioctl(0, TIOCLGET, (char *)&lb);
 230:                     (void) ioctl(0, TIOCGWINSZ, (char *)&win);
 231:                     return;
 232:                 }
 233:                 (void) close(master);
 234:             }
 235:         }
 236:     }
 237:     fprintf(stderr, "Out of pty's\n");
 238:     fail();
 239: }
 240: 
 241: getslave()
 242: {
 243: 
 244:     line[strlen("/dev/")] = 't';
 245:     slave = open(line, O_RDWR);
 246:     if (slave < 0) {
 247:         perror(line);
 248:         fail();
 249:     }
 250:     (void) ioctl(slave, TIOCSETP, (char *)&b);
 251:     (void) ioctl(slave, TIOCSETC, (char *)&tc);
 252:     (void) ioctl(slave, TIOCSLTC, (char *)&lc);
 253:     (void) ioctl(slave, TIOCLSET, (char *)&lb);
 254:     (void) ioctl(slave, TIOCSETD, (char *)&l);
 255:     (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
 256: }

Defined functions

doinput defined in line 102; used 1 times
  • in line 99
done defined in line 186; used 4 times
dooutput defined in line 129; used 1 times
  • in line 95
doshell defined in line 148; used 1 times
  • in line 97
fail defined in line 179; used 6 times
finish defined in line 115; used 2 times
fixtty defined in line 169; used 1 times
  • in line 80
getmaster defined in line 202; used 1 times
  • in line 78
getslave defined in line 241; used 1 times
main defined in line 49; never used

Defined variables

aflg defined in line 47; used 2 times
b defined in line 40; used 4 times
child defined in line 35; used 7 times
copyright defined in line 8; never used
fname defined in line 37; used 5 times
l defined in line 45; used 2 times
lb defined in line 44; used 2 times
lc defined in line 42; used 2 times
line defined in line 46; used 9 times
master defined in line 33; used 7 times
sccsid defined in line 14; never used
shell defined in line 31; used 5 times
slave defined in line 34; used 12 times
subchild defined in line 36; used 2 times
tc defined in line 41; used 2 times
win defined in line 43; used 2 times
Last modified: 1985-11-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1435
Valid CSS Valid XHTML 1.0 Strict