Annotation of MiNT/src/pipefs.c, revision 1.1.1.5

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1991,1992 Eric R. Smith.
                      4: 
1.1.1.4   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: /* simple pipefs.c */
                     14: 
                     15: 
                     16: 
                     17: #include "mint.h"
                     18: 
                     19: 
                     20: 
                     21: static int pipetime, pipedate; /* root directory time/date stamp */
                     22: 
                     23: 
                     24: 
1.1.1.2   root       25: static long    ARGS_ON_STACK pipe_root P_((int drv, fcookie *fc));
1.1       root       26: 
1.1.1.2   root       27: static long    ARGS_ON_STACK pipe_lookup       P_((fcookie *dir, const char *name, fcookie *fc));
1.1       root       28: 
1.1.1.2   root       29: static long    ARGS_ON_STACK pipe_getxattr     P_((fcookie *file, XATTR *xattr));
1.1       root       30: 
1.1.1.2   root       31: static long    ARGS_ON_STACK pipe_chattr       P_((fcookie *file, int attrib));
1.1       root       32: 
1.1.1.2   root       33: static long    ARGS_ON_STACK pipe_chown        P_((fcookie *file, int uid, int gid));
1.1       root       34: 
1.1.1.2   root       35: static long    ARGS_ON_STACK pipe_chmode       P_((fcookie *file, unsigned mode));
1.1       root       36: 
1.1.1.2   root       37: static long    ARGS_ON_STACK pipe_rmdir        P_((fcookie *dir, const char *name));
1.1       root       38: 
1.1.1.2   root       39: static long    ARGS_ON_STACK pipe_remove       P_((fcookie *dir, const char *name));
1.1       root       40: 
1.1.1.3   root       41: static long    ARGS_ON_STACK pipe_getname      P_((fcookie *root, fcookie *dir,
                     42: 
                     43:                                                    char *pathname, int size));
1.1       root       44: 
1.1.1.2   root       45: static long    ARGS_ON_STACK pipe_rename       P_((fcookie *olddir, char *oldname,
1.1       root       46: 
                     47:                                    fcookie *newdir, const char *newname));
                     48: 
1.1.1.2   root       49: static long    ARGS_ON_STACK pipe_opendir      P_((DIR *dirh, int flags));
1.1       root       50: 
1.1.1.2   root       51: static long    ARGS_ON_STACK pipe_readdir      P_((DIR *dirh, char *nm, int nmlen, fcookie *));
1.1       root       52: 
1.1.1.2   root       53: static long    ARGS_ON_STACK pipe_rewinddir    P_((DIR *dirh));
1.1       root       54: 
1.1.1.2   root       55: static long    ARGS_ON_STACK pipe_closedir     P_((DIR *dirh));
1.1       root       56: 
1.1.1.2   root       57: static long    ARGS_ON_STACK pipe_pathconf     P_((fcookie *dir, int which));
1.1       root       58: 
1.1.1.2   root       59: static long    ARGS_ON_STACK pipe_dfree        P_((fcookie *dir, long *buf));
1.1       root       60: 
1.1.1.2   root       61: static long    ARGS_ON_STACK pipe_creat        P_((fcookie *dir, const char *name, unsigned mode,
1.1       root       62: 
                     63:                                        int attrib, fcookie *fc));
                     64: 
1.1.1.2   root       65: static DEVDRV *        ARGS_ON_STACK pipe_getdev       P_((fcookie *fc, long *devsp));
1.1       root       66: 
                     67: 
                     68: 
1.1.1.2   root       69: static long    ARGS_ON_STACK pipe_open P_((FILEPTR *f));
1.1       root       70: 
1.1.1.2   root       71: static long    ARGS_ON_STACK pipe_write        P_((FILEPTR *f, const char *buf, long bytes));
1.1       root       72: 
1.1.1.2   root       73: static long    ARGS_ON_STACK pipe_read P_((FILEPTR *f, char *buf, long bytes));
1.1       root       74: 
1.1.1.5 ! root       75: static long    ARGS_ON_STACK pty_write         P_((FILEPTR *f, const char *buf, long bytes));
        !            76: 
        !            77: static long    ARGS_ON_STACK pty_read  P_((FILEPTR *f, char *buf, long bytes));
        !            78: 
        !            79: static long    ARGS_ON_STACK pty_writeb        P_((FILEPTR *f, const char *buf, long bytes));
        !            80: 
        !            81: static long    ARGS_ON_STACK pty_readb P_((FILEPTR *f, char *buf, long bytes));
        !            82: 
1.1.1.2   root       83: static long    ARGS_ON_STACK pipe_lseek        P_((FILEPTR *f, long where, int whence));
1.1       root       84: 
1.1.1.2   root       85: static long    ARGS_ON_STACK pipe_ioctl        P_((FILEPTR *f, int mode, void *buf));
1.1       root       86: 
1.1.1.2   root       87: static long    ARGS_ON_STACK pipe_datime       P_((FILEPTR *f, short *time, int rwflag));
1.1       root       88: 
1.1.1.2   root       89: static long    ARGS_ON_STACK pipe_close        P_((FILEPTR *f, int pid));
1.1       root       90: 
1.1.1.2   root       91: static long    ARGS_ON_STACK pipe_select       P_((FILEPTR *f, long p, int mode));
1.1       root       92: 
1.1.1.2   root       93: static void    ARGS_ON_STACK pipe_unselect     P_((FILEPTR *f, long p, int mode));
1.1       root       94: 
                     95: 
                     96: 
1.1.1.5 ! root       97: DEVDRV pty_device = {
        !            98: 
        !            99:        pipe_open, pty_write, pty_read, pipe_lseek, pipe_ioctl, pipe_datime,
        !           100: 
        !           101:        pipe_close, pipe_select, pipe_unselect, pty_writeb, pty_readb
        !           102: 
        !           103: };
        !           104: 
        !           105:  
        !           106: 
1.1       root      107: DEVDRV pipe_device = {
                    108: 
                    109:        pipe_open, pipe_write, pipe_read, pipe_lseek, pipe_ioctl, pipe_datime,
                    110: 
                    111:        pipe_close, pipe_select, pipe_unselect
                    112: 
                    113: };
                    114: 
                    115: 
                    116: 
                    117: 
                    118: 
                    119: FILESYS pipe_filesys = {
                    120: 
                    121:        (FILESYS *)0,
                    122: 
                    123:        0,
                    124: 
                    125:        pipe_root,
                    126: 
                    127:        pipe_lookup, pipe_creat, pipe_getdev, pipe_getxattr,
                    128: 
                    129:        pipe_chattr, pipe_chown, pipe_chmode,
                    130: 
                    131:        nomkdir, pipe_rmdir, pipe_remove, pipe_getname, pipe_rename,
                    132: 
                    133:        pipe_opendir, pipe_readdir, pipe_rewinddir, pipe_closedir,
                    134: 
                    135:        pipe_pathconf, pipe_dfree,
                    136: 
                    137:        nowritelabel, noreadlabel, nosymlink, noreadlink,
                    138: 
                    139:        nohardlink, nofscntl, nodskchng
                    140: 
                    141: };
                    142: 
                    143: 
                    144: 
                    145: /* size of pipes */
                    146: 
                    147: #define PIPESIZ        4096            /* MUST be a multiple of 4 */
                    148: 
                    149: 
                    150: 
                    151: /* writes smaller than this are atomic */
                    152: 
                    153: #define PIPE_BUF 1024          /* should be a multiple of 4 */
                    154: 
                    155: 
                    156: 
                    157: /* magic flag: indicates that nobody but the creator has opened this pipe */
                    158: 
                    159: /* note: if this many processes open the pipe, we lose :-( */
                    160: 
                    161: #define VIRGIN_PIPE    0x7fff
                    162: 
                    163: 
                    164: 
                    165: struct pipe {
                    166: 
                    167:        int     readers;        /* number of readers of this pipe */
                    168: 
                    169:        int     writers;        /* number of writers of this pipe */
                    170: 
1.1.1.5 ! root      171:        int     start, len;     /* pipe head index, size */
1.1       root      172: 
                    173:        long    rsel;           /* process that did select() for reads */
                    174: 
                    175:        long    wsel;           /* process that did select() for writes */
                    176: 
                    177:        char    buf[PIPESIZ];   /* pipe data */
                    178: 
                    179: };
                    180: 
                    181: 
                    182: 
                    183: struct fifo {
                    184: 
                    185:        char    name[NAME_MAX+1]; /* FIFO's name */
                    186: 
                    187:        short   date, time;     /* date & time of last write */
                    188: 
                    189:        short   dosflags;       /* DOS flags, e.g. FA_RDONLY, FA_HIDDEN */
                    190: 
                    191:        ushort  mode;           /* file access mode, for XATTR */
                    192: 
                    193:        ushort  uid, gid;       /* file owner; uid and gid */
                    194: 
                    195:        short   flags;          /* various other flags (e.g. O_TTY) */
                    196: 
                    197:        short   lockpid;        /* pid of locking process */
                    198: 
1.1.1.2   root      199:        short   cursrate;       /* cursor flash rate for pseudo TTY's */
                    200: 
1.1       root      201:        struct tty *tty;        /* tty struct for pseudo TTY's */
                    202: 
                    203:        struct pipe *inp;       /* pipe for reads */
                    204: 
                    205:        struct pipe *outp;      /* pipe for writes (0 if unidirectional) */
                    206: 
                    207:        struct fifo *next;      /* link to next FIFO in list */
                    208: 
                    209:        FILEPTR *open;          /* open file pointers for this fifo */
                    210: 
                    211: } *rootlist;
                    212: 
                    213: 
                    214: 
                    215: 
                    216: 
1.1.1.2   root      217: static long ARGS_ON_STACK 
1.1       root      218: 
                    219: pipe_root(drv, fc)
                    220: 
                    221:        int drv;
                    222: 
                    223:        fcookie *fc;
                    224: 
                    225: {
                    226: 
                    227:        if (drv == PIPEDRV) {
                    228: 
                    229:                fc->fs = &pipe_filesys;
                    230: 
                    231:                fc->dev = drv;
                    232: 
                    233:                fc->index = 0L;
                    234: 
                    235:                return 0;
                    236: 
                    237:        }
                    238: 
                    239:        fc->fs = 0;
                    240: 
                    241:        return EINTRN;
                    242: 
                    243: }
                    244: 
                    245: 
                    246: 
