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

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1990,1991,1992 Eric R. Smith.
                      4: 
1.1.1.5   root        5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3   root        6: 
                      7: All rights reserved.
1.1       root        8: 
                      9: */
                     10: 
                     11: 
                     12: 
                     13: /* DOS file handling routines */
                     14: 
                     15: 
                     16: 
                     17: #include "mint.h"
                     18: 
                     19: 
                     20: 
                     21: static long do_dup P_((int,int));
                     22: 
                     23: static void unselectme P_((PROC *));
                     24: 
                     25: 
                     26: 
1.1.1.6 ! root       27: MEMREGION *tofreed;    /* to-be-freed shared text region (set in denyshare) */
        !            28: 
        !            29: 
        !            30: 
        !            31: /* wait condition for selecting processes which got collisions */
        !            32: 
        !            33: short select_coll;
        !            34: 
        !            35: 
        !            36: 
1.1       root       37: /*
                     38: 
                     39:  * first, some utility routines
                     40: 
                     41:  */
                     42: 
                     43: 
                     44: 
                     45: FILEPTR *
                     46: 
                     47: do_open(name, rwmode, attr, x)
                     48: 
                     49:        const char *name;       /* file name */
                     50: 
                     51:        int rwmode;     /* file access mode */
                     52: 
                     53:        int attr;       /* TOS attributes for created files (if applicable) */
                     54: 
                     55:        XATTR *x;       /* filled in with attributes of opened file */
                     56: 
                     57: {
                     58: 
                     59:        struct tty *tty;
                     60: 
                     61:        fcookie dir, fc;
                     62: 
                     63:        long devsp;
                     64: 
                     65:        FILEPTR *f;
                     66: 
                     67:        DEVDRV *dev;
                     68: 
                     69:        long r;
                     70: 
                     71:        XATTR xattr;
                     72: 
                     73:        unsigned perm;
                     74: 
                     75:        int creating;
                     76: 
1.1.1.4   root       77:        char temp1[PATH_MAX];
                     78: 
1.1.1.3   root       79:        extern FILESYS proc_filesys;
                     80: 
1.1       root       81: 
                     82: 
                     83: /* for special BIOS "fake" devices */
                     84: 
                     85:        extern DEVDRV fakedev;
                     86: 
                     87: 
                     88: 
1.1.1.2   root       89:        TRACE(("do_open(%s)", name));
1.1       root       90: 
                     91: 
                     92: 
                     93: /*
                     94: 
                     95:  * first step: get a cookie for the directory
                     96: 
                     97:  */
                     98: 
                     99: 
                    100: 
                    101:        r = path2cookie(name, temp1, &dir);
                    102: 
                    103:        if (r) {
                    104: 
1.1.1.2   root      105:                mint_errno = (int)r;
1.1       root      106: 
1.1.1.2   root      107:                DEBUG(("do_open(%s): error %ld", name, r));
1.1       root      108: 
                    109:                return NULL;
                    110: 
                    111:        }
                    112: 
                    113: 
                    114: 
                    115: /*
                    116: 
                    117:  * second step: try to locate the file itself
                    118: 
                    119:  */
                    120: 
                    121:        r = relpath2cookie(&dir, temp1, follow_links, &fc, 0);
                    122: 
                    123: 
                    124: 
                    125: /*
                    126: 
                    127:  * file found: this is an error if (O_CREAT|O_EXCL) are set
                    128: 
                    129:  */
                    130: 
1.1.1.3   root      131: 
                    132: 
1.1       root      133:        if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
                    134: 
1.1.1.2   root      135:                DEBUG(("do_open(%s): file already exists",name));
1.1       root      136: 
                    137:                mint_errno = EACCDN;
                    138: 
1.1.1.3   root      139:                release_cookie(&fc);
                    140: 
                    141:                release_cookie(&dir);
                    142: 
1.1       root      143:                return NULL;
                    144: 
                    145:        }
                    146: 
                    147: /*
                    148: 
                    149:  * file not found: maybe we should create it
                    150: 
1.1.1.3   root      151:  * note that if r != 0, the fc cookie is invalid (so we don't need to
                    152: 
                    153:  * release it)
                    154: 
1.1       root      155:  */
                    156: 
                    157:        if (r == EFILNF && (rwmode & O_CREAT)) {
                    158: 
                    159:        /* check first for write permission in the directory */
                    160: 
                    161:                r = (*dir.fs->getxattr)(&dir, &xattr);
                    162: 
                    163:                if (r == 0) {
                    164: 
                    165:                        if (denyaccess(&xattr, S_IWOTH))
                    166: 
                    167:                                r = EACCDN;
                    168: 
                    169:                }
                    170: 
                    171:                if (r) {
                    172: 
1.1.1.2   root      173:                        DEBUG(("do_open(%s): couldn't get "
1.1       root      174: 
1.1.1.2   root      175:                              "write permission on directory",name));
1.1       root      176: 
1.1.1.2   root      177:                        mint_errno = (int)r;
1.1       root      178: 
1.1.1.3   root      179:                        release_cookie(&dir);
                    180: 
1.1       root      181:                        return NULL;
                    182: 
                    183:                }
                    184: 
                    185:                r = (*dir.fs->creat)(&dir, temp1,
                    186: 
                    187:                        (S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc);
                    188: 
                    189:                if (r) {
                    190: 
1.1.1.2   root      191:                        DEBUG(("do_open(%s): error %ld while creating file",
1.1       root      192: 
1.1.1.2   root      193:                                name, r));
1.1       root      194: 
1.1.1.2   root      195:                        mint_errno = (int)r;
1.1       root      196: 
1.1.1.3   root      197:                        release_cookie(&dir);
                    198: 
1.1       root      199:                        return NULL;
                    200: 
                    201:                }
                    202: 
                    203:                creating = 1;
                    204: 
                    205:        } else if (r) {
                    206: 
1.1.1.2   root      207:                DEBUG(("do_open(%s): error %ld while searching for file",
1.1       root      208: 
1.1.1.2   root      209:                        name, r));
1.1       root      210: 
1.1.1.2   root      211:                mint_errno = (int)r;
1.1       root      212: 
1.1.1.3   root      213:                release_cookie(&dir);
                    214: 
1.1       root      215:                return NULL;
                    216: 
                    217:        } else {
                    218: 
                    219:                creating = 0;
                    220: 
                    221:        }
                    222: 
                    223: 
                    224: 
                    225: /*
                    226: 
                    227:  * check now for permission to actually access the file
                    228: 
                    229:  */
                    230: 
                    231:        r = (*fc.fs->getxattr)(&fc, &xattr);
                    232: 
                    233:        if (r) {
                    234: 
1.1.1.2   root      235:                DEBUG(("do_open(%s): couldn't get file attributes",name));
1.1       root      236: 
1.1.1.2   root      237:                mint_errno = (int)r;
1.1       root      238: 
1.1.1.3   root      239:                release_cookie(&dir);
                    240: 
                    241:                release_cookie(&fc);
                    242: 
1.1       root      243:                return NULL;
                    244: 
                    245:        }
                    246: 
                    247: /*
                    248: 
                    249:  * we don't do directories
                    250: 
                    251:  */
                    252: 
                    253:        if ( (xattr.mode & S_IFMT) == S_IFDIR ) {
                    254: 
1.1.1.2   root      255:                DEBUG(("do_open(%s): file is a directory",name));
1.1       root      256: 
1.1.1.3   root      257:                release_cookie(&dir);
                    258: 
                    259:                release_cookie(&fc);
                    260: 
1.1       root      261:                mint_errno = EFILNF;
                    262: 
                    263:                return NULL;
                    264: 
                    265:        }
                    266: 
                    267: 
                    268: 
                    269:        switch (rwmode & O_RWMODE) {
                    270: 
                    271:        case O_WRONLY:
                    272: 
                    273:                perm = S_IWOTH;
                    274: 
                    275:                break;
                    276: 
                    277:        case O_RDWR:
                    278: 
                    279:                perm = S_IROTH|S_IWOTH;
                    280: 
                    281:                break;
                    282: 
                    283:        case O_EXEC:
                    284: 
                    285:                perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH;
                    286: 
                    287:                break;
                    288: 
                    289:        case O_RDONLY:
                    290: 
                    291:                perm = S_IROTH;
                    292: 
                    293:                break;
                    294: 
                    295:        default:
                    296: 
                    297:                perm = 0;
                    298: 
                    299:                ALERT("do_open: bad file access mode: %x", rwmode);
                    300: 
                    301:        }
                    302: 
                    303:        if (!creating && denyaccess(&xattr, perm)) {
                    304: 
1.1.1.2   root      305:                DEBUG(("do_open(%s): access to file denied",name));
1.1       root      306: 
1.1.1.3   root      307:                release_cookie(&dir);
                    308: 
                    309:                release_cookie(&fc);
                    310: 
1.1       root      311:                mint_errno = EACCDN;
                    312: 
                    313:                return NULL;
                    314: 
                    315:        }
                    316: 
                    317: 
                    318: 
                    319: /*
                    320: 
                    321:  * an extra check for write access -- even the superuser shouldn't
                    322: 
                    323:  * write to files with the FA_RDONLY attribute bit set (unless,
                    324: 
1.1.1.3   root      325:  * we just created the file, or unless the file is on the proc
                    326: 
                    327:  * file system and hence FA_RDONLY has a different meaning)
1.1       root      328: 
                    329:  */
                    330: 
1.1.1.3   root      331:        if ( !creating && (xattr.attr & FA_RDONLY) && fc.fs != &proc_filesys) {
1.1       root      332: 
                    333:                if ( (rwmode & O_RWMODE) == O_RDWR ||
                    334: 
                    335:                     (rwmode & O_RWMODE) == O_WRONLY ) {
                    336: 
1.1.1.2   root      337:                        DEBUG(("do_open(%s): can't write a read-only file",
1.1       root      338: 
1.1.1.2   root      339:                                name));
1.1       root      340: 
1.1.1.3   root      341:                        release_cookie(&dir);
                    342: 
                    343:                        release_cookie(&fc);
                    344: 
1.1       root      345:                        mint_errno = EACCDN;
                    346: 
                    347:                        return NULL;
                    348: 
                    349:                }
                    350: 
                    351:        }
                    352: 
                    353: 
                    354: 
                    355: /*
                    356: 
                    357:  * if writing to a setuid or setgid file, clear those bits
                    358: 
                    359:  */
                    360: 
                    361:        if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) {
                    362: 
                    363:                xattr.mode &= ~(S_ISUID|S_ISGID);
                    364: 
                    365:                (*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT));
                    366: 
                    367:        }
                    368: 
                    369: /*
                    370: 
                    371:  * If the caller asked for the attributes of the opened file, copy them over.
                    372: 
                    373:  */
                    374: 
                    375:        if (x) *x = xattr;
                    376: 
                    377: 
                    378: 
                    379: /*
                    380: 
                    381:  * So far, so good. Let's get the device driver now, and try to
                    382: 
                    383:  * actually open the file.
                    384: 
                    385:  */
                    386: 
                    387:        dev = (*fc.fs->getdev)(&fc, &devsp);
                    388: 
                    389:        if (!dev) {
                    390: 
1.1.1.2   root      391:                mint_errno = (int)devsp;
1.1       root      392: 
1.1.1.2   root      393:                DEBUG(("do_open(%s): device driver not found",name));
1.1       root      394: 
1.1.1.3   root      395:                release_cookie(&dir);
                    396: 
                    397:                release_cookie(&fc);
                    398: 
1.1       root      399:                return NULL;
                    400: 
                    401:        }
                    402: 
                    403: 
                    404: 
                    405:        if (dev == &fakedev) {          /* fake BIOS devices */
                    406: 
                    407:                f = curproc->handle[devsp];
                    408: 
1.1.1.6 ! root      409:                if (!f || f == (FILEPTR *)1) {
1.1       root      410: 
                    411:                        mint_errno = EIHNDL;
                    412: 
                    413:                        return 0;
                    414: 
                    415:                }
                    416: 
                    417:                f->links++;
                    418: 
1.1.1.3   root      419:                release_cookie(&dir);
                    420: 
                    421:                release_cookie(&fc);
                    422: 
1.1       root      423:                return f;
                    424: 
                    425:        }
                    426: 
