1*14310Ssam static char sccsid[] = "@(#)runcompat.c 4.2 83/07/31";
26801Srrh
36801Srrh /*
4*14310Ssam * Compatability mode support
56801Srrh * written by Art Wetzel during August 1979
66801Srrh * at the Interdisciplinary Dept of Information Science
76801Srrh * Room 711, LIS Bldg
86801Srrh * University of Pittsburgh
96801Srrh * Pittsburgh, Pa 15260
106801Srrh *
116801Srrh * No claims are made on the completeness of the support of any
126801Srrh * of the systems simulated under this package
136801Srrh */
14*14310Ssam
156801Srrh #include <stdio.h>
166801Srrh #include <signal.h>
176801Srrh #include <sys/types.h>
186801Srrh #include <sys/stat.h>
196801Srrh #include <errno.h>
206801Srrh #include "defs.h"
216801Srrh #ifdef UNIX
226801Srrh #include "unixhdr.h"
236801Srrh #endif
246801Srrh #ifdef RT11
256801Srrh #include "rt11.h"
266801Srrh #endif
27*14310Ssam
28*14310Ssam struct stat stat32v;
29*14310Ssam u_short regs[8];
30*14310Ssam u_long psl;
31*14310Ssam u_short *pc;
32*14310Ssam int incompat;
336801Srrh char *progname;
346801Srrh char *nameend;
35*14310Ssam
main(argc,argv,envp)36*14310Ssam main(argc, argv, envp)
37*14310Ssam int argc;
38*14310Ssam char **argv, **envp;
39*14310Ssam {
40*14310Ssam
41*14310Ssam if (argc < 2) {
426801Srrh fprintf(stderr,"Usage: %s [-rootdir] file args...\n",argv[0]);
436801Srrh exit(1);
446801Srrh }
456801Srrh /* remember where the program name etc should go for using ps */
466801Srrh progname = argv[0];
476801Srrh nameend = envp[0]-1;
486801Srrh argv++;
496801Srrh /* set up alternate root directory if flagged for */
50*14310Ssam if (*argv[0] == '-') {
51*14310Ssam if (chroot(argv[0]+1)) {
526801Srrh fprintf(stderr,"Can't change root to %s\n",argv[0]+1);
536801Srrh exit(-1);
546801Srrh }
556801Srrh argv++;
566801Srrh }
576801Srrh /* check out file stats of file to run */
58*14310Ssam if (stat(argv[0], &stat32v)) {
596801Srrh fprintf(stderr,"%s does not exist\n",argv[0]);
606801Srrh exit(1);
616801Srrh }
626801Srrh /* a version of SETUID and SETGID file executions */
636801Srrh /* the binary of this program should be SETUID root for this to work */
646801Srrh /* requires nonstandard seteuid and setegid sys calls */
65*14310Ssam if (!(stat32v.st_mode & S_ISGID) || setegid(stat32v.st_gid))
666801Srrh /* if not SETGID file or error, drop back to real group */
676801Srrh setgid(getgid());
68*14310Ssam if (!(stat32v.st_mode & S_ISUID) || seteuid(stat32v.st_uid))
696801Srrh /* if not SETUID file or error, drop back to real uid */
706801Srrh setuid(getuid());
716801Srrh #ifdef V6UNIX
726801Srrh /* no umasks in version 6 */
736801Srrh umask(0);
746801Srrh #endif
756801Srrh /* go try to execute , passing along args and environment */
766801Srrh execute(argv[0], argv, envp);
776801Srrh /* only get here if execute fails */
786801Srrh fprintf(stderr,"Execution failure on %s\n",argv[0]);
796801Srrh exit(1);
806801Srrh }
81*14310Ssam
execute(file,argv,envp)82*14310Ssam execute(file, argv, envp)
83*14310Ssam char *file, **argv, **envp;
84*14310Ssam {
856801Srrh int fd, n, tloadpt, dloadpt, tloadsize, dloadsize, stacksize;
866801Srrh register short *p;
876801Srrh extern illtrap();
886801Srrh extern char **environ;
89*14310Ssam
906801Srrh /* file to run should be readable */
91*14310Ssam if ((fd = open(file, 0)) == -1) {
926801Srrh fprintf(stderr,"Can't open %s for read access\n",file);
936801Srrh return(-1);
946801Srrh }
956801Srrh #ifdef UNIX
96*14310Ssam if ((n = read(fd, &header, sizeof header)) != sizeof header)
976801Srrh return(ENOEXEC);
986801Srrh /* check to see if really unix file */
99*14310Ssam if (header.magic != MAGIC1 && header.magic != MAGIC2 &&
100*14310Ssam header.magic != MAGIC3 && header.magic != MAGIC4) {
1016801Srrh return(ENOEXEC);
1026801Srrh }
103*14310Ssam /* if a UNIX file run it */
104*14310Ssam if (header.textsize == 0) {
1056801Srrh close(fd);
1066801Srrh /* if no explicit env, pass along environ */
107*14310Ssam if (!envp || *envp == 0)
1086801Srrh return(execve(file, argv, environ));
1096801Srrh return(execve(file, argv, envp));
1106801Srrh }
1116801Srrh /* checks out OK as PDP-11 UNIX file */
112*14310Ssam if (header.magic == MAGIC3) {
1136801Srrh fprintf(stderr,"%s compiled for separate I/D space\n",argv[0]);
1146801Srrh return(-1);
1156801Srrh }
1166801Srrh /* unix text loads at 0 */
1176801Srrh tloadpt = 0;
1186801Srrh /* set starting pc value */
1196801Srrh pc = (unsigned short *)header.entry;
1206801Srrh /* figure out where to load initialized data */
1216801Srrh dloadpt = tloadsize = header.textsize;
1226801Srrh /* check if alignment of data segment to 8k byte boundary */
123*14310Ssam if (header.magic == MAGIC2)
1246801Srrh dloadpt = (dloadpt+8191) & (~8191);
1256801Srrh /* how much data */
1266801Srrh dloadsize = header.datasize;
1276801Srrh stacksize = header.bsssize;
1286801Srrh #endif
1296801Srrh #ifdef RT11
130*14310Ssam if ((n = read(fd, shortspace, RTHDRSIZ)) != RTHDRSIZ) {
1316801Srrh fprintf(stderr,"Error reading 1st block\n");
1326801Srrh return(-1);
1336801Srrh }
1346801Srrh /* rt11 files are 0 aligned including the header */
1356801Srrh tloadpt = RTHDRSIZ;
1366801Srrh /* set starting pc value */
1376801Srrh pc = (unsigned short *)shortspace[RTPC];
1386801Srrh /* initialize stack location */
1396801Srrh regs[6] = shortspace[RTSP];
1406801Srrh /* figure how much to load */
1416801Srrh dloadpt = tloadsize = shortspace[RTHGH]-RTHDRSIZ;
1426801Srrh /* no separate data as in unix */
1436801Srrh dloadsize = 0;
1446801Srrh stacksize = 0;
1456801Srrh #endif
1466801Srrh /* see if it all fits into available memory space */
147*14310Ssam if ((dloadpt+dloadsize+stacksize) > (int)memsiz) {
1486801Srrh fprintf(stderr,"File too big to run\n");
1496801Srrh return(-1);
1506801Srrh }
1516801Srrh /* read text segment */
152*14310Ssam if ((n = read(fd, tloadpt, tloadsize)) < tloadsize) {
1536801Srrh fprintf(stderr,"Text read failure\n");
1546801Srrh return(-1);
1556801Srrh }
1566801Srrh /* read data segment */
157*14310Ssam if ((n = read(fd, dloadpt, dloadsize)) < dloadsize) {
1586801Srrh fprintf(stderr,"Data read failure\n");
1596801Srrh return(-1);
1606801Srrh }
1616801Srrh /* clear out the rest of memory */
1626801Srrh p = (short *)(dloadpt + dloadsize);
163*14310Ssam while (p < (short *)memsiz)
164*14310Ssam *p++ = 0;
1656801Srrh /* close file before starting it */
1666801Srrh close(fd);
1676801Srrh /* set up illegal instruction trapping */
1686801Srrh signal(SIGILL, illtrap);
1696801Srrh /* lets give it a try */
1706801Srrh start(argv, envp);
1716801Srrh }
172*14310Ssam
illtrap(signum,faultcode,scp)173*14310Ssam illtrap(signum, faultcode, scp)
174*14310Ssam int signum, faultcode;
175*14310Ssam struct sigcontext *scp;
176*14310Ssam {
1776801Srrh unsigned short *pcptr;
1786801Srrh int instr;
1796801Srrh register int i;
1806801Srrh extern getregs();
181*14310Ssam
1826801Srrh /* record the fact that we are not in compatability mode now */
1836801Srrh incompat = 0;
1846801Srrh /* get the register values before they get clobbered */
1856801Srrh getregs();
1866801Srrh /* figure out what the pc was */
187*14310Ssam pcptr = (unsigned short *) &scp->sc_pc;
1886801Srrh pc = (unsigned short *) *pcptr;
1896801Srrh /* get the instruction */
1906801Srrh instr = *pc;
1916801Srrh /* incriment the pc over this instruction */
1926801Srrh pc++;
1936801Srrh /* set register 7 as pc synonym */
1946801Srrh regs[7] = (unsigned short)(int)pc;
1956801Srrh /* set up psl with condition codes */
1966801Srrh /* a UNIX-32V monitor patch is required to not clear condition codes */
197*14310Ssam psl = 0x83c00000 | (scp->sc_ps & 017);
198*14310Ssam sigsetmask(scp->sc_mask);
1996801Srrh /* pick out the appropriate action for this illegal instruction */
2006801Srrh switch(instr>>8){
201*14310Ssam
202*14310Ssam case TRAPS:
2036801Srrh dotrap(instr & 0377);
2046801Srrh break;
205*14310Ssam
206*14310Ssam case EMTS:
207*14310Ssam if (sigvals[SIGEMT] && ((sigvals[SIGEMT]%2) != 1)) {
2086801Srrh dosig(SIGEMT, pc);
2096801Srrh break;
2106801Srrh }
2116801Srrh doemt(instr & 0377);
2126801Srrh break;
213*14310Ssam
2146801Srrh default:
215*14310Ssam if (instr >= 075000 && instr < 075040) {
2166801Srrh /* fis instructions */
217*14310Ssam if (dofloat(instr) == 0)
2186801Srrh break;
2196801Srrh }
220*14310Ssam if (instr >= 0170000) {
2216801Srrh /* floating point unit instructions */
222*14310Ssam if (dofloat(instr) == 0)
2236801Srrh break;
2246801Srrh }
2256801Srrh /* genuine illegal instruction */
2266801Srrh /* if signal trap set go to user's trap location */
227*14310Ssam if (sigvals[SIGILL] && ((sigvals[SIGILL]%2) != 1)) {
2286801Srrh dosig(SIGILL, pc);
2296801Srrh break;
2306801Srrh }
2316801Srrh /* ignore uncaught setd instructions */
232*14310Ssam if (instr == SETD)
2336801Srrh break;
2346801Srrh /* otherwise put out a message and quit */
235*14310Ssam printf("Illegal instruction, psl 0x%08x, pc 0%04o\n",psl,pc-1);
236*14310Ssam for (i = 0; i < 7; i++)
237*14310Ssam printf("0x%04x ",regs[i]);
2386801Srrh printf("0x%04x -> 0%o\n",pc-1,instr);
2396801Srrh /* set up to dump on illegal instruction */
2406801Srrh signal(SIGILL,SIG_DFL);
2416801Srrh /* set pc back to bad instruction */
2426801Srrh pc--;
2436801Srrh /* go do it again for dump */
2446801Srrh compat();
2456801Srrh }
2466801Srrh /* go back to compatability mode */
2476801Srrh incompat++;
2486801Srrh compat();
2496801Srrh }
250