consistency with tty.c about value for "no pgrp"
[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 *
93080c46 7 * @(#)tty_pty.c 7.21 (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;
f2f3b49b 536 extern ttyinput();
45372428 537
f2f3b49b
MK
538 /*
539 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
540 * ttywflush(tp) will hang if there are characters in the outq.
541 */
44ce8f01
MT
542 if (cmd == TIOCEXT) {
543 /*
544 * When the EXTPROC bit is being toggled, we need
545 * to send an TIOCPKT_IOCTL if the packet driver
546 * is turned on.
547 */
548 if (*(int *)data) {
549 if (pti->pt_flags & PF_PKT) {
550 pti->pt_send |= TIOCPKT_IOCTL;
551 ptcwakeup(tp);
552 }
553 tp->t_lflag |= EXTPROC;
554 } else {
555 if ((tp->t_state & EXTPROC) &&
556 (pti->pt_flags & PF_PKT)) {
557 pti->pt_send |= TIOCPKT_IOCTL;
558 ptcwakeup(tp);
559 }
560 tp->t_lflag &= ~EXTPROC;
561 }
562 return(0);
563 } else
6a5ca8a0
KM
564 if (cdevsw[major(dev)].d_open == ptcopen) {
565 if ((cmd & 0xffff) == (TIOCIOANS(0) & 0xffff)) {
566 if (!(pti->pt_flags & PF_LIOC) || pti->pt_ioc.c_cc)
567 return (EINVAL);
568 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
569 wakeup((caddr_t)&pti->pt_ioc);
570 return (0);
571 }
4b72e2f9
SL
572 switch (cmd) {
573
1b2a00b5
MT
574 case TIOCGPGRP:
575 /*
576 * We aviod calling ttioctl on the controller since,
577 * in that case, tp must be the controlling terminal.
578 */
579 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
580 return (0);
581
4b72e2f9 582 case TIOCPKT:
5bb90914
JB
583 if (*(int *)data) {
584 if (pti->pt_flags & PF_UCNTL)
585 return (EINVAL);
1a954a11 586 pti->pt_flags |= PF_PKT;
5bb90914 587 } else
1a954a11 588 pti->pt_flags &= ~PF_PKT;
f21c8fb8 589 return (0);
4b72e2f9 590
5bb90914
JB
591 case TIOCUCNTL:
592 if (*(int *)data) {
593 if (pti->pt_flags & PF_PKT)
594 return (EINVAL);
595 pti->pt_flags |= PF_UCNTL;
596 } else
597 pti->pt_flags &= ~PF_UCNTL;
598 return (0);
599
6a5ca8a0
KM
600 case TIOCTIOC:
601 if (*(int *)data) {
602 if (pti->pt_flags & PF_UCNTL)
603 return (EINVAL);
604 pti->pt_flags |= PF_TIOC;
605 } else {
606 pti->pt_flags &= ~(PF_TIOC|PF_LIOC|PF_WIOC);
607 while (pti->pt_ioc.c_cc)
608 (void) getc(&pti->pt_ioc);
609 wakeup((caddr_t)&pti->pt_ioc);
610 }
611 return (0);
612
613 case TIOCBLK:
614 if (*(int *)data)
615 pti->pt_flags |= PF_BLOCK;
616 else {
617 if (pti->pt_flags & PF_OWAIT)
618 wakeup((caddr_t)pti + 1);
619 pti->pt_flags &= ~(PF_BLOCK|PF_OWAIT);
620 ptswake(tp);
621 }
622 return (0);
623
4b72e2f9
SL
624 case TIOCREMOTE:
625 if (*(int *)data)
defdbcd1
BJ
626 pti->pt_flags |= PF_REMOTE;
627 else
628 pti->pt_flags &= ~PF_REMOTE;
88a7a62a 629 ttyflush(tp, FREAD|FWRITE);
f21c8fb8 630 return (0);
4b72e2f9 631
6a5ca8a0
KM
632 case FIONREAD:
633 *(int *)data = tp->t_outq.c_cc;
634 return (0);
635
e39f9ea6 636 case TIOCSETP:
f2f3b49b
MK
637 case TIOCSETN:
638 case TIOCSETD:
e39f9ea6
MT
639 case TIOCSETA:
640 case TIOCSETAW:
641 case TIOCSETAF:
4b72e2f9
SL
642 while (getc(&tp->t_outq) >= 0)
643 ;
644 break;
44ce8f01
MT
645
646 case TIOCSIG:
647 if (*(unsigned int *)data >= NSIG)
648 return(EINVAL);
649 if ((tp->t_lflag&NOFLSH) == 0)
650 ttyflush(tp, FREAD|FWRITE);
3ae82c34
PB
651 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
652 if ((*(unsigned int *)data == SIGINFO) &&
653 ((tp->t_lflag&NOKERNINFO) == 0))
654 ttyinfo(tp);
44ce8f01 655 return(0);
8b8271ac 656 }
6a5ca8a0
KM
657 } else if (pti->pt_flags & PF_TIOC) {
658 while (pti->pt_flags & PF_LIOC) {
659 pti->pt_flags |= PF_WIOC;
660 switch (tsleep((caddr_t)&pti->pt_flags,TTIPRI-1,5*hz)) {
661 case TS_OK:
662 continue;
663 case TS_SIG:
664 case TS_TIME:
665 return (EBUSY);
666 }
667 }
668 pti->pt_flags |= PF_LIOC | PF_BLOCK;
669 while (pti->pt_ioc.c_cc)
670 (void) getc(&pti->pt_ioc);
671 (void) b_to_q(&cmd, sizeof cmd, &pti->pt_ioc);
672 if (cmd & IOC_IN)
673 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
674 ptcwakeup(tp, FREAD);
675 switch (tsleep((caddr_t)&pti->pt_ioc, TTIPRI-1, 5*hz)) {
676 case TS_SIG:
677 case TS_TIME:
678 while (pti->pt_ioc.c_cc)
679 (void) getc(&pti->pt_ioc);
680 if (pti->pt_flags & PF_WIOC)
681 wakeup((caddr_t)&pti->pt_flags);
682 if (pti->pt_flags & PF_OWAIT)
683 wakeup((caddr_t)pti + 1);
684 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
685 ptswake(tp);
686 return (EBUSY);
687 case TS_OK:
688 break;
689 }
690 if (pti->pt_ioc.c_cc == 0) {
691 if (pti->pt_flags & PF_WIOC)
692 wakeup((caddr_t)&pti->pt_flags);
693 if (pti->pt_flags & PF_OWAIT)
694 wakeup((caddr_t)pti + 1);
695 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
696 ptswake(tp);
697 goto doioctl;
698 }
699 if (q_to_b(&pti->pt_ioc, &error, sizeof error) != sizeof error)
700 error = EINVAL;
701 if (error == 0 && cmd & IOC_OUT) {
702 if (IOCPARM_LEN(cmd) != pti->pt_ioc.c_cc)
703 error = EINVAL;
704 else
705 (void) q_to_b(&pti->pt_ioc, data,
706 pti->pt_ioc.c_cc);
707 }
708 while (pti->pt_ioc.c_cc)
709 (void) getc(&pti->pt_ioc);
710 if (pti->pt_flags & PF_WIOC)
711 wakeup((caddr_t)&pti->pt_flags);
712 if (pti->pt_flags & PF_OWAIT)
713 wakeup((caddr_t)pti + 1);
714 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
715 ptswake(tp);
716 return (error);
717 }
718
719 doioctl:
e39f9ea6
MT
720 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
721 if (error < 0)
722 error = ttioctl(tp, cmd, data, flag);
f2f3b49b
MK
723 /*
724 * Since we use the tty queues internally,
725 * pty's can't be switched to disciplines which overwrite
726 * the queues. We can't tell anything about the discipline
727 * from here...
6a5ca8a0
KM
728 *
729 * Nb: this is not really good enough, the line disc open routine
730 * may have done anything at all, no guarantees that close
731 * will fix it. This also has the effect of losing the
732 * previous discipline, which an error on a TIOCSETD shouldn't
733 * do... Sometime it should be done via an explicit check
734 * for TIOCSETD, then check to see what linesw[new_number].l_rint
735 * really is.
f2f3b49b
MK
736 */
737 if (linesw[tp->t_line].l_rint != ttyinput) {
2b38506d 738 (*linesw[tp->t_line].l_close)(tp, flag);
88b2ff48 739 tp->t_line = TTYDISC;
e9fe78f8 740 (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
f2f3b49b
MK
741 error = ENOTTY;
742 }
6a5ca8a0 743
5bb90914
JB
744 if (error < 0) {
745 if (pti->pt_flags & PF_UCNTL &&
97d7430f 746 (cmd & ~0xff) == UIOCCMD(0)) {
5bb90914
JB
747 if (cmd & 0xff) {
748 pti->pt_ucntl = (u_char)cmd;
749 ptcwakeup(tp, FREAD);
750 }
751 return (0);
752 }
f21c8fb8 753 error = ENOTTY;
5bb90914 754 }
44ce8f01
MT
755 /*
756 * If external processing and packet mode send ioctl packet.
757 */
758 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
759 switch(cmd) {
760 case TIOCSETA:
761 case TIOCSETAW:
762 case TIOCSETAF:
44ce8f01
MT
763 case TIOCSETP:
764 case TIOCSETN:
765#ifdef COMPAT_43
766 case TIOCSETC:
767 case TIOCSLTC:
768 case TIOCLBIS:
769 case TIOCLBIC:
770 case TIOCLSET:
771#endif
772 pti->pt_send |= TIOCPKT_IOCTL;
773 default:
774 break;
775 }
776 }
e39f9ea6
MT
777 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
778 && CCEQ(cc[VSTART], CTRL('q'));
0a2bd708
BJ
779 if (pti->pt_flags & PF_NOSTOP) {
780 if (stop) {
b31eb1ff 781 pti->pt_send &= ~TIOCPKT_NOSTOP;
0a2bd708
BJ
782 pti->pt_send |= TIOCPKT_DOSTOP;
783 pti->pt_flags &= ~PF_NOSTOP;
5bb90914 784 ptcwakeup(tp, FREAD);
0a2bd708
BJ
785 }
786 } else {
5bb90914 787 if (!stop) {
0a2bd708
BJ
788 pti->pt_send &= ~TIOCPKT_DOSTOP;
789 pti->pt_send |= TIOCPKT_NOSTOP;
790 pti->pt_flags |= PF_NOSTOP;
5bb90914 791 ptcwakeup(tp, FREAD);
0a2bd708
BJ
792 }
793 }
f21c8fb8 794 return (error);
45372428 795}
4f07e6e5 796#endif