Commit | Line | Data |
---|---|---|
d19cae27 | 1 | /* tty_pty.c 6.11 85/06/07 */ |
be4367b3 | 2 | |
45372428 MT |
3 | /* |
4 | * Pseudo-teletype Driver | |
5 | * (Actually two drivers, requiring two entries in 'cdevsw') | |
45372428 | 6 | */ |
647d645f MT |
7 | #include "pty.h" |
8 | ||
f12183e4 | 9 | #if NPTY > 0 |
94368568 JB |
10 | #include "param.h" |
11 | #include "systm.h" | |
12 | #include "ioctl.h" | |
13 | #include "tty.h" | |
14 | #include "dir.h" | |
15 | #include "user.h" | |
16 | #include "conf.h" | |
17 | #include "file.h" | |
18 | #include "proc.h" | |
19 | #include "uio.h" | |
20 | #include "kernel.h" | |
941944c9 | 21 | |
b3c8737d | 22 | #if NPTY == 1 |
5bb90914 | 23 | #undef NPTY |
c91c01fe | 24 | #define NPTY 32 /* crude XXX */ |
b3c8737d | 25 | #endif |
45372428 | 26 | |
2bb0bef9 | 27 | #define BUFSIZ 100 /* Chunk size iomoved to/from user */ |
e1d74936 | 28 | |
45372428 | 29 | /* |
5bb90914 JB |
30 | * pts == /dev/tty[pqrs]? |
31 | * ptc == /dev/pty[pqrs]? | |
45372428 | 32 | */ |
e1d74936 BJ |
33 | struct tty pt_tty[NPTY]; |
34 | struct pt_ioctl { | |
1a954a11 BJ |
35 | int pt_flags; |
36 | int pt_gensym; | |
37 | struct proc *pt_selr, *pt_selw; | |
5bb90914 JB |
38 | u_char pt_send; |
39 | u_char pt_ucntl; | |
e1d74936 | 40 | } pt_ioctl[NPTY]; |
5bb90914 | 41 | int npty = NPTY; /* for pstat -t */ |
45372428 | 42 | |
1a954a11 BJ |
43 | #define PF_RCOLL 0x01 |
44 | #define PF_WCOLL 0x02 | |
45 | #define PF_NBIO 0x04 | |
46 | #define PF_PKT 0x08 /* packet mode */ | |
1e6d24b1 | 47 | #define PF_STOPPED 0x10 /* user told stopped */ |
defdbcd1 | 48 | #define PF_REMOTE 0x20 /* remote and flow controlled input */ |
0a2bd708 | 49 | #define PF_NOSTOP 0x40 |
5bb90914 | 50 | #define PF_UCNTL 0x80 /* user control mode */ |
45372428 MT |
51 | |
52 | /*ARGSUSED*/ | |
53 | ptsopen(dev, flag) | |
73c77d38 | 54 | dev_t dev; |
e1d74936 | 55 | { |
45372428 | 56 | register struct tty *tp; |
5bb90914 | 57 | int error; |
45372428 | 58 | |
5bb90914 JB |
59 | #ifdef lint |
60 | npty = npty; | |
61 | #endif | |
f21c8fb8 BJ |
62 | if (minor(dev) >= NPTY) |
63 | return (ENXIO); | |
45372428 | 64 | tp = &pt_tty[minor(dev)]; |
941944c9 | 65 | if ((tp->t_state & TS_ISOPEN) == 0) { |
bdda6b91 | 66 | ttychars(tp); /* Set up default chars */ |
d2f24af0 | 67 | tp->t_ispeed = tp->t_ospeed = EXTB; |
bdda6b91 | 68 | tp->t_flags = 0; /* No features (nor raw mode) */ |
f21c8fb8 BJ |
69 | } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) |
70 | return (EBUSY); | |
e1d74936 | 71 | if (tp->t_oproc) /* Ctrlr still around. */ |
941944c9 BJ |
72 | tp->t_state |= TS_CARR_ON; |
73 | while ((tp->t_state & TS_CARR_ON) == 0) { | |
74 | tp->t_state |= TS_WOPEN; | |
45372428 MT |
75 | sleep((caddr_t)&tp->t_rawq, TTIPRI); |
76 | } | |
5bb90914 JB |
77 | error = (*linesw[tp->t_line].l_open)(dev, tp); |
78 | ptcwakeup(tp, FREAD|FWRITE); | |
79 | return (error); | |
45372428 MT |
80 | } |
81 | ||
82 | ptsclose(dev) | |
73c77d38 | 83 | dev_t dev; |
941944c9 | 84 | { |
45372428 MT |
85 | register struct tty *tp; |
86 | ||
87 | tp = &pt_tty[minor(dev)]; | |
88 | (*linesw[tp->t_line].l_close)(tp); | |
4b39cb77 | 89 | ttyclose(tp); |
5bb90914 | 90 | ptcwakeup(tp, FREAD|FWRITE); |
45372428 MT |
91 | } |
92 | ||
ae9a0a69 | 93 | ptsread(dev, uio) |
73c77d38 | 94 | dev_t dev; |
ae9a0a69 | 95 | struct uio *uio; |
e1d74936 | 96 | { |
defdbcd1 BJ |
97 | register struct tty *tp = &pt_tty[minor(dev)]; |
98 | register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; | |
840510a3 | 99 | int error = 0; |
defdbcd1 BJ |
100 | |
101 | again: | |
102 | if (pti->pt_flags & PF_REMOTE) { | |
103 | while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { | |
5bb90914 JB |
104 | if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || |
105 | (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || | |
defdbcd1 BJ |
106 | /* |
107 | (u.u_procp->p_flag&SDETACH) || | |
108 | */ | |
109 | u.u_procp->p_flag&SVFORK) | |
840510a3 | 110 | return (EIO); |
defdbcd1 BJ |
111 | gsignal(u.u_procp->p_pgrp, SIGTTIN); |
112 | sleep((caddr_t)&lbolt, TTIPRI); | |
941944c9 | 113 | } |
5bb90914 | 114 | if (tp->t_canq.c_cc == 0) { |
840510a3 BJ |
115 | if (tp->t_state & TS_NBIO) |
116 | return (EWOULDBLOCK); | |
5bb90914 | 117 | sleep((caddr_t)&tp->t_canq, TTIPRI); |
defdbcd1 BJ |
118 | goto again; |
119 | } | |
5bb90914 JB |
120 | while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) |
121 | if (ureadc(getc(&tp->t_canq), uio) < 0) { | |
840510a3 | 122 | error = EFAULT; |
ae9a0a69 BJ |
123 | break; |
124 | } | |
5bb90914 JB |
125 | if (tp->t_canq.c_cc == 1) |
126 | (void) getc(&tp->t_canq); | |
127 | if (tp->t_canq.c_cc) | |
840510a3 | 128 | return (error); |
defdbcd1 BJ |
129 | } else |
130 | if (tp->t_oproc) | |
840510a3 | 131 | error = (*linesw[tp->t_line].l_read)(tp, uio); |
5bb90914 | 132 | ptcwakeup(tp, FWRITE); |
840510a3 | 133 | return (error); |
45372428 MT |
134 | } |
135 | ||
941944c9 BJ |
136 | /* |
137 | * Write to pseudo-tty. | |
138 | * Wakeups of controlling tty will happen | |
139 | * indirectly, when tty driver calls ptsstart. | |
140 | */ | |
ae9a0a69 | 141 | ptswrite(dev, uio) |
73c77d38 | 142 | dev_t dev; |
ae9a0a69 | 143 | struct uio *uio; |
e1d74936 | 144 | { |
45372428 MT |
145 | register struct tty *tp; |
146 | ||
147 | tp = &pt_tty[minor(dev)]; | |
840510a3 BJ |
148 | if (tp->t_oproc == 0) |
149 | return (EIO); | |
150 | return ((*linesw[tp->t_line].l_write)(tp, uio)); | |
45372428 MT |
151 | } |
152 | ||
941944c9 BJ |
153 | /* |
154 | * Start output on pseudo-tty. | |
155 | * Wake up process selecting or sleeping for input from controlling tty. | |
156 | */ | |
45372428 | 157 | ptsstart(tp) |
e1d74936 BJ |
158 | struct tty *tp; |
159 | { | |
1e6d24b1 | 160 | register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; |
e1d74936 | 161 | |
941944c9 | 162 | if (tp->t_state & TS_TTSTOP) |
45372428 | 163 | return; |
1e6d24b1 BJ |
164 | if (pti->pt_flags & PF_STOPPED) { |
165 | pti->pt_flags &= ~PF_STOPPED; | |
166 | pti->pt_send = TIOCPKT_START; | |
167 | } | |
5bb90914 | 168 | ptcwakeup(tp, FREAD); |
d427b3b2 BJ |
169 | } |
170 | ||
5bb90914 | 171 | ptcwakeup(tp, flag) |
d427b3b2 BJ |
172 | struct tty *tp; |
173 | { | |
174 | struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; | |
175 | ||
5bb90914 JB |
176 | if (flag & FREAD) { |
177 | if (pti->pt_selr) { | |
178 | selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); | |
179 | pti->pt_selr = 0; | |
180 | pti->pt_flags &= ~PF_RCOLL; | |
181 | } | |
182 | wakeup((caddr_t)&tp->t_outq.c_cf); | |
183 | } | |
184 | if (flag & FWRITE) { | |
185 | if (pti->pt_selw) { | |
186 | selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); | |
187 | pti->pt_selw = 0; | |
188 | pti->pt_flags &= ~PF_WCOLL; | |
189 | } | |
190 | wakeup((caddr_t)&tp->t_rawq.c_cf); | |
e1d74936 | 191 | } |
45372428 MT |
192 | } |
193 | ||
194 | /*ARGSUSED*/ | |
195 | ptcopen(dev, flag) | |
e1d74936 BJ |
196 | dev_t dev; |
197 | int flag; | |
198 | { | |
45372428 | 199 | register struct tty *tp; |
1a954a11 | 200 | struct pt_ioctl *pti; |
45372428 | 201 | |
f21c8fb8 BJ |
202 | if (minor(dev) >= NPTY) |
203 | return (ENXIO); | |
45372428 | 204 | tp = &pt_tty[minor(dev)]; |
f21c8fb8 BJ |
205 | if (tp->t_oproc) |
206 | return (EIO); | |
e1d74936 | 207 | tp->t_oproc = ptsstart; |
941944c9 | 208 | if (tp->t_state & TS_WOPEN) |
45372428 | 209 | wakeup((caddr_t)&tp->t_rawq); |
941944c9 | 210 | tp->t_state |= TS_CARR_ON; |
1a954a11 BJ |
211 | pti = &pt_ioctl[minor(dev)]; |
212 | pti->pt_flags = 0; | |
213 | pti->pt_send = 0; | |
5bb90914 | 214 | pti->pt_ucntl = 0; |
f21c8fb8 | 215 | return (0); |
45372428 MT |
216 | } |
217 | ||
218 | ptcclose(dev) | |
e1d74936 BJ |
219 | dev_t dev; |
220 | { | |
45372428 MT |
221 | register struct tty *tp; |
222 | ||
223 | tp = &pt_tty[minor(dev)]; | |
941944c9 | 224 | if (tp->t_state & TS_ISOPEN) |
45372428 | 225 | gsignal(tp->t_pgrp, SIGHUP); |
941944c9 | 226 | tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ |
88a7a62a | 227 | ttyflush(tp, FREAD|FWRITE); |
e1d74936 | 228 | tp->t_oproc = 0; /* mark closed */ |
45372428 MT |
229 | } |
230 | ||
ae9a0a69 | 231 | ptcread(dev, uio) |
1a954a11 | 232 | dev_t dev; |
ae9a0a69 | 233 | struct uio *uio; |
e1d74936 | 234 | { |
840510a3 | 235 | register struct tty *tp = &pt_tty[minor(dev)]; |
5bb90914 | 236 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
2bb0bef9 SL |
237 | char buf[BUFSIZ]; |
238 | int error = 0, cc; | |
45372428 | 239 | |
5bb90914 JB |
240 | /* |
241 | * We want to block until the slave | |
242 | * is open, and there's something to read; | |
243 | * but if we lost the slave or we're NBIO, | |
244 | * then return the appropriate error instead. | |
245 | */ | |
246 | for (;;) { | |
247 | if (tp->t_state&TS_ISOPEN) { | |
248 | if (pti->pt_flags&PF_PKT && pti->pt_send) { | |
249 | error = ureadc(pti->pt_send, uio); | |
250 | if (error) | |
251 | return (error); | |
252 | pti->pt_send = 0; | |
253 | return (0); | |
254 | } | |
255 | if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { | |
256 | error = ureadc(pti->pt_ucntl, uio); | |
257 | if (error) | |
258 | return (error); | |
259 | pti->pt_ucntl = 0; | |
260 | return (0); | |
261 | } | |
262 | if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) | |
263 | break; | |
1a954a11 | 264 | } |
2bb0bef9 SL |
265 | if ((tp->t_state&TS_CARR_ON) == 0) |
266 | return (EIO); | |
840510a3 BJ |
267 | if (pti->pt_flags&PF_NBIO) |
268 | return (EWOULDBLOCK); | |
45372428 | 269 | sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); |
8b8271ac | 270 | } |
5bb90914 JB |
271 | if (pti->pt_flags & (PF_PKT|PF_UCNTL)) |
272 | error = ureadc(0, uio); | |
2bb0bef9 SL |
273 | while (uio->uio_resid > 0 && error == 0) { |
274 | cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); | |
275 | if (cc <= 0) | |
ae9a0a69 | 276 | break; |
2bb0bef9 SL |
277 | error = uiomove(buf, cc, UIO_READ, uio); |
278 | } | |
941944c9 BJ |
279 | if (tp->t_outq.c_cc <= TTLOWAT(tp)) { |
280 | if (tp->t_state&TS_ASLEEP) { | |
281 | tp->t_state &= ~TS_ASLEEP; | |
282 | wakeup((caddr_t)&tp->t_outq); | |
283 | } | |
284 | if (tp->t_wsel) { | |
285 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
286 | tp->t_wsel = 0; | |
287 | tp->t_state &= ~TS_WCOLL; | |
288 | } | |
45372428 | 289 | } |
840510a3 | 290 | return (error); |
45372428 MT |
291 | } |
292 | ||
1a954a11 BJ |
293 | ptsstop(tp, flush) |
294 | register struct tty *tp; | |
295 | int flush; | |
296 | { | |
297 | struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; | |
5bb90914 | 298 | int flag; |
1a954a11 | 299 | |
1e6d24b1 BJ |
300 | /* note: FLUSHREAD and FLUSHWRITE already ok */ |
301 | if (flush == 0) { | |
302 | flush = TIOCPKT_STOP; | |
303 | pti->pt_flags |= PF_STOPPED; | |
5bb90914 | 304 | } else |
1e6d24b1 | 305 | pti->pt_flags &= ~PF_STOPPED; |
0a2bd708 | 306 | pti->pt_send |= flush; |
5bb90914 JB |
307 | /* change of perspective */ |
308 | flag = 0; | |
309 | if (flush & FREAD) | |
310 | flag |= FWRITE; | |
311 | if (flush & FWRITE) | |
312 | flag |= FREAD; | |
313 | ptcwakeup(tp, flush); | |
1a954a11 BJ |
314 | } |
315 | ||
941944c9 | 316 | ptcselect(dev, rw) |
e1d74936 | 317 | dev_t dev; |
941944c9 | 318 | int rw; |
e1d74936 BJ |
319 | { |
320 | register struct tty *tp = &pt_tty[minor(dev)]; | |
defdbcd1 | 321 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
e1d74936 | 322 | struct proc *p; |
d427b3b2 | 323 | int s; |
e1d74936 | 324 | |
5bb90914 | 325 | if ((tp->t_state&TS_CARR_ON) == 0) |
e1d74936 | 326 | return (1); |
d427b3b2 | 327 | s = spl5(); |
941944c9 BJ |
328 | switch (rw) { |
329 | ||
330 | case FREAD: | |
5bb90914 JB |
331 | if ((tp->t_state&TS_ISOPEN) && |
332 | (pti->pt_flags&PF_PKT && pti->pt_send || | |
333 | pti->pt_flags&PF_UCNTL && pti->pt_ucntl || | |
334 | tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)) { | |
d427b3b2 | 335 | splx(s); |
941944c9 | 336 | return (1); |
d427b3b2 | 337 | } |
1a954a11 BJ |
338 | if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) |
339 | pti->pt_flags |= PF_RCOLL; | |
941944c9 | 340 | else |
1a954a11 | 341 | pti->pt_selr = u.u_procp; |
d427b3b2 | 342 | break; |
941944c9 BJ |
343 | |
344 | case FWRITE: | |
5bb90914 | 345 | if ((tp->t_state&TS_ISOPEN) && |
d19cae27 | 346 | ((pti->pt_flags&PF_REMOTE) == 0 || tp->t_canq.c_cc == 0)) { |
d427b3b2 | 347 | splx(s); |
941944c9 | 348 | return (1); |
d427b3b2 | 349 | } |
1a954a11 BJ |
350 | if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) |
351 | pti->pt_flags |= PF_WCOLL; | |
941944c9 | 352 | else |
1a954a11 | 353 | pti->pt_selw = u.u_procp; |
d427b3b2 | 354 | break; |
941944c9 | 355 | } |
d427b3b2 BJ |
356 | splx(s); |
357 | return (0); | |
e1d74936 BJ |
358 | } |
359 | ||
ae9a0a69 | 360 | ptcwrite(dev, uio) |
941944c9 | 361 | dev_t dev; |
5bb90914 | 362 | register struct uio *uio; |
e1d74936 | 363 | { |
840510a3 | 364 | register struct tty *tp = &pt_tty[minor(dev)]; |
5bb90914 JB |
365 | register struct iovec *iov; |
366 | register char *cp; | |
367 | register int cc = 0; | |
45372428 | 368 | char locbuf[BUFSIZ]; |
941944c9 | 369 | int cnt = 0; |
defdbcd1 | 370 | struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; |
840510a3 | 371 | int error = 0; |
45372428 | 372 | |
defdbcd1 | 373 | again: |
5bb90914 JB |
374 | if ((tp->t_state&TS_ISOPEN) == 0) |
375 | goto block; | |
376 | if (cnt == 0 && pti->pt_flags & PF_REMOTE) { | |
377 | if (uio->uio_iovcnt <= 0) | |
840510a3 | 378 | return (0); |
5bb90914 JB |
379 | if (tp->t_canq.c_cc) |
380 | goto block; | |
381 | iov = uio->uio_iov; | |
382 | if (cc == 0 && iov->iov_len) { | |
383 | cc = MIN(iov->iov_len, BUFSIZ); | |
384 | cp = locbuf; | |
385 | error = uiomove(cp, cc, UIO_WRITE, uio); | |
386 | if (error) | |
387 | return (error); | |
388 | /* check again for safety */ | |
389 | if ((tp->t_state&TS_ISOPEN) == 0) | |
390 | return (EIO); | |
391 | if (tp->t_canq.c_cc) | |
392 | goto block; | |
defdbcd1 | 393 | } |
5bb90914 JB |
394 | if (cc) |
395 | (void) b_to_q(cp, cc, &tp->t_canq); | |
396 | (void) putc(0, &tp->t_canq); | |
397 | ttwakeup(tp); | |
398 | wakeup((caddr_t)&tp->t_canq); | |
399 | return (0); | |
400 | } | |
401 | while (uio->uio_iovcnt > 0) { | |
402 | iov = uio->uio_iov; | |
403 | if (cc == 0) { | |
404 | if (iov->iov_len == 0) { | |
405 | uio->uio_iovcnt--; | |
406 | uio->uio_iov++; | |
407 | continue; | |
45372428 | 408 | } |
5bb90914 JB |
409 | cc = MIN(iov->iov_len, BUFSIZ); |
410 | cp = locbuf; | |
411 | error = uiomove(cp, cc, UIO_WRITE, uio); | |
412 | if (error) | |
413 | return (error); | |
414 | /* check again for safety */ | |
415 | if ((tp->t_state&TS_ISOPEN) == 0) | |
416 | return (EIO); | |
417 | } | |
418 | while (--cc >= 0) { | |
36612a8f | 419 | (*linesw[tp->t_line].l_rint)(*cp++, tp); |
941944c9 | 420 | cnt++; |
45372428 | 421 | } |
5bb90914 JB |
422 | cc = 0; |
423 | } | |
424 | return (0); | |
425 | block: | |
426 | /* | |
427 | * Come here to wait for slave to open or for space | |
428 | * in outq. | |
429 | */ | |
430 | if ((tp->t_state&TS_CARR_ON) == 0) | |
431 | return (EIO); | |
432 | if (pti->pt_flags & PF_NBIO) { | |
433 | if (cnt == 0) | |
434 | return (EWOULDBLOCK); | |
435 | iov->iov_base -= cc; | |
436 | iov->iov_len += cc; | |
437 | uio->uio_resid += cc; | |
438 | uio->uio_offset -= cc; | |
439 | return (0); | |
440 | } | |
441 | sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); | |
442 | goto again; | |
45372428 MT |
443 | } |
444 | ||
45372428 | 445 | /*ARGSUSED*/ |
4b72e2f9 SL |
446 | ptyioctl(dev, cmd, data, flag) |
447 | caddr_t data; | |
e1d74936 BJ |
448 | dev_t dev; |
449 | { | |
0a2bd708 BJ |
450 | register struct tty *tp = &pt_tty[minor(dev)]; |
451 | register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; | |
5bb90914 | 452 | int stop, error; |
45372428 | 453 | |
e1d74936 | 454 | /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ |
4b72e2f9 SL |
455 | if (cdevsw[major(dev)].d_open == ptcopen) |
456 | switch (cmd) { | |
457 | ||
458 | case TIOCPKT: | |
5bb90914 JB |
459 | if (*(int *)data) { |
460 | if (pti->pt_flags & PF_UCNTL) | |
461 | return (EINVAL); | |
1a954a11 | 462 | pti->pt_flags |= PF_PKT; |
5bb90914 | 463 | } else |
1a954a11 | 464 | pti->pt_flags &= ~PF_PKT; |
f21c8fb8 | 465 | return (0); |
4b72e2f9 | 466 | |
5bb90914 JB |
467 | case TIOCUCNTL: |
468 | if (*(int *)data) { | |
469 | if (pti->pt_flags & PF_PKT) | |
470 | return (EINVAL); | |
471 | pti->pt_flags |= PF_UCNTL; | |
472 | } else | |
473 | pti->pt_flags &= ~PF_UCNTL; | |
474 | return (0); | |
475 | ||
4b72e2f9 SL |
476 | case TIOCREMOTE: |
477 | if (*(int *)data) | |
defdbcd1 BJ |
478 | pti->pt_flags |= PF_REMOTE; |
479 | else | |
480 | pti->pt_flags &= ~PF_REMOTE; | |
88a7a62a | 481 | ttyflush(tp, FREAD|FWRITE); |
f21c8fb8 | 482 | return (0); |
4b72e2f9 SL |
483 | |
484 | case FIONBIO: | |
485 | if (*(int *)data) | |
1a954a11 | 486 | pti->pt_flags |= PF_NBIO; |
8b8271ac | 487 | else |
1a954a11 | 488 | pti->pt_flags &= ~PF_NBIO; |
f21c8fb8 | 489 | return (0); |
4b72e2f9 SL |
490 | |
491 | case TIOCSETP: | |
492 | while (getc(&tp->t_outq) >= 0) | |
493 | ; | |
494 | break; | |
8b8271ac | 495 | } |
477d62ec | 496 | error = ttioctl(tp, cmd, data, flag); |
5bb90914 JB |
497 | if (error < 0) { |
498 | if (pti->pt_flags & PF_UCNTL && | |
499 | (cmd & ~0xff) == _IO(u,0)) { | |
500 | if (cmd & 0xff) { | |
501 | pti->pt_ucntl = (u_char)cmd; | |
502 | ptcwakeup(tp, FREAD); | |
503 | } | |
504 | return (0); | |
505 | } | |
f21c8fb8 | 506 | error = ENOTTY; |
5bb90914 JB |
507 | } |
508 | stop = (tp->t_flags & RAW) == 0 && | |
509 | tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); | |
0a2bd708 BJ |
510 | if (pti->pt_flags & PF_NOSTOP) { |
511 | if (stop) { | |
512 | pti->pt_send &= TIOCPKT_NOSTOP; | |
513 | pti->pt_send |= TIOCPKT_DOSTOP; | |
514 | pti->pt_flags &= ~PF_NOSTOP; | |
5bb90914 | 515 | ptcwakeup(tp, FREAD); |
0a2bd708 BJ |
516 | } |
517 | } else { | |
5bb90914 | 518 | if (!stop) { |
0a2bd708 BJ |
519 | pti->pt_send &= ~TIOCPKT_DOSTOP; |
520 | pti->pt_send |= TIOCPKT_NOSTOP; | |
521 | pti->pt_flags |= PF_NOSTOP; | |
5bb90914 | 522 | ptcwakeup(tp, FREAD); |
0a2bd708 BJ |
523 | } |
524 | } | |
f21c8fb8 | 525 | return (error); |
45372428 | 526 | } |
4f07e6e5 | 527 | #endif |