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