|
|
1.1 root 1: #
2: /* Function to execute version 6 and version 7 UNIX system calls from
3: * compatability mode on UNIX-32V.
4: * Art Wetzel August 1979
5: */
6: #include <stdio.h>
7: #include <signal.h>
8: #include <sys/types.h>
9: #include <sys/stat.h>
10: #ifdef V6UNIX
11: #ifdef TRACE
12: #define RTSNAME "/../../../../usr/local/v6trc"
13: #else
14: #define RTSNAME "/../../../../usr/local/v6run"
15: #endif
16: #include "unix6sys.h"
17: #ifdef TRACE
18: #include "unix6sysn.h"
19: #endif
20: #endif
21: #ifdef V7UNIX
22: #ifdef TRACE
23: #define RTSNAME "/../../../../usr/local/v7trc"
24: #else
25: #define RTSNAME "/../../../../usr/local/v7run"
26: #endif
27: #include "unix7sys.h"
28: #ifdef TRACE
29: #include "unix7sysn.h"
30: #endif
31: #endif
32: #include "defs.h"
33: #define CARRY 1
34: #define MAXSARGS 25
35: #ifdef V6UNIX
36: #define ARGVLEN 512
37: #define ENVLEN 0
38: #endif
39: #ifdef V7UNIX
40: #define ARGVLEN 5120
41: #define ENVLEN 1000
42: #endif
43: char argvs[ARGVLEN+ENVLEN];
44: int args[MAXSARGS];
45: /* 32v type stat structure */
46: extern struct stat stat32v;
47: /* place for times data so we can reverse the longs */
48: struct timebuf {
49: long t1;
50: long t2;
51: long t3;
52: long t4;
53: } timebuf;
54: /* place for pipe file descriptors */
55: int pipes[2];
56: /* wait status */
57: int wstatus;
58: #ifdef V6UNIX
59: /* version 6 style stat structure */
60: struct v6nod {
61: dev_t majmin;
62: ino_t inumber;
63: unsigned short flags;
64: unsigned char nlinks;
65: unsigned char uid;
66: unsigned char gid;
67: unsigned char size0;
68: unsigned short size1;
69: unsigned short addr[8];
70: long actime;
71: long modtime;
72: } *v6stat;
73: #endif
74: /* do the trap stuff for the trap with code */
75: dotrap(code) int code; {
76: register unsigned short *argp, *savp, *savep;
77: register int i, j, indirflg;
78: register char *avp, *oavp;
79: extern sigcatch();
80: extern errno;
81: /* clear out condition codes of psl */
82: psl &= ~017;
83: /* special case of indirect sys call */
84: if(code == 0) {
85: /* remember this was indirect */
86: indirflg = 1;
87: /* point to args */
88: argp = (unsigned short *)*(pc++);
89: /* code for indirect sys call */
90: code = *argp++;
91: /* is it legit */
92: if(code>>8 != TRAPS) {
93: fprintf(stderr,"Bad indirect sys call at 0x%x\n",pc-2);
94: pc++;
95: /* set carry flag */
96: psl |= CARRY;
97: regs[0] = -1;
98: return(-1);
99: }
100: code &= 0377;
101: }
102: else {
103: /* remember this was not indirect */
104: indirflg = 0;
105: /* point to args */
106: argp = pc;
107: }
108: /* check if code too high or bad sys code */
109: if(code >= NSYSTRAPS || sysargs[code][0] == ILLSYS) {
110: fprintf(stderr,"Unimplimented trap %d at 0x%x\n",code,argp);
111: /* set carry bit */
112: psl |= CARRY;
113: regs[0] = -1;
114: return(-1);
115: }
116: /* copy args to known locations */
117: i=0;
118: for(j=0; j<sysargs[code][0]; j++) args[i++] = regs[j];
119: for(j=0; j<(sysargs[code][1]); j++) args[i++] = *argp++;
120: #ifdef TRACE
121: fprintf(stderr,"pid %d ",getpid());
122: if(indirflg) fprintf(stderr,"indirect ");
123: fprintf(stderr,"%s (%d) from 0%o with %d args",sysnames[code],code,pc-1,i);
124: for(j=0; j<i; j++)
125: fprintf(stderr," 0%o",args[j]);
126: if(code==OPEN||code==STAT||code==CREAT||code==EXEC||code==UNLNK||code==LINK||code==CHDIR||code==MKNOD)
127: fprintf(stderr," (%s)",args[0]);
128: #ifdef V7UNIX
129: if(code==EXECE)
130: fprintf(stderr," (%s)",args[0]);
131: #endif
132: if(code==LINK)
133: fprintf(stderr," (%s)",args[1]);
134: #endif
135: /* go do whatever sys call it is */
136: switch(code) {
137: case FORK:
138: /* indirect forks return pids on both sides - must do here */
139: /* this is possibly a bug in 32V */
140: i = fork();
141: break;
142: case WAIT:
143: i = wait(&wstatus);
144: args[0] = i;
145: args[1] = wstatus;
146: break;
147: case EXEC:
148: #ifdef V7UNIX
149: case EXECE:
150: #endif
151: /*
152: * have to do a lot of junk here to fix up an argv
153: * for execute since (1) the pdp-11 argv consists of 16
154: * bit pointers and (2) the argv itself is in the
155: * pdp-11 program space where it would get clobbered
156: * when a new program is read in and before its
157: * argv is set up.
158: */
159: avp = &argvs[0];
160: savp = (unsigned short *)args[1];
161: #ifdef V6UNIX
162: for(i=1; args[i] = *savp++; i++)
163: if(args[i] == 0177777) break;
164: #ifdef TRACE
165: else fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
166: #endif
167: #endif
168: #ifdef V7UNIX
169: savep = (unsigned short *)args[2];
170: for(i=1; args[i] = *savp++; i++)
171: #ifdef TRACE
172: fprintf(stderr,"argv[%d]%s ",i-1,args[i]);
173: #else
174: ;
175: #endif
176: #endif
177: if(stat(args[0], &stat32v)) {
178: /* return error here if file does not exist */
179: #ifdef TRACE
180: fprintf(stderr," does not exist\n");
181: #endif
182: i = -1;
183: break;
184: }
185: /* must have execute permission */
186: if(stat32v.st_mode & (S_IEXEC>>6)) goto experm;
187: if(stat32v.st_mode & (S_IEXEC>>3)) {
188: if(stat32v.st_gid == getegid()) goto experm;
189: if(geteuid() == 0) goto experm;
190: }
191: if(stat32v.st_mode & S_IEXEC) {
192: if(stat32v.st_uid == geteuid()) goto experm;
193: if(geteuid() == 0) goto experm;
194: }
195: /* return failure if no exec permision allowed */
196: i = -1;
197: experm:
198: /* can't exec a directory */
199: if(stat32v.st_mode & S_IFDIR)
200: i = -1;
201: if(i == -1) break;
202: args[i] = 0;
203: for(j=0; j<i; j++) {
204: oavp = (char *)args[j];
205: args[j] = (int)avp;
206: while(*avp++ = *oavp++) ;
207: }
208: #ifdef V7UNIX
209: if(code == EXECE) {
210: for(j = ++i; args[j] = *savep++; j++) ;
211: for( ; j>i; j--) {
212: oavp = (char *)args[j];
213: args[j] = (int)avp;
214: while(*avp++ = *oavp++) ;
215: }
216: }
217: #endif
218: /* SETUID and SETGID files must be started with a fresh RTS */
219: if(stat32v.st_mode & S_ISGID || stat32v.st_mode & S_ISUID) {
220: /* should add a check here for good magic # in header */
221: args[1] = args[0];
222: args[0] = (int)RTSNAME;
223: #ifdef TRACE
224: fprintf(stderr," SETUID-GID");
225: #endif
226: if(args[i])
227: i = execve(args[0], &args[0], &args[i]);
228: else
229: i = execv(args[0], &args[0]);
230: fprintf(stderr,"can't exec %s\n",RTSNAME);
231: break;
232: }
233: i = execute(args[0], &args[1], &args[i]);
234: /* shouldn't get here if exec works */
235: break;
236: case SEEK:
237: #ifdef V6UNIX
238: /* fix up negative offsets */
239: if(args[2] != 0 && args[2] != 3)
240: if(args[1] >= 32768) args[1] -= 65536;
241: if(args[2] <= 2)
242: i = lseek(args[0], args[1], args[2]);
243: else
244: i = lseek(args[0], args[1]*512, args[2]-3);
245: if(i != -1) i = 0;
246: #endif
247: #ifdef V7UNIX
248: i = lseek(args[0], (args[1]<<16)|(args[2]&0177777), args[3]);
249: #endif
250: break;
251: #ifdef V6UNIX
252: case MKNOD:
253: /* version 6 uses allocated bit which means regular file here */
254: if(args[1] & S_IFBLK)
255: args[1] &= ~S_IFREG;
256: i = mknod(args[0], args[1], args[2]);
257: break;
258: #endif
259: case PIPE:
260: i = pipe(pipes);
261: args[0] = pipes[0];
262: args[1] = pipes[1];
263: break;
264: #ifdef V6UNIX
265: case TELL:
266: i = lseek(args[0], 0L, 1);
267: break;
268: #endif
269: case STAT:
270: case FSTAT:
271: /* do the syscall to a local stat buffer */
272: i = syscall(code, args[0], &stat32v);
273: /* reverse the longs */
274: stat32v.st_size = longrev(stat32v.st_size);
275: stat32v.st_atime = longrev(stat32v.st_atime);
276: stat32v.st_mtime = longrev(stat32v.st_mtime);
277: stat32v.st_ctime = longrev(stat32v.st_ctime);
278: #ifdef V7UNIX
279: /* copy out otherwise unchanged stat buffer */
280: /* in two pieces with st_size as the breaking point */
281: /* note that st_rdev is a short but due to alingnmemt */
282: /* problems the rest of the structure is out of sync */
283: j = (int)((char *)(&stat32v.st_size)-(char *)(&stat32v.st_dev));
284: bcopy(&stat32v, args[1], j);
285: bcopy(&stat32v.st_size, args[1]+j-2, sizeof(struct stat)-j);
286: #endif
287: #ifdef V6UNIX
288: /* point to user area as v6stat structure */
289: v6stat = (struct v6nod *)args[1];
290: /* copy out piece by piece */
291: v6stat->majmin = stat32v.st_dev;
292: v6stat->inumber = stat32v.st_ino;
293: v6stat->flags = stat32v.st_mode;
294: v6stat->nlinks = (unsigned char)stat32v.st_nlink;
295: v6stat->uid = (unsigned char)stat32v.st_uid;
296: v6stat->gid = (unsigned char)stat32v.st_gid;
297: /* note size already reversed */
298: v6stat->size0 = (unsigned char)(stat32v.st_size & 0377);
299: v6stat->size1 = (unsigned short)(stat32v.st_size>>16);
300: v6stat->actime = stat32v.st_atime;
301: v6stat->modtime = stat32v.st_mtime;
302: /* patch up flags */
303: /* for now just set 100000 bit if not a plain file */
304: if(v6stat->flags & 060000)
305: v6stat->flags |= 0100000;
306: #endif
307: break;
308: case TIMES:
309: i = times(&timebuf);
310: timebuf.t2 = longrev(timebuf.t2) + timebuf.t1;
311: timebuf.t3 = longrev(timebuf.t3);
312: timebuf.t4 = longrev(timebuf.t4);
313: bcopy(&timebuf.t2,args[0],sizeof(struct timebuf)-sizeof(long));
314: break;
315: #ifdef V6UNIX
316: case SLEEP:
317: /* do a sleep function - what about pwb which has alarm? */
318: sleep(args[0]);
319: break;
320: #endif
321: case GETUID:
322: args[0] = getuid();
323: args[1] = geteuid();
324: #ifdef V6UNIX
325: i = args[1]<<8 | args[0];
326: #endif
327: break;
328: case GETGID:
329: args[0] = getgid();
330: args[1] = getegid();
331: #ifdef V6UNIX
332: i = args[1]<<8 | args[0];
333: #endif
334: break;
335: #ifdef V6UNIX
336: case SETUID:
337: case SETGID:
338: /* uids and gids are 8 bits in version 6 */
339: i = syscall(code,args[0]&0377);
340: break;
341: #endif
342: case SIG:
343: /* if it is a good signal code */
344: if(args[0] <= NSIG) {
345: /* get the current signal value */
346: i = sigvals[args[0]];
347: /* reset the signal to the new value */
348: sigvals[args[0]] = args[1];
349: /* actually do signal except don't reset SIGILL */
350: if(args[0] != SIGILL) {
351: if(args[1] == (int)SIG_DFL || args[1] & (int)SIG_IGN) {
352: if((int)signal(args[0],args[1]) == -1)
353: i = -1;
354: } else {
355: if((int)signal(args[0], sigcatch) == -1)
356: i = -1;
357: }
358: }
359: }
360: else i = -1;
361: break;
362: case BRK:
363: /* brk is successful unless we run over the stack */
364: i = 0;
365: if(args[0] >= regs[6]) i = -1;
366: break;
367: #ifdef V6UNIX
368: case PWBSYS:
369: /* ignore pwbsys for now */
370: switch(args[2]) {
371: case UNAME:
372: #ifdef TRACE
373: fprintf(stderr,"UNAME with %d %d\n",args[0],args[1]);
374: #endif
375: strcpy(args[0],"pwbname");
376: i = 0;
377: break;
378: case UDATA:
379: #ifdef TRACE
380: fprintf(stderr,"UDATA with %d %d\n",args[0],args[1]);
381: #endif
382: i = 0;
383: break;
384: case USTAT:
385: fprintf(stderr,"USTAT with %d %d\n",args[0],args[1]);
386: i = 0;
387: break;
388: case UTIME:
389: fprintf(stderr,"UTIME with %d %d\n",args[0],args[1]);
390: i = 0;
391: break;
392: default:
393: fprintf(stderr,"bad PWBSYS %d\n",args[3]);
394: i = -1;
395: break;
396: }
397: break;
398: #endif
399: default:
400: /*
401: * Many sys calls are easily done here since most
402: * system call codes are the same on version 6 and 7 UNIX
403: * as they are here.
404: */
405: i = syscall(code,args[0],args[1],args[2],args[3],args[4]);
406: #ifdef V6UNIX
407: /* allow read write access to created files for(IDIS v6 mod) */
408: if(code==CREAT) {
409: /* get actual file mode after create */
410: fstat(i, &stat32v);
411: close(i);
412: /* ensure read/write access to owner */
413: chmod(args[0], 0644);
414: i = open(args[0], 2);
415: /* change mode back the way it was */
416: chmod(args[0], stat32v.st_mode);
417: }
418: #endif
419: break;
420: }
421: #ifdef TRACE
422: fprintf(stderr," sys val -> 0%o\n",i);
423: #endif
424: /* set carry bit if sys error */
425: if(i == -1)
426: psl |= CARRY;
427: /* if not an indirect sys call, adjust the pc */
428: if(indirflg == 0)
429: pc = argp;
430: /* do alternate return on one side of fork */
431: if(code == FORK && i != 0)
432: pc++;
433: /* do the various return value formats */
434: switch(sysargs[code][2]) {
435: case NORMRET:
436: /* normal case only one return value in r0 */
437: regs[0] = i;
438: break;
439: case LONGRET:
440: /* return a long in r0 - r1 as in time */
441: regs[1] = i;
442: regs[0] = i >> 16;
443: break;
444: case TWORET:
445: /* return two ints in r0 - r1 as in pipe */
446: if(i == -1)
447: regs[0] = i;
448: else {
449: regs[1] = args[1];
450: regs[0] = args[0];
451: }
452: break;
453: }
454: if(i== -1)
455: regs[0] = errno;
456: }
457: long longrev(l) long l; {
458: /* function to reverse the halves of a long */
459: union {
460: long lng;
461: short s[2];
462: } u;
463: register short t;
464: u.lng = l;
465: t = u.s[0];
466: u.s[0] = u.s[1];
467: u.s[1] = t;
468: return(u.lng);
469: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.