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