Annotation of 3BSD/cmd/script.c, revision 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.