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