1.1.1.2   root      247: static long ARGS_ON_STACK 
1.1       root      248: 
                    249: pipe_lookup(dir, name, fc)
                    250: 
                    251:        fcookie *dir;
                    252: 
                    253:        const char *name;
                    254: 
                    255:        fcookie *fc;
                    256: 
                    257: {
                    258: 
                    259:        struct fifo *b;
                    260: 
                    261: 
                    262: 
1.1.1.2   root      263:        TRACE(("pipe_lookup(%s)", name));
1.1       root      264: 
                    265: 
                    266: 
                    267:        if (dir->index != 0) {
                    268: 
1.1.1.2   root      269:                DEBUG(("pipe_lookup(%s): bad directory", name));
1.1       root      270: 
                    271:                return EPTHNF;
                    272: 
                    273:        }
                    274: 
                    275: /* special case: an empty name in a directory means that directory */
                    276: 
                    277: /* so does "." */
                    278: 
                    279:        if (!*name || (name[0] == '.' && name[1] == 0)) {
                    280: 
                    281:                *fc = *dir;
                    282: 
                    283:                return 0;
                    284: 
                    285:        }
                    286: 
                    287: 
                    288: 
                    289: /* another special case: ".." could be a mount point */
                    290: 
                    291:        if (!strcmp(name, "..")) {
                    292: 
                    293:                *fc = *dir;
                    294: 
                    295:                return EMOUNT;
                    296: 
                    297:        }
                    298: 
                    299: 
                    300: 
                    301:        for (b = rootlist; b; b = b->next) {
                    302: 
1.1.1.3   root      303:                if (!strnicmp(b->name, name, NAME_MAX)) {
1.1       root      304: 
                    305:                        fc->fs = &pipe_filesys;
                    306: 
                    307:                        fc->index = (long)b;
                    308: 
                    309:                        fc->dev = dir->dev;
                    310: 
                    311:                        return 0;
                    312: 
                    313:                }
                    314: 
                    315:        }
                    316: 
1.1.1.2   root      317:        DEBUG(("pipe_lookup: name `%s' not found", name));
1.1       root      318: 
                    319:        return EFILNF;
                    320: 
                    321: }
                    322: 
                    323: 
                    324: 
1.1.1.2   root      325: static long ARGS_ON_STACK 
1.1       root      326: 
                    327: pipe_getxattr(fc, xattr)
                    328: 
                    329:        fcookie *fc;
                    330: 
                    331:        XATTR *xattr;
                    332: 
                    333: {
                    334: 
                    335:        struct fifo *this;
                    336: 
                    337: 
                    338: 
                    339:        xattr->index = fc->index;
                    340: 
                    341:        xattr->dev = fc->dev;
                    342: 
1.1.1.4   root      343:        xattr->rdev = fc->dev;
                    344: 
1.1       root      345:        xattr->nlink = 1;
                    346: 
1.1.1.5 ! root      347:        xattr->blksize = 1024L;
1.1       root      348: 
                    349: 
                    350: 
                    351:        if (fc->index == 0) {           /* root directory? */
                    352: 
                    353:                xattr->uid = xattr->gid = 0;
                    354: 
                    355:                xattr->mtime = xattr->atime = xattr->ctime = pipetime;
                    356: 
                    357:                xattr->mdate = xattr->adate = xattr->cdate = pipedate;
                    358: 
                    359:                xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
                    360: 
                    361:                xattr->attr = FA_DIR;
                    362: 
                    363:                xattr->size = xattr->nblocks = 0;
                    364: 
                    365:        } else {
                    366: 
                    367:                this = (struct fifo *)fc->index;
                    368: 
                    369:                xattr->uid = this->uid;
                    370: 
                    371:                xattr->gid = this->gid;
                    372: 
                    373:                xattr->mtime = xattr->atime = xattr->ctime = this->time;
                    374: 
                    375:                xattr->mdate = xattr->adate = xattr->cdate = this->date;
                    376: 
                    377:                xattr->mode = this->mode;
                    378: 
                    379:                xattr->attr = this->dosflags;
                    380: 
                    381:        /* note: fifo's that haven't been opened yet can be written to */
                    382: 
                    383:                if (this->flags & O_HEAD) {
                    384: 
                    385:                        xattr->attr &= ~FA_RDONLY;
                    386: 
                    387:                }
                    388: 
                    389: 
                    390: 
                    391:                if (this->dosflags & FA_SYSTEM) {       /* pseudo-tty */
                    392: 
                    393:                        xattr->size = PIPESIZ/4;
                    394: 
1.1.1.4   root      395:                        xattr->rdev = PIPE_RDEV|1;
                    396: 
1.1       root      397:                } else {
                    398: 
                    399:                        xattr->size = PIPESIZ;
                    400: 
1.1.1.4   root      401:                        xattr->rdev = PIPE_RDEV|0;
                    402: 
1.1       root      403:                }
                    404: 
1.1.1.5 ! root      405:                xattr->nblocks = xattr->size / 1024L;
        !           406: 
1.1       root      407:        }
                    408: 
                    409:        return 0;
                    410: 
                    411: }
                    412: 
                    413: 
                    414: 
1.1.1.2   root      415: static long ARGS_ON_STACK 
1.1       root      416: 
                    417: pipe_chattr(fc, attrib)
                    418: 
                    419:        fcookie *fc;
                    420: 
                    421:        int attrib;
                    422: 
                    423: {
                    424: 
1.1.1.2   root      425:        UNUSED(fc); UNUSED(attrib);
                    426: 
1.1       root      427:        return EACCDN;
                    428: 
                    429: }
                    430: 
                    431: 
                    432: 
1.1.1.2   root      433: static long ARGS_ON_STACK 
1.1       root      434: 
                    435: pipe_chown(fc, uid, gid)
                    436: 
                    437:        fcookie *fc;
                    438: 
                    439:        int uid, gid;
                    440: 
                    441: {
                    442: 
                    443:        struct fifo *this;
                    444: 
                    445: 
                    446: 
1.1.1.2   root      447:        if ((this = (struct fifo *)fc->index) == 0)
                    448: 
                    449:                return EACCDN;
1.1       root      450: 
                    451: 
                    452: 
                    453:        this->uid = uid;
                    454: 
                    455:        this->gid = gid;
                    456: 
                    457:        return 0;
                    458: 
                    459: }
                    460: 
                    461: 
                    462: 
1.1.1.2   root      463: static long ARGS_ON_STACK 
1.1       root      464: 
                    465: pipe_chmode(fc, mode)
                    466: 
                    467:        fcookie *fc;
                    468: 
                    469:        unsigned mode;
                    470: 
                    471: {
                    472: 
                    473:        struct fifo *this;
                    474: 
                    475: 
                    476: 
1.1.1.2   root      477:        if ((this = (struct fifo *)fc->index) == 0)
                    478: 
                    479:                return EACCDN;
1.1       root      480: 
                    481: 
                    482: 
                    483:        this->mode = (this->mode & S_IFMT) | (mode & ~S_IFMT);
                    484: 
                    485:        return 0;
                    486: 
                    487: }
                    488: 
                    489: 
                    490: 
1.1.1.2   root      491: static long ARGS_ON_STACK 
1.1       root      492: 
                    493: pipe_rmdir(dir, name)
                    494: 
                    495:        fcookie *dir;
                    496: 
                    497:        const char *name;
                    498: 
                    499: {
                    500: 
1.1.1.2   root      501:        UNUSED(dir); UNUSED(name);
                    502: 
                    503: 
                    504: 
1.1       root      505: /* the kernel already checked to see if the file exists */
                    506: 
                    507:        return EACCDN;
                    508: 
                    509: }
                    510: 
                    511: 
                    512: 
1.1.1.2   root      513: static long ARGS_ON_STACK 
1.1       root      514: 
                    515: pipe_remove(dir, name)
                    516: 
                    517:        fcookie *dir;
                    518: 
                    519:        const char *name;
                    520: 
                    521: {
                    522: 
1.1.1.2   root      523:        UNUSED(dir); UNUSED(name);
                    524: 
                    525: 
                    526: 
1.1       root      527: /* the kernel already checked to see if the file exists */
                    528: 
                    529:        return EACCDN;
                    530: 
                    531: }
                    532: 
                    533: 
                    534: 
1.1.1.2   root      535: static long ARGS_ON_STACK 
1.1       root      536: 
1.1.1.3   root      537: pipe_getname(root, dir, pathname, size)
1.1       root      538: 
                    539:        fcookie *root, *dir; char *pathname;
                    540: 
1.1.1.3   root      541:        int size;
                    542: 
1.1       root      543: {
                    544: 
1.1.1.2   root      545:        UNUSED(root);
                    546: 
1.1.1.3   root      547:        UNUSED(size);   /* BUG: we should support 'size' */
                    548: 
1.1.1.2   root      549: 
                    550: 
1.1       root      551:        if (dir->index == 0)
                    552: 
                    553:                *pathname = 0;
                    554: 
                    555:        else
                    556: 
                    557:                strcpy(pathname, ((struct fifo *)dir->index)->name);
                    558: 
                    559:        return 0;
                    560: 
                    561: }
                    562: 
                    563: 
                    564: 
1.1.1.2   root      565: static long ARGS_ON_STACK 
1.1       root      566: 
                    567: pipe_rename(olddir, oldname, newdir, newname)
                    568: 
                    569:        fcookie *olddir;
                    570: 
                    571:        char *oldname;
                    572: 
                    573:        fcookie *newdir;
                    574: 
                    575:        const char *newname;
                    576: 
                    577: {
                    578: 
1.1.1.2   root      579:        UNUSED(olddir); UNUSED(oldname);
                    580: 
                    581:        UNUSED(newdir); UNUSED(newname);
                    582: 
                    583: 
                    584: 
1.1       root      585:        return EACCDN;
                    586: 
                    587: }
                    588: 
                    589: 
                    590: 