1.1.1.2   root      427:        if (0 == (f = new_fileptr())) {
1.1       root      428: 
1.1.1.3   root      429:                release_cookie(&dir);
                    430: 
                    431:                release_cookie(&fc);
                    432: 
1.1       root      433:                mint_errno = ENSMEM;
                    434: 
                    435:                return NULL;
                    436: 
                    437:        }
                    438: 
                    439:        f->links = 1;
                    440: 
                    441:        f->flags = rwmode;
                    442: 
                    443:        f->pos = 0;
                    444: 
                    445:        f->devinfo = devsp;
                    446: 
                    447:        f->fc = fc;
                    448: 
                    449:        f->dev = dev;
                    450: 
1.1.1.3   root      451:        release_cookie(&dir);
                    452: 
1.1       root      453: 
                    454: 
                    455:        r = (*dev->open)(f);
                    456: 
                    457:        if (r < 0) {
                    458: 
1.1.1.2   root      459:                DEBUG(("do_open(%s): device open failed with error %ld",
1.1       root      460: 
1.1.1.2   root      461:                        name, r));
1.1       root      462: 
1.1.1.2   root      463:                mint_errno = (int)r;
1.1       root      464: 
                    465:                f->links = 0;
                    466: 
1.1.1.3   root      467:                release_cookie(&fc);
                    468: 
1.1       root      469:                dispose_fileptr(f);
                    470: 
                    471:                return NULL;
                    472: 
                    473:        }
                    474: 
                    475: 
                    476: 
1.1.1.6 ! root      477:        if (tofreed) {
        !           478: 
        !           479:                tofreed->links = 0;
        !           480: 
        !           481:                free_region(tofreed);
        !           482: 
        !           483:                tofreed = 0;
        !           484: 
        !           485:        }
        !           486: 
        !           487: 
        !           488: 
1.1       root      489: /* special code for opening a tty */
                    490: 
                    491:        if (is_terminal(f)) {
                    492: 
                    493:                extern struct tty default_tty;  /* in tty.c */
                    494: 
                    495: 
                    496: 
                    497:                tty = (struct tty *)f->devinfo;
                    498: 
1.1.1.6 ! root      499:                tty->use_cnt++;
        !           500: 
        !           501:                while (tty->hup_ospeed && !creating) {
1.1       root      502: 
1.1.1.6 ! root      503:                        sleep (IO_Q, (long)&tty->state);
1.1       root      504: 
                    505:                }
                    506: 
1.1.1.6 ! root      507:                /* first open for this device (not counting set_auxhandle)? */
        !           508: 
        !           509:                if ((!tty->pgrp && tty->use_cnt-tty->aux_cnt <= 1) ||
        !           510: 
        !           511:                    tty->use_cnt <= 1) {
        !           512: 
        !           513:                        short s = tty->state & (TS_BLIND|TS_HOLD|TS_HPCL);
        !           514: 
        !           515:                        short u = tty->use_cnt, a = tty->aux_cnt;
        !           516: 
        !           517:                        short r = tty->rsel, w = tty->wsel;
        !           518: 
        !           519:                        *tty = default_tty;
        !           520: 
        !           521:                        if (!creating)
        !           522: 
        !           523:                                tty->state = s;
        !           524: 
        !           525:                        if ((tty->use_cnt = u) > 1 || !creating) {
        !           526: 
        !           527:                                tty->aux_cnt = a;
        !           528: 
        !           529:                                tty->rsel = r, tty->wsel = w;
        !           530: 
        !           531:                        }
        !           532: 
        !           533:                        if (!(f->flags & O_HEAD)) {
        !           534: 
        !           535:                                tty_ioctl(f, TIOCSTART, 0);
        !           536: 
        !           537:                        }
        !           538: 
        !           539:                }
1.1       root      540: 
                    541:        }
                    542: 
                    543:        return f;
                    544: 
                    545: }
                    546: 
                    547: 
                    548: 
1.1.1.6 ! root      549: /* 2500 ms after hangup: close device, ready for use again */
        !           550: 
        !           551: 
        !           552: 
        !           553: static void ARGS_ON_STACK
        !           554: 
        !           555: hangup_done(p, f)
        !           556: 
        !           557:        PROC *p;
        !           558: 
        !           559:        FILEPTR *f;
        !           560: 
        !           561: {
        !           562: 
        !           563:        struct tty *tty = (struct tty *)f->devinfo;
        !           564: 
        !           565: 
        !           566: 
        !           567:        tty->hup_ospeed = 0;
        !           568: 
        !           569:        tty->state &= ~TS_HPCL;
        !           570: 
        !           571:        tty_ioctl(f, TIOCSTART, 0);
        !           572: 
        !           573:        wake (IO_Q, (long)&tty->state);
        !           574: 
        !           575:        tty->state &= ~TS_HPCL;
        !           576: 
        !           577:        if (--f->links <= 0) {
        !           578: 
        !           579:                if (--tty->use_cnt-tty->aux_cnt <= 0)
        !           580: 
        !           581:                        tty->pgrp = 0;
        !           582: 
        !           583:                if (tty->use_cnt <= 0 && tty->xkey) {
        !           584: 
        !           585:                        kfree(tty->xkey);
        !           586: 
        !           587:                        tty->xkey = 0;
        !           588: 
        !           589:                }
        !           590: 
        !           591:        }
        !           592: 
        !           593: 
        !           594: 
        !           595: /* hack(?): the closing process may no longer exist, use pid 0 */
        !           596: 
        !           597:        if ((*f->dev->close)(f, 0)) {
        !           598: 
        !           599:                DEBUG(("hangup: device close failed"));
        !           600: 
        !           601:        }
        !           602: 
        !           603:        if (f->links <= 0) {
        !           604: 
        !           605:                release_cookie(&f->fc);
        !           606: 
        !           607:                dispose_fileptr(f);
        !           608: 
        !           609:        }
        !           610: 
        !           611: }
        !           612: 
        !           613: 
        !           614: 
        !           615: /* 500 ms after hangup: restore DTR */
        !           616: 
        !           617: 
        !           618: 
        !           619: static void ARGS_ON_STACK
        !           620: 
        !           621: hangup_b1(p, f)
        !           622: 
        !           623:        PROC *p;
        !           624: 
        !           625:        FILEPTR *f;
        !           626: 
        !           627: {
        !           628: 
        !           629:        struct tty *tty = (struct tty *)f->devinfo;
        !           630: 
        !           631:        TIMEOUT *t = addroottimeout(2000L, (void (*)P_((PROC *)))hangup_done, 0);
        !           632: 
        !           633: 
        !           634: 
        !           635:        if (tty->hup_ospeed > 0)
        !           636: 
        !           637:                (*f->dev->ioctl)(f, TIOCOBAUD, &tty->hup_ospeed);
        !           638: 
        !           639:        if (!t) {
        !           640: 
        !           641:                /* should never happen, but... */
        !           642: 
        !           643:                hangup_done(p, f);
        !           644: 
        !           645:                return;
        !           646: 
        !           647:        }
        !           648: 
        !           649:        t->arg = (long)f;
        !           650: 
        !           651:        tty->hup_ospeed = -1;
        !           652: 
        !           653: }
        !           654: 
        !           655: 
        !           656: 
