|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/user.h"
3: #include "sys/buf.h"
4: #include "sys/stream.h"
5: #include "sys/inode.h"
6: #include "sys/filio.h"
7: #include "sys/ttyio.h"
8: #include "sys/conf.h"
9: #include "sys/proc.h"
10: #include "sys/file.h"
11:
12: extern struct queue queue[];
13:
14: #define STIPRI 28
15: #define STOPRI 29
16:
17: extern struct stdata streams[];
18: extern int streamcnt;
19:
20: struct stdata *stenter();
21: int strput(), stwsrv(), nulldev(), nilput();
22: long nilopen();
23:
24: struct qinit strdata = { strput, NULL, nilopen, nulldev, 512, 256 };
25: struct qinit stwdata = { nulldev, stwsrv, nilopen, nulldev, 0, 0};
26: struct qinit nilw = { nilput, NULL, nilopen, nulldev, 1, 0 };
27: struct streamtab nilinfo = { &nilw, &nilw };
28:
29: /*
30: * open a stream device
31: * returns the inode,
32: * which may be different from ip,
33: * in which event ip has been put.
34: * return NULL on error,
35: * in which event ip has also been put.
36: */
37: struct inode *
38: stopen(qinfo, dev, flag, ip)
39: struct streamtab *qinfo;
40: dev_t dev;
41: struct inode *ip;
42: {
43: register struct queue *qp;
44: register struct stdata *sp;
45: register struct inode *nip;
46: register s;
47:
48: if (sp = ip->i_sptr) { /* already streaming? */
49: if (sp->flag & EXCL && u.u_uid!=0
50: && (sp->pgrp==0 || sp->pgrp != u.u_procp->p_pgrp)) {
51: u.u_error = ENXIO;
52: iput(ip);
53: return(NULL);
54: }
55: if (stenter(ip)==NULL) {
56: iput(ip);
57: return(NULL);
58: }
59: while (sp->flag&STWOPEN) {
60: if (tsleep((caddr_t)sp, STOPRI, 0)!=TS_OK) {
61: stexit(ip);
62: u.u_error = ENXIO;
63: iput(ip);
64: return(NULL);
65: }
66: }
67: if (sp->flag&HUNGUP) {
68: flushq(RD(sp->wrq), 1);
69: stexit(ip);
70: u.u_error = ENXIO;
71: iput(ip);
72: return(NULL);
73: }
74: for (qp = sp->wrq; qp->next && (qp->next->flag&QREADR)==0; qp = qp->next) {
75: /* device-cloning; qopen s.b. struct inode * */
76: nip = (struct inode *)
77: (*qp->next->qinfo->qopen)(RD(qp->next), dev);
78: if (nip == NULL) { /* open failed */
79: stexit(ip);
80: u.u_error = ENXIO;
81: iput(ip);
82: return(NULL);
83: }
84: if ((long)nip != 1) { /* changed inode, so stop now */
85: stexit(ip);
86: iput(ip);
87: return(nip);
88: }
89: }
90: stexit(ip);
91: return(ip);
92: } else { /* new stream */
93: register struct stdata *esp = &streams[streamcnt];
94: register struct queue *nq;
95:
96: for (sp = streams; sp < esp; sp++)
97: if (sp->wrq==NULL)
98: break;
99: if (sp >= esp) {
100: printf("out of streams\n");
101: u.u_error = ENFILE;
102: iput(ip);
103: return(NULL);
104: }
105: if ((qp = allocq()) == NULL) {
106: printf("Out of queues in stopen\n");
107: u.u_error = ENFILE;
108: iput(ip);
109: return(NULL);
110: }
111: sp->wrq = WR(qp);
112: sp->pgrp = 0;
113: sp->inode = ip;
114: sp->flag = 0;
115: sp->iocblk = NULL;
116: sp->count = 1;
117: qp->ptr = (caddr_t)sp;
118: WR(qp)->ptr = (caddr_t)sp;
119: qp->qinfo = &strdata;
120: WR(qp)->qinfo = &stwdata;
121: qp->flag |= QBIGB;
122: WR(qp)->flag |= QDELIM;
123: ip->i_sptr = sp;
124: s = spl6();
125: if (qattach(qinfo, qp, dev) == 0) {
126: sp->flag |= HUNGUP;
127: splx(s);
128: stexit(ip);
129: u.u_error = ENXIO;
130: iput(ip);
131: return(NULL);
132: }
133: nq = RD(WR(qp)->next);
134: sp->flag |= STWOPEN;
135: nip = (struct inode *)(*nq->qinfo->qopen)(nq, dev);
136: sp->flag &= ~STWOPEN;
137: splx(s);
138: wakeup((caddr_t)sp);
139: if (nip == NULL) {
140: qdetach(nq, 0);
141: sp->flag |= HUNGUP;
142: stexit(ip);
143: u.u_error = ENXIO;
144: iput(ip);
145: return(NULL);
146: }
147: if ((long)nip != 1) {
148: stexit(ip);
149: iput(ip);
150: return(nip);
151: }
152: stexit(ip);
153: return(ip);
154: }
155: }
156:
157: /*
158: * Shut down a stream
159: * -- pop all line disciplines
160: * -- shut down the driver
161: */
162: stclose(ip, sleepOK)
163: struct inode *ip;
164: {
165: register struct stdata *stp;
166: register struct queue *qp;
167: register s;
168: register struct block *bp;
169:
170: s = spl6();
171: if ((stp = ip->i_sptr) == NULL) {
172: splx(s);
173: return;
174: }
175: forceclose(stp, FREAD|FWRITE);
176: if (stp->count != 0) {
177: printf("count is %d in stclose, stream %x\n", stp->count, stp);
178: splx(s);
179: return;
180: }
181: ip->i_sptr = NULL;
182: splx(s);
183: qp = stp->wrq;
184: while (qp->next) {
185: register i;
186: /* detect cross-connects, and seal off other end */
187: if (qp->next->flag & QREADR) {
188: putctl(qp->next, M_HANGUP);
189: if (qattach(&nilinfo, qp->next, (dev_t)-1) == 0)
190: panic("close/qattach");
191: WR(qp->next)->next = NULL;
192: break;
193: }
194: if (sleepOK && (stp->flag&HUNGUP)==0)
195: for (i=0; qp->next->count!=0 && i<60; i++)
196: tsleep((caddr_t)qp, STIPRI, 1);
197: qdetach(RD(qp->next), 1);
198: }
199: flushq(qp, 1);
200: while (bp = getq(RD(qp))) {
201: if (bp->type == M_PASS)
202: closef(((struct kpassfd *)bp->rptr)->f.fp);
203: freeb(bp);
204: }
205: stp->wrq = NULL;
206: RD(qp)->flag = 0;
207: qp->flag = 0;
208: }
209:
210: /*
211: * Read a stream
212: */
213: stread(ip)
214: struct inode *ip;
215: {
216: register struct stdata *stq;
217: register struct block *bp;
218: register n;
219: register s, nc = 0;
220:
221: if ((stq = stenter(ip)) == NULL) {
222: u.u_error = 0; /* return EOF not error */
223: return;
224: }
225: /*
226: * Read is complete when:
227: * Q is empty and some data has been read and next Q might not generate
228: * delimiters, or
229: * There is data on Q and count has been satisfied, or
230: * A delimiter is taken from the Q, or
231: * There was an error.
232: */
233: for (;;) {
234: s = spl6();
235: if ((bp = getq(RD(stq->wrq))) == NULL) {
236: if ((nc && (OTHERQ(stq->wrq->next)->flag&QDELIM)==0)
237: || stq->flag&HUNGUP) {
238: splx(s);
239: stexit(ip);
240: return;
241: }
242: stq->flag |= RSLEEP;
243: n = tsleep((caddr_t)RD(stq->wrq), STIPRI, 0);
244: splx(s);
245: if (n == TS_SIG) {
246: stexit(ip);
247: longjmp(u.u_qsav);
248: }
249: continue;
250: }
251: splx(s);
252: switch (bp->type) {
253:
254: case M_DATA:
255: n = min(u.u_count, bp->wptr - bp->rptr);
256: if (n)
257: iomove(bp->rptr, n, B_READ);
258: bp->rptr += n;
259: nc += n;
260: if (bp->rptr >= bp->wptr) {
261: n = bp->class;
262: freeb(bp);
263: if (n&S_DELIM)
264: goto out;
265: } else {
266: putbq(RD(stq->wrq), bp);
267: if (u.u_count == 0)
268: goto out;
269: }
270: if (u.u_error)
271: goto out;
272: continue;
273:
274: case M_PASS:
275: putbq(RD(stq->wrq), bp);
276: goto out;
277:
278: default:
279: printf("stread: msg %d\n", bp->type);
280: freeb(bp);
281: continue;
282: }
283: }
284: out:
285: stexit(ip);
286: }
287:
288: /*
289: * Internal version of stread: transfer to given address.
290: * Always returns; >= 0 is # bytes transferred, -1 is error.
291: * Always reads a whole record; excess discarded.
292: */
293: istread(ip, addr, count, flag) /* flag is for timeout debugging */
294: struct inode *ip;
295: caddr_t addr;
296: {
297: register struct stdata *stq;
298: register struct block *bp;
299: register n;
300: register s, nc = 0;
301:
302: if ((stq = stenter(ip)) == NULL)
303: return(-1);
304: for (;;) {
305: s = spl6();
306: if ((bp = getq(RD(stq->wrq))) == NULL) {
307: if ((nc && (OTHERQ(stq->wrq->next)->flag&QDELIM)==0)
308: || stq->flag&HUNGUP) {
309: splx(s);
310: stexit(ip);
311: return(nc);
312: }
313: stq->flag |= RSLEEP;
314: n = tsleep((caddr_t)RD(stq->wrq), PRIBIO, 30);
315: splx(s);
316: if (n == TS_TIME) {
317: if(flag)
318: printf("nb timeout nc %d count %d addr #%x\n",
319: nc, count, addr);
320: stexit(ip);
321: return(-1);
322: }
323: continue;
324: }
325: splx(s);
326: switch (bp->type) {
327:
328: case M_DATA:
329: n = min(count, bp->wptr - bp->rptr);
330: if (n)
331: bcopy(bp->rptr, addr, n);
332: addr += n;
333: nc += n;
334: count -= n;
335: n = bp->class;
336: freeb(bp);
337: if (n&S_DELIM) {
338: stexit(ip);
339: return(nc);
340: }
341: continue;
342:
343: case M_PASS:
344: putbq(RD(stq->wrq), bp);
345: stexit(ip);
346: return(nc);
347:
348: default:
349: printf("istread: msg %d\n", bp->type);
350: freeb(bp);
351: continue;
352: }
353: }
354: }
355:
356: /*
357: * Stream input put proc
358: * -- collect signals and ioctl acks
359: -- put data and delims on data queue
360: -- see hangups and seal off channel
361: */
362: strput(q, bp)
363: register struct queue *q;
364: register struct block *bp;
365: {
366: register struct stdata *stp = (struct stdata *)q->ptr;
367:
368: switch (bp->type) {
369:
370: case M_DATA:
371: default:
372: putq(q, bp);
373: if (stp->flag & RSLEEP) {
374: stp->flag &= ~RSLEEP;
375: wakeup((caddr_t)q);
376: }
377: break;
378:
379: case M_HANGUP:
380: stp->flag |= HUNGUP;
381: freeb(bp);
382: if (stp->pgrp)
383: gsignal(stp->pgrp, SIGHUP);
384: forceclose(stp, FWRITE);
385: wakeup((caddr_t)q); /* the readers */
386: wakeup((caddr_t)WR(q)); /* the writers */
387: wakeup((caddr_t)stp); /* the ioctllers */
388: break;
389:
390: case M_SIGNAL:
391: gsignal(stp->pgrp, *bp->rptr);
392: case M_FLUSH:
393: flushq(q, 0); /* flush races with select */
394: case M_BREAK:
395: case M_YDEL:
396: case M_NDEL:
397: case M_CTL:
398: freeb(bp);
399: return;
400:
401: case M_IOCACK:
402: case M_IOCNAK:
403: case M_IOCWAIT:
404: if(stp->iocblk && stp->iocblk->type==M_IOCWAIT) {
405: freeb(stp->iocblk);
406: stp->iocblk = NULL;
407: }
408: if ((stp->flag&IOCWAIT)==0 || stp->iocblk) {
409: freeb(bp);
410: return;
411: }
412: stp->iocblk = bp;
413: wakeup((caddr_t)stp);
414: return;
415:
416: case M_IOCTL:
417: bp->type = M_IOCNAK;
418: bp->wptr = bp->rptr; /* data means error */
419: qreply(q, bp);
420: return;
421: }
422: if (stp->rsel) {
423: selwakeup(stp->rsel, stp->flag&RSEL);
424: stp->flag &= ~RSEL;
425: stp->rsel = NULL;
426: }
427: }
428:
429:
430: /*
431: * Write on a stream
432: */
433: stwrite(ip)
434: struct inode *ip;
435: {
436: register struct stdata *stq;
437: register struct block *bp;
438: register n;
439: register s;
440:
441: if ((stq = stenter(ip)) == NULL)
442: return;
443: do {
444: s = spl6();
445: while ((stq->flag&HUNGUP)==0 && stq->wrq->next->flag&QFULL) {
446: stq->flag |= WSLEEP;
447: if (tsleep((caddr_t)stq->wrq, STOPRI, 0)==TS_SIG) {
448: splx(s);
449: stexit(ip);
450: longjmp(u.u_qsav);
451: }
452: }
453: splx(s);
454: if (stq->flag & HUNGUP) {
455: psignal(u.u_procp, SIGPIPE);
456: u.u_error = ENXIO;
457: break;
458: }
459: n = QBSIZE;
460: if (u.u_count >= 512 && stq->wrq->next->flag&QBIGB)
461: n = 1024;
462: if ((bp = allocb(n)) == NULL) {
463: printf("stwrite can't alloc\n");
464: continue; /* temp */
465: }
466: bp->type = M_DATA;
467: n = min(bp->lim - bp->wptr, u.u_count);
468: iomove(bp->wptr, n, B_WRITE);
469: if (u.u_error) {
470: freeb(bp);
471: break;
472: }
473: bp->wptr += n;
474: if (u.u_count==0)
475: bp->class |= S_DELIM;
476: (*stq->wrq->next->qinfo->putp)(stq->wrq->next, bp);
477: } while (u.u_count);
478: stexit(ip);
479: }
480:
481: /*
482: * Stream output -- internal version
483: * return -1 on error, 0 OK
484: */
485: istwrite(ip, addr, count)
486: register count;
487: struct inode *ip;
488: caddr_t addr;
489: {
490: register struct stdata *stq;
491: register struct block *bp;
492: register n;
493: register s;
494:
495: if ((stq = stenter(ip)) == NULL)
496: return(-1);
497: do {
498: s = spl6();
499: while (stq->wrq->next->flag&QFULL && (stq->flag&HUNGUP)==0) {
500: stq->flag |= WSLEEP;
501: if (tsleep((caddr_t)stq->wrq, PRIBIO, 30)==TS_TIME) {
502: splx(s);
503: stexit(ip);
504: return(-1);
505: }
506: }
507: splx(s);
508: if (stq->flag & HUNGUP) {
509: stexit(ip);
510: return(-1);
511: }
512: n = QBSIZE;
513: if (count >= 512 && stq->wrq->next->flag&QBIGB)
514: n = 1024;
515: if ((bp = allocb(n)) == NULL) {
516: printf("istwrite can't alloc\n");
517: continue; /* temp */
518: }
519: bp->type = M_DATA;
520: n = min(bp->lim - bp->wptr, count);
521: bcopy(addr, bp->wptr, n);
522: bp->wptr += n;
523: addr += n;
524: count -= n;
525: if (count==0)
526: bp->class |= S_DELIM;
527: (*stq->wrq->next->qinfo->putp)(stq->wrq->next, bp);
528: } while (count);
529: stexit(ip);
530: return(0);
531: }
532:
533: /*
534: * Stream output server (when full queue empties)
535: */
536: stwsrv(q)
537: register struct queue *q;
538: {
539: register struct stdata *stq = (struct stdata *)q->ptr;
540:
541: if (stq->flag & WSLEEP) {
542: stq->flag &= ~WSLEEP;
543: wakeup((caddr_t)q);
544: }
545: if (stq->wsel) {
546: selwakeup(stq->wsel, stq->flag&WSEL);
547: stq->flag &= ~WSEL;
548: stq->wsel = NULL;
549: }
550: }
551:
552: /*
553: * ioctl for streams
554: */
555: stioctl(ip, cmd, arg)
556: struct inode *ip;
557: caddr_t arg;
558: {
559: register struct stdata *stq;
560: register struct block *bp;
561: register struct queue *q;
562: register s;
563: int fmt, nld, ioctime;
564: struct insld ld;
565: extern nstreamtab;
566:
567: if ((stq = stenter(ip)) == NULL)
568: return;
569: switch(cmd) {
570:
571: case FIONREAD:
572: nld = 0;
573: bp = RD(stq->wrq)->first;
574: if (bp && bp->type==M_DATA)
575: nld = bp->wptr - bp->rptr;
576: if (copyout((caddr_t)&nld, arg, sizeof(nld)))
577: u.u_error = EFAULT;
578: goto out;
579:
580: case TIOCGPGRP:
581: if (copyout ((caddr_t) &stq->pgrp, arg, sizeof (stq->pgrp)))
582: u.u_error = EFAULT;
583: goto out;
584:
585: case TIOCSPGRP:
586: if (arg==0) {
587: stq->pgrp = u.u_procp->p_pgrp = u.u_procp->p_pid;
588: u.u_ttydev = ip->i_dev;
589: u.u_ttyino = ip->i_number;
590: } else if (copyin(arg, (caddr_t)&stq->pgrp, sizeof(stq->pgrp)))
591: u.u_error = EFAULT;
592: goto out;
593:
594: case TIOCEXCL:
595: stq->flag |= EXCL;
596: goto out;
597:
598: case TIOCNXCL:
599: stq->flag &= ~EXCL;
600: goto out;
601:
602: case TIOCFLUSH:
603: if (stq->flag & HUNGUP) {
604: u.u_error = ENXIO;
605: goto out;
606: }
607: flushq(RD(stq->wrq), 0);
608: putctl(stq->wrq->next, M_FLUSH);
609: goto out;
610:
611: case TIOCSBRK:
612: if (stq->flag & HUNGUP) {
613: u.u_error = ENXIO;
614: goto out;
615: }
616: putctl(stq->wrq->next, M_BREAK);
617: goto out;
618:
619: case FIOSNDFD:
620: if (stq->flag & HUNGUP) {
621: u.u_error = ENXIO;
622: goto out;
623: }
624: usndfile(stq, arg);
625: goto out;
626:
627: case FIORCVFD:
628: urcvfile(stq, arg);
629: goto out;
630:
631: case FIOPUSHLD: /* add a line discipline */
632: case FIOINSLD:
633: if (stq->flag & HUNGUP) {
634: u.u_error = ENXIO;
635: goto out;
636: }
637: if (copyin(arg, (caddr_t)&ld, sizeof(ld))) {
638: u.u_error = EFAULT;
639: goto out;
640: }
641: if(ld.ld<0 || ld.ld>=nstreamtab || streamtab[ld.ld]==NULL){
642: u.u_error = EINVAL;
643: goto out;
644: }
645: if (cmd==FIOPUSHLD)
646: ld.level = 0;
647: q = stq->wrq;
648: while (ld.level > 0) {
649: if (q->next == NULL) {
650: u.u_error = EINVAL;
651: goto out;
652: }
653: q = q->next;
654: ld.level--;
655: }
656: s = spl6();
657: if (qattach(streamtab[ld.ld], RD(q), ip->i_un.i_rdev)) {
658: long nip =
659: (*q->next->qinfo->qopen)(RD(q->next), ip->i_un.i_rdev);
660: if (nip==0) {
661: qdetach(RD(q->next), 0);
662: u.u_error = ENXIO;
663: } else if (nip!=1)
664: panic("pushld qopen returns inode");
665: splx(s);
666: goto out;
667: }
668: splx(s);
669: u.u_error = ENOMEM;
670: goto out;
671:
672: case FIOPOPLD:
673: if (stq->flag & HUNGUP) {
674: u.u_error = ENXIO;
675: goto out;
676: }
677: nld = 0;
678: if (arg) {
679: if (copyin(arg, (caddr_t)&nld, sizeof(nld))) {
680: u.u_error = EFAULT;
681: goto out;
682: }
683: }
684: q = stq->wrq;
685: while (nld > 0) {
686: if (q == NULL || q->next==NULL
687: || q->next->flag&QREADR) {
688: u.u_error = EINVAL;
689: goto out;
690: }
691: q = q->next;
692: nld--;
693: }
694: if (q->next->next && (q->next->flag&QREADR) == 0) { /* LD exists? */
695: qdetach(RD(q->next), 1);
696: goto out;
697: }
698: u.u_error = EINVAL;
699: goto out;
700:
701: case FIOLOOKLD:
702: nld = 0;
703: if (arg) {
704: if (copyin(arg, (caddr_t)&nld, sizeof(nld))) {
705: u.u_error = EFAULT;
706: goto out;
707: }
708: }
709: q = stq->wrq;
710: for (;;) {
711: if (q == NULL || q->next==NULL || q->next->next == NULL
712: || q->next->flag&QREADR) {
713: u.u_error = EINVAL;
714: goto out;
715: }
716: if (--nld < 0)
717: break;
718: q = q->next;
719: }
720: for (fmt=0; fmt<nstreamtab; fmt++)
721: if(streamtab[fmt] && streamtab[fmt]->wrinit==q->next->qinfo)
722: break;
723: if (fmt >= nstreamtab) {
724: u.u_error = ENXIO;
725: goto out;
726: }
727: if (arg) {
728: if (copyout((caddr_t)&fmt, arg, sizeof(arg))) {
729: u.u_error = EINVAL;
730: goto out;
731: }
732: }
733: u.u_r.r_val1 = fmt;
734: goto out;
735:
736: }
737: if (stq->flag & HUNGUP) {
738: u.u_error = ENXIO;
739: goto out;
740: }
741: if ((bp = allocb(STIOCHDR+(arg?STIOCSIZE:0))) == NULL) {
742: u.u_error = ENOSPC;
743: goto out;
744: }
745: ((struct stioctl *)bp->wptr)->com[0] = cmd;
746: ((struct stioctl *)bp->wptr)->com[1] = cmd>>8;
747: ((struct stioctl *)bp->wptr)->com[2] = cmd>>16;
748: ((struct stioctl *)bp->wptr)->com[3] = cmd>>24;
749: bp->wptr += STIOCHDR;
750: if (arg) {
751: if (copyin(arg, (caddr_t)stiodata(bp), STIOCSIZE)) {
752: u.u_error = EFAULT;
753: freeb(bp);
754: goto out;
755: }
756: bp->wptr += STIOCSIZE;
757: }
758: bp->type = M_IOCTL;
759: s = spl6();
760: while (stq->flag & IOCWAIT) {
761: if (tsleep((caddr_t)stq,STIPRI,0)!=TS_OK || stq->flag&HUNGUP) {
762: splx(s);
763: u.u_error = EIO;
764: freeb(bp);
765: goto out;
766: }
767: }
768: stq->flag |= IOCWAIT;
769: splx(s);
770: (*stq->wrq->next->qinfo->putp)(stq->wrq->next, bp);
771: /* wait for acknowledgment */
772: s = spl6();
773: ioctime = 15;
774: while ((bp = stq->iocblk) == NULL || bp->type == M_IOCWAIT) {
775: if (bp)
776: ioctime = 0;
777: if (tsleep((caddr_t)stq, STIPRI, ioctime) != TS_OK
778: || stq->flag & HUNGUP) {
779: if (stq->iocblk)
780: freeb(stq->iocblk);
781: stq->iocblk = NULL;
782: u.u_error = EIO;
783: stq->flag &= ~IOCWAIT;
784: splx(s);
785: goto out;
786: }
787: }
788: stq->iocblk = NULL;
789: stq->flag &= ~IOCWAIT;
790: splx(s);
791: switch (bp->type) {
792: case M_IOCACK:
793: if (bp->wptr > bp->rptr) {
794: bp->rptr = (u_char *)((struct stioctl *)(bp->rptr))->data;
795: if (copyout((caddr_t)bp->rptr, arg, bp->wptr-bp->rptr))
796: u.u_error = EFAULT;
797: }
798: freeb(bp);
799: break;
800:
801: case M_IOCNAK:
802: if (bp->rptr < bp->wptr)
803: u.u_error = *bp->rptr;
804: freeb(bp);
805: if (u.u_error==0)
806: u.u_error = ENOTTY;
807: break;
808:
809: default:
810: printf("strange stuff on ioctl ack cell %x\n", stq);
811: break;
812: }
813: wakeup((caddr_t)stq);
814: out:
815: stexit(ip);
816: }
817:
818: /*
819: * attach a stream device or line discipline
820: * qp is a read queue; the new queue goes in so its next
821: * read ptr is the argument, and the write queue corresponding
822: * to the argument points to this queue.
823: */
824: qattach(qinfo, qp, dev)
825: register struct streamtab *qinfo;
826: register struct queue *qp;
827: dev_t dev;
828: {
829: register struct queue *nq;
830: register s;
831: extern putq();
832:
833: if ((nq = allocq()) == NULL) {
834: printf("allocq NULL\n");
835: return(0);
836: }
837: s = spl6();
838: nq->next = qp;
839: WR(nq)->next = WR(qp)->next;
840: if (WR(qp)->next)
841: OTHERQ(WR(qp)->next)->next = nq;
842: WR(qp)->next = WR(nq);
843: nq->qinfo = qinfo->rdinit;
844: WR(nq)->qinfo = qinfo->wrinit;
845: nq->flag |= QREADR|QWANTR;
846: WR(nq)->flag |= QWANTR;
847: nq->ptr = NULL;
848: WR(nq)->ptr = NULL;
849: splx(s);
850: return(1);
851: }
852:
853: /*
854: * Detach a stream device or line discipline.
855: * Call its close routine, then evict it.
856: * The close routine is required to return.
857: * The flag (if 1) indicates that the close routine
858: * should be called (real shutdown) otherwise this
859: * is merely a failed open.
860: */
861: qdetach(qp, flag)
862: register struct queue *qp;
863: {
864: register s = spl6();
865: register i;
866:
867: if (flag) {
868: queuerun();
869: (*qp->qinfo->qclose)(qp);
870: for (i=0; (qp->flag|WR(qp)->flag)&QENAB; i++) {
871: queuerun();
872: if (i>10)
873: panic("queue won't give up");
874: }
875: flushq(qp, 1);
876: flushq(WR(qp), 1);
877: }
878: if (WR(qp)->next)
879: backq(qp)->next = qp->next;
880: if (qp->next)
881: backq(WR(qp))->next = WR(qp)->next;
882: qp->flag = 0;
883: WR(qp)->flag = 0;
884: splx(s);
885: }
886:
887: /*
888: * Count entries/exits to the routines that process streams.
889: * If a stream receives a HANGUP, it should be shut down
890: * forcibly, and this makes sure that it does not happen while
891: * pointers are still floating about.
892: */
893: struct stdata *
894: stenter(ip)
895: register struct inode *ip;
896: {
897: register struct stdata *stp;
898: register s = spl6();
899:
900: if ((stp = ip->i_sptr) == NULL) {
901: u.u_error = ENXIO;
902: splx(s);
903: return(NULL);
904: }
905: stp->count++;
906: splx(s);
907: return(stp);
908: }
909:
910: stexit(ip)
911: register struct inode *ip;
912: {
913: register struct stdata *stp = ip->i_sptr;
914:
915: if(stp == 0) {
916: printf("null stp in stexit\n");
917: return;
918: } /* can't happen, of course */
919: if (--stp->count==0 && stp->flag&HUNGUP && RD(stp->wrq)->count==0)
920: stclose(ip, 1);
921: }
922:
923: /*
924: * create a message transferring a file to process on the other end of a stream
925: */
926: usndfile(stq, arg)
927: register struct stdata *stq;
928: caddr_t arg;
929: {
930: int f;
931: register struct file *fp;
932:
933: if (copyin(arg, (caddr_t)&f, sizeof(f))) {
934: u.u_error = EFAULT;
935: return;
936: }
937: if ((fp = getf(f)) == NULL) {
938: u.u_error = EBADF;
939: return;
940: }
941: sndfile(stq->wrq, fp);
942: }
943:
944: sndfile(q, fp)
945: register struct queue *q;
946: register struct file *fp;
947: {
948: register struct block *bp;
949:
950: for (;;) {
951: if (q==NULL) {
952: u.u_error = ENXIO;
953: return(0);
954: }
955: if (q->qinfo == &strdata)
956: break;
957: /* follow pt's here */
958: q = q->next;
959: }
960: if (q->flag&QFULL) {
961: u.u_error = ENOMEM;
962: return(0);
963: }
964: if ((bp = allocb(sizeof(struct kpassfd))) == NULL) {
965: u.u_error = ENOMEM;
966: return(0);
967: }
968: bp->type = M_PASS;
969: ((struct kpassfd *)bp->rptr)->uid = u.u_uid;
970: ((struct kpassfd *)bp->rptr)->gid = u.u_gid;
971: ((struct kpassfd *)bp->rptr)->nice = u.u_procp->p_nice-NZERO;
972: bcopy(u.u_logname,((struct kpassfd *)bp->rptr)->logname,
973: sizeof(u.u_logname));
974: ((struct kpassfd *)bp->rptr)->f.fp = fp;
975: bp->wptr += sizeof(struct kpassfd);
976: fp->f_count++;
977: strput(q, bp);
978: return(1);
979: }
980:
981: urcvfile(stq, arg)
982: register struct stdata *stq;
983: caddr_t arg;
984: {
985: register struct block *bp;
986: register i;
987: register struct file *fp;
988: register struct kpassfd *kp;
989: struct passfd pfd;
990:
991: while ((bp = getq(RD(stq->wrq))) == NULL) {
992: if (stq->flag&HUNGUP) {
993: u.u_error = ENXIO;
994: return;
995: }
996: stq->flag |= RSLEEP;
997: if (tsleep((caddr_t)RD(stq->wrq), STIPRI, 0)==TS_SIG) {
998: stexit(stq->inode);
999: longjmp(u.u_qsav);
1000: }
1001: }
1002: if (bp->type != M_PASS) {
1003: putbq(RD(stq->wrq), bp);
1004: u.u_error = EIO;
1005: return;
1006: }
1007: kp = (struct kpassfd *)bp->rptr;
1008: fp = kp->f.fp;
1009: i = ufalloc();
1010: if (i < 0) {
1011: closef(fp);
1012: freeb(bp);
1013: return;
1014: }
1015: u.u_ofile[i] = fp;
1016: pfd.fd = i;
1017: pfd.uid = kp->uid;
1018: pfd.gid = kp->gid;
1019: bcopy(kp->logname, pfd.logname, sizeof(kp->logname));
1020: if (copyout((caddr_t)&pfd, arg, sizeof(struct passfd)))
1021: u.u_error = EFAULT;
1022: freeb(bp);
1023: }
1024:
1025: stselect(stp, rw, anyyet)
1026: register struct stdata *stp;
1027: {
1028: register ret = 0;
1029: register s = spl6();
1030: extern int selwait;
1031:
1032: if (rw==FWRITE) {
1033: if ((stp->wrq->next->flag&QFULL) == 0)
1034: ret = 1;
1035: else if (!anyyet) {
1036: if (stp->wsel && stp->wsel->p_wchan==(caddr_t)&selwait)
1037: stp->flag |= WSEL;
1038: else
1039: stp->wsel = u.u_procp;
1040: }
1041: } else {
1042: if (streadable(RD(stp->wrq)) || stp->flag&HUNGUP)
1043: ret = 1;
1044: else if (!anyyet) {
1045: if (stp->rsel && stp->rsel->p_wchan==(caddr_t)&selwait)
1046: stp->flag |= RSEL;
1047: else
1048: stp->rsel = u.u_procp;
1049: }
1050: }
1051: splx(s);
1052: return(ret);
1053: }
1054:
1055: /*
1056: * poison the flags in the file table leading to this stream
1057: */
1058: forceclose(sptr, whichflags)
1059: register struct stdata *sptr;
1060: {
1061: register struct file *fp;
1062:
1063: for (fp = &file[0]; fp < fileNFILE; fp++) {
1064: if (fp->f_count==0)
1065: continue;
1066: if (fp->f_inode==NULL || fp->f_inode->i_sptr != sptr)
1067: continue;
1068: fp->f_flag &= ~whichflags;
1069: fp->f_flag |= FHUNGUP;
1070: }
1071: }
1072:
1073: /*
1074: * check if a queue is likely to be readable
1075: */
1076: streadable(q)
1077: register struct queue *q;
1078: {
1079: register struct block *bp;
1080:
1081: if (q->first == 0)
1082: return(0);
1083: if ((backq(q)->flag&QDELIM) == 0 || q->count >= q->qinfo->lolimit)
1084: return(1);
1085: for (bp = q->first; bp; bp = bp->next)
1086: if (bp->class&S_DELIM || bp->type==M_PASS)
1087: return(1);
1088: return(0);
1089: }
1090:
1091:
1092: /*
1093: * Black hole to seal off closed pipes, and serve as a stub device.
1094: */
1095: long
1096: nilopen(q, dev)
1097: struct queue *q;
1098: dev_t dev;
1099: {
1100: return(1);
1101: }
1102:
1103: nilput(q, bp)
1104: struct queue *q;
1105: struct block *bp;
1106: {
1107: if (bp->type == M_IOCTL) {
1108: bp->type = M_IOCNAK;
1109: bp->wptr = bp->rptr;
1110: qreply(q, bp);
1111: return;
1112: }
1113: freeb(bp);
1114: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.