|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)tty_pty.c 7.21 (Berkeley) 5/30/91
34: */
35:
36: /*
37: * Pseudo-teletype Driver
38: * (Actually two drivers, requiring two entries in 'cdevsw')
39: */
40: #include "pty.h"
41:
42: #if NPTY > 0
43: #include "param.h"
44: #include "systm.h"
45: #include "ioctl.h"
46: #include "tty.h"
47: #include "conf.h"
48: #include "file.h"
49: #include "proc.h"
50: #include "uio.h"
51: #include "kernel.h"
52: #include "vnode.h"
53:
54: #if NPTY == 1
55: #undef NPTY
56: #define NPTY 32 /* crude XXX */
57: #endif
58:
59: #define BUFSIZ 100 /* Chunk size iomoved to/from user */
60:
61: /*
62: * pts == /dev/tty[pqrs]?
63: * ptc == /dev/pty[pqrs]?
64: */
65: struct tty pt_tty[NPTY];
66: struct pt_ioctl {
67: int pt_flags;
68: struct proc *pt_selr, *pt_selw;
69: u_char pt_send;
70: u_char pt_ucntl;
71: } pt_ioctl[NPTY];
72: int npty = NPTY; /* for pstat -t */
73:
74: #define PF_RCOLL 0x01
75: #define PF_WCOLL 0x02
76: #define PF_PKT 0x08 /* packet mode */
77: #define PF_STOPPED 0x10 /* user told stopped */
78: #define PF_REMOTE 0x20 /* remote and flow controlled input */
79: #define PF_NOSTOP 0x40
80: #define PF_UCNTL 0x80 /* user control mode */
81:
82: /*ARGSUSED*/
83: ptsopen(dev, flag, devtype, p)
84: dev_t dev;
85: struct proc *p;
86: {
87: register struct tty *tp;
88: int error;
89:
90: #ifdef lint
91: npty = npty;
92: #endif
93: if (minor(dev) >= NPTY)
94: return (ENXIO);
95: tp = &pt_tty[minor(dev)];
96: if ((tp->t_state & TS_ISOPEN) == 0) {
97: tp->t_state |= TS_WOPEN;
98: ttychars(tp); /* Set up default chars */
99: tp->t_iflag = TTYDEF_IFLAG;
100: tp->t_oflag = TTYDEF_OFLAG;
101: tp->t_lflag = TTYDEF_LFLAG;
102: tp->t_cflag = TTYDEF_CFLAG;
103: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
104: ttsetwater(tp); /* would be done in xxparam() */
105: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
106: return (EBUSY);
107: if (tp->t_oproc) /* Ctrlr still around. */
108: tp->t_state |= TS_CARR_ON;
109: while ((tp->t_state & TS_CARR_ON) == 0) {
110: tp->t_state |= TS_WOPEN;
111: if (flag&FNONBLOCK)
112: break;
113: if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
114: ttopen, 0))
115: return (error);
116: }
117: error = (*linesw[tp->t_line].l_open)(dev, tp, flag);
118: ptcwakeup(tp, FREAD|FWRITE);
119: return (error);
120: }
121:
122: ptsclose(dev, flag, mode, p)
123: dev_t dev;
124: int flag, mode;
125: struct proc *p;
126: {
127: register struct tty *tp;
128:
129: tp = &pt_tty[minor(dev)];
130: (*linesw[tp->t_line].l_close)(tp, flag);
131: ttyclose(tp);
132: ptcwakeup(tp, FREAD|FWRITE);
133: }
134:
135: ptsread(dev, uio, flag)
136: dev_t dev;
137: struct uio *uio;
138: {
139: struct proc *p = curproc;
140: register struct tty *tp = &pt_tty[minor(dev)];
141: register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
142: int error = 0;
143:
144: again:
145: if (pti->pt_flags & PF_REMOTE) {
146: while (isbackground(p, tp)) {
147: if ((p->p_sigignore & sigmask(SIGTTIN)) ||
148: (p->p_sigmask & sigmask(SIGTTIN)) ||
149: p->p_pgrp->pg_jobc == 0 ||
150: p->p_flag&SPPWAIT)
151: return (EIO);
152: pgsignal(p->p_pgrp, SIGTTIN, 1);
153: if (error = ttysleep(tp, (caddr_t)&lbolt,
154: TTIPRI | PCATCH, ttybg, 0))
155: return (error);
156: }
157: if (tp->t_canq.c_cc == 0) {
158: if (flag & IO_NDELAY)
159: return (EWOULDBLOCK);
160: if (error = ttysleep(tp, (caddr_t)&tp->t_canq,
161: TTIPRI | PCATCH, ttyin, 0))
162: return (error);
163: goto again;
164: }
165: while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
166: if (ureadc(getc(&tp->t_canq), uio) < 0) {
167: error = EFAULT;
168: break;
169: }
170: if (tp->t_canq.c_cc == 1)
171: (void) getc(&tp->t_canq);
172: if (tp->t_canq.c_cc)
173: return (error);
174: } else
175: if (tp->t_oproc)
176: error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
177: ptcwakeup(tp, FWRITE);
178: return (error);
179: }
180:
181: /*
182: * Write to pseudo-tty.
183: * Wakeups of controlling tty will happen
184: * indirectly, when tty driver calls ptsstart.
185: */
186: ptswrite(dev, uio, flag)
187: dev_t dev;
188: struct uio *uio;
189: {
190: register struct tty *tp;
191:
192: tp = &pt_tty[minor(dev)];
193: if (tp->t_oproc == 0)
194: return (EIO);
195: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
196: }
197:
198: /*
199: * Start output on pseudo-tty.
200: * Wake up process selecting or sleeping for input from controlling tty.
201: */
202: ptsstart(tp)
203: struct tty *tp;
204: {
205: register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
206:
207: if (tp->t_state & TS_TTSTOP)
208: return;
209: if (pti->pt_flags & PF_STOPPED) {
210: pti->pt_flags &= ~PF_STOPPED;
211: pti->pt_send = TIOCPKT_START;
212: }
213: ptcwakeup(tp, FREAD);
214: }
215:
216: ptcwakeup(tp, flag)
217: struct tty *tp;
218: {
219: struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
220:
221: if (flag & FREAD) {
222: if (pti->pt_selr) {
223: selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
224: pti->pt_selr = 0;
225: pti->pt_flags &= ~PF_RCOLL;
226: }
227: wakeup((caddr_t)&tp->t_outq.c_cf);
228: }
229: if (flag & FWRITE) {
230: if (pti->pt_selw) {
231: selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
232: pti->pt_selw = 0;
233: pti->pt_flags &= ~PF_WCOLL;
234: }
235: wakeup((caddr_t)&tp->t_rawq.c_cf);
236: }
237: }
238:
239: /*ARGSUSED*/
240: #ifdef __STDC__
241: ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
242: #else
243: ptcopen(dev, flag, devtype, p)
244: dev_t dev;
245: int flag, devtype;
246: struct proc *p;
247: #endif
248: {
249: register struct tty *tp;
250: struct pt_ioctl *pti;
251:
252: if (minor(dev) >= NPTY)
253: return (ENXIO);
254: tp = &pt_tty[minor(dev)];
255: if (tp->t_oproc)
256: return (EIO);
257: tp->t_oproc = ptsstart;
258: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
259: tp->t_lflag &= ~EXTPROC;
260: pti = &pt_ioctl[minor(dev)];
261: pti->pt_flags = 0;
262: pti->pt_send = 0;
263: pti->pt_ucntl = 0;
264: return (0);
265: }
266:
267: ptcclose(dev)
268: dev_t dev;
269: {
270: register struct tty *tp;
271:
272: tp = &pt_tty[minor(dev)];
273: (void)(*linesw[tp->t_line].l_modem)(tp, 0);
274: tp->t_state &= ~TS_CARR_ON;
275: tp->t_oproc = 0; /* mark closed */
276: tp->t_session = 0;
277: }
278:
279: ptcread(dev, uio, flag)
280: dev_t dev;
281: struct uio *uio;
282: {
283: register struct tty *tp = &pt_tty[minor(dev)];
284: struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
285: char buf[BUFSIZ];
286: int error = 0, cc;
287:
288: /*
289: * We want to block until the slave
290: * is open, and there's something to read;
291: * but if we lost the slave or we're NBIO,
292: * then return the appropriate error instead.
293: */
294: for (;;) {
295: if (tp->t_state&TS_ISOPEN) {
296: if (pti->pt_flags&PF_PKT && pti->pt_send) {
297: error = ureadc((int)pti->pt_send, uio);
298: if (error)
299: return (error);
300: if (pti->pt_send & TIOCPKT_IOCTL) {
301: cc = MIN(uio->uio_resid,
302: sizeof(tp->t_termios));
303: uiomove(&tp->t_termios, cc, uio);
304: }
305: pti->pt_send = 0;
306: return (0);
307: }
308: if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
309: error = ureadc((int)pti->pt_ucntl, uio);
310: if (error)
311: return (error);
312: pti->pt_ucntl = 0;
313: return (0);
314: }
315: if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
316: break;
317: }
318: if ((tp->t_state&TS_CARR_ON) == 0)
319: return (0); /* EOF */
320: if (flag & IO_NDELAY)
321: return (EWOULDBLOCK);
322: if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
323: ttyin, 0))
324: return (error);
325: }
326: if (pti->pt_flags & (PF_PKT|PF_UCNTL))
327: error = ureadc(0, uio);
328: while (uio->uio_resid > 0 && error == 0) {
329: cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
330: if (cc <= 0)
331: break;
332: error = uiomove(buf, cc, uio);
333: }
334: if (tp->t_outq.c_cc <= tp->t_lowat) {
335: if (tp->t_state&TS_ASLEEP) {
336: tp->t_state &= ~TS_ASLEEP;
337: wakeup((caddr_t)&tp->t_outq);
338: }
339: if (tp->t_wsel) {
340: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
341: tp->t_wsel = 0;
342: tp->t_state &= ~TS_WCOLL;
343: }
344: }
345: return (error);
346: }
347:
348: ptsstop(tp, flush)
349: register struct tty *tp;
350: int flush;
351: {
352: struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
353: int flag;
354:
355: /* note: FLUSHREAD and FLUSHWRITE already ok */
356: if (flush == 0) {
357: flush = TIOCPKT_STOP;
358: pti->pt_flags |= PF_STOPPED;
359: } else
360: pti->pt_flags &= ~PF_STOPPED;
361: pti->pt_send |= flush;
362: /* change of perspective */
363: flag = 0;
364: if (flush & FREAD)
365: flag |= FWRITE;
366: if (flush & FWRITE)
367: flag |= FREAD;
368: ptcwakeup(tp, flag);
369: }
370:
371: ptcselect(dev, rw, p)
372: dev_t dev;
373: int rw;
374: struct proc *p;
375: {
376: register struct tty *tp = &pt_tty[minor(dev)];
377: struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
378: struct proc *prev;
379: int s;
380:
381: if ((tp->t_state&TS_CARR_ON) == 0)
382: return (1);
383: switch (rw) {
384:
385: case FREAD:
386: /*
387: * Need to block timeouts (ttrstart).
388: */
389: s = spltty();
390: if ((tp->t_state&TS_ISOPEN) &&
391: tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
392: splx(s);
393: return (1);
394: }
395: splx(s);
396: /* FALLTHROUGH */
397:
398: case 0: /* exceptional */
399: if ((tp->t_state&TS_ISOPEN) &&
400: (pti->pt_flags&PF_PKT && pti->pt_send ||
401: pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
402: return (1);
403: if ((prev = pti->pt_selr) && prev->p_wchan == (caddr_t)&selwait)
404: pti->pt_flags |= PF_RCOLL;
405: else
406: pti->pt_selr = p;
407: break;
408:
409:
410: case FWRITE:
411: if (tp->t_state&TS_ISOPEN) {
412: if (pti->pt_flags & PF_REMOTE) {
413: if (tp->t_canq.c_cc == 0)
414: return (1);
415: } else {
416: if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
417: return (1);
418: if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
419: return (1);
420: }
421: }
422: if ((prev = pti->pt_selw) && prev->p_wchan == (caddr_t)&selwait)
423: pti->pt_flags |= PF_WCOLL;
424: else
425: pti->pt_selw = p;
426: break;
427:
428: }
429: return (0);
430: }
431:
432: ptcwrite(dev, uio, flag)
433: dev_t dev;
434: register struct uio *uio;
435: {
436: register struct tty *tp = &pt_tty[minor(dev)];
437: register u_char *cp;
438: register int cc = 0;
439: u_char locbuf[BUFSIZ];
440: int cnt = 0;
441: struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
442: int error = 0;
443:
444: again:
445: if ((tp->t_state&TS_ISOPEN) == 0)
446: goto block;
447: if (pti->pt_flags & PF_REMOTE) {
448: if (tp->t_canq.c_cc)
449: goto block;
450: while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
451: if (cc == 0) {
452: cc = min(uio->uio_resid, BUFSIZ);
453: cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
454: cp = locbuf;
455: error = uiomove((caddr_t)cp, cc, uio);
456: if (error)
457: return (error);
458: /* check again for safety */
459: if ((tp->t_state&TS_ISOPEN) == 0)
460: return (EIO);
461: }
462: if (cc)
463: (void) b_to_q((char *)cp, cc, &tp->t_canq);
464: cc = 0;
465: }
466: (void) putc(0, &tp->t_canq);
467: ttwakeup(tp);
468: wakeup((caddr_t)&tp->t_canq);
469: return (0);
470: }
471: while (uio->uio_resid > 0) {
472: if (cc == 0) {
473: cc = min(uio->uio_resid, BUFSIZ);
474: cp = locbuf;
475: error = uiomove((caddr_t)cp, cc, uio);
476: if (error)
477: return (error);
478: /* check again for safety */
479: if ((tp->t_state&TS_ISOPEN) == 0)
480: return (EIO);
481: }
482: while (cc > 0) {
483: if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
484: (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
485: wakeup((caddr_t)&tp->t_rawq);
486: goto block;
487: }
488: (*linesw[tp->t_line].l_rint)(*cp++, tp);
489: cnt++;
490: cc--;
491: }
492: cc = 0;
493: }
494: return (0);
495: block:
496: /*
497: * Come here to wait for slave to open, for space
498: * in outq, or space in rawq.
499: */
500: if ((tp->t_state&TS_CARR_ON) == 0)
501: return (EIO);
502: if (flag & IO_NDELAY) {
503: /* adjust for data copied in but not written */
504: uio->uio_resid += cc;
505: if (cnt == 0)
506: return (EWOULDBLOCK);
507: return (0);
508: }
509: if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
510: ttyout, 0)) {
511: /* adjust for data copied in but not written */
512: uio->uio_resid += cc;
513: return (error);
514: }
515: goto again;
516: }
517:
518: /*ARGSUSED*/
519: ptyioctl(dev, cmd, data, flag)
520: caddr_t data;
521: dev_t dev;
522: {
523: register struct tty *tp = &pt_tty[minor(dev)];
524: register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
525: register u_char *cc = tp->t_cc;
526: int stop, error;
527: extern ttyinput();
528:
529: /*
530: * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
531: * ttywflush(tp) will hang if there are characters in the outq.
532: */
533: if (cmd == TIOCEXT) {
534: /*
535: * When the EXTPROC bit is being toggled, we need
536: * to send an TIOCPKT_IOCTL if the packet driver
537: * is turned on.
538: */
539: if (*(int *)data) {
540: if (pti->pt_flags & PF_PKT) {
541: pti->pt_send |= TIOCPKT_IOCTL;
542: ptcwakeup(tp);
543: }
544: tp->t_lflag |= EXTPROC;
545: } else {
546: if ((tp->t_state & EXTPROC) &&
547: (pti->pt_flags & PF_PKT)) {
548: pti->pt_send |= TIOCPKT_IOCTL;
549: ptcwakeup(tp);
550: }
551: tp->t_lflag &= ~EXTPROC;
552: }
553: return(0);
554: } else
555: if (cdevsw[major(dev)].d_open == ptcopen)
556: switch (cmd) {
557:
558: case TIOCGPGRP:
559: /*
560: * We aviod calling ttioctl on the controller since,
561: * in that case, tp must be the controlling terminal.
562: */
563: *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
564: return (0);
565:
566: case TIOCPKT:
567: if (*(int *)data) {
568: if (pti->pt_flags & PF_UCNTL)
569: return (EINVAL);
570: pti->pt_flags |= PF_PKT;
571: } else
572: pti->pt_flags &= ~PF_PKT;
573: return (0);
574:
575: case TIOCUCNTL:
576: if (*(int *)data) {
577: if (pti->pt_flags & PF_PKT)
578: return (EINVAL);
579: pti->pt_flags |= PF_UCNTL;
580: } else
581: pti->pt_flags &= ~PF_UCNTL;
582: return (0);
583:
584: case TIOCREMOTE:
585: if (*(int *)data)
586: pti->pt_flags |= PF_REMOTE;
587: else
588: pti->pt_flags &= ~PF_REMOTE;
589: ttyflush(tp, FREAD|FWRITE);
590: return (0);
591:
592: case TIOCSETP:
593: case TIOCSETN:
594: case TIOCSETD:
595: case TIOCSETA:
596: case TIOCSETAW:
597: case TIOCSETAF:
598: while (getc(&tp->t_outq) >= 0)
599: ;
600: break;
601:
602: case TIOCSIG:
603: if (*(unsigned int *)data >= NSIG)
604: return(EINVAL);
605: if ((tp->t_lflag&NOFLSH) == 0)
606: ttyflush(tp, FREAD|FWRITE);
607: pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
608: if ((*(unsigned int *)data == SIGINFO) &&
609: ((tp->t_lflag&NOKERNINFO) == 0))
610: ttyinfo(tp);
611: return(0);
612: }
613: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
614: if (error < 0)
615: error = ttioctl(tp, cmd, data, flag);
616: /*
617: * Since we use the tty queues internally,
618: * pty's can't be switched to disciplines which overwrite
619: * the queues. We can't tell anything about the discipline
620: * from here...
621: */
622: if (linesw[tp->t_line].l_rint != ttyinput) {
623: (*linesw[tp->t_line].l_close)(tp, flag);
624: tp->t_line = TTYDISC;
625: (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
626: error = ENOTTY;
627: }
628: if (error < 0) {
629: if (pti->pt_flags & PF_UCNTL &&
630: (cmd & ~0xff) == UIOCCMD(0)) {
631: if (cmd & 0xff) {
632: pti->pt_ucntl = (u_char)cmd;
633: ptcwakeup(tp, FREAD);
634: }
635: return (0);
636: }
637: error = ENOTTY;
638: }
639: /*
640: * If external processing and packet mode send ioctl packet.
641: */
642: if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
643: switch(cmd) {
644: case TIOCSETA:
645: case TIOCSETAW:
646: case TIOCSETAF:
647: case TIOCSETP:
648: case TIOCSETN:
649: #ifdef COMPAT_43
650: case TIOCSETC:
651: case TIOCSLTC:
652: case TIOCLBIS:
653: case TIOCLBIC:
654: case TIOCLSET:
655: #endif
656: pti->pt_send |= TIOCPKT_IOCTL;
657: default:
658: break;
659: }
660: }
661: stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
662: && CCEQ(cc[VSTART], CTRL('q'));
663: if (pti->pt_flags & PF_NOSTOP) {
664: if (stop) {
665: pti->pt_send &= ~TIOCPKT_NOSTOP;
666: pti->pt_send |= TIOCPKT_DOSTOP;
667: pti->pt_flags &= ~PF_NOSTOP;
668: ptcwakeup(tp, FREAD);
669: }
670: } else {
671: if (!stop) {
672: pti->pt_send &= ~TIOCPKT_DOSTOP;
673: pti->pt_send |= TIOCPKT_NOSTOP;
674: pti->pt_flags |= PF_NOSTOP;
675: ptcwakeup(tp, FREAD);
676: }
677: }
678: return (error);
679: }
680: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.