|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.