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

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

unix.superglobalmegacorp.com

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