Deleted Added
full compact
pty.c (6782) pty.c (7724)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. 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 8.2 (Berkeley) 9/23/93
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. 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 8.2 (Berkeley) 9/23/93
34 * $Id: tty_pty.c,v 1.7 1995/02/25 20:09:30 pst Exp $
34 * $Id: tty_pty.c,v 1.8 1995/02/28 00:21:05 pst Exp $
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "pty.h" /* XXX */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/ioctl.h>
46#include <sys/proc.h>
47#include <sys/tty.h>
48#include <sys/conf.h>
49#include <sys/file.h>
50#include <sys/uio.h>
51#include <sys/kernel.h>
52#include <sys/vnode.h>
53#include <sys/signalvar.h>
54
55#if NPTY == 1
56#undef NPTY
57#define NPTY 32 /* crude XXX */
58#endif
59
60#define BUFSIZ 100 /* Chunk size iomoved to/from user */
61
62/*
63 * pts == /dev/tty[pqrs]?
64 * ptc == /dev/pty[pqrs]?
65 */
66struct tty pt_tty[NPTY]; /* XXX */
67struct pt_ioctl {
68 int pt_flags;
69 struct selinfo pt_selr, pt_selw;
70 u_char pt_send;
71 u_char pt_ucntl;
72} pt_ioctl[NPTY]; /* XXX */
73int npty = NPTY; /* for pstat -t */
74
75#define PF_PKT 0x08 /* packet mode */
76#define PF_STOPPED 0x10 /* user told stopped */
77#define PF_REMOTE 0x20 /* remote and flow controlled input */
78#define PF_NOSTOP 0x40
79#define PF_UCNTL 0x80 /* user control mode */
80
81void ptsstop __P((struct tty *, int));
82void ptcwakeup __P((struct tty *, int));
83
84/*
85 * Establish n (or default if n is 1) ptys in the system.
86 *
87 * XXX cdevsw & pstat require the array `pty[]' to be an array
88 */
89void
90ptyattach(n)
91 int n;
92{
93#ifdef notyet
94 char *mem;
95 register u_long ntb;
96#define DEFAULT_NPTY 32
97
98 /* maybe should allow 0 => none? */
99 if (n <= 1)
100 n = DEFAULT_NPTY;
101 ntb = n * sizeof(struct tty);
102 mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
103 M_DEVBUF, M_WAITOK);
104 pt_tty = (struct tty *)mem;
105 mem = (char *)ALIGN(mem + ntb);
106 pt_ioctl = (struct pt_ioctl *)mem;
107 npty = n;
108#endif
109}
110
111/*ARGSUSED*/
112int
113ptsopen(dev, flag, devtype, p)
114 dev_t dev;
115 int flag, devtype;
116 struct proc *p;
117{
118 register struct tty *tp;
119 int error;
120
121 if (minor(dev) >= npty)
122 return (ENXIO);
123 tp = &pt_tty[minor(dev)];
124 if ((tp->t_state & TS_ISOPEN) == 0) {
125 tp->t_state |= TS_WOPEN;
126 ttychars(tp); /* Set up default chars */
127 tp->t_iflag = TTYDEF_IFLAG;
128 tp->t_oflag = TTYDEF_OFLAG;
129 tp->t_lflag = TTYDEF_LFLAG;
130 tp->t_cflag = TTYDEF_CFLAG;
131 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
132 ttsetwater(tp); /* would be done in xxparam() */
133 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
134 return (EBUSY);
135 if (tp->t_oproc) /* Ctrlr still around. */
136 tp->t_state |= TS_CARR_ON;
137 while ((tp->t_state & TS_CARR_ON) == 0) {
138 tp->t_state |= TS_WOPEN;
139 if (flag&FNONBLOCK)
140 break;
141 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
142 ttopen, 0);
143 if (error)
144 return (error);
145 }
146 error = (*linesw[tp->t_line].l_open)(dev, tp);
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "pty.h" /* XXX */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/ioctl.h>
46#include <sys/proc.h>
47#include <sys/tty.h>
48#include <sys/conf.h>
49#include <sys/file.h>
50#include <sys/uio.h>
51#include <sys/kernel.h>
52#include <sys/vnode.h>
53#include <sys/signalvar.h>
54
55#if NPTY == 1
56#undef NPTY
57#define NPTY 32 /* crude XXX */
58#endif
59
60#define BUFSIZ 100 /* Chunk size iomoved to/from user */
61
62/*
63 * pts == /dev/tty[pqrs]?
64 * ptc == /dev/pty[pqrs]?
65 */
66struct tty pt_tty[NPTY]; /* XXX */
67struct pt_ioctl {
68 int pt_flags;
69 struct selinfo pt_selr, pt_selw;
70 u_char pt_send;
71 u_char pt_ucntl;
72} pt_ioctl[NPTY]; /* XXX */
73int npty = NPTY; /* for pstat -t */
74
75#define PF_PKT 0x08 /* packet mode */
76#define PF_STOPPED 0x10 /* user told stopped */
77#define PF_REMOTE 0x20 /* remote and flow controlled input */
78#define PF_NOSTOP 0x40
79#define PF_UCNTL 0x80 /* user control mode */
80
81void ptsstop __P((struct tty *, int));
82void ptcwakeup __P((struct tty *, int));
83
84/*
85 * Establish n (or default if n is 1) ptys in the system.
86 *
87 * XXX cdevsw & pstat require the array `pty[]' to be an array
88 */
89void
90ptyattach(n)
91 int n;
92{
93#ifdef notyet
94 char *mem;
95 register u_long ntb;
96#define DEFAULT_NPTY 32
97
98 /* maybe should allow 0 => none? */
99 if (n <= 1)
100 n = DEFAULT_NPTY;
101 ntb = n * sizeof(struct tty);
102 mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
103 M_DEVBUF, M_WAITOK);
104 pt_tty = (struct tty *)mem;
105 mem = (char *)ALIGN(mem + ntb);
106 pt_ioctl = (struct pt_ioctl *)mem;
107 npty = n;
108#endif
109}
110
111/*ARGSUSED*/
112int
113ptsopen(dev, flag, devtype, p)
114 dev_t dev;
115 int flag, devtype;
116 struct proc *p;
117{
118 register struct tty *tp;
119 int error;
120
121 if (minor(dev) >= npty)
122 return (ENXIO);
123 tp = &pt_tty[minor(dev)];
124 if ((tp->t_state & TS_ISOPEN) == 0) {
125 tp->t_state |= TS_WOPEN;
126 ttychars(tp); /* Set up default chars */
127 tp->t_iflag = TTYDEF_IFLAG;
128 tp->t_oflag = TTYDEF_OFLAG;
129 tp->t_lflag = TTYDEF_LFLAG;
130 tp->t_cflag = TTYDEF_CFLAG;
131 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
132 ttsetwater(tp); /* would be done in xxparam() */
133 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
134 return (EBUSY);
135 if (tp->t_oproc) /* Ctrlr still around. */
136 tp->t_state |= TS_CARR_ON;
137 while ((tp->t_state & TS_CARR_ON) == 0) {
138 tp->t_state |= TS_WOPEN;
139 if (flag&FNONBLOCK)
140 break;
141 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
142 ttopen, 0);
143 if (error)
144 return (error);
145 }
146 error = (*linesw[tp->t_line].l_open)(dev, tp);
147 ptcwakeup(tp, FREAD|FWRITE);
147 if (error == 0)
148 ptcwakeup(tp, FREAD|FWRITE);
148 return (error);
149}
150
151int
152ptsclose(dev, flag, mode, p)
153 dev_t dev;
154 int flag, mode;
155 struct proc *p;
156{
157 register struct tty *tp;
158 int err;
159
160 tp = &pt_tty[minor(dev)];
149 return (error);
150}
151
152int
153ptsclose(dev, flag, mode, p)
154 dev_t dev;
155 int flag, mode;
156 struct proc *p;
157{
158 register struct tty *tp;
159 int err;
160
161 tp = &pt_tty[minor(dev)];
161 err = (*linesw[tp->t_line].l_close)(tp, flag);
162 err |= ttyclose(tp);
163 ptcwakeup(tp, FREAD|FWRITE);
162 ptcwakeup(tp, FREAD|FWRITE);
163 err = (*linesw[tp->t_line].l_close)(tp, flag);
164 (void) ttyclose(tp);
164 return (err);
165}
166
167int
168ptsread(dev, uio, flag)
169 dev_t dev;
170 struct uio *uio;
171 int flag;
172{
173 struct proc *p = curproc;
174 register struct tty *tp = &pt_tty[minor(dev)];
175 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
176 int error = 0;
177
178again:
179 if (pti->pt_flags & PF_REMOTE) {
180 while (isbackground(p, tp)) {
181 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
182 (p->p_sigmask & sigmask(SIGTTIN)) ||
183 p->p_pgrp->pg_jobc == 0 ||
184 p->p_flag & P_PPWAIT)
185 return (EIO);
186 pgsignal(p->p_pgrp, SIGTTIN, 1);
187 error = ttysleep(tp, (caddr_t)&lbolt,
188 TTIPRI | PCATCH, ttybg, 0);
189 if (error)
190 return (error);
191 }
192 if (tp->t_canq.c_cc == 0) {
193 if (flag & IO_NDELAY)
194 return (EWOULDBLOCK);
195 error = ttysleep(tp, (caddr_t)&tp->t_canq,
196 TTIPRI | PCATCH, ttyin, 0);
197 if (error)
198 return (error);
199 goto again;
200 }
201 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
202 if (ureadc(getc(&tp->t_canq), uio) < 0) {
203 error = EFAULT;
204 break;
205 }
206 if (tp->t_canq.c_cc == 1)
207 (void) getc(&tp->t_canq);
208 if (tp->t_canq.c_cc)
209 return (error);
210 } else
211 if (tp->t_oproc)
212 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
213 ptcwakeup(tp, FWRITE);
214 return (error);
215}
216
217/*
218 * Write to pseudo-tty.
219 * Wakeups of controlling tty will happen
220 * indirectly, when tty driver calls ptsstart.
221 */
222int
223ptswrite(dev, uio, flag)
224 dev_t dev;
225 struct uio *uio;
226 int flag;
227{
228 register struct tty *tp;
229
230 tp = &pt_tty[minor(dev)];
231 if (tp->t_oproc == 0)
232 return (EIO);
233 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
234}
235
236/*
237 * Start output on pseudo-tty.
238 * Wake up process selecting or sleeping for input from controlling tty.
239 */
240void
241ptsstart(tp)
242 struct tty *tp;
243{
244 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
245
246 if (tp->t_state & TS_TTSTOP)
247 return;
248 if (pti->pt_flags & PF_STOPPED) {
249 pti->pt_flags &= ~PF_STOPPED;
250 pti->pt_send = TIOCPKT_START;
251 }
252 ptcwakeup(tp, FREAD);
253}
254
255void
256ptcwakeup(tp, flag)
257 struct tty *tp;
258 int flag;
259{
260 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
261
262 if (flag & FREAD) {
263 selwakeup(&pti->pt_selr);
264 wakeup((caddr_t)&tp->t_outq.c_cf);
265 }
266 if (flag & FWRITE) {
267 selwakeup(&pti->pt_selw);
268 wakeup((caddr_t)&tp->t_rawq.c_cl);
269 }
270}
271
272/*ARGSUSED*/
273#ifdef __STDC__
274int
275ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
276#else
277int
278ptcopen(dev, flag, devtype, p)
279 dev_t dev;
280 int flag, devtype;
281 struct proc *p;
282#endif
283{
284 register struct tty *tp;
285 struct pt_ioctl *pti;
286
287 if (minor(dev) >= npty)
288 return (ENXIO);
289 tp = &pt_tty[minor(dev)];
290 if (tp->t_oproc)
291 return (EIO);
292 tp->t_oproc = ptsstart;
293#ifdef sun4c
294 tp->t_stop = ptsstop;
295#endif
296 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
297 tp->t_lflag &= ~EXTPROC;
298 pti = &pt_ioctl[minor(dev)];
299 pti->pt_flags = 0;
300 pti->pt_send = 0;
301 pti->pt_ucntl = 0;
302 return (0);
303}
304
305int
306ptcclose(dev)
307 dev_t dev;
308{
309 register struct tty *tp;
310
311 tp = &pt_tty[minor(dev)];
312 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
313 tp->t_state &= ~TS_CARR_ON;
314 tp->t_oproc = 0; /* mark closed */
315 tp->t_session = 0;
316 return (0);
317}
318
319int
320ptcread(dev, uio, flag)
321 dev_t dev;
322 struct uio *uio;
323 int flag;
324{
325 register struct tty *tp = &pt_tty[minor(dev)];
326 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
327 char buf[BUFSIZ];
328 int error = 0, cc;
329
330 /*
331 * We want to block until the slave
332 * is open, and there's something to read;
333 * but if we lost the slave or we're NBIO,
334 * then return the appropriate error instead.
335 */
336 for (;;) {
337 if (tp->t_state&TS_ISOPEN) {
338 if (pti->pt_flags&PF_PKT && pti->pt_send) {
339 error = ureadc((int)pti->pt_send, uio);
340 if (error)
341 return (error);
342 if (pti->pt_send & TIOCPKT_IOCTL) {
343 cc = min(uio->uio_resid,
344 sizeof(tp->t_termios));
345 uiomove((caddr_t)&tp->t_termios, cc,
346 uio);
347 }
348 pti->pt_send = 0;
349 return (0);
350 }
351 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
352 error = ureadc((int)pti->pt_ucntl, uio);
353 if (error)
354 return (error);
355 pti->pt_ucntl = 0;
356 return (0);
357 }
358 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
359 break;
360 }
361 if ((tp->t_state&TS_CARR_ON) == 0)
362 return (0); /* EOF */
363 if (flag & IO_NDELAY)
364 return (EWOULDBLOCK);
365 error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
366 ttyin, 0);
367 if (error)
368 return (error);
369 }
370 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
371 error = ureadc(0, uio);
372 while (uio->uio_resid > 0 && error == 0) {
373 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
374 if (cc <= 0)
375 break;
376 error = uiomove(buf, cc, uio);
377 }
378 if (tp->t_outq.c_cc <= tp->t_lowat) {
379 if (tp->t_state&TS_ASLEEP) {
380 tp->t_state &= ~TS_ASLEEP;
381 wakeup((caddr_t)&tp->t_outq);
382 }
383 selwakeup(&tp->t_wsel);
384 }
385 return (error);
386}
387
388void
389ptsstop(tp, flush)
390 register struct tty *tp;
391 int flush;
392{
393 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
394 int flag;
395
396 /* note: FLUSHREAD and FLUSHWRITE already ok */
397 if (flush == 0) {
398 flush = TIOCPKT_STOP;
399 pti->pt_flags |= PF_STOPPED;
400 } else
401 pti->pt_flags &= ~PF_STOPPED;
402 pti->pt_send |= flush;
403 /* change of perspective */
404 flag = 0;
405 if (flush & FREAD)
406 flag |= FWRITE;
407 if (flush & FWRITE)
408 flag |= FREAD;
409 ptcwakeup(tp, flag);
410}
411
412int
413ptcselect(dev, rw, p)
414 dev_t dev;
415 int rw;
416 struct proc *p;
417{
418 register struct tty *tp = &pt_tty[minor(dev)];
419 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
420 int s;
421
422 if ((tp->t_state&TS_CARR_ON) == 0)
423 return (1);
424 switch (rw) {
425
426 case FREAD:
427 /*
428 * Need to block timeouts (ttrstart).
429 */
430 s = spltty();
431 if ((tp->t_state&TS_ISOPEN) &&
432 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
433 splx(s);
434 return (1);
435 }
436 splx(s);
437 /* FALLTHROUGH */
438
439 case 0: /* exceptional */
440 if ((tp->t_state&TS_ISOPEN) &&
441 ((pti->pt_flags&PF_PKT && pti->pt_send) ||
442 (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
443 return (1);
444 selrecord(p, &pti->pt_selr);
445 break;
446
447
448 case FWRITE:
449 if (tp->t_state&TS_ISOPEN) {
450 if (pti->pt_flags & PF_REMOTE) {
451 if (tp->t_canq.c_cc == 0)
452 return (1);
453 } else {
454 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
455 return (1);
456 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
457 return (1);
458 }
459 }
460 selrecord(p, &pti->pt_selw);
461 break;
462
463 }
464 return (0);
465}
466
467int
468ptcwrite(dev, uio, flag)
469 dev_t dev;
470 register struct uio *uio;
471 int flag;
472{
473 register struct tty *tp = &pt_tty[minor(dev)];
474 register u_char *cp = 0;
475 register int cc = 0;
476 u_char locbuf[BUFSIZ];
477 int cnt = 0;
478 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
479 int error = 0;
480
481again:
482 if ((tp->t_state&TS_ISOPEN) == 0)
483 goto block;
484 if (pti->pt_flags & PF_REMOTE) {
485 if (tp->t_canq.c_cc)
486 goto block;
487 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
488 if (cc == 0) {
489 cc = min(uio->uio_resid, BUFSIZ);
490 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
491 cp = locbuf;
492 error = uiomove((caddr_t)cp, cc, uio);
493 if (error)
494 return (error);
495 /* check again for safety */
496 if ((tp->t_state&TS_ISOPEN) == 0)
497 return (EIO);
498 }
499 if (cc)
500 (void) b_to_q((char *)cp, cc, &tp->t_canq);
501 cc = 0;
502 }
503 (void) putc(0, &tp->t_canq);
504 ttwakeup(tp);
505 wakeup((caddr_t)&tp->t_canq);
506 return (0);
507 }
508 while (uio->uio_resid > 0) {
509 if (cc == 0) {
510 cc = min(uio->uio_resid, BUFSIZ);
511 cp = locbuf;
512 error = uiomove((caddr_t)cp, cc, uio);
513 if (error)
514 return (error);
515 /* check again for safety */
516 if ((tp->t_state&TS_ISOPEN) == 0)
517 return (EIO);
518 }
519 while (cc > 0) {
520 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
521 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
522 wakeup((caddr_t)&tp->t_rawq);
523 goto block;
524 }
525 (*linesw[tp->t_line].l_rint)(*cp++, tp);
526 cnt++;
527 cc--;
528 }
529 cc = 0;
530 }
531 return (0);
532block:
533 /*
534 * Come here to wait for slave to open, for space
535 * in outq, or space in rawq.
536 */
537 if ((tp->t_state&TS_CARR_ON) == 0)
538 return (EIO);
539 if (flag & IO_NDELAY) {
540 /* adjust for data copied in but not written */
541 uio->uio_resid += cc;
542 if (cnt == 0)
543 return (EWOULDBLOCK);
544 return (0);
545 }
546 error = tsleep((caddr_t)&tp->t_rawq.c_cl, TTOPRI | PCATCH, ttyout, 0);
547 if (error) {
548 /* adjust for data copied in but not written */
549 uio->uio_resid += cc;
550 return (error);
551 }
552 goto again;
553}
554
555struct tty *
556ptydevtotty(dev)
557 dev_t dev;
558{
559 if (minor(dev) >= npty)
560 return (NULL);
561
562 return &pt_tty[minor(dev)];
563}
564
565/*ARGSUSED*/
566int
567ptyioctl(dev, cmd, data, flag, p)
568 dev_t dev;
569 int cmd;
570 caddr_t data;
571 int flag;
572 struct proc *p;
573{
574 register struct tty *tp = &pt_tty[minor(dev)];
575 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
576 register u_char *cc = tp->t_cc;
577 int stop, error;
578
579 /*
580 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
581 * ttywflush(tp) will hang if there are characters in the outq.
582 */
583 if (cmd == TIOCEXT) {
584 /*
585 * When the EXTPROC bit is being toggled, we need
586 * to send an TIOCPKT_IOCTL if the packet driver
587 * is turned on.
588 */
589 if (*(int *)data) {
590 if (pti->pt_flags & PF_PKT) {
591 pti->pt_send |= TIOCPKT_IOCTL;
592 ptcwakeup(tp, FREAD);
593 }
594 tp->t_lflag |= EXTPROC;
595 } else {
596 if ((tp->t_state & EXTPROC) &&
597 (pti->pt_flags & PF_PKT)) {
598 pti->pt_send |= TIOCPKT_IOCTL;
599 ptcwakeup(tp, FREAD);
600 }
601 tp->t_lflag &= ~EXTPROC;
602 }
603 return(0);
604 } else
605 if (cdevsw[major(dev)].d_open == ptcopen)
606 switch (cmd) {
607
608 case TIOCGPGRP:
609 /*
610 * We aviod calling ttioctl on the controller since,
611 * in that case, tp must be the controlling terminal.
612 */
613 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
614 return (0);
615
616 case TIOCPKT:
617 if (*(int *)data) {
618 if (pti->pt_flags & PF_UCNTL)
619 return (EINVAL);
620 pti->pt_flags |= PF_PKT;
621 } else
622 pti->pt_flags &= ~PF_PKT;
623 return (0);
624
625 case TIOCUCNTL:
626 if (*(int *)data) {
627 if (pti->pt_flags & PF_PKT)
628 return (EINVAL);
629 pti->pt_flags |= PF_UCNTL;
630 } else
631 pti->pt_flags &= ~PF_UCNTL;
632 return (0);
633
634 case TIOCREMOTE:
635 if (*(int *)data)
636 pti->pt_flags |= PF_REMOTE;
637 else
638 pti->pt_flags &= ~PF_REMOTE;
639 ttyflush(tp, FREAD|FWRITE);
640 return (0);
641
642#ifdef COMPAT_43
643 case TIOCSETP:
644 case TIOCSETN:
645#endif
646 case TIOCSETD:
647 case TIOCSETA:
648 case TIOCSETAW:
649 case TIOCSETAF:
650 ndflush(&tp->t_outq, tp->t_outq.c_cc);
651 break;
652
653 case TIOCSIG:
654 if (*(unsigned int *)data >= NSIG)
655 return(EINVAL);
656 if ((tp->t_lflag&NOFLSH) == 0)
657 ttyflush(tp, FREAD|FWRITE);
658 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
659 if ((*(unsigned int *)data == SIGINFO) &&
660 ((tp->t_lflag&NOKERNINFO) == 0))
661 ttyinfo(tp);
662 return(0);
663 }
664 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
665 if (error < 0)
666 error = ttioctl(tp, cmd, data, flag);
667 if (error < 0) {
668 if (pti->pt_flags & PF_UCNTL &&
669 (cmd & ~0xff) == UIOCCMD(0)) {
670 if (cmd & 0xff) {
671 pti->pt_ucntl = (u_char)cmd;
672 ptcwakeup(tp, FREAD);
673 }
674 return (0);
675 }
676 error = ENOTTY;
677 }
678 /*
679 * If external processing and packet mode send ioctl packet.
680 */
681 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
682 switch(cmd) {
683 case TIOCSETA:
684 case TIOCSETAW:
685 case TIOCSETAF:
686#ifdef COMPAT_43
687 case TIOCSETP:
688 case TIOCSETN:
689#endif
690#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
691 case TIOCSETC:
692 case TIOCSLTC:
693 case TIOCLBIS:
694 case TIOCLBIC:
695 case TIOCLSET:
696#endif
697 pti->pt_send |= TIOCPKT_IOCTL;
698 ptcwakeup(tp, FREAD);
699 default:
700 break;
701 }
702 }
703 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
704 && CCEQ(cc[VSTART], CTRL('q'));
705 if (pti->pt_flags & PF_NOSTOP) {
706 if (stop) {
707 pti->pt_send &= ~TIOCPKT_NOSTOP;
708 pti->pt_send |= TIOCPKT_DOSTOP;
709 pti->pt_flags &= ~PF_NOSTOP;
710 ptcwakeup(tp, FREAD);
711 }
712 } else {
713 if (!stop) {
714 pti->pt_send &= ~TIOCPKT_DOSTOP;
715 pti->pt_send |= TIOCPKT_NOSTOP;
716 pti->pt_flags |= PF_NOSTOP;
717 ptcwakeup(tp, FREAD);
718 }
719 }
720 return (error);
721}
165 return (err);
166}
167
168int
169ptsread(dev, uio, flag)
170 dev_t dev;
171 struct uio *uio;
172 int flag;
173{
174 struct proc *p = curproc;
175 register struct tty *tp = &pt_tty[minor(dev)];
176 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
177 int error = 0;
178
179again:
180 if (pti->pt_flags & PF_REMOTE) {
181 while (isbackground(p, tp)) {
182 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
183 (p->p_sigmask & sigmask(SIGTTIN)) ||
184 p->p_pgrp->pg_jobc == 0 ||
185 p->p_flag & P_PPWAIT)
186 return (EIO);
187 pgsignal(p->p_pgrp, SIGTTIN, 1);
188 error = ttysleep(tp, (caddr_t)&lbolt,
189 TTIPRI | PCATCH, ttybg, 0);
190 if (error)
191 return (error);
192 }
193 if (tp->t_canq.c_cc == 0) {
194 if (flag & IO_NDELAY)
195 return (EWOULDBLOCK);
196 error = ttysleep(tp, (caddr_t)&tp->t_canq,
197 TTIPRI | PCATCH, ttyin, 0);
198 if (error)
199 return (error);
200 goto again;
201 }
202 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
203 if (ureadc(getc(&tp->t_canq), uio) < 0) {
204 error = EFAULT;
205 break;
206 }
207 if (tp->t_canq.c_cc == 1)
208 (void) getc(&tp->t_canq);
209 if (tp->t_canq.c_cc)
210 return (error);
211 } else
212 if (tp->t_oproc)
213 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
214 ptcwakeup(tp, FWRITE);
215 return (error);
216}
217
218/*
219 * Write to pseudo-tty.
220 * Wakeups of controlling tty will happen
221 * indirectly, when tty driver calls ptsstart.
222 */
223int
224ptswrite(dev, uio, flag)
225 dev_t dev;
226 struct uio *uio;
227 int flag;
228{
229 register struct tty *tp;
230
231 tp = &pt_tty[minor(dev)];
232 if (tp->t_oproc == 0)
233 return (EIO);
234 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
235}
236
237/*
238 * Start output on pseudo-tty.
239 * Wake up process selecting or sleeping for input from controlling tty.
240 */
241void
242ptsstart(tp)
243 struct tty *tp;
244{
245 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
246
247 if (tp->t_state & TS_TTSTOP)
248 return;
249 if (pti->pt_flags & PF_STOPPED) {
250 pti->pt_flags &= ~PF_STOPPED;
251 pti->pt_send = TIOCPKT_START;
252 }
253 ptcwakeup(tp, FREAD);
254}
255
256void
257ptcwakeup(tp, flag)
258 struct tty *tp;
259 int flag;
260{
261 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
262
263 if (flag & FREAD) {
264 selwakeup(&pti->pt_selr);
265 wakeup((caddr_t)&tp->t_outq.c_cf);
266 }
267 if (flag & FWRITE) {
268 selwakeup(&pti->pt_selw);
269 wakeup((caddr_t)&tp->t_rawq.c_cl);
270 }
271}
272
273/*ARGSUSED*/
274#ifdef __STDC__
275int
276ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
277#else
278int
279ptcopen(dev, flag, devtype, p)
280 dev_t dev;
281 int flag, devtype;
282 struct proc *p;
283#endif
284{
285 register struct tty *tp;
286 struct pt_ioctl *pti;
287
288 if (minor(dev) >= npty)
289 return (ENXIO);
290 tp = &pt_tty[minor(dev)];
291 if (tp->t_oproc)
292 return (EIO);
293 tp->t_oproc = ptsstart;
294#ifdef sun4c
295 tp->t_stop = ptsstop;
296#endif
297 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
298 tp->t_lflag &= ~EXTPROC;
299 pti = &pt_ioctl[minor(dev)];
300 pti->pt_flags = 0;
301 pti->pt_send = 0;
302 pti->pt_ucntl = 0;
303 return (0);
304}
305
306int
307ptcclose(dev)
308 dev_t dev;
309{
310 register struct tty *tp;
311
312 tp = &pt_tty[minor(dev)];
313 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
314 tp->t_state &= ~TS_CARR_ON;
315 tp->t_oproc = 0; /* mark closed */
316 tp->t_session = 0;
317 return (0);
318}
319
320int
321ptcread(dev, uio, flag)
322 dev_t dev;
323 struct uio *uio;
324 int flag;
325{
326 register struct tty *tp = &pt_tty[minor(dev)];
327 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
328 char buf[BUFSIZ];
329 int error = 0, cc;
330
331 /*
332 * We want to block until the slave
333 * is open, and there's something to read;
334 * but if we lost the slave or we're NBIO,
335 * then return the appropriate error instead.
336 */
337 for (;;) {
338 if (tp->t_state&TS_ISOPEN) {
339 if (pti->pt_flags&PF_PKT && pti->pt_send) {
340 error = ureadc((int)pti->pt_send, uio);
341 if (error)
342 return (error);
343 if (pti->pt_send & TIOCPKT_IOCTL) {
344 cc = min(uio->uio_resid,
345 sizeof(tp->t_termios));
346 uiomove((caddr_t)&tp->t_termios, cc,
347 uio);
348 }
349 pti->pt_send = 0;
350 return (0);
351 }
352 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
353 error = ureadc((int)pti->pt_ucntl, uio);
354 if (error)
355 return (error);
356 pti->pt_ucntl = 0;
357 return (0);
358 }
359 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
360 break;
361 }
362 if ((tp->t_state&TS_CARR_ON) == 0)
363 return (0); /* EOF */
364 if (flag & IO_NDELAY)
365 return (EWOULDBLOCK);
366 error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
367 ttyin, 0);
368 if (error)
369 return (error);
370 }
371 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
372 error = ureadc(0, uio);
373 while (uio->uio_resid > 0 && error == 0) {
374 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
375 if (cc <= 0)
376 break;
377 error = uiomove(buf, cc, uio);
378 }
379 if (tp->t_outq.c_cc <= tp->t_lowat) {
380 if (tp->t_state&TS_ASLEEP) {
381 tp->t_state &= ~TS_ASLEEP;
382 wakeup((caddr_t)&tp->t_outq);
383 }
384 selwakeup(&tp->t_wsel);
385 }
386 return (error);
387}
388
389void
390ptsstop(tp, flush)
391 register struct tty *tp;
392 int flush;
393{
394 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
395 int flag;
396
397 /* note: FLUSHREAD and FLUSHWRITE already ok */
398 if (flush == 0) {
399 flush = TIOCPKT_STOP;
400 pti->pt_flags |= PF_STOPPED;
401 } else
402 pti->pt_flags &= ~PF_STOPPED;
403 pti->pt_send |= flush;
404 /* change of perspective */
405 flag = 0;
406 if (flush & FREAD)
407 flag |= FWRITE;
408 if (flush & FWRITE)
409 flag |= FREAD;
410 ptcwakeup(tp, flag);
411}
412
413int
414ptcselect(dev, rw, p)
415 dev_t dev;
416 int rw;
417 struct proc *p;
418{
419 register struct tty *tp = &pt_tty[minor(dev)];
420 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
421 int s;
422
423 if ((tp->t_state&TS_CARR_ON) == 0)
424 return (1);
425 switch (rw) {
426
427 case FREAD:
428 /*
429 * Need to block timeouts (ttrstart).
430 */
431 s = spltty();
432 if ((tp->t_state&TS_ISOPEN) &&
433 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
434 splx(s);
435 return (1);
436 }
437 splx(s);
438 /* FALLTHROUGH */
439
440 case 0: /* exceptional */
441 if ((tp->t_state&TS_ISOPEN) &&
442 ((pti->pt_flags&PF_PKT && pti->pt_send) ||
443 (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
444 return (1);
445 selrecord(p, &pti->pt_selr);
446 break;
447
448
449 case FWRITE:
450 if (tp->t_state&TS_ISOPEN) {
451 if (pti->pt_flags & PF_REMOTE) {
452 if (tp->t_canq.c_cc == 0)
453 return (1);
454 } else {
455 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
456 return (1);
457 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
458 return (1);
459 }
460 }
461 selrecord(p, &pti->pt_selw);
462 break;
463
464 }
465 return (0);
466}
467
468int
469ptcwrite(dev, uio, flag)
470 dev_t dev;
471 register struct uio *uio;
472 int flag;
473{
474 register struct tty *tp = &pt_tty[minor(dev)];
475 register u_char *cp = 0;
476 register int cc = 0;
477 u_char locbuf[BUFSIZ];
478 int cnt = 0;
479 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
480 int error = 0;
481
482again:
483 if ((tp->t_state&TS_ISOPEN) == 0)
484 goto block;
485 if (pti->pt_flags & PF_REMOTE) {
486 if (tp->t_canq.c_cc)
487 goto block;
488 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
489 if (cc == 0) {
490 cc = min(uio->uio_resid, BUFSIZ);
491 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
492 cp = locbuf;
493 error = uiomove((caddr_t)cp, cc, uio);
494 if (error)
495 return (error);
496 /* check again for safety */
497 if ((tp->t_state&TS_ISOPEN) == 0)
498 return (EIO);
499 }
500 if (cc)
501 (void) b_to_q((char *)cp, cc, &tp->t_canq);
502 cc = 0;
503 }
504 (void) putc(0, &tp->t_canq);
505 ttwakeup(tp);
506 wakeup((caddr_t)&tp->t_canq);
507 return (0);
508 }
509 while (uio->uio_resid > 0) {
510 if (cc == 0) {
511 cc = min(uio->uio_resid, BUFSIZ);
512 cp = locbuf;
513 error = uiomove((caddr_t)cp, cc, uio);
514 if (error)
515 return (error);
516 /* check again for safety */
517 if ((tp->t_state&TS_ISOPEN) == 0)
518 return (EIO);
519 }
520 while (cc > 0) {
521 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
522 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
523 wakeup((caddr_t)&tp->t_rawq);
524 goto block;
525 }
526 (*linesw[tp->t_line].l_rint)(*cp++, tp);
527 cnt++;
528 cc--;
529 }
530 cc = 0;
531 }
532 return (0);
533block:
534 /*
535 * Come here to wait for slave to open, for space
536 * in outq, or space in rawq.
537 */
538 if ((tp->t_state&TS_CARR_ON) == 0)
539 return (EIO);
540 if (flag & IO_NDELAY) {
541 /* adjust for data copied in but not written */
542 uio->uio_resid += cc;
543 if (cnt == 0)
544 return (EWOULDBLOCK);
545 return (0);
546 }
547 error = tsleep((caddr_t)&tp->t_rawq.c_cl, TTOPRI | PCATCH, ttyout, 0);
548 if (error) {
549 /* adjust for data copied in but not written */
550 uio->uio_resid += cc;
551 return (error);
552 }
553 goto again;
554}
555
556struct tty *
557ptydevtotty(dev)
558 dev_t dev;
559{
560 if (minor(dev) >= npty)
561 return (NULL);
562
563 return &pt_tty[minor(dev)];
564}
565
566/*ARGSUSED*/
567int
568ptyioctl(dev, cmd, data, flag, p)
569 dev_t dev;
570 int cmd;
571 caddr_t data;
572 int flag;
573 struct proc *p;
574{
575 register struct tty *tp = &pt_tty[minor(dev)];
576 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
577 register u_char *cc = tp->t_cc;
578 int stop, error;
579
580 /*
581 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
582 * ttywflush(tp) will hang if there are characters in the outq.
583 */
584 if (cmd == TIOCEXT) {
585 /*
586 * When the EXTPROC bit is being toggled, we need
587 * to send an TIOCPKT_IOCTL if the packet driver
588 * is turned on.
589 */
590 if (*(int *)data) {
591 if (pti->pt_flags & PF_PKT) {
592 pti->pt_send |= TIOCPKT_IOCTL;
593 ptcwakeup(tp, FREAD);
594 }
595 tp->t_lflag |= EXTPROC;
596 } else {
597 if ((tp->t_state & EXTPROC) &&
598 (pti->pt_flags & PF_PKT)) {
599 pti->pt_send |= TIOCPKT_IOCTL;
600 ptcwakeup(tp, FREAD);
601 }
602 tp->t_lflag &= ~EXTPROC;
603 }
604 return(0);
605 } else
606 if (cdevsw[major(dev)].d_open == ptcopen)
607 switch (cmd) {
608
609 case TIOCGPGRP:
610 /*
611 * We aviod calling ttioctl on the controller since,
612 * in that case, tp must be the controlling terminal.
613 */
614 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
615 return (0);
616
617 case TIOCPKT:
618 if (*(int *)data) {
619 if (pti->pt_flags & PF_UCNTL)
620 return (EINVAL);
621 pti->pt_flags |= PF_PKT;
622 } else
623 pti->pt_flags &= ~PF_PKT;
624 return (0);
625
626 case TIOCUCNTL:
627 if (*(int *)data) {
628 if (pti->pt_flags & PF_PKT)
629 return (EINVAL);
630 pti->pt_flags |= PF_UCNTL;
631 } else
632 pti->pt_flags &= ~PF_UCNTL;
633 return (0);
634
635 case TIOCREMOTE:
636 if (*(int *)data)
637 pti->pt_flags |= PF_REMOTE;
638 else
639 pti->pt_flags &= ~PF_REMOTE;
640 ttyflush(tp, FREAD|FWRITE);
641 return (0);
642
643#ifdef COMPAT_43
644 case TIOCSETP:
645 case TIOCSETN:
646#endif
647 case TIOCSETD:
648 case TIOCSETA:
649 case TIOCSETAW:
650 case TIOCSETAF:
651 ndflush(&tp->t_outq, tp->t_outq.c_cc);
652 break;
653
654 case TIOCSIG:
655 if (*(unsigned int *)data >= NSIG)
656 return(EINVAL);
657 if ((tp->t_lflag&NOFLSH) == 0)
658 ttyflush(tp, FREAD|FWRITE);
659 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
660 if ((*(unsigned int *)data == SIGINFO) &&
661 ((tp->t_lflag&NOKERNINFO) == 0))
662 ttyinfo(tp);
663 return(0);
664 }
665 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
666 if (error < 0)
667 error = ttioctl(tp, cmd, data, flag);
668 if (error < 0) {
669 if (pti->pt_flags & PF_UCNTL &&
670 (cmd & ~0xff) == UIOCCMD(0)) {
671 if (cmd & 0xff) {
672 pti->pt_ucntl = (u_char)cmd;
673 ptcwakeup(tp, FREAD);
674 }
675 return (0);
676 }
677 error = ENOTTY;
678 }
679 /*
680 * If external processing and packet mode send ioctl packet.
681 */
682 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
683 switch(cmd) {
684 case TIOCSETA:
685 case TIOCSETAW:
686 case TIOCSETAF:
687#ifdef COMPAT_43
688 case TIOCSETP:
689 case TIOCSETN:
690#endif
691#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
692 case TIOCSETC:
693 case TIOCSLTC:
694 case TIOCLBIS:
695 case TIOCLBIC:
696 case TIOCLSET:
697#endif
698 pti->pt_send |= TIOCPKT_IOCTL;
699 ptcwakeup(tp, FREAD);
700 default:
701 break;
702 }
703 }
704 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
705 && CCEQ(cc[VSTART], CTRL('q'));
706 if (pti->pt_flags & PF_NOSTOP) {
707 if (stop) {
708 pti->pt_send &= ~TIOCPKT_NOSTOP;
709 pti->pt_send |= TIOCPKT_DOSTOP;
710 pti->pt_flags &= ~PF_NOSTOP;
711 ptcwakeup(tp, FREAD);
712 }
713 } else {
714 if (!stop) {
715 pti->pt_send &= ~TIOCPKT_DOSTOP;
716 pti->pt_send |= TIOCPKT_NOSTOP;
717 pti->pt_flags |= PF_NOSTOP;
718 ptcwakeup(tp, FREAD);
719 }
720 }
721 return (error);
722}