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