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