1.1       root      657: /*
                    658: 
                    659:  * helper function for do_close: this closes the indicated file pointer which
                    660: 
                    661:  * is assumed to be associated with process p. The extra parameter is necessary
                    662: 
                    663:  * because f_midipipe mucks with file pointers of other processes, so
                    664: 
                    665:  * sometimes p != curproc.
                    666: 
                    667:  *
                    668: 
                    669:  * Note that the function changedrv() in filesys.c can call this routine.
                    670: 
                    671:  * in that case, f->dev will be 0 to represent an invalid device, and
                    672: 
                    673:  * we cannot call the device close routine.
                    674: 
                    675:  */
                    676: 
                    677: 
                    678: 
                    679: long
                    680: 
                    681: do_pclose(p, f)
                    682: 
                    683:        PROC *p;
                    684: 
                    685:        FILEPTR *f;
                    686: 
                    687: {
                    688: 
                    689:        long r = 0;
                    690: 
                    691: 
                    692: 
                    693:        if (!f) return EIHNDL;
                    694: 
1.1.1.6 ! root      695:        if (f == (FILEPTR *)1)
        !           696: 
        !           697:                return 0;
        !           698: 
1.1       root      699: 
                    700: 
                    701: /* if this file is "select'd" by this process, unselect it
                    702: 
1.1.1.2   root      703:  * (this is just in case we were killed by a signal)
1.1       root      704: 
                    705:  */
                    706: 
                    707: 
                    708: 
                    709: /* BUG? Feature? If media change is detected while we're doing the select,
                    710: 
                    711:  * we'll never unselect (since f->dev is set to NULL by changedrv())
                    712: 
                    713:  */
                    714: 
                    715:        if (f->dev) {
                    716: 
                    717:                (*f->dev->unselect)(f, (long)p, O_RDONLY);
                    718: 
                    719:                (*f->dev->unselect)(f, (long)p, O_WRONLY);
                    720: 
1.1.1.6 ! root      721:                (*f->dev->unselect)(f, (long)p, O_RDWR);
        !           722: 
        !           723:                wake (SELECT_Q, (long)&select_coll);
        !           724: 
1.1       root      725:        }
                    726: 
                    727: 
                    728: 
                    729:        f->links--;
                    730: 
                    731: 
                    732: 
                    733: /* TTY manipulation must be done *before* calling the device close routine,
                    734: 
                    735:  * since afterwards the TTY structure may no longer exist
                    736: 
                    737:  */
                    738: 
                    739:        if (is_terminal(f) && f->links <= 0) {
                    740: 
                    741:                struct tty *tty = (struct tty *)f->devinfo;
                    742: 
1.1.1.6 ! root      743:                TIMEOUT *t;
1.1       root      744: 
1.1.1.6 ! root      745:                long ospeed = -1L, z = 0;
1.1.1.3   root      746: 
1.1.1.6 ! root      747: /* for HPCL ignore ttys open as /dev/aux, else they would never hang up */
        !           748: 
        !           749:                if (tty->use_cnt-tty->aux_cnt <= 1) {
        !           750: 
        !           751:                        if ((tty->state & TS_HPCL) && !tty->hup_ospeed &&
        !           752: 
        !           753:                            !(f->flags & O_HEAD) &&
        !           754: 
        !           755:                            (*f->dev->ioctl)(f, TIOCOBAUD, &ospeed) >= 0 &&
        !           756: 
        !           757:                            (t = addroottimeout(500L, (void (*)P_((PROC *)))hangup_b1, 0))) {
        !           758: 
        !           759:                        /* keep device open until hangup complete */
        !           760: 
        !           761:                                f->links = 1;
        !           762: 
        !           763:                                ++tty->use_cnt;
        !           764: 
        !           765:                        /* pass f to timeout function */
        !           766: 
        !           767:                                t->arg = (long)f;
        !           768: 
        !           769:                                (*f->dev->ioctl)(f, TIOCCBRK, 0);
        !           770: 
        !           771:                        /* flag: hanging up */
        !           772: 
        !           773:                                tty->hup_ospeed = -1;
        !           774: 
        !           775:                        /* stop output, flush buffers, drop DTR... */
        !           776: 
        !           777:                                tty_ioctl(f, TIOCSTOP, 0);
        !           778: 
        !           779:                                tty_ioctl(f, TIOCFLUSH, 0);
        !           780: 
        !           781:                                if (ospeed > 0) {
        !           782: 
        !           783:                                        tty->hup_ospeed = ospeed;
        !           784: 
        !           785:                                        (*f->dev->ioctl)(f, TIOCOBAUD, &z);
        !           786: 
        !           787:                                }
        !           788: 
        !           789:                        } else {
        !           790: 
        !           791:                                tty->pgrp = 0;
        !           792: 
        !           793:                        }
        !           794: 
        !           795:                }
        !           796: 
        !           797:                tty->use_cnt--;
1.1.1.3   root      798: 
1.1       root      799:                if (tty->use_cnt <= 0 && tty->xkey) {
                    800: 
                    801:                        kfree(tty->xkey);
                    802: 
                    803:                        tty->xkey = 0;
                    804: 
                    805:                }
                    806: 
                    807:        }
                    808: 
                    809: 
                    810: 
                    811:        if (f->dev) {
                    812: 
                    813:                r = (*f->dev->close)(f, p->pid);
                    814: 
                    815:                if (r) {
                    816: 
1.1.1.2   root      817:                        DEBUG(("close: device close failed"));
1.1       root      818: 
                    819:                }
                    820: 
                    821:        }
                    822: 
                    823:        if (f->links <= 0) {
                    824: 
1.1.1.3   root      825:                release_cookie(&f->fc);
                    826: 
1.1       root      827:                dispose_fileptr(f);
                    828: 
                    829:        }
                    830: 
                    831:        return  r;
                    832: 
                    833: }
                    834: 
                    835: 
                    836: 
                    837: long
                    838: 
                    839: do_close(f)
                    840: 
                    841:        FILEPTR *f;
                    842: 
                    843: {
                    844: 
                    845:        return do_pclose(curproc, f);
                    846: 
                    847: }
                    848: 
                    849: 
                    850: 
1.1.1.2   root      851: long ARGS_ON_STACK
1.1       root      852: 
                    853: f_open(name, mode)
                    854: 
                    855:        const char *name;
                    856: 
                    857:        int mode;
                    858: 
                    859: {
                    860: 
                    861:        int i;
                    862: 
                    863:        FILEPTR *f;
                    864: 
                    865:        PROC *proc;
                    866: 
                    867: 
                    868: 
1.1.1.2   root      869:        TRACE(("Fopen(%s, %x)", name, mode));
1.1       root      870: 
                    871: #if O_GLOBAL
                    872: 
                    873:        if (mode & O_GLOBAL) {
                    874: 
                    875:            /* oh, boy! user wants us to open a global handle! */
                    876: 
                    877:            proc = rootproc;
                    878: 
                    879:        }
                    880: 
                    881:        else
                    882: 
                    883: #endif
                    884: 
                    885:            proc = curproc;
                    886: 
                    887: 
                    888: 
                    889:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
                    890: 
                    891:                if (!proc->handle[i])
                    892: 
                    893:                        goto found_for_open;
                    894: 
                    895:        }
                    896: 
1.1.1.2   root      897:        DEBUG(("Fopen(%s): process out of handles",name));
1.1       root      898: 
                    899:        return ENHNDL;          /* no more handles */
                    900: 
                    901: 
                    902: 
                    903: found_for_open:
                    904: 
                    905:        mode &= O_USER;         /* make sure the mode is legal */
                    906: 
                    907: 
                    908: 
                    909: /* note: file mode 3 is reserved for the kernel; for users, transmogrify it
                    910: 
                    911:  * into O_RDWR (mode 2)
                    912: 
                    913:  */
                    914: 
                    915:        if ( (mode & O_RWMODE) == O_EXEC ) {
                    916: 
                    917:                mode = (mode & ~O_RWMODE) | O_RDWR;
                    918: 
                    919:        }
                    920: 
                    921: 
                    922: 
1.1.1.5   root      923:        proc->handle[i] = (FILEPTR *)1; /* reserve this handle */
1.1       root      924: 
1.1.1.5   root      925:        f = do_open(name, mode, 0, (XATTR *)0);
1.1       root      926: 
1.1.1.5   root      927:        proc->handle[i] = (FILEPTR *)0;
1.1       root      928: 
                    929: 
                    930: 
                    931:        if (!f) {
                    932: 
                    933:                return mint_errno;
                    934: 
                    935:        }
                    936: 
                    937:        proc->handle[i] = f;
                    938: 
                    939: /* default is to close non-standard files on exec */
                    940: 
                    941:        proc->fdflags[i] = FD_CLOEXEC;
                    942: 
                    943: 
                    944: 
                    945: #if O_GLOBAL
                    946: 
                    947:        if (proc != curproc) {
                    948: 
                    949:            /* we just opened a global handle */
                    950: 
                    951:            i += 100;
                    952: 
                    953:        }
                    954: 
                    955: #endif
                    956: 
                    957: 
                    958: 
1.1.1.2   root      959:        TRACE(("Fopen: returning %d", i));
1.1       root      960: 
                    961:        return i;
                    962: 
                    963: }
                    964: 
                    965: 
                    966: 
1.1.1.2   root      967: long ARGS_ON_STACK
1.1       root      968: 
                    969: f_create(name, attrib)
                    970: 
                    971:        const char *name;
                    972: 
                    973:        int attrib;
                    974: 
                    975: {
                    976: 
                    977:        fcookie dir;
                    978: 
                    979:        int i;
                    980: 
                    981:        FILEPTR *f;
                    982: 
                    983:        long r;
                    984: 
                    985:        PROC *proc;
                    986: 
                    987:        int offset = 0;
                    988: 
1.1.1.4   root      989:        char temp1[PATH_MAX];
                    990: 
1.1       root      991: 
                    992: 
1.1.1.2   root      993:        TRACE(("Fcreate(%s, %x)", name, attrib));
1.1       root      994: 
                    995: #if O_GLOBAL
                    996: 
                    997:        if (attrib & O_GLOBAL) {
                    998: 
                    999:                proc = rootproc;
                   1000: 
                   1001:                offset = 100;
                   1002: 
                   1003:                attrib &= ~O_GLOBAL;
                   1004: 
                   1005:        }
                   1006: 
                   1007:        else
                   1008: 
                   1009: #endif
                   1010: 
                   1011:                proc = curproc;
                   1012: 
                   1013: 
                   1014: 
                   1015:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
                   1016: 
                   1017:                if (!proc->handle[i])
                   1018: 
                   1019:                        goto found_for_create;
                   1020: 
                   1021:        }
                   1022: 
1.1.1.2   root     1023:        DEBUG(("Fcreate(%s): process out of handles",name));
1.1       root     1024: 
                   1025:        return ENHNDL;          /* no more handles */
                   1026: 
                   1027: 
                   1028: 
                   1029: found_for_create:
                   1030: 
                   1031:        if (attrib == FA_LABEL) {
                   1032: 
                   1033:                r = path2cookie(name, temp1, &dir);
                   1034: 
                   1035:                if (r) return r;
                   1036: 
                   1037:                r = (*dir.fs->writelabel)(&dir, temp1);
                   1038: 
1.1.1.3   root     1039:                release_cookie(&dir);
                   1040: 
1.1       root     1041:                if (r) return r;
                   1042: 
                   1043: /*
                   1044: 
                   1045:  * just in case the caller tries to do something with this handle,
                   1046: 
                   1047:  * make it point to u:\dev\null
                   1048: 
                   1049:  */
                   1050: 
                   1051:                f = do_open("u:\\dev\\null", O_RDWR|O_CREAT|O_TRUNC, 0,
                   1052: 
                   1053:                             (XATTR *)0);
                   1054: 
                   1055:                proc->handle[i] = f;
                   1056: 
1.1.1.4   root     1057:                proc->fdflags[i] = FD_CLOEXEC;
                   1058: 
1.1       root     1059:                return i+offset;
                   1060: 
                   1061:        }
                   1062: 
                   1063:        if (attrib & (FA_LABEL|FA_DIR)) {
                   1064: 
1.1.1.2   root     1065:                DEBUG(("Fcreate(%s,%x): illegal attributes",name,attrib));
1.1       root     1066: 
                   1067:                return EACCDN;
                   1068: 
                   1069:        }
                   1070: 
                   1071: 
                   1072: 
1.1.1.5   root     1073:        proc->handle[i] = (FILEPTR *)1;         /* reserve this handle */
                   1074: 
1.1       root     1075:        f = do_open(name, O_RDWR|O_CREAT|O_TRUNC, attrib, (XATTR *)0);
                   1076: 
1.1.1.5   root     1077:        proc->handle[i] = (FILEPTR *)0;
                   1078: 