1.1.1.2   root      591: static long ARGS_ON_STACK 
1.1       root      592: 
                    593: pipe_opendir(dirh, flags)
                    594: 
                    595:        DIR *dirh;
                    596: 
                    597:        int flags;
                    598: 
                    599: {
                    600: 
1.1.1.2   root      601:        UNUSED(flags);
                    602: 
                    603: 
                    604: 
1.1       root      605:        if (dirh->fc.index != 0) {
                    606: 
1.1.1.2   root      607:                DEBUG(("pipe_opendir: bad directory"));
1.1       root      608: 
                    609:                return EPTHNF;
                    610: 
                    611:        }
                    612: 
                    613:        dirh->index = 0;
                    614: 
                    615:        return 0;
                    616: 
                    617: }
                    618: 
                    619: 
                    620: 
1.1.1.2   root      621: static long ARGS_ON_STACK 
1.1       root      622: 
                    623: pipe_readdir(dirh, name, namelen, fc)
                    624: 
                    625:        DIR *dirh;
                    626: 
                    627:        char *name;
                    628: 
                    629:        int namelen;
                    630: 
                    631:        fcookie *fc;
                    632: 
                    633: {
                    634: 
                    635:        struct fifo *this;
                    636: 
                    637:        int i;
                    638: 
                    639:        int giveindex = dirh->flags == 0;
                    640: 
                    641: 
                    642: 
                    643:        i = dirh->index++;
                    644: 
                    645:        this = rootlist;
                    646: 
                    647:        while (i > 0 && this) {
                    648: 
                    649:                --i; this = this->next;
                    650: 
                    651:        }
                    652: 
                    653:        if (!this)
                    654: 
                    655:                return ENMFIL;
                    656: 
                    657: 
                    658: 
                    659:        fc->fs = &pipe_filesys;
                    660: 
                    661:        fc->index = (long)this;
                    662: 
                    663:        fc->dev = dirh->fc.dev;
                    664: 
                    665:        if (giveindex) {
                    666: 
1.1.1.2   root      667:                namelen -= (int) sizeof(long);
1.1       root      668: 
                    669:                if (namelen <= 0) return ERANGE;
                    670: 
                    671:                *((long *)name) = (long)this;
                    672: 
                    673:                name += sizeof(long);
                    674: 
                    675:        }
                    676: 
                    677:        strncpy(name, this->name, namelen-1);
                    678: 
                    679:        if (strlen(this->name) >= namelen)
                    680: 
                    681:                return ENAMETOOLONG;
                    682: 
                    683:        return 0;
                    684: 
                    685: }
                    686: 
                    687: 
                    688: 
1.1.1.2   root      689: static long ARGS_ON_STACK 
1.1       root      690: 
                    691: pipe_rewinddir(dirh)
                    692: 
                    693:        DIR *dirh;
                    694: 
                    695: {
                    696: 
                    697:        dirh->index = 0;
                    698: 
                    699:        return 0;
                    700: 
                    701: }
                    702: 
                    703: 
                    704: 
1.1.1.2   root      705: static long ARGS_ON_STACK 
1.1       root      706: 
                    707: pipe_closedir(dirh)
                    708: 
                    709:        DIR *dirh;
                    710: 
                    711: {
                    712: 
1.1.1.2   root      713:        UNUSED(dirh);
                    714: 
1.1       root      715:        return 0;
                    716: 
                    717: }
                    718: 
                    719: 
                    720: 
1.1.1.2   root      721: static long ARGS_ON_STACK 
1.1       root      722: 
                    723: pipe_pathconf(dir, which)
                    724: 
                    725:        fcookie *dir;
                    726: 
                    727:        int which;
                    728: 
                    729: {
                    730: 
1.1.1.2   root      731:        UNUSED(dir);
                    732: 
                    733: 
                    734: 
1.1       root      735:        switch(which) {
                    736: 
                    737:        case -1:
                    738: 
                    739:                return DP_MAXREQ;
                    740: 
                    741:        case DP_IOPEN:
                    742: 
                    743:                return UNLIMITED;       /* no internal limit on open files */
                    744: 
                    745:        case DP_MAXLINKS:
                    746: 
                    747:                return 1;               /* no hard links */
                    748: 
                    749:        case DP_PATHMAX:
                    750: 
                    751:                return PATH_MAX;
                    752: 
                    753:        case DP_NAMEMAX:
                    754: 
                    755:                return NAME_MAX;
                    756: 
                    757:        case DP_ATOMIC:
                    758: 
                    759:        /* BUG: for pty's, this should actually be PIPE_BUF/4 */
                    760: 
                    761:                return PIPE_BUF;
                    762: 
                    763:        case DP_TRUNC:
                    764: 
                    765:                return DP_AUTOTRUNC;
                    766: 
                    767:        case DP_CASE:
                    768: 
                    769:                return DP_CASEINSENS;
                    770: 
1.1.1.5 ! root      771:        case DP_MODEATTR:
        !           772: 
        !           773:                return (0777L << 8)|
        !           774: 
        !           775:                                DP_FT_DIR|DP_FT_FIFO;
        !           776: 
        !           777:        case DP_XATTRFIELDS:
        !           778: 
        !           779:                return DP_INDEX|DP_DEV|DP_NLINK|DP_UID|DP_GID|DP_MTIME;
        !           780: 
1.1       root      781:        default:
                    782: 
                    783:                return EINVFN;
                    784: 
                    785:        }
                    786: 
                    787: }
                    788: 
                    789: 
                    790: 
1.1.1.2   root      791: static long ARGS_ON_STACK 
1.1       root      792: 
                    793: pipe_dfree(dir, buf)
                    794: 
                    795:        fcookie *dir;
                    796: 
                    797:        long *buf;
                    798: 
                    799: {
                    800: 
                    801:        int i;
                    802: 
                    803:        struct fifo *b;
                    804: 
                    805:        long freemem;
                    806: 
                    807: 
                    808: 
1.1.1.2   root      809:        UNUSED(dir);
                    810: 
                    811: 
                    812: 
1.1       root      813: /* the "sector" size is the number of bytes per pipe */
                    814: 
                    815: /* so we get the total number of sectors used by counting pipes */
                    816: 
                    817: 
                    818: 
                    819:        i = 0;
                    820: 
                    821:        for (b = rootlist; b; b = b->next) {
                    822: 
                    823:                if (b->inp) i++;
                    824: 
                    825:                if (b->outp) i++;
                    826: 
                    827:        }
                    828: 
                    829: 
                    830: 
                    831:        freemem = tot_rsize(core, 0) + tot_rsize(alt, 0);
                    832: 
                    833: 
                    834: 
                    835: /* note: the "free clusters" isn't quite accurate, since there's overhead
                    836: 
                    837:  * in the fifo structure; but we're not looking for 100% accuracy here
                    838: 
                    839:  */
                    840: 
                    841:        buf[0] = freemem/PIPESIZ;       /* number of free clusters */
                    842: 
                    843:        buf[1] = buf[0]+i;              /* total number of clusters */
                    844: 
                    845:        buf[2] = PIPESIZ;               /* sector size (bytes) */
                    846: 
                    847:        buf[3] = 1;                     /* cluster size (sectors) */
                    848: 
                    849:        return 0;
                    850: 
                    851: }
                    852: 
                    853: 
                    854: 
                    855: /* create a new pipe.
                    856: 
                    857:  * this only gets called by the kernel if a lookup already failed,
                    858: 
                    859:  * so we know that the new pipe creation is OK
                    860: 
                    861:  */
                    862: 
                    863: 
                    864: 
