Deleted Added
full compact
pty.c (9824) pty.c (9850)
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.15 1995/07/22 16:45:08 bde Exp $
34 * $Id: tty_pty.c,v 1.16 1995/07/31 21:01:25 bde 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 ttychars(tp); /* Set up default chars */
126 tp->t_iflag = TTYDEF_IFLAG;
127 tp->t_oflag = TTYDEF_OFLAG;
128 tp->t_lflag = TTYDEF_LFLAG;
129 tp->t_cflag = TTYDEF_CFLAG;
130 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
131 ttsetwater(tp); /* would be done in xxparam() */
132 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
133 return (EBUSY);
134 if (tp->t_oproc) /* Ctrlr still around. */
135 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
136 while ((tp->t_state & TS_CARR_ON) == 0) {
137 if (flag&FNONBLOCK)
138 break;
139 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
140 "ptsopn", 0);
141 if (error)
142 return (error);
143 }
144 error = (*linesw[tp->t_line].l_open)(dev, tp);
145 if (error == 0)
146 ptcwakeup(tp, FREAD|FWRITE);
147 return (error);
148}
149
150int
151ptsclose(dev, flag, mode, p)
152 dev_t dev;
153 int flag, mode;
154 struct proc *p;
155{
156 register struct tty *tp;
157 int err;
158
159 tp = &pt_tty[minor(dev)];
160 err = (*linesw[tp->t_line].l_close)(tp, flag);
161 ptsstop(tp, FREAD|FWRITE);
162 (void) ttyclose(tp);
163 return (err);
164}
165
166int
167ptsread(dev, uio, flag)
168 dev_t dev;
169 struct uio *uio;
170 int flag;
171{
172 struct proc *p = curproc;
173 register struct tty *tp = &pt_tty[minor(dev)];
174 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
175 int error = 0;
176
177again:
178 if (pti->pt_flags & PF_REMOTE) {
179 while (isbackground(p, tp)) {
180 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
181 (p->p_sigmask & sigmask(SIGTTIN)) ||
182 p->p_pgrp->pg_jobc == 0 ||
183 p->p_flag & P_PPWAIT)
184 return (EIO);
185 pgsignal(p->p_pgrp, SIGTTIN, 1);
186 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
187 0);
188 if (error)
189 return (error);
190 }
191 if (tp->t_canq.c_cc == 0) {
192 if (flag & IO_NDELAY)
193 return (EWOULDBLOCK);
194 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
195 "ptsin", 0);
196 if (error)
197 return (error);
198 goto again;
199 }
200 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
201 if (ureadc(getc(&tp->t_canq), uio) < 0) {
202 error = EFAULT;
203 break;
204 }
205 if (tp->t_canq.c_cc == 1)
206 (void) getc(&tp->t_canq);
207 if (tp->t_canq.c_cc)
208 return (error);
209 } else
210 if (tp->t_oproc)
211 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
212 ptcwakeup(tp, FWRITE);
213 return (error);
214}
215
216/*
217 * Write to pseudo-tty.
218 * Wakeups of controlling tty will happen
219 * indirectly, when tty driver calls ptsstart.
220 */
221int
222ptswrite(dev, uio, flag)
223 dev_t dev;
224 struct uio *uio;
225 int flag;
226{
227 register struct tty *tp;
228
229 tp = &pt_tty[minor(dev)];
230 if (tp->t_oproc == 0)
231 return (EIO);
232 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
233}
234
235/*
236 * Start output on pseudo-tty.
237 * Wake up process selecting or sleeping for input from controlling tty.
238 */
239void
240ptsstart(tp)
241 struct tty *tp;
242{
243 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
244
245 if (tp->t_state & TS_TTSTOP)
246 return;
247 if (pti->pt_flags & PF_STOPPED) {
248 pti->pt_flags &= ~PF_STOPPED;
249 pti->pt_send = TIOCPKT_START;
250 }
251 ptcwakeup(tp, FREAD);
252}
253
254void
255ptcwakeup(tp, flag)
256 struct tty *tp;
257 int flag;
258{
259 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
260
261 if (flag & FREAD) {
262 selwakeup(&pti->pt_selr);
263 wakeup(TSA_PTC_READ(tp));
264 }
265 if (flag & FWRITE) {
266 selwakeup(&pti->pt_selw);
267 wakeup(TSA_PTC_WRITE(tp));
268 }
269}
270
271int
272ptcopen(dev, flag, devtype, p)
273 dev_t dev;
274 int flag, devtype;
275 struct proc *p;
276{
277 register struct tty *tp;
278 struct pt_ioctl *pti;
279
280 if (minor(dev) >= npty)
281 return (ENXIO);
282 tp = &pt_tty[minor(dev)];
283 if (tp->t_oproc)
284 return (EIO);
285 tp->t_oproc = ptsstart;
286#ifdef sun4c
287 tp->t_stop = ptsstop;
288#endif
289 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
290 tp->t_lflag &= ~EXTPROC;
291 pti = &pt_ioctl[minor(dev)];
292 pti->pt_flags = 0;
293 pti->pt_send = 0;
294 pti->pt_ucntl = 0;
295 return (0);
296}
297
298int
299ptcclose(dev)
300 dev_t dev;
301{
302 register struct tty *tp;
303
304 tp = &pt_tty[minor(dev)];
305 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
306
307 /*
308 * XXX MDMBUF makes no sense for ptys but would inhibit the above
309 * l_modem(). CLOCAL makes sense but isn't supported. Special
310 * l_modem()s that ignore carrier drop make no sense for ptys but
311 * may be in use because other parts of the line discipline make
312 * sense for ptys. Recover by doing everything that a normal
313 * ttymodem() would have done except for sending a SIGHUP.
314 */
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 ttychars(tp); /* Set up default chars */
126 tp->t_iflag = TTYDEF_IFLAG;
127 tp->t_oflag = TTYDEF_OFLAG;
128 tp->t_lflag = TTYDEF_LFLAG;
129 tp->t_cflag = TTYDEF_CFLAG;
130 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
131 ttsetwater(tp); /* would be done in xxparam() */
132 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
133 return (EBUSY);
134 if (tp->t_oproc) /* Ctrlr still around. */
135 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
136 while ((tp->t_state & TS_CARR_ON) == 0) {
137 if (flag&FNONBLOCK)
138 break;
139 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
140 "ptsopn", 0);
141 if (error)
142 return (error);
143 }
144 error = (*linesw[tp->t_line].l_open)(dev, tp);
145 if (error == 0)
146 ptcwakeup(tp, FREAD|FWRITE);
147 return (error);
148}
149
150int
151ptsclose(dev, flag, mode, p)
152 dev_t dev;
153 int flag, mode;
154 struct proc *p;
155{
156 register struct tty *tp;
157 int err;
158
159 tp = &pt_tty[minor(dev)];
160 err = (*linesw[tp->t_line].l_close)(tp, flag);
161 ptsstop(tp, FREAD|FWRITE);
162 (void) ttyclose(tp);
163 return (err);
164}
165
166int
167ptsread(dev, uio, flag)
168 dev_t dev;
169 struct uio *uio;
170 int flag;
171{
172 struct proc *p = curproc;
173 register struct tty *tp = &pt_tty[minor(dev)];
174 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
175 int error = 0;
176
177again:
178 if (pti->pt_flags & PF_REMOTE) {
179 while (isbackground(p, tp)) {
180 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
181 (p->p_sigmask & sigmask(SIGTTIN)) ||
182 p->p_pgrp->pg_jobc == 0 ||
183 p->p_flag & P_PPWAIT)
184 return (EIO);
185 pgsignal(p->p_pgrp, SIGTTIN, 1);
186 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
187 0);
188 if (error)
189 return (error);
190 }
191 if (tp->t_canq.c_cc == 0) {
192 if (flag & IO_NDELAY)
193 return (EWOULDBLOCK);
194 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
195 "ptsin", 0);
196 if (error)
197 return (error);
198 goto again;
199 }
200 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
201 if (ureadc(getc(&tp->t_canq), uio) < 0) {
202 error = EFAULT;
203 break;
204 }
205 if (tp->t_canq.c_cc == 1)
206 (void) getc(&tp->t_canq);
207 if (tp->t_canq.c_cc)
208 return (error);
209 } else
210 if (tp->t_oproc)
211 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
212 ptcwakeup(tp, FWRITE);
213 return (error);
214}
215
216/*
217 * Write to pseudo-tty.
218 * Wakeups of controlling tty will happen
219 * indirectly, when tty driver calls ptsstart.
220 */
221int
222ptswrite(dev, uio, flag)
223 dev_t dev;
224 struct uio *uio;
225 int flag;
226{
227 register struct tty *tp;
228
229 tp = &pt_tty[minor(dev)];
230 if (tp->t_oproc == 0)
231 return (EIO);
232 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
233}
234
235/*
236 * Start output on pseudo-tty.
237 * Wake up process selecting or sleeping for input from controlling tty.
238 */
239void
240ptsstart(tp)
241 struct tty *tp;
242{
243 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
244
245 if (tp->t_state & TS_TTSTOP)
246 return;
247 if (pti->pt_flags & PF_STOPPED) {
248 pti->pt_flags &= ~PF_STOPPED;
249 pti->pt_send = TIOCPKT_START;
250 }
251 ptcwakeup(tp, FREAD);
252}
253
254void
255ptcwakeup(tp, flag)
256 struct tty *tp;
257 int flag;
258{
259 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
260
261 if (flag & FREAD) {
262 selwakeup(&pti->pt_selr);
263 wakeup(TSA_PTC_READ(tp));
264 }
265 if (flag & FWRITE) {
266 selwakeup(&pti->pt_selw);
267 wakeup(TSA_PTC_WRITE(tp));
268 }
269}
270
271int
272ptcopen(dev, flag, devtype, p)
273 dev_t dev;
274 int flag, devtype;
275 struct proc *p;
276{
277 register struct tty *tp;
278 struct pt_ioctl *pti;
279
280 if (minor(dev) >= npty)
281 return (ENXIO);
282 tp = &pt_tty[minor(dev)];
283 if (tp->t_oproc)
284 return (EIO);
285 tp->t_oproc = ptsstart;
286#ifdef sun4c
287 tp->t_stop = ptsstop;
288#endif
289 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
290 tp->t_lflag &= ~EXTPROC;
291 pti = &pt_ioctl[minor(dev)];
292 pti->pt_flags = 0;
293 pti->pt_send = 0;
294 pti->pt_ucntl = 0;
295 return (0);
296}
297
298int
299ptcclose(dev)
300 dev_t dev;
301{
302 register struct tty *tp;
303
304 tp = &pt_tty[minor(dev)];
305 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
306
307 /*
308 * XXX MDMBUF makes no sense for ptys but would inhibit the above
309 * l_modem(). CLOCAL makes sense but isn't supported. Special
310 * l_modem()s that ignore carrier drop make no sense for ptys but
311 * may be in use because other parts of the line discipline make
312 * sense for ptys. Recover by doing everything that a normal
313 * ttymodem() would have done except for sending a SIGHUP.
314 */
315 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
316 tp->t_state |= TS_ZOMBIE;
317 ttyflush(tp, FREAD | FWRITE);
315 if (tp->t_state & TS_ISOPEN) {
316 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
317 tp->t_state |= TS_ZOMBIE;
318 ttyflush(tp, FREAD | FWRITE);
319 }
318
319 tp->t_oproc = 0; /* mark closed */
320 tp->t_session = 0;
321 return (0);
322}
323
324int
325ptcread(dev, uio, flag)
326 dev_t dev;
327 struct uio *uio;
328 int flag;
329{
330 register struct tty *tp = &pt_tty[minor(dev)];
331 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
332 char buf[BUFSIZ];
333 int error = 0, cc;
334
335 /*
336 * We want to block until the slave
337 * is open, and there's something to read;
338 * but if we lost the slave or we're NBIO,
339 * then return the appropriate error instead.
340 */
341 for (;;) {
342 if (tp->t_state&TS_ISOPEN) {
343 if (pti->pt_flags&PF_PKT && pti->pt_send) {
344 error = ureadc((int)pti->pt_send, uio);
345 if (error)
346 return (error);
347 if (pti->pt_send & TIOCPKT_IOCTL) {
348 cc = min(uio->uio_resid,
349 sizeof(tp->t_termios));
350 uiomove((caddr_t)&tp->t_termios, cc,
351 uio);
352 }
353 pti->pt_send = 0;
354 return (0);
355 }
356 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
357 error = ureadc((int)pti->pt_ucntl, uio);
358 if (error)
359 return (error);
360 pti->pt_ucntl = 0;
361 return (0);
362 }
363 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
364 break;
365 }
366 if ((tp->t_state & TS_CONNECTED) == 0)
367 return (0); /* EOF */
368 if (flag & IO_NDELAY)
369 return (EWOULDBLOCK);
370 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
371 if (error)
372 return (error);
373 }
374 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
375 error = ureadc(0, uio);
376 while (uio->uio_resid > 0 && error == 0) {
377 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
378 if (cc <= 0)
379 break;
380 error = uiomove(buf, cc, uio);
381 }
382 ttwwakeup(tp);
383 return (error);
384}
385
386void
387ptsstop(tp, flush)
388 register struct tty *tp;
389 int flush;
390{
391 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
392 int flag;
393
394 /* note: FLUSHREAD and FLUSHWRITE already ok */
395 if (flush == 0) {
396 flush = TIOCPKT_STOP;
397 pti->pt_flags |= PF_STOPPED;
398 } else
399 pti->pt_flags &= ~PF_STOPPED;
400 pti->pt_send |= flush;
401 /* change of perspective */
402 flag = 0;
403 if (flush & FREAD)
404 flag |= FWRITE;
405 if (flush & FWRITE)
406 flag |= FREAD;
407 ptcwakeup(tp, flag);
408}
409
410int
411ptcselect(dev, rw, p)
412 dev_t dev;
413 int rw;
414 struct proc *p;
415{
416 register struct tty *tp = &pt_tty[minor(dev)];
417 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
418 int s;
419
420 if ((tp->t_state & TS_CONNECTED) == 0)
421 return (1);
422 switch (rw) {
423
424 case FREAD:
425 /*
426 * Need to block timeouts (ttrstart).
427 */
428 s = spltty();
429 if ((tp->t_state&TS_ISOPEN) &&
430 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
431 splx(s);
432 return (1);
433 }
434 splx(s);
435 /* FALLTHROUGH */
436
437 case 0: /* exceptional */
438 if ((tp->t_state&TS_ISOPEN) &&
439 ((pti->pt_flags&PF_PKT && pti->pt_send) ||
440 (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
441 return (1);
442 selrecord(p, &pti->pt_selr);
443 break;
444
445
446 case FWRITE:
447 if (tp->t_state&TS_ISOPEN) {
448 if (pti->pt_flags & PF_REMOTE) {
449 if (tp->t_canq.c_cc == 0)
450 return (1);
451 } else {
452 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
453 return (1);
454 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
455 return (1);
456 }
457 }
458 selrecord(p, &pti->pt_selw);
459 break;
460
461 }
462 return (0);
463}
464
465int
466ptcwrite(dev, uio, flag)
467 dev_t dev;
468 register struct uio *uio;
469 int flag;
470{
471 register struct tty *tp = &pt_tty[minor(dev)];
472 register u_char *cp = 0;
473 register int cc = 0;
474 u_char locbuf[BUFSIZ];
475 int cnt = 0;
476 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
477 int error = 0;
478
479again:
480 if ((tp->t_state&TS_ISOPEN) == 0)
481 goto block;
482 if (pti->pt_flags & PF_REMOTE) {
483 if (tp->t_canq.c_cc)
484 goto block;
485 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
486 if (cc == 0) {
487 cc = min(uio->uio_resid, BUFSIZ);
488 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
489 cp = locbuf;
490 error = uiomove((caddr_t)cp, cc, uio);
491 if (error)
492 return (error);
493 /* check again for safety */
494 if ((tp->t_state&TS_ISOPEN) == 0)
495 return (EIO);
496 }
497 if (cc)
498 (void) b_to_q((char *)cp, cc, &tp->t_canq);
499 cc = 0;
500 }
501 (void) putc(0, &tp->t_canq);
502 ttwakeup(tp);
503 wakeup(TSA_PTS_READ(tp));
504 return (0);
505 }
506 while (uio->uio_resid > 0) {
507 if (cc == 0) {
508 cc = min(uio->uio_resid, BUFSIZ);
509 cp = locbuf;
510 error = uiomove((caddr_t)cp, cc, uio);
511 if (error)
512 return (error);
513 /* check again for safety */
514 if ((tp->t_state&TS_ISOPEN) == 0)
515 return (EIO);
516 }
517 while (cc > 0) {
518 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
519 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
520 wakeup(TSA_HUP_OR_INPUT(tp));
521 goto block;
522 }
523 (*linesw[tp->t_line].l_rint)(*cp++, tp);
524 cnt++;
525 cc--;
526 }
527 cc = 0;
528 }
529 return (0);
530block:
531 /*
532 * Come here to wait for slave to open, for space
533 * in outq, or space in rawq.
534 */
535 if ((tp->t_state & TS_CONNECTED) == 0)
536 return (EIO);
537 if (flag & IO_NDELAY) {
538 /* adjust for data copied in but not written */
539 uio->uio_resid += cc;
540 if (cnt == 0)
541 return (EWOULDBLOCK);
542 return (0);
543 }
544 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
545 if (error) {
546 /* adjust for data copied in but not written */
547 uio->uio_resid += cc;
548 return (error);
549 }
550 goto again;
551}
552
553struct tty *
554ptydevtotty(dev)
555 dev_t dev;
556{
557 if (minor(dev) >= npty)
558 return (NULL);
559
560 return &pt_tty[minor(dev)];
561}
562
563/*ARGSUSED*/
564int
565ptyioctl(dev, cmd, data, flag, p)
566 dev_t dev;
567 int cmd;
568 caddr_t data;
569 int flag;
570 struct proc *p;
571{
572 register struct tty *tp = &pt_tty[minor(dev)];
573 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
574 register u_char *cc = tp->t_cc;
575 int stop, error;
576
577 /*
578 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
579 * ttywflush(tp) will hang if there are characters in the outq.
580 */
581 if (cmd == TIOCEXT) {
582 /*
583 * When the EXTPROC bit is being toggled, we need
584 * to send an TIOCPKT_IOCTL if the packet driver
585 * is turned on.
586 */
587 if (*(int *)data) {
588 if (pti->pt_flags & PF_PKT) {
589 pti->pt_send |= TIOCPKT_IOCTL;
590 ptcwakeup(tp, FREAD);
591 }
592 tp->t_lflag |= EXTPROC;
593 } else {
594 if ((tp->t_state & EXTPROC) &&
595 (pti->pt_flags & PF_PKT)) {
596 pti->pt_send |= TIOCPKT_IOCTL;
597 ptcwakeup(tp, FREAD);
598 }
599 tp->t_lflag &= ~EXTPROC;
600 }
601 return(0);
602 } else
603 if (cdevsw[major(dev)].d_open == ptcopen)
604 switch (cmd) {
605
606 case TIOCGPGRP:
607 /*
608 * We aviod calling ttioctl on the controller since,
609 * in that case, tp must be the controlling terminal.
610 */
611 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
612 return (0);
613
614 case TIOCPKT:
615 if (*(int *)data) {
616 if (pti->pt_flags & PF_UCNTL)
617 return (EINVAL);
618 pti->pt_flags |= PF_PKT;
619 } else
620 pti->pt_flags &= ~PF_PKT;
621 return (0);
622
623 case TIOCUCNTL:
624 if (*(int *)data) {
625 if (pti->pt_flags & PF_PKT)
626 return (EINVAL);
627 pti->pt_flags |= PF_UCNTL;
628 } else
629 pti->pt_flags &= ~PF_UCNTL;
630 return (0);
631
632 case TIOCREMOTE:
633 if (*(int *)data)
634 pti->pt_flags |= PF_REMOTE;
635 else
636 pti->pt_flags &= ~PF_REMOTE;
637 ttyflush(tp, FREAD|FWRITE);
638 return (0);
639
640#ifdef COMPAT_43
641 case TIOCSETP:
642 case TIOCSETN:
643#endif
644 case TIOCSETD:
645 case TIOCSETA:
646 case TIOCSETAW:
647 case TIOCSETAF:
648 ndflush(&tp->t_outq, tp->t_outq.c_cc);
649 break;
650
651 case TIOCSIG:
652 if (*(unsigned int *)data >= NSIG)
653 return(EINVAL);
654 if ((tp->t_lflag&NOFLSH) == 0)
655 ttyflush(tp, FREAD|FWRITE);
656 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
657 if ((*(unsigned int *)data == SIGINFO) &&
658 ((tp->t_lflag&NOKERNINFO) == 0))
659 ttyinfo(tp);
660 return(0);
661 }
662 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
663 if (error < 0)
664 error = ttioctl(tp, cmd, data, flag);
665 if (error < 0) {
666 if (pti->pt_flags & PF_UCNTL &&
667 (cmd & ~0xff) == UIOCCMD(0)) {
668 if (cmd & 0xff) {
669 pti->pt_ucntl = (u_char)cmd;
670 ptcwakeup(tp, FREAD);
671 }
672 return (0);
673 }
674 error = ENOTTY;
675 }
676 /*
677 * If external processing and packet mode send ioctl packet.
678 */
679 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
680 switch(cmd) {
681 case TIOCSETA:
682 case TIOCSETAW:
683 case TIOCSETAF:
684#ifdef COMPAT_43
685 case TIOCSETP:
686 case TIOCSETN:
687#endif
688#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
689 case TIOCSETC:
690 case TIOCSLTC:
691 case TIOCLBIS:
692 case TIOCLBIC:
693 case TIOCLSET:
694#endif
695 pti->pt_send |= TIOCPKT_IOCTL;
696 ptcwakeup(tp, FREAD);
697 default:
698 break;
699 }
700 }
701 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
702 && CCEQ(cc[VSTART], CTRL('q'));
703 if (pti->pt_flags & PF_NOSTOP) {
704 if (stop) {
705 pti->pt_send &= ~TIOCPKT_NOSTOP;
706 pti->pt_send |= TIOCPKT_DOSTOP;
707 pti->pt_flags &= ~PF_NOSTOP;
708 ptcwakeup(tp, FREAD);
709 }
710 } else {
711 if (!stop) {
712 pti->pt_send &= ~TIOCPKT_DOSTOP;
713 pti->pt_send |= TIOCPKT_NOSTOP;
714 pti->pt_flags |= PF_NOSTOP;
715 ptcwakeup(tp, FREAD);
716 }
717 }
718 return (error);
719}
320
321 tp->t_oproc = 0; /* mark closed */
322 tp->t_session = 0;
323 return (0);
324}
325
326int
327ptcread(dev, uio, flag)
328 dev_t dev;
329 struct uio *uio;
330 int flag;
331{
332 register struct tty *tp = &pt_tty[minor(dev)];
333 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
334 char buf[BUFSIZ];
335 int error = 0, cc;
336
337 /*
338 * We want to block until the slave
339 * is open, and there's something to read;
340 * but if we lost the slave or we're NBIO,
341 * then return the appropriate error instead.
342 */
343 for (;;) {
344 if (tp->t_state&TS_ISOPEN) {
345 if (pti->pt_flags&PF_PKT && pti->pt_send) {
346 error = ureadc((int)pti->pt_send, uio);
347 if (error)
348 return (error);
349 if (pti->pt_send & TIOCPKT_IOCTL) {
350 cc = min(uio->uio_resid,
351 sizeof(tp->t_termios));
352 uiomove((caddr_t)&tp->t_termios, cc,
353 uio);
354 }
355 pti->pt_send = 0;
356 return (0);
357 }
358 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
359 error = ureadc((int)pti->pt_ucntl, uio);
360 if (error)
361 return (error);
362 pti->pt_ucntl = 0;
363 return (0);
364 }
365 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
366 break;
367 }
368 if ((tp->t_state & TS_CONNECTED) == 0)
369 return (0); /* EOF */
370 if (flag & IO_NDELAY)
371 return (EWOULDBLOCK);
372 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
373 if (error)
374 return (error);
375 }
376 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
377 error = ureadc(0, uio);
378 while (uio->uio_resid > 0 && error == 0) {
379 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
380 if (cc <= 0)
381 break;
382 error = uiomove(buf, cc, uio);
383 }
384 ttwwakeup(tp);
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_CONNECTED) == 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(TSA_PTS_READ(tp));
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(TSA_HUP_OR_INPUT(tp));
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_CONNECTED) == 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(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 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}