Annotation of 3BSD/cmd/script.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.