SLIP needs nullmodem (and then lint is happy, too)
[unix-history] / usr / src / sys / kern / tty_pty.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6a5ca8a0 6 * @(#)tty_pty.c 7.3.1.1 (Berkeley) %G%
da7c5cc6 7 */
be4367b3 8
45372428
MT
9/*
10 * Pseudo-teletype Driver
11 * (Actually two drivers, requiring two entries in 'cdevsw')
45372428 12 */
647d645f
MT
13#include "pty.h"
14
f12183e4 15#if NPTY > 0
94368568
JB
16#include "param.h"
17#include "systm.h"
18#include "ioctl.h"
19#include "tty.h"
20#include "dir.h"
21#include "user.h"
22#include "conf.h"
23#include "file.h"
24#include "proc.h"
25#include "uio.h"
26#include "kernel.h"
6a5ca8a0 27#include "tsleep.h"
941944c9 28
b3c8737d 29#if NPTY == 1
5bb90914 30#undef NPTY
c91c01fe 31#define NPTY 32 /* crude XXX */
b3c8737d 32#endif
45372428 33
2bb0bef9 34#define BUFSIZ 100 /* Chunk size iomoved to/from user */
e1d74936 35
45372428 36/*
5bb90914
JB
37 * pts == /dev/tty[pqrs]?
38 * ptc == /dev/pty[pqrs]?
45372428 39 */
e1d74936
BJ
40struct tty pt_tty[NPTY];
41struct pt_ioctl {
1a954a11 42 int pt_flags;
1a954a11 43 struct proc *pt_selr, *pt_selw;
5bb90914
JB
44 u_char pt_send;
45 u_char pt_ucntl;
6a5ca8a0 46 struct clist pt_ioc;
e1d74936 47} pt_ioctl[NPTY];
5bb90914 48int npty = NPTY; /* for pstat -t */
45372428 49
6a5ca8a0
KM
50#define PF_RCOLL 0x0001
51#define PF_WCOLL 0x0002
52#define PF_NBIO 0x0004
53#define PF_PKT 0x0008 /* packet mode */
54#define PF_STOPPED 0x0010 /* user told stopped */
55#define PF_REMOTE 0x0020 /* remote and flow controlled input */
56#define PF_NOSTOP 0x0040
57#define PF_UCNTL 0x0080 /* user control mode */
58#define PF_TIOC 0x0100 /* transparent control mode */
59#define PF_LIOC 0x0200 /* transparent control locked */
60#define PF_WIOC 0x0400 /* waiting for PF_LIOC to clear */
61#define PF_BLOCK 0x0800 /* block writes to slave */
62#define PF_OWAIT 0x1000 /* waiting for PF_BLOCK to clear */
45372428
MT
63
64/*ARGSUSED*/
65ptsopen(dev, flag)
73c77d38 66 dev_t dev;
e1d74936 67{
45372428 68 register struct tty *tp;
5bb90914 69 int error;
45372428 70
5bb90914
JB
71#ifdef lint
72 npty = npty;
73#endif
f21c8fb8
BJ
74 if (minor(dev) >= NPTY)
75 return (ENXIO);
45372428 76 tp = &pt_tty[minor(dev)];
941944c9 77 if ((tp->t_state & TS_ISOPEN) == 0) {
bdda6b91 78 ttychars(tp); /* Set up default chars */
d2f24af0 79 tp->t_ispeed = tp->t_ospeed = EXTB;
bdda6b91 80 tp->t_flags = 0; /* No features (nor raw mode) */
f21c8fb8
BJ
81 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
82 return (EBUSY);
e1d74936 83 if (tp->t_oproc) /* Ctrlr still around. */
941944c9
BJ
84 tp->t_state |= TS_CARR_ON;
85 while ((tp->t_state & TS_CARR_ON) == 0) {
86 tp->t_state |= TS_WOPEN;
45372428
MT
87 sleep((caddr_t)&tp->t_rawq, TTIPRI);
88 }
5bb90914
JB
89 error = (*linesw[tp->t_line].l_open)(dev, tp);
90 ptcwakeup(tp, FREAD|FWRITE);
91 return (error);
45372428
MT
92}
93
94ptsclose(dev)
73c77d38 95 dev_t dev;
941944c9 96{
45372428
MT
97 register struct tty *tp;
98
99 tp = &pt_tty[minor(dev)];
100 (*linesw[tp->t_line].l_close)(tp);
4b39cb77 101 ttyclose(tp);
5bb90914 102 ptcwakeup(tp, FREAD|FWRITE);
6a5ca8a0 103 return (0);
45372428
MT
104}
105
ae9a0a69 106ptsread(dev, uio)
73c77d38 107 dev_t dev;
ae9a0a69 108 struct uio *uio;
e1d74936 109{
defdbcd1
BJ
110 register struct tty *tp = &pt_tty[minor(dev)];
111 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 112 int error = 0;
defdbcd1
BJ
113
114again:
115 if (pti->pt_flags & PF_REMOTE) {
116 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
5bb90914
JB
117 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
118 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
defdbcd1 119 u.u_procp->p_flag&SVFORK)
840510a3 120 return (EIO);
defdbcd1
BJ
121 gsignal(u.u_procp->p_pgrp, SIGTTIN);
122 sleep((caddr_t)&lbolt, TTIPRI);
941944c9 123 }
5bb90914 124 if (tp->t_canq.c_cc == 0) {
840510a3
BJ
125 if (tp->t_state & TS_NBIO)
126 return (EWOULDBLOCK);
5bb90914 127 sleep((caddr_t)&tp->t_canq, TTIPRI);
defdbcd1
BJ
128 goto again;
129 }
5bb90914
JB
130 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
131 if (ureadc(getc(&tp->t_canq), uio) < 0) {
840510a3 132 error = EFAULT;
ae9a0a69
BJ
133 break;
134 }
5bb90914
JB
135 if (tp->t_canq.c_cc == 1)
136 (void) getc(&tp->t_canq);
137 if (tp->t_canq.c_cc)
840510a3 138 return (error);
defdbcd1
BJ
139 } else
140 if (tp->t_oproc)
840510a3 141 error = (*linesw[tp->t_line].l_read)(tp, uio);
5bb90914 142 ptcwakeup(tp, FWRITE);
840510a3 143 return (error);
45372428
MT
144}
145
941944c9
BJ
146/*
147 * Write to pseudo-tty.
148 * Wakeups of controlling tty will happen
149 * indirectly, when tty driver calls ptsstart.
150 */
ae9a0a69 151ptswrite(dev, uio)
73c77d38 152 dev_t dev;
ae9a0a69 153 struct uio *uio;
e1d74936 154{
6a5ca8a0
KM
155 register struct tty *tp = &pt_tty[minor(dev)];
156 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
45372428 157
840510a3
BJ
158 if (tp->t_oproc == 0)
159 return (EIO);
6a5ca8a0
KM
160
161 while (pti->pt_flags & PF_BLOCK) {
162 pti->pt_flags |= PF_OWAIT;
163 sleep((caddr_t)pti + 1, TTOPRI);
164 }
165
840510a3 166 return ((*linesw[tp->t_line].l_write)(tp, uio));
45372428
MT
167}
168
941944c9
BJ
169/*
170 * Start output on pseudo-tty.
171 * Wake up process selecting or sleeping for input from controlling tty.
172 */
45372428 173ptsstart(tp)
e1d74936
BJ
174 struct tty *tp;
175{
1e6d24b1 176 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
e1d74936 177
941944c9 178 if (tp->t_state & TS_TTSTOP)
45372428 179 return;
1e6d24b1
BJ
180 if (pti->pt_flags & PF_STOPPED) {
181 pti->pt_flags &= ~PF_STOPPED;
182 pti->pt_send = TIOCPKT_START;
183 }
5bb90914 184 ptcwakeup(tp, FREAD);
d427b3b2
BJ
185}
186
5bb90914 187ptcwakeup(tp, flag)
d427b3b2
BJ
188 struct tty *tp;
189{
190 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
191
5bb90914
JB
192 if (flag & FREAD) {
193 if (pti->pt_selr) {
194 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
195 pti->pt_selr = 0;
196 pti->pt_flags &= ~PF_RCOLL;
197 }
198 wakeup((caddr_t)&tp->t_outq.c_cf);
199 }
200 if (flag & FWRITE) {
201 if (pti->pt_selw) {
202 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
203 pti->pt_selw = 0;
204 pti->pt_flags &= ~PF_WCOLL;
205 }
206 wakeup((caddr_t)&tp->t_rawq.c_cf);
e1d74936 207 }
45372428
MT
208}
209
210/*ARGSUSED*/
211ptcopen(dev, flag)
e1d74936
BJ
212 dev_t dev;
213 int flag;
214{
45372428 215 register struct tty *tp;
1a954a11 216 struct pt_ioctl *pti;
45372428 217
f21c8fb8
BJ
218 if (minor(dev) >= NPTY)
219 return (ENXIO);
45372428 220 tp = &pt_tty[minor(dev)];
f21c8fb8
BJ
221 if (tp->t_oproc)
222 return (EIO);
e1d74936 223 tp->t_oproc = ptsstart;
f2f3b49b 224 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1a954a11
BJ
225 pti = &pt_ioctl[minor(dev)];
226 pti->pt_flags = 0;
227 pti->pt_send = 0;
5bb90914 228 pti->pt_ucntl = 0;
f21c8fb8 229 return (0);
45372428
MT
230}
231
232ptcclose(dev)
e1d74936
BJ
233 dev_t dev;
234{
45372428
MT
235 register struct tty *tp;
236
237 tp = &pt_tty[minor(dev)];
f2f3b49b 238 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
d3be7d55 239 tp->t_state &= ~TS_CARR_ON;
e1d74936 240 tp->t_oproc = 0; /* mark closed */
6a5ca8a0 241 return (0);
45372428
MT
242}
243
ae9a0a69 244ptcread(dev, uio)
1a954a11 245 dev_t dev;
ae9a0a69 246 struct uio *uio;
e1d74936 247{
840510a3 248 register struct tty *tp = &pt_tty[minor(dev)];
5bb90914 249 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
2bb0bef9
SL
250 char buf[BUFSIZ];
251 int error = 0, cc;
45372428 252
5bb90914
JB
253 /*
254 * We want to block until the slave
255 * is open, and there's something to read;
256 * but if we lost the slave or we're NBIO,
257 * then return the appropriate error instead.
258 */
259 for (;;) {
260 if (tp->t_state&TS_ISOPEN) {
261 if (pti->pt_flags&PF_PKT && pti->pt_send) {
8011f5df 262 error = ureadc((int)pti->pt_send, uio);
5bb90914
JB
263 if (error)
264 return (error);
265 pti->pt_send = 0;
266 return (0);
267 }
268 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
8011f5df 269 error = ureadc((int)pti->pt_ucntl, uio);
5bb90914
JB
270 if (error)
271 return (error);
272 pti->pt_ucntl = 0;
273 return (0);
274 }
6a5ca8a0
KM
275 if (pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc) {
276 if (uio->uio_resid < pti->pt_ioc.c_cc + 1)
277 return (E2BIG);
278 error = ureadc(TIOCPKT_TIOC, uio);
279 while (error == 0 && pti->pt_ioc.c_cc > 0) {
280 cc = q_to_b(&pti->pt_ioc, buf,
281 MIN(pti->pt_ioc.c_cc, BUFSIZ));
282 if (cc <= 0) /* impossible? */
283 break;
284 error = uiomove(buf, cc, UIO_READ, uio);
285 }
286 return (error);
287 }
5bb90914
JB
288 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
289 break;
1a954a11 290 }
2bb0bef9
SL
291 if ((tp->t_state&TS_CARR_ON) == 0)
292 return (EIO);
840510a3
BJ
293 if (pti->pt_flags&PF_NBIO)
294 return (EWOULDBLOCK);
45372428 295 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
8b8271ac 296 }
6a5ca8a0 297 if (pti->pt_flags & (PF_PKT|PF_UCNTL|PF_TIOC))
5bb90914 298 error = ureadc(0, uio);
2bb0bef9
SL
299 while (uio->uio_resid > 0 && error == 0) {
300 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
301 if (cc <= 0)
ae9a0a69 302 break;
2bb0bef9
SL
303 error = uiomove(buf, cc, UIO_READ, uio);
304 }
6a5ca8a0
KM
305 if (tp->t_outq.c_cc <= TTLOWAT(tp) && !(pti->pt_flags & PF_BLOCK))
306 ptswake(tp);
840510a3 307 return (error);
45372428
MT
308}
309
6a5ca8a0
KM
310ptswake(tp)
311 register struct tty *tp;
312{
313 if (tp->t_state&TS_ASLEEP) {
314 tp->t_state &= ~TS_ASLEEP;
315 wakeup((caddr_t)&tp->t_outq);
316 }
317 if (tp->t_wsel) {
318 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
319 tp->t_wsel = 0;
320 tp->t_state &= ~TS_WCOLL;
321 }
322}
323
1a954a11
BJ
324ptsstop(tp, flush)
325 register struct tty *tp;
326 int flush;
327{
328 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
5bb90914 329 int flag;
1a954a11 330
1e6d24b1
BJ
331 /* note: FLUSHREAD and FLUSHWRITE already ok */
332 if (flush == 0) {
333 flush = TIOCPKT_STOP;
334 pti->pt_flags |= PF_STOPPED;
5bb90914 335 } else
1e6d24b1 336 pti->pt_flags &= ~PF_STOPPED;
0a2bd708 337 pti->pt_send |= flush;
5bb90914
JB
338 /* change of perspective */
339 flag = 0;
340 if (flush & FREAD)
341 flag |= FWRITE;
342 if (flush & FWRITE)
343 flag |= FREAD;
9d2a90b1 344 ptcwakeup(tp, flag);
1a954a11
BJ
345}
346
941944c9 347ptcselect(dev, rw)
e1d74936 348 dev_t dev;
941944c9 349 int rw;
e1d74936
BJ
350{
351 register struct tty *tp = &pt_tty[minor(dev)];
defdbcd1 352 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
e1d74936 353 struct proc *p;
d427b3b2 354 int s;
e1d74936 355
5bb90914 356 if ((tp->t_state&TS_CARR_ON) == 0)
e1d74936 357 return (1);
941944c9
BJ
358 switch (rw) {
359
360 case FREAD:
892f2f35
MK
361 /*
362 * Need to block timeouts (ttrstart).
363 */
364 s = spltty();
7cbd29e4
MK
365 if ((tp->t_state&TS_ISOPEN) &&
366 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
367 splx(s);
368 return (1);
369 }
892f2f35 370 splx(s);
7cbd29e4
MK
371 /* FALLTHROUGH */
372
373 case 0: /* exceptional */
5bb90914
JB
374 if ((tp->t_state&TS_ISOPEN) &&
375 (pti->pt_flags&PF_PKT && pti->pt_send ||
6a5ca8a0 376 pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc ||
892f2f35 377 pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
941944c9 378 return (1);
1a954a11
BJ
379 if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait)
380 pti->pt_flags |= PF_RCOLL;
941944c9 381 else
1a954a11 382 pti->pt_selr = u.u_procp;
d427b3b2 383 break;
941944c9 384
7cbd29e4 385
941944c9 386 case FWRITE:
892f2f35
MK
387 if (tp->t_state&TS_ISOPEN) {
388 if (pti->pt_flags & PF_REMOTE) {
389 if (tp->t_canq.c_cc == 0)
390 return (1);
391 } else {
392 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
393 return (1);
394 if (tp->t_canq.c_cc == 0 &&
aec7dd3b 395 (tp->t_flags & (RAW|CBREAK)) == 0)
892f2f35
MK
396 return (1);
397 }
d427b3b2 398 }
1a954a11
BJ
399 if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait)
400 pti->pt_flags |= PF_WCOLL;
941944c9 401 else
1a954a11 402 pti->pt_selw = u.u_procp;
d427b3b2 403 break;
7cbd29e4 404
941944c9 405 }
d427b3b2 406 return (0);
e1d74936
BJ
407}
408
ae9a0a69 409ptcwrite(dev, uio)
941944c9 410 dev_t dev;
5bb90914 411 register struct uio *uio;
e1d74936 412{
840510a3 413 register struct tty *tp = &pt_tty[minor(dev)];
5bb90914
JB
414 register struct iovec *iov;
415 register char *cp;
416 register int cc = 0;
45372428 417 char locbuf[BUFSIZ];
941944c9 418 int cnt = 0;
defdbcd1 419 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 420 int error = 0;
45372428 421
defdbcd1 422again:
5bb90914
JB
423 if ((tp->t_state&TS_ISOPEN) == 0)
424 goto block;
9d2a90b1 425 if (pti->pt_flags & PF_REMOTE) {
5bb90914
JB
426 if (tp->t_canq.c_cc)
427 goto block;
9d2a90b1
JB
428 while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
429 iov = uio->uio_iov;
430 if (iov->iov_len == 0) {
431 uio->uio_iovcnt--;
432 uio->uio_iov++;
433 continue;
434 }
435 if (cc == 0) {
436 cc = MIN(iov->iov_len, BUFSIZ);
437 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc);
438 cp = locbuf;
439 error = uiomove(cp, cc, UIO_WRITE, uio);
440 if (error)
441 return (error);
442 /* check again for safety */
443 if ((tp->t_state&TS_ISOPEN) == 0)
444 return (EIO);
445 }
446 if (cc)
447 (void) b_to_q(cp, cc, &tp->t_canq);
448 cc = 0;
defdbcd1 449 }
5bb90914
JB
450 (void) putc(0, &tp->t_canq);
451 ttwakeup(tp);
452 wakeup((caddr_t)&tp->t_canq);
453 return (0);
454 }
455 while (uio->uio_iovcnt > 0) {
456 iov = uio->uio_iov;
457 if (cc == 0) {
458 if (iov->iov_len == 0) {
459 uio->uio_iovcnt--;
460 uio->uio_iov++;
461 continue;
45372428 462 }
5bb90914
JB
463 cc = MIN(iov->iov_len, BUFSIZ);
464 cp = locbuf;
465 error = uiomove(cp, cc, UIO_WRITE, uio);
466 if (error)
467 return (error);
468 /* check again for safety */
469 if ((tp->t_state&TS_ISOPEN) == 0)
470 return (EIO);
471 }
9d2a90b1
JB
472 while (cc > 0) {
473 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
892f2f35
MK
474 (tp->t_canq.c_cc > 0 ||
475 tp->t_flags & (RAW|CBREAK))) {
9d2a90b1
JB
476 wakeup((caddr_t)&tp->t_rawq);
477 goto block;
478 }
36612a8f 479 (*linesw[tp->t_line].l_rint)(*cp++, tp);
941944c9 480 cnt++;
9d2a90b1 481 cc--;
45372428 482 }
5bb90914
JB
483 cc = 0;
484 }
485 return (0);
486block:
487 /*
9d2a90b1
JB
488 * Come here to wait for slave to open, for space
489 * in outq, or space in rawq.
5bb90914
JB
490 */
491 if ((tp->t_state&TS_CARR_ON) == 0)
492 return (EIO);
493 if (pti->pt_flags & PF_NBIO) {
5bb90914
JB
494 iov->iov_base -= cc;
495 iov->iov_len += cc;
496 uio->uio_resid += cc;
497 uio->uio_offset -= cc;
9d2a90b1
JB
498 if (cnt == 0)
499 return (EWOULDBLOCK);
5bb90914
JB
500 return (0);
501 }
502 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
503 goto again;
45372428
MT
504}
505
45372428 506/*ARGSUSED*/
4b72e2f9
SL
507ptyioctl(dev, cmd, data, flag)
508 caddr_t data;
e1d74936
BJ
509 dev_t dev;
510{
0a2bd708
BJ
511 register struct tty *tp = &pt_tty[minor(dev)];
512 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
5bb90914 513 int stop, error;
f2f3b49b 514 extern ttyinput();
45372428 515
f2f3b49b
MK
516 /*
517 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
518 * ttywflush(tp) will hang if there are characters in the outq.
519 */
6a5ca8a0
KM
520 if (cdevsw[major(dev)].d_open == ptcopen) {
521 if ((cmd & 0xffff) == (TIOCIOANS(0) & 0xffff)) {
522 if (!(pti->pt_flags & PF_LIOC) || pti->pt_ioc.c_cc)
523 return (EINVAL);
524 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
525 wakeup((caddr_t)&pti->pt_ioc);
526 return (0);
527 }
4b72e2f9
SL
528 switch (cmd) {
529
530 case TIOCPKT:
5bb90914
JB
531 if (*(int *)data) {
532 if (pti->pt_flags & PF_UCNTL)
533 return (EINVAL);
1a954a11 534 pti->pt_flags |= PF_PKT;
5bb90914 535 } else
1a954a11 536 pti->pt_flags &= ~PF_PKT;
f21c8fb8 537 return (0);
4b72e2f9 538
5bb90914
JB
539 case TIOCUCNTL:
540 if (*(int *)data) {
541 if (pti->pt_flags & PF_PKT)
542 return (EINVAL);
543 pti->pt_flags |= PF_UCNTL;
544 } else
545 pti->pt_flags &= ~PF_UCNTL;
546 return (0);
547
6a5ca8a0
KM
548 case TIOCTIOC:
549 if (*(int *)data) {
550 if (pti->pt_flags & PF_UCNTL)
551 return (EINVAL);
552 pti->pt_flags |= PF_TIOC;
553 } else {
554 pti->pt_flags &= ~(PF_TIOC|PF_LIOC|PF_WIOC);
555 while (pti->pt_ioc.c_cc)
556 (void) getc(&pti->pt_ioc);
557 wakeup((caddr_t)&pti->pt_ioc);
558 }
559 return (0);
560
561 case TIOCBLK:
562 if (*(int *)data)
563 pti->pt_flags |= PF_BLOCK;
564 else {
565 if (pti->pt_flags & PF_OWAIT)
566 wakeup((caddr_t)pti + 1);
567 pti->pt_flags &= ~(PF_BLOCK|PF_OWAIT);
568 ptswake(tp);
569 }
570 return (0);
571
4b72e2f9
SL
572 case TIOCREMOTE:
573 if (*(int *)data)
defdbcd1
BJ
574 pti->pt_flags |= PF_REMOTE;
575 else
576 pti->pt_flags &= ~PF_REMOTE;
88a7a62a 577 ttyflush(tp, FREAD|FWRITE);
f21c8fb8 578 return (0);
4b72e2f9
SL
579
580 case FIONBIO:
581 if (*(int *)data)
1a954a11 582 pti->pt_flags |= PF_NBIO;
8b8271ac 583 else
1a954a11 584 pti->pt_flags &= ~PF_NBIO;
f21c8fb8 585 return (0);
4b72e2f9 586
6a5ca8a0
KM
587 case FIONREAD:
588 *(int *)data = tp->t_outq.c_cc;
589 return (0);
590
4b72e2f9 591 case TIOCSETP:
f2f3b49b
MK
592 case TIOCSETN:
593 case TIOCSETD:
4b72e2f9
SL
594 while (getc(&tp->t_outq) >= 0)
595 ;
596 break;
8b8271ac 597 }
6a5ca8a0
KM
598 } else if (pti->pt_flags & PF_TIOC) {
599 while (pti->pt_flags & PF_LIOC) {
600 pti->pt_flags |= PF_WIOC;
601 switch (tsleep((caddr_t)&pti->pt_flags,TTIPRI-1,5*hz)) {
602 case TS_OK:
603 continue;
604 case TS_SIG:
605 case TS_TIME:
606 return (EBUSY);
607 }
608 }
609 pti->pt_flags |= PF_LIOC | PF_BLOCK;
610 while (pti->pt_ioc.c_cc)
611 (void) getc(&pti->pt_ioc);
612 (void) b_to_q(&cmd, sizeof cmd, &pti->pt_ioc);
613 if (cmd & IOC_IN)
614 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
615 ptcwakeup(tp, FREAD);
616 switch (tsleep((caddr_t)&pti->pt_ioc, TTIPRI-1, 5*hz)) {
617 case TS_SIG:
618 case TS_TIME:
619 while (pti->pt_ioc.c_cc)
620 (void) getc(&pti->pt_ioc);
621 if (pti->pt_flags & PF_WIOC)
622 wakeup((caddr_t)&pti->pt_flags);
623 if (pti->pt_flags & PF_OWAIT)
624 wakeup((caddr_t)pti + 1);
625 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
626 ptswake(tp);
627 return (EBUSY);
628 case TS_OK:
629 break;
630 }
631 if (pti->pt_ioc.c_cc == 0) {
632 if (pti->pt_flags & PF_WIOC)
633 wakeup((caddr_t)&pti->pt_flags);
634 if (pti->pt_flags & PF_OWAIT)
635 wakeup((caddr_t)pti + 1);
636 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
637 ptswake(tp);
638 goto doioctl;
639 }
640 if (q_to_b(&pti->pt_ioc, &error, sizeof error) != sizeof error)
641 error = EINVAL;
642 if (error == 0 && cmd & IOC_OUT) {
643 if (IOCPARM_LEN(cmd) != pti->pt_ioc.c_cc)
644 error = EINVAL;
645 else
646 (void) q_to_b(&pti->pt_ioc, data,
647 pti->pt_ioc.c_cc);
648 }
649 while (pti->pt_ioc.c_cc)
650 (void) getc(&pti->pt_ioc);
651 if (pti->pt_flags & PF_WIOC)
652 wakeup((caddr_t)&pti->pt_flags);
653 if (pti->pt_flags & PF_OWAIT)
654 wakeup((caddr_t)pti + 1);
655 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
656 ptswake(tp);
657 return (error);
658 }
659
660 doioctl:
477d62ec 661 error = ttioctl(tp, cmd, data, flag);
f2f3b49b
MK
662 /*
663 * Since we use the tty queues internally,
664 * pty's can't be switched to disciplines which overwrite
665 * the queues. We can't tell anything about the discipline
666 * from here...
6a5ca8a0
KM
667 *
668 * Nb: this is not really good enough, the line disc open routine
669 * may have done anything at all, no guarantees that close
670 * will fix it. This also has the effect of losing the
671 * previous discipline, which an error on a TIOCSETD shouldn't
672 * do... Sometime it should be done via an explicit check
673 * for TIOCSETD, then check to see what linesw[new_number].l_rint
674 * really is.
f2f3b49b
MK
675 */
676 if (linesw[tp->t_line].l_rint != ttyinput) {
677 (*linesw[tp->t_line].l_close)(tp);
678 tp->t_line = 0;
679 (void)(*linesw[tp->t_line].l_open)(dev, tp);
680 error = ENOTTY;
681 }
6a5ca8a0 682
5bb90914
JB
683 if (error < 0) {
684 if (pti->pt_flags & PF_UCNTL &&
97d7430f 685 (cmd & ~0xff) == UIOCCMD(0)) {
5bb90914
JB
686 if (cmd & 0xff) {
687 pti->pt_ucntl = (u_char)cmd;
688 ptcwakeup(tp, FREAD);
689 }
690 return (0);
691 }
f21c8fb8 692 error = ENOTTY;
5bb90914
JB
693 }
694 stop = (tp->t_flags & RAW) == 0 &&
c16520ef 695 tp->t_stopc == CTRL('s') && tp->t_startc == CTRL('q');
0a2bd708
BJ
696 if (pti->pt_flags & PF_NOSTOP) {
697 if (stop) {
b31eb1ff 698 pti->pt_send &= ~TIOCPKT_NOSTOP;
0a2bd708
BJ
699 pti->pt_send |= TIOCPKT_DOSTOP;
700 pti->pt_flags &= ~PF_NOSTOP;
5bb90914 701 ptcwakeup(tp, FREAD);
0a2bd708
BJ
702 }
703 } else {
5bb90914 704 if (!stop) {
0a2bd708
BJ
705 pti->pt_send &= ~TIOCPKT_DOSTOP;
706 pti->pt_send |= TIOCPKT_NOSTOP;
707 pti->pt_flags |= PF_NOSTOP;
5bb90914 708 ptcwakeup(tp, FREAD);
0a2bd708
BJ
709 }
710 }
f21c8fb8 711 return (error);
45372428 712}
4f07e6e5 713#endif