1.1       root     1079: 
                   1080: 
                   1081:        if (!f) {
                   1082: 
1.1.1.2   root     1083:                DEBUG(("Fcreate(%s) failed, error %d", name, mint_errno));
1.1       root     1084: 
                   1085:                return mint_errno;
                   1086: 
                   1087:        }
                   1088: 
                   1089:        proc->handle[i] = f;
                   1090: 
1.1.1.4   root     1091:        proc->fdflags[i] = FD_CLOEXEC;
                   1092: 
1.1       root     1093:        i += offset;
                   1094: 
1.1.1.2   root     1095:        TRACE(("Fcreate: returning %d", i));
1.1       root     1096: 
                   1097:        return i;
                   1098: 
                   1099: }
                   1100: 
                   1101: 
                   1102: 
1.1.1.2   root     1103: long ARGS_ON_STACK
1.1       root     1104: 
                   1105: f_close(fh)
                   1106: 
                   1107:        int fh;
                   1108: 
                   1109: {
                   1110: 
                   1111:        FILEPTR *f;
                   1112: 
                   1113:        long r;
                   1114: 
                   1115:        PROC *proc;
                   1116: 
                   1117: 
                   1118: 
1.1.1.2   root     1119:        TRACE(("Fclose: %d", fh));
1.1       root     1120: 
                   1121: #if O_GLOBAL
                   1122: 
                   1123:        if (fh >= 100) {
                   1124: 
                   1125:            fh -= 100;
                   1126: 
                   1127:            proc = rootproc;
                   1128: 
                   1129:        }
                   1130: 
                   1131:        else
                   1132: 
                   1133: #endif
                   1134: 
                   1135:            proc = curproc;
                   1136: 
                   1137: 
                   1138: 
1.1.1.2   root     1139:        if (fh < 0 || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1140: 
                   1141:                return EIHNDL;
                   1142: 
                   1143:        }
                   1144: 
1.1.1.3   root     1145:        r = do_pclose(proc, f);
1.1       root     1146: 
                   1147: 
                   1148: 
                   1149: /* standard handles should be restored to default values */
                   1150: 
                   1151: /* do this for TOS domain only! */
                   1152: 
                   1153:        if (proc->domain == DOM_TOS) {
                   1154: 
                   1155:                if (fh == 0 || fh == 1)
                   1156: 
                   1157:                        f = proc->handle[-1];
                   1158: 
                   1159:                else if (fh == 2 || fh == 3)
                   1160: 
                   1161:                        f = proc->handle[-fh];
                   1162: 
                   1163:                else
                   1164: 
                   1165:                        f = 0;
                   1166: 
                   1167:        } else
                   1168: 
                   1169:                f = 0;
                   1170: 
                   1171: 
                   1172: 
1.1.1.4   root     1173:        if (f) {
                   1174: 
                   1175:                f->links++;
                   1176: 
                   1177:                proc->fdflags[fh] = 0;
                   1178: 
                   1179:        }
1.1       root     1180: 
                   1181:        proc->handle[fh] = f;
                   1182: 
                   1183:        return r;
                   1184: 
                   1185: }
                   1186: 
                   1187: 
                   1188: 
1.1.1.2   root     1189: long ARGS_ON_STACK
1.1       root     1190: 
                   1191: f_read(fh, count, buf)
                   1192: 
                   1193:        int fh;
                   1194: 
                   1195:        long count;
                   1196: 
                   1197:        char *buf;
                   1198: 
                   1199: {
                   1200: 
                   1201:        FILEPTR *f;
                   1202: 
                   1203: 
                   1204: 
                   1205:        PROC *proc;
                   1206: 
                   1207: 
                   1208: 
                   1209: #if O_GLOBAL
                   1210: 
                   1211:        if (fh >= 100) {
                   1212: 
                   1213:            fh -= 100;
                   1214: 
                   1215:            proc = rootproc;
                   1216: 
                   1217:        }
                   1218: 
                   1219:        else
                   1220: 
                   1221: #endif
                   1222: 
                   1223:            proc = curproc;
                   1224: 
                   1225: 
                   1226: 
1.1.1.2   root     1227:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1228: 
1.1.1.2   root     1229:                DEBUG(("Fread: invalid handle: %d", fh));
1.1       root     1230: 
                   1231:                return EIHNDL;
                   1232: 
                   1233:        }
                   1234: 
                   1235:        if ( (f->flags & O_RWMODE) == O_WRONLY ) {
                   1236: 
1.1.1.2   root     1237:                DEBUG(("Fread: read on a write-only handle"));
1.1       root     1238: 
                   1239:                return EACCDN;
                   1240: 
                   1241:        }
                   1242: 
                   1243:        if (is_terminal(f))
                   1244: 
                   1245:                return tty_read(f, buf, count);
                   1246: 
                   1247: 
                   1248: 
1.1.1.3   root     1249:        TRACELOW(("Fread: %ld bytes from handle %d to %lx", count, fh, buf));
1.1       root     1250: 
                   1251:        return (*f->dev->read)(f, buf, count);
                   1252: 
                   1253: }
                   1254: 
                   1255: 
                   1256: 
1.1.1.2   root     1257: long ARGS_ON_STACK
1.1       root     1258: 
                   1259: f_write(fh, count, buf)
                   1260: 
                   1261:        int fh;
                   1262: 
                   1263:        long count;
                   1264: 
                   1265:        const char *buf;
                   1266: 
                   1267: {
                   1268: 
                   1269:        FILEPTR *f;
                   1270: 
                   1271:        PROC *proc;
                   1272: 
                   1273:        long r;
                   1274: 
                   1275: 
                   1276: 
                   1277: #if O_GLOBAL
                   1278: 
                   1279:        if (fh >= 100) {
                   1280: 
                   1281:            fh -= 100;
                   1282: 
                   1283:            proc = rootproc;
                   1284: 
                   1285:        }
                   1286: 
                   1287:        else
                   1288: 
                   1289: #endif
                   1290: 
                   1291:            proc = curproc;
                   1292: 
                   1293: 
                   1294: 
1.1.1.2   root     1295:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1296: 
1.1.1.2   root     1297:                DEBUG(("Fwrite: bad handle: %d", fh));
1.1       root     1298: 
                   1299:                return EIHNDL;
                   1300: 
                   1301:        }
                   1302: 
                   1303:        if ( (f->flags & O_RWMODE) == O_RDONLY ) {
                   1304: 
1.1.1.2   root     1305:                DEBUG(("Fwrite: write on a read-only handle"));
1.1       root     1306: 
                   1307:                return EACCDN;
                   1308: 
                   1309:        }
                   1310: 
                   1311:        if (is_terminal(f))
                   1312: 
                   1313:                return tty_write(f, buf, count);
                   1314: 
                   1315: 
                   1316: 
                   1317:        /* it would be faster to do this in the device driver, but this
                   1318: 
                   1319:         * way the drivers are easier to write
                   1320: 
                   1321:         */
                   1322: 
1.1.1.3   root     1323:        if (f->flags & O_APPEND) {
1.1       root     1324: 
                   1325:                r = (*f->dev->lseek)(f, 0L, SEEK_END);
                   1326: 
1.1.1.3   root     1327:                /* ignore errors from unseekable files (e.g. pipes) */
                   1328: 
                   1329:                if (r == EACCDN)
                   1330: 
                   1331:                        r = 0;
                   1332: 
                   1333:        } else
1.1       root     1334: 
                   1335:                r = 0;
                   1336: 
                   1337:        if (r >= 0) {
                   1338: 
1.1.1.3   root     1339:                TRACELOW(("Fwrite: %ld bytes to handle %d", count, fh));
1.1       root     1340: 
                   1341:                r = (*f->dev->write)(f, buf, count);
                   1342: 
                   1343:        }
                   1344: 
                   1345:        if (r < 0) {
                   1346: 
1.1.1.2   root     1347:                DEBUG(("Fwrite: error %ld", r));
1.1       root     1348: 
                   1349:        }
                   1350: 
                   1351:        return r;
                   1352: 
                   1353: }
                   1354: 
                   1355: 
                   1356: 
1.1.1.2   root     1357: long ARGS_ON_STACK
1.1       root     1358: 
                   1359: f_seek(place, fh, how)
                   1360: 
                   1361:        long place;
                   1362: 
                   1363:        int fh;
                   1364: 
                   1365:        int how;
                   1366: 
                   1367: {
                   1368: 
                   1369:        FILEPTR *f;
                   1370: 
                   1371:        PROC *proc;
                   1372: 
                   1373: 
                   1374: 
1.1.1.2   root     1375:        TRACE(("Fseek(%ld, %d) on handle %d", place, how, fh));
1.1       root     1376: 
                   1377: #if O_GLOBAL
                   1378: 
                   1379:        if (fh >= 100) {
                   1380: 
                   1381:            fh -= 100;
                   1382: 
                   1383:            proc = rootproc;
                   1384: 
                   1385:        }
                   1386: 
                   1387:        else
                   1388: 
                   1389: #endif
                   1390: 
                   1391:            proc = curproc;
                   1392: 
                   1393: 
                   1394: 
1.1.1.2   root     1395:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1396: 
1.1.1.2   root     1397:                DEBUG(("Fseek: bad handle: %d", fh));
1.1       root     1398: 
                   1399:                return EIHNDL;
                   1400: 
                   1401:        }
                   1402: 
                   1403:        if (is_terminal(f)) {
                   1404: 
                   1405:                return 0;
                   1406: 
                   1407:        }
                   1408: 
                   1409:        return (*f->dev->lseek)(f, place, how);
                   1410: 
                   1411: }
                   1412: 
                   1413: 
                   1414: 
                   1415: /* duplicate file pointer fh; returns a new file pointer >= min, if
                   1416: 
                   1417:    one exists, or ENHNDL if not. called by f_dup and f_cntl
                   1418: 
                   1419:  */
                   1420: 
                   1421: 
                   1422: 
                   1423: static long do_dup(fh, min)
                   1424: 
                   1425:        int fh, min;
                   1426: 
                   1427: {
                   1428: 
                   1429:        FILEPTR *f;
                   1430: 
                   1431:        int i;
                   1432: 
                   1433:        PROC *proc;
                   1434: 
                   1435: 
                   1436: 
                   1437:        for (i = min; i < MAX_OPEN; i++) {
                   1438: 
                   1439:                if (!curproc->handle[i])
                   1440: 
                   1441:                        goto found;
                   1442: 
                   1443:        }
                   1444: 
                   1445:        return ENHNDL;          /* no more handles */
                   1446: 
                   1447: found:
                   1448: 
                   1449: #if O_GLOBAL
                   1450: 
                   1451:        if (fh >= 100) {
                   1452: 
                   1453:            fh -= 100;
                   1454: 
                   1455:            proc = rootproc;
                   1456: 
                   1457:        } else
                   1458: 
                   1459: #endif
                   1460: 
                   1461:            proc = curproc;
                   1462: 
                   1463: 
                   1464: 
1.1.1.2   root     1465:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh]))
1.1       root     1466: 
                   1467:                return EIHNDL;
                   1468: 
                   1469: 
                   1470: 
                   1471:        curproc->handle[i] = f;
                   1472: 
                   1473: 
                   1474: 
                   1475: /* set default file descriptor flags */
                   1476: 
                   1477:        if (i >= 0) {
                   1478: 
                   1479:                if (i >= MIN_OPEN)
                   1480: 
                   1481:                        curproc->fdflags[i] = FD_CLOEXEC;
                   1482: 
                   1483:                else
                   1484: 
                   1485:                        curproc->fdflags[i] = 0;
                   1486: 
                   1487:        }
                   1488: 
                   1489:        f->links++;
                   1490: 
                   1491:        return i;
                   1492: 
                   1493: }
                   1494: 
                   1495: 
                   1496: 
