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

1.1     ! root        1: #
        !             2: /*     Function to execute version 6 and version 7 UNIX system calls from
        !             3:  *     compatability mode on UNIX-32V.
        !             4:  *     Art Wetzel      August 1979
        !             5:  */
        !             6: #include <stdio.h>
        !             7: #include <signal.h>
        !             8: #include <sys/types.h>
        !             9: #include <sys/stat.h>
        !            10: #ifdef V6UNIX
        !            11: #ifdef TRACE
        !            12: #define        RTSNAME "/../../../../usr/local/v6trc"
        !            13: #else
        !            14: #define        RTSNAME "/../../../../usr/local/v6run"
        !            15: #endif
        !            16: #include "unix6sys.h"
        !            17: #ifdef TRACE
        !            18: #include "unix6sysn.h"
        !            19: #endif
        !            20: #endif
        !            21: #ifdef V7UNIX
        !            22: #ifdef TRACE
        !            23: #define        RTSNAME "/../../../../usr/local/v7trc"
        !            24: #else
        !            25: #define        RTSNAME "/../../../../usr/local/v7run"
        !            26: #endif
        !            27: #include "unix7sys.h"
        !            28: #ifdef TRACE
        !            29: #include "unix7sysn.h"
        !            30: #endif
        !            31: #endif
        !            32: #include "defs.h"
        !            33: #define        CARRY   1
        !            34: #define        MAXSARGS        25
        !            35: #ifdef V6UNIX
        !            36: #define        ARGVLEN 512
        !            37: #define        ENVLEN  0
        !            38: #endif
        !            39: #ifdef V7UNIX
        !            40: #define        ARGVLEN 5120
        !            41: #define        ENVLEN  1000
        !            42: #endif
        !            43: char   argvs[ARGVLEN+ENVLEN];
        !            44: int    args[MAXSARGS];
        !            45: /* 32v type stat structure */
        !            46: extern struct  stat    stat32v;
        !            47: /* place for times data so we can reverse the longs */
        !            48: struct timebuf {
        !            49:        long    t1;
        !            50:        long    t2;
        !            51:        long    t3;
        !            52:        long    t4;
        !            53: } timebuf;
        !            54: /* place for pipe file descriptors */
        !            55: int    pipes[2];
        !            56: /* wait status */
        !            57: int    wstatus;
        !            58: #ifdef V6UNIX
        !            59: /* version 6 style stat structure */
        !            60: struct v6nod {
        !            61:        dev_t   majmin;
        !            62:        ino_t   inumber;
        !            63:        unsigned short  flags;
        !            64:        unsigned char   nlinks;
        !            65:        unsigned char   uid;
        !            66:        unsigned char   gid;
        !            67:        unsigned char   size0;
        !            68:        unsigned short  size1;
        !            69:        unsigned short  addr[8];
        !            70:        long    actime;
        !            71:        long    modtime;
        !            72: } *v6stat;
        !            73: #endif
        !            74: /* do the trap stuff for the trap with code */
        !            75: dotrap(code) int code; {
        !            76:        register unsigned short *argp, *savp, *savep;
        !            77:        register int i, j, indirflg;
        !            78:        register char *avp, *oavp;
        !            79:        extern sigcatch();
        !            80:        extern errno;
        !            81:        /* clear out condition codes of psl */
        !            82:        psl &= ~017;
        !            83:        /* special case of indirect sys call */
        !            84:        if(code == 0) {
        !            85:                /* remember this was indirect */
        !            86:                indirflg = 1;
        !            87:                /* point to args */
        !            88:                argp = (unsigned short *)*(pc++);
        !            89:                /* code for indirect sys call */
        !            90:                code = *argp++;
        !            91:                /* is it legit */
        !            92:                if(code>>8 != TRAPS) {
        !            93:                        fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
        !            94:                        pc++;
        !            95:                        /* set carry flag */
        !            96:                        psl |= CARRY;
        !            97:                        regs[0] = -1;
        !            98:                        return(-1);
        !            99:                }
        !           100:                code &= 0377;
        !           101:        }
        !           102:        else {
        !           103:                /* remember this was not indirect */
        !           104:                indirflg = 0;
        !           105:                /* point to args */
        !           106:                argp = pc;
        !           107:        }
        !           108:        /* check if code too high or bad sys code */
        !           109:        if(code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
        !           110:                fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
        !           111:                /* set carry bit */
        !           112:                psl |= CARRY;
        !           113:                regs[0] = -1;
        !           114:                return(-1);
        !           115:        }
        !           116:        /* copy args to known locations */
        !           117:        i=0;
        !           118:        for(j=0; j<sysargs[code][0]; j++) args[i++] = regs[j];
        !           119:        for(j=0; j<(sysargs[code][1]); j++) args[i++] = *argp++;
        !           120: #ifdef TRACE
        !           121:        fprintf(stderr,"pid %d ",getpid());
        !           122:        if(indirflg) fprintf(stderr,"indirect ");
        !           123:        fprintf(stderr,"%s (%d) from 0%o with %d args",sysnames[code],code,pc-1,i);
        !           124:        for(j=0; j<i; j++)
        !           125:                fprintf(stderr," 0%o",args[j]);
        !           126:        if(code==OPEN||code==STAT||code==CREAT||code==EXEC||code==UNLNK||code==LINK||code==CHDIR||code==MKNOD)
        !           127:                fprintf(stderr," (%s)",args[0]);
        !           128: #ifdef V7UNIX
        !           129:        if(code==EXECE)
        !           130:                fprintf(stderr," (%s)",args[0]);
        !           131: #endif
        !           132:        if(code==LINK)
        !           133:                fprintf(stderr," (%s)",args[1]);
        !           134: #endif
        !           135:        /* go do whatever sys call it is */
        !           136:        switch(code) {
        !           137:        case    FORK:
        !           138:                /* indirect forks return pids on both sides - must do here */
        !           139:                /* this is possibly a bug in 32V */
        !           140:                i = fork();
        !           141:                break;
        !           142:        case    WAIT:
        !           143:                i = wait(&wstatus);
        !           144:                args[0] = i;
        !           145:                args[1] = wstatus;
        !           146:                break;
        !           147:        case    EXEC:
        !           148: #ifdef V7UNIX
        !           149:        case    EXECE:
        !           150: #endif
        !           151:                /*
        !           152:                 *  have to do a lot of junk here to fix up an argv
        !           153:                 *  for execute since (1) the pdp-11 argv consists of 16
        !           154:                 *  bit pointers and (2) the argv itself is in the
        !           155:                 *  pdp-11 program space where it would get clobbered
        !           156:                 *  when a new program is read in and before its
        !           157:                 *  argv is set up.
        !           158:                 */
        !           159:                avp = &argvs[0];
        !           160:                savp = (unsigned short *)args[1];
        !           161: #ifdef V6UNIX
        !           162:                for(i=1; args[i] = *savp++; i++)
        !           163:                        if(args[i] == 0177777) break;
        !           164: #ifdef TRACE
        !           165:                        else fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
        !           166: #endif
        !           167: #endif
        !           168: #ifdef V7UNIX
        !           169:                savep = (unsigned short *)args[2];
        !           170:                for(i=1; args[i] = *savp++; i++)
        !           171: #ifdef TRACE
        !           172:                        fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
        !           173: #else
        !           174:                        ;
        !           175: #endif
        !           176: #endif
        !           177:                if(stat(args[0], &stat32v)) {
        !           178:                        /* return error here if file does not exist */
        !           179: #ifdef TRACE
        !           180:                        fprintf(stderr," does not exist\n");
        !           181: #endif
        !           182:                        i = -1;
        !           183:                        break;
        !           184:                }
        !           185:                /* must have execute permission */
        !           186:                if(stat32v.st_mode & (S_IEXEC>>6)) goto experm;
        !           187:                if(stat32v.st_mode & (S_IEXEC>>3)) {
        !           188:                        if(stat32v.st_gid == getegid()) goto experm;
        !           189:                        if(geteuid() == 0) goto experm;
        !           190:                }
        !           191:                if(stat32v.st_mode & S_IEXEC) {
        !           192:                        if(stat32v.st_uid == geteuid()) goto experm;
        !           193:                        if(geteuid() == 0) goto experm;
        !           194:                }
        !           195:                /* return failure if no exec permision allowed */
        !           196:                i = -1;
        !           197: experm:
        !           198:                /* can't exec a directory */
        !           199:                if(stat32v.st_mode & S_IFDIR)
        !           200:                        i = -1;
        !           201:                if(i == -1) break;
        !           202:                args[i] = 0;
        !           203:                for(j=0; j<i; j++) {
        !           204:                        oavp = (char *)args[j];
        !           205:                        args[j] = (int)avp;
        !           206:                        while(*avp++ = *oavp++) ;
        !           207:                }
        !           208: #ifdef V7UNIX
        !           209:                if(code == EXECE) {
        !           210:                        for(j = ++i; args[j] = *savep++; j++) ;
        !           211:                        for( ; j>i; j--) {
        !           212:                                oavp = (char *)args[j];
        !           213:                                args[j] = (int)avp;
        !           214:                                while(*avp++ = *oavp++) ;
        !           215:                        }
        !           216:                }
        !           217: #endif
        !           218:                /* SETUID and SETGID files must be started with a fresh RTS */
        !           219:                if(stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
        !           220:                        /* should add a check here for good magic # in header */
        !           221:                        args[1] = args[0];
        !           222:                        args[0] = (int)RTSNAME;
        !           223: #ifdef TRACE
        !           224:                        fprintf(stderr," SETUID-GID");
        !           225: #endif
        !           226:                        if(args[i])
        !           227:                                i = execve(args[0], &args[0], &args[i]);
        !           228:                        else
        !           229:                                i = execv(args[0], &args[0]);
        !           230:                        fprintf(stderr,"can't exec %s\n",RTSNAME);
        !           231:                        break;
        !           232:                }
        !           233:                i = execute(args[0], &args[1], &args[i]);
        !           234:                /* shouldn't get here if exec works */
        !           235:                break;
        !           236:        case    SEEK:
        !           237: #ifdef V6UNIX
        !           238:                /* fix up negative offsets */
        !           239:                if(args[2] != 0 && args[2] != 3)
        !           240:                        if(args[1] >= 32768) args[1] -= 65536;
        !           241:                if(args[2] <= 2)
        !           242:                        i = lseek(args[0], args[1], args[2]);
        !           243:                else
        !           244:                        i = lseek(args[0], args[1]*512, args[2]-3);
        !           245:                if(i != -1) i = 0;
        !           246: #endif
        !           247: #ifdef V7UNIX
        !           248:                i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
        !           249: #endif
        !           250:                break;
        !           251: #ifdef V6UNIX
        !           252:        case    MKNOD:
        !           253:                /* version 6 uses allocated bit which means regular file here */
        !           254:                if(args[1] & S_IFBLK)
        !           255:                        args[1] &= ~S_IFREG;
        !           256:                i = mknod(args[0], args[1], args[2]);
        !           257:                break;
        !           258: #endif 
        !           259:        case    PIPE:
        !           260:                i = pipe(pipes);
        !           261:                args[0] = pipes[0];
        !           262:                args[1] = pipes[1];
        !           263:                break;
        !           264: #ifdef V6UNIX
        !           265:        case    TELL:
        !           266:                i = lseek(args[0], 0L, 1);
        !           267:                break;
        !           268: #endif
        !           269:        case    STAT:
        !           270:        case    FSTAT:
        !           271:                /* do the syscall to a local stat buffer */
        !           272:                i = syscall(code, args[0], &stat32v);
        !           273:                /* reverse the longs */
        !           274:                stat32v.st_size = longrev(stat32v.st_size);
        !           275:                stat32v.st_atime = longrev(stat32v.st_atime);
        !           276:                stat32v.st_mtime = longrev(stat32v.st_mtime);
        !           277:                stat32v.st_ctime = longrev(stat32v.st_ctime);
        !           278: #ifdef V7UNIX
        !           279:                /* copy out otherwise unchanged stat buffer */
        !           280:                /* in two pieces with st_size as the breaking point */
        !           281:                /* note that st_rdev is a short but due to alingnmemt */
        !           282:                /* problems the rest of the structure is out of sync */
        !           283:                j = (int)((char *)(&stat32v.st_size)-(char *)(&stat32v.st_dev));
        !           284:                bcopy(&stat32v, args[1], j);
        !           285:                bcopy(&stat32v.st_size, args[1]+j-2, sizeof(struct stat)-j);
        !           286: #endif
        !           287: #ifdef V6UNIX
        !           288:                /* point to user area as v6stat structure */
        !           289:                v6stat = (struct v6nod *)args[1];
        !           290:                /* copy out piece by piece */
        !           291:                v6stat->majmin = stat32v.st_dev;
        !           292:                v6stat->inumber = stat32v.st_ino;
        !           293:                v6stat->flags = stat32v.st_mode;
        !           294:                v6stat->nlinks = (unsigned char)stat32v.st_nlink;
        !           295:                v6stat->uid = (unsigned char)stat32v.st_uid;
        !           296:                v6stat->gid = (unsigned char)stat32v.st_gid;
        !           297:                /* note size already reversed */
        !           298:                v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
        !           299:                v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
        !           300:                v6stat->actime = stat32v.st_atime;
        !           301:                v6stat->modtime = stat32v.st_mtime;
        !           302:                /* patch up flags */
        !           303:                /* for now just set 100000 bit if not a plain file */
        !           304:                if(v6stat->flags & 060000)
        !           305:                        v6stat->flags |= 0100000;
        !           306: #endif
        !           307:                break;
        !           308:        case    TIMES:
        !           309:                i = times(&timebuf);
        !           310:                timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
        !           311:                timebuf.t3 = longrev(timebuf.t3);
        !           312:                timebuf.t4 = longrev(timebuf.t4);
        !           313:                bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
        !           314:                break;
        !           315: #ifdef V6UNIX
        !           316:        case    SLEEP:
        !           317:                /* do a sleep function - what about pwb which has alarm? */
        !           318:                sleep(args[0]);
        !           319:                break;
        !           320: #endif
        !           321:        case    GETUID:
        !           322:                args[0] = getuid();
        !           323:                args[1] = geteuid();
        !           324: #ifdef V6UNIX
        !           325:                i = args[1]<<8 | args[0];
        !           326: #endif
        !           327:                break;
        !           328:        case    GETGID:
        !           329:                args[0] = getgid();
        !           330:                args[1] = getegid();
        !           331: #ifdef V6UNIX
        !           332:                i = args[1]<<8 | args[0];
        !           333: #endif
        !           334:                break;
        !           335: #ifdef V6UNIX
        !           336:        case    SETUID:
        !           337:        case    SETGID:
        !           338:                /* uids and gids are 8 bits in version 6 */
        !           339:                i = syscall(code,args[0]&0377);
        !           340:                break;
        !           341: #endif
        !           342:        case    SIG:
        !           343:                /* if it is a good signal code */
        !           344:                if(args[0] <= NSIG) {
        !           345:                        /* get the current signal value */
        !           346:                        i = sigvals[args[0]];
        !           347:                        /* reset the signal to the new value */
        !           348:                        sigvals[args[0]] = args[1];
        !           349:                        /* actually do signal except don't reset SIGILL */
        !           350:                        if(args[0] != SIGILL) {
        !           351:                                if(args[1] == (int)SIG_DFL || args[1] & (int)SIG_IGN) {
        !           352:                                        if((int)signal(args[0],args[1]) == -1)
        !           353:                                                i = -1;
        !           354:                                } else {
        !           355:                                        if((int)signal(args[0], sigcatch) == -1)
        !           356:                                                i = -1;
        !           357:                                }
        !           358:                        }
        !           359:                }
        !           360:                else i = -1;
        !           361:                break;
        !           362:        case    BRK:
        !           363:                /* brk is successful unless we run over the stack */
        !           364:                i = 0;
        !           365:                if(args[0] >= regs[6]) i = -1;
        !           366:                break;
        !           367: #ifdef V6UNIX
        !           368:        case    PWBSYS:
        !           369:                /* ignore pwbsys for now */
        !           370:                switch(args[2]) {
        !           371:                case    UNAME:
        !           372: #ifdef TRACE
        !           373:                        fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
        !           374: #endif
        !           375:                        strcpy(args[0],"pwbname");
        !           376:                        i = 0;
        !           377:                        break;
        !           378:                case    UDATA:
        !           379: #ifdef TRACE
        !           380:                        fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
        !           381: #endif
        !           382:                        i = 0;
        !           383:                        break;
        !           384:                case    USTAT:
        !           385: fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
        !           386:                        i = 0;
        !           387:                        break;
        !           388:                case    UTIME:
        !           389: fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
        !           390:                        i = 0;
        !           391:                        break;
        !           392:                default:
        !           393: fprintf(stderr,"bad PWBSYS %d\n",args[3]);
        !           394:                        i = -1;
        !           395:                        break;
        !           396:                }
        !           397:                break;
        !           398: #endif
        !           399:        default:
        !           400:                /*
        !           401:                 *      Many sys calls are easily done here since most
        !           402:                 *      system call codes are the same on version 6 and 7 UNIX
        !           403:                 *      as they are here.
        !           404:                 */
        !           405:                i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
        !           406: #ifdef V6UNIX
        !           407:                /* allow read write access to created files for(IDIS v6 mod) */
        !           408:                if(code==CREAT) {
        !           409:                        /* get actual file mode after create */
        !           410:                        fstat(i, &stat32v);
        !           411:                        close(i);
        !           412:                        /* ensure read/write access to owner */
        !           413:                        chmod(args[0], 0644);
        !           414:                        i = open(args[0], 2);
        !           415:                        /* change mode back the way it was */
        !           416:                        chmod(args[0], stat32v.st_mode);
        !           417:                }
        !           418: #endif
        !           419:                break;
        !           420:        }
        !           421: #ifdef TRACE
        !           422:        fprintf(stderr," sys val -> 0%o\n",i);
        !           423: #endif
        !           424:        /* set carry bit if sys error */
        !           425:        if(i == -1)
        !           426:                psl |= CARRY;
        !           427:        /* if not an indirect sys call, adjust the pc */
        !           428:        if(indirflg == 0)
        !           429:                pc = argp;
        !           430:        /* do alternate return on one side of fork */
        !           431:        if(code == FORK && i != 0)
        !           432:                pc++;
        !           433:        /* do the various return value formats */
        !           434:        switch(sysargs[code][2]) {
        !           435:        case    NORMRET:
        !           436:                /* normal case only one return value in r0 */
        !           437:                regs[0] = i;
        !           438:                break;
        !           439:        case    LONGRET:
        !           440:                /* return a long in r0 - r1 as in time */
        !           441:                regs[1] = i;
        !           442:                regs[0] = i >> 16;
        !           443:                break;
        !           444:        case    TWORET:
        !           445:                /* return two ints in r0 - r1 as in pipe */
        !           446:                if(i == -1)
        !           447:                        regs[0] = i;
        !           448:                else {
        !           449:                        regs[1] = args[1];
        !           450:                        regs[0] = args[0];
        !           451:                }
        !           452:                break;
        !           453:        }
        !           454:        if(i== -1)
        !           455:                regs[0] = errno;
        !           456: }
        !           457: long longrev(l) long l; {
        !           458:        /* function to reverse the halves of a long */
        !           459:        union {
        !           460:                long    lng;
        !           461:                short   s[2];
        !           462:        } u;
        !           463:        register short t;
        !           464:        u.lng = l;
        !           465:        t = u.s[0];
        !           466:        u.s[0] = u.s[1];
        !           467:        u.s[1] = t;
        !           468:        return(u.lng);
        !           469: }

unix.superglobalmegacorp.com

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