|
|
1.1 ! root 1: /* ! 2: * ! 3: * script - makes copy of terminal conversation. usage: ! 4: * script [ -n ] [ -s ] [ -q ] [ -a ] [ -S shell ] [ file ] ! 5: * conversation saved in file. default is DFNAME ! 6: * ! 7: */ ! 8: ! 9: #define DFNAME "typescript" ! 10: ! 11: #ifdef HOUXP ! 12: #define STDSHELL "/bin/sh" ! 13: #define NEWSHELL "/p4/3723mrh/bin/csh" ! 14: char *shell = NEWSHELL; ! 15: #endif ! 16: ! 17: #ifdef HOUXT ! 18: #define STDSHELL "/bin/sh" ! 19: #define NEWSHELL "/t1/bruce/ucb/bin/csh" ! 20: char *shell = NEWSHELL; ! 21: #endif ! 22: ! 23: #ifdef CORY ! 24: #define STDSHELL "/bin/sh" ! 25: #define NEWSHELL "/bin/csh" ! 26: char *shell = NEWSHELL; ! 27: #endif ! 28: ! 29: #ifdef CC ! 30: #define STDSHELL "/bin/sh" ! 31: #define NEWSHELL "/bin/csh" ! 32: char *shell = NEWSHELL; ! 33: #endif ! 34: ! 35: #ifndef STDSHELL ! 36: # define V7ENV ! 37: #endif ! 38: ! 39: #ifdef V7ENV ! 40: /* used for version 7 with environments - gets your environment shell */ ! 41: #define STDSHELL "/bin/sh" ! 42: #define NEWSHELL "/bin/csh" ! 43: char *shell; /* initialized in the code */ ! 44: # include <sys/types.h> ! 45: # include <sys/stat.h> ! 46: # define MODE st_mode ! 47: # define STAT stat ! 48: char *getenv(); ! 49: ! 50: #else ! 51: ! 52: /* ! 53: * The following is the structure of the block returned by ! 54: * the stat and fstat system calls. ! 55: */ ! 56: ! 57: struct inode { ! 58: char i_minor; /* +0: minor device of i-node */ ! 59: char i_major; /* +1: major device */ ! 60: int i_number; /* +2 */ ! 61: int i_flags; /* +4: see below */ ! 62: char i_nlinks; /* +6: number of links to file */ ! 63: char i_uid; /* +7: user ID of owner */ ! 64: char i_gid; /* +8: group ID of owner */ ! 65: char i_size0; /* +9: high byte of 24-bit size */ ! 66: int i_size1; /* +10: low word of 24-bit size */ ! 67: int i_addr[8]; /* +12: block numbers or device number */ ! 68: int i_actime[2]; /* +28: time of last access */ ! 69: int i_modtime[2]; /* +32: time of last modification */ ! 70: }; ! 71: ! 72: #define IALLOC 0100000 ! 73: #define IFMT 060000 ! 74: #define IFDIR 040000 ! 75: #define IFCHR 020000 ! 76: #define IFBLK 060000 ! 77: #define MODE i_flags ! 78: #define STAT inode ! 79: #endif ! 80: ! 81: char *tty; /* name of users tty so can turn off writes */ ! 82: char *ttyname(); /* std subroutine */ ! 83: int mode = 0622; /* old permission bits for users tty */ ! 84: int outpipe[2]; /* pipe from shell to output */ ! 85: int fd; /* file descriptor of typescript file */ ! 86: int inpipe[2]; /* pipe from input to shell */ ! 87: long tvec; /* current time */ ! 88: char buffer[256]; /* for block I/O's */ ! 89: int n; /* number of chars read */ ! 90: int status; /* dummy for wait sys call */ ! 91: char *fname; /* name of typescript file */ ! 92: int forkval, ttn; /* temps for error checking */ ! 93: int qflg; /* true if -q (quiet) flag */ ! 94: int aflg; /* true if -q (append) flag */ ! 95: struct STAT sbuf; ! 96: int flsh(); ! 97: ! 98: main(argc,argv) int argc; char **argv; { ! 99: ! 100: if ((tty = ttyname(2)) < 0) { ! 101: printf("Nested script not allowed.\n"); ! 102: fail(); ! 103: } ! 104: ! 105: #ifdef V7ENV ! 106: shell = getenv("SHELL"); ! 107: #endif ! 108: ! 109: while ( argc > 1 && argv[1][0] == '-') { ! 110: switch(argv[1][1]) { ! 111: case 'n': ! 112: shell = NEWSHELL; ! 113: break; ! 114: case 's': ! 115: shell = STDSHELL; ! 116: break; ! 117: case 'S': ! 118: shell = argv[2]; ! 119: argc--; argv++; ! 120: break; ! 121: case 'q': ! 122: qflg++; ! 123: break; ! 124: case 'a': ! 125: aflg++; ! 126: break; ! 127: default: ! 128: printf("Bad flag %s - ignored\n",argv[1]); ! 129: } ! 130: argc--; argv++; ! 131: } ! 132: ! 133: if (argc > 1) { ! 134: fname = argv[1]; ! 135: if (!aflg && stat(fname,&sbuf) >= 0) { ! 136: printf("File %s already exists.\n",fname); ! 137: done(); ! 138: } ! 139: } else fname = DFNAME; ! 140: if (!aflg) { ! 141: fd = creat(fname,0); /* so can't cat/lpr typescript from inside */ ! 142: } else { ! 143: /* try to append to existing file first */ ! 144: fd = open(fname,1); ! 145: if (fd >= 0) lseek(fd,0l,2); ! 146: else fd = creat(fname,0); ! 147: } ! 148: if (fd<0) { ! 149: printf("Can't create %s\n",fname); ! 150: if (unlink(fname)==0) { ! 151: printf("because of previous typescript bomb - try again\n"); ! 152: } ! 153: fail(); ! 154: } ! 155: ! 156: chmod(fname,0); /* in case it already exists */ ! 157: fixtty(); ! 158: if (!qflg) { ! 159: printf("Script started, file is %s\n",fname); ! 160: check(write(fd,"Script started on ",18)); ! 161: time(&tvec); ! 162: check(write(fd,ctime(&tvec),25)); ! 163: } ! 164: pipe(inpipe); ! 165: pipe(outpipe); ! 166: ! 167: forkval = fork(); ! 168: if (forkval < 0) { ! 169: printf("Fork failed - try again.\n"); ! 170: fail(); ! 171: } ! 172: if (forkval == 0) doshell(); ! 173: ! 174: forkval = fork(); ! 175: if (forkval < 0) { ! 176: printf("Fork failed. Try again.\n"); ! 177: fail(); ! 178: } ! 179: if (forkval == 0) dooutput(); ! 180: else doinput(); ! 181: } ! 182: ! 183: doinput() { ! 184: int done(); ! 185: /* input process - copy tty to pipe and file */ ! 186: signal(2,1); /* ignore interrupts from delete */ ! 187: signal(3,done); /* fix files when users quits. */ ! 188: ! 189: close(inpipe[0]); ! 190: close(outpipe[0]); ! 191: close(outpipe[1]); ! 192: ! 193: /* main input loop - copy until end of file (ctrl D) */ ! 194: while (n=read(0,buffer,256)) { ! 195: check(write(fd,buffer,n)); ! 196: write(inpipe[1],buffer,n); ! 197: } ! 198: ! 199: /* end of script - close files and exit */ ! 200: close(inpipe[1]); ! 201: close(fd); ! 202: wait(&status); /* wait for shell to terminate */ ! 203: wait(&status); /* wait for output to terminate */ ! 204: done(); ! 205: } ! 206: ! 207: dooutput() { ! 208: /* do output process - copy to tty & file */ ! 209: signal(2,flsh); /* trap to flsh on interrupts */ ! 210: signal(3,1); /* ignore quits */ ! 211: ! 212: close(0); ! 213: close(inpipe[0]); ! 214: close(inpipe[1]); ! 215: close(outpipe[1]); ! 216: ! 217: /* main output proc loop */ ! 218: while (n=read(outpipe[0],buffer,256)) { ! 219: if (n > 0) { /* -1 means trap to flsh just happened */ ! 220: write(1,buffer,n); ! 221: check(write(fd,buffer,n)); ! 222: } ! 223: } ! 224: ! 225: /* output sees eof - close files and exit */ ! 226: if (!qflg) { ! 227: printf("Script done, file is %s\n",fname); ! 228: check(write(fd,"\nscript done on ",16)); ! 229: time(&tvec); ! 230: check(write(fd,ctime(&tvec),25)); ! 231: } ! 232: close(fd); ! 233: exit(); ! 234: } ! 235: ! 236: doshell() { ! 237: /* exec shell, after divirting std input & output */ ! 238: close(0); ! 239: dup(inpipe[0]); ! 240: close(1); ! 241: dup(outpipe[1]); ! 242: close(2); ! 243: dup(outpipe[1]); ! 244: ! 245: /* close useless files */ ! 246: close(inpipe[0]); ! 247: close(inpipe[1]); ! 248: close(outpipe[0]); ! 249: close(outpipe[1]); ! 250: /* signal(2,1); /* shell should ignore interrupts */ ! 251: execl(shell,"sh","-i",0); ! 252: execl(STDSHELL,"sh","-i",0); ! 253: execl(NEWSHELL,"sh","-i",0); ! 254: printf("Can't execute shell\n"); ! 255: fail(); ! 256: } ! 257: ! 258: fixtty() ! 259: { ! 260: ! 261: fstat(2, &sbuf); ! 262: mode = sbuf.MODE&0777; ! 263: chmod(tty, 0600); ! 264: } ! 265: ! 266: flsh() { ! 267: /* come here on rubout to flush output - this doesn't work */ ! 268: signal(2,flsh); ! 269: /* lseek(outpipe[0],0l,2); /* seeks on pipes don't work !"$"$!! */ ! 270: } ! 271: ! 272: fail() { ! 273: unlink(fname); ! 274: kill(0,15); /* shut off other script processes */ ! 275: done(); ! 276: } ! 277: ! 278: done() { ! 279: chmod(tty,mode); ! 280: chmod(fname,0664); ! 281: exit(); ! 282: } ! 283: ! 284: #ifndef V7ENV ! 285: #ifndef CC ! 286: char *ttyname(i) int i; { ! 287: char *string; ! 288: string = "/dev/ttyx"; ! 289: string[8] = ttyn(fd); ! 290: if (string[8] == 'x') return((char *) (-1)); ! 291: else return(string); ! 292: } ! 293: #endif ! 294: #endif ! 295: ! 296: check(n) int n; { ! 297: /* checks the result of a write call, if neg ! 298: assume ran out of disk space & die */ ! 299: if (n < 0) { ! 300: write(1,"Disk quota exceeded - script quits\n",35); ! 301: kill(0,15); ! 302: done(); ! 303: } ! 304: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.