1.1.1.2   root      865: static long ARGS_ON_STACK 
1.1       root      866: 
                    867: pipe_creat(dir, name, mode, attrib, fc)
                    868: 
                    869:        fcookie *dir;
                    870: 
                    871:        const char *name;
                    872: 
                    873:        unsigned mode;
                    874: 
                    875:        int attrib;
                    876: 
                    877:        fcookie *fc;
                    878: 
                    879: {
                    880: 
                    881:        struct pipe *inp, *outp;
                    882: 
                    883:        struct tty *tty;
                    884: 
                    885:        struct fifo *b;
                    886: 
                    887: /* selfread == 1 if we want reads to wait even if no other processes
                    888: 
                    889:    have currently opened the file, and writes to succeed in the same
                    890: 
                    891:    event. This is useful for servers who want to wait for requests.
                    892: 
                    893:    Pipes should always have selfread == 0.
                    894: 
                    895: */
                    896: 
                    897:        int selfread = (attrib & FA_HIDDEN) ? 0 : 1;
                    898: 
                    899: 
                    900: 
                    901: 
                    902: 
                    903:        /* create the new pipe */
                    904: 
1.1.1.2   root      905:        if (0 == (inp = (struct pipe *)kmalloc(SIZEOF(struct pipe)))) {
1.1       root      906: 
                    907:                return ENSMEM;
                    908: 
                    909:        }
                    910: 
                    911:        if (attrib & FA_RDONLY) {       /* read only FIFOs are unidirectional */
                    912: 
                    913:                outp = 0;
                    914: 
                    915:        } else {
                    916: 
                    917:                outp = (struct pipe *)kmalloc(SIZEOF(struct pipe));
                    918: 
                    919:                if (!outp) {
                    920: 
                    921:                        kfree(inp);
                    922: 
                    923:                        return ENSMEM;
                    924: 
                    925:                }
                    926: 
                    927:        }
                    928: 
                    929:        b = (struct fifo *)kmalloc(SIZEOF(struct fifo));
                    930: 
                    931:        if (!b) {
                    932: 
                    933:                kfree(inp);
                    934: 
                    935:                if (outp) kfree(outp);
                    936: 
                    937:                return ENSMEM;
                    938: 
                    939:        }
                    940: 
                    941:        if (attrib & FA_SYSTEM) {       /* pseudo-tty */
                    942: 
                    943:                tty = (struct tty *)kmalloc(SIZEOF(struct tty));
                    944: 
                    945:                if (!tty) {
                    946: 
                    947:                        kfree(inp);
                    948: 
                    949:                        kfree(b);
                    950: 
                    951:                        if (outp) kfree(outp);
                    952: 
                    953:                        return ENSMEM;
                    954: 
                    955:                }
                    956: 
                    957:                tty->use_cnt = 0;
                    958: 
1.1.1.5 ! root      959:                tty->rsel = tty->wsel = 0;
        !           960: 
1.1       root      961:                    /* do_open does the rest of tty initialization */
                    962: 
                    963:        } else tty = 0;
                    964: 
                    965: 
                    966: 
                    967: /* set up the pipes appropriately */
                    968: 
1.1.1.5 ! root      969:        inp->start = inp->len = 0;
1.1       root      970: 
                    971:        inp->readers = selfread ? 1 : VIRGIN_PIPE; inp->writers = 1;
                    972: 
                    973:        inp->rsel = inp->wsel = 0;
                    974: 
                    975:        if (outp) {
                    976: 
1.1.1.5 ! root      977:                outp->start = outp->len = 0;
1.1       root      978: 
                    979:                outp->readers = 1; outp->writers = selfread ? 1 : VIRGIN_PIPE;
                    980: 
                    981:                outp->wsel = outp->rsel = 0;
                    982: 
                    983:        }
                    984: 
                    985:        strncpy(b->name, name, NAME_MAX);
                    986: 
1.1.1.5 ! root      987:        b->name[NAME_MAX] = '\0';
        !           988: 
1.1       root      989:        b->time = timestamp;
                    990: 
                    991:        b->date = datestamp;
                    992: 
                    993:        b->dosflags = attrib;
                    994: 
1.1.1.5 ! root      995:        b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | (mode & ~S_IFMT);
1.1       root      996: 
1.1.1.5 ! root      997:        b->uid = curproc->euid;
1.1       root      998: 
1.1.1.5 ! root      999:        b->gid = curproc->egid;
1.1       root     1000: 
                   1001: 
                   1002: 
                   1003: /* the O_HEAD flag indicates that the file hasn't actually been opened
                   1004: 
                   1005:  * yet; the next open gets to be the pty master. pipe_open will
                   1006: 
                   1007:  * clear the flag when this happens.
                   1008: 
                   1009:  */
                   1010: 
                   1011:        b->flags = ((attrib & FA_SYSTEM) ? O_TTY : 0) | O_HEAD;
                   1012: 
                   1013:        b->inp = inp; b->outp = outp; b->tty = tty;
                   1014: 
                   1015: 
                   1016: 
                   1017:        b->next = rootlist;
                   1018: 
                   1019:        b->open = (FILEPTR *)0;
                   1020: 
                   1021:        rootlist = b;
                   1022: 
                   1023: 
                   1024: 
                   1025: /* we have to return a file cookie as well */
                   1026: 
                   1027:        fc->fs = &pipe_filesys;
                   1028: 
                   1029:        fc->index = (long)b;
                   1030: 
                   1031:        fc->dev = dir->dev;
                   1032: 
                   1033: 
                   1034: 
                   1035: /* update time/date stamps for u:\pipe */
                   1036: 
                   1037:        pipetime = timestamp;
                   1038: 
                   1039:        pipedate = datestamp;
                   1040: 
                   1041: 
                   1042: 
                   1043:        return 0;
                   1044: 
                   1045: }
                   1046: 
                   1047: 
                   1048: 
1.1.1.2   root     1049: static DEVDRV * ARGS_ON_STACK 
1.1       root     1050: 
                   1051: pipe_getdev(fc, devsp)
                   1052: 
                   1053:        fcookie *fc;
                   1054: 
                   1055:        long *devsp;
                   1056: 
                   1057: {
                   1058: 
                   1059:        struct fifo *b = (struct fifo *)fc->index;
                   1060: 
                   1061: 
                   1062: 
1.1.1.2   root     1063:        UNUSED(devsp);
                   1064: 
1.1       root     1065:        return (b->flags & O_TTY) ? &pty_device : &pipe_device;
                   1066: 
                   1067: }
                   1068: 
                   1069: 
                   1070: 
                   1071: /*
                   1072: 
                   1073:  * PIPE device driver
                   1074: 
                   1075:  */
                   1076: 
                   1077: 
                   1078: 
1.1.1.2   root     1079: static long ARGS_ON_STACK 
1.1       root     1080: 
                   1081: pipe_open(f)
                   1082: 
                   1083:        FILEPTR *f;
                   1084: 
                   1085: {
                   1086: 
                   1087:        struct fifo *p;
                   1088: 
                   1089:        int rwmode = f->flags & O_RWMODE;
                   1090: 
                   1091: 
                   1092: 
                   1093:        p = (struct fifo *)f->fc.index;
                   1094: 
                   1095:        f->flags |= p->flags;
                   1096: 
                   1097: /*
                   1098: 
                   1099:  * if this is the first open for this file, then the O_HEAD flag is
                   1100: 
                   1101:  * set in p->flags. If not, and someone was trying to create the file,
                   1102: 
                   1103:  * return an error
                   1104: 
                   1105:  */
                   1106: 
                   1107:        if (p->flags & O_HEAD) {
                   1108: 
                   1109:                if (!(f->flags & O_CREAT)) {
                   1110: 
1.1.1.2   root     1111:                        DEBUG(("pipe_open: file hasn't been created yet"));
1.1       root     1112: 
                   1113:                        return EINTRN;
                   1114: 
                   1115:                }
                   1116: 
                   1117:                p->flags &= ~O_HEAD;
                   1118: 
                   1119:        } else {
                   1120: 
                   1121:                if (f->flags & O_CREAT) {
                   1122: 
1.1.1.2   root     1123:                        DEBUG(("pipe_open: fifo already exists"));
1.1       root     1124: 
                   1125:                        return EACCDN;
                   1126: 
                   1127:                }
                   1128: 
                   1129:        }
                   1130: 
                   1131: /*
                   1132: 
                   1133:  * check for file sharing compatibility. note that O_COMPAT gets mutated
                   1134: 
                   1135:  * into O_DENYNONE, because any old programs that know about pipes will
                   1136: 
                   1137:  * already handle multitasking correctly
                   1138: 
                   1139:  */
                   1140: 
                   1141:        if ( (f->flags & O_SHMODE) == O_COMPAT ) {
                   1142: 
                   1143:                f->flags = (f->flags & ~O_SHMODE) | O_DENYNONE;
                   1144: 
                   1145:        }
                   1146: 
                   1147:        if (denyshare(p->open, f))
                   1148: 
                   1149:                return EACCDN;
                   1150: 
                   1151:        f->next = p->open;              /* add this open fileptr to the list */
                   1152: 
                   1153:        p->open = f;
                   1154: 
                   1155: 
                   1156: 
                   1157: /*
                   1158: 
                   1159:  * add readers/writers to the list
                   1160: 
                   1161:  */
                   1162: 
                   1163:        if (!(f->flags & O_HEAD)) {
                   1164: 
                   1165:                if (rwmode == O_RDONLY || rwmode == O_RDWR) {
                   1166: 
                   1167:                        if (p->inp->readers == VIRGIN_PIPE)
                   1168: 
                   1169:                                p->inp->readers = 1;
                   1170: 
                   1171:                        else
                   1172: 
                   1173:                                p->inp->readers++;
                   1174: 
                   1175:                }
                   1176: 
                   1177:                if ((rwmode == O_WRONLY || rwmode == O_RDWR) && p->outp) {
                   1178: 
                   1179:                        if (p->outp->writers == VIRGIN_PIPE)
                   1180: 
                   1181:                                p->outp->writers = 1;
                   1182: 
                   1183:                        else
                   1184: 
                   1185:                                p->outp->writers++;
                   1186: 
                   1187:                }
                   1188: 
                   1189:        }
                   1190: 
                   1191: 
                   1192: 
                   1193: /* TTY devices need a tty structure in f->devinfo */
                   1194: 
                   1195:        f->devinfo = (long)p->tty;
                   1196: 
                   1197: 
                   1198: 
                   1199:        return 0;
                   1200: 
                   1201: }
                   1202: 
                   1203: 
                   1204: 