1.1.1.2   root     1497: long ARGS_ON_STACK
1.1       root     1498: 
                   1499: f_dup(fh)
                   1500: 
                   1501:        int fh;
                   1502: 
                   1503: {
                   1504: 
                   1505:        long r;
                   1506: 
                   1507:        r = do_dup(fh, MIN_OPEN);
                   1508: 
1.1.1.2   root     1509:        TRACE(("Fdup(%d) -> %ld", fh, r));
1.1       root     1510: 
                   1511:        return r;
                   1512: 
                   1513: }
                   1514: 
                   1515: 
                   1516: 
1.1.1.2   root     1517: long ARGS_ON_STACK
1.1       root     1518: 
                   1519: f_force(newh, oldh)
                   1520: 
                   1521:        int newh;
                   1522: 
                   1523:        int oldh;
                   1524: 
                   1525: {
                   1526: 
                   1527:        FILEPTR *f;
                   1528: 
                   1529:        PROC *proc;
                   1530: 
                   1531: 
                   1532: 
1.1.1.2   root     1533:        TRACE(("Fforce(%d, %d)", newh, oldh));
1.1       root     1534: 
                   1535: 
                   1536: 
                   1537: #if O_GLOBAL
                   1538: 
                   1539:        if (oldh >= 100) {
                   1540: 
                   1541:            oldh -= 100;
                   1542: 
                   1543:            proc = rootproc;
                   1544: 
                   1545:        } else
                   1546: 
                   1547: #endif
                   1548: 
                   1549:            proc = curproc;
                   1550: 
                   1551: 
                   1552: 
                   1553:        if (oldh < MIN_HANDLE || oldh >= MAX_OPEN ||
                   1554: 
1.1.1.2   root     1555:            0 == (f = proc->handle[oldh])) {
1.1       root     1556: 
1.1.1.2   root     1557:                DEBUG(("Fforce: old handle invalid"));
1.1       root     1558: 
                   1559:                return EIHNDL;
                   1560: 
                   1561:        }
                   1562: 
                   1563: 
                   1564: 
                   1565:        if (newh < MIN_HANDLE || newh >= MAX_OPEN) {
                   1566: 
1.1.1.2   root     1567:                DEBUG(("Fforce: new handle out of range"));
1.1       root     1568: 
                   1569:                return EIHNDL;
                   1570: 
                   1571:        }
                   1572: 
                   1573: 
                   1574: 
                   1575:        (void)do_close(curproc->handle[newh]);
                   1576: 
                   1577:        curproc->handle[newh] = f;
                   1578: 
1.1.1.4   root     1579:        /* set default file descriptor flags */
                   1580: 
                   1581:        if (newh >= 0)
                   1582: 
                   1583:                curproc->fdflags[newh] = (newh >= MIN_OPEN) ? FD_CLOEXEC : 0;
                   1584: 
1.1       root     1585:        f->links++;
                   1586: 
                   1587: /*
                   1588: 
                   1589:  * special: for a tty, if this is becoming a control terminal and the
                   1590: 
                   1591:  * tty doesn't have a pgrp yet, make it have the pgrp of the process
                   1592: 
                   1593:  * doing the Fforce
                   1594: 
                   1595:  */
                   1596: 
1.1.1.6 ! root     1597:        if (is_terminal(f) && newh == -1 && !(f->flags & O_HEAD)) {
1.1       root     1598: 
                   1599:                struct tty *tty = (struct tty *)f->devinfo;
                   1600: 
                   1601: 
                   1602: 
1.1.1.6 ! root     1603:                if (!tty->pgrp) {
1.1       root     1604: 
                   1605:                        tty->pgrp = curproc->pgrp;
                   1606: 
1.1.1.6 ! root     1607: 
        !          1608: 
        !          1609:                        if (!(f->flags & O_NDELAY) && (tty->state & TS_BLIND))
        !          1610: 
        !          1611:                                (*f->dev->ioctl)(f, TIOCWONLINE, 0);
        !          1612: 
        !          1613:                }
        !          1614: 
1.1       root     1615:        }
                   1616: 
1.1.1.4   root     1617:        return 0;
1.1       root     1618: 
                   1619: }
                   1620: 
                   1621: 
                   1622: 
1.1.1.2   root     1623: long ARGS_ON_STACK
1.1       root     1624: 
                   1625: f_datime(timeptr, fh, rwflag)
                   1626: 
                   1627:        short *timeptr;
                   1628: 
                   1629:        int fh;
                   1630: 
                   1631:        int rwflag;
                   1632: 
                   1633: {
                   1634: 
                   1635:        FILEPTR *f;
                   1636: 
                   1637:        PROC *proc;
                   1638: 
                   1639: 
                   1640: 
1.1.1.2   root     1641:        TRACE(("Fdatime(%d)", fh));
1.1       root     1642: 
                   1643: #if O_GLOBAL
                   1644: 
                   1645:        if (fh >= 100) {
                   1646: 
                   1647:            fh -= 100;
                   1648: 
                   1649:            proc = rootproc;
                   1650: 
                   1651:        }
                   1652: 
                   1653:        else
                   1654: 
                   1655: #endif
                   1656: 
                   1657:            proc = curproc;
                   1658: 
                   1659: 
                   1660: 
1.1.1.2   root     1661:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1662: 
1.1.1.2   root     1663:                DEBUG(("Fdatime: invalid handle"));
1.1       root     1664: 
                   1665:                return EIHNDL;
                   1666: 
                   1667:        }
                   1668: 
                   1669: 
                   1670: 
                   1671: /* some programs use Fdatime to test for TTY devices */
                   1672: 
                   1673:        if (is_terminal(f))
                   1674: 
                   1675:                return EACCDN;
                   1676: 
                   1677: 
                   1678: 
                   1679:        return (*f->dev->datime)(f, timeptr, rwflag);
                   1680: 
                   1681: }
                   1682: 
                   1683: 
                   1684: 
1.1.1.2   root     1685: long ARGS_ON_STACK
1.1       root     1686: 
                   1687: f_lock(fh, mode, start, length)
                   1688: 
                   1689:        int fh, mode;
                   1690: 
                   1691:        long start, length;
                   1692: 
                   1693: {
                   1694: 
                   1695:        FILEPTR *f;
                   1696: 
                   1697:        struct flock lock;
                   1698: 
                   1699:        PROC *proc;
                   1700: 
                   1701: 
                   1702: 
                   1703: #if O_GLOBAL
                   1704: 
                   1705:        if (fh >= 100) {
                   1706: 
                   1707:            fh -= 100;
                   1708: 
                   1709:            proc = rootproc;
                   1710: 
                   1711:        }
                   1712: 
                   1713:        else
                   1714: 
                   1715: #endif
                   1716: 
                   1717:            proc = curproc;
                   1718: 
                   1719: 
                   1720: 
1.1.1.2   root     1721:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1       root     1722: 
1.1.1.2   root     1723:                DEBUG(("Flock: invalid handle"));
1.1       root     1724: 
                   1725:                return EIHNDL;
                   1726: 
                   1727:        }
                   1728: 
1.1.1.2   root     1729:        TRACE(("Flock(%d,%d,%ld,%ld)", fh, mode, start, length));
1.1       root     1730: 
                   1731:        lock.l_whence = SEEK_SET;
                   1732: 
                   1733:        lock.l_start = start;
                   1734: 
                   1735:        lock.l_len = length;
                   1736: 
                   1737: 
                   1738: 
                   1739:        if (mode == 0)          /* create a lock */
                   1740: 
                   1741:                lock.l_type = F_WRLCK;
                   1742: 
                   1743:        else if (mode == 1)     /* unlock region */
                   1744: 
                   1745:                lock.l_type = F_UNLCK;
                   1746: 
                   1747:        else
                   1748: 
                   1749:                return EINVFN;
                   1750: 
                   1751: 
                   1752: 
                   1753:        return (*f->dev->ioctl)(f, F_SETLK, &lock);
                   1754: 
                   1755: }
                   1756: 
                   1757: 
                   1758: 
                   1759: /*
                   1760: 
                   1761:  * extensions to GEMDOS:
                   1762: 
                   1763:  */
                   1764: 
                   1765: 
                   1766: 
                   1767: /*
                   1768: 
                   1769:  * Fpipe(int *handles): opens a pipe. if successful, returns 0, and
                   1770: 
                   1771:  * sets handles[0] to a file descriptor for the read end of the pipe
                   1772: 
                   1773:  * and handles[1] to one for the write end.
                   1774: 
                   1775:  */
                   1776: 
                   1777: 
                   1778: 
