Annotation of MiNT/src/dosfile.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.