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