1.1.1.2   root     1779: long ARGS_ON_STACK
1.1       root     1780: 
                   1781: f_pipe(usrh)
                   1782: 
                   1783:        short *usrh;
                   1784: 
                   1785: {
                   1786: 
                   1787:        FILEPTR *in, *out;
                   1788: 
                   1789:        static int pipeno = 0;
                   1790: 
                   1791:        int i, j;
                   1792: 
                   1793:        char pipename[32]; /* MAGIC: 32 >= strlen "u:\pipe\sys$pipe.000\0" */
                   1794: 
                   1795: 
                   1796: 
1.1.1.2   root     1797:        TRACE(("Fpipe"));
1.1       root     1798: 
                   1799: 
                   1800: 
                   1801: /* BUG: more than 999 open pipes hangs the system */
                   1802: 
                   1803:        do {
                   1804: 
                   1805:                ksprintf(pipename, "u:\\pipe\\sys$pipe.%03d", pipeno);
                   1806: 
                   1807:                pipeno++; if (pipeno > 999) pipeno = 0;
                   1808: 
1.1.1.2   root     1809:                out = do_open(pipename, O_WRONLY|O_CREAT|O_EXCL, FA_RDONLY|FA_HIDDEN|FA_CHANGED,
                   1810: 
                   1811:                                 (XATTR *)0);
1.1       root     1812: 
                   1813:                        /* read-only attribute means unidirectional fifo */
                   1814: 
                   1815:                        /* hidden attribute means check for broken pipes */
                   1816: 
1.1.1.2   root     1817:                        /* changed attribute means act like Unix fifos */
                   1818: 
1.1       root     1819:        } while (out == 0 && mint_errno == EACCDN);
                   1820: 
                   1821: 
                   1822: 
                   1823:        if (!out) {
                   1824: 
1.1.1.2   root     1825:                DEBUG(("Fpipe: error %d", mint_errno));
1.1       root     1826: 
                   1827:                return mint_errno;
                   1828: 
                   1829:        }
                   1830: 
                   1831: 
                   1832: 
                   1833:        in = do_open(pipename, O_RDONLY, 0, (XATTR *)0);
                   1834: 
                   1835:        if (!in) {
                   1836: 
1.1.1.2   root     1837:                DEBUG(("Fpipe: in side of pipe not opened (error %d)",
1.1       root     1838: 
1.1.1.2   root     1839:                        mint_errno));
1.1       root     1840: 
                   1841:                (void)do_close(out);
                   1842: 
                   1843:                return mint_errno;
                   1844: 
                   1845:        }
                   1846: 
                   1847: 
                   1848: 
                   1849:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
                   1850: 
                   1851:                if (curproc->handle[i] == 0)
                   1852: 
                   1853:                        break;
                   1854: 
                   1855:        }
                   1856: 
                   1857: 
                   1858: 
                   1859:        for (j = i+1; j < MAX_OPEN; j++) {
                   1860: 
                   1861:                if (curproc->handle[j] == 0)
                   1862: 
                   1863:                        break;
                   1864: 
                   1865:        }
                   1866: 
                   1867: 
                   1868: 
                   1869:        if (j >= MAX_OPEN) {
                   1870: 
1.1.1.2   root     1871:                DEBUG(("Fpipe: not enough handles left"));
1.1       root     1872: 
                   1873:                (void) do_close(in);
                   1874: 
                   1875:                (void) do_close(out);
                   1876: 
                   1877:                return ENHNDL;
                   1878: 
                   1879:        }
                   1880: 
                   1881:        curproc->handle[i] = in; curproc->handle[j] = out;
                   1882: 
                   1883: /* leave pipes open across Pexec */
                   1884: 
                   1885:        curproc->fdflags[i] = 0;
                   1886: 
                   1887:        curproc->fdflags[j] = 0;
                   1888: 
                   1889: 
                   1890: 
                   1891:        usrh[0] = i;
                   1892: 
                   1893:        usrh[1] = j;
                   1894: 
1.1.1.2   root     1895:        TRACE(("Fpipe: returning 0: input %d output %d",i,j));
1.1       root     1896: 
                   1897:        return 0;
                   1898: 
                   1899: }
                   1900: 
                   1901: 
                   1902: 
                   1903: /*
                   1904: 
                   1905:  * f_cntl: a combination "ioctl" and "fcntl". Some functions are
                   1906: 
                   1907:  * handled here, if they apply to the file descriptors directly
                   1908: 
                   1909:  * (e.g. F_DUPFD) or if they're easily translated into file system
                   1910: 
                   1911:  * functions (e.g. FSTAT). Others are passed on to the device driver
                   1912: 
                   1913:  * via dev->ioctl.
                   1914: 
                   1915:  */
                   1916: 
                   1917: 
                   1918: 
1.1.1.2   root     1919: long ARGS_ON_STACK
1.1       root     1920: 
                   1921: f_cntl(fh, arg, cmd)
                   1922: 
                   1923:        int fh;
                   1924: 
                   1925:        long arg;
                   1926: 
                   1927:        int cmd;
                   1928: 
                   1929: {
                   1930: 
                   1931:        FILEPTR *f;
                   1932: 
                   1933:        PROC *proc;
                   1934: 
                   1935:        struct flock *fl;
                   1936: 
                   1937:        long r;
                   1938: 
                   1939: 
                   1940: 
1.1.1.2   root     1941:        TRACE(("Fcntl(%d, cmd=0x%x)", fh, cmd));
1.1       root     1942: 
                   1943: #if O_GLOBAL
                   1944: 
                   1945:        if (fh >= 100) {
                   1946: 
                   1947:            fh -= 100;
                   1948: 
                   1949:            proc = rootproc;
                   1950: 
                   1951:        }
                   1952: 
                   1953:        else
                   1954: 
                   1955: #endif
                   1956: 
                   1957:            proc = curproc;
                   1958: 
                   1959: 
                   1960: 
                   1961:        if (fh < MIN_HANDLE || fh >= MAX_OPEN) {
                   1962: 
1.1.1.2   root     1963:                DEBUG(("Fcntl: bad file handle"));
1.1       root     1964: 
                   1965:                return EIHNDL;
                   1966: 
                   1967:        }
                   1968: 
                   1969: 
                   1970: 
                   1971:        if (cmd == F_DUPFD) {
                   1972: 
                   1973: #if O_GLOBAL
                   1974: 
                   1975:                if (proc != curproc) fh += 100;
                   1976: 
                   1977: #endif
                   1978: 
                   1979:                return do_dup(fh, (int)arg);
                   1980: 
                   1981:        }
                   1982: 
                   1983: 
                   1984: 
                   1985:        f = proc->handle[fh];
                   1986: 
                   1987:        if (!f) return EIHNDL;
                   1988: 
                   1989: 
                   1990: 
                   1991:        switch(cmd) {
                   1992: 
                   1993:        case F_GETFD:
                   1994: 
1.1.1.2   root     1995:                TRACE(("Fcntl F_GETFD"));
1.1       root     1996: 
                   1997:                if (fh < 0) return EIHNDL;
                   1998: 
                   1999:                return proc->fdflags[fh];
                   2000: 
                   2001:        case F_SETFD:
                   2002: 
1.1.1.2   root     2003:                TRACE(("Fcntl F_SETFD"));
1.1       root     2004: 
                   2005:                if (fh < 0) return EIHNDL;
                   2006: 
                   2007:                proc->fdflags[fh] = arg;
                   2008: 
                   2009:                return 0;
                   2010: 
                   2011:        case F_GETFL:
                   2012: 
1.1.1.2   root     2013:                TRACE(("Fcntl F_GETFL"));
1.1       root     2014: 
                   2015:                return f->flags & O_USER;
                   2016: 
                   2017:        case F_SETFL:
                   2018: 
1.1.1.2   root     2019:                TRACE(("Fcntl F_SETFL"));
1.1       root     2020: 
                   2021:                arg &= O_USER;          /* make sure only user bits set */
                   2022: 
1.1.1.3   root     2023: #if 0
                   2024: 
1.1       root     2025:        /* COMPATIBILITY WITH OLD VERSIONS ONLY */
                   2026: 
                   2027:        /* THIS CODE WILL GO AWAY. REALLY! */
                   2028: 
                   2029:                if (arg & 4) {
                   2030: 
                   2031:                        arg |= O_NDELAY;
                   2032: 
                   2033:                        arg &= ~4;
                   2034: 
                   2035:                }
                   2036: 
1.1.1.3   root     2037: #endif
                   2038: 
1.1       root     2039: 
                   2040: 
                   2041:        /* make sure the file access and sharing modes are not changed */
                   2042: 
                   2043:                arg &= ~(O_RWMODE|O_SHMODE);
                   2044: 
                   2045:                arg |= f->flags & (O_RWMODE|O_SHMODE);
                   2046: 
                   2047:                f->flags &= ~O_USER;    /* set user bits to arg */
                   2048: 
                   2049:                f->flags |= arg;
                   2050: 
                   2051:                return 0;
                   2052: 
                   2053:        case FSTAT:
                   2054: 
                   2055:                return (*f->fc.fs->getxattr)(&f->fc, (XATTR *)arg);
                   2056: 
                   2057:        case F_SETLK:
                   2058: 
1.1.1.2   root     2059:        case F_SETLKW:
                   2060: 
1.1       root     2061:        /* make sure that the file was opened with appropriate permissions */
                   2062: 
                   2063:                fl = (struct flock *)arg;
                   2064: 
                   2065:                if (fl->l_type == F_RDLCK) {
                   2066: 
                   2067:                        if ( (f->flags & O_RWMODE) == O_WRONLY )
                   2068: 
                   2069:                                return EACCDN;
                   2070: 
                   2071:                } else {
                   2072: 
                   2073:                        if ( (f->flags & O_RWMODE) == O_RDONLY )
                   2074: 
                   2075:                                return EACCDN;
                   2076: 
                   2077:                }
                   2078: 
                   2079:                /* fall through to device ioctl */
                   2080: 
                   2081:        default:
                   2082: 
1.1.1.2   root     2083:                TRACE(("Fcntl mode %x: calling ioctl",cmd));
1.1       root     2084: 
1.1.1.6 ! root     2085:                if (is_terminal(f)) {
        !          2086: 
        !          2087:                        /* tty in the middle of a hangup? */
        !          2088: 
        !          2089:                        while (((struct tty *)f->devinfo)->hup_ospeed) {
1.1       root     2090: 
1.1.1.6 ! root     2091:                                sleep (IO_Q, (long)&((struct tty *)f->devinfo)->state);
        !          2092: 
        !          2093:                        }
1.1       root     2094: 
1.1.1.6 ! root     2095:                        if (cmd == FIONREAD || cmd == FIONWRITE ||
        !          2096: 
        !          2097:                            cmd == TIOCSTART || cmd == TIOCSTOP ||
        !          2098: 
        !          2099:                            cmd == TIOCSBRK || cmd == TIOCFLUSH) {
        !          2100: 
        !          2101:                                r = tty_ioctl(f, cmd, (void *)arg);
        !          2102: 
        !          2103:                        } else {
        !          2104: 
        !          2105:                                r = (*f->dev->ioctl)(f, cmd, (void *)arg);
        !          2106: 
        !          2107:                                if (r == EINVFN) {
        !          2108: 
        !          2109:                                        r = tty_ioctl(f, cmd, (void *)arg);
        !          2110: 
        !          2111:                                }
        !          2112: 
        !          2113:                        }
        !          2114: 
        !          2115:                } else {
        !          2116: 
        !          2117:                        r = (*f->dev->ioctl)(f, cmd, (void *)arg);
1.1       root     2118: 
                   2119:                }
                   2120: 
                   2121:                return r;
                   2122: 
                   2123:        }
                   2124: 
                   2125: }
                   2126: 
                   2127: 
                   2128: 
                   2129: /*
                   2130: 
                   2131:  * fselect(timeout, rfd, wfd, xfd)
                   2132: 
                   2133:  * timeout is an (unsigned) 16 bit integer giving the maximum number
                   2134: 
                   2135:  * of milliseconds to wait; rfd, wfd, and xfd are pointers to 32 bit
                   2136: 
                   2137:  * integers containing bitmasks that describe which file descriptors
                   2138: 
                   2139:  * we're interested in. These masks are changed to represent which
                   2140: 
                   2141:  * file descriptors actually have data waiting (rfd), are ready to
                   2142: 
1.1.1.6 ! root     2143:  * output (wfd), or have exceptional conditions (xfd). If timeout is 0,
1.1       root     2144: 
1.1.1.6 ! root     2145:  * fselect blocks until some file descriptor is ready; otherwise, it
1.1       root     2146: 
1.1.1.6 ! root     2147:  * waits only "timeout" milliseconds. Return value: number of file
1.1       root     2148: 
1.1.1.6 ! root     2149:  * descriptors that are available for reading/writing; or a negative
1.1       root     2150: 
1.1.1.6 ! root     2151:  * error number.
1.1       root     2152: 
                   2153:  */
                   2154: 
                   2155: 
                   2156: 
                   2157: /* helper function for time outs */
                   2158: 
                   2159: static void
                   2160: 
                   2161: unselectme(p)
                   2162: 
                   2163:        PROC *p;
                   2164: 
                   2165: {
                   2166: 
                   2167:        wakeselect((long)p);
                   2168: 
                   2169: }
                   2170: 
                   2171: 
                   2172: 
