missing a cylinder group in brute force search
[unix-history] / usr / src / sys / kern / tty_pty.c
CommitLineData
425a48ad 1/* tty_pty.c 4.29 82/12/05 */
be4367b3 2
45372428
MT
3/*
4 * Pseudo-teletype Driver
5 * (Actually two drivers, requiring two entries in 'cdevsw')
45372428 6 */
647d645f
MT
7#include "pty.h"
8
f12183e4 9#if NPTY > 0
45372428
MT
10#include "../h/param.h"
11#include "../h/systm.h"
425a48ad 12#include "../h/ioctl.h"
45372428
MT
13#include "../h/tty.h"
14#include "../h/dir.h"
15#include "../h/user.h"
16#include "../h/conf.h"
bdda6b91 17#include "../h/file.h"
e1d74936 18#include "../h/proc.h"
ae9a0a69 19#include "../h/uio.h"
7ba3a9ca 20#include "../h/kernel.h"
941944c9 21
b3c8737d 22#if NPTY == 1
c91c01fe
BJ
23#undef NPTY
24#define NPTY 32 /* crude XXX */
b3c8737d 25#endif
45372428 26
bdda6b91 27#define BUFSIZ 100 /* Chunk size iomoved from user */
e1d74936 28
45372428 29/*
e1d74936
BJ
30 * pts == /dev/tty[pP]?
31 * ptc == /dev/ptp[pP]?
45372428 32 */
e1d74936
BJ
33struct tty pt_tty[NPTY];
34struct pt_ioctl {
1a954a11
BJ
35 int pt_flags;
36 int pt_gensym;
37 struct proc *pt_selr, *pt_selw;
38 int pt_send;
e1d74936 39} pt_ioctl[NPTY];
45372428 40
1a954a11
BJ
41#define PF_RCOLL 0x01
42#define PF_WCOLL 0x02
43#define PF_NBIO 0x04
44#define PF_PKT 0x08 /* packet mode */
1e6d24b1 45#define PF_STOPPED 0x10 /* user told stopped */
defdbcd1 46#define PF_REMOTE 0x20 /* remote and flow controlled input */
0a2bd708 47#define PF_NOSTOP 0x40
45372428
MT
48
49/*ARGSUSED*/
50ptsopen(dev, flag)
73c77d38 51 dev_t dev;
e1d74936 52{
45372428
MT
53 register struct tty *tp;
54
f21c8fb8
BJ
55 if (minor(dev) >= NPTY)
56 return (ENXIO);
45372428 57 tp = &pt_tty[minor(dev)];
941944c9 58 if ((tp->t_state & TS_ISOPEN) == 0) {
bdda6b91
BJ
59 ttychars(tp); /* Set up default chars */
60 tp->t_flags = 0; /* No features (nor raw mode) */
f21c8fb8
BJ
61 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
62 return (EBUSY);
e1d74936 63 if (tp->t_oproc) /* Ctrlr still around. */
941944c9
BJ
64 tp->t_state |= TS_CARR_ON;
65 while ((tp->t_state & TS_CARR_ON) == 0) {
66 tp->t_state |= TS_WOPEN;
45372428
MT
67 sleep((caddr_t)&tp->t_rawq, TTIPRI);
68 }
f21c8fb8 69 return ((*linesw[tp->t_line].l_open)(dev, tp));
45372428
MT
70}
71
72ptsclose(dev)
73c77d38 73 dev_t dev;
941944c9 74{
45372428
MT
75 register struct tty *tp;
76
77 tp = &pt_tty[minor(dev)];
78 (*linesw[tp->t_line].l_close)(tp);
4b39cb77 79 ttyclose(tp);
45372428
MT
80}
81
ae9a0a69 82ptsread(dev, uio)
73c77d38 83 dev_t dev;
ae9a0a69 84 struct uio *uio;
e1d74936 85{
defdbcd1
BJ
86 register struct tty *tp = &pt_tty[minor(dev)];
87 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 88 int error = 0;
defdbcd1
BJ
89
90again:
91 if (pti->pt_flags & PF_REMOTE) {
92 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
93 if (u.u_signal[SIGTTIN] == SIG_IGN ||
94 u.u_signal[SIGTTIN] == SIG_HOLD ||
95 /*
96 (u.u_procp->p_flag&SDETACH) ||
97 */
98 u.u_procp->p_flag&SVFORK)
840510a3 99 return (EIO);
defdbcd1
BJ
100 gsignal(u.u_procp->p_pgrp, SIGTTIN);
101 sleep((caddr_t)&lbolt, TTIPRI);
941944c9 102 }
defdbcd1 103 if (tp->t_rawq.c_cc == 0) {
840510a3
BJ
104 if (tp->t_state & TS_NBIO)
105 return (EWOULDBLOCK);
defdbcd1
BJ
106 sleep((caddr_t)&tp->t_rawq, TTIPRI);
107 goto again;
108 }
ae9a0a69
BJ
109 while (tp->t_rawq.c_cc > 1 && uio->uio_resid > 0)
110 if (ureadc(getc(&tp->t_rawq), uio) < 0) {
840510a3 111 error = EFAULT;
ae9a0a69
BJ
112 break;
113 }
defdbcd1
BJ
114 if (tp->t_rawq.c_cc == 1)
115 (void) getc(&tp->t_rawq);
116 if (tp->t_rawq.c_cc)
840510a3 117 return (error);
defdbcd1
BJ
118 } else
119 if (tp->t_oproc)
840510a3 120 error = (*linesw[tp->t_line].l_read)(tp, uio);
defdbcd1
BJ
121 wakeup((caddr_t)&tp->t_rawq.c_cf);
122 if (pti->pt_selw) {
123 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
124 pti->pt_selw = 0;
125 pti->pt_flags &= ~PF_WCOLL;
45372428 126 }
840510a3 127 return (error);
45372428
MT
128}
129
941944c9
BJ
130/*
131 * Write to pseudo-tty.
132 * Wakeups of controlling tty will happen
133 * indirectly, when tty driver calls ptsstart.
134 */
ae9a0a69 135ptswrite(dev, uio)
73c77d38 136 dev_t dev;
ae9a0a69 137 struct uio *uio;
e1d74936 138{
45372428
MT
139 register struct tty *tp;
140
141 tp = &pt_tty[minor(dev)];
840510a3
BJ
142 if (tp->t_oproc == 0)
143 return (EIO);
144 return ((*linesw[tp->t_line].l_write)(tp, uio));
45372428
MT
145}
146
941944c9
BJ
147/*
148 * Start output on pseudo-tty.
149 * Wake up process selecting or sleeping for input from controlling tty.
150 */
45372428 151ptsstart(tp)
e1d74936
BJ
152 struct tty *tp;
153{
1e6d24b1 154 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
e1d74936 155
941944c9 156 if (tp->t_state & TS_TTSTOP)
45372428 157 return;
1e6d24b1
BJ
158 if (pti->pt_flags & PF_STOPPED) {
159 pti->pt_flags &= ~PF_STOPPED;
160 pti->pt_send = TIOCPKT_START;
161 }
d427b3b2
BJ
162 ptcwakeup(tp);
163}
164
165ptcwakeup(tp)
166 struct tty *tp;
167{
168 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
169
1a954a11
BJ
170 if (pti->pt_selr) {
171 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
172 pti->pt_selr = 0;
173 pti->pt_flags &= ~PF_RCOLL;
e1d74936 174 }
45372428
MT
175 wakeup((caddr_t)&tp->t_outq.c_cf);
176}
177
178/*ARGSUSED*/
179ptcopen(dev, flag)
e1d74936
BJ
180 dev_t dev;
181 int flag;
182{
45372428 183 register struct tty *tp;
1a954a11 184 struct pt_ioctl *pti;
45372428 185
f21c8fb8
BJ
186 if (minor(dev) >= NPTY)
187 return (ENXIO);
45372428 188 tp = &pt_tty[minor(dev)];
f21c8fb8
BJ
189 if (tp->t_oproc)
190 return (EIO);
e1d74936 191 tp->t_oproc = ptsstart;
941944c9 192 if (tp->t_state & TS_WOPEN)
45372428 193 wakeup((caddr_t)&tp->t_rawq);
941944c9 194 tp->t_state |= TS_CARR_ON;
1a954a11
BJ
195 pti = &pt_ioctl[minor(dev)];
196 pti->pt_flags = 0;
197 pti->pt_send = 0;
f21c8fb8 198 return (0);
45372428
MT
199}
200
201ptcclose(dev)
e1d74936
BJ
202 dev_t dev;
203{
45372428
MT
204 register struct tty *tp;
205
206 tp = &pt_tty[minor(dev)];
941944c9 207 if (tp->t_state & TS_ISOPEN)
45372428 208 gsignal(tp->t_pgrp, SIGHUP);
941944c9 209 tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */
e1d74936
BJ
210 flushtty(tp, FREAD|FWRITE);
211 tp->t_oproc = 0; /* mark closed */
45372428
MT
212}
213
ae9a0a69 214ptcread(dev, uio)
1a954a11 215 dev_t dev;
ae9a0a69 216 struct uio *uio;
e1d74936 217{
840510a3 218 register struct tty *tp = &pt_tty[minor(dev)];
1a954a11 219 struct pt_ioctl *pti;
840510a3 220 int error = 0;
45372428 221
941944c9 222 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
a8d3bf7f 223 return (EIO);
1a954a11
BJ
224 pti = &pt_ioctl[minor(dev)];
225 if (pti->pt_flags & PF_PKT) {
226 if (pti->pt_send) {
840510a3
BJ
227 error = ureadc(pti->pt_send, uio);
228 if (error)
229 return (error);
1a954a11 230 pti->pt_send = 0;
840510a3 231 return (0);
1a954a11 232 }
840510a3 233 error = ureadc(0, uio);
1a954a11 234 }
8b8271ac 235 while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) {
840510a3
BJ
236 if (pti->pt_flags&PF_NBIO)
237 return (EWOULDBLOCK);
45372428 238 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
8b8271ac 239 }
ae9a0a69
BJ
240 while (tp->t_outq.c_cc && uio->uio_resid > 0)
241 if (ureadc(getc(&tp->t_outq), uio) < 0) {
840510a3 242 error = EFAULT;
ae9a0a69
BJ
243 break;
244 }
941944c9
BJ
245 if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
246 if (tp->t_state&TS_ASLEEP) {
247 tp->t_state &= ~TS_ASLEEP;
248 wakeup((caddr_t)&tp->t_outq);
249 }
250 if (tp->t_wsel) {
251 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
252 tp->t_wsel = 0;
253 tp->t_state &= ~TS_WCOLL;
254 }
45372428 255 }
840510a3 256 return (error);
45372428
MT
257}
258
1a954a11
BJ
259ptsstop(tp, flush)
260 register struct tty *tp;
261 int flush;
262{
263 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
264
1e6d24b1
BJ
265 /* note: FLUSHREAD and FLUSHWRITE already ok */
266 if (flush == 0) {
267 flush = TIOCPKT_STOP;
268 pti->pt_flags |= PF_STOPPED;
269 } else {
270 pti->pt_flags &= ~PF_STOPPED;
271 }
0a2bd708 272 pti->pt_send |= flush;
d427b3b2 273 ptcwakeup(tp);
1a954a11
BJ
274}
275
941944c9 276ptcselect(dev, rw)
e1d74936 277 dev_t dev;
941944c9 278 int rw;
e1d74936
BJ
279{
280 register struct tty *tp = &pt_tty[minor(dev)];
defdbcd1 281 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
e1d74936 282 struct proc *p;
d427b3b2 283 int s;
e1d74936 284
941944c9 285 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
e1d74936 286 return (1);
d427b3b2 287 s = spl5();
941944c9
BJ
288 switch (rw) {
289
290 case FREAD:
d427b3b2
BJ
291 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
292 splx(s);
941944c9 293 return (1);
d427b3b2 294 }
1a954a11
BJ
295 if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait)
296 pti->pt_flags |= PF_RCOLL;
941944c9 297 else
1a954a11 298 pti->pt_selr = u.u_procp;
d427b3b2 299 break;
941944c9
BJ
300
301 case FWRITE:
defdbcd1 302 if ((pti->pt_flags & PF_REMOTE) == 0 || tp->t_rawq.c_cc == 0) {
d427b3b2 303 splx(s);
941944c9 304 return (1);
d427b3b2 305 }
1a954a11
BJ
306 if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait)
307 pti->pt_flags |= PF_WCOLL;
941944c9 308 else
1a954a11 309 pti->pt_selw = u.u_procp;
d427b3b2 310 break;
941944c9 311 }
d427b3b2
BJ
312 splx(s);
313 return (0);
e1d74936
BJ
314}
315
ae9a0a69 316ptcwrite(dev, uio)
941944c9 317 dev_t dev;
ae9a0a69 318 struct uio *uio;
e1d74936 319{
840510a3 320 register struct tty *tp = &pt_tty[minor(dev)];
45372428
MT
321 register char *cp, *ce;
322 register int cc;
323 char locbuf[BUFSIZ];
941944c9 324 int cnt = 0;
defdbcd1 325 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
840510a3 326 int error = 0;
45372428 327
941944c9 328 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
840510a3 329 return (EIO);
defdbcd1 330 do {
ae9a0a69
BJ
331 register struct iovec *iov;
332
333 if (uio->uio_iovcnt == 0)
334 break;
335 iov = uio->uio_iov;
336 if (iov->iov_len == 0) {
337 uio->uio_iovcnt--;
338 uio->uio_iov++;
339 if (uio->uio_iovcnt < 0)
340 panic("ptcwrite");
341 continue;
342 }
343 cc = MIN(iov->iov_len, BUFSIZ);
45372428 344 cp = locbuf;
840510a3
BJ
345 error = uiomove(cp, cc, UIO_WRITE, uio);
346 if (error)
45372428
MT
347 break;
348 ce = cp + cc;
defdbcd1
BJ
349again:
350 if (pti->pt_flags & PF_REMOTE) {
351 if (tp->t_rawq.c_cc) {
352 if (pti->pt_flags & PF_NBIO) {
ae9a0a69
BJ
353 iov->iov_base -= ce - cp;
354 iov->iov_len += ce - cp;
355 uio->uio_resid += ce - cp;
356 uio->uio_offset -= ce - cp;
840510a3 357 return (EWOULDBLOCK);
defdbcd1
BJ
358 }
359 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
360 goto again;
361 }
668cc26d
SL
362 (void) b_to_q(cp, cc, &tp->t_rawq);
363 (void) putc(0, &tp->t_rawq);
defdbcd1 364 wakeup((caddr_t)&tp->t_rawq);
840510a3 365 return (0);
defdbcd1 366 }
e1d74936
BJ
367 while (cp < ce) {
368 while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) {
45372428 369 wakeup((caddr_t)&tp->t_rawq);
941944c9 370 if (tp->t_state & TS_NBIO) {
ae9a0a69
BJ
371 iov->iov_base -= ce - cp;
372 iov->iov_len += ce - cp;
373 uio->uio_resid += ce - cp;
374 uio->uio_offset -= ce - cp;
941944c9 375 if (cnt == 0)
840510a3
BJ
376 return (EWOULDBLOCK);
377 return (0);
941944c9 378 }
45372428
MT
379 /* Better than just flushing it! */
380 /* Wait for something to be read */
381 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
defdbcd1 382 goto again;
45372428 383 }
36612a8f 384 (*linesw[tp->t_line].l_rint)(*cp++, tp);
941944c9 385 cnt++;
45372428 386 }
ae9a0a69 387 } while (uio->uio_resid);
840510a3 388 return (error);
45372428
MT
389}
390
45372428 391/*ARGSUSED*/
4b72e2f9
SL
392ptyioctl(dev, cmd, data, flag)
393 caddr_t data;
e1d74936
BJ
394 dev_t dev;
395{
0a2bd708
BJ
396 register struct tty *tp = &pt_tty[minor(dev)];
397 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
f21c8fb8 398 int error;
45372428 399
e1d74936 400 /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
4b72e2f9
SL
401 if (cdevsw[major(dev)].d_open == ptcopen)
402 switch (cmd) {
403
404 case TIOCPKT:
405 if (*(int *)data)
1a954a11
BJ
406 pti->pt_flags |= PF_PKT;
407 else
408 pti->pt_flags &= ~PF_PKT;
f21c8fb8 409 return (0);
4b72e2f9
SL
410
411 case TIOCREMOTE:
412 if (*(int *)data)
defdbcd1
BJ
413 pti->pt_flags |= PF_REMOTE;
414 else
415 pti->pt_flags &= ~PF_REMOTE;
416 flushtty(tp, FREAD|FWRITE);
f21c8fb8 417 return (0);
4b72e2f9
SL
418
419 case FIONBIO:
420 if (*(int *)data)
1a954a11 421 pti->pt_flags |= PF_NBIO;
8b8271ac 422 else
1a954a11 423 pti->pt_flags &= ~PF_NBIO;
f21c8fb8 424 return (0);
4b72e2f9
SL
425
426 case TIOCSETP:
427 while (getc(&tp->t_outq) >= 0)
428 ;
429 break;
8b8271ac 430 }
f21c8fb8
BJ
431 error = ttioctl(tp, cmd, data, dev);
432 if (error < 0)
433 error = ENOTTY;
425a48ad
SL
434 { int stop = (tp->t_stopc == ('s'&037) &&
435 tp->t_startc == ('q'&037));
0a2bd708
BJ
436 if (pti->pt_flags & PF_NOSTOP) {
437 if (stop) {
438 pti->pt_send &= TIOCPKT_NOSTOP;
439 pti->pt_send |= TIOCPKT_DOSTOP;
440 pti->pt_flags &= ~PF_NOSTOP;
441 ptcwakeup(tp);
442 }
443 } else {
444 if (stop == 0) {
445 pti->pt_send &= ~TIOCPKT_DOSTOP;
446 pti->pt_send |= TIOCPKT_NOSTOP;
447 pti->pt_flags |= PF_NOSTOP;
448 ptcwakeup(tp);
449 }
450 }
451 }
f21c8fb8 452 return (error);
45372428 453}
4f07e6e5 454#endif