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

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

unix.superglobalmegacorp.com

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