1.1.1.2   root     2173: long ARGS_ON_STACK
1.1       root     2174: 
                   2175: f_select(timeout, rfdp, wfdp, xfdp)
                   2176: 
                   2177:        unsigned timeout;
                   2178: 
                   2179:        long *rfdp, *wfdp, *xfdp;
                   2180: 
                   2181: {
                   2182: 
1.1.1.6 ! root     2183:        long rfd, wfd, xfd, col_rfd, col_wfd, col_xfd;
1.1       root     2184: 
                   2185:        long mask, bytes;
                   2186: 
                   2187:        int i, count;
                   2188: 
                   2189:        FILEPTR *f;
                   2190: 
                   2191:        PROC *p;
                   2192: 
                   2193:        TIMEOUT *t;
                   2194: 
1.1.1.6 ! root     2195:        int rsel;
1.1       root     2196: 
1.1.1.6 ! root     2197:        long wait_cond;
1.1       root     2198: 
1.1.1.6 ! root     2199:        short sr;
1.1.1.2   root     2200: 
                   2201: 
                   2202: 
1.1       root     2203:        if (rfdp) {
                   2204: 
1.1.1.6 ! root     2205:                col_rfd = rfd = *rfdp;
1.1       root     2206: 
                   2207:        }
                   2208: 
                   2209:        else
                   2210: 
1.1.1.6 ! root     2211:                col_rfd = rfd = 0;
        !          2212: 
        !          2213: 
1.1       root     2214: 
                   2215:        if (wfdp) {
                   2216: 
1.1.1.6 ! root     2217:                col_wfd = wfd = *wfdp;
1.1       root     2218: 
                   2219:        }
                   2220: 
                   2221:        else
                   2222: 
1.1.1.6 ! root     2223:                col_wfd = wfd = 0;
        !          2224: 
        !          2225:        if (xfdp) {
1.1       root     2226: 
1.1.1.6 ! root     2227:                col_xfd = xfd = *xfdp;
        !          2228: 
        !          2229:        } else {
        !          2230: 
        !          2231:                col_xfd = xfd = 0;
        !          2232: 
        !          2233:        }
        !          2234: 
        !          2235: 
        !          2236: 
        !          2237:        /* watch out for aliasing */
        !          2238: 
        !          2239:        if (rfdp) *rfdp = 0;
        !          2240: 
        !          2241:        if (wfdp) *wfdp = 0;
        !          2242: 
        !          2243:        if (xfdp) *xfdp = 0;
1.1       root     2244: 
                   2245: 
1.1.1.6 ! root     2246: 
        !          2247:        t = 0;
        !          2248: 
        !          2249: 
        !          2250: 
        !          2251:        TRACE(("Fselect(%u, %lx, %lx, %lx)", timeout, rfd, wfd, xfd));
1.1       root     2252: 
                   2253:        p = curproc;                    /* help the optimizer out */
                   2254: 
                   2255: 
                   2256: 
                   2257:        /* first, validate the masks */
                   2258: 
                   2259:        mask = 1L;
                   2260: 
                   2261:        for (i = 0; i < MAX_OPEN; i++) {
                   2262: 
1.1.1.6 ! root     2263:                if ( ((rfd & mask) || (wfd & mask) || (xfd & mask)) && !(p->handle[i]) ) {
1.1       root     2264: 
1.1.1.4   root     2265:                        DEBUG(("Fselect: invalid handle: %d", i));
1.1       root     2266: 
                   2267:                        return EIHNDL;
                   2268: 
                   2269:                }
                   2270: 
                   2271:                mask = mask << 1L;
                   2272: 
                   2273:        }
                   2274: 
                   2275: 
                   2276: 
                   2277: /* now, loop through the file descriptors, setting up the select process */
                   2278: 
                   2279: /* NOTE: wakeselect will set p->wait_cond to 0 if data arrives during the
                   2280: 
                   2281:  * selection
                   2282: 
                   2283:  * Also note: because of the validation above, we may assume that the
                   2284: 
                   2285:  * file handles are valid here. However, this assumption may no longer
                   2286: 
                   2287:  * be true after we've gone to sleep, since a signal handler may have
                   2288: 
                   2289:  * closed one of the handles.
                   2290: 
                   2291:  */
                   2292: 
                   2293: 
                   2294: 
1.1.1.6 ! root     2295:        curproc->wait_cond = (long)wakeselect;          /* flag */
1.1       root     2296: 
                   2297: 
                   2298: 
1.1.1.6 ! root     2299:  
1.1       root     2300: 
1.1.1.6 ! root     2301: retry_after_collision:
        !          2302: 
        !          2303:        mask = 1L;
        !          2304: 
        !          2305:        wait_cond = (long)wakeselect;
        !          2306: 
        !          2307:        count = 0;
        !          2308: 
        !          2309:        
1.1       root     2310: 
                   2311:        for (i = 0; i < MAX_OPEN; i++) {
                   2312: 
1.1.1.6 ! root     2313:                if (col_rfd & mask) {
1.1       root     2314: 
                   2315:                        f = p->handle[i];
                   2316: 
1.1.1.6 ! root     2317:                        if (is_terminal(f))
        !          2318: 
        !          2319:                                rsel = (int) tty_select(f, (long)p, O_RDONLY);
        !          2320: 
        !          2321:                        else
        !          2322: 
        !          2323:                                rsel = (int) (*f->dev->select)(f, (long)p, O_RDONLY);
        !          2324: 
        !          2325:                        switch(rsel) {
        !          2326: 
        !          2327:                        case 0:
        !          2328: 
        !          2329:                                col_rfd &= ~mask;
        !          2330: 
        !          2331:                                break;
        !          2332: 
        !          2333:                        case 1:
1.1       root     2334: 
                   2335:                                count++;
                   2336: 
                   2337:                                *rfdp |= mask;
                   2338: 
1.1.1.6 ! root     2339:                                break;
        !          2340: 
        !          2341:                        case 2:
        !          2342: 
        !          2343:                                wait_cond = (long)&select_coll;
        !          2344: 
        !          2345:                                break;
        !          2346: 
1.1       root     2347:                        }
                   2348: 
                   2349:                }
                   2350: 
1.1.1.6 ! root     2351:                if (col_wfd & mask) {
1.1       root     2352: 
                   2353:                        f = p->handle[i];
                   2354: 
1.1.1.6 ! root     2355:                        if (is_terminal(f))
        !          2356: 
        !          2357:                                rsel = (int) tty_select(f, (long)p, O_WRONLY);
        !          2358: 
        !          2359:                        else
        !          2360: 
        !          2361:                                rsel = (int) (*f->dev->select)(f, (long)p, O_WRONLY);
        !          2362: 
        !          2363:                        switch(rsel) {
        !          2364: 
        !          2365:                        case 0:
        !          2366: 
        !          2367:                                col_wfd &= ~mask;
        !          2368: 
        !          2369:                                break;
        !          2370: 
        !          2371:                        case 1:
1.1       root     2372: 
                   2373:                                count++;
                   2374: 
                   2375:                                *wfdp |= mask;
                   2376: 
1.1.1.6 ! root     2377:                                break;
        !          2378: 
        !          2379:                        case 2:
        !          2380: 
        !          2381:                                wait_cond = (long)&select_coll;
        !          2382: 
        !          2383:                                break;
        !          2384: 
1.1       root     2385:                        }
                   2386: 
                   2387:                }
                   2388: 
1.1.1.6 ! root     2389:                if (col_xfd & mask) {
1.1       root     2390: 
1.1.1.6 ! root     2391:                        f = p->handle[i];
1.1       root     2392: 
1.1.1.6 ! root     2393: /* tesche: anybody worried about using O_RDWR for exceptional data? ;) */
1.1       root     2394: 
1.1.1.6 ! root     2395:                        rsel = (*f->dev->select)(f, (long)p, O_RDWR);
1.1       root     2396: 
1.1.1.6 ! root     2397: /*  tesche: for old device drivers, which don't understand this
1.1       root     2398: 
1.1.1.6 ! root     2399:  * call, this will never be true and therefore won't disturb us here.
1.1       root     2400: 
1.1.1.6 ! root     2401:  */
1.1       root     2402: 
1.1.1.6 ! root     2403:                        switch (rsel) {
1.1       root     2404: 
1.1.1.6 ! root     2405:                        case 0:
1.1       root     2406: 
1.1.1.6 ! root     2407:                                col_xfd &= ~mask;
1.1       root     2408: 
1.1.1.6 ! root     2409:                                break;
        !          2410: 
        !          2411:                        case 1:
        !          2412: 
        !          2413:                                count++;
        !          2414: 
        !          2415:                                *xfdp |= mask;
1.1       root     2416: 
1.1.1.6 ! root     2417:                                break;
        !          2418: 
        !          2419:                        case 2:
        !          2420: 
        !          2421:                                wait_cond = (long)&select_coll;
        !          2422: 
        !          2423:                                break;
        !          2424: 
        !          2425:                        }
1.1       root     2426: 
                   2427:                }
                   2428: 
1.1.1.6 ! root     2429:                mask = mask << 1L;
        !          2430: 
        !          2431:        }
1.1       root     2432: 
                   2433: 
1.1.1.6 ! root     2434: 
        !          2435:        if (count == 0) {       /* no data is ready yet */
        !          2436: 
        !          2437:                if (timeout && !t) {
        !          2438: 
        !          2439:                        t = addtimeout((long)timeout, unselectme);
        !          2440: 
        !          2441:                        timeout = 0;
        !          2442: 
        !          2443:                }
1.1.1.3   root     2444: 
                   2445: 
                   2446: 
1.1       root     2447:        /* curproc->wait_cond changes when data arrives or the timeout happens */
                   2448: 
1.1.1.6 ! root     2449:                sr = spl7();
        !          2450: 
1.1.1.2   root     2451:                while (curproc->wait_cond == (long)wakeselect) {
1.1       root     2452: 
1.1.1.6 ! root     2453:                        curproc->wait_cond = wait_cond;
        !          2454: 
        !          2455:                        spl(sr);
        !          2456: 
        !          2457:                        /*
        !          2458: 
        !          2459:                         * The 0x100 tells sleep() to return without sleeping
1.1       root     2460: 
1.1.1.6 ! root     2461:                         * when curproc->wait_cond changes. This way we don't
        !          2462: 
        !          2463:                         * need spl7 (avoiding endless serial overruns).
        !          2464: 
        !          2465:                         * Also fixes a deadlock with checkkeys/checkbttys.
        !          2466: 
        !          2467:                         * They are called from sleep and may wakeselect()
        !          2468: 
        !          2469:                         * curproc. But sleep used to reset curproc->wait_cond
        !          2470: 
        !          2471:                         * to wakeselect causing curproc to sleep forever.
        !          2472: 
        !          2473:                         */
        !          2474: 
        !          2475:                        if (sleep(SELECT_Q|0x100, wait_cond))
        !          2476: 
        !          2477:                                curproc->wait_cond = 0;
        !          2478: 
        !          2479:                        sr = spl7();
        !          2480: 
        !          2481:                }
        !          2482: 
        !          2483:                if (curproc->wait_cond == (long)&select_coll) {
        !          2484: 
        !          2485:                        curproc->wait_cond = (long)wakeselect;
        !          2486: 
        !          2487:                        spl(sr);
        !          2488: 
        !          2489:                        goto retry_after_collision;
1.1       root     2490: 
                   2491:                }
                   2492: 
1.1.1.3   root     2493:                spl(sr);
                   2494: 
1.1       root     2495: 
                   2496: 
                   2497:        /* we can cancel the time out now (if it hasn't already happened) */
                   2498: 
                   2499:                if (t) canceltimeout(t);
                   2500: 
                   2501: 
                   2502: 
                   2503:        /* OK, let's see what data arrived (if any) */
                   2504: 
                   2505:                mask = 1L;
                   2506: 
                   2507:                for (i = 0; i < MAX_OPEN; i++) {
                   2508: 
                   2509:                        if (rfd & mask) {
                   2510: 
                   2511:                                f = p->handle[i];
                   2512: 
                   2513:                                if (f) {
                   2514: 
                   2515:                                    bytes = 1L;
                   2516: 
1.1.1.6 ! root     2517:                                    if (is_terminal(f))
        !          2518: 
        !          2519:                                        (void)tty_ioctl(f, FIONREAD, &bytes);
        !          2520: 
        !          2521:                                    else
        !          2522: 
        !          2523:                                        (void)(*f->dev->ioctl)(f, FIONREAD,&bytes);
1.1       root     2524: 
                   2525:                                    if (bytes > 0) {
                   2526: 
                   2527:                                        *rfdp |= mask;
                   2528: 
                   2529:                                        count++;
                   2530: 
                   2531:                                    }
                   2532: 
                   2533:                                }
                   2534: 
                   2535:                        }
                   2536: 
                   2537:                        if (wfd & mask) {
                   2538: 
                   2539:                                f = p->handle[i];
                   2540: 
                   2541:                                if (f) {
                   2542: 
                   2543:                                    bytes = 1L;
                   2544: 
1.1.1.6 ! root     2545:                                    if (is_terminal(f))
        !          2546: 
        !          2547:                                        (void)tty_ioctl(f, FIONWRITE, &bytes);
        !          2548: 
        !          2549:                                    else
        !          2550: 
        !          2551:                                        (void)(*f->dev->ioctl)(f, FIONWRITE,&bytes);
1.1       root     2552: 
                   2553:                                    if (bytes > 0) {
                   2554: 
                   2555:                                        *wfdp |= mask;
                   2556: 
                   2557:                                        count++;
                   2558: 
                   2559:                                    }
                   2560: 
                   2561:                                }
                   2562: 
                   2563:                        }
                   2564: 
1.1.1.6 ! root     2565:                        if (xfd & mask) {
        !          2566: 
        !          2567:                                f = p->handle[i];
        !          2568: 
        !          2569:                                if (f) {
        !          2570: 
        !          2571: /*  tesche: since old device drivers won't understand this call,
        !          2572: 
        !          2573:  * we set up `no exceptional condition' as default.
        !          2574: 
        !          2575:  */
        !          2576: 
        !          2577:                                    bytes = 0L;
        !          2578: 
        !          2579:                                    (void)(*f->dev->ioctl)(f, FIOEXCEPT,&bytes);
        !          2580: 
        !          2581:                                    if (bytes > 0) {
        !          2582: 
        !          2583:                                        *xfdp |= mask;
        !          2584: 
        !          2585:                                        count++;
        !          2586: 
        !          2587:                                    }
        !          2588: 
        !          2589:                                }
        !          2590: 
        !          2591:                        }
        !          2592: 
1.1       root     2593:                        mask = mask << 1L;
                   2594: 
                   2595:                }
                   2596: 
1.1.1.6 ! root     2597:        } else if (t) {
        !          2598: 
        !          2599:                /* in case data arrived after a collsion, there
        !          2600: 
        !          2601:                 * could be a timeout pending even if count > 0
        !          2602: 
        !          2603:                 */
        !          2604: 
        !          2605:                canceltimeout(t);
        !          2606: 
1.1       root     2607:        }
                   2608: 
                   2609: 
                   2610: 
                   2611:        /* at this point, we either have data or a time out */
                   2612: 
                   2613:        /* cancel all the selects */
                   2614: 
                   2615:        mask = 1L;
                   2616: 
                   2617: 
                   2618: 
                   2619:        for (i = 0; i < MAX_OPEN; i++) {
                   2620: 
                   2621:                if (rfd & mask) {
                   2622: 
                   2623:                        f = p->handle[i];
                   2624: 
                   2625:                        if (f)
                   2626: 
                   2627:                                (*f->dev->unselect)(f, (long)p, O_RDONLY);
                   2628: 
                   2629:                }
                   2630: 
                   2631:                if (wfd & mask) {
                   2632: 
                   2633:                        f = p->handle[i];
                   2634: 
                   2635:                        if (f)
                   2636: 
                   2637:                                (*f->dev->unselect)(f, (long)p, O_WRONLY);
                   2638: 
                   2639:                }
                   2640: 
1.1.1.6 ! root     2641:                if (xfd & mask) {
        !          2642: 
        !          2643:                        f = p->handle[i];
        !          2644: 
        !          2645:                        if (f)
        !          2646: 
        !          2647:                                (*f->dev->unselect)(f, (long)p, O_RDWR);
        !          2648: 
        !          2649:                }
        !          2650: 
1.1       root     2651:                mask = mask << 1L;
                   2652: 
                   2653:        }
                   2654: 
                   2655: 
                   2656: 
1.1.1.6 ! root     2657:        /* wake other processes which got a collision */
        !          2658: 
        !          2659:        if (rfd || wfd || xfd)
        !          2660: 
        !          2661:                wake(SELECT_Q, (long)&select_coll);
        !          2662: 
        !          2663: 
        !          2664: 
1.1.1.2   root     2665:        TRACE(("Fselect: returning %d", count));
1.1       root     2666: 
                   2667:        return count;
                   2668: 
                   2669: }
                   2670: 
                   2671: 
                   2672: 
                   2673: 
                   2674: 
                   2675: /*
                   2676: 
                   2677:  * GEMDOS extension: Fmidipipe
                   2678: 
1.1.1.6 ! root     2679:  * Fmidipipe(pid, in, out) manipulates the MIDI file handles (handles -4 and -5)
1.1       root     2680: 
                   2681:  * of process "pid" so that they now point to the files with handles "in" and
                   2682: 
                   2683:  * "out" in the calling process
                   2684: 
                   2685:  */
                   2686: 
                   2687: 
                   2688: 
