1*16442Smckusick #ifndef	lint
2*16442Smckusick static char sccsid[] = "@(#)unixtraps.c	4.3 84/05/05";
3*16442Smckusick #endif
414311Ssam 
5*16442Smckusick /* From Lou Salkind: compat/RCS/unixtraps.c,v 1.2 84/01/31 13:34:34 */
6*16442Smckusick 
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>
19*16442Smckusick #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
44*16442Smckusick #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 
114*16442Smckusick #define	NFILES	20
115*16442Smckusick #define	ODSIZE	16
116*16442Smckusick 
117*16442Smckusick off_t	olseek();
118*16442Smckusick 
119*16442Smckusick struct odirect {
120*16442Smckusick 	u_short	od_ino;
121*16442Smckusick 	char	od_name[14];
122*16442Smckusick };
123*16442Smckusick 
124*16442Smckusick struct fdflags {
125*16442Smckusick 	DIR	*fd_dirp;
126*16442Smckusick 	struct odirect	fd_od;
127*16442Smckusick 	off_t	fd_offset;
128*16442Smckusick } fdflags[NFILES];
129*16442Smckusick 
1306809Srrh /* do the trap stuff for the trap with code */
13114311Ssam dotrap(code)
13214311Ssam 	int code;
13314311Ssam {
1346809Srrh 	register unsigned short *argp, *savp, *savep;
1356809Srrh 	register int i, j, indirflg;
1366809Srrh 	register char *avp, *oavp;
1376809Srrh 	extern sigcatch();
1386809Srrh 	extern errno;
139*16442Smckusick 	extern int sigtrapped;
140*16442Smckusick 	DIR *dp;
14114311Ssam 
142*16442Smckusick 	sigtrapped = 0;
1436809Srrh 	/* clear out condition codes of psl */
1446809Srrh 	psl &= ~017;
1456809Srrh 	/* special case of indirect sys call */
14614311Ssam 	if (code == 0) {
1476809Srrh 		/* remember this was indirect */
1486809Srrh 		indirflg = 1;
1496809Srrh 		/* point to args */
1506809Srrh 		argp = (unsigned short *)*(pc++);
1516809Srrh 		/* code for indirect sys call */
1526809Srrh 		code = *argp++;
1536809Srrh 		/* is it legit */
15414311Ssam 		if (code>>8 != TRAPS) {
1556809Srrh 			fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
1566809Srrh 			pc++;
1576809Srrh 			/* set carry flag */
1586809Srrh 			psl |= CARRY;
1596809Srrh 			regs[0] = -1;
1606809Srrh 			return(-1);
1616809Srrh 		}
1626809Srrh 		code &= 0377;
16314311Ssam 	} else {
1646809Srrh 		/* remember this was not indirect */
1656809Srrh 		indirflg = 0;
1666809Srrh 		/* point to args */
1676809Srrh 		argp = pc;
1686809Srrh 	}
1696809Srrh 	/* check if code too high or bad sys code */
17014311Ssam 	if (code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
1716809Srrh 		fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
1726809Srrh 		/* set carry bit */
1736809Srrh 		psl |= CARRY;
1746809Srrh 		regs[0] = -1;
1756809Srrh 		return(-1);
1766809Srrh 	}
1776809Srrh 	/* copy args to known locations */
1786809Srrh 	i=0;
17914311Ssam 	for (j=0; j<sysargs[code][0]; j++)
18014311Ssam 		args[i++] = regs[j];
18114311Ssam 	for (j=0; j<(sysargs[code][1]); j++)
18214311Ssam 		args[i++] = *argp++;
1836809Srrh #ifdef TRACE
1846809Srrh 	fprintf(stderr,"pid %d ",getpid());
18514311Ssam 	if (indirflg)
18614311Ssam 		fprintf(stderr,"indirect ");
18714311Ssam 	fprintf(stderr, "%s (%d) from 0%o with %d args",
18814311Ssam 	    sysnames[code], code, pc-1, i);
18914311Ssam 	for (j=0; j<i; j++)
1906809Srrh 		fprintf(stderr," 0%o",args[j]);
19114311Ssam 	if (code==OPEN || code==STAT || code==CREAT || code==EXEC ||
19214311Ssam 	    code==UNLNK || code==LINK || code==CHDIR || code==MKNOD)
1936809Srrh 		fprintf(stderr," (%s)",args[0]);
1946809Srrh #ifdef V7UNIX
19514311Ssam 	if (code==EXECE)
1966809Srrh 		fprintf(stderr," (%s)",args[0]);
1976809Srrh #endif
19814311Ssam 	if (code==LINK)
1996809Srrh 		fprintf(stderr," (%s)",args[1]);
2006809Srrh #endif
2016809Srrh 	/* go do whatever sys call it is */
20214311Ssam 	switch (code) {
20314311Ssam 	case FORK:
2046809Srrh 		/* indirect forks return pids on both sides - must do here */
2056809Srrh 		/* this is possibly a bug in 32V */
2066809Srrh 		i = fork();
2076809Srrh 		break;
20814311Ssam 
20914311Ssam 	case WAIT:
2106809Srrh 		i = wait(&wstatus);
2116809Srrh 		args[0] = i;
2126809Srrh 		args[1] = wstatus;
2136809Srrh 		break;
21414311Ssam 
21514311Ssam 	case EXEC:
2166809Srrh #ifdef V7UNIX
21714311Ssam 	case EXECE:
2186809Srrh #endif
2196809Srrh 		/*
2206809Srrh 		 *  have to do a lot of junk here to fix up an argv
2216809Srrh 		 *  for execute since (1) the pdp-11 argv consists of 16
2226809Srrh 		 *  bit pointers and (2) the argv itself is in the
2236809Srrh 		 *  pdp-11 program space where it would get clobbered
2246809Srrh 		 *  when a new program is read in and before its
2256809Srrh 		 *  argv is set up.
2266809Srrh 		 */
2276809Srrh 		avp = &argvs[0];
2286809Srrh 		savp = (unsigned short *)args[1];
2296809Srrh #ifdef	V6UNIX
23014311Ssam 		for (i=1; args[i] = *savp++; i++)
23114311Ssam 			if (args[i] == 0177777)
23214311Ssam 				break;
2336809Srrh #ifdef	TRACE
23414311Ssam 			else
23514311Ssam 				fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
2366809Srrh #endif
2376809Srrh #endif
2386809Srrh #ifdef	V7UNIX
2396809Srrh 		savep = (unsigned short *)args[2];
24014311Ssam 		for (i=1; args[i] = *savp++; i++)
2416809Srrh #ifdef	TRACE
2426809Srrh 			fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
2436809Srrh #else
2446809Srrh 			;
2456809Srrh #endif
2466809Srrh #endif
24714311Ssam 		if (stat(args[0], &stat32v)) {
2486809Srrh 			/* return error here if file does not exist */
2496809Srrh #ifdef	TRACE
2506809Srrh 			fprintf(stderr," does not exist\n");
2516809Srrh #endif
2526809Srrh 			i = -1;
2536809Srrh 			break;
2546809Srrh 		}
2556809Srrh 		/* must have execute permission */
25614311Ssam 		if (stat32v.st_mode & (S_IEXEC>>6))
25714311Ssam 			goto experm;
25814311Ssam 		if (stat32v.st_mode & (S_IEXEC>>3)) {
25914311Ssam 			if (stat32v.st_gid == getegid())
26014311Ssam 				goto experm;
26114311Ssam 			if (geteuid() == 0)
26214311Ssam 				goto experm;
2636809Srrh 		}
26414311Ssam 		if (stat32v.st_mode & S_IEXEC) {
26514311Ssam 			if (stat32v.st_uid == geteuid())
26614311Ssam 				goto experm;
26714311Ssam 			if (geteuid() == 0)
26814311Ssam 				goto experm;
2696809Srrh 		}
2706809Srrh 		/* return failure if no exec permision allowed */
2716809Srrh 		i = -1;
2726809Srrh experm:
2736809Srrh 		/* can't exec a directory */
27414311Ssam 		if ((stat32v.st_mode&S_IFMT) == S_IFDIR)
2756809Srrh 			i = -1;
27614311Ssam 		if (i == -1)
27714311Ssam 			break;
2786809Srrh 		args[i] = 0;
279*16442Smckusick 		for (j=1; j<i; j++) {
2806809Srrh 			oavp = (char *)args[j];
2816809Srrh 			args[j] = (int)avp;
28214311Ssam 			while (*avp++ = *oavp++)
28314311Ssam 				;
2846809Srrh 		}
2856809Srrh #ifdef V7UNIX
28614311Ssam 		if (code == EXECE) {
28714311Ssam 			for (j = ++i; args[j] = *savep++; j++)
28814311Ssam 				;
289*16442Smckusick 			for (j = i; oavp = (char *)args[j]; j++) {
2906809Srrh 				args[j] = (int)avp;
29114311Ssam 				while (*avp++ = *oavp++)
29214311Ssam 					;
2936809Srrh 			}
2946809Srrh 		}
2956809Srrh #endif
2966809Srrh 		/* SETUID and SETGID files must be started with a fresh RTS */
29714311Ssam 		if (stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
2986809Srrh 			/* should add a check here for good magic # in header */
2996809Srrh 			args[1] = args[0];
3006809Srrh 			args[0] = (int)RTSNAME;
3016809Srrh #ifdef TRACE
3026809Srrh 			fprintf(stderr," SETUID-GID");
3036809Srrh #endif
30414311Ssam 			if (args[i])
3056809Srrh 				i = execve(args[0], &args[0], &args[i]);
3066809Srrh 			else
3076809Srrh 				i = execv(args[0], &args[0]);
3086809Srrh 			fprintf(stderr,"can't exec %s\n",RTSNAME);
3096809Srrh 			break;
3106809Srrh 		}
3116809Srrh 		i = execute(args[0], &args[1], &args[i]);
3126809Srrh 		/* shouldn't get here if exec works */
3136809Srrh 		break;
31414311Ssam 
31514311Ssam 	case SEEK:
3166809Srrh #ifdef	V6UNIX
3176809Srrh 		/* fix up negative offsets */
31814311Ssam 		if (args[2] != 0 && args[2] != 3)
31914311Ssam 			if (args[1] >= 32768)
32014311Ssam 				args[1] -= 65536;
32114311Ssam 		if (args[2] <= 2)
322*16442Smckusick 			i = olseek(args[0], args[1], args[2]);
3236809Srrh 		else
324*16442Smckusick 			i = olseek(args[0], args[1]*512, args[2]-3);
32514311Ssam 		if (i != -1)
32614311Ssam 			i = 0;
3276809Srrh #endif
3286809Srrh #ifdef	V7UNIX
329*16442Smckusick 		i = olseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
3306809Srrh #endif
3316809Srrh 		break;
33214311Ssam 
333*16442Smckusick 	case MKNOD:
334*16442Smckusick 		if ((args[1] & S_IFMT) == S_IFDIR)
335*16442Smckusick 			i = mkdir(args[0], args[1] & 0777);
336*16442Smckusick 		else {
3376809Srrh #ifdef	V6UNIX
338*16442Smckusick 			/*
339*16442Smckusick 			 * version 6 uses allocated bit which
340*16442Smckusick 			 * means regular file here
341*16442Smckusick 			 */
342*16442Smckusick 			if (args[1] & S_IFBLK)
343*16442Smckusick 				args[1] &= ~S_IFREG;
344*16442Smckusick #endif
345*16442Smckusick 			i = mknod(args[0], args[1], args[2]);
346*16442Smckusick 		}
3476809Srrh 		break;
34814311Ssam 
34914311Ssam 	case PIPE:
3506809Srrh 		i = pipe(pipes);
3516809Srrh 		args[0] = pipes[0];
3526809Srrh 		args[1] = pipes[1];
3536809Srrh 		break;
35414311Ssam 
3556809Srrh #ifdef	V6UNIX
35614311Ssam 	case TELL:
3576809Srrh 		i = lseek(args[0], 0L, 1);
3586809Srrh 		break;
35914311Ssam 
36014311Ssam 	case STTY:
36114311Ssam 		i = stty(args[0], args[1]);
36214311Ssam 		break;
36314311Ssam 
36414311Ssam 	case GTTY:
36514311Ssam 		i = gtty(args[0], args[1]);
36614311Ssam 		break;
3676809Srrh #endif
36814311Ssam 
369*16442Smckusick 	/* HAVE TO FAKE THE SIZE OF DIRECTORIES */
370*16442Smckusick 
37114311Ssam 	case STAT:
37214311Ssam 		i = stat(args[0], &stat32v);
37314311Ssam 		goto allstat;
37414311Ssam 
37514311Ssam 	case FSTAT:
3766809Srrh 		/* do the syscall to a local stat buffer */
37714311Ssam 		i = fstat(args[0], &stat32v);
37814311Ssam 
37914311Ssam 	allstat:
3806809Srrh 		/* reverse the longs */
3816809Srrh 		stat32v.st_size = longrev(stat32v.st_size);
3826809Srrh 		stat32v.st_atime = longrev(stat32v.st_atime);
3836809Srrh 		stat32v.st_mtime = longrev(stat32v.st_mtime);
3846809Srrh 		stat32v.st_ctime = longrev(stat32v.st_ctime);
3856809Srrh #ifdef V7UNIX
38614311Ssam 		statv7.v7st_dev = stat32v.st_dev;
38714311Ssam 		statv7.v7st_ino = stat32v.st_ino;
38814311Ssam 		statv7.v7st_mode = stat32v.st_mode;
38914311Ssam 		statv7.v7st_nlink = stat32v.st_nlink;
39014311Ssam 		statv7.v7st_uid = stat32v.st_uid;
39114311Ssam 		statv7.v7st_gid = stat32v.st_gid;
39214311Ssam 		statv7.v7st_rdev = stat32v.st_rdev;
39314311Ssam 		statv7.v7st_size = stat32v.st_size;
39414311Ssam 		statv7.v7st_atime = stat32v.st_atime;
39514311Ssam 		statv7.v7st_mtime = stat32v.st_mtime;
39614311Ssam 		statv7.v7st_ctime = stat32v.st_ctime;
3976809Srrh 		/* copy out otherwise unchanged stat buffer */
3986809Srrh 		/* in two pieces with st_size as the breaking point */
3996809Srrh 		/* note that st_rdev is a short but due to alingnmemt */
4006809Srrh 		/* problems the rest of the structure is out of sync */
40114311Ssam 		j = (int)((char *)(&statv7.v7st_size) -
40214311Ssam 		    (char *)(&statv7.v7st_dev));
40314311Ssam 		bcopy(&statv7, args[1], j);
40414311Ssam 		bcopy(&statv7.v7st_size, args[1]+j-2, sizeof(struct v7stat)-j);
4056809Srrh #endif
4066809Srrh #ifdef	V6UNIX
4076809Srrh 		/* point to user area as v6stat structure */
4086809Srrh 		v6stat = (struct v6nod *)args[1];
4096809Srrh 		/* copy out piece by piece */
4106809Srrh 		v6stat->majmin = stat32v.st_dev;
4116809Srrh 		v6stat->inumber = stat32v.st_ino;
4126809Srrh 		v6stat->flags = stat32v.st_mode;
4136809Srrh 		v6stat->nlinks = (unsigned char)stat32v.st_nlink;
4146809Srrh 		v6stat->uid = (unsigned char)stat32v.st_uid;
4156809Srrh 		v6stat->gid = (unsigned char)stat32v.st_gid;
4166809Srrh 		/* note size already reversed */
4176809Srrh 		v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
4186809Srrh 		v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
4196809Srrh 		v6stat->actime = stat32v.st_atime;
4206809Srrh 		v6stat->modtime = stat32v.st_mtime;
4216809Srrh 		/* patch up flags */
4226809Srrh 		/* for now just set 100000 bit if not a plain file */
42314311Ssam 		if (v6stat->flags & 060000)
4246809Srrh 			v6stat->flags |= 0100000;
4256809Srrh #endif
4266809Srrh 		break;
42714311Ssam 
42814311Ssam 	case TIMES:
4296809Srrh 		i = times(&timebuf);
4306809Srrh 		timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
4316809Srrh 		timebuf.t3 = longrev(timebuf.t3);
4326809Srrh 		timebuf.t4 = longrev(timebuf.t4);
4336809Srrh 		bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
4346809Srrh 		break;
43514311Ssam 
4366809Srrh #ifdef	V6UNIX
43714311Ssam 	case SLEEP:
4386809Srrh 		/* do a sleep function - what about pwb which has alarm? */
4396809Srrh 		sleep(args[0]);
4406809Srrh 		break;
4416809Srrh #endif
44214311Ssam 
44314311Ssam 	case GETUID:
4446809Srrh 		args[0] = getuid();
4456809Srrh 		args[1] = geteuid();
4466809Srrh #ifdef V6UNIX
44714311Ssam 		i = args[1]<<8 | (args[0] & 0377);
4486809Srrh #endif
4496809Srrh 		break;
45014311Ssam 
45114311Ssam 	case GETGID:
4526809Srrh 		args[0] = getgid();
4536809Srrh 		args[1] = getegid();
4546809Srrh #ifdef V6UNIX
45514311Ssam 		i = args[1]<<8 | (args[0] & 0377);
4566809Srrh #endif
4576809Srrh 		break;
45814311Ssam 
45914311Ssam 		/* uids and gids are 8 bits in version 6 */
46014311Ssam 	case SETUID:
46114311Ssam 	case SETGID:
4626809Srrh #ifdef V6UNIX
46314311Ssam 		args[0] &= 0377;
46414311Ssam #endif
46514311Ssam 		if (code == SETUID)
46614311Ssam 			i = setuid(args[0]);
46714311Ssam 		else
46814311Ssam 			i = setgid(args[0]);
4696809Srrh 		break;
47014311Ssam 
47114311Ssam 	case SIG:
4726809Srrh 		/* if it is a good signal code */
47314311Ssam 		if (args[0] <= NSIG) {
4746809Srrh 			/* get the current signal value */
4756809Srrh 			i = sigvals[args[0]];
4766809Srrh 			/* reset the signal to the new value */
4776809Srrh 			sigvals[args[0]] = args[1];
4786809Srrh 			/* actually do signal except don't reset SIGILL */
47914311Ssam 			if (args[0] != SIGILL) {
48014311Ssam 				if (args[1] == (int)SIG_DFL ||
48114311Ssam 				    args[1] & (int)SIG_IGN) {
48214311Ssam 					if ((int)signal(args[0],args[1]) == -1)
4836809Srrh 						i = -1;
4846809Srrh 				} else {
48514311Ssam 					if ((int)signal(args[0],sigcatch) == -1)
4866809Srrh 						i = -1;
4876809Srrh 				}
4886809Srrh 			}
48914311Ssam 		} else
49014311Ssam 			i = -1;
4916809Srrh 		break;
49214311Ssam 
49314311Ssam 	case BRK:
4946809Srrh 		/* brk is successful unless we run over the stack */
49514311Ssam 		/* NB: this assumes register usage which need not be used */
4966809Srrh 		i = 0;
49714311Ssam 		if (args[0] >= regs[6])
49814311Ssam 			i = -1;
4996809Srrh 		break;
50014311Ssam 
50114311Ssam 	/*
50214311Ssam 	 * the next bunch are to cope with sys calls removed from 4.2
50314311Ssam 	 */
50414311Ssam 	case TIME:
50514311Ssam 		i = time(0);
50614311Ssam 		break;
50714311Ssam 
50814311Ssam 	case STIME: {
50914311Ssam 		struct timeval tv;
51014311Ssam 
51114311Ssam 		tv.tv_usec = 0;
51214311Ssam 		tv.tv_sec = (args[0] & 0xffff) | ((args[1] & 0xffff) << 16);
51314311Ssam 		i = settimeofday(&tv);
51414311Ssam 		break;
51514311Ssam 	}
51614311Ssam 
51714311Ssam 	case NICE:
51814311Ssam 		i = nice(args[0]);
51914311Ssam 		break;
52014311Ssam 
52114311Ssam #ifdef V7UNIX
52214311Ssam 	case ALARM:
52314311Ssam 		i = alarm(args[0]);
52414311Ssam 		break;
52514311Ssam 
52614311Ssam 	case PAUSE:
52714311Ssam 		i = pause();
52814311Ssam 		break;
52914311Ssam 
53014311Ssam 	case UTIME:
53114311Ssam 		i = utime(args[0], args[1]);
53214311Ssam 		break;
53314311Ssam 
53414311Ssam 	case FTIME:
53514311Ssam 		i = ftime(&timeb);
53614311Ssam 		timeb.time = longrev(timeb.time);
53714311Ssam 		bcopy(&timeb, args[0], sizeof timeb - 2);
53814311Ssam 		break;
53914311Ssam 
54014311Ssam 	case IOCTL:
54114311Ssam 		args[1] = mapioctl(args[1]);
54214311Ssam 		if (args[1] == 0)
54314311Ssam 			i = -1;
54414311Ssam 		else
54514311Ssam 			i = ioctl(args[0], args[1], args[2]);
54614311Ssam 		break;
54714311Ssam #endif
54814311Ssam 
5496809Srrh #ifdef	V6UNIX
55014311Ssam 	case PWBSYS:
5516809Srrh 		/* ignore pwbsys for now */
55214311Ssam 		switch (args[2]) {
55314311Ssam 		case UNAME:
5546809Srrh #ifdef	TRACE
5556809Srrh 			fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
5566809Srrh #endif
5576809Srrh 			strcpy(args[0],"pwbname");
5586809Srrh 			i = 0;
5596809Srrh 			break;
56014311Ssam 
56114311Ssam 		case UDATA:
5626809Srrh #ifdef	TRACE
5636809Srrh 			fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
5646809Srrh #endif
5656809Srrh 			i = 0;
5666809Srrh 			break;
56714311Ssam 
56814311Ssam 		case USTAT:
5696809Srrh fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
5706809Srrh 			i = 0;
5716809Srrh 			break;
57214311Ssam 
57314311Ssam 		case UTIME:
5746809Srrh fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
5756809Srrh 			i = 0;
5766809Srrh 			break;
5776809Srrh 		default:
5786809Srrh fprintf(stderr,"bad PWBSYS %d\n",args[3]);
5796809Srrh 			i = -1;
5806809Srrh 			break;
5816809Srrh 		}
5826809Srrh 		break;
5836809Srrh #endif
58414311Ssam 
5856809Srrh 	default:
5866809Srrh 		/*
5876809Srrh 		 *	Many sys calls are easily done here since most
5886809Srrh 		 *	system call codes are the same on version 6 and 7 UNIX
5896809Srrh 		 *	as they are here.
5906809Srrh 		 */
5916809Srrh 		i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
5926809Srrh #ifdef V6UNIX
59314311Ssam 		/* allow read write access to created files for (IDIS v6 mod) */
59414311Ssam 		if (code==CREAT) {
5956809Srrh 			/* get actual file mode after create */
5966809Srrh 			fstat(i, &stat32v);
5976809Srrh 			close(i);
5986809Srrh 			/* ensure read/write access to owner */
5996809Srrh 			chmod(args[0], 0644);
6006809Srrh 			i = open(args[0], 2);
6016809Srrh 			/* change mode back the way it was */
6026809Srrh 			chmod(args[0], stat32v.st_mode);
6036809Srrh 		}
6046809Srrh #endif
6056809Srrh 		break;
606*16442Smckusick 	case OPEN:
607*16442Smckusick 		/*
608*16442Smckusick 		 * check if we are opening a directory
609*16442Smckusick 		 */
610*16442Smckusick 		if (stat(args[0], &stat32v) >= 0  &&
611*16442Smckusick 		    ((stat32v.st_mode & S_IFMT) == S_IFDIR) &&
612*16442Smckusick 		    ((dp = opendir(args[0])) != NULL)) {
613*16442Smckusick #ifdef DTRACE
614*16442Smckusick 			fprintf(stderr,"open directory fd %d\n", i);
615*16442Smckusick #endif
616*16442Smckusick 			i = dp->dd_fd;
617*16442Smckusick 			fdflags[i].fd_dirp = dp;
618*16442Smckusick 			fdflags[i].fd_offset = 0;
619*16442Smckusick 		} else
620*16442Smckusick 			i = open(args[0], args[1]);
621*16442Smckusick 		break;
622*16442Smckusick 	case CLOSE:
623*16442Smckusick 		i = close(args[0]);
624*16442Smckusick 		if (i >= 0 && fdflags[args[0]].fd_dirp) {
625*16442Smckusick 			closedir(fdflags[args[0]].fd_dirp);
626*16442Smckusick 			fdflags[args[0]].fd_dirp = 0;
627*16442Smckusick 		}
628*16442Smckusick 		break;
629*16442Smckusick 	case READ:
630*16442Smckusick 		if ((unsigned)args[0] < NFILES && fdflags[args[0]].fd_dirp)
631*16442Smckusick 			i = oread(args[0], args[1], args[2]);
632*16442Smckusick 		else
633*16442Smckusick 			i = read(args[0], args[1], args[2]);
634*16442Smckusick 		break;
6356809Srrh 	}
6366809Srrh #ifdef TRACE
6376809Srrh 	fprintf(stderr," sys val -> 0%o\n",i);
6386809Srrh #endif
6396809Srrh 	/* set carry bit if sys error */
64014311Ssam 	if (i == -1)
6416809Srrh 		psl |= CARRY;
6426809Srrh 	/* if not an indirect sys call, adjust the pc */
643*16442Smckusick 	if (!indirflg && !sigtrapped)
6446809Srrh 		pc = argp;
6456809Srrh 	/* do alternate return on one side of fork */
64614311Ssam 	if (code == FORK && i != 0)
6476809Srrh 		pc++;
6486809Srrh 	/* do the various return value formats */
64914311Ssam 	switch (sysargs[code][2]) {
65014311Ssam 	case NORMRET:
6516809Srrh 		/* normal case only one return value in r0 */
6526809Srrh 		regs[0] = i;
6536809Srrh 		break;
65414311Ssam 	case LONGRET:
6556809Srrh 		/* return a long in r0 - r1 as in time */
6566809Srrh 		regs[1] = i;
6576809Srrh 		regs[0] = i >> 16;
6586809Srrh 		break;
65914311Ssam 	case TWORET:
6606809Srrh 		/* return two ints in r0 - r1 as in pipe */
66114311Ssam 		if (i == -1)
6626809Srrh 			regs[0] = i;
6636809Srrh 		else {
6646809Srrh 			regs[1] = args[1];
6656809Srrh 			regs[0] = args[0];
6666809Srrh 		}
6676809Srrh 		break;
6686809Srrh 	}
66914311Ssam 	if (i== -1)
6706809Srrh 		regs[0] = errno;
6716809Srrh }
67214311Ssam 
67314311Ssam long
67414311Ssam longrev(l)
67514311Ssam 	long l;
67614311Ssam {
6776809Srrh 	/* function to reverse the halves of a long */
6786809Srrh 	union {
6796809Srrh 		long	lng;
6806809Srrh 		short	s[2];
6816809Srrh 	} u;
6826809Srrh 	register short t;
6836809Srrh 	u.lng = l;
6846809Srrh 	t = u.s[0];
6856809Srrh 	u.s[0] = u.s[1];
6866809Srrh 	u.s[1] = t;
6876809Srrh 	return(u.lng);
6886809Srrh }
68914311Ssam 
69014311Ssam /*
69114311Ssam  * Note: these tables are sorted by
69214311Ssam  * ioctl "code" (in ascending order).
69314311Ssam  */
69414311Ssam int fctls[] = { FIOCLEX, FIONCLEX, FIOASYNC, FIONBIO, FIONREAD, 0 };
69514311Ssam int tctls[] = {
69614311Ssam 	TIOCGETD, TIOCSETD, TIOCHPCL, TIOCMODG, TIOCMODS,
69714311Ssam 	TIOCGETP, TIOCSETP, TIOCSETN, TIOCEXCL, TIOCNXCL,
69814311Ssam 	TIOCFLUSH,TIOCSETC, TIOCGETC, TIOCREMOTE,TIOCMGET,
69914311Ssam 	TIOCMBIC, TIOCMBIS, TIOCMSET, TIOCSTART,TIOCSTOP,
70014311Ssam 	TIOCPKT,  TIOCNOTTY,TIOCSTI,  TIOCOUTQ, TIOCGLTC,
70114311Ssam 	TIOCSLTC, TIOCSPGRP,TIOCGPGRP,TIOCCDTR, TIOCSDTR,
70214311Ssam 	TIOCCBRK, TIOCSBRK, TIOCLGET, TIOCLSET, TIOCLBIC,
70314311Ssam 	TIOCLBIS, 0
70414311Ssam };
70514311Ssam 
70614311Ssam /*
70714311Ssam  * Map an old style ioctl command to new.
70814311Ssam  */
70914311Ssam mapioctl(cmd)
71014311Ssam 	int cmd;
71114311Ssam {
71214311Ssam 	register int *map, c;
71314311Ssam 
71414311Ssam 	switch ((cmd >> 8) & 0xff) {
71514311Ssam 
71614311Ssam 	case 'f':
71714311Ssam 		map = fctls;
71814311Ssam 		break;
71914311Ssam 
72014311Ssam 	case 't':
72114311Ssam 		map = tctls;
72214311Ssam 		break;
72314311Ssam 
72414311Ssam 	default:
72514311Ssam 		return (0);
72614311Ssam 	}
72714311Ssam 	while ((c = *map) && (c&0xff) < (cmd&0xff))
72814311Ssam 		map++;
72914311Ssam 	if (c && (c&0xff) == (cmd&0xff))
73014311Ssam 		return (c);
73114311Ssam 	return (0);
73214311Ssam }
733*16442Smckusick 
734*16442Smckusick /*
735*16442Smckusick  * emulate a read of n bytes on an old style directory
736*16442Smckusick  */
737*16442Smckusick oread(fd, buf, count)
738*16442Smckusick int fd, count;
739*16442Smckusick char *buf;
740*16442Smckusick {
741*16442Smckusick 	struct fdflags *fp;
742*16442Smckusick 	struct direct *dp;
743*16442Smckusick 	DIR *dirp;
744*16442Smckusick 	struct odirect *odp;
745*16442Smckusick 	register int nleft = count;
746*16442Smckusick 	int dir_off;
747*16442Smckusick 	int i;
748*16442Smckusick 
749*16442Smckusick 	fp = &fdflags[fd];
750*16442Smckusick 	dirp = fp->fd_dirp;
751*16442Smckusick 	odp = &fp->fd_od;
752*16442Smckusick 	if (dirp == NULL)
753*16442Smckusick 		return(-1);
754*16442Smckusick 	dir_off = fp->fd_offset % ODSIZE;
755*16442Smckusick 	if (dir_off) {
756*16442Smckusick 		i = ODSIZE - dir_off;
757*16442Smckusick 		if (nleft < i)
758*16442Smckusick 			i = nleft;
759*16442Smckusick 		bcopy((caddr_t)odp + dir_off, buf, i);
760*16442Smckusick 		fp->fd_offset += i;
761*16442Smckusick 		if (i == nleft)
762*16442Smckusick 			return(i);
763*16442Smckusick 		buf += i;
764*16442Smckusick 		nleft -= i;
765*16442Smckusick 	}
766*16442Smckusick 	while (nleft >= ODSIZE) {
767*16442Smckusick 		if ((dp = readdir(dirp)) == NULL)
768*16442Smckusick 			return(count - nleft);
769*16442Smckusick 		odp->od_ino = dp->d_ino;
770*16442Smckusick 		strncpy(odp->od_name, dp->d_name, 14);
771*16442Smckusick 		bcopy((caddr_t)odp, buf, ODSIZE);
772*16442Smckusick 		fp->fd_offset += ODSIZE;
773*16442Smckusick 		buf += ODSIZE;
774*16442Smckusick 		nleft -= ODSIZE;
775*16442Smckusick 	}
776*16442Smckusick 	if (nleft > 0) {
777*16442Smckusick 		if ((dp = readdir(dirp)) == NULL)
778*16442Smckusick 			return(count - nleft);
779*16442Smckusick 		odp->od_ino = dp->d_ino;
780*16442Smckusick 		strncpy(odp->od_name, dp->d_name, 14);
781*16442Smckusick 		bcopy((caddr_t)odp, buf, nleft);
782*16442Smckusick 		fp->fd_offset += nleft;
783*16442Smckusick 		/* nleft = 0; */
784*16442Smckusick 	}
785*16442Smckusick 	return(count);
786*16442Smckusick }
787*16442Smckusick 
788*16442Smckusick /*
789*16442Smckusick  * emulate the lseek system call
790*16442Smckusick  */
791*16442Smckusick off_t
792*16442Smckusick olseek(fd, n, whence)
793*16442Smckusick int fd, whence;
794*16442Smckusick off_t n;
795*16442Smckusick {
796*16442Smckusick 	struct fdflags *fp;
797*16442Smckusick 	char buf[512];
798*16442Smckusick 	off_t newpos;
799*16442Smckusick 	int i, j;
800*16442Smckusick 
801*16442Smckusick 	if ((unsigned)fd >= NFILES)
802*16442Smckusick 		return(-1);
803*16442Smckusick 	fp = &fdflags[fd];
804*16442Smckusick 	/*
805*16442Smckusick 	 * the system can handle everything
806*16442Smckusick 	 * except directory files
807*16442Smckusick 	 */
808*16442Smckusick 	if (fp->fd_dirp == NULL)
809*16442Smckusick 		return(lseek(fd, n, whence));
810*16442Smckusick 	switch (whence) {
811*16442Smckusick 	case 0:
812*16442Smckusick 		newpos = n;
813*16442Smckusick 		break;
814*16442Smckusick 	case 1:
815*16442Smckusick 		newpos = fp->fd_offset + n;
816*16442Smckusick 		break;
817*16442Smckusick 	case 2:		/* not yet implemented */
818*16442Smckusick 	default:
819*16442Smckusick 		return(-1);
820*16442Smckusick 	}
821*16442Smckusick 	if (newpos < 0)
822*16442Smckusick 		return(-1);
823*16442Smckusick 	if (newpos < fp->fd_offset) {
824*16442Smckusick 		rewinddir(fdflags[fd].fd_dirp);
825*16442Smckusick 		fp->fd_offset = 0;
826*16442Smckusick 	}
827*16442Smckusick 	i = newpos - fp->fd_offset;
828*16442Smckusick 	while (i > 0) {
829*16442Smckusick 		j = i < 512 ? i : 512;
830*16442Smckusick 		if (oread(fd, buf, j) != j)
831*16442Smckusick 			break;
832*16442Smckusick 		i -= j;
833*16442Smckusick 	}
834*16442Smckusick 	return(fp->fd_offset);
835*16442Smckusick }
836