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