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: }