1.1.1.2   root     1205: static long ARGS_ON_STACK 
1.1       root     1206: 
                   1207: pipe_write(f, buf, nbytes)
                   1208: 
                   1209:        FILEPTR *f; const char *buf; long nbytes;
                   1210: 
                   1211: {
                   1212: 
1.1.1.5 ! root     1213:        int plen, j;
1.1       root     1214: 
                   1215:        char *pbuf;
                   1216: 
                   1217:        struct pipe *p;
                   1218: 
                   1219:        struct fifo *this;
                   1220: 
                   1221:        long bytes_written = 0;
                   1222: 
                   1223:        long r;
                   1224: 
                   1225: 
                   1226: 
                   1227:        this = (struct fifo *)f->fc.index;
                   1228: 
                   1229:        p = (f->flags & O_HEAD) ? this->inp : this->outp;
                   1230: 
                   1231:        if (!p) {
                   1232: 
1.1.1.2   root     1233:                DEBUG(("pipe_write: write on wrong end of pipe"));
1.1       root     1234: 
                   1235:                return EACCDN;
                   1236: 
                   1237:        }
                   1238: 
                   1239: 
                   1240: 
                   1241:        if (nbytes > 0 && nbytes <= PIPE_BUF) {
                   1242: 
                   1243: check_atomicity:
                   1244: 
1.1.1.5 ! root     1245:                if (is_terminal(f) && !(f->flags & O_HEAD) &&
1.1       root     1246: 
1.1.1.5 ! root     1247:                    (this->tty->state & TS_HOLD)) {
        !          1248: 
        !          1249:                        if (f->flags & O_NDELAY)
        !          1250: 
        !          1251:                                return 0;
        !          1252: 
        !          1253:                        sleep (IO_Q, (long)&this->tty->state);
        !          1254: 
        !          1255:                        goto check_atomicity;
        !          1256: 
        !          1257:                }
1.1       root     1258: 
1.1.1.5 ! root     1259:                r = PIPESIZ - p->len; /* r is the number of bytes we can write */
1.1       root     1260: 
                   1261:                if (r < nbytes) {
                   1262: 
                   1263:        /* check for broken pipes */
                   1264: 
                   1265:                        if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
                   1266: 
                   1267:                                check_sigs();
                   1268: 
1.1.1.2   root     1269:                                DEBUG(("pipe_write: broken pipe"));
1.1       root     1270: 
                   1271:                                raise(SIGPIPE);
                   1272: 
1.1.1.3   root     1273:                                return EPIPE;
1.1       root     1274: 
                   1275:                        }
                   1276: 
                   1277: /* wake up any readers, and wait for them to gobble some data */
                   1278: 
                   1279:                        if (p->rsel) {
                   1280: 
                   1281:                                wakeselect(p->rsel);
                   1282: 
1.1.1.5 ! root     1283: #if 0
        !          1284: 
1.1       root     1285:                                p->rsel = 0;
                   1286: 
1.1.1.5 ! root     1287: #endif
        !          1288: 
1.1       root     1289:                        }
                   1290: 
                   1291:                        wake(IO_Q, (long)p);
                   1292: 
                   1293:                        sleep(IO_Q, (long)p);
                   1294: 
                   1295:                        goto check_atomicity;
                   1296: 
                   1297:                }
                   1298: 
                   1299:        }
                   1300: 
                   1301: 
                   1302: 
                   1303:        while (nbytes > 0) {
                   1304: 
1.1.1.5 ! root     1305:                plen = p->len;
        !          1306: 
        !          1307:                if (plen < PIPESIZ) {
        !          1308: 
        !          1309:                        pbuf = &p->buf[(p->start + plen) & (PIPESIZ - 1)];
        !          1310: 
        !          1311:                        /* j is the amount that can be written continuously */
        !          1312: 
        !          1313:                        j = (int)(PIPESIZ - (pbuf - p->buf));
        !          1314: 
        !          1315:                        if (j > nbytes) j = (int)nbytes;
1.1       root     1316: 
1.1.1.5 ! root     1317:                        if (j > PIPESIZ - plen) j = PIPESIZ - plen;
1.1       root     1318: 
1.1.1.5 ! root     1319:                        nbytes -= j; plen += j;
1.1       root     1320: 
1.1.1.5 ! root     1321:                        bytes_written += j;
1.1       root     1322: 
1.1.1.5 ! root     1323:                        memcpy (pbuf, buf, j);
1.1       root     1324: 
1.1.1.5 ! root     1325:                        buf += j;
1.1       root     1326: 
1.1.1.5 ! root     1327:                        if (nbytes > 0 && plen < PIPESIZ)
1.1       root     1328: 
1.1.1.5 ! root     1329:                          {
1.1       root     1330: 
1.1.1.5 ! root     1331:                            j = PIPESIZ - plen;
1.1       root     1332: 
1.1.1.5 ! root     1333:                            if (j > nbytes) j = (int)nbytes;
1.1       root     1334: 
1.1.1.5 ! root     1335:                            nbytes -= j; plen += j;
1.1       root     1336: 
1.1.1.5 ! root     1337:                            bytes_written += j;
1.1       root     1338: 
1.1.1.5 ! root     1339:                            memcpy (p->buf, buf, j);
1.1       root     1340: 
1.1.1.5 ! root     1341:                            buf += j;
        !          1342: 
        !          1343:                          }
        !          1344: 
        !          1345:                        p->len = plen;
1.1       root     1346: 
                   1347:                } else {                /* pipe full */
                   1348: 
                   1349:                        if (p->readers == 0 || p->readers == VIRGIN_PIPE) {
                   1350: 
                   1351:                        /* maybe some other signal is waiting for us? */
                   1352: 
                   1353:                                check_sigs();
                   1354: 
1.1.1.2   root     1355:                                DEBUG(("pipe_write: broken pipe"));
1.1       root     1356: 
                   1357:                                raise(SIGPIPE);
                   1358: 
1.1.1.3   root     1359:                                return EPIPE;
1.1       root     1360: 
                   1361:                        }
                   1362: 
                   1363:                        if (f->flags & O_NDELAY) {
                   1364: 
                   1365:                                break;
                   1366: 
                   1367:                        }
                   1368: 
                   1369:        /* is someone select()ing the other end of the pipe for reading? */
                   1370: 
                   1371:                        if (p->rsel) {
                   1372: 
                   1373:                                wakeselect(p->rsel);
                   1374: 
                   1375:                        }
                   1376: 
                   1377:                        wake(IO_Q, (long)p);    /* readers may continue */
                   1378: 
1.1.1.2   root     1379: DEBUG(("pipe_write: sleep on %lx", p));
1.1       root     1380: 
                   1381:                        sleep(IO_Q, (long)p);
                   1382: 
                   1383:                }
                   1384: 
                   1385:        }
                   1386: 
                   1387:        this->time = timestamp;
                   1388: 
                   1389:        this->date = datestamp;
                   1390: 
                   1391:        if (bytes_written > 0) {
                   1392: 
                   1393:                if (p->rsel) {
                   1394: 
                   1395:                        wakeselect(p->rsel);
                   1396: 
                   1397:                }
                   1398: 
                   1399:                wake(IO_Q, (long)p);    /* maybe someone wants this data */
                   1400: 
                   1401:        }
                   1402: 
                   1403: 
                   1404: 
                   1405:        return bytes_written;
                   1406: 
                   1407: }
                   1408: 
                   1409: 
                   1410: 
1.1.1.2   root     1411: static long ARGS_ON_STACK 
1.1       root     1412: 
                   1413: pipe_read(f, buf, nbytes)
                   1414: 
                   1415:        FILEPTR *f; char *buf; long nbytes;
                   1416: 
                   1417: {
                   1418: 
1.1.1.5 ! root     1419:        int plen, j;
1.1       root     1420: 
                   1421:        struct fifo *this;
                   1422: 
                   1423:        struct pipe *p;
                   1424: 
                   1425:        long bytes_read = 0;
                   1426: 
                   1427:        char *pbuf;
                   1428: 
                   1429: 
                   1430: 
                   1431:        this = (struct fifo *)f->fc.index;
                   1432: 
                   1433:        p = (f->flags & O_HEAD) ? this->outp : this->inp;
                   1434: 
                   1435:        if (!p) {
                   1436: 
1.1.1.2   root     1437:                DEBUG(("pipe_read: read on the wrong end of a pipe"));
1.1       root     1438: 
                   1439:                return EACCDN;
                   1440: 
                   1441:        }
                   1442: 
                   1443: 
                   1444: 
                   1445:        while (nbytes > 0) {
                   1446: 
1.1.1.5 ! root     1447:                plen = p->len;
1.1       root     1448: 
1.1.1.5 ! root     1449:                if (plen > 0) {
1.1       root     1450: 
1.1.1.5 ! root     1451:                        pbuf = &p->buf[p->start];
1.1       root     1452: 
1.1.1.5 ! root     1453:                        /* j is the amount that can be read continuously */
1.1       root     1454: 
1.1.1.5 ! root     1455:                        j = PIPESIZ - p->start;
1.1       root     1456: 
1.1.1.5 ! root     1457:                        if (j > nbytes) j = (int)nbytes;
1.1       root     1458: 
1.1.1.5 ! root     1459:                        if (j > plen) j = plen;
1.1       root     1460: 
1.1.1.5 ! root     1461:                        nbytes -= j; plen -= j;
1.1       root     1462: 
1.1.1.5 ! root     1463:                        bytes_read += j;
1.1       root     1464: 
1.1.1.5 ! root     1465:                        p->start += j;
1.1       root     1466: 
1.1.1.5 ! root     1467:                        memcpy (buf, pbuf, j);
1.1       root     1468: 
1.1.1.5 ! root     1469:                        buf += j;
1.1       root     1470: 
1.1.1.5 ! root     1471:                        if (nbytes > 0 && plen > 0)
        !          1472: 
        !          1473:                          {
        !          1474: 
        !          1475:                            j = plen;
        !          1476: 
        !          1477:                            if (j > nbytes) j = (int)nbytes;
        !          1478: 
        !          1479:                            nbytes -= j; plen -= j;
        !          1480: 
        !          1481:                            bytes_read += j;
        !          1482: 
        !          1483:                            p->start = j;
        !          1484: 
        !          1485:                            memcpy (buf, p->buf, j);
        !          1486: 
        !          1487:                            buf += j;
        !          1488: 
        !          1489:                          }
        !          1490: 
        !          1491:                        p->len = plen;
        !          1492: 
        !          1493:                        if (plen == 0 || p->start == PIPESIZ)
        !          1494: 
        !          1495:                          p->start = 0;
1.1       root     1496: 
                   1497:                }
                   1498: 
                   1499:                else if (p->writers <= 0 || p->writers == VIRGIN_PIPE) {
                   1500: 
1.1.1.2   root     1501:                        TRACE(("pipe_read: no more writers"));
1.1       root     1502: 
                   1503:                        break;
                   1504: 
                   1505:                }
                   1506: 
1.1.1.2   root     1507:                else if ((f->flags & O_NDELAY) ||
                   1508: 
                   1509:                           ((this->dosflags & FA_CHANGED) && bytes_read > 0) )
                   1510: 
                   1511:                {
1.1       root     1512: 
                   1513:                        break;
                   1514: 
                   1515:                }
                   1516: 
                   1517:                else {
                   1518: 
                   1519:        /* is someone select()ing the other end of the pipe for writing? */
                   1520: 
                   1521:                        if (p->wsel) {
                   1522: 
                   1523:                                wakeselect(p->wsel);
                   1524: 
                   1525:                        }
                   1526: 
                   1527:                        wake(IO_Q, (long)p);    /* writers may continue */
                   1528: 
                   1529:                        sleep(IO_Q, (long)p);
                   1530: 
                   1531:                }
                   1532: 
                   1533:        }
                   1534: 
                   1535:        if (bytes_read > 0) {
                   1536: 
                   1537:                if (p->wsel) {
                   1538: 
                   1539:                        wakeselect(p->wsel);
                   1540: 
                   1541:                }
                   1542: 
                   1543:                wake(IO_Q, (long)p);    /* wake writers */
                   1544: 
                   1545:        }
                   1546: 
                   1547:        return bytes_read;
                   1548: 
                   1549: }
                   1550: 
                   1551: 
                   1552: 
