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