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;
main(argc,argv,envp)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 }
execute(file,argv,envp)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 }
illtrap()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