1.1.1.2   root     1553: static long ARGS_ON_STACK 
1.1       root     1554: 
1.1.1.5 ! root     1555: pty_write(f, buf, nbytes)
        !          1556: 
        !          1557:        FILEPTR *f; const char *buf; long nbytes;
        !          1558: 
        !          1559: {
        !          1560: 
        !          1561:        long bytes_written = 0;
        !          1562: 
        !          1563: 
        !          1564: 
        !          1565:        if (!nbytes)
        !          1566: 
        !          1567:                return 0;
        !          1568: 
        !          1569:        if (f->flags & O_HEAD)
        !          1570: 
        !          1571:                return pipe_write(f, buf, nbytes);
        !          1572: 
        !          1573:        if (nbytes != 4)
        !          1574: 
        !          1575:                ALERT("pty_write: slave nbytes != 4");
        !          1576: 
        !          1577:        bytes_written = pipe_write(f, buf+3, 1);
        !          1578: 
        !          1579:        if (bytes_written == 1)
        !          1580: 
        !          1581:                bytes_written = 4;
        !          1582: 
        !          1583:        return bytes_written;
        !          1584: 
        !          1585: }
        !          1586: 
        !          1587: 
        !          1588: 
        !          1589: static long ARGS_ON_STACK 
        !          1590: 
        !          1591: pty_read(f, buf, nbytes)
        !          1592: 
        !          1593:        FILEPTR *f; char *buf; long nbytes;
        !          1594: 
        !          1595: {
        !          1596: 
        !          1597:        long bytes_read = 0;
        !          1598: 
        !          1599: 
        !          1600: 
        !          1601:        if (!nbytes)
        !          1602: 
        !          1603:                return 0;
        !          1604: 
        !          1605:        if (!(f->flags & O_HEAD))
        !          1606: 
        !          1607:                return pipe_read(f, buf, nbytes);
        !          1608: 
        !          1609:        if (nbytes != 4)
        !          1610: 
        !          1611:                ALERT("pty_read: master nbytes != 4");
        !          1612: 
        !          1613:        bytes_read = pipe_read(f, buf+3, 1);
        !          1614: 
        !          1615:        if (bytes_read == 1)
        !          1616: 
        !          1617:                bytes_read = 4;
        !          1618: 
        !          1619:        return bytes_read;
        !          1620: 
        !          1621: }
        !          1622: 
        !          1623: 
        !          1624: 
        !          1625: static long ARGS_ON_STACK 
        !          1626: 
        !          1627: pty_writeb(f, buf, nbytes)
        !          1628: 
        !          1629:        FILEPTR *f; const char *buf; long nbytes;
        !          1630: 
        !          1631: {
        !          1632: 
        !          1633:        if (!nbytes)
        !          1634: 
        !          1635:                return 0;
        !          1636: 
        !          1637:        if (f->flags & O_HEAD)
        !          1638: 
        !          1639:                return EUNDEV;
        !          1640: 
        !          1641:        return pipe_write(f, buf, nbytes);
        !          1642: 
        !          1643: }
        !          1644: 
        !          1645: 
        !          1646: 
        !          1647: static long ARGS_ON_STACK 
        !          1648: 
        !          1649: pty_readb(f, buf, nbytes)
        !          1650: 
        !          1651:        FILEPTR *f; char *buf; long nbytes;
        !          1652: 
        !          1653: {
        !          1654: 
        !          1655:        if (!nbytes)
        !          1656: 
        !          1657:                return 0;
        !          1658: 
        !          1659:        if (!(f->flags & O_HEAD))
        !          1660: 
        !          1661:                return EUNDEV;
        !          1662: 
        !          1663:        return pipe_read(f, buf, nbytes);
        !          1664: 
        !          1665: }
        !          1666: 
        !          1667: 
        !          1668: 
        !          1669: static long ARGS_ON_STACK 
        !          1670: 
