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