|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: /* DOS file handling routines */ ! 10: ! 11: ! 12: ! 13: #include "mint.h" ! 14: ! 15: ! 16: ! 17: extern char temp1[]; /* see filesys.c */ ! 18: ! 19: ! 20: ! 21: static long do_dup P_((int,int)); ! 22: ! 23: static void unselectme P_((PROC *)); ! 24: ! 25: ! 26: ! 27: /* ! 28: ! 29: * first, some utility routines ! 30: ! 31: */ ! 32: ! 33: ! 34: ! 35: FILEPTR * ! 36: ! 37: do_open(name, rwmode, attr, x) ! 38: ! 39: const char *name; /* file name */ ! 40: ! 41: int rwmode; /* file access mode */ ! 42: ! 43: int attr; /* TOS attributes for created files (if applicable) */ ! 44: ! 45: XATTR *x; /* filled in with attributes of opened file */ ! 46: ! 47: { ! 48: ! 49: struct tty *tty; ! 50: ! 51: fcookie dir, fc; ! 52: ! 53: long devsp; ! 54: ! 55: FILEPTR *f; ! 56: ! 57: DEVDRV *dev; ! 58: ! 59: long r; ! 60: ! 61: XATTR xattr; ! 62: ! 63: unsigned perm; ! 64: ! 65: int creating; ! 66: ! 67: ! 68: ! 69: /* for special BIOS "fake" devices */ ! 70: ! 71: extern DEVDRV fakedev; ! 72: ! 73: ! 74: ! 75: TRACE("do_open(%s)", name); ! 76: ! 77: ! 78: ! 79: /* ! 80: ! 81: * first step: get a cookie for the directory ! 82: ! 83: */ ! 84: ! 85: ! 86: ! 87: r = path2cookie(name, temp1, &dir); ! 88: ! 89: if (r) { ! 90: ! 91: mint_errno = r; ! 92: ! 93: DEBUG("do_open(%s): error %ld", name, r); ! 94: ! 95: return NULL; ! 96: ! 97: } ! 98: ! 99: ! 100: ! 101: /* ! 102: ! 103: * second step: try to locate the file itself ! 104: ! 105: */ ! 106: ! 107: r = relpath2cookie(&dir, temp1, follow_links, &fc, 0); ! 108: ! 109: ! 110: ! 111: /* ! 112: ! 113: * file found: this is an error if (O_CREAT|O_EXCL) are set ! 114: ! 115: */ ! 116: ! 117: if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) { ! 118: ! 119: DEBUG("do_open(%s): file already exists",name); ! 120: ! 121: mint_errno = EACCDN; ! 122: ! 123: return NULL; ! 124: ! 125: } ! 126: ! 127: /* ! 128: ! 129: * file not found: maybe we should create it ! 130: ! 131: */ ! 132: ! 133: if (r == EFILNF && (rwmode & O_CREAT)) { ! 134: ! 135: /* check first for write permission in the directory */ ! 136: ! 137: r = (*dir.fs->getxattr)(&dir, &xattr); ! 138: ! 139: if (r == 0) { ! 140: ! 141: if (denyaccess(&xattr, S_IWOTH)) ! 142: ! 143: r = EACCDN; ! 144: ! 145: } ! 146: ! 147: if (r) { ! 148: ! 149: DEBUG("do_open(%s): couldn't get " ! 150: ! 151: "write permission on directory",name); ! 152: ! 153: mint_errno = r; ! 154: ! 155: return NULL; ! 156: ! 157: } ! 158: ! 159: r = (*dir.fs->creat)(&dir, temp1, ! 160: ! 161: (S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc); ! 162: ! 163: if (r) { ! 164: ! 165: DEBUG("do_open(%s): error %ld while creating file", ! 166: ! 167: name, r); ! 168: ! 169: mint_errno = r; ! 170: ! 171: return NULL; ! 172: ! 173: } ! 174: ! 175: creating = 1; ! 176: ! 177: } else if (r) { ! 178: ! 179: DEBUG("do_open(%s): error %ld while searching for file", ! 180: ! 181: name, r); ! 182: ! 183: mint_errno = r; ! 184: ! 185: return NULL; ! 186: ! 187: } else { ! 188: ! 189: creating = 0; ! 190: ! 191: } ! 192: ! 193: ! 194: ! 195: /* ! 196: ! 197: * check now for permission to actually access the file ! 198: ! 199: */ ! 200: ! 201: r = (*fc.fs->getxattr)(&fc, &xattr); ! 202: ! 203: if (r) { ! 204: ! 205: DEBUG("do_open(%s): couldn't get file attributes",name); ! 206: ! 207: mint_errno = r; ! 208: ! 209: return NULL; ! 210: ! 211: } ! 212: ! 213: /* ! 214: ! 215: * we don't do directories ! 216: ! 217: */ ! 218: ! 219: if ( (xattr.mode & S_IFMT) == S_IFDIR ) { ! 220: ! 221: DEBUG("do_open(%s): file is a directory",name); ! 222: ! 223: mint_errno = EFILNF; ! 224: ! 225: return NULL; ! 226: ! 227: } ! 228: ! 229: ! 230: ! 231: switch (rwmode & O_RWMODE) { ! 232: ! 233: case O_WRONLY: ! 234: ! 235: perm = S_IWOTH; ! 236: ! 237: break; ! 238: ! 239: case O_RDWR: ! 240: ! 241: perm = S_IROTH|S_IWOTH; ! 242: ! 243: break; ! 244: ! 245: case O_EXEC: ! 246: ! 247: perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH; ! 248: ! 249: break; ! 250: ! 251: case O_RDONLY: ! 252: ! 253: perm = S_IROTH; ! 254: ! 255: break; ! 256: ! 257: default: ! 258: ! 259: perm = 0; ! 260: ! 261: ALERT("do_open: bad file access mode: %x", rwmode); ! 262: ! 263: } ! 264: ! 265: if (!creating && denyaccess(&xattr, perm)) { ! 266: ! 267: DEBUG("do_open(%s): access to file denied",name); ! 268: ! 269: mint_errno = EACCDN; ! 270: ! 271: return NULL; ! 272: ! 273: } ! 274: ! 275: ! 276: ! 277: /* ! 278: ! 279: * an extra check for write access -- even the superuser shouldn't ! 280: ! 281: * write to files with the FA_RDONLY attribute bit set (unless, ! 282: ! 283: * we just created the file) ! 284: ! 285: */ ! 286: ! 287: if ( !creating && (xattr.attr & FA_RDONLY)) { ! 288: ! 289: if ( (rwmode & O_RWMODE) == O_RDWR || ! 290: ! 291: (rwmode & O_RWMODE) == O_WRONLY ) { ! 292: ! 293: DEBUG("do_open(%s): can't write a read-only file", ! 294: ! 295: name); ! 296: ! 297: mint_errno = EACCDN; ! 298: ! 299: return NULL; ! 300: ! 301: } ! 302: ! 303: } ! 304: ! 305: ! 306: ! 307: /* ! 308: ! 309: * if writing to a setuid or setgid file, clear those bits ! 310: ! 311: */ ! 312: ! 313: if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) { ! 314: ! 315: xattr.mode &= ~(S_ISUID|S_ISGID); ! 316: ! 317: (*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT)); ! 318: ! 319: } ! 320: ! 321: /* ! 322: ! 323: * If the caller asked for the attributes of the opened file, copy them over. ! 324: ! 325: */ ! 326: ! 327: if (x) *x = xattr; ! 328: ! 329: ! 330: ! 331: /* ! 332: ! 333: * So far, so good. Let's get the device driver now, and try to ! 334: ! 335: * actually open the file. ! 336: ! 337: */ ! 338: ! 339: dev = (*fc.fs->getdev)(&fc, &devsp); ! 340: ! 341: if (!dev) { ! 342: ! 343: mint_errno = devsp; ! 344: ! 345: DEBUG("do_open(%s): device driver not found",name); ! 346: ! 347: return NULL; ! 348: ! 349: } ! 350: ! 351: ! 352: ! 353: if (dev == &fakedev) { /* fake BIOS devices */ ! 354: ! 355: f = curproc->handle[devsp]; ! 356: ! 357: if (!f) { ! 358: ! 359: mint_errno = EIHNDL; ! 360: ! 361: return 0; ! 362: ! 363: } ! 364: ! 365: f->links++; ! 366: ! 367: return f; ! 368: ! 369: } ! 370: ! 371: if (!(f = new_fileptr())) { ! 372: ! 373: mint_errno = ENSMEM; ! 374: ! 375: return NULL; ! 376: ! 377: } ! 378: ! 379: f->links = 1; ! 380: ! 381: f->flags = rwmode; ! 382: ! 383: f->pos = 0; ! 384: ! 385: f->devinfo = devsp; ! 386: ! 387: f->fc = fc; ! 388: ! 389: f->dev = dev; ! 390: ! 391: ! 392: ! 393: r = (*dev->open)(f); ! 394: ! 395: if (r < 0) { ! 396: ! 397: DEBUG("do_open(%s): device open failed with error %ld", ! 398: ! 399: name, r); ! 400: ! 401: mint_errno = r; ! 402: ! 403: f->links = 0; ! 404: ! 405: dispose_fileptr(f); ! 406: ! 407: return NULL; ! 408: ! 409: } ! 410: ! 411: ! 412: ! 413: /* special code for opening a tty */ ! 414: ! 415: if (is_terminal(f)) { ! 416: ! 417: extern struct tty default_tty; /* in tty.c */ ! 418: ! 419: ! 420: ! 421: tty = (struct tty *)f->devinfo; ! 422: ! 423: if (tty->use_cnt == 0) { /* first open for this device? */ ! 424: ! 425: *tty = default_tty; ! 426: ! 427: } ! 428: ! 429: tty->use_cnt++; ! 430: ! 431: } ! 432: ! 433: return f; ! 434: ! 435: } ! 436: ! 437: ! 438: ! 439: /* ! 440: ! 441: * helper function for do_close: this closes the indicated file pointer which ! 442: ! 443: * is assumed to be associated with process p. The extra parameter is necessary ! 444: ! 445: * because f_midipipe mucks with file pointers of other processes, so ! 446: ! 447: * sometimes p != curproc. ! 448: ! 449: * ! 450: ! 451: * Note that the function changedrv() in filesys.c can call this routine. ! 452: ! 453: * in that case, f->dev will be 0 to represent an invalid device, and ! 454: ! 455: * we cannot call the device close routine. ! 456: ! 457: */ ! 458: ! 459: ! 460: ! 461: long ! 462: ! 463: do_pclose(p, f) ! 464: ! 465: PROC *p; ! 466: ! 467: FILEPTR *f; ! 468: ! 469: { ! 470: ! 471: long r = 0; ! 472: ! 473: ! 474: ! 475: if (!f) return EIHNDL; ! 476: ! 477: ! 478: ! 479: /* if this file is "select'd" by this process, unselect it ! 480: ! 481: * (this is just in case we were killed by a signal ! 482: ! 483: */ ! 484: ! 485: ! 486: ! 487: /* BUG? Feature? If media change is detected while we're doing the select, ! 488: ! 489: * we'll never unselect (since f->dev is set to NULL by changedrv()) ! 490: ! 491: */ ! 492: ! 493: if (f->dev) { ! 494: ! 495: (*f->dev->unselect)(f, (long)p, O_RDONLY); ! 496: ! 497: (*f->dev->unselect)(f, (long)p, O_WRONLY); ! 498: ! 499: } ! 500: ! 501: ! 502: ! 503: f->links--; ! 504: ! 505: ! 506: ! 507: /* TTY manipulation must be done *before* calling the device close routine, ! 508: ! 509: * since afterwards the TTY structure may no longer exist ! 510: ! 511: */ ! 512: ! 513: if (is_terminal(f) && f->links <= 0) { ! 514: ! 515: struct tty *tty = (struct tty *)f->devinfo; ! 516: ! 517: tty->use_cnt--; ! 518: ! 519: if (tty->use_cnt <= 0 && tty->xkey) { ! 520: ! 521: kfree(tty->xkey); ! 522: ! 523: tty->xkey = 0; ! 524: ! 525: } ! 526: ! 527: } ! 528: ! 529: ! 530: ! 531: if (f->dev) { ! 532: ! 533: r = (*f->dev->close)(f, p->pid); ! 534: ! 535: if (r) { ! 536: ! 537: DEBUG("close: device close failed"); ! 538: ! 539: } ! 540: ! 541: } ! 542: ! 543: if (f->links <= 0) { ! 544: ! 545: dispose_fileptr(f); ! 546: ! 547: } ! 548: ! 549: return r; ! 550: ! 551: } ! 552: ! 553: ! 554: ! 555: long ! 556: ! 557: do_close(f) ! 558: ! 559: FILEPTR *f; ! 560: ! 561: { ! 562: ! 563: return do_pclose(curproc, f); ! 564: ! 565: } ! 566: ! 567: ! 568: ! 569: long ! 570: ! 571: f_open(name, mode) ! 572: ! 573: const char *name; ! 574: ! 575: int mode; ! 576: ! 577: { ! 578: ! 579: int i; ! 580: ! 581: FILEPTR *f; ! 582: ! 583: PROC *proc; ! 584: ! 585: ! 586: ! 587: TRACE("Fopen(%s, %x)", name, mode); ! 588: ! 589: #if O_GLOBAL ! 590: ! 591: if (mode & O_GLOBAL) { ! 592: ! 593: /* oh, boy! user wants us to open a global handle! */ ! 594: ! 595: proc = rootproc; ! 596: ! 597: } ! 598: ! 599: else ! 600: ! 601: #endif ! 602: ! 603: proc = curproc; ! 604: ! 605: ! 606: ! 607: for (i = MIN_OPEN; i < MAX_OPEN; i++) { ! 608: ! 609: if (!proc->handle[i]) ! 610: ! 611: goto found_for_open; ! 612: ! 613: } ! 614: ! 615: DEBUG("Fopen(%s): process out of handles",name); ! 616: ! 617: return ENHNDL; /* no more handles */ ! 618: ! 619: ! 620: ! 621: found_for_open: ! 622: ! 623: mode &= O_USER; /* make sure the mode is legal */ ! 624: ! 625: ! 626: ! 627: /* note: file mode 3 is reserved for the kernel; for users, transmogrify it ! 628: ! 629: * into O_RDWR (mode 2) ! 630: ! 631: */ ! 632: ! 633: if ( (mode & O_RWMODE) == O_EXEC ) { ! 634: ! 635: mode = (mode & ~O_RWMODE) | O_RDWR; ! 636: ! 637: } ! 638: ! 639: ! 640: ! 641: f = do_open(name, mode, 0, (XATTR *)0); ! 642: ! 643: ! 644: ! 645: ! 646: ! 647: if (!f) { ! 648: ! 649: return mint_errno; ! 650: ! 651: } ! 652: ! 653: proc->handle[i] = f; ! 654: ! 655: /* default is to close non-standard files on exec */ ! 656: ! 657: proc->fdflags[i] = FD_CLOEXEC; ! 658: ! 659: ! 660: ! 661: #if O_GLOBAL ! 662: ! 663: if (proc != curproc) { ! 664: ! 665: /* we just opened a global handle */ ! 666: ! 667: i += 100; ! 668: ! 669: } ! 670: ! 671: #endif ! 672: ! 673: ! 674: ! 675: TRACE("Fopen: returning %d", i); ! 676: ! 677: return i; ! 678: ! 679: } ! 680: ! 681: ! 682: ! 683: long ! 684: ! 685: f_create(name, attrib) ! 686: ! 687: const char *name; ! 688: ! 689: int attrib; ! 690: ! 691: { ! 692: ! 693: fcookie dir; ! 694: ! 695: int i; ! 696: ! 697: FILEPTR *f; ! 698: ! 699: long r; ! 700: ! 701: PROC *proc; ! 702: ! 703: int offset = 0; ! 704: ! 705: ! 706: ! 707: TRACE("Fcreate(%s, %x)", name, attrib); ! 708: ! 709: #if O_GLOBAL ! 710: ! 711: if (attrib & O_GLOBAL) { ! 712: ! 713: proc = rootproc; ! 714: ! 715: offset = 100; ! 716: ! 717: attrib &= ~O_GLOBAL; ! 718: ! 719: } ! 720: ! 721: else ! 722: ! 723: #endif ! 724: ! 725: proc = curproc; ! 726: ! 727: ! 728: ! 729: for (i = MIN_OPEN; i < MAX_OPEN; i++) { ! 730: ! 731: if (!proc->handle[i]) ! 732: ! 733: goto found_for_create; ! 734: ! 735: } ! 736: ! 737: DEBUG("Fcreate(%s): process out of handles",name); ! 738: ! 739: return ENHNDL; /* no more handles */ ! 740: ! 741: ! 742: ! 743: found_for_create: ! 744: ! 745: if (attrib == FA_LABEL) { ! 746: ! 747: r = path2cookie(name, temp1, &dir); ! 748: ! 749: if (r) return r; ! 750: ! 751: r = (*dir.fs->writelabel)(&dir, temp1); ! 752: ! 753: if (r) return r; ! 754: ! 755: /* ! 756: ! 757: * just in case the caller tries to do something with this handle, ! 758: ! 759: * make it point to u:\dev\null ! 760: ! 761: */ ! 762: ! 763: f = do_open("u:\\dev\\null", O_RDWR|O_CREAT|O_TRUNC, 0, ! 764: ! 765: (XATTR *)0); ! 766: ! 767: proc->handle[i] = f; ! 768: ! 769: return i+offset; ! 770: ! 771: } ! 772: ! 773: if (attrib & (FA_LABEL|FA_DIR)) { ! 774: ! 775: DEBUG("Fcreate(%s,%x): illegal attributes",name,attrib); ! 776: ! 777: return EACCDN; ! 778: ! 779: } ! 780: ! 781: ! 782: ! 783: f = do_open(name, O_RDWR|O_CREAT|O_TRUNC, attrib, (XATTR *)0); ! 784: ! 785: ! 786: ! 787: if (!f) { ! 788: ! 789: DEBUG("Fcreate(%s) failed, error %d", name, mint_errno); ! 790: ! 791: return mint_errno; ! 792: ! 793: } ! 794: ! 795: proc->handle[i] = f; ! 796: ! 797: i += offset; ! 798: ! 799: TRACE("Fcreate: returning %d", i); ! 800: ! 801: return i; ! 802: ! 803: } ! 804: ! 805: ! 806: ! 807: long ! 808: ! 809: f_close(fh) ! 810: ! 811: int fh; ! 812: ! 813: { ! 814: ! 815: FILEPTR *f; ! 816: ! 817: long r; ! 818: ! 819: PROC *proc; ! 820: ! 821: ! 822: ! 823: TRACE("Fclose: %d", fh); ! 824: ! 825: #if O_GLOBAL ! 826: ! 827: if (fh >= 100) { ! 828: ! 829: fh -= 100; ! 830: ! 831: proc = rootproc; ! 832: ! 833: } ! 834: ! 835: else ! 836: ! 837: #endif ! 838: ! 839: proc = curproc; ! 840: ! 841: ! 842: ! 843: if (fh < 0 || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 844: ! 845: return EIHNDL; ! 846: ! 847: } ! 848: ! 849: r = do_close(f); ! 850: ! 851: ! 852: ! 853: /* standard handles should be restored to default values */ ! 854: ! 855: /* do this for TOS domain only! */ ! 856: ! 857: if (proc->domain == DOM_TOS) { ! 858: ! 859: if (fh == 0 || fh == 1) ! 860: ! 861: f = proc->handle[-1]; ! 862: ! 863: else if (fh == 2 || fh == 3) ! 864: ! 865: f = proc->handle[-fh]; ! 866: ! 867: else ! 868: ! 869: f = 0; ! 870: ! 871: } else ! 872: ! 873: f = 0; ! 874: ! 875: ! 876: ! 877: if (f) f->links++; ! 878: ! 879: proc->handle[fh] = f; ! 880: ! 881: return r; ! 882: ! 883: } ! 884: ! 885: ! 886: ! 887: long ! 888: ! 889: f_read(fh, count, buf) ! 890: ! 891: int fh; ! 892: ! 893: long count; ! 894: ! 895: char *buf; ! 896: ! 897: { ! 898: ! 899: FILEPTR *f; ! 900: ! 901: ! 902: ! 903: PROC *proc; ! 904: ! 905: ! 906: ! 907: #if O_GLOBAL ! 908: ! 909: if (fh >= 100) { ! 910: ! 911: fh -= 100; ! 912: ! 913: proc = rootproc; ! 914: ! 915: } ! 916: ! 917: else ! 918: ! 919: #endif ! 920: ! 921: proc = curproc; ! 922: ! 923: ! 924: ! 925: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 926: ! 927: DEBUG("Fread: invalid handle: %d", fh); ! 928: ! 929: return EIHNDL; ! 930: ! 931: } ! 932: ! 933: if ( (f->flags & O_RWMODE) == O_WRONLY ) { ! 934: ! 935: DEBUG("Fread: read on a write-only handle"); ! 936: ! 937: return EACCDN; ! 938: ! 939: } ! 940: ! 941: if (is_terminal(f)) ! 942: ! 943: return tty_read(f, buf, count); ! 944: ! 945: ! 946: ! 947: TRACE("Fread: %ld bytes from handle %d", count, fh); ! 948: ! 949: return (*f->dev->read)(f, buf, count); ! 950: ! 951: } ! 952: ! 953: ! 954: ! 955: long ! 956: ! 957: f_write(fh, count, buf) ! 958: ! 959: int fh; ! 960: ! 961: long count; ! 962: ! 963: const char *buf; ! 964: ! 965: { ! 966: ! 967: FILEPTR *f; ! 968: ! 969: PROC *proc; ! 970: ! 971: long r; ! 972: ! 973: ! 974: ! 975: #if O_GLOBAL ! 976: ! 977: if (fh >= 100) { ! 978: ! 979: fh -= 100; ! 980: ! 981: proc = rootproc; ! 982: ! 983: } ! 984: ! 985: else ! 986: ! 987: #endif ! 988: ! 989: proc = curproc; ! 990: ! 991: ! 992: ! 993: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 994: ! 995: DEBUG("Fwrite: bad handle: %d", fh); ! 996: ! 997: return EIHNDL; ! 998: ! 999: } ! 1000: ! 1001: if ( (f->flags & O_RWMODE) == O_RDONLY ) { ! 1002: ! 1003: DEBUG("Fwrite: write on a read-only handle"); ! 1004: ! 1005: return EACCDN; ! 1006: ! 1007: } ! 1008: ! 1009: if (is_terminal(f)) ! 1010: ! 1011: return tty_write(f, buf, count); ! 1012: ! 1013: ! 1014: ! 1015: /* it would be faster to do this in the device driver, but this ! 1016: ! 1017: * way the drivers are easier to write ! 1018: ! 1019: */ ! 1020: ! 1021: if (f->flags & O_APPEND) ! 1022: ! 1023: r = (*f->dev->lseek)(f, 0L, SEEK_END); ! 1024: ! 1025: else ! 1026: ! 1027: r = 0; ! 1028: ! 1029: if (r >= 0) { ! 1030: ! 1031: TRACE("Fwrite: %ld bytes to handle %d", count, fh); ! 1032: ! 1033: r = (*f->dev->write)(f, buf, count); ! 1034: ! 1035: } ! 1036: ! 1037: if (r < 0) { ! 1038: ! 1039: DEBUG("Fwrite: error %ld", r); ! 1040: ! 1041: } ! 1042: ! 1043: return r; ! 1044: ! 1045: } ! 1046: ! 1047: ! 1048: ! 1049: long ! 1050: ! 1051: f_seek(place, fh, how) ! 1052: ! 1053: long place; ! 1054: ! 1055: int fh; ! 1056: ! 1057: int how; ! 1058: ! 1059: { ! 1060: ! 1061: FILEPTR *f; ! 1062: ! 1063: PROC *proc; ! 1064: ! 1065: ! 1066: ! 1067: TRACE("Fseek(%ld, %d) on handle %d", place, how, fh); ! 1068: ! 1069: #if O_GLOBAL ! 1070: ! 1071: if (fh >= 100) { ! 1072: ! 1073: fh -= 100; ! 1074: ! 1075: proc = rootproc; ! 1076: ! 1077: } ! 1078: ! 1079: else ! 1080: ! 1081: #endif ! 1082: ! 1083: proc = curproc; ! 1084: ! 1085: ! 1086: ! 1087: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 1088: ! 1089: DEBUG("Fseek: bad handle: %d", fh); ! 1090: ! 1091: return EIHNDL; ! 1092: ! 1093: } ! 1094: ! 1095: if (is_terminal(f)) { ! 1096: ! 1097: return 0; ! 1098: ! 1099: } ! 1100: ! 1101: return (*f->dev->lseek)(f, place, how); ! 1102: ! 1103: } ! 1104: ! 1105: ! 1106: ! 1107: /* duplicate file pointer fh; returns a new file pointer >= min, if ! 1108: ! 1109: one exists, or ENHNDL if not. called by f_dup and f_cntl ! 1110: ! 1111: */ ! 1112: ! 1113: ! 1114: ! 1115: static long do_dup(fh, min) ! 1116: ! 1117: int fh, min; ! 1118: ! 1119: { ! 1120: ! 1121: FILEPTR *f; ! 1122: ! 1123: int i; ! 1124: ! 1125: PROC *proc; ! 1126: ! 1127: ! 1128: ! 1129: for (i = min; i < MAX_OPEN; i++) { ! 1130: ! 1131: if (!curproc->handle[i]) ! 1132: ! 1133: goto found; ! 1134: ! 1135: } ! 1136: ! 1137: return ENHNDL; /* no more handles */ ! 1138: ! 1139: found: ! 1140: ! 1141: #if O_GLOBAL ! 1142: ! 1143: if (fh >= 100) { ! 1144: ! 1145: fh -= 100; ! 1146: ! 1147: proc = rootproc; ! 1148: ! 1149: } else ! 1150: ! 1151: #endif ! 1152: ! 1153: proc = curproc; ! 1154: ! 1155: ! 1156: ! 1157: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) ! 1158: ! 1159: return EIHNDL; ! 1160: ! 1161: ! 1162: ! 1163: curproc->handle[i] = f; ! 1164: ! 1165: ! 1166: ! 1167: /* set default file descriptor flags */ ! 1168: ! 1169: if (i >= 0) { ! 1170: ! 1171: if (i >= MIN_OPEN) ! 1172: ! 1173: curproc->fdflags[i] = FD_CLOEXEC; ! 1174: ! 1175: else ! 1176: ! 1177: curproc->fdflags[i] = 0; ! 1178: ! 1179: } ! 1180: ! 1181: f->links++; ! 1182: ! 1183: return i; ! 1184: ! 1185: } ! 1186: ! 1187: ! 1188: ! 1189: long ! 1190: ! 1191: f_dup(fh) ! 1192: ! 1193: int fh; ! 1194: ! 1195: { ! 1196: ! 1197: long r; ! 1198: ! 1199: r = do_dup(fh, MIN_OPEN); ! 1200: ! 1201: TRACE("Fdup(%d) -> %ld", fh, r); ! 1202: ! 1203: return r; ! 1204: ! 1205: } ! 1206: ! 1207: ! 1208: ! 1209: long ! 1210: ! 1211: f_force(newh, oldh) ! 1212: ! 1213: int newh; ! 1214: ! 1215: int oldh; ! 1216: ! 1217: { ! 1218: ! 1219: FILEPTR *f; ! 1220: ! 1221: PROC *proc; ! 1222: ! 1223: ! 1224: ! 1225: TRACE("Fforce(%d, %d)", newh, oldh); ! 1226: ! 1227: ! 1228: ! 1229: #if O_GLOBAL ! 1230: ! 1231: if (oldh >= 100) { ! 1232: ! 1233: oldh -= 100; ! 1234: ! 1235: proc = rootproc; ! 1236: ! 1237: } else ! 1238: ! 1239: #endif ! 1240: ! 1241: proc = curproc; ! 1242: ! 1243: ! 1244: ! 1245: if (oldh < MIN_HANDLE || oldh >= MAX_OPEN || ! 1246: ! 1247: !(f = proc->handle[oldh])) { ! 1248: ! 1249: DEBUG("Fforce: old handle invalid"); ! 1250: ! 1251: return EIHNDL; ! 1252: ! 1253: } ! 1254: ! 1255: ! 1256: ! 1257: if (newh < MIN_HANDLE || newh >= MAX_OPEN) { ! 1258: ! 1259: DEBUG("Fforce: new handle out of range"); ! 1260: ! 1261: return EIHNDL; ! 1262: ! 1263: } ! 1264: ! 1265: ! 1266: ! 1267: (void)do_close(curproc->handle[newh]); ! 1268: ! 1269: curproc->handle[newh] = f; ! 1270: ! 1271: f->links++; ! 1272: ! 1273: /* ! 1274: ! 1275: * special: for a tty, if this is becoming a control terminal and the ! 1276: ! 1277: * tty doesn't have a pgrp yet, make it have the pgrp of the process ! 1278: ! 1279: * doing the Fforce ! 1280: ! 1281: */ ! 1282: ! 1283: if (is_terminal(f) && newh == -1) { ! 1284: ! 1285: struct tty *tty = (struct tty *)f->devinfo; ! 1286: ! 1287: ! 1288: ! 1289: if (!tty->pgrp) ! 1290: ! 1291: tty->pgrp = curproc->pgrp; ! 1292: ! 1293: } ! 1294: ! 1295: return newh; ! 1296: ! 1297: } ! 1298: ! 1299: ! 1300: ! 1301: long ! 1302: ! 1303: f_datime(timeptr, fh, rwflag) ! 1304: ! 1305: short *timeptr; ! 1306: ! 1307: int fh; ! 1308: ! 1309: int rwflag; ! 1310: ! 1311: { ! 1312: ! 1313: FILEPTR *f; ! 1314: ! 1315: PROC *proc; ! 1316: ! 1317: ! 1318: ! 1319: TRACE("Fdatime(%d)", fh); ! 1320: ! 1321: #if O_GLOBAL ! 1322: ! 1323: if (fh >= 100) { ! 1324: ! 1325: fh -= 100; ! 1326: ! 1327: proc = rootproc; ! 1328: ! 1329: } ! 1330: ! 1331: else ! 1332: ! 1333: #endif ! 1334: ! 1335: proc = curproc; ! 1336: ! 1337: ! 1338: ! 1339: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 1340: ! 1341: DEBUG("Fdatime: invalid handle"); ! 1342: ! 1343: return EIHNDL; ! 1344: ! 1345: } ! 1346: ! 1347: ! 1348: ! 1349: /* some programs use Fdatime to test for TTY devices */ ! 1350: ! 1351: if (is_terminal(f)) ! 1352: ! 1353: return EACCDN; ! 1354: ! 1355: ! 1356: ! 1357: return (*f->dev->datime)(f, timeptr, rwflag); ! 1358: ! 1359: } ! 1360: ! 1361: ! 1362: ! 1363: long ! 1364: ! 1365: f_lock(fh, mode, start, length) ! 1366: ! 1367: int fh, mode; ! 1368: ! 1369: long start, length; ! 1370: ! 1371: { ! 1372: ! 1373: FILEPTR *f; ! 1374: ! 1375: struct flock lock; ! 1376: ! 1377: PROC *proc; ! 1378: ! 1379: ! 1380: ! 1381: #if O_GLOBAL ! 1382: ! 1383: if (fh >= 100) { ! 1384: ! 1385: fh -= 100; ! 1386: ! 1387: proc = rootproc; ! 1388: ! 1389: } ! 1390: ! 1391: else ! 1392: ! 1393: #endif ! 1394: ! 1395: proc = curproc; ! 1396: ! 1397: ! 1398: ! 1399: if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) { ! 1400: ! 1401: DEBUG("Flock: invalid handle"); ! 1402: ! 1403: return EIHNDL; ! 1404: ! 1405: } ! 1406: ! 1407: TRACE("Flock(%d,%d,%ld,%ld)", fh, mode, start, length); ! 1408: ! 1409: lock.l_whence = SEEK_SET; ! 1410: ! 1411: lock.l_start = start; ! 1412: ! 1413: lock.l_len = length; ! 1414: ! 1415: ! 1416: ! 1417: if (mode == 0) /* create a lock */ ! 1418: ! 1419: lock.l_type = F_WRLCK; ! 1420: ! 1421: else if (mode == 1) /* unlock region */ ! 1422: ! 1423: lock.l_type = F_UNLCK; ! 1424: ! 1425: else ! 1426: ! 1427: return EINVFN; ! 1428: ! 1429: ! 1430: ! 1431: return (*f->dev->ioctl)(f, F_SETLK, &lock); ! 1432: ! 1433: } ! 1434: ! 1435: ! 1436: ! 1437: /* ! 1438: ! 1439: * extensions to GEMDOS: ! 1440: ! 1441: */ ! 1442: ! 1443: ! 1444: ! 1445: /* ! 1446: ! 1447: * Fpipe(int *handles): opens a pipe. if successful, returns 0, and ! 1448: ! 1449: * sets handles[0] to a file descriptor for the read end of the pipe ! 1450: ! 1451: * and handles[1] to one for the write end. ! 1452: ! 1453: */ ! 1454: ! 1455: ! 1456: ! 1457: long ! 1458: ! 1459: f_pipe(usrh) ! 1460: ! 1461: short *usrh; ! 1462: ! 1463: { ! 1464: ! 1465: extern FILESYS pipe_filesys; ! 1466: ! 1467: FILESYS *fs; ! 1468: ! 1469: FILEPTR *in, *out; ! 1470: ! 1471: static int pipeno = 0; ! 1472: ! 1473: int i, j; ! 1474: ! 1475: char pipename[32]; /* MAGIC: 32 >= strlen "u:\pipe\sys$pipe.000\0" */ ! 1476: ! 1477: ! 1478: ! 1479: TRACE("Fpipe"); ! 1480: ! 1481: fs = &pipe_filesys; ! 1482: ! 1483: ! 1484: ! 1485: /* BUG: more than 999 open pipes hangs the system */ ! 1486: ! 1487: do { ! 1488: ! 1489: ksprintf(pipename, "u:\\pipe\\sys$pipe.%03d", pipeno); ! 1490: ! 1491: pipeno++; if (pipeno > 999) pipeno = 0; ! 1492: ! 1493: out = do_open(pipename, O_WRONLY|O_CREAT|O_EXCL, 3, (XATTR *)0); ! 1494: ! 1495: /* read-only attribute means unidirectional fifo */ ! 1496: ! 1497: /* hidden attribute means check for broken pipes */ ! 1498: ! 1499: } while (out == 0 && mint_errno == EACCDN); ! 1500: ! 1501: ! 1502: ! 1503: if (!out) { ! 1504: ! 1505: DEBUG("Fpipe: error %d", mint_errno); ! 1506: ! 1507: return mint_errno; ! 1508: ! 1509: } ! 1510: ! 1511: ! 1512: ! 1513: in = do_open(pipename, O_RDONLY, 0, (XATTR *)0); ! 1514: ! 1515: if (!in) { ! 1516: ! 1517: DEBUG("Fpipe: in side of pipe not opened (error %d)", ! 1518: ! 1519: mint_errno); ! 1520: ! 1521: (void)do_close(out); ! 1522: ! 1523: return mint_errno; ! 1524: ! 1525: } ! 1526: ! 1527: ! 1528: ! 1529: for (i = MIN_OPEN; i < MAX_OPEN; i++) { ! 1530: ! 1531: if (curproc->handle[i] == 0) ! 1532: ! 1533: break; ! 1534: ! 1535: } ! 1536: ! 1537: ! 1538: ! 1539: for (j = i+1; j < MAX_OPEN; j++) { ! 1540: ! 1541: if (curproc->handle[j] == 0) ! 1542: ! 1543: break; ! 1544: ! 1545: } ! 1546: ! 1547: ! 1548: ! 1549: if (j >= MAX_OPEN) { ! 1550: ! 1551: DEBUG("Fpipe: not enough handles left"); ! 1552: ! 1553: (void) do_close(in); ! 1554: ! 1555: (void) do_close(out); ! 1556: ! 1557: return ENHNDL; ! 1558: ! 1559: } ! 1560: ! 1561: curproc->handle[i] = in; curproc->handle[j] = out; ! 1562: ! 1563: /* leave pipes open across Pexec */ ! 1564: ! 1565: curproc->fdflags[i] = 0; ! 1566: ! 1567: curproc->fdflags[j] = 0; ! 1568: ! 1569: ! 1570: ! 1571: usrh[0] = i; ! 1572: ! 1573: usrh[1] = j; ! 1574: ! 1575: TRACE("Fpipe: returning 0: input %d output %d",i,j); ! 1576: ! 1577: return 0; ! 1578: ! 1579: } ! 1580: ! 1581: ! 1582: ! 1583: /* ! 1584: ! 1585: * f_cntl: a combination "ioctl" and "fcntl". Some functions are ! 1586: ! 1587: * handled here, if they apply to the file descriptors directly ! 1588: ! 1589: * (e.g. F_DUPFD) or if they're easily translated into file system ! 1590: ! 1591: * functions (e.g. FSTAT). Others are passed on to the device driver ! 1592: ! 1593: * via dev->ioctl. ! 1594: ! 1595: */ ! 1596: ! 1597: ! 1598: ! 1599: long ! 1600: ! 1601: f_cntl(fh, arg, cmd) ! 1602: ! 1603: int fh; ! 1604: ! 1605: long arg; ! 1606: ! 1607: int cmd; ! 1608: ! 1609: { ! 1610: ! 1611: FILEPTR *f; ! 1612: ! 1613: PROC *proc; ! 1614: ! 1615: struct flock *fl; ! 1616: ! 1617: long r; ! 1618: ! 1619: ! 1620: ! 1621: TRACE("Fcntl(%d, cmd=0x%x)", fh, cmd); ! 1622: ! 1623: #if O_GLOBAL ! 1624: ! 1625: if (fh >= 100) { ! 1626: ! 1627: fh -= 100; ! 1628: ! 1629: proc = rootproc; ! 1630: ! 1631: } ! 1632: ! 1633: else ! 1634: ! 1635: #endif ! 1636: ! 1637: proc = curproc; ! 1638: ! 1639: ! 1640: ! 1641: if (fh < MIN_HANDLE || fh >= MAX_OPEN) { ! 1642: ! 1643: DEBUG("Fcntl: bad file handle"); ! 1644: ! 1645: return EIHNDL; ! 1646: ! 1647: } ! 1648: ! 1649: ! 1650: ! 1651: if (cmd == F_DUPFD) { ! 1652: ! 1653: #if O_GLOBAL ! 1654: ! 1655: if (proc != curproc) fh += 100; ! 1656: ! 1657: #endif ! 1658: ! 1659: return do_dup(fh, (int)arg); ! 1660: ! 1661: } ! 1662: ! 1663: ! 1664: ! 1665: f = proc->handle[fh]; ! 1666: ! 1667: if (!f) return EIHNDL; ! 1668: ! 1669: ! 1670: ! 1671: switch(cmd) { ! 1672: ! 1673: case F_GETFD: ! 1674: ! 1675: TRACE("Fcntl F_GETFD"); ! 1676: ! 1677: if (fh < 0) return EIHNDL; ! 1678: ! 1679: return proc->fdflags[fh]; ! 1680: ! 1681: case F_SETFD: ! 1682: ! 1683: TRACE("Fcntl F_SETFD"); ! 1684: ! 1685: if (fh < 0) return EIHNDL; ! 1686: ! 1687: proc->fdflags[fh] = arg; ! 1688: ! 1689: return 0; ! 1690: ! 1691: case F_GETFL: ! 1692: ! 1693: TRACE("Fcntl F_GETFL"); ! 1694: ! 1695: return f->flags & O_USER; ! 1696: ! 1697: case F_SETFL: ! 1698: ! 1699: TRACE("Fcntl F_SETFL"); ! 1700: ! 1701: arg &= O_USER; /* make sure only user bits set */ ! 1702: ! 1703: /* COMPATIBILITY WITH OLD VERSIONS ONLY */ ! 1704: ! 1705: /* THIS CODE WILL GO AWAY. REALLY! */ ! 1706: ! 1707: if (arg & 4) { ! 1708: ! 1709: arg |= O_NDELAY; ! 1710: ! 1711: arg &= ~4; ! 1712: ! 1713: } ! 1714: ! 1715: ! 1716: ! 1717: /* make sure the file access and sharing modes are not changed */ ! 1718: ! 1719: arg &= ~(O_RWMODE|O_SHMODE); ! 1720: ! 1721: arg |= f->flags & (O_RWMODE|O_SHMODE); ! 1722: ! 1723: f->flags &= ~O_USER; /* set user bits to arg */ ! 1724: ! 1725: f->flags |= arg; ! 1726: ! 1727: return 0; ! 1728: ! 1729: case FSTAT: ! 1730: ! 1731: return (*f->fc.fs->getxattr)(&f->fc, (XATTR *)arg); ! 1732: ! 1733: case F_SETLK: ! 1734: ! 1735: /* make sure that the file was opened with appropriate permissions */ ! 1736: ! 1737: fl = (struct flock *)arg; ! 1738: ! 1739: if (fl->l_type == F_RDLCK) { ! 1740: ! 1741: if ( (f->flags & O_RWMODE) == O_WRONLY ) ! 1742: ! 1743: return EACCDN; ! 1744: ! 1745: } else { ! 1746: ! 1747: if ( (f->flags & O_RWMODE) == O_RDONLY ) ! 1748: ! 1749: return EACCDN; ! 1750: ! 1751: } ! 1752: ! 1753: /* fall through to device ioctl */ ! 1754: ! 1755: default: ! 1756: ! 1757: TRACE("Fcntl mode %x: calling ioctl",cmd); ! 1758: ! 1759: r = (*f->dev->ioctl)(f, cmd, (void *)arg); ! 1760: ! 1761: if (r == EINVFN && is_terminal(f)) { ! 1762: ! 1763: r = tty_ioctl(f, cmd, (void *)arg); ! 1764: ! 1765: } ! 1766: ! 1767: return r; ! 1768: ! 1769: } ! 1770: ! 1771: } ! 1772: ! 1773: ! 1774: ! 1775: /* ! 1776: ! 1777: * fselect(timeout, rfd, wfd, xfd) ! 1778: ! 1779: * timeout is an (unsigned) 16 bit integer giving the maximum number ! 1780: ! 1781: * of milliseconds to wait; rfd, wfd, and xfd are pointers to 32 bit ! 1782: ! 1783: * integers containing bitmasks that describe which file descriptors ! 1784: ! 1785: * we're interested in. These masks are changed to represent which ! 1786: ! 1787: * file descriptors actually have data waiting (rfd), are ready to ! 1788: ! 1789: * output (wfd), or have exceptional conditions (xfd -- currently ! 1790: ! 1791: * ignored). If timeout is 0, fselect blocks until some file descriptor ! 1792: ! 1793: * is ready; otherwise, it waits only "timeout" milliseconds. ! 1794: ! 1795: * Return value: number of file descriptors that are available for ! 1796: ! 1797: * reading/writing; or a negative error number. ! 1798: ! 1799: */ ! 1800: ! 1801: ! 1802: ! 1803: /* helper function for time outs */ ! 1804: ! 1805: static void ! 1806: ! 1807: unselectme(p) ! 1808: ! 1809: PROC *p; ! 1810: ! 1811: { ! 1812: ! 1813: wakeselect((long)p); ! 1814: ! 1815: } ! 1816: ! 1817: ! 1818: ! 1819: long ! 1820: ! 1821: f_select(timeout, rfdp, wfdp, xfdp) ! 1822: ! 1823: unsigned timeout; ! 1824: ! 1825: long *rfdp, *wfdp, *xfdp; ! 1826: ! 1827: { ! 1828: ! 1829: long rfd, wfd; ! 1830: ! 1831: long mask, bytes; ! 1832: ! 1833: int i, count; ! 1834: ! 1835: FILEPTR *f; ! 1836: ! 1837: PROC *p; ! 1838: ! 1839: TIMEOUT *t; ! 1840: ! 1841: ! 1842: ! 1843: if (rfdp) { ! 1844: ! 1845: rfd = *rfdp; *rfdp = 0; ! 1846: ! 1847: } ! 1848: ! 1849: else ! 1850: ! 1851: rfd = 0; ! 1852: ! 1853: if (wfdp) { ! 1854: ! 1855: wfd = *wfdp; *wfdp = 0; ! 1856: ! 1857: } ! 1858: ! 1859: else ! 1860: ! 1861: wfd = 0; ! 1862: ! 1863: ! 1864: ! 1865: TRACE("Fselect(%u, %lx, %lx)", timeout, rfd, wfd); ! 1866: ! 1867: p = curproc; /* help the optimizer out */ ! 1868: ! 1869: ! 1870: ! 1871: /* first, validate the masks */ ! 1872: ! 1873: mask = 1L; ! 1874: ! 1875: for (i = 0; i < MAX_OPEN; i++) { ! 1876: ! 1877: if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) { ! 1878: ! 1879: DEBUG("Fselect: invalid handle"); ! 1880: ! 1881: return EIHNDL; ! 1882: ! 1883: } ! 1884: ! 1885: mask = mask << 1L; ! 1886: ! 1887: } ! 1888: ! 1889: ! 1890: ! 1891: /* now, loop through the file descriptors, setting up the select process */ ! 1892: ! 1893: /* NOTE: wakeselect will set p->wait_cond to 0 if data arrives during the ! 1894: ! 1895: * selection ! 1896: ! 1897: * Also note: because of the validation above, we may assume that the ! 1898: ! 1899: * file handles are valid here. However, this assumption may no longer ! 1900: ! 1901: * be true after we've gone to sleep, since a signal handler may have ! 1902: ! 1903: * closed one of the handles. ! 1904: ! 1905: */ ! 1906: ! 1907: ! 1908: ! 1909: mask = 1L; ! 1910: ! 1911: count = 0; ! 1912: ! 1913: curproc->wait_cond = (long)&wakeselect; /* flag */ ! 1914: ! 1915: ! 1916: ! 1917: for (i = 0; i < MAX_OPEN; i++) { ! 1918: ! 1919: if (rfd & mask) { ! 1920: ! 1921: f = p->handle[i]; ! 1922: ! 1923: if ((*f->dev->select)(f, (long)p, O_RDONLY)) { ! 1924: ! 1925: count++; ! 1926: ! 1927: *rfdp |= mask; ! 1928: ! 1929: } ! 1930: ! 1931: } ! 1932: ! 1933: if (wfd & mask) { ! 1934: ! 1935: f = p->handle[i]; ! 1936: ! 1937: if ((*f->dev->select)(f, (long)p, O_WRONLY)) { ! 1938: ! 1939: count++; ! 1940: ! 1941: *wfdp |= mask; ! 1942: ! 1943: } ! 1944: ! 1945: } ! 1946: ! 1947: mask = mask << 1L; ! 1948: ! 1949: } ! 1950: ! 1951: ! 1952: ! 1953: if (count == 0) { ! 1954: ! 1955: /* OK, now let's set a timeout */ ! 1956: ! 1957: ! 1958: ! 1959: if (timeout) { ! 1960: ! 1961: t = addtimeout((long)timeout, unselectme); ! 1962: ! 1963: } else { ! 1964: ! 1965: t = 0; ! 1966: ! 1967: } ! 1968: ! 1969: ! 1970: ! 1971: /* curproc->wait_cond changes when data arrives or the timeout happens */ ! 1972: ! 1973: while (curproc->wait_cond == (long)&wakeselect) { ! 1974: ! 1975: TRACE("sleeping in Fselect"); ! 1976: ! 1977: sleep(SELECT_Q, (long)&wakeselect); ! 1978: ! 1979: } ! 1980: ! 1981: ! 1982: ! 1983: /* we can cancel the time out now (if it hasn't already happened) */ ! 1984: ! 1985: if (t) canceltimeout(t); ! 1986: ! 1987: ! 1988: ! 1989: /* OK, let's see what data arrived (if any) */ ! 1990: ! 1991: mask = 1L; ! 1992: ! 1993: for (i = 0; i < MAX_OPEN; i++) { ! 1994: ! 1995: if (rfd & mask) { ! 1996: ! 1997: f = p->handle[i]; ! 1998: ! 1999: if (f) { ! 2000: ! 2001: bytes = 1L; ! 2002: ! 2003: (void)(*f->dev->ioctl)(f, FIONREAD,&bytes); ! 2004: ! 2005: if (bytes > 0) { ! 2006: ! 2007: *rfdp |= mask; ! 2008: ! 2009: count++; ! 2010: ! 2011: } ! 2012: ! 2013: } ! 2014: ! 2015: } ! 2016: ! 2017: if (wfd & mask) { ! 2018: ! 2019: f = p->handle[i]; ! 2020: ! 2021: if (f) { ! 2022: ! 2023: bytes = 1L; ! 2024: ! 2025: (void)(*f->dev->ioctl)(f, FIONWRITE,&bytes); ! 2026: ! 2027: if (bytes > 0) { ! 2028: ! 2029: *wfdp |= mask; ! 2030: ! 2031: count++; ! 2032: ! 2033: } ! 2034: ! 2035: } ! 2036: ! 2037: } ! 2038: ! 2039: mask = mask << 1L; ! 2040: ! 2041: } ! 2042: ! 2043: } else { ! 2044: ! 2045: /* TRACE("Fselect: data already present (count == %d)", count); */ ! 2046: ! 2047: } ! 2048: ! 2049: ! 2050: ! 2051: /* at this point, we either have data or a time out */ ! 2052: ! 2053: /* cancel all the selects */ ! 2054: ! 2055: mask = 1L; ! 2056: ! 2057: ! 2058: ! 2059: for (i = 0; i < MAX_OPEN; i++) { ! 2060: ! 2061: if (rfd & mask) { ! 2062: ! 2063: f = p->handle[i]; ! 2064: ! 2065: if (f) ! 2066: ! 2067: (*f->dev->unselect)(f, (long)p, O_RDONLY); ! 2068: ! 2069: } ! 2070: ! 2071: if (wfd & mask) { ! 2072: ! 2073: f = p->handle[i]; ! 2074: ! 2075: if (f) ! 2076: ! 2077: (*f->dev->unselect)(f, (long)p, O_WRONLY); ! 2078: ! 2079: } ! 2080: ! 2081: mask = mask << 1L; ! 2082: ! 2083: } ! 2084: ! 2085: ! 2086: ! 2087: TRACE("Fselect: returning %d", count); ! 2088: ! 2089: return count; ! 2090: ! 2091: } ! 2092: ! 2093: ! 2094: ! 2095: ! 2096: ! 2097: /* ! 2098: ! 2099: * GEMDOS extension: Fmidipipe ! 2100: ! 2101: * Fmidipipe(pid, in, out) manipultes the MIDI file handles (handles -4 and -5) ! 2102: ! 2103: * of process "pid" so that they now point to the files with handles "in" and ! 2104: ! 2105: * "out" in the calling process ! 2106: ! 2107: */ ! 2108: ! 2109: ! 2110: ! 2111: long ! 2112: ! 2113: f_midipipe(pid, in, out) ! 2114: ! 2115: int pid, in, out; ! 2116: ! 2117: { ! 2118: ! 2119: PROC *p; ! 2120: ! 2121: FILEPTR *fin, *fout; ! 2122: ! 2123: ! 2124: ! 2125: /* first, find the process */ ! 2126: ! 2127: ! 2128: ! 2129: if (pid == 0) ! 2130: ! 2131: p = curproc; ! 2132: ! 2133: else { ! 2134: ! 2135: p = pid2proc(pid); ! 2136: ! 2137: if (!p) ! 2138: ! 2139: return EFILNF; ! 2140: ! 2141: } ! 2142: ! 2143: ! 2144: ! 2145: /* next, validate the input and output file handles */ ! 2146: ! 2147: if (in < MIN_HANDLE || in >= MAX_OPEN || (!(fin = curproc->handle[in]))) ! 2148: ! 2149: return EIHNDL; ! 2150: ! 2151: if ( (fin->flags & O_RWMODE) == O_WRONLY ) { ! 2152: ! 2153: DEBUG("Fmidipipe: input side is write only"); ! 2154: ! 2155: return EACCDN; ! 2156: ! 2157: } ! 2158: ! 2159: if (out < MIN_HANDLE || out >= MAX_OPEN || (!(fout = curproc->handle[out]))) ! 2160: ! 2161: return EIHNDL; ! 2162: ! 2163: if ( (fout->flags & O_RWMODE) == O_RDONLY ) { ! 2164: ! 2165: DEBUG("Fmidipipe: output side is read only"); ! 2166: ! 2167: return EACCDN; ! 2168: ! 2169: } ! 2170: ! 2171: ! 2172: ! 2173: /* OK, duplicate the handles and put them in the new process */ ! 2174: ! 2175: fin->links++; fout->links++; ! 2176: ! 2177: (void)do_pclose(p, p->midiin); ! 2178: ! 2179: (void)do_pclose(p, p->midiout); ! 2180: ! 2181: p->midiin = fin; p->midiout = fout; ! 2182: ! 2183: return 0; ! 2184: ! 2185: } ! 2186:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.