1.1.1.2   root     2689: long ARGS_ON_STACK
1.1       root     2690: 
                   2691: f_midipipe(pid, in, out)
                   2692: 
                   2693:        int pid, in, out;
                   2694: 
                   2695: {
                   2696: 
                   2697:        PROC *p;
                   2698: 
                   2699:        FILEPTR *fin, *fout;
                   2700: 
                   2701: 
                   2702: 
                   2703: /* first, find the process */
                   2704: 
                   2705: 
                   2706: 
                   2707:        if (pid == 0)
                   2708: 
                   2709:                p = curproc;
                   2710: 
                   2711:        else {
                   2712: 
                   2713:                p = pid2proc(pid);
                   2714: 
                   2715:                if (!p)
                   2716: 
                   2717:                        return EFILNF;
                   2718: 
                   2719:        }
                   2720: 
                   2721:  
                   2722: 
                   2723: /* next, validate the input and output file handles */
                   2724: 
1.1.1.2   root     2725:        if (in < MIN_HANDLE || in >= MAX_OPEN || (0==(fin = curproc->handle[in])))
1.1       root     2726: 
                   2727:                return EIHNDL;
                   2728: 
                   2729:        if ( (fin->flags & O_RWMODE) == O_WRONLY ) {
                   2730: 
1.1.1.2   root     2731:                DEBUG(("Fmidipipe: input side is write only"));
1.1       root     2732: 
                   2733:                return EACCDN;
                   2734: 
                   2735:        }
                   2736: 
1.1.1.2   root     2737:        if (out < MIN_HANDLE || out >= MAX_OPEN || (0==(fout = curproc->handle[out])))
1.1       root     2738: 
                   2739:                return EIHNDL;
                   2740: 
                   2741:        if ( (fout->flags & O_RWMODE) == O_RDONLY ) {
                   2742: 
1.1.1.2   root     2743:                DEBUG(("Fmidipipe: output side is read only"));
1.1       root     2744: 
                   2745:                return EACCDN;
                   2746: 
                   2747:        }
                   2748: 
                   2749: 
                   2750: 
                   2751: /* OK, duplicate the handles and put them in the new process */
                   2752: 
                   2753:        fin->links++; fout->links++;
                   2754: 
                   2755:        (void)do_pclose(p, p->midiin);
                   2756: 
                   2757:        (void)do_pclose(p, p->midiout);
                   2758: 
                   2759:        p->midiin = fin; p->midiout = fout;
                   2760: 
                   2761:        return 0;
                   2762: 
                   2763: }
                   2764: 

unix.superglobalmegacorp.com

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