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