BSD 4 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Fri, 7 Nov 1980 09:42:20 +0000 (01:42 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Fri, 7 Nov 1980 09:42:20 +0000 (01:42 -0800)
Work on file usr/src/games/compat/unixtraps.c

Synthesized-from: CSRG//cd1/4.0

usr/src/games/compat/unixtraps.c [new file with mode: 0644]

diff --git a/usr/src/games/compat/unixtraps.c b/usr/src/games/compat/unixtraps.c
new file mode 100644 (file)
index 0000000..dc88b5a
--- /dev/null
@@ -0,0 +1,469 @@
+#
+/*     Function to execute version 6 and version 7 UNIX system calls from
+ *     compatability mode on UNIX-32V.
+ *     Art Wetzel      August 1979
+ */
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef V6UNIX
+#ifdef TRACE
+#define        RTSNAME "/../../../../usr/local/v6trc"
+#else
+#define        RTSNAME "/../../../../usr/local/v6run"
+#endif
+#include "unix6sys.h"
+#ifdef TRACE
+#include "unix6sysn.h"
+#endif
+#endif
+#ifdef V7UNIX
+#ifdef TRACE
+#define        RTSNAME "/../../../../usr/local/v7trc"
+#else
+#define        RTSNAME "/../../../../usr/local/v7run"
+#endif
+#include "unix7sys.h"
+#ifdef TRACE
+#include "unix7sysn.h"
+#endif
+#endif
+#include "defs.h"
+#define        CARRY   1
+#define        MAXSARGS        25
+#ifdef V6UNIX
+#define        ARGVLEN 512
+#define        ENVLEN  0
+#endif
+#ifdef V7UNIX
+#define        ARGVLEN 5120
+#define        ENVLEN  1000
+#endif
+char   argvs[ARGVLEN+ENVLEN];
+int    args[MAXSARGS];
+/* 32v type stat structure */
+extern struct  stat    stat32v;
+/* place for times data so we can reverse the longs */
+struct timebuf {
+       long    t1;
+       long    t2;
+       long    t3;
+       long    t4;
+} timebuf;
+/* place for pipe file descriptors */
+int    pipes[2];
+/* wait status */
+int    wstatus;
+#ifdef V6UNIX
+/* version 6 style stat structure */
+struct v6nod {
+       dev_t   majmin;
+       ino_t   inumber;
+       unsigned short  flags;
+       unsigned char   nlinks;
+       unsigned char   uid;
+       unsigned char   gid;
+       unsigned char   size0;
+       unsigned short  size1;
+       unsigned short  addr[8];
+       long    actime;
+       long    modtime;
+} *v6stat;
+#endif
+/* do the trap stuff for the trap with code */
+dotrap(code) int code; {
+       register unsigned short *argp, *savp, *savep;
+       register int i, j, indirflg;
+       register char *avp, *oavp;
+       extern sigcatch();
+       extern errno;
+       /* clear out condition codes of psl */
+       psl &= ~017;
+       /* special case of indirect sys call */
+       if(code == 0) {
+               /* remember this was indirect */
+               indirflg = 1;
+               /* point to args */
+               argp = (unsigned short *)*(pc++);
+               /* code for indirect sys call */
+               code = *argp++;
+               /* is it legit */
+               if(code>>8 != TRAPS) {
+                       fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
+                       pc++;
+                       /* set carry flag */
+                       psl |= CARRY;
+                       regs[0] = -1;
+                       return(-1);
+               }
+               code &= 0377;
+       }
+       else {
+               /* remember this was not indirect */
+               indirflg = 0;
+               /* point to args */
+               argp = pc;
+       }
+       /* check if code too high or bad sys code */
+       if(code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
+               fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
+               /* set carry bit */
+               psl |= CARRY;
+               regs[0] = -1;
+               return(-1);
+       }
+       /* copy args to known locations */
+       i=0;
+       for(j=0; j<sysargs[code][0]; j++) args[i++] = regs[j];
+       for(j=0; j<(sysargs[code][1]); j++) args[i++] = *argp++;
+#ifdef TRACE
+       fprintf(stderr,"pid %d ",getpid());
+       if(indirflg) fprintf(stderr,"indirect ");
+       fprintf(stderr,"%s (%d) from 0%o with %d args",sysnames[code],code,pc-1,i);
+       for(j=0; j<i; j++)
+               fprintf(stderr," 0%o",args[j]);
+       if(code==OPEN||code==STAT||code==CREAT||code==EXEC||code==UNLNK||code==LINK||code==CHDIR||code==MKNOD)
+               fprintf(stderr," (%s)",args[0]);
+#ifdef V7UNIX
+       if(code==EXECE)
+               fprintf(stderr," (%s)",args[0]);
+#endif
+       if(code==LINK)
+               fprintf(stderr," (%s)",args[1]);
+#endif
+       /* go do whatever sys call it is */
+       switch(code) {
+       case    FORK:
+               /* indirect forks return pids on both sides - must do here */
+               /* this is possibly a bug in 32V */
+               i = fork();
+               break;
+       case    WAIT:
+               i = wait(&wstatus);
+               args[0] = i;
+               args[1] = wstatus;
+               break;
+       case    EXEC:
+#ifdef V7UNIX
+       case    EXECE:
+#endif
+               /*
+                *  have to do a lot of junk here to fix up an argv
+                *  for execute since (1) the pdp-11 argv consists of 16
+                *  bit pointers and (2) the argv itself is in the
+                *  pdp-11 program space where it would get clobbered
+                *  when a new program is read in and before its
+                *  argv is set up.
+                */
+               avp = &argvs[0];
+               savp = (unsigned short *)args[1];
+#ifdef V6UNIX
+               for(i=1; args[i] = *savp++; i++)
+                       if(args[i] == 0177777) break;
+#ifdef TRACE
+                       else fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
+#endif
+#endif
+#ifdef V7UNIX
+               savep = (unsigned short *)args[2];
+               for(i=1; args[i] = *savp++; i++)
+#ifdef TRACE
+                       fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
+#else
+                       ;
+#endif
+#endif
+               if(stat(args[0], &stat32v)) {
+                       /* return error here if file does not exist */
+#ifdef TRACE
+                       fprintf(stderr," does not exist\n");
+#endif
+                       i = -1;
+                       break;
+               }
+               /* must have execute permission */
+               if(stat32v.st_mode & (S_IEXEC>>6)) goto experm;
+               if(stat32v.st_mode & (S_IEXEC>>3)) {
+                       if(stat32v.st_gid == getegid()) goto experm;
+                       if(geteuid() == 0) goto experm;
+               }
+               if(stat32v.st_mode & S_IEXEC) {
+                       if(stat32v.st_uid == geteuid()) goto experm;
+                       if(geteuid() == 0) goto experm;
+               }
+               /* return failure if no exec permision allowed */
+               i = -1;
+experm:
+               /* can't exec a directory */
+               if(stat32v.st_mode & S_IFDIR)
+                       i = -1;
+               if(i == -1) break;
+               args[i] = 0;
+               for(j=0; j<i; j++) {
+                       oavp = (char *)args[j];
+                       args[j] = (int)avp;
+                       while(*avp++ = *oavp++) ;
+               }
+#ifdef V7UNIX
+               if(code == EXECE) {
+                       for(j = ++i; args[j] = *savep++; j++) ;
+                       for( ; j>i; j--) {
+                               oavp = (char *)args[j];
+                               args[j] = (int)avp;
+                               while(*avp++ = *oavp++) ;
+                       }
+               }
+#endif
+               /* SETUID and SETGID files must be started with a fresh RTS */
+               if(stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
+                       /* should add a check here for good magic # in header */
+                       args[1] = args[0];
+                       args[0] = (int)RTSNAME;
+#ifdef TRACE
+                       fprintf(stderr," SETUID-GID");
+#endif
+                       if(args[i])
+                               i = execve(args[0], &args[0], &args[i]);
+                       else
+                               i = execv(args[0], &args[0]);
+                       fprintf(stderr,"can't exec %s\n",RTSNAME);
+                       break;
+               }
+               i = execute(args[0], &args[1], &args[i]);
+               /* shouldn't get here if exec works */
+               break;
+       case    SEEK:
+#ifdef V6UNIX
+               /* fix up negative offsets */
+               if(args[2] != 0 && args[2] != 3)
+                       if(args[1] >= 32768) args[1] -= 65536;
+               if(args[2] <= 2)
+                       i = lseek(args[0], args[1], args[2]);
+               else
+                       i = lseek(args[0], args[1]*512, args[2]-3);
+               if(i != -1) i = 0;
+#endif
+#ifdef V7UNIX
+               i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
+#endif
+               break;
+#ifdef V6UNIX
+       case    MKNOD:
+               /* version 6 uses allocated bit which means regular file here */
+               if(args[1] & S_IFBLK)
+                       args[1] &= ~S_IFREG;
+               i = mknod(args[0], args[1], args[2]);
+               break;
+#endif 
+       case    PIPE:
+               i = pipe(pipes);
+               args[0] = pipes[0];
+               args[1] = pipes[1];
+               break;
+#ifdef V6UNIX
+       case    TELL:
+               i = lseek(args[0], 0L, 1);
+               break;
+#endif
+       case    STAT:
+       case    FSTAT:
+               /* do the syscall to a local stat buffer */
+               i = syscall(code, args[0], &stat32v);
+               /* reverse the longs */
+               stat32v.st_size = longrev(stat32v.st_size);
+               stat32v.st_atime = longrev(stat32v.st_atime);
+               stat32v.st_mtime = longrev(stat32v.st_mtime);
+               stat32v.st_ctime = longrev(stat32v.st_ctime);
+#ifdef V7UNIX
+               /* copy out otherwise unchanged stat buffer */
+               /* in two pieces with st_size as the breaking point */
+               /* note that st_rdev is a short but due to alingnmemt */
+               /* problems the rest of the structure is out of sync */
+               j = (int)((char *)(&stat32v.st_size)-(char *)(&stat32v.st_dev));
+               bcopy(&stat32v, args[1], j);
+               bcopy(&stat32v.st_size, args[1]+j-2, sizeof(struct stat)-j);
+#endif
+#ifdef V6UNIX
+               /* point to user area as v6stat structure */
+               v6stat = (struct v6nod *)args[1];
+               /* copy out piece by piece */
+               v6stat->majmin = stat32v.st_dev;
+               v6stat->inumber = stat32v.st_ino;
+               v6stat->flags = stat32v.st_mode;
+               v6stat->nlinks = (unsigned char)stat32v.st_nlink;
+               v6stat->uid = (unsigned char)stat32v.st_uid;
+               v6stat->gid = (unsigned char)stat32v.st_gid;
+               /* note size already reversed */
+               v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
+               v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
+               v6stat->actime = stat32v.st_atime;
+               v6stat->modtime = stat32v.st_mtime;
+               /* patch up flags */
+               /* for now just set 100000 bit if not a plain file */
+               if(v6stat->flags & 060000)
+                       v6stat->flags |= 0100000;
+#endif
+               break;
+       case    TIMES:
+               i = times(&timebuf);
+               timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
+               timebuf.t3 = longrev(timebuf.t3);
+               timebuf.t4 = longrev(timebuf.t4);
+               bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
+               break;
+#ifdef V6UNIX
+       case    SLEEP:
+               /* do a sleep function - what about pwb which has alarm? */
+               sleep(args[0]);
+               break;
+#endif
+       case    GETUID:
+               args[0] = getuid();
+               args[1] = geteuid();
+#ifdef V6UNIX
+               i = args[1]<<8 | args[0];
+#endif
+               break;
+       case    GETGID:
+               args[0] = getgid();
+               args[1] = getegid();
+#ifdef V6UNIX
+               i = args[1]<<8 | args[0];
+#endif
+               break;
+#ifdef V6UNIX
+       case    SETUID:
+       case    SETGID:
+               /* uids and gids are 8 bits in version 6 */
+               i = syscall(code,args[0]&0377);
+               break;
+#endif
+       case    SIG:
+               /* if it is a good signal code */
+               if(args[0] <= NSIG) {
+                       /* get the current signal value */
+                       i = sigvals[args[0]];
+                       /* reset the signal to the new value */
+                       sigvals[args[0]] = args[1];
+                       /* actually do signal except don't reset SIGILL */
+                       if(args[0] != SIGILL) {
+                               if(args[1] == (int)SIG_DFL || args[1] & (int)SIG_IGN) {
+                                       if((int)signal(args[0],args[1]) == -1)
+                                               i = -1;
+                               } else {
+                                       if((int)signal(args[0], sigcatch) == -1)
+                                               i = -1;
+                               }
+                       }
+               }
+               else i = -1;
+               break;
+       case    BRK:
+               /* brk is successful unless we run over the stack */
+               i = 0;
+               if(args[0] >= regs[6]) i = -1;
+               break;
+#ifdef V6UNIX
+       case    PWBSYS:
+               /* ignore pwbsys for now */
+               switch(args[2]) {
+               case    UNAME:
+#ifdef TRACE
+                       fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
+#endif
+                       strcpy(args[0],"pwbname");
+                       i = 0;
+                       break;
+               case    UDATA:
+#ifdef TRACE
+                       fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
+#endif
+                       i = 0;
+                       break;
+               case    USTAT:
+fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
+                       i = 0;
+                       break;
+               case    UTIME:
+fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
+                       i = 0;
+                       break;
+               default:
+fprintf(stderr,"bad PWBSYS %d\n",args[3]);
+                       i = -1;
+                       break;
+               }
+               break;
+#endif
+       default:
+               /*
+                *      Many sys calls are easily done here since most
+                *      system call codes are the same on version 6 and 7 UNIX
+                *      as they are here.
+                */
+               i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
+#ifdef V6UNIX
+               /* allow read write access to created files for(IDIS v6 mod) */
+               if(code==CREAT) {
+                       /* get actual file mode after create */
+                       fstat(i, &stat32v);
+                       close(i);
+                       /* ensure read/write access to owner */
+                       chmod(args[0], 0644);
+                       i = open(args[0], 2);
+                       /* change mode back the way it was */
+                       chmod(args[0], stat32v.st_mode);
+               }
+#endif
+               break;
+       }
+#ifdef TRACE
+       fprintf(stderr," sys val -> 0%o\n",i);
+#endif
+       /* set carry bit if sys error */
+       if(i == -1)
+               psl |= CARRY;
+       /* if not an indirect sys call, adjust the pc */
+       if(indirflg == 0)
+               pc = argp;
+       /* do alternate return on one side of fork */
+       if(code == FORK && i != 0)
+               pc++;
+       /* do the various return value formats */
+       switch(sysargs[code][2]) {
+       case    NORMRET:
+               /* normal case only one return value in r0 */
+               regs[0] = i;
+               break;
+       case    LONGRET:
+               /* return a long in r0 - r1 as in time */
+               regs[1] = i;
+               regs[0] = i >> 16;
+               break;
+       case    TWORET:
+               /* return two ints in r0 - r1 as in pipe */
+               if(i == -1)
+                       regs[0] = i;
+               else {
+                       regs[1] = args[1];
+                       regs[0] = args[0];
+               }
+               break;
+       }
+       if(i== -1)
+               regs[0] = errno;
+}
+long longrev(l) long l; {
+       /* function to reverse the halves of a long */
+       union {
+               long    lng;
+               short   s[2];
+       } u;
+       register short t;
+       u.lng = l;
+       t = u.s[0];
+       u.s[0] = u.s[1];
+       u.s[1] = t;
+       return(u.lng);
+}