pass flags to l_close, dont ttywait if IO_NDELAY (revoke)
[unix-history] / usr / src / sys / kern / tty_pty.c
CommitLineData
da7c5cc6 1/*
fccd027d
KB
2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
fccd027d 6 *
f50ba5a1 7 * @(#)tty_pty.c 7.19 (Berkeley) %G%
da7c5cc6 8 */
be4367b3 9
45372428
MT
10/*
11 * Pseudo-teletype Driver
12 * (Actually two drivers, requiring two entries in 'cdevsw')
45372428 13 */
647d645f
MT
14#include "pty.h"
15
f12183e4 16#if NPTY > 0
94368568
JB
17#include "param.h"
18#include "systm.h"
19#include "ioctl.h"
20#include "tty.h"
94368568
JB
21#include "conf.h"
22#include "file.h"
23#include "proc.h"
24#include "uio.h"
25#include "kernel.h"
c4ec2128 26#include "vnode.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*/
f50ba5a1 65ptsopen(dev, flag, devtype, p)
73c77d38 66 dev_t dev;
f50ba5a1 67 struct proc *p;
e1d74936 68{
45372428 69 register struct tty *tp;
5bb90914 70 int error;
45372428 71
5bb90914
JB
72#ifdef lint
73 npty = npty;
74#endif
f21c8fb8
BJ
75 if (minor(dev) >= NPTY)
76 return (ENXIO);
45372428 77 tp = &pt_tty[minor(dev)];
941944c9 78 if ((tp->t_state & TS_ISOPEN) == 0) {
7595f992 79 tp->t_state |= TS_WOPEN;
bdda6b91 80 ttychars(tp); /* Set up default chars */
e39f9ea6
MT
81 tp->t_iflag = TTYDEF_IFLAG;
82 tp->t_oflag = TTYDEF_OFLAG;
83 tp->t_lflag = TTYDEF_LFLAG;
84 tp->t_cflag = TTYDEF_CFLAG;
85 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
86 ttsetwater(tp); /* would be done in xxparam() */
b98b2de8 87 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
f21c8fb8 88 return (EBUSY);
e1d74936 89 if (tp->t_oproc) /* Ctrlr still around. */
941944c9
BJ
90 tp->t_state |= TS_CARR_ON;
91 while ((tp->t_state & TS_CARR_ON) == 0) {
92 tp->t_state |= TS_WOPEN;
e9fe78f8
MT
93 if (flag&FNDELAY)
94 break;
7595f992 95 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
9a418eca
MK
96 ttopen, 0))
97 return (error);
45372428 98 }
e9fe78f8 99 error = (*linesw[tp->t_line].l_open)(dev, tp, flag);
5bb90914
JB
100 ptcwakeup(tp, FREAD|FWRITE);
101 return (error);
45372428
MT
102}
103
104ptsclose(dev)
73c77d38 105 dev_t dev;
941944c9 106{
45372428
MT
107 register struct tty *tp;
108
109 tp = &pt_tty[minor(dev)];
110 (*linesw[tp->t_line].l_close)(tp);
4b39cb77 111 ttyclose(tp);
5bb90914 112 ptcwakeup(tp, FREAD|FWRITE);
6a5ca8a0 113 return (0);
45372428
MT
114}
115
e9fe78f8 116ptsread(dev, uio, flag)
73c77d38 117 dev_t dev;
ae9a0a69 118 struct uio *uio;
e1d74936 119{
b98b2de8 120 struct proc *p = curproc;
defdbcd1
BJ
121 register struct tty *tp = &pt_tty[minor(dev)];
122 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 123 int error = 0;
defdbcd1
BJ
124
125again:
126 if (pti->pt_flags & PF_REMOTE) {
b98b2de8
MK
127 while (isbackground(p, tp)) {
128 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
129 (p->p_sigmask & sigmask(SIGTTIN)) ||
130 p->p_pgrp->pg_jobc == 0 ||
131 p->p_flag&SPPWAIT)
840510a3 132 return (EIO);
b98b2de8 133 pgsignal(p->p_pgrp, SIGTTIN, 1);
7595f992
MT
134 if (error = ttysleep(tp, (caddr_t)&lbolt,
135 TTIPRI | PCATCH, ttybg, 0))
9a418eca 136 return (error);
941944c9 137 }
5bb90914 138 if (tp->t_canq.c_cc == 0) {
c4ec2128 139 if (flag & IO_NDELAY)
840510a3 140 return (EWOULDBLOCK);
7595f992 141 if (error = ttysleep(tp, (caddr_t)&tp->t_canq,
9a418eca
MK
142 TTIPRI | PCATCH, ttyin, 0))
143 return (error);
defdbcd1
BJ
144 goto again;
145 }
5bb90914
JB
146 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
147 if (ureadc(getc(&tp->t_canq), uio) < 0) {
840510a3 148 error = EFAULT;
ae9a0a69
BJ
149 break;
150 }
5bb90914
JB
151 if (tp->t_canq.c_cc == 1)
152 (void) getc(&tp->t_canq);
153 if (tp->t_canq.c_cc)
840510a3 154 return (error);
defdbcd1
BJ
155 } else
156 if (tp->t_oproc)
e9fe78f8 157 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
5bb90914 158 ptcwakeup(tp, FWRITE);
840510a3 159 return (error);
45372428
MT
160}
161
941944c9
BJ
162/*
163 * Write to pseudo-tty.
164 * Wakeups of controlling tty will happen
165 * indirectly, when tty driver calls ptsstart.
166 */
e9fe78f8 167ptswrite(dev, uio, flag)
73c77d38 168 dev_t dev;
ae9a0a69 169 struct uio *uio;
e1d74936 170{
6a5ca8a0
KM
171 register struct tty *tp = &pt_tty[minor(dev)];
172 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
45372428 173
840510a3
BJ
174 if (tp->t_oproc == 0)
175 return (EIO);
6a5ca8a0
KM
176
177 while (pti->pt_flags & PF_BLOCK) {
178 pti->pt_flags |= PF_OWAIT;
179 sleep((caddr_t)pti + 1, TTOPRI);
180 }
181
e9fe78f8 182 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
45372428
MT
183}
184
941944c9
BJ
185/*
186 * Start output on pseudo-tty.
187 * Wake up process selecting or sleeping for input from controlling tty.
188 */
45372428 189ptsstart(tp)
e1d74936
BJ
190 struct tty *tp;
191{
1e6d24b1 192 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
e1d74936 193
941944c9 194 if (tp->t_state & TS_TTSTOP)
45372428 195 return;
1e6d24b1
BJ
196 if (pti->pt_flags & PF_STOPPED) {
197 pti->pt_flags &= ~PF_STOPPED;
198 pti->pt_send = TIOCPKT_START;
199 }
5bb90914 200 ptcwakeup(tp, FREAD);
d427b3b2
BJ
201}
202
5bb90914 203ptcwakeup(tp, flag)
d427b3b2
BJ
204 struct tty *tp;
205{
206 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
207
5bb90914
JB
208 if (flag & FREAD) {
209 if (pti->pt_selr) {
210 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
211 pti->pt_selr = 0;
212 pti->pt_flags &= ~PF_RCOLL;
213 }
214 wakeup((caddr_t)&tp->t_outq.c_cf);
215 }
216 if (flag & FWRITE) {
217 if (pti->pt_selw) {
218 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
219 pti->pt_selw = 0;
220 pti->pt_flags &= ~PF_WCOLL;
221 }
222 wakeup((caddr_t)&tp->t_rawq.c_cf);
e1d74936 223 }
45372428
MT
224}
225
226/*ARGSUSED*/
f50ba5a1
MK
227#ifdef __STDC__
228ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
229#else
230ptcopen(dev, flag, devtype, p)
e1d74936 231 dev_t dev;
f50ba5a1
MK
232 int flag, devtype;
233 struct proc *p;
234#endif
e1d74936 235{
45372428 236 register struct tty *tp;
1a954a11 237 struct pt_ioctl *pti;
45372428 238
f21c8fb8
BJ
239 if (minor(dev) >= NPTY)
240 return (ENXIO);
45372428 241 tp = &pt_tty[minor(dev)];
f21c8fb8
BJ
242 if (tp->t_oproc)
243 return (EIO);
e1d74936 244 tp->t_oproc = ptsstart;
f2f3b49b 245 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
44ce8f01 246 tp->t_lflag &= ~EXTPROC;
1a954a11
BJ
247 pti = &pt_ioctl[minor(dev)];
248 pti->pt_flags = 0;
249 pti->pt_send = 0;
5bb90914 250 pti->pt_ucntl = 0;
f21c8fb8 251 return (0);
45372428
MT
252}
253
254ptcclose(dev)
e1d74936
BJ
255 dev_t dev;
256{
45372428
MT
257 register struct tty *tp;
258
259 tp = &pt_tty[minor(dev)];
f2f3b49b 260 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
d3be7d55 261 tp->t_state &= ~TS_CARR_ON;
e1d74936 262 tp->t_oproc = 0; /* mark closed */
bc8d7925 263 tp->t_session = 0;
6a5ca8a0 264 return (0);
45372428
MT
265}
266
e9fe78f8 267ptcread(dev, uio, flag)
1a954a11 268 dev_t dev;
ae9a0a69 269 struct uio *uio;
e1d74936 270{
840510a3 271 register struct tty *tp = &pt_tty[minor(dev)];
5bb90914 272 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
2bb0bef9
SL
273 char buf[BUFSIZ];
274 int error = 0, cc;
45372428 275
5bb90914
JB
276 /*
277 * We want to block until the slave
278 * is open, and there's something to read;
279 * but if we lost the slave or we're NBIO,
280 * then return the appropriate error instead.
281 */
282 for (;;) {
283 if (tp->t_state&TS_ISOPEN) {
284 if (pti->pt_flags&PF_PKT && pti->pt_send) {
8011f5df 285 error = ureadc((int)pti->pt_send, uio);
5bb90914
JB
286 if (error)
287 return (error);
44ce8f01
MT
288 if (pti->pt_send & TIOCPKT_IOCTL) {
289 cc = MIN(uio->uio_resid,
290 sizeof(tp->t_termios));
291 uiomove(&tp->t_termios, cc, uio);
292 }
5bb90914
JB
293 pti->pt_send = 0;
294 return (0);
295 }
296 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
8011f5df 297 error = ureadc((int)pti->pt_ucntl, uio);
5bb90914
JB
298 if (error)
299 return (error);
300 pti->pt_ucntl = 0;
301 return (0);
302 }
6a5ca8a0
KM
303 if (pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc) {
304 if (uio->uio_resid < pti->pt_ioc.c_cc + 1)
305 return (E2BIG);
306 error = ureadc(TIOCPKT_TIOC, uio);
307 while (error == 0 && pti->pt_ioc.c_cc > 0) {
308 cc = q_to_b(&pti->pt_ioc, buf,
309 MIN(pti->pt_ioc.c_cc, BUFSIZ));
310 if (cc <= 0) /* impossible? */
311 break;
312 error = uiomove(buf, cc, UIO_READ, uio);
313 }
314 return (error);
315 }
5bb90914
JB
316 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
317 break;
1a954a11 318 }
2bb0bef9 319 if ((tp->t_state&TS_CARR_ON) == 0)
e9fe78f8 320 return (0); /* EOF */
c4ec2128 321 if (flag & IO_NDELAY)
840510a3 322 return (EWOULDBLOCK);
9a418eca
MK
323 if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
324 ttyin, 0))
325 return (error);
8b8271ac 326 }
6a5ca8a0 327 if (pti->pt_flags & (PF_PKT|PF_UCNTL|PF_TIOC))
5bb90914 328 error = ureadc(0, uio);
2bb0bef9
SL
329 while (uio->uio_resid > 0 && error == 0) {
330 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
331 if (cc <= 0)
ae9a0a69 332 break;
c4ec2128 333 error = uiomove(buf, cc, uio);
2bb0bef9 334 }
6a5ca8a0
KM
335 if (tp->t_outq.c_cc <= TTLOWAT(tp) && !(pti->pt_flags & PF_BLOCK))
336 ptswake(tp);
840510a3 337 return (error);
45372428
MT
338}
339
6a5ca8a0
KM
340ptswake(tp)
341 register struct tty *tp;
342{
343 if (tp->t_state&TS_ASLEEP) {
344 tp->t_state &= ~TS_ASLEEP;
345 wakeup((caddr_t)&tp->t_outq);
346 }
347 if (tp->t_wsel) {
348 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
349 tp->t_wsel = 0;
350 tp->t_state &= ~TS_WCOLL;
351 }
352}
353
1a954a11
BJ
354ptsstop(tp, flush)
355 register struct tty *tp;
356 int flush;
357{
358 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
5bb90914 359 int flag;
1a954a11 360
1e6d24b1
BJ
361 /* note: FLUSHREAD and FLUSHWRITE already ok */
362 if (flush == 0) {
363 flush = TIOCPKT_STOP;
364 pti->pt_flags |= PF_STOPPED;
5bb90914 365 } else
1e6d24b1 366 pti->pt_flags &= ~PF_STOPPED;
0a2bd708 367 pti->pt_send |= flush;
5bb90914
JB
368 /* change of perspective */
369 flag = 0;
370 if (flush & FREAD)
371 flag |= FWRITE;
372 if (flush & FWRITE)
373 flag |= FREAD;
9d2a90b1 374 ptcwakeup(tp, flag);
1a954a11
BJ
375}
376
f50ba5a1 377ptcselect(dev, rw, p)
e1d74936 378 dev_t dev;
941944c9 379 int rw;
f50ba5a1 380 struct proc *p;
e1d74936
BJ
381{
382 register struct tty *tp = &pt_tty[minor(dev)];
defdbcd1 383 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
f50ba5a1 384 struct proc *prev;
d427b3b2 385 int s;
e1d74936 386
5bb90914 387 if ((tp->t_state&TS_CARR_ON) == 0)
e1d74936 388 return (1);
941944c9
BJ
389 switch (rw) {
390
391 case FREAD:
892f2f35
MK
392 /*
393 * Need to block timeouts (ttrstart).
394 */
395 s = spltty();
7cbd29e4
MK
396 if ((tp->t_state&TS_ISOPEN) &&
397 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
398 splx(s);
399 return (1);
400 }
892f2f35 401 splx(s);
7cbd29e4
MK
402 /* FALLTHROUGH */
403
404 case 0: /* exceptional */
5bb90914
JB
405 if ((tp->t_state&TS_ISOPEN) &&
406 (pti->pt_flags&PF_PKT && pti->pt_send ||
6a5ca8a0 407 pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc ||
892f2f35 408 pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
941944c9 409 return (1);
f50ba5a1 410 if ((prev = pti->pt_selr) && prev->p_wchan == (caddr_t)&selwait)
1a954a11 411 pti->pt_flags |= PF_RCOLL;
941944c9 412 else
f50ba5a1 413 pti->pt_selr = p;
d427b3b2 414 break;
941944c9 415
7cbd29e4 416
941944c9 417 case FWRITE:
892f2f35
MK
418 if (tp->t_state&TS_ISOPEN) {
419 if (pti->pt_flags & PF_REMOTE) {
420 if (tp->t_canq.c_cc == 0)
421 return (1);
422 } else {
423 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
424 return (1);
e39f9ea6 425 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
892f2f35
MK
426 return (1);
427 }
d427b3b2 428 }
f50ba5a1 429 if ((prev = pti->pt_selw) && prev->p_wchan == (caddr_t)&selwait)
1a954a11 430 pti->pt_flags |= PF_WCOLL;
941944c9 431 else
f50ba5a1 432 pti->pt_selw = p;
d427b3b2 433 break;
7cbd29e4 434
941944c9 435 }
d427b3b2 436 return (0);
e1d74936
BJ
437}
438
e9fe78f8 439ptcwrite(dev, uio, flag)
941944c9 440 dev_t dev;
5bb90914 441 register struct uio *uio;
e1d74936 442{
840510a3 443 register struct tty *tp = &pt_tty[minor(dev)];
88b2ff48 444 register u_char *cp;
5bb90914 445 register int cc = 0;
88b2ff48 446 u_char locbuf[BUFSIZ];
941944c9 447 int cnt = 0;
defdbcd1 448 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 449 int error = 0;
45372428 450
defdbcd1 451again:
5bb90914
JB
452 if ((tp->t_state&TS_ISOPEN) == 0)
453 goto block;
9d2a90b1 454 if (pti->pt_flags & PF_REMOTE) {
5bb90914
JB
455 if (tp->t_canq.c_cc)
456 goto block;
88b2ff48 457 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
9d2a90b1 458 if (cc == 0) {
88b2ff48
MK
459 cc = min(uio->uio_resid, BUFSIZ);
460 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
9d2a90b1 461 cp = locbuf;
88b2ff48 462 error = uiomove((caddr_t)cp, cc, uio);
9d2a90b1
JB
463 if (error)
464 return (error);
465 /* check again for safety */
466 if ((tp->t_state&TS_ISOPEN) == 0)
467 return (EIO);
468 }
469 if (cc)
88b2ff48 470 (void) b_to_q((char *)cp, cc, &tp->t_canq);
9d2a90b1 471 cc = 0;
defdbcd1 472 }
5bb90914
JB
473 (void) putc(0, &tp->t_canq);
474 ttwakeup(tp);
475 wakeup((caddr_t)&tp->t_canq);
476 return (0);
477 }
88b2ff48 478 while (uio->uio_resid > 0) {
5bb90914 479 if (cc == 0) {
88b2ff48 480 cc = min(uio->uio_resid, BUFSIZ);
5bb90914 481 cp = locbuf;
88b2ff48 482 error = uiomove((caddr_t)cp, cc, uio);
5bb90914
JB
483 if (error)
484 return (error);
485 /* check again for safety */
486 if ((tp->t_state&TS_ISOPEN) == 0)
487 return (EIO);
488 }
9d2a90b1
JB
489 while (cc > 0) {
490 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
e39f9ea6 491 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
9d2a90b1
JB
492 wakeup((caddr_t)&tp->t_rawq);
493 goto block;
494 }
88b2ff48 495 (*linesw[tp->t_line].l_rint)(*cp++, tp);
941944c9 496 cnt++;
9d2a90b1 497 cc--;
45372428 498 }
5bb90914
JB
499 cc = 0;
500 }
501 return (0);
502block:
503 /*
9d2a90b1
JB
504 * Come here to wait for slave to open, for space
505 * in outq, or space in rawq.
5bb90914
JB
506 */
507 if ((tp->t_state&TS_CARR_ON) == 0)
508 return (EIO);
88b2ff48
MK
509 if (flag & IO_NDELAY) {
510 /* adjust for data copied in but not written */
5bb90914 511 uio->uio_resid += cc;
9d2a90b1
JB
512 if (cnt == 0)
513 return (EWOULDBLOCK);
5bb90914
JB
514 return (0);
515 }
9a418eca 516 if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
88b2ff48
MK
517 ttyout, 0)) {
518 /* adjust for data copied in but not written */
519 uio->uio_resid += cc;
9a418eca 520 return (error);
88b2ff48 521 }
5bb90914 522 goto again;
45372428
MT
523}
524
45372428 525/*ARGSUSED*/
4b72e2f9
SL
526ptyioctl(dev, cmd, data, flag)
527 caddr_t data;
e1d74936
BJ
528 dev_t dev;
529{
0a2bd708
BJ
530 register struct tty *tp = &pt_tty[minor(dev)];
531 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
e39f9ea6 532 register u_char *cc = tp->t_cc;
5bb90914 533 int stop, error;
f2f3b49b 534 extern ttyinput();
45372428 535
f2f3b49b
MK
536 /*
537 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
538 * ttywflush(tp) will hang if there are characters in the outq.
539 */
44ce8f01
MT
540 if (cmd == TIOCEXT) {
541 /*
542 * When the EXTPROC bit is being toggled, we need
543 * to send an TIOCPKT_IOCTL if the packet driver
544 * is turned on.
545 */
546 if (*(int *)data) {
547 if (pti->pt_flags & PF_PKT) {
548 pti->pt_send |= TIOCPKT_IOCTL;
549 ptcwakeup(tp);
550 }
551 tp->t_lflag |= EXTPROC;
552 } else {
553 if ((tp->t_state & EXTPROC) &&
554 (pti->pt_flags & PF_PKT)) {
555 pti->pt_send |= TIOCPKT_IOCTL;
556 ptcwakeup(tp);
557 }
558 tp->t_lflag &= ~EXTPROC;
559 }
560 return(0);
561 } else
6a5ca8a0
KM
562 if (cdevsw[major(dev)].d_open == ptcopen) {
563 if ((cmd & 0xffff) == (TIOCIOANS(0) & 0xffff)) {
564 if (!(pti->pt_flags & PF_LIOC) || pti->pt_ioc.c_cc)
565 return (EINVAL);
566 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
567 wakeup((caddr_t)&pti->pt_ioc);
568 return (0);
569 }
4b72e2f9
SL
570 switch (cmd) {
571
1b2a00b5
MT
572 case TIOCGPGRP:
573 /*
574 * We aviod calling ttioctl on the controller since,
575 * in that case, tp must be the controlling terminal.
576 */
577 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
578 return (0);
579
4b72e2f9 580 case TIOCPKT:
5bb90914
JB
581 if (*(int *)data) {
582 if (pti->pt_flags & PF_UCNTL)
583 return (EINVAL);
1a954a11 584 pti->pt_flags |= PF_PKT;
5bb90914 585 } else
1a954a11 586 pti->pt_flags &= ~PF_PKT;
f21c8fb8 587 return (0);
4b72e2f9 588
5bb90914
JB
589 case TIOCUCNTL:
590 if (*(int *)data) {
591 if (pti->pt_flags & PF_PKT)
592 return (EINVAL);
593 pti->pt_flags |= PF_UCNTL;
594 } else
595 pti->pt_flags &= ~PF_UCNTL;
596 return (0);
597
6a5ca8a0
KM
598 case TIOCTIOC:
599 if (*(int *)data) {
600 if (pti->pt_flags & PF_UCNTL)
601 return (EINVAL);
602 pti->pt_flags |= PF_TIOC;
603 } else {
604 pti->pt_flags &= ~(PF_TIOC|PF_LIOC|PF_WIOC);
605 while (pti->pt_ioc.c_cc)
606 (void) getc(&pti->pt_ioc);
607 wakeup((caddr_t)&pti->pt_ioc);
608 }
609 return (0);
610
611 case TIOCBLK:
612 if (*(int *)data)
613 pti->pt_flags |= PF_BLOCK;
614 else {
615 if (pti->pt_flags & PF_OWAIT)
616 wakeup((caddr_t)pti + 1);
617 pti->pt_flags &= ~(PF_BLOCK|PF_OWAIT);
618 ptswake(tp);
619 }
620 return (0);
621
4b72e2f9
SL
622 case TIOCREMOTE:
623 if (*(int *)data)
defdbcd1
BJ
624 pti->pt_flags |= PF_REMOTE;
625 else
626 pti->pt_flags &= ~PF_REMOTE;
88a7a62a 627 ttyflush(tp, FREAD|FWRITE);
f21c8fb8 628 return (0);
4b72e2f9 629
6a5ca8a0
KM
630 case FIONREAD:
631 *(int *)data = tp->t_outq.c_cc;
632 return (0);
633
e39f9ea6 634 case TIOCSETP:
f2f3b49b
MK
635 case TIOCSETN:
636 case TIOCSETD:
e39f9ea6
MT
637 case TIOCSETA:
638 case TIOCSETAW:
639 case TIOCSETAF:
4b72e2f9
SL
640 while (getc(&tp->t_outq) >= 0)
641 ;
642 break;
44ce8f01
MT
643
644 case TIOCSIG:
645 if (*(unsigned int *)data >= NSIG)
646 return(EINVAL);
647 if ((tp->t_lflag&NOFLSH) == 0)
648 ttyflush(tp, FREAD|FWRITE);
3ae82c34
PB
649 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
650 if ((*(unsigned int *)data == SIGINFO) &&
651 ((tp->t_lflag&NOKERNINFO) == 0))
652 ttyinfo(tp);
44ce8f01 653 return(0);
8b8271ac 654 }
6a5ca8a0
KM
655 } else if (pti->pt_flags & PF_TIOC) {
656 while (pti->pt_flags & PF_LIOC) {
657 pti->pt_flags |= PF_WIOC;
658 switch (tsleep((caddr_t)&pti->pt_flags,TTIPRI-1,5*hz)) {
659 case TS_OK:
660 continue;
661 case TS_SIG:
662 case TS_TIME:
663 return (EBUSY);
664 }
665 }
666 pti->pt_flags |= PF_LIOC | PF_BLOCK;
667 while (pti->pt_ioc.c_cc)
668 (void) getc(&pti->pt_ioc);
669 (void) b_to_q(&cmd, sizeof cmd, &pti->pt_ioc);
670 if (cmd & IOC_IN)
671 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
672 ptcwakeup(tp, FREAD);
673 switch (tsleep((caddr_t)&pti->pt_ioc, TTIPRI-1, 5*hz)) {
674 case TS_SIG:
675 case TS_TIME:
676 while (pti->pt_ioc.c_cc)
677 (void) getc(&pti->pt_ioc);
678 if (pti->pt_flags & PF_WIOC)
679 wakeup((caddr_t)&pti->pt_flags);
680 if (pti->pt_flags & PF_OWAIT)
681 wakeup((caddr_t)pti + 1);
682 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
683 ptswake(tp);
684 return (EBUSY);
685 case TS_OK:
686 break;
687 }
688 if (pti->pt_ioc.c_cc == 0) {
689 if (pti->pt_flags & PF_WIOC)
690 wakeup((caddr_t)&pti->pt_flags);
691 if (pti->pt_flags & PF_OWAIT)
692 wakeup((caddr_t)pti + 1);
693 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
694 ptswake(tp);
695 goto doioctl;
696 }
697 if (q_to_b(&pti->pt_ioc, &error, sizeof error) != sizeof error)
698 error = EINVAL;
699 if (error == 0 && cmd & IOC_OUT) {
700 if (IOCPARM_LEN(cmd) != pti->pt_ioc.c_cc)
701 error = EINVAL;
702 else
703 (void) q_to_b(&pti->pt_ioc, data,
704 pti->pt_ioc.c_cc);
705 }
706 while (pti->pt_ioc.c_cc)
707 (void) getc(&pti->pt_ioc);
708 if (pti->pt_flags & PF_WIOC)
709 wakeup((caddr_t)&pti->pt_flags);
710 if (pti->pt_flags & PF_OWAIT)
711 wakeup((caddr_t)pti + 1);
712 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
713 ptswake(tp);
714 return (error);
715 }
716
717 doioctl:
e39f9ea6
MT
718 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
719 if (error < 0)
720 error = ttioctl(tp, cmd, data, flag);
f2f3b49b
MK
721 /*
722 * Since we use the tty queues internally,
723 * pty's can't be switched to disciplines which overwrite
724 * the queues. We can't tell anything about the discipline
725 * from here...
6a5ca8a0
KM
726 *
727 * Nb: this is not really good enough, the line disc open routine
728 * may have done anything at all, no guarantees that close
729 * will fix it. This also has the effect of losing the
730 * previous discipline, which an error on a TIOCSETD shouldn't
731 * do... Sometime it should be done via an explicit check
732 * for TIOCSETD, then check to see what linesw[new_number].l_rint
733 * really is.
f2f3b49b
MK
734 */
735 if (linesw[tp->t_line].l_rint != ttyinput) {
736 (*linesw[tp->t_line].l_close)(tp);
88b2ff48 737 tp->t_line = TTYDISC;
e9fe78f8 738 (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
f2f3b49b
MK
739 error = ENOTTY;
740 }
6a5ca8a0 741
5bb90914
JB
742 if (error < 0) {
743 if (pti->pt_flags & PF_UCNTL &&
97d7430f 744 (cmd & ~0xff) == UIOCCMD(0)) {
5bb90914
JB
745 if (cmd & 0xff) {
746 pti->pt_ucntl = (u_char)cmd;
747 ptcwakeup(tp, FREAD);
748 }
749 return (0);
750 }
f21c8fb8 751 error = ENOTTY;
5bb90914 752 }
44ce8f01
MT
753 /*
754 * If external processing and packet mode send ioctl packet.
755 */
756 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
757 switch(cmd) {
758 case TIOCSETA:
759 case TIOCSETAW:
760 case TIOCSETAF:
44ce8f01
MT
761 case TIOCSETP:
762 case TIOCSETN:
763#ifdef COMPAT_43
764 case TIOCSETC:
765 case TIOCSLTC:
766 case TIOCLBIS:
767 case TIOCLBIC:
768 case TIOCLSET:
769#endif
770 pti->pt_send |= TIOCPKT_IOCTL;
771 default:
772 break;
773 }
774 }
e39f9ea6
MT
775 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
776 && CCEQ(cc[VSTART], CTRL('q'));
0a2bd708
BJ
777 if (pti->pt_flags & PF_NOSTOP) {
778 if (stop) {
b31eb1ff 779 pti->pt_send &= ~TIOCPKT_NOSTOP;
0a2bd708
BJ
780 pti->pt_send |= TIOCPKT_DOSTOP;
781 pti->pt_flags &= ~PF_NOSTOP;
5bb90914 782 ptcwakeup(tp, FREAD);
0a2bd708
BJ
783 }
784 } else {
5bb90914 785 if (!stop) {
0a2bd708
BJ
786 pti->pt_send &= ~TIOCPKT_DOSTOP;
787 pti->pt_send |= TIOCPKT_NOSTOP;
788 pti->pt_flags |= PF_NOSTOP;
5bb90914 789 ptcwakeup(tp, FREAD);
0a2bd708
BJ
790 }
791 }
f21c8fb8 792 return (error);
45372428 793}
4f07e6e5 794#endif