1.1       root     1671: pipe_ioctl(f, mode, buf)
                   1672: 
                   1673:        FILEPTR *f; int mode; void *buf;
                   1674: 
                   1675: {
                   1676: 
                   1677:        struct pipe *p;
                   1678: 
                   1679:        struct fifo *this;
                   1680: 
                   1681:        struct flock *lck;
                   1682: 
                   1683: 
                   1684: 
                   1685:        long r;
                   1686: 
                   1687: 
                   1688: 
                   1689:        this = (struct fifo *)f->fc.index;
                   1690: 
                   1691: 
                   1692: 
1.1.1.5 ! root     1693:        switch(mode) {
1.1       root     1694: 
1.1.1.5 ! root     1695:        case FIONREAD:
        !          1696: 
        !          1697:                p = (f->flags & O_HEAD) ? this->outp : this->inp;
        !          1698: 
        !          1699:                if (p == 0) return EINVFN;
1.1       root     1700: 
1.1.1.5 ! root     1701:                r = p->len;
        !          1702: 
        !          1703:                if (r == 0) {
1.1       root     1704: 
                   1705:                        if (p->writers <= 0 || p->writers == VIRGIN_PIPE) {
                   1706: 
1.1.1.2   root     1707:                                DEBUG(("pipe FIONREAD: no writers"));
1.1       root     1708: 
1.1.1.5 ! root     1709:        /* arguably, we should return 0 for EOF, but this would break MINIWIN and
        !          1710: 
        !          1711:         * perhaps some other MultiTOS programs
        !          1712: 
        !          1713:         */
        !          1714: 
1.1       root     1715:                                r = -1;
                   1716: 
1.1.1.5 ! root     1717:                        }
1.1       root     1718: 
1.1.1.5 ! root     1719:                } else if (is_terminal(f)) {
1.1       root     1720: 
1.1.1.5 ! root     1721:                        if (!(f->flags & O_HEAD))
1.1       root     1722: 
1.1.1.5 ! root     1723:                                r = r >> 2;             /* r /= 4 */
1.1       root     1724: 
1.1.1.5 ! root     1725:                        else if (this->tty->state & TS_HOLD)
1.1       root     1726: 
1.1.1.5 ! root     1727:                                r = 0;
1.1       root     1728: 
1.1.1.5 ! root     1729:                }
1.1       root     1730: 
1.1.1.5 ! root     1731:                *((long *) buf) = r;
1.1       root     1732: 
1.1.1.5 ! root     1733:                break;
1.1       root     1734: 
1.1.1.5 ! root     1735:        case FIONWRITE:
        !          1736: 
        !          1737:                p = (f->flags & O_HEAD) ? this->inp : this->outp;
1.1       root     1738: 
1.1.1.5 ! root     1739:                if (p == 0) return EINVFN;
1.1       root     1740: 
1.1.1.5 ! root     1741:                if (p->readers <= 0) {
1.1       root     1742: 
1.1.1.5 ! root     1743:        /* see compatibility comment under FIONREAD */
1.1       root     1744: 
1.1.1.5 ! root     1745:                        r = -1;
1.1       root     1746: 
1.1.1.5 ! root     1747:                } else {
1.1       root     1748: 
1.1.1.5 ! root     1749:                        r = PIPESIZ - p->len;
1.1       root     1750: 
1.1.1.5 ! root     1751:                        if (is_terminal(f)) {
1.1       root     1752: 
1.1.1.5 ! root     1753:                                if (f->flags & O_HEAD)
1.1       root     1754: 
                   1755:                                        r = r >> 2;     /* r /= 4 */
                   1756: 
1.1.1.5 ! root     1757:                                else if (this->tty->state & TS_HOLD)
        !          1758: 
        !          1759:                                        r = 0;
        !          1760: 
1.1       root     1761:                        }
                   1762: 
1.1.1.5 ! root     1763:                }
1.1       root     1764: 
1.1.1.5 ! root     1765:                *((long *) buf) = r;
1.1       root     1766: 
1.1.1.5 ! root     1767:                break;
        !          1768: 
        !          1769:        case FIOEXCEPT:
        !          1770: 
        !          1771:                *((long *) buf) = 0;
        !          1772: 
        !          1773:                break;
        !          1774: 
        !          1775:        case F_SETLK:
        !          1776: 
        !          1777:        case F_SETLKW:
1.1       root     1778: 
                   1779:                lck = (struct flock *)buf;
                   1780: 
1.1.1.2   root     1781:                while (this->flags & O_LOCK) {
1.1       root     1782: 
                   1783:                        if (this->lockpid != curproc->pid) {
                   1784: 
1.1.1.2   root     1785:                                DEBUG(("pipe_ioctl: pipe already locked"));
1.1       root     1786: 
1.1.1.2   root     1787:                                if (mode == F_SETLKW && lck->l_type != F_UNLCK) {
1.1       root     1788: 
1.1.1.2   root     1789:                                        sleep(IO_Q, (long)this);                /* sleep a while */
                   1790: 
                   1791:                                }
                   1792: 
                   1793:                                else
                   1794: 
                   1795:                                        return ELOCKED;
                   1796: 
                   1797:                        } else
                   1798: 
                   1799:                                break;
1.1       root     1800: 
                   1801:                }
                   1802: 
                   1803:                if (lck->l_type == F_UNLCK) {
                   1804: 
                   1805:                        if (!(f->flags & O_LOCK)) {
                   1806: 
1.1.1.2   root     1807:                                DEBUG(("pipe_ioctl: wrong file descriptor for UNLCK"));
1.1       root     1808: 
                   1809:                                return ENSLOCK;
                   1810: 
                   1811:                        }
                   1812: 
                   1813:                        this->flags &= ~O_LOCK;
                   1814: 
                   1815:                        this->lockpid = 0;
                   1816: 
                   1817:                        f->flags &= ~O_LOCK;
                   1818: 
1.1.1.2   root     1819:                        wake(IO_Q, (long)this); /* wake up anyone waiting on the lock */
                   1820: 
1.1       root     1821:                }
                   1822: 
                   1823:                else {
                   1824: 
                   1825:                        this->flags |= O_LOCK;
                   1826: 
                   1827:                        this->lockpid = curproc->pid;
                   1828: 
                   1829:                        f->flags |= O_LOCK;
                   1830: 
                   1831:                }
                   1832: 
1.1.1.5 ! root     1833:                break;
1.1       root     1834: 
1.1.1.5 ! root     1835:        case F_GETLK:
1.1       root     1836: 
                   1837:                lck = (struct flock *)buf;
                   1838: 
                   1839:                if (this->flags & O_LOCK) {
                   1840: 
                   1841:                        lck->l_type = F_WRLCK;
                   1842: 
                   1843:                        lck->l_start = lck->l_len = 0;
                   1844: 
                   1845:                        lck->l_pid = this->lockpid;
                   1846: 
                   1847:                }
                   1848: 
                   1849:                else
                   1850: 
                   1851:                        lck->l_type = F_UNLCK;
                   1852: 
1.1.1.5 ! root     1853:                break;
        !          1854: 
        !          1855:        case TIOCSTART:
        !          1856: 
        !          1857:                if (is_terminal(f) && !(f->flags & O_HEAD) &&
        !          1858: 
        !          1859: #if 0
        !          1860: 
        !          1861:                    NULL != (p = this->outp) && p->rsel && p->tail != p->head)
        !          1862: 
        !          1863: #else
        !          1864: 
        !          1865:                    NULL != (p = this->outp) && p->rsel && p->len > 0)
        !          1866: 
        !          1867: #endif
1.1       root     1868: 
1.1.1.5 ! root     1869:                        wakeselect (p->rsel);
        !          1870: 
        !          1871:                break;
        !          1872: 
        !          1873:        case TIOCFLUSH:
        !          1874: 
        !          1875:            {
1.1       root     1876: 
1.1.1.4   root     1877:                long flushtype;
                   1878: 
                   1879:                long *which;
                   1880: 
                   1881: 
                   1882: 
                   1883:                which = (long *)buf;
                   1884: 
                   1885:                if (!which || !(*which & 3))
                   1886: 
                   1887:                        flushtype = 3;
                   1888: 
                   1889:                else
                   1890: 
                   1891:                        flushtype = *which;
                   1892: 
                   1893: 
                   1894: 
                   1895:                if ((flushtype & 1) && this->inp) {
1.1       root     1896: 
1.1.1.5 ! root     1897:                        this->inp->start = this->inp->len = 0;
1.1       root     1898: 
                   1899:                        wake(IO_Q, (long)this->inp);
                   1900: 
                   1901:                }
                   1902: 
1.1.1.4   root     1903:                if ((flushtype & 2) && this->outp) {
1.1       root     1904: 
1.1.1.5 ! root     1905:                        this->outp->start = this->outp->len = 0;
1.1       root     1906: 
                   1907:                        wake(IO_Q, (long)this->outp);
                   1908: 
                   1909:                }
                   1910: 
1.1.1.5 ! root     1911:                break;
1.1.1.4   root     1912: 
1.1.1.5 ! root     1913:            }
1.1.1.4   root     1914: 
1.1.1.5 ! root     1915:        case TIOCOUTQ:
1.1.1.4   root     1916: 
1.1.1.5 ! root     1917:                p = (f->flags & O_HEAD) ? this->inp : this->outp;
1.1.1.4   root     1918: 
1.1.1.5 ! root     1919:                assert(p != 0);
        !          1920: 
        !          1921:                if (p->readers <= 0) {
1.1.1.4   root     1922: 
1.1.1.5 ! root     1923:                        r = -1;
1.1.1.4   root     1924: 
1.1.1.5 ! root     1925:                } else {
1.1.1.4   root     1926: 
1.1.1.5 ! root     1927:                        r = p->len;
1.1.1.4   root     1928: 
1.1.1.5 ! root     1929:                        if (is_terminal(f) && (f->flags & O_HEAD))
1.1.1.4   root     1930: 
1.1.1.5 ! root     1931:                                r = r >> 2;     /* r /= 4 */
1.1.1.4   root     1932: 
1.1.1.5 ! root     1933:                }
1.1.1.4   root     1934: 
1.1.1.5 ! root     1935:                *((long *) buf) = r;
1.1.1.4   root     1936: 
1.1.1.5 ! root     1937:                break;
        !          1938: 
        !          1939:        case TIOCIBAUD:
        !          1940: 
        !          1941:        case TIOCOBAUD:
1.1       root     1942: 
                   1943:                *(long *)buf = -1L;
                   1944: 
1.1.1.5 ! root     1945:                break;
        !          1946: 
        !          1947:        case TIOCGFLAGS:
1.1       root     1948: 
                   1949:                *((unsigned short *)buf) = 0;
                   1950: 
1.1.1.5 ! root     1951:                break;
        !          1952: 
        !          1953:        case TCURSOFF:
        !          1954: 
        !          1955:        case TCURSON:
        !          1956: 
        !          1957:        case TCURSSRATE:
        !          1958: 
        !          1959:        case TCURSBLINK:
        !          1960: 
        !          1961:        case TCURSSTEADY:
        !          1962: 
        !          1963:        case TCURSGRATE:
1.1.1.2   root     1964: 
                   1965:        /* kludge: this assumes TOSWIN style escape sequences */
                   1966: 
                   1967:                tty_putchar(f, (long)'\033', RAW);
                   1968: 
                   1969:                switch (mode) {
                   1970: 
                   1971:                case TCURSOFF:
                   1972: 
                   1973:                        tty_putchar(f, (long)'f', RAW);
                   1974: 
                   1975:                        break;
                   1976: 
                   1977:                case TCURSON:
                   1978: 
                   1979:                        tty_putchar(f, (long)'e', RAW);
                   1980: 
                   1981:                        break;
                   1982: 
                   1983:                case TCURSSRATE:
                   1984: 
                   1985:                        this->cursrate = *((int *)buf);
                   1986: 
                   1987:                        /* fall through */
                   1988: 
                   1989:                case TCURSBLINK:
                   1990: 
                   1991:                        tty_putchar(f, (long)'t', RAW);
                   1992: 
                   1993:                        tty_putchar(f, (long)this->cursrate+32, RAW);
                   1994: 
                   1995:                        break;
                   1996: 
                   1997:                case TCURSSTEADY:
                   1998: 
                   1999:                        tty_putchar(f, (long)'t', RAW);
                   2000: 
                   2001:                        tty_putchar(f, (long)32, RAW);
                   2002: 
                   2003:                        break;
                   2004: 
                   2005:                case TCURSGRATE:
                   2006: 
                   2007:                        return this->cursrate;
                   2008: 
                   2009:                }
                   2010: 
1.1.1.5 ! root     2011:                break;
        !          2012: 
        !          2013:        default:
1.1       root     2014: 
                   2015:        /* if the file is a terminal, Fcntl will automatically
                   2016: 
                   2017:         * call tty_ioctl for us to handle 'generic' terminal
                   2018: 
                   2019:         * functions
                   2020: 
                   2021:         */
                   2022: 
                   2023:                return EINVFN;
                   2024: 
                   2025:        }
                   2026: 
                   2027: 
                   2028: 
                   2029:        return 0;
                   2030: 
                   2031: }
                   2032: 
                   2033: 
                   2034: 
1.1.1.2   root     2035: static long ARGS_ON_STACK 
1.1       root     2036: 
                   2037: pipe_lseek(f, where, whence)
                   2038: 
                   2039:        FILEPTR *f; long where; int whence;
                   2040: 
                   2041: {
                   2042: 
1.1.1.2   root     2043:        UNUSED(f); UNUSED(where); UNUSED(whence);
                   2044: 
1.1       root     2045:        return EACCDN;
                   2046: 
                   2047: }
                   2048: 
                   2049: 
                   2050: 
1.1.1.2   root     2051: static long ARGS_ON_STACK 
1.1       root     2052: 
                   2053: pipe_datime(f, timeptr, rwflag)
                   2054: 
                   2055:        FILEPTR *f;
                   2056: 
                   2057:        short *timeptr;
                   2058: 
                   2059:        int rwflag;
                   2060: 
                   2061: {
                   2062: 
                   2063:        struct fifo *this;
                   2064: 
                   2065: 
                   2066: 
                   2067:        this = (struct fifo *)f->fc.index;
                   2068: 
                   2069:        if (rwflag) {
                   2070: 
                   2071:                this->time = timeptr[0];
                   2072: 
                   2073:                this->date = timeptr[1];
                   2074: 
                   2075:        }
                   2076: 
                   2077:        else {
                   2078: 
                   2079:                timeptr[0] = this->time;
                   2080: 
                   2081:                timeptr[1] = this->date;
                   2082: 
                   2083:        }
                   2084: 
                   2085:        return 0;
                   2086: 
                   2087: }
                   2088: 
                   2089: 
                   2090: 
