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