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