|
|
1.1 root 1: static char sccsid[] = "@(#)unixtraps.c 4.2 83/07/31";
2:
3: /*
4: * Function to execute version 6 and version 7 UNIX system calls from
5: * compatability mode on UNIX-32V.
6: * Art Wetzel August 1979
7: */
8:
9: #include <stdio.h>
10: #include <signal.h>
11: #include <sys/types.h>
12: #include <sys/stat.h>
13: #include <sys/ioctl.h>
14: #include <sys/time.h>
15: #ifdef V6UNIX
16: #ifdef TRACE
17: #define RTSNAME "/../../../../usr/local/v6trc"
18: #else
19: #define RTSNAME "/../../../../usr/local/v6run"
20: #endif
21: #include "unix6sys.h"
22: #ifdef TRACE
23: #include "unix6sysn.h"
24: #endif
25: #endif
26: #ifdef V7UNIX
27: #ifdef TRACE
28: #define RTSNAME "/../../../../usr/local/v7trc"
29: #else
30: #define RTSNAME "/../../../../usr/local/v7run"
31: #endif
32: #include "unix7sys.h"
33: #ifdef TRACE
34: #include "unix7sysn.h"
35: #endif
36: #endif
37: #include "defs.h"
38: #define CARRY 1
39: #define MAXSARGS 25
40: #ifdef V6UNIX
41: #define ARGVLEN 512
42: #define ENVLEN 0
43: #endif
44: #ifdef V7UNIX
45: #define ARGVLEN 5120
46: #define ENVLEN 1000
47: #endif
48: char argvs[ARGVLEN+ENVLEN];
49: int args[MAXSARGS];
50:
51: /* 32v type stat structure */
52: extern struct stat stat32v;
53:
54: /* place for times data so we can reverse the longs */
55: struct timebuf {
56: long t1;
57: long t2;
58: long t3;
59: long t4;
60: } timebuf;
61:
62: /* place for pipe file descriptors */
63: int pipes[2];
64:
65: /* wait status */
66: int wstatus;
67:
68: #ifdef V6UNIX
69: /* version 6 style stat structure */
70: struct v6nod {
71: dev_t majmin;
72: ino_t inumber;
73: unsigned short flags;
74: unsigned char nlinks;
75: unsigned char uid;
76: unsigned char gid;
77: unsigned char size0;
78: unsigned short size1;
79: unsigned short addr[8];
80: long actime;
81: long modtime;
82: } *v6stat;
83: #endif
84:
85: #ifdef V7UNIX
86: /* version 7 style stat structure */
87: struct v7stat {
88: dev_t v7st_dev;
89: u_short v7st_ino;
90: u_short v7st_mode;
91: short v7st_nlink;
92: short v7st_uid;
93: short v7st_gid;
94: dev_t v7st_rdev;
95: int v7st_size;
96: int v7st_atime;
97: int v7st_mtime;
98: int v7st_ctime;
99: } statv7;
100:
101: struct timeb {
102: time_t time;
103: u_short millitm;
104: short timezone;
105: short dstflag;
106: } timeb;
107: #endif
108:
109: /* do the trap stuff for the trap with code */
110: dotrap(code)
111: int code;
112: {
113: register unsigned short *argp, *savp, *savep;
114: register int i, j, indirflg;
115: register char *avp, *oavp;
116: extern sigcatch();
117: extern errno;
118:
119: /* clear out condition codes of psl */
120: psl &= ~017;
121: /* special case of indirect sys call */
122: if (code == 0) {
123: /* remember this was indirect */
124: indirflg = 1;
125: /* point to args */
126: argp = (unsigned short *)*(pc++);
127: /* code for indirect sys call */
128: code = *argp++;
129: /* is it legit */
130: if (code>>8 != TRAPS) {
131: fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
132: pc++;
133: /* set carry flag */
134: psl |= CARRY;
135: regs[0] = -1;
136: return(-1);
137: }
138: code &= 0377;
139: } else {
140: /* remember this was not indirect */
141: indirflg = 0;
142: /* point to args */
143: argp = pc;
144: }
145: /* check if code too high or bad sys code */
146: if (code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
147: fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
148: /* set carry bit */
149: psl |= CARRY;
150: regs[0] = -1;
151: return(-1);
152: }
153: /* copy args to known locations */
154: i=0;
155: for (j=0; j<sysargs[code][0]; j++)
156: args[i++] = regs[j];
157: for (j=0; j<(sysargs[code][1]); j++)
158: args[i++] = *argp++;
159: #ifdef TRACE
160: fprintf(stderr,"pid %d ",getpid());
161: if (indirflg)
162: fprintf(stderr,"indirect ");
163: fprintf(stderr, "%s (%d) from 0%o with %d args",
164: sysnames[code], code, pc-1, i);
165: for (j=0; j<i; j++)
166: fprintf(stderr," 0%o",args[j]);
167: if (code==OPEN || code==STAT || code==CREAT || code==EXEC ||
168: code==UNLNK || code==LINK || code==CHDIR || code==MKNOD)
169: fprintf(stderr," (%s)",args[0]);
170: #ifdef V7UNIX
171: if (code==EXECE)
172: fprintf(stderr," (%s)",args[0]);
173: #endif
174: if (code==LINK)
175: fprintf(stderr," (%s)",args[1]);
176: #endif
177: /* go do whatever sys call it is */
178: switch (code) {
179: case FORK:
180: /* indirect forks return pids on both sides - must do here */
181: /* this is possibly a bug in 32V */
182: i = fork();
183: break;
184:
185: case WAIT:
186: i = wait(&wstatus);
187: args[0] = i;
188: args[1] = wstatus;
189: break;
190:
191: case EXEC:
192: #ifdef V7UNIX
193: case EXECE:
194: #endif
195: /*
196: * have to do a lot of junk here to fix up an argv
197: * for execute since (1) the pdp-11 argv consists of 16
198: * bit pointers and (2) the argv itself is in the
199: * pdp-11 program space where it would get clobbered
200: * when a new program is read in and before its
201: * argv is set up.
202: */
203: avp = &argvs[0];
204: savp = (unsigned short *)args[1];
205: #ifdef V6UNIX
206: for (i=1; args[i] = *savp++; i++)
207: if (args[i] == 0177777)
208: break;
209: #ifdef TRACE
210: else
211: fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
212: #endif
213: #endif
214: #ifdef V7UNIX
215: savep = (unsigned short *)args[2];
216: for (i=1; args[i] = *savp++; i++)
217: #ifdef TRACE
218: fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
219: #else
220: ;
221: #endif
222: #endif
223: if (stat(args[0], &stat32v)) {
224: /* return error here if file does not exist */
225: #ifdef TRACE
226: fprintf(stderr," does not exist\n");
227: #endif
228: i = -1;
229: break;
230: }
231: /* must have execute permission */
232: if (stat32v.st_mode & (S_IEXEC>>6))
233: goto experm;
234: if (stat32v.st_mode & (S_IEXEC>>3)) {
235: if (stat32v.st_gid == getegid())
236: goto experm;
237: if (geteuid() == 0)
238: goto experm;
239: }
240: if (stat32v.st_mode & S_IEXEC) {
241: if (stat32v.st_uid == geteuid())
242: goto experm;
243: if (geteuid() == 0)
244: goto experm;
245: }
246: /* return failure if no exec permision allowed */
247: i = -1;
248: experm:
249: /* can't exec a directory */
250: if ((stat32v.st_mode&S_IFMT) == S_IFDIR)
251: i = -1;
252: if (i == -1)
253: break;
254: args[i] = 0;
255: for (j=0; j<i; j++) {
256: oavp = (char *)args[j];
257: args[j] = (int)avp;
258: while (*avp++ = *oavp++)
259: ;
260: }
261: #ifdef V7UNIX
262: if (code == EXECE) {
263: for (j = ++i; args[j] = *savep++; j++)
264: ;
265: for ( ; j > i; j--) {
266: oavp = (char *)args[j];
267: args[j] = (int)avp;
268: while (*avp++ = *oavp++)
269: ;
270: }
271: }
272: #endif
273: /* SETUID and SETGID files must be started with a fresh RTS */
274: if (stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
275: /* should add a check here for good magic # in header */
276: args[1] = args[0];
277: args[0] = (int)RTSNAME;
278: #ifdef TRACE
279: fprintf(stderr," SETUID-GID");
280: #endif
281: if (args[i])
282: i = execve(args[0], &args[0], &args[i]);
283: else
284: i = execv(args[0], &args[0]);
285: fprintf(stderr,"can't exec %s\n",RTSNAME);
286: break;
287: }
288: i = execute(args[0], &args[1], &args[i]);
289: /* shouldn't get here if exec works */
290: break;
291:
292: case SEEK:
293: #ifdef V6UNIX
294: /* fix up negative offsets */
295: if (args[2] != 0 && args[2] != 3)
296: if (args[1] >= 32768)
297: args[1] -= 65536;
298: if (args[2] <= 2)
299: i = lseek(args[0], args[1], args[2]);
300: else
301: i = lseek(args[0], args[1]*512, args[2]-3);
302: if (i != -1)
303: i = 0;
304: #endif
305: #ifdef V7UNIX
306: i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
307: #endif
308: break;
309:
310: #ifdef V6UNIX
311: case MKNOD:
312: /* version 6 uses allocated bit which means regular file here */
313: if (args[1] & S_IFBLK)
314: args[1] &= ~S_IFREG;
315: i = mknod(args[0], args[1], args[2]);
316: break;
317: #endif
318:
319: case PIPE:
320: i = pipe(pipes);
321: args[0] = pipes[0];
322: args[1] = pipes[1];
323: break;
324:
325: #ifdef V6UNIX
326: case TELL:
327: i = lseek(args[0], 0L, 1);
328: break;
329:
330: case STTY:
331: i = stty(args[0], args[1]);
332: break;
333:
334: case GTTY:
335: i = gtty(args[0], args[1]);
336: break;
337: #endif
338:
339: case STAT:
340: i = stat(args[0], &stat32v);
341: goto allstat;
342:
343: case FSTAT:
344: /* do the syscall to a local stat buffer */
345: i = fstat(args[0], &stat32v);
346:
347: allstat:
348: /* reverse the longs */
349: stat32v.st_size = longrev(stat32v.st_size);
350: stat32v.st_atime = longrev(stat32v.st_atime);
351: stat32v.st_mtime = longrev(stat32v.st_mtime);
352: stat32v.st_ctime = longrev(stat32v.st_ctime);
353: #ifdef V7UNIX
354: statv7.v7st_dev = stat32v.st_dev;
355: statv7.v7st_ino = stat32v.st_ino;
356: statv7.v7st_mode = stat32v.st_mode;
357: statv7.v7st_nlink = stat32v.st_nlink;
358: statv7.v7st_uid = stat32v.st_uid;
359: statv7.v7st_gid = stat32v.st_gid;
360: statv7.v7st_rdev = stat32v.st_rdev;
361: statv7.v7st_size = stat32v.st_size;
362: statv7.v7st_atime = stat32v.st_atime;
363: statv7.v7st_mtime = stat32v.st_mtime;
364: statv7.v7st_ctime = stat32v.st_ctime;
365: /* copy out otherwise unchanged stat buffer */
366: /* in two pieces with st_size as the breaking point */
367: /* note that st_rdev is a short but due to alingnmemt */
368: /* problems the rest of the structure is out of sync */
369: j = (int)((char *)(&statv7.v7st_size) -
370: (char *)(&statv7.v7st_dev));
371: bcopy(&statv7, args[1], j);
372: bcopy(&statv7.v7st_size, args[1]+j-2, sizeof(struct v7stat)-j);
373: #endif
374: #ifdef V6UNIX
375: /* point to user area as v6stat structure */
376: v6stat = (struct v6nod *)args[1];
377: /* copy out piece by piece */
378: v6stat->majmin = stat32v.st_dev;
379: v6stat->inumber = stat32v.st_ino;
380: v6stat->flags = stat32v.st_mode;
381: v6stat->nlinks = (unsigned char)stat32v.st_nlink;
382: v6stat->uid = (unsigned char)stat32v.st_uid;
383: v6stat->gid = (unsigned char)stat32v.st_gid;
384: /* note size already reversed */
385: v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
386: v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
387: v6stat->actime = stat32v.st_atime;
388: v6stat->modtime = stat32v.st_mtime;
389: /* patch up flags */
390: /* for now just set 100000 bit if not a plain file */
391: if (v6stat->flags & 060000)
392: v6stat->flags |= 0100000;
393: #endif
394: break;
395:
396: case TIMES:
397: i = times(&timebuf);
398: timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
399: timebuf.t3 = longrev(timebuf.t3);
400: timebuf.t4 = longrev(timebuf.t4);
401: bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
402: break;
403:
404: #ifdef V6UNIX
405: case SLEEP:
406: /* do a sleep function - what about pwb which has alarm? */
407: sleep(args[0]);
408: break;
409: #endif
410:
411: case GETUID:
412: args[0] = getuid();
413: args[1] = geteuid();
414: #ifdef V6UNIX
415: i = args[1]<<8 | (args[0] & 0377);
416: #endif
417: break;
418:
419: case GETGID:
420: args[0] = getgid();
421: args[1] = getegid();
422: #ifdef V6UNIX
423: i = args[1]<<8 | (args[0] & 0377);
424: #endif
425: break;
426:
427: /* uids and gids are 8 bits in version 6 */
428: case SETUID:
429: case SETGID:
430: #ifdef V6UNIX
431: args[0] &= 0377;
432: #endif
433: if (code == SETUID)
434: i = setuid(args[0]);
435: else
436: i = setgid(args[0]);
437: break;
438:
439: case SIG:
440: /* if it is a good signal code */
441: if (args[0] <= NSIG) {
442: /* get the current signal value */
443: i = sigvals[args[0]];
444: /* reset the signal to the new value */
445: sigvals[args[0]] = args[1];
446: /* actually do signal except don't reset SIGILL */
447: if (args[0] != SIGILL) {
448: if (args[1] == (int)SIG_DFL ||
449: args[1] & (int)SIG_IGN) {
450: if ((int)signal(args[0],args[1]) == -1)
451: i = -1;
452: } else {
453: if ((int)signal(args[0],sigcatch) == -1)
454: i = -1;
455: }
456: }
457: } else
458: i = -1;
459: break;
460:
461: case BRK:
462: /* brk is successful unless we run over the stack */
463: /* NB: this assumes register usage which need not be used */
464: i = 0;
465: if (args[0] >= regs[6])
466: i = -1;
467: break;
468:
469: /*
470: * the next bunch are to cope with sys calls removed from 4.2
471: */
472: case TIME:
473: i = time(0);
474: break;
475:
476: case STIME: {
477: struct timeval tv;
478:
479: tv.tv_usec = 0;
480: tv.tv_sec = (args[0] & 0xffff) | ((args[1] & 0xffff) << 16);
481: i = settimeofday(&tv);
482: break;
483: }
484:
485: case NICE:
486: i = nice(args[0]);
487: break;
488:
489: #ifdef V7UNIX
490: case ALARM:
491: i = alarm(args[0]);
492: break;
493:
494: case PAUSE:
495: i = pause();
496: break;
497:
498: case UTIME:
499: i = utime(args[0], args[1]);
500: break;
501:
502: case FTIME:
503: i = ftime(&timeb);
504: timeb.time = longrev(timeb.time);
505: bcopy(&timeb, args[0], sizeof timeb - 2);
506: break;
507:
508: case IOCTL:
509: args[1] = mapioctl(args[1]);
510: if (args[1] == 0)
511: i = -1;
512: else
513: i = ioctl(args[0], args[1], args[2]);
514: break;
515: #endif
516:
517: #ifdef V6UNIX
518: case PWBSYS:
519: /* ignore pwbsys for now */
520: switch (args[2]) {
521: case UNAME:
522: #ifdef TRACE
523: fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
524: #endif
525: strcpy(args[0],"pwbname");
526: i = 0;
527: break;
528:
529: case UDATA:
530: #ifdef TRACE
531: fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
532: #endif
533: i = 0;
534: break;
535:
536: case USTAT:
537: fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
538: i = 0;
539: break;
540:
541: case UTIME:
542: fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
543: i = 0;
544: break;
545: default:
546: fprintf(stderr,"bad PWBSYS %d\n",args[3]);
547: i = -1;
548: break;
549: }
550: break;
551: #endif
552:
553: default:
554: /*
555: * Many sys calls are easily done here since most
556: * system call codes are the same on version 6 and 7 UNIX
557: * as they are here.
558: */
559: i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
560: #ifdef V6UNIX
561: /* allow read write access to created files for (IDIS v6 mod) */
562: if (code==CREAT) {
563: /* get actual file mode after create */
564: fstat(i, &stat32v);
565: close(i);
566: /* ensure read/write access to owner */
567: chmod(args[0], 0644);
568: i = open(args[0], 2);
569: /* change mode back the way it was */
570: chmod(args[0], stat32v.st_mode);
571: }
572: #endif
573: break;
574: }
575: #ifdef TRACE
576: fprintf(stderr," sys val -> 0%o\n",i);
577: #endif
578: /* set carry bit if sys error */
579: if (i == -1)
580: psl |= CARRY;
581: /* if not an indirect sys call, adjust the pc */
582: if (indirflg == 0)
583: pc = argp;
584: /* do alternate return on one side of fork */
585: if (code == FORK && i != 0)
586: pc++;
587: /* do the various return value formats */
588: switch (sysargs[code][2]) {
589: case NORMRET:
590: /* normal case only one return value in r0 */
591: regs[0] = i;
592: break;
593: case LONGRET:
594: /* return a long in r0 - r1 as in time */
595: regs[1] = i;
596: regs[0] = i >> 16;
597: break;
598: case TWORET:
599: /* return two ints in r0 - r1 as in pipe */
600: if (i == -1)
601: regs[0] = i;
602: else {
603: regs[1] = args[1];
604: regs[0] = args[0];
605: }
606: break;
607: }
608: if (i== -1)
609: regs[0] = errno;
610: }
611:
612: long
613: longrev(l)
614: long l;
615: {
616: /* function to reverse the halves of a long */
617: union {
618: long lng;
619: short s[2];
620: } u;
621: register short t;
622: u.lng = l;
623: t = u.s[0];
624: u.s[0] = u.s[1];
625: u.s[1] = t;
626: return(u.lng);
627: }
628:
629: /*
630: * Note: these tables are sorted by
631: * ioctl "code" (in ascending order).
632: */
633: int fctls[] = { FIOCLEX, FIONCLEX, FIOASYNC, FIONBIO, FIONREAD, 0 };
634: int tctls[] = {
635: TIOCGETD, TIOCSETD, TIOCHPCL, TIOCMODG, TIOCMODS,
636: TIOCGETP, TIOCSETP, TIOCSETN, TIOCEXCL, TIOCNXCL,
637: TIOCFLUSH,TIOCSETC, TIOCGETC, TIOCREMOTE,TIOCMGET,
638: TIOCMBIC, TIOCMBIS, TIOCMSET, TIOCSTART,TIOCSTOP,
639: TIOCPKT, TIOCNOTTY,TIOCSTI, TIOCOUTQ, TIOCGLTC,
640: TIOCSLTC, TIOCSPGRP,TIOCGPGRP,TIOCCDTR, TIOCSDTR,
641: TIOCCBRK, TIOCSBRK, TIOCLGET, TIOCLSET, TIOCLBIC,
642: TIOCLBIS, 0
643: };
644:
645: /*
646: * Map an old style ioctl command to new.
647: */
648: mapioctl(cmd)
649: int cmd;
650: {
651: register int *map, c;
652:
653: switch ((cmd >> 8) & 0xff) {
654:
655: case 'f':
656: map = fctls;
657: break;
658:
659: case 't':
660: map = tctls;
661: break;
662:
663: default:
664: return (0);
665: }
666: while ((c = *map) && (c&0xff) < (cmd&0xff))
667: map++;
668: if (c && (c&0xff) == (cmd&0xff))
669: return (c);
670: return (0);
671: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.