1.1.1.2   root     2091: static long ARGS_ON_STACK 
1.1       root     2092: 
                   2093: pipe_close(f, pid)
                   2094: 
                   2095:        FILEPTR *f;
                   2096: 
                   2097:        int pid;
                   2098: 
                   2099: {
                   2100: 
                   2101:        struct fifo *this, *old;
                   2102: 
                   2103:        struct pipe *p;
                   2104: 
                   2105:        int rwmode;
                   2106: 
                   2107:        FILEPTR **old_x, *x;
                   2108: 
                   2109: 
                   2110: 
                   2111:        this = (struct fifo *)f->fc.index;
                   2112: 
                   2113: 
                   2114: 
1.1.1.5 ! root     2115:        if (f->links <= 0) {
1.1       root     2116: 
                   2117: 
                   2118: 
1.1.1.5 ! root     2119: /* wake any processes waiting on this pipe */
1.1       root     2120: 
1.1.1.5 ! root     2121:                wake(IO_Q, (long)this->inp);
1.1       root     2122: 
1.1.1.5 ! root     2123:                if (this->inp->rsel)
1.1       root     2124: 
1.1.1.5 ! root     2125:                        wakeselect(this->inp->rsel);
1.1       root     2126: 
1.1.1.5 ! root     2127:                if (this->inp->wsel)
1.1       root     2128: 
1.1.1.5 ! root     2129:                        wakeselect(this->inp->wsel);
1.1       root     2130: 
                   2131: 
                   2132: 
1.1.1.5 ! root     2133:                if (this->outp) {
1.1       root     2134: 
1.1.1.5 ! root     2135:                        wake(IO_Q, (long)this->outp);
1.1       root     2136: 
1.1.1.5 ! root     2137:                        if (this->outp->wsel)
1.1       root     2138: 
1.1.1.5 ! root     2139:                                wakeselect(this->outp->wsel);
1.1       root     2140: 
1.1.1.5 ! root     2141:                        if (this->outp->rsel)
        !          2142: 
        !          2143:                                wakeselect(this->outp->rsel);
        !          2144: 
        !          2145:                }
1.1       root     2146: 
                   2147: 
                   2148: 
                   2149: /* remove the file pointer from the list of open file pointers 
                   2150: 
                   2151:  * of this pipe
                   2152: 
                   2153:  */
                   2154: 
                   2155:                old_x = &this->open;
                   2156: 
                   2157:                x = this->open;
                   2158: 
                   2159:                while (x && x != f) {
                   2160: 
                   2161:                        old_x = &x->next;
                   2162: 
                   2163:                        x = x->next;
                   2164: 
                   2165:                }
                   2166: 
                   2167:                assert(x);
                   2168: 
                   2169:                *old_x = f->next;
                   2170: 
                   2171:                /* f->next = 0; */
                   2172: 
                   2173: 
                   2174: 
                   2175:                rwmode = f->flags & O_RWMODE;
                   2176: 
                   2177:                if (rwmode == O_RDONLY || rwmode == O_RDWR) {
                   2178: 
                   2179:                        p = (f->flags & O_HEAD) ? this->outp : this->inp;
                   2180: 
                   2181: /* note that this can never be a virgin pipe, since we had a handle
                   2182: 
                   2183:  * on it!
                   2184: 
                   2185:  */                    if (p)
                   2186: 
                   2187:                                p->readers--;
                   2188: 
                   2189:                }
                   2190: 
                   2191:                if (rwmode == O_WRONLY || rwmode == O_RDWR) {
                   2192: 
                   2193:                        p = (f->flags & O_HEAD) ? this->inp : this->outp;
                   2194: 
                   2195:                        if (p) p->writers--;
                   2196: 
                   2197:                }
                   2198: 
                   2199: 
                   2200: 
                   2201: /* correct for the "selfread" flag (see pipe_creat) */
                   2202: 
                   2203:                if ((f->flags & O_HEAD) && !(this->dosflags & 0x02))
                   2204: 
                   2205:                        this->inp->readers--;
                   2206: 
                   2207: 
                   2208: 
                   2209: /* check for locks */
                   2210: 
                   2211:                if ((f->flags & O_LOCK) && (this->lockpid == pid)) {
                   2212: 
                   2213:                        this->flags &= ~O_LOCK;
                   2214: 
1.1.1.2   root     2215:                        wake(IO_Q, (long)this); /* wake up anyone waiting on the lock */
                   2216: 
1.1       root     2217:                }
                   2218: 
                   2219:        }
                   2220: 
                   2221: 
                   2222: 
                   2223: /* see if we're finished with the pipe */
                   2224: 
                   2225:        if (this->inp->readers == VIRGIN_PIPE)
                   2226: 
                   2227:                this->inp->readers = 0;
                   2228: 
                   2229:        if (this->inp->writers == VIRGIN_PIPE)
                   2230: 
                   2231:                this->inp->writers = 0;
                   2232: 
                   2233: 
                   2234: 
                   2235:        if (this->inp->readers <= 0 && this->inp->writers <= 0) {
                   2236: 
1.1.1.2   root     2237:                TRACE(("disposing of closed fifo"));
1.1       root     2238: 
                   2239: /* unlink from list of FIFOs */
                   2240: 
                   2241:                if (rootlist == this)
                   2242: 
                   2243:                        rootlist = this->next;
                   2244: 
                   2245:                else {
                   2246: 
                   2247:                        for (old = rootlist; old->next != this;
                   2248: 
                   2249:                                        old = old->next) {
                   2250: 
                   2251:                                if (!old) {
                   2252: 
                   2253:                                        ALERT("fifo not on list???");
                   2254: 
                   2255:                                        return EINTRN;
                   2256: 
                   2257:                                }
                   2258: 
                   2259:                        }
                   2260: 
                   2261:                        old->next = this->next;
                   2262: 
                   2263:                }
                   2264: 
                   2265:                kfree(this->inp);
                   2266: 
                   2267:                if (this->outp) kfree(this->outp);
                   2268: 
1.1.1.4   root     2269:                if (this->tty) kfree(this->tty);
                   2270: 
1.1       root     2271:                kfree(this);
                   2272: 
                   2273:                pipetime = timestamp;
                   2274: 
                   2275:                pipedate = datestamp;
                   2276: 
                   2277:        }
                   2278: 
                   2279: 
                   2280: 
                   2281:        return 0;
                   2282: 
                   2283: }
                   2284: 
                   2285: 
                   2286: 
1.1.1.2   root     2287: static long ARGS_ON_STACK 
1.1       root     2288: 
                   2289: pipe_select(f, proc, mode)
                   2290: 
                   2291:        FILEPTR *f;
                   2292: 
                   2293:        long proc;
                   2294: 
                   2295:        int mode;
                   2296: 
                   2297: {
                   2298: 
                   2299:        struct fifo *this;
                   2300: 
                   2301:        struct pipe *p;
                   2302: 
                   2303: 
                   2304: 
                   2305:        this = (struct fifo *)f->fc.index;
                   2306: 
                   2307: 
                   2308: 
                   2309:        if (mode == O_RDONLY) {
                   2310: 
                   2311:                p = (f->flags & O_HEAD) ? this->outp : this->inp;
                   2312: 
                   2313:                if (!p) {
                   2314: 
1.1.1.2   root     2315:                        DEBUG(("read select on wrong end of pipe"));
1.1       root     2316: 
                   2317:                        return 0;
                   2318: 
                   2319:                }
                   2320: 
                   2321: 
                   2322: 
                   2323: /* NOTE: if p->writers <= 0 then reads won't block (they'll fail) */
                   2324: 
1.1.1.5 ! root     2325:                if ((p->len > 0 &&
        !          2326: 
        !          2327:                        (!is_terminal(f) || !(f->flags & O_HEAD) ||
        !          2328: 
        !          2329:                         !(this->tty->state & TS_HOLD))) ||
        !          2330: 
        !          2331:                    p->writers <= 0) {
1.1       root     2332: 
                   2333:                        return 1;
                   2334: 
                   2335:                }
                   2336: 
                   2337: 
                   2338: 
1.1.1.4   root     2339:                if (p->rsel)
1.1       root     2340: 
1.1.1.4   root     2341:                        return 2;       /* collision */
1.1       root     2342: 
1.1.1.4   root     2343:                p->rsel = proc;
1.1       root     2344: 
1.1.1.5 ! root     2345:                if (is_terminal(f) && !(f->flags & O_HEAD))
        !          2346: 
        !          2347:                        this->tty->rsel = proc;
        !          2348: 
1.1       root     2349:                return 0;
                   2350: 
                   2351:        } else if (mode == O_WRONLY) {
                   2352: 
                   2353:                p = (f->flags & O_HEAD) ? this->inp : this->outp;
                   2354: 
                   2355:                if (!p) {
                   2356: 
1.1.1.2   root     2357:                        DEBUG(("write select on wrong end of pipe"));
1.1       root     2358: 
                   2359:                        return 0;
                   2360: 
                   2361:                }
                   2362: 
1.1.1.5 ! root     2363:                if ((p->len < PIPESIZ &&
1.1       root     2364: 
1.1.1.5 ! root     2365:                        (!is_terminal(f) || (f->flags & O_HEAD) ||
1.1       root     2366: 
1.1.1.5 ! root     2367:                         !(this->tty->state & TS_HOLD))) ||
        !          2368: 
        !          2369:                    p->readers <= 0)
1.1       root     2370: 
                   2371:                        return 1;       /* data may be written */
                   2372: 
1.1.1.4   root     2373:                if (p->wsel)
                   2374: 
                   2375:                        return 2;       /* collision */
1.1       root     2376: 
1.1.1.4   root     2377:                p->wsel = proc;
1.1       root     2378: 
1.1.1.5 ! root     2379:                if (is_terminal(f) && !(f->flags & O_HEAD))
        !          2380: 
        !          2381:                        this->tty->wsel = proc;
        !          2382: 
1.1       root     2383:                return 0;
                   2384: 
                   2385:        }
                   2386: 
                   2387:        return 0;
                   2388: 
                   2389: }
                   2390: 
                   2391: 
                   2392: 
1.1.1.2   root     2393: static void ARGS_ON_STACK 
1.1       root     2394: 
                   2395: pipe_unselect(f, proc, mode)
                   2396: 
                   2397:        FILEPTR *f;
                   2398: 
                   2399:        long proc;
                   2400: 
                   2401:        int mode;
                   2402: 
                   2403: {
                   2404: 
                   2405:        struct fifo *this;
                   2406: 
                   2407:        struct pipe *p;
                   2408: 
                   2409: 
                   2410: 
                   2411:        this = (struct fifo *)f->fc.index;
                   2412: 
                   2413: 
                   2414: 
                   2415:        if (mode == O_RDONLY) {
                   2416: 
                   2417:                p = (f->flags & O_HEAD) ? this->outp : this->inp;
                   2418: 
                   2419:                if (!p) {
                   2420: 
                   2421:                        return;
                   2422: 
                   2423:                }
                   2424: 
                   2425:                if (p->rsel == proc)
                   2426: 
                   2427:                        p->rsel = 0;
                   2428: 
                   2429:        } else if (mode == O_WRONLY) {
                   2430: 
                   2431:                p = (f->flags & O_HEAD) ? this->inp : this->outp;
                   2432: 
                   2433:                if (!p) {
                   2434: 
                   2435:                        return;
                   2436: 
                   2437:                }
                   2438: 
                   2439:                if (p->wsel == proc)
                   2440: 
                   2441:                        p->wsel = 0;
                   2442: 
                   2443:        }
                   2444: 
                   2445: }
                   2446: 

unix.superglobalmegacorp.com

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