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