|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: char copyright[] = ! 20: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 21: All rights reserved.\n"; ! 22: #endif /* not lint */ ! 23: ! 24: #ifndef lint ! 25: static char sccsid[] = "@(#)script.c 5.6 (Berkeley) 6/29/88"; ! 26: #endif /* not lint */ ! 27: ! 28: /* ! 29: * script ! 30: */ ! 31: #include <sys/types.h> ! 32: #include <sys/stat.h> ! 33: #include <sys/ioctl.h> ! 34: #include <sys/time.h> ! 35: #include <sys/file.h> ! 36: #include <stdio.h> ! 37: #include <signal.h> ! 38: ! 39: char *shell; ! 40: FILE *fscript; ! 41: int master; ! 42: int slave; ! 43: int child; ! 44: int subchild; ! 45: char *fname; ! 46: ! 47: struct sgttyb b; ! 48: struct tchars tc; ! 49: struct ltchars lc; ! 50: struct winsize win; ! 51: int lb; ! 52: int l; ! 53: char *line = "/dev/ptyXX"; ! 54: int aflg; ! 55: ! 56: main(argc, argv) ! 57: int argc; ! 58: char *argv[]; ! 59: { ! 60: extern char *optarg; ! 61: extern int optind; ! 62: int ch; ! 63: int finish(); ! 64: char *getenv(); ! 65: ! 66: while ((ch = getopt(argc, argv, "a")) != EOF) ! 67: switch((char)ch) { ! 68: case 'a': ! 69: aflg++; ! 70: break; ! 71: case '?': ! 72: default: ! 73: fprintf(stderr, "usage: script [-a] [file]\n"); ! 74: exit(1); ! 75: } ! 76: argc -= optind; ! 77: argv += optind; ! 78: ! 79: if (argc > 0) ! 80: fname = argv[0]; ! 81: else ! 82: fname = "typescript"; ! 83: if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { ! 84: perror(fname); ! 85: fail(); ! 86: } ! 87: ! 88: shell = getenv("SHELL"); ! 89: if (shell == NULL) ! 90: shell = "/bin/sh"; ! 91: ! 92: getmaster(); ! 93: printf("Script started, file is %s\n", fname); ! 94: fixtty(); ! 95: ! 96: (void) signal(SIGCHLD, finish); ! 97: child = fork(); ! 98: if (child < 0) { ! 99: perror("fork"); ! 100: fail(); ! 101: } ! 102: if (child == 0) { ! 103: subchild = child = fork(); ! 104: if (child < 0) { ! 105: perror("fork"); ! 106: fail(); ! 107: } ! 108: if (child) ! 109: dooutput(); ! 110: else ! 111: doshell(); ! 112: } ! 113: doinput(); ! 114: } ! 115: ! 116: doinput() ! 117: { ! 118: register int cc; ! 119: char ibuf[BUFSIZ]; ! 120: ! 121: (void) fclose(fscript); ! 122: while ((cc = read(0, ibuf, BUFSIZ)) > 0) ! 123: (void) write(master, ibuf, cc); ! 124: done(); ! 125: } ! 126: ! 127: #include <sys/wait.h> ! 128: ! 129: finish() ! 130: { ! 131: union wait status; ! 132: register int pid; ! 133: register int die = 0; ! 134: ! 135: while ((pid = wait3(&status, WNOHANG, 0)) > 0) ! 136: if (pid == child) ! 137: die = 1; ! 138: ! 139: if (die) ! 140: done(); ! 141: } ! 142: ! 143: dooutput() ! 144: { ! 145: register int cc; ! 146: time_t tvec, time(); ! 147: char obuf[BUFSIZ], *ctime(); ! 148: ! 149: (void) close(0); ! 150: tvec = time((time_t *)NULL); ! 151: fprintf(fscript, "Script started on %s", ctime(&tvec)); ! 152: for (;;) { ! 153: cc = read(master, obuf, sizeof (obuf)); ! 154: if (cc <= 0) ! 155: break; ! 156: (void) write(1, obuf, cc); ! 157: (void) fwrite(obuf, 1, cc, fscript); ! 158: } ! 159: done(); ! 160: } ! 161: ! 162: doshell() ! 163: { ! 164: int t; ! 165: ! 166: t = open("/dev/tty", O_RDWR); ! 167: if (t >= 0) { ! 168: (void) ioctl(t, TIOCNOTTY, (char *)0); ! 169: (void) close(t); ! 170: } ! 171: getslave(); ! 172: (void) close(master); ! 173: (void) fclose(fscript); ! 174: (void) dup2(slave, 0); ! 175: (void) dup2(slave, 1); ! 176: (void) dup2(slave, 2); ! 177: (void) close(slave); ! 178: execl(shell, "sh", "-i", 0); ! 179: perror(shell); ! 180: fail(); ! 181: } ! 182: ! 183: fixtty() ! 184: { ! 185: struct sgttyb sbuf; ! 186: ! 187: sbuf = b; ! 188: sbuf.sg_flags |= RAW; ! 189: sbuf.sg_flags &= ~ECHO; ! 190: (void) ioctl(0, TIOCSETP, (char *)&sbuf); ! 191: } ! 192: ! 193: fail() ! 194: { ! 195: ! 196: (void) kill(0, SIGTERM); ! 197: done(); ! 198: } ! 199: ! 200: done() ! 201: { ! 202: time_t tvec, time(); ! 203: char *ctime(); ! 204: ! 205: if (subchild) { ! 206: tvec = time((time_t *)NULL); ! 207: fprintf(fscript,"\nscript done on %s", ctime(&tvec)); ! 208: (void) fclose(fscript); ! 209: (void) close(master); ! 210: } else { ! 211: (void) ioctl(0, TIOCSETP, (char *)&b); ! 212: printf("Script done, file is %s\n", fname); ! 213: } ! 214: exit(0); ! 215: } ! 216: ! 217: getmaster() ! 218: { ! 219: char *pty, *bank, *cp; ! 220: struct stat stb; ! 221: ! 222: pty = &line[strlen("/dev/ptyp")]; ! 223: for (bank = "pqrs"; *bank; bank++) { ! 224: line[strlen("/dev/pty")] = *bank; ! 225: *pty = '0'; ! 226: if (stat(line, &stb) < 0) ! 227: break; ! 228: for (cp = "0123456789abcdef"; *cp; cp++) { ! 229: *pty = *cp; ! 230: master = open(line, O_RDWR); ! 231: if (master >= 0) { ! 232: char *tp = &line[strlen("/dev/")]; ! 233: int ok; ! 234: ! 235: /* verify slave side is usable */ ! 236: *tp = 't'; ! 237: ok = access(line, R_OK|W_OK) == 0; ! 238: *tp = 'p'; ! 239: if (ok) { ! 240: (void) ioctl(0, TIOCGETP, (char *)&b); ! 241: (void) ioctl(0, TIOCGETC, (char *)&tc); ! 242: (void) ioctl(0, TIOCGETD, (char *)&l); ! 243: (void) ioctl(0, TIOCGLTC, (char *)&lc); ! 244: (void) ioctl(0, TIOCLGET, (char *)&lb); ! 245: (void) ioctl(0, TIOCGWINSZ, (char *)&win); ! 246: return; ! 247: } ! 248: (void) close(master); ! 249: } ! 250: } ! 251: } ! 252: fprintf(stderr, "Out of pty's\n"); ! 253: fail(); ! 254: } ! 255: ! 256: getslave() ! 257: { ! 258: ! 259: line[strlen("/dev/")] = 't'; ! 260: slave = open(line, O_RDWR); ! 261: if (slave < 0) { ! 262: perror(line); ! 263: fail(); ! 264: } ! 265: (void) ioctl(slave, TIOCSETP, (char *)&b); ! 266: (void) ioctl(slave, TIOCSETC, (char *)&tc); ! 267: (void) ioctl(slave, TIOCSLTC, (char *)&lc); ! 268: (void) ioctl(slave, TIOCLSET, (char *)&lb); ! 269: (void) ioctl(slave, TIOCSETD, (char *)&l); ! 270: (void) ioctl(slave, TIOCSWINSZ, (char *)&win); ! 271: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.