Annotation of 40BSD/games/compat/Original/runcompat.c, revision 1.1

1.1     ! root        1: #
        !             2: /*
        !             3:  *     Compatability mode support under UNIX-32V
        !             4:  *     written by Art Wetzel during August 1979
        !             5:  *     at the Interdisciplinary Dept of Information Science
        !             6:  *     Room 711, LIS Bldg
        !             7:  *     University of Pittsburgh
        !             8:  *     Pittsburgh, Pa 15260
        !             9:  *
        !            10:  *     No claims are made on the completeness of the support of any
        !            11:  *     of the systems simulated under this package
        !            12:  */
        !            13: #include <stdio.h>
        !            14: #include <signal.h>
        !            15: #include <sys/types.h>
        !            16: #include <sys/stat.h>
        !            17: #include <errno.h>
        !            18: #include "defs.h"
        !            19: #ifdef UNIX
        !            20: #include "unixhdr.h"
        !            21: #endif
        !            22: #ifdef RT11
        !            23: #include "rt11.h"
        !            24: #endif
        !            25: struct stat    stat32v;
        !            26: unsigned short regs[8];
        !            27: unsigned long psl;
        !            28: unsigned short *pc;
        !            29: int incompat;
        !            30: char   *progname;
        !            31: char   *nameend;
        !            32: main(argc, argv, envp) int argc; char **argv, **envp; {
        !            33:        if(argc < 2){
        !            34:                printf(stderr,"Usage: %s [-rootdir] file args...\n",argv[0]);
        !            35:                exit(1);
        !            36:        }
        !            37:        /* remember where the program name etc should go for using ps */
        !            38:        progname = argv[0];
        !            39:        nameend = envp[0]-1;
        !            40:        argv++;
        !            41:        /* set up alternate root directory if flagged for */
        !            42:        if(*argv[0] == '-') {
        !            43:                if(chroot(argv[0]+1)) {
        !            44:                        fprintf(stderr,"Can't change root to %s\n",argv[0]+1);
        !            45:                        exit(-1);
        !            46:                }
        !            47:                argv++;
        !            48:        }
        !            49:        /* check out file stats of file to run */
        !            50:        if(stat(argv[0], &stat32v)) {
        !            51:                fprintf(stderr,"%s does not exist\n",argv[0]);
        !            52:                exit(1);
        !            53:        }
        !            54:        /* a version of SETUID and SETGID file executions */
        !            55:        /* the binary of this program should be SETUID root for this to work */
        !            56:        /* requires nonstandard seteuid and setegid sys calls */
        !            57:        if(!(stat32v.st_mode & S_ISGID) || setegid(stat32v.st_gid))
        !            58:                /* if not SETGID file or error, drop back to real group */
        !            59:                setgid(getgid());
        !            60:        if(!(stat32v.st_mode & S_ISUID) || seteuid(stat32v.st_uid))
        !            61:                /* if not SETUID file or error, drop back to real uid */
        !            62:                setuid(getuid());
        !            63: #ifdef V6UNIX
        !            64:        /* no umasks in version 6 */
        !            65:        umask(0);
        !            66: #endif
        !            67:        /* go try to execute , passing along args and environment */
        !            68:        execute(argv[0], argv, envp);
        !            69:        /* only get here if execute fails */
        !            70:        fprintf(stderr,"Execution failure on %s\n",argv[0]);
        !            71:        exit(1);
        !            72: }
        !            73: execute(file, argv, envp) char *file, **argv, **envp; {
        !            74:        int fd, n, tloadpt, dloadpt, tloadsize, dloadsize, stacksize;
        !            75:        register short *p;
        !            76:        extern illtrap();
        !            77:        /* file to run should be readable */
        !            78:        if((fd = open(file, 0)) == -1) {
        !            79:                fprintf(stderr,"Can't open %s for read access\n",file);
        !            80:                return(-1);
        !            81:        }
        !            82: #ifdef UNIX
        !            83:        if((n = read(fd, &header, sizeof header)) != sizeof header)
        !            84:                return(ENOEXEC);
        !            85:        /* check to see if really unix file */
        !            86:        if(header.magic != MAGIC1 && header.magic != MAGIC2 &&
        !            87:                header.magic != MAGIC3 && header.magic != MAGIC4) {
        !            88:                return(ENOEXEC);
        !            89:        }
        !            90:        /* if a UNIX-32V file run it */
        !            91:        if(header.textsize == 0) {
        !            92:                close(fd);
        !            93:                return(execv(file, argv,  envp));
        !            94:        }
        !            95:        /* checks out OK as PDP-11 UNIX file */
        !            96:        if(header.magic == MAGIC3) {
        !            97:                fprintf(stderr,"%s compiled for separate I/D space\n",argv[0]);
        !            98:                return(-1);
        !            99:        }
        !           100:        /* unix text loads at 0 */
        !           101:        tloadpt = 0;
        !           102:        /* set starting pc value */
        !           103:        pc = (unsigned short *)header.entry;
        !           104:        /* figure out where to load initialized data */
        !           105:        dloadpt = tloadsize = header.textsize;
        !           106:        /* check if alignment of data segment to 8k byte boundary */
        !           107:        if(header.magic == MAGIC2)
        !           108:                dloadpt = (dloadpt+8191) & (~8191);
        !           109:        /* how much data */
        !           110:        dloadsize = header.datasize;
        !           111:        stacksize = header.bsssize;
        !           112: #endif
        !           113: #ifdef RT11
        !           114:        if((n = read(fd, shortspace, RTHDRSIZ)) != RTHDRSIZ) {
        !           115:                fprintf(stderr,"Error reading 1st block\n");
        !           116:                return(-1);
        !           117:        }
        !           118:        /* rt11 files are 0 aligned including the header */
        !           119:        tloadpt = RTHDRSIZ;
        !           120:        /* set starting pc value */
        !           121:        pc = (unsigned short *)shortspace[RTPC];
        !           122:        /* initialize stack location */
        !           123:        regs[6] = shortspace[RTSP];
        !           124:        /* figure how much to load */
        !           125:        dloadpt = tloadsize = shortspace[RTHGH]-RTHDRSIZ;
        !           126:        /* no separate data as in unix */
        !           127:        dloadsize = 0;
        !           128:        stacksize = 0;
        !           129: #endif
        !           130:        /* see if it all fits into available memory space */
        !           131:        if((dloadpt+dloadsize+stacksize) > (int)memsiz) {
        !           132:                fprintf(stderr,"File too big to run\n");
        !           133:                return(-1);
        !           134:        }
        !           135:        /* read text segment */
        !           136:        if((n = read(fd, tloadpt, tloadsize)) < tloadsize) {
        !           137:                fprintf(stderr,"Text read failure\n");
        !           138:                return(-1);
        !           139:        }
        !           140:        /* read data segment */
        !           141:        if((n = read(fd, dloadpt, dloadsize)) < dloadsize) {
        !           142:                fprintf(stderr,"Data read failure\n");
        !           143:                return(-1);
        !           144:        }
        !           145:        /* clear out the rest of memory */
        !           146:        p = (short *)(dloadpt + dloadsize);
        !           147:        while(p < (short *)memsiz) *p++ = 0;
        !           148:        /* close file before starting it */
        !           149:        close(fd);
        !           150:        /* set up illegal instruction trapping */
        !           151:        signal(SIGILL, illtrap);
        !           152:        /* lets give it a try */
        !           153:        start(argv, envp);
        !           154: }
        !           155: illtrap(){
        !           156:        unsigned short *pcptr;
        !           157:        int instr;
        !           158:        register int i;
        !           159:        extern getregs();
        !           160:        /* record the fact that we are not in compatability mode now */
        !           161:        incompat = 0;
        !           162:        /* get the register values before they get clobbered */
        !           163:        getregs();
        !           164:        /* figure out what the pc was */
        !           165:        pcptr = (unsigned short *)((char *)&pcptr + 20);
        !           166:        pc = (unsigned short *) *pcptr;
        !           167:        /* get the instruction */
        !           168:        instr = *pc;
        !           169:        /* incriment the pc over this instruction */
        !           170:        pc++;
        !           171:        /* set register 7 as pc synonym */
        !           172:        regs[7] = (unsigned short)(int)pc;
        !           173:        /* set up psl with condition codes */
        !           174:        /* a UNIX-32V monitor patch is required to not clear condition codes */
        !           175:        psl = 0x83c00000 | (*(pcptr - 6) & 017);
        !           176:        /* pick out the appropriate action for this illegal instruction */
        !           177:        switch(instr>>8){
        !           178:        case    TRAPS:
        !           179:                dotrap(instr & 0377);
        !           180:                break;
        !           181:        case    EMTS:
        !           182:                if(sigvals[SIGEMT] && ((sigvals[SIGEMT]%2) != 1)) {
        !           183:                        dosig(SIGEMT, pc);
        !           184:                        break;
        !           185:                }
        !           186:                doemt(instr & 0377);
        !           187:                break;
        !           188:        default:
        !           189:                if(instr >= 075000 && instr < 075040) {
        !           190:                        /* fis instructions */
        !           191:                        if(dofloat(instr) == 0)
        !           192:                                break;
        !           193:                }
        !           194:                if(instr >=  0170000) {
        !           195:                        /* floating point unit instructions */
        !           196:                        if(dofloat(instr) == 0)
        !           197:                                break;
        !           198:                }
        !           199:                /* genuine illegal instruction */
        !           200:                /* if signal trap set go to user's trap location */
        !           201:                if(sigvals[SIGILL] && ((sigvals[SIGILL]%2) != 1)) {
        !           202:                        dosig(SIGILL, pc);
        !           203:                        break;
        !           204:                }
        !           205:                /* ignore uncaught setd instructions */
        !           206:                if(instr == SETD)
        !           207:                        break;
        !           208:                /* otherwise put out a message and quit */
        !           209:                printf("illegal instruction, psl 0x%08x, pc 0%04o\n",psl,pc-1);
        !           210:                for(i=0; i<7; i++) printf("0x%04x  ",regs[i]);
        !           211:                printf("0x%04x -> 0%o\n",pc-1,instr);
        !           212:                /* set up to dump on illegal instruction */
        !           213:                signal(SIGILL,SIG_DFL);
        !           214:                /* set pc back to bad instruction */
        !           215:                pc--;
        !           216:                /* go do it again for dump */
        !           217:                compat();
        !           218:        }
        !           219:        /* go back to compatability mode */
        !           220:        incompat++;
        !           221:        compat();
        !           222: }

unix.superglobalmegacorp.com

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