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