116442Smckusick #ifndef	lint
2*35698Sbostic static char sccsid[] = "@(#)unixtraps.c	4.4 88/09/22";
316442Smckusick #endif
414311Ssam 
516442Smckusick /* From Lou Salkind: compat/RCS/unixtraps.c,v 1.2 84/01/31 13:34:34 */
616442Smckusick 
714311Ssam /*
814311Ssam  * Function to execute version 6 and version 7 UNIX system calls from
914311Ssam  * compatability mode on UNIX-32V.
106809Srrh  *	Art Wetzel	August 1979
116809Srrh  */
1214311Ssam 
136809Srrh #include <stdio.h>
146809Srrh #include <signal.h>
156809Srrh #include <sys/types.h>
166809Srrh #include <sys/stat.h>
1714311Ssam #include <sys/ioctl.h>
1814311Ssam #include <sys/time.h>
1916442Smckusick #include <sys/dir.h>
206809Srrh #ifdef V6UNIX
216809Srrh #ifdef TRACE
226809Srrh #define	RTSNAME	"/../../../../usr/local/v6trc"
236809Srrh #else
246809Srrh #define	RTSNAME	"/../../../../usr/local/v6run"
256809Srrh #endif
266809Srrh #include "unix6sys.h"
276809Srrh #ifdef TRACE
286809Srrh #include "unix6sysn.h"
296809Srrh #endif
306809Srrh #endif
316809Srrh #ifdef V7UNIX
326809Srrh #ifdef TRACE
336809Srrh #define	RTSNAME	"/../../../../usr/local/v7trc"
346809Srrh #else
356809Srrh #define	RTSNAME	"/../../../../usr/local/v7run"
366809Srrh #endif
376809Srrh #include "unix7sys.h"
386809Srrh #ifdef TRACE
396809Srrh #include "unix7sysn.h"
406809Srrh #endif
416809Srrh #endif
426809Srrh #include "defs.h"
436809Srrh #define	CARRY	1
4416442Smckusick #define	MAXSARGS	100
456809Srrh #ifdef V6UNIX
466809Srrh #define	ARGVLEN	512
476809Srrh #define	ENVLEN	0
486809Srrh #endif
496809Srrh #ifdef V7UNIX
506809Srrh #define	ARGVLEN	5120
516809Srrh #define	ENVLEN	1000
526809Srrh #endif
536809Srrh char	argvs[ARGVLEN+ENVLEN];
546809Srrh int	args[MAXSARGS];
5514311Ssam 
566809Srrh /* 32v type stat structure */
576809Srrh extern struct	stat	stat32v;
5814311Ssam 
596809Srrh /* place for times data so we can reverse the longs */
606809Srrh struct timebuf {
616809Srrh 	long	t1;
626809Srrh 	long	t2;
636809Srrh 	long	t3;
646809Srrh 	long	t4;
656809Srrh } timebuf;
6614311Ssam 
676809Srrh /* place for pipe file descriptors */
686809Srrh int	pipes[2];
6914311Ssam 
706809Srrh /* wait status */
716809Srrh int	wstatus;
7214311Ssam 
736809Srrh #ifdef	V6UNIX
746809Srrh /* version 6 style stat structure */
756809Srrh struct v6nod {
766809Srrh 	dev_t	majmin;
776809Srrh 	ino_t	inumber;
786809Srrh 	unsigned short	flags;
796809Srrh 	unsigned char	nlinks;
806809Srrh 	unsigned char	uid;
816809Srrh 	unsigned char	gid;
826809Srrh 	unsigned char	size0;
836809Srrh 	unsigned short	size1;
846809Srrh 	unsigned short	addr[8];
856809Srrh 	long	actime;
866809Srrh 	long	modtime;
876809Srrh } *v6stat;
886809Srrh #endif
8914311Ssam 
9014311Ssam #ifdef	V7UNIX
9114311Ssam /* version 7 style stat structure */
9214311Ssam struct	v7stat {
9314311Ssam 	dev_t	v7st_dev;
9414311Ssam 	u_short	v7st_ino;
9514311Ssam 	u_short v7st_mode;
9614311Ssam 	short  	v7st_nlink;
9714311Ssam 	short  	v7st_uid;
9814311Ssam 	short  	v7st_gid;
9914311Ssam 	dev_t	v7st_rdev;
10014311Ssam 	int	v7st_size;
10114311Ssam 	int	v7st_atime;
10214311Ssam 	int	v7st_mtime;
10314311Ssam 	int	v7st_ctime;
10414311Ssam } statv7;
10514311Ssam 
10614311Ssam struct timeb {
10714311Ssam 	time_t	time;
10814311Ssam 	u_short	millitm;
10914311Ssam 	short	timezone;
11014311Ssam 	short	dstflag;
11114311Ssam } timeb;
11214311Ssam #endif
11314311Ssam 
11416442Smckusick #define	NFILES	20
11516442Smckusick #define	ODSIZE	16
11616442Smckusick 
11716442Smckusick off_t	olseek();
118*35698Sbostic long	longrev();
11916442Smckusick 
12016442Smckusick struct odirect {
12116442Smckusick 	u_short	od_ino;
12216442Smckusick 	char	od_name[14];
12316442Smckusick };
12416442Smckusick 
12516442Smckusick struct fdflags {
12616442Smckusick 	DIR	*fd_dirp;
12716442Smckusick 	struct odirect	fd_od;
12816442Smckusick 	off_t	fd_offset;
12916442Smckusick } fdflags[NFILES];
13016442Smckusick 
1316809Srrh /* do the trap stuff for the trap with code */
dotrap(code)13214311Ssam dotrap(code)
13314311Ssam 	int code;
13414311Ssam {
1356809Srrh 	register unsigned short *argp, *savp, *savep;
1366809Srrh 	register int i, j, indirflg;
1376809Srrh 	register char *avp, *oavp;
1386809Srrh 	extern sigcatch();
1396809Srrh 	extern errno;
14016442Smckusick 	extern int sigtrapped;
14116442Smckusick 	DIR *dp;
14214311Ssam 
14316442Smckusick 	sigtrapped = 0;
1446809Srrh 	/* clear out condition codes of psl */
1456809Srrh 	psl &= ~017;
1466809Srrh 	/* special case of indirect sys call */
14714311Ssam 	if (code == 0) {
1486809Srrh 		/* remember this was indirect */
1496809Srrh 		indirflg = 1;
1506809Srrh 		/* point to args */
1516809Srrh 		argp = (unsigned short *)*(pc++);
1526809Srrh 		/* code for indirect sys call */
1536809Srrh 		code = *argp++;
1546809Srrh 		/* is it legit */
15514311Ssam 		if (code>>8 != TRAPS) {
1566809Srrh 			fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
1576809Srrh 			pc++;
1586809Srrh 			/* set carry flag */
1596809Srrh 			psl |= CARRY;
1606809Srrh 			regs[0] = -1;
1616809Srrh 			return(-1);
1626809Srrh 		}
1636809Srrh 		code &= 0377;
16414311Ssam 	} else {
1656809Srrh 		/* remember this was not indirect */
1666809Srrh 		indirflg = 0;
1676809Srrh 		/* point to args */
1686809Srrh 		argp = pc;
1696809Srrh 	}
1706809Srrh 	/* check if code too high or bad sys code */
17114311Ssam 	if (code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
1726809Srrh 		fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
1736809Srrh 		/* set carry bit */
1746809Srrh 		psl |= CARRY;
1756809Srrh 		regs[0] = -1;
1766809Srrh 		return(-1);
1776809Srrh 	}
1786809Srrh 	/* copy args to known locations */
1796809Srrh 	i=0;
18014311Ssam 	for (j=0; j<sysargs[code][0]; j++)
18114311Ssam 		args[i++] = regs[j];
18214311Ssam 	for (j=0; j<(sysargs[code][1]); j++)
18314311Ssam 		args[i++] = *argp++;
1846809Srrh #ifdef TRACE
1856809Srrh 	fprintf(stderr,"pid %d ",getpid());
18614311Ssam 	if (indirflg)
18714311Ssam 		fprintf(stderr,"indirect ");
18814311Ssam 	fprintf(stderr, "%s (%d) from 0%o with %d args",
18914311Ssam 	    sysnames[code], code, pc-1, i);
19014311Ssam 	for (j=0; j<i; j++)
1916809Srrh 		fprintf(stderr," 0%o",args[j]);
19214311Ssam 	if (code==OPEN || code==STAT || code==CREAT || code==EXEC ||
19314311Ssam 	    code==UNLNK || code==LINK || code==CHDIR || code==MKNOD)
1946809Srrh 		fprintf(stderr," (%s)",args[0]);
1956809Srrh #ifdef V7UNIX
19614311Ssam 	if (code==EXECE)
1976809Srrh 		fprintf(stderr," (%s)",args[0]);
1986809Srrh #endif
19914311Ssam 	if (code==LINK)
2006809Srrh 		fprintf(stderr," (%s)",args[1]);
2016809Srrh #endif
2026809Srrh 	/* go do whatever sys call it is */
20314311Ssam 	switch (code) {
20414311Ssam 	case FORK:
2056809Srrh 		/* indirect forks return pids on both sides - must do here */
2066809Srrh 		/* this is possibly a bug in 32V */
2076809Srrh 		i = fork();
2086809Srrh 		break;
20914311Ssam 
21014311Ssam 	case WAIT:
2116809Srrh 		i = wait(&wstatus);
2126809Srrh 		args[0] = i;
2136809Srrh 		args[1] = wstatus;
2146809Srrh 		break;
21514311Ssam 
21614311Ssam 	case EXEC:
2176809Srrh #ifdef V7UNIX
21814311Ssam 	case EXECE:
2196809Srrh #endif
2206809Srrh 		/*
2216809Srrh 		 *  have to do a lot of junk here to fix up an argv
2226809Srrh 		 *  for execute since (1) the pdp-11 argv consists of 16
2236809Srrh 		 *  bit pointers and (2) the argv itself is in the
2246809Srrh 		 *  pdp-11 program space where it would get clobbered
2256809Srrh 		 *  when a new program is read in and before its
2266809Srrh 		 *  argv is set up.
2276809Srrh 		 */
2286809Srrh 		avp = &argvs[0];
2296809Srrh 		savp = (unsigned short *)args[1];
2306809Srrh #ifdef	V6UNIX
23114311Ssam 		for (i=1; args[i] = *savp++; i++)
23214311Ssam 			if (args[i] == 0177777)
23314311Ssam 				break;
2346809Srrh #ifdef	TRACE
23514311Ssam 			else
23614311Ssam 				fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
2376809Srrh #endif
2386809Srrh #endif
2396809Srrh #ifdef	V7UNIX
2406809Srrh 		savep = (unsigned short *)args[2];
24114311Ssam 		for (i=1; args[i] = *savp++; i++)
2426809Srrh #ifdef	TRACE
2436809Srrh 			fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
2446809Srrh #else
2456809Srrh 			;
2466809Srrh #endif
2476809Srrh #endif
24814311Ssam 		if (stat(args[0], &stat32v)) {
2496809Srrh 			/* return error here if file does not exist */
2506809Srrh #ifdef	TRACE
2516809Srrh 			fprintf(stderr," does not exist\n");
2526809Srrh #endif
2536809Srrh 			i = -1;
2546809Srrh 			break;
2556809Srrh 		}
2566809Srrh 		/* must have execute permission */
25714311Ssam 		if (stat32v.st_mode & (S_IEXEC>>6))
25814311Ssam 			goto experm;
25914311Ssam 		if (stat32v.st_mode & (S_IEXEC>>3)) {
26014311Ssam 			if (stat32v.st_gid == getegid())
26114311Ssam 				goto experm;
26214311Ssam 			if (geteuid() == 0)
26314311Ssam 				goto experm;
2646809Srrh 		}
26514311Ssam 		if (stat32v.st_mode & S_IEXEC) {
26614311Ssam 			if (stat32v.st_uid == geteuid())
26714311Ssam 				goto experm;
26814311Ssam 			if (geteuid() == 0)
26914311Ssam 				goto experm;
2706809Srrh 		}
2716809Srrh 		/* return failure if no exec permision allowed */
2726809Srrh 		i = -1;
2736809Srrh experm:
2746809Srrh 		/* can't exec a directory */
27514311Ssam 		if ((stat32v.st_mode&S_IFMT) == S_IFDIR)
2766809Srrh 			i = -1;
27714311Ssam 		if (i == -1)
27814311Ssam 			break;
2796809Srrh 		args[i] = 0;
28016442Smckusick 		for (j=1; j<i; j++) {
2816809Srrh 			oavp = (char *)args[j];
2826809Srrh 			args[j] = (int)avp;
28314311Ssam 			while (*avp++ = *oavp++)
28414311Ssam 				;
2856809Srrh 		}
2866809Srrh #ifdef V7UNIX
28714311Ssam 		if (code == EXECE) {
28814311Ssam 			for (j = ++i; args[j] = *savep++; j++)
28914311Ssam 				;
29016442Smckusick 			for (j = i; oavp = (char *)args[j]; j++) {
2916809Srrh 				args[j] = (int)avp;
29214311Ssam 				while (*avp++ = *oavp++)
29314311Ssam 					;
2946809Srrh 			}
2956809Srrh 		}
2966809Srrh #endif
2976809Srrh 		/* SETUID and SETGID files must be started with a fresh RTS */
29814311Ssam 		if (stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
2996809Srrh 			/* should add a check here for good magic # in header */
3006809Srrh 			args[1] = args[0];
3016809Srrh 			args[0] = (int)RTSNAME;
3026809Srrh #ifdef TRACE
3036809Srrh 			fprintf(stderr," SETUID-GID");
3046809Srrh #endif
30514311Ssam 			if (args[i])
3066809Srrh 				i = execve(args[0], &args[0], &args[i]);
3076809Srrh 			else
3086809Srrh 				i = execv(args[0], &args[0]);
3096809Srrh 			fprintf(stderr,"can't exec %s\n",RTSNAME);
3106809Srrh 			break;
3116809Srrh 		}
3126809Srrh 		i = execute(args[0], &args[1], &args[i]);
3136809Srrh 		/* shouldn't get here if exec works */
3146809Srrh 		break;
31514311Ssam 
31614311Ssam 	case SEEK:
3176809Srrh #ifdef	V6UNIX
3186809Srrh 		/* fix up negative offsets */
31914311Ssam 		if (args[2] != 0 && args[2] != 3)
32014311Ssam 			if (args[1] >= 32768)
32114311Ssam 				args[1] -= 65536;
32214311Ssam 		if (args[2] <= 2)
32316442Smckusick 			i = olseek(args[0], args[1], args[2]);
3246809Srrh 		else
32516442Smckusick 			i = olseek(args[0], args[1]*512, args[2]-3);
32614311Ssam 		if (i != -1)
32714311Ssam 			i = 0;
3286809Srrh #endif
3296809Srrh #ifdef	V7UNIX
33016442Smckusick 		i = olseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
3316809Srrh #endif
3326809Srrh 		break;
33314311Ssam 
33416442Smckusick 	case MKNOD:
33516442Smckusick 		if ((args[1] & S_IFMT) == S_IFDIR)
33616442Smckusick 			i = mkdir(args[0], args[1] & 0777);
33716442Smckusick 		else {
3386809Srrh #ifdef	V6UNIX
33916442Smckusick 			/*
34016442Smckusick 			 * version 6 uses allocated bit which
34116442Smckusick 			 * means regular file here
34216442Smckusick 			 */
34316442Smckusick 			if (args[1] & S_IFBLK)
34416442Smckusick 				args[1] &= ~S_IFREG;
34516442Smckusick #endif
34616442Smckusick 			i = mknod(args[0], args[1], args[2]);
34716442Smckusick 		}
3486809Srrh 		break;
34914311Ssam 
35014311Ssam 	case PIPE:
3516809Srrh 		i = pipe(pipes);
3526809Srrh 		args[0] = pipes[0];
3536809Srrh 		args[1] = pipes[1];
3546809Srrh 		break;
35514311Ssam 
3566809Srrh #ifdef	V6UNIX
35714311Ssam 	case TELL:
3586809Srrh 		i = lseek(args[0], 0L, 1);
3596809Srrh 		break;
36014311Ssam 
36114311Ssam 	case STTY:
36214311Ssam 		i = stty(args[0], args[1]);
36314311Ssam 		break;
36414311Ssam 
36514311Ssam 	case GTTY:
36614311Ssam 		i = gtty(args[0], args[1]);
36714311Ssam 		break;
3686809Srrh #endif
36914311Ssam 
37016442Smckusick 	/* HAVE TO FAKE THE SIZE OF DIRECTORIES */
37116442Smckusick 
37214311Ssam 	case STAT:
37314311Ssam 		i = stat(args[0], &stat32v);
37414311Ssam 		goto allstat;
37514311Ssam 
37614311Ssam 	case FSTAT:
3776809Srrh 		/* do the syscall to a local stat buffer */
37814311Ssam 		i = fstat(args[0], &stat32v);
37914311Ssam 
38014311Ssam 	allstat:
3816809Srrh 		/* reverse the longs */
3826809Srrh 		stat32v.st_size = longrev(stat32v.st_size);
3836809Srrh 		stat32v.st_atime = longrev(stat32v.st_atime);
3846809Srrh 		stat32v.st_mtime = longrev(stat32v.st_mtime);
3856809Srrh 		stat32v.st_ctime = longrev(stat32v.st_ctime);
3866809Srrh #ifdef V7UNIX
38714311Ssam 		statv7.v7st_dev = stat32v.st_dev;
38814311Ssam 		statv7.v7st_ino = stat32v.st_ino;
38914311Ssam 		statv7.v7st_mode = stat32v.st_mode;
39014311Ssam 		statv7.v7st_nlink = stat32v.st_nlink;
39114311Ssam 		statv7.v7st_uid = stat32v.st_uid;
39214311Ssam 		statv7.v7st_gid = stat32v.st_gid;
39314311Ssam 		statv7.v7st_rdev = stat32v.st_rdev;
39414311Ssam 		statv7.v7st_size = stat32v.st_size;
39514311Ssam 		statv7.v7st_atime = stat32v.st_atime;
39614311Ssam 		statv7.v7st_mtime = stat32v.st_mtime;
39714311Ssam 		statv7.v7st_ctime = stat32v.st_ctime;
3986809Srrh 		/* copy out otherwise unchanged stat buffer */
3996809Srrh 		/* in two pieces with st_size as the breaking point */
4006809Srrh 		/* note that st_rdev is a short but due to alingnmemt */
4016809Srrh 		/* problems the rest of the structure is out of sync */
40214311Ssam 		j = (int)((char *)(&statv7.v7st_size) -
40314311Ssam 		    (char *)(&statv7.v7st_dev));
40414311Ssam 		bcopy(&statv7, args[1], j);
40514311Ssam 		bcopy(&statv7.v7st_size, args[1]+j-2, sizeof(struct v7stat)-j);
4066809Srrh #endif
4076809Srrh #ifdef	V6UNIX
4086809Srrh 		/* point to user area as v6stat structure */
4096809Srrh 		v6stat = (struct v6nod *)args[1];
4106809Srrh 		/* copy out piece by piece */
4116809Srrh 		v6stat->majmin = stat32v.st_dev;
4126809Srrh 		v6stat->inumber = stat32v.st_ino;
4136809Srrh 		v6stat->flags = stat32v.st_mode;
4146809Srrh 		v6stat->nlinks = (unsigned char)stat32v.st_nlink;
4156809Srrh 		v6stat->uid = (unsigned char)stat32v.st_uid;
4166809Srrh 		v6stat->gid = (unsigned char)stat32v.st_gid;
4176809Srrh 		/* note size already reversed */
4186809Srrh 		v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
4196809Srrh 		v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
4206809Srrh 		v6stat->actime = stat32v.st_atime;
4216809Srrh 		v6stat->modtime = stat32v.st_mtime;
4226809Srrh 		/* patch up flags */
4236809Srrh 		/* for now just set 100000 bit if not a plain file */
42414311Ssam 		if (v6stat->flags & 060000)
4256809Srrh 			v6stat->flags |= 0100000;
4266809Srrh #endif
4276809Srrh 		break;
42814311Ssam 
42914311Ssam 	case TIMES:
4306809Srrh 		i = times(&timebuf);
4316809Srrh 		timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
4326809Srrh 		timebuf.t3 = longrev(timebuf.t3);
4336809Srrh 		timebuf.t4 = longrev(timebuf.t4);
4346809Srrh 		bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
4356809Srrh 		break;
43614311Ssam 
4376809Srrh #ifdef	V6UNIX
43814311Ssam 	case SLEEP:
4396809Srrh 		/* do a sleep function - what about pwb which has alarm? */
4406809Srrh 		sleep(args[0]);
4416809Srrh 		break;
4426809Srrh #endif
44314311Ssam 
44414311Ssam 	case GETUID:
4456809Srrh 		args[0] = getuid();
4466809Srrh 		args[1] = geteuid();
4476809Srrh #ifdef V6UNIX
44814311Ssam 		i = args[1]<<8 | (args[0] & 0377);
4496809Srrh #endif
4506809Srrh 		break;
45114311Ssam 
45214311Ssam 	case GETGID:
4536809Srrh 		args[0] = getgid();
4546809Srrh 		args[1] = getegid();
4556809Srrh #ifdef V6UNIX
45614311Ssam 		i = args[1]<<8 | (args[0] & 0377);
4576809Srrh #endif
4586809Srrh 		break;
45914311Ssam 
46014311Ssam 		/* uids and gids are 8 bits in version 6 */
46114311Ssam 	case SETUID:
46214311Ssam 	case SETGID:
4636809Srrh #ifdef V6UNIX
46414311Ssam 		args[0] &= 0377;
46514311Ssam #endif
46614311Ssam 		if (code == SETUID)
46714311Ssam 			i = setuid(args[0]);
46814311Ssam 		else
46914311Ssam 			i = setgid(args[0]);
4706809Srrh 		break;
47114311Ssam 
47214311Ssam 	case SIG:
4736809Srrh 		/* if it is a good signal code */
47414311Ssam 		if (args[0] <= NSIG) {
4756809Srrh 			/* get the current signal value */
4766809Srrh 			i = sigvals[args[0]];
4776809Srrh 			/* reset the signal to the new value */
4786809Srrh 			sigvals[args[0]] = args[1];
4796809Srrh 			/* actually do signal except don't reset SIGILL */
48014311Ssam 			if (args[0] != SIGILL) {
48114311Ssam 				if (args[1] == (int)SIG_DFL ||
48214311Ssam 				    args[1] & (int)SIG_IGN) {
48314311Ssam 					if ((int)signal(args[0],args[1]) == -1)
4846809Srrh 						i = -1;
4856809Srrh 				} else {
48614311Ssam 					if ((int)signal(args[0],sigcatch) == -1)
4876809Srrh 						i = -1;
4886809Srrh 				}
4896809Srrh 			}
49014311Ssam 		} else
49114311Ssam 			i = -1;
4926809Srrh 		break;
49314311Ssam 
49414311Ssam 	case BRK:
4956809Srrh 		/* brk is successful unless we run over the stack */
49614311Ssam 		/* NB: this assumes register usage which need not be used */
4976809Srrh 		i = 0;
49814311Ssam 		if (args[0] >= regs[6])
49914311Ssam 			i = -1;
5006809Srrh 		break;
50114311Ssam 
50214311Ssam 	/*
50314311Ssam 	 * the next bunch are to cope with sys calls removed from 4.2
50414311Ssam 	 */
50514311Ssam 	case TIME:
50614311Ssam 		i = time(0);
50714311Ssam 		break;
50814311Ssam 
50914311Ssam 	case STIME: {
51014311Ssam 		struct timeval tv;
51114311Ssam 
51214311Ssam 		tv.tv_usec = 0;
51314311Ssam 		tv.tv_sec = (args[0] & 0xffff) | ((args[1] & 0xffff) << 16);
51414311Ssam 		i = settimeofday(&tv);
51514311Ssam 		break;
51614311Ssam 	}
51714311Ssam 
51814311Ssam 	case NICE:
51914311Ssam 		i = nice(args[0]);
52014311Ssam 		break;
52114311Ssam 
52214311Ssam #ifdef V7UNIX
52314311Ssam 	case ALARM:
52414311Ssam 		i = alarm(args[0]);
52514311Ssam 		break;
52614311Ssam 
52714311Ssam 	case PAUSE:
52814311Ssam 		i = pause();
52914311Ssam 		break;
53014311Ssam 
53114311Ssam 	case UTIME:
53214311Ssam 		i = utime(args[0], args[1]);
53314311Ssam 		break;
53414311Ssam 
53514311Ssam 	case FTIME:
53614311Ssam 		i = ftime(&timeb);
53714311Ssam 		timeb.time = longrev(timeb.time);
53814311Ssam 		bcopy(&timeb, args[0], sizeof timeb - 2);
53914311Ssam 		break;
54014311Ssam 
54114311Ssam 	case IOCTL:
54214311Ssam 		args[1] = mapioctl(args[1]);
54314311Ssam 		if (args[1] == 0)
54414311Ssam 			i = -1;
54514311Ssam 		else
54614311Ssam 			i = ioctl(args[0], args[1], args[2]);
54714311Ssam 		break;
54814311Ssam #endif
54914311Ssam 
5506809Srrh #ifdef	V6UNIX
55114311Ssam 	case PWBSYS:
5526809Srrh 		/* ignore pwbsys for now */
55314311Ssam 		switch (args[2]) {
55414311Ssam 		case UNAME:
5556809Srrh #ifdef	TRACE
5566809Srrh 			fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
5576809Srrh #endif
5586809Srrh 			strcpy(args[0],"pwbname");
5596809Srrh 			i = 0;
5606809Srrh 			break;
56114311Ssam 
56214311Ssam 		case UDATA:
5636809Srrh #ifdef	TRACE
5646809Srrh 			fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
5656809Srrh #endif
5666809Srrh 			i = 0;
5676809Srrh 			break;
56814311Ssam 
56914311Ssam 		case USTAT:
5706809Srrh fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
5716809Srrh 			i = 0;
5726809Srrh 			break;
57314311Ssam 
57414311Ssam 		case UTIME:
5756809Srrh fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
5766809Srrh 			i = 0;
5776809Srrh 			break;
5786809Srrh 		default:
5796809Srrh fprintf(stderr,"bad PWBSYS %d\n",args[3]);
5806809Srrh 			i = -1;
5816809Srrh 			break;
5826809Srrh 		}
5836809Srrh 		break;
5846809Srrh #endif
58514311Ssam 
5866809Srrh 	default:
5876809Srrh 		/*
5886809Srrh 		 *	Many sys calls are easily done here since most
5896809Srrh 		 *	system call codes are the same on version 6 and 7 UNIX
5906809Srrh 		 *	as they are here.
5916809Srrh 		 */
5926809Srrh 		i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
5936809Srrh #ifdef V6UNIX
59414311Ssam 		/* allow read write access to created files for (IDIS v6 mod) */
59514311Ssam 		if (code==CREAT) {
5966809Srrh 			/* get actual file mode after create */
5976809Srrh 			fstat(i, &stat32v);
5986809Srrh 			close(i);
5996809Srrh 			/* ensure read/write access to owner */
6006809Srrh 			chmod(args[0], 0644);
6016809Srrh 			i = open(args[0], 2);
6026809Srrh 			/* change mode back the way it was */
6036809Srrh 			chmod(args[0], stat32v.st_mode);
6046809Srrh 		}
6056809Srrh #endif
6066809Srrh 		break;
60716442Smckusick 	case OPEN:
60816442Smckusick 		/*
60916442Smckusick 		 * check if we are opening a directory
61016442Smckusick 		 */
61116442Smckusick 		if (stat(args[0], &stat32v) >= 0  &&
61216442Smckusick 		    ((stat32v.st_mode & S_IFMT) == S_IFDIR) &&
61316442Smckusick 		    ((dp = opendir(args[0])) != NULL)) {
61416442Smckusick #ifdef DTRACE
61516442Smckusick 			fprintf(stderr,"open directory fd %d\n", i);
61616442Smckusick #endif
61716442Smckusick 			i = dp->dd_fd;
61816442Smckusick 			fdflags[i].fd_dirp = dp;
61916442Smckusick 			fdflags[i].fd_offset = 0;
62016442Smckusick 		} else
62116442Smckusick 			i = open(args[0], args[1]);
62216442Smckusick 		break;
62316442Smckusick 	case CLOSE:
62416442Smckusick 		i = close(args[0]);
62516442Smckusick 		if (i >= 0 && fdflags[args[0]].fd_dirp) {
62616442Smckusick 			closedir(fdflags[args[0]].fd_dirp);
62716442Smckusick 			fdflags[args[0]].fd_dirp = 0;
62816442Smckusick 		}
62916442Smckusick 		break;
63016442Smckusick 	case READ:
63116442Smckusick 		if ((unsigned)args[0] < NFILES && fdflags[args[0]].fd_dirp)
63216442Smckusick 			i = oread(args[0], args[1], args[2]);
63316442Smckusick 		else
63416442Smckusick 			i = read(args[0], args[1], args[2]);
63516442Smckusick 		break;
6366809Srrh 	}
6376809Srrh #ifdef TRACE
6386809Srrh 	fprintf(stderr," sys val -> 0%o\n",i);
6396809Srrh #endif
6406809Srrh 	/* set carry bit if sys error */
64114311Ssam 	if (i == -1)
6426809Srrh 		psl |= CARRY;
6436809Srrh 	/* if not an indirect sys call, adjust the pc */
64416442Smckusick 	if (!indirflg && !sigtrapped)
6456809Srrh 		pc = argp;
6466809Srrh 	/* do alternate return on one side of fork */
64714311Ssam 	if (code == FORK && i != 0)
6486809Srrh 		pc++;
6496809Srrh 	/* do the various return value formats */
65014311Ssam 	switch (sysargs[code][2]) {
65114311Ssam 	case NORMRET:
6526809Srrh 		/* normal case only one return value in r0 */
6536809Srrh 		regs[0] = i;
6546809Srrh 		break;
65514311Ssam 	case LONGRET:
6566809Srrh 		/* return a long in r0 - r1 as in time */
6576809Srrh 		regs[1] = i;
6586809Srrh 		regs[0] = i >> 16;
6596809Srrh 		break;
66014311Ssam 	case TWORET:
6616809Srrh 		/* return two ints in r0 - r1 as in pipe */
66214311Ssam 		if (i == -1)
6636809Srrh 			regs[0] = i;
6646809Srrh 		else {
6656809Srrh 			regs[1] = args[1];
6666809Srrh 			regs[0] = args[0];
6676809Srrh 		}
6686809Srrh 		break;
6696809Srrh 	}
67014311Ssam 	if (i== -1)
6716809Srrh 		regs[0] = errno;
6726809Srrh }
67314311Ssam 
67414311Ssam long
longrev(l)67514311Ssam longrev(l)
67614311Ssam 	long l;
67714311Ssam {
6786809Srrh 	/* function to reverse the halves of a long */
6796809Srrh 	union {
6806809Srrh 		long	lng;
6816809Srrh 		short	s[2];
6826809Srrh 	} u;
6836809Srrh 	register short t;
6846809Srrh 	u.lng = l;
6856809Srrh 	t = u.s[0];
6866809Srrh 	u.s[0] = u.s[1];
6876809Srrh 	u.s[1] = t;
6886809Srrh 	return(u.lng);
6896809Srrh }
69014311Ssam 
69114311Ssam /*
69214311Ssam  * Note: these tables are sorted by
69314311Ssam  * ioctl "code" (in ascending order).
69414311Ssam  */
69514311Ssam int fctls[] = { FIOCLEX, FIONCLEX, FIOASYNC, FIONBIO, FIONREAD, 0 };
69614311Ssam int tctls[] = {
69714311Ssam 	TIOCGETD, TIOCSETD, TIOCHPCL, TIOCMODG, TIOCMODS,
69814311Ssam 	TIOCGETP, TIOCSETP, TIOCSETN, TIOCEXCL, TIOCNXCL,
69914311Ssam 	TIOCFLUSH,TIOCSETC, TIOCGETC, TIOCREMOTE,TIOCMGET,
70014311Ssam 	TIOCMBIC, TIOCMBIS, TIOCMSET, TIOCSTART,TIOCSTOP,
70114311Ssam 	TIOCPKT,  TIOCNOTTY,TIOCSTI,  TIOCOUTQ, TIOCGLTC,
70214311Ssam 	TIOCSLTC, TIOCSPGRP,TIOCGPGRP,TIOCCDTR, TIOCSDTR,
70314311Ssam 	TIOCCBRK, TIOCSBRK, TIOCLGET, TIOCLSET, TIOCLBIC,
70414311Ssam 	TIOCLBIS, 0
70514311Ssam };
70614311Ssam 
70714311Ssam /*
70814311Ssam  * Map an old style ioctl command to new.
70914311Ssam  */
mapioctl(cmd)71014311Ssam mapioctl(cmd)
71114311Ssam 	int cmd;
71214311Ssam {
71314311Ssam 	register int *map, c;
71414311Ssam 
71514311Ssam 	switch ((cmd >> 8) & 0xff) {
71614311Ssam 
71714311Ssam 	case 'f':
71814311Ssam 		map = fctls;
71914311Ssam 		break;
72014311Ssam 
72114311Ssam 	case 't':
72214311Ssam 		map = tctls;
72314311Ssam 		break;
72414311Ssam 
72514311Ssam 	default:
72614311Ssam 		return (0);
72714311Ssam 	}
72814311Ssam 	while ((c = *map) && (c&0xff) < (cmd&0xff))
72914311Ssam 		map++;
73014311Ssam 	if (c && (c&0xff) == (cmd&0xff))
73114311Ssam 		return (c);
73214311Ssam 	return (0);
73314311Ssam }
73416442Smckusick 
73516442Smckusick /*
73616442Smckusick  * emulate a read of n bytes on an old style directory
73716442Smckusick  */
oread(fd,buf,count)73816442Smckusick oread(fd, buf, count)
73916442Smckusick int fd, count;
74016442Smckusick char *buf;
74116442Smckusick {
74216442Smckusick 	struct fdflags *fp;
74316442Smckusick 	struct direct *dp;
74416442Smckusick 	DIR *dirp;
74516442Smckusick 	struct odirect *odp;
74616442Smckusick 	register int nleft = count;
74716442Smckusick 	int dir_off;
74816442Smckusick 	int i;
74916442Smckusick 
75016442Smckusick 	fp = &fdflags[fd];
75116442Smckusick 	dirp = fp->fd_dirp;
75216442Smckusick 	odp = &fp->fd_od;
75316442Smckusick 	if (dirp == NULL)
75416442Smckusick 		return(-1);
75516442Smckusick 	dir_off = fp->fd_offset % ODSIZE;
75616442Smckusick 	if (dir_off) {
75716442Smckusick 		i = ODSIZE - dir_off;
75816442Smckusick 		if (nleft < i)
75916442Smckusick 			i = nleft;
76016442Smckusick 		bcopy((caddr_t)odp + dir_off, buf, i);
76116442Smckusick 		fp->fd_offset += i;
76216442Smckusick 		if (i == nleft)
76316442Smckusick 			return(i);
76416442Smckusick 		buf += i;
76516442Smckusick 		nleft -= i;
76616442Smckusick 	}
76716442Smckusick 	while (nleft >= ODSIZE) {
76816442Smckusick 		if ((dp = readdir(dirp)) == NULL)
76916442Smckusick 			return(count - nleft);
77016442Smckusick 		odp->od_ino = dp->d_ino;
77116442Smckusick 		strncpy(odp->od_name, dp->d_name, 14);
77216442Smckusick 		bcopy((caddr_t)odp, buf, ODSIZE);
77316442Smckusick 		fp->fd_offset += ODSIZE;
77416442Smckusick 		buf += ODSIZE;
77516442Smckusick 		nleft -= ODSIZE;
77616442Smckusick 	}
77716442Smckusick 	if (nleft > 0) {
77816442Smckusick 		if ((dp = readdir(dirp)) == NULL)
77916442Smckusick 			return(count - nleft);
78016442Smckusick 		odp->od_ino = dp->d_ino;
78116442Smckusick 		strncpy(odp->od_name, dp->d_name, 14);
78216442Smckusick 		bcopy((caddr_t)odp, buf, nleft);
78316442Smckusick 		fp->fd_offset += nleft;
78416442Smckusick 		/* nleft = 0; */
78516442Smckusick 	}
78616442Smckusick 	return(count);
78716442Smckusick }
78816442Smckusick 
78916442Smckusick /*
79016442Smckusick  * emulate the lseek system call
79116442Smckusick  */
79216442Smckusick off_t
olseek(fd,n,whence)79316442Smckusick olseek(fd, n, whence)
79416442Smckusick int fd, whence;
79516442Smckusick off_t n;
79616442Smckusick {
79716442Smckusick 	struct fdflags *fp;
79816442Smckusick 	char buf[512];
79916442Smckusick 	off_t newpos;
80016442Smckusick 	int i, j;
80116442Smckusick 
80216442Smckusick 	if ((unsigned)fd >= NFILES)
80316442Smckusick 		return(-1);
80416442Smckusick 	fp = &fdflags[fd];
80516442Smckusick 	/*
80616442Smckusick 	 * the system can handle everything
80716442Smckusick 	 * except directory files
80816442Smckusick 	 */
80916442Smckusick 	if (fp->fd_dirp == NULL)
81016442Smckusick 		return(lseek(fd, n, whence));
81116442Smckusick 	switch (whence) {
81216442Smckusick 	case 0:
81316442Smckusick 		newpos = n;
81416442Smckusick 		break;
81516442Smckusick 	case 1:
81616442Smckusick 		newpos = fp->fd_offset + n;
81716442Smckusick 		break;
81816442Smckusick 	case 2:		/* not yet implemented */
81916442Smckusick 	default:
82016442Smckusick 		return(-1);
82116442Smckusick 	}
82216442Smckusick 	if (newpos < 0)
82316442Smckusick 		return(-1);
82416442Smckusick 	if (newpos < fp->fd_offset) {
82516442Smckusick 		rewinddir(fdflags[fd].fd_dirp);
82616442Smckusick 		fp->fd_offset = 0;
82716442Smckusick 	}
82816442Smckusick 	i = newpos - fp->fd_offset;
82916442Smckusick 	while (i > 0) {
83016442Smckusick 		j = i < 512 ? i : 512;
83116442Smckusick 		if (oread(fd, buf, j) != j)
83216442Smckusick 			break;
83316442Smckusick 		i -= j;
83416442Smckusick 	}
83516442Smckusick 	return(fp->fd_offset);
83616442Smckusick }
837