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