1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)tty_pty.c 8.4 (Berkeley) 02/20/95
8 */
9
10 /*
11 * Pseudo-teletype Driver
12 * (Actually two drivers, requiring two entries in 'cdevsw')
13 */
14 #include "pty.h" /* XXX */
15
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <sys/ioctl.h>
19 #include <sys/proc.h>
20 #include <sys/tty.h>
21 #include <sys/conf.h>
22 #include <sys/file.h>
23 #include <sys/uio.h>
24 #include <sys/kernel.h>
25 #include <sys/vnode.h>
26
27 #if NPTY == 1
28 #undef NPTY
29 #define NPTY 32 /* crude XXX */
30 #endif
31
32 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
33
34 /*
35 * pts == /dev/tty[pqrs]?
36 * ptc == /dev/pty[pqrs]?
37 */
38 struct tty pt_tty[NPTY]; /* XXX */
39 struct pt_ioctl {
40 int pt_flags;
41 struct selinfo pt_selr, pt_selw;
42 u_char pt_send;
43 u_char pt_ucntl;
44 } pt_ioctl[NPTY]; /* XXX */
45 int npty = NPTY; /* for pstat -t */
46
47 #define PF_PKT 0x08 /* packet mode */
48 #define PF_STOPPED 0x10 /* user told stopped */
49 #define PF_REMOTE 0x20 /* remote and flow controlled input */
50 #define PF_NOSTOP 0x40
51 #define PF_UCNTL 0x80 /* user control mode */
52
53 void ptsstop __P((struct tty *, int));
54
55 /*
56 * Establish n (or default if n is 1) ptys in the system.
57 *
58 * XXX cdevsw & pstat require the array `pty[]' to be an array
59 */
60 void
ptyattach(n)61 ptyattach(n)
62 int n;
63 {
64 #ifdef notyet
65 char *mem;
66 register u_long ntb;
67 #define DEFAULT_NPTY 32
68
69 /* maybe should allow 0 => none? */
70 if (n <= 1)
71 n = DEFAULT_NPTY;
72 ntb = n * sizeof(struct tty);
73 mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
74 M_DEVBUF, M_WAITOK);
75 pt_tty = (struct tty *)mem;
76 mem = (char *)ALIGN(mem + ntb);
77 pt_ioctl = (struct pt_ioctl *)mem;
78 npty = n;
79 #endif
80 }
81
82 /*ARGSUSED*/
ptsopen(dev,flag,devtype,p)83 ptsopen(dev, flag, devtype, p)
84 dev_t dev;
85 int flag, devtype;
86 struct proc *p;
87 {
88 register struct tty *tp;
89 int error;
90
91 if (minor(dev) >= npty)
92 return (ENXIO);
93 tp = &pt_tty[minor(dev)];
94 if ((tp->t_state & TS_ISOPEN) == 0) {
95 tp->t_state |= TS_WOPEN;
96 ttychars(tp); /* Set up default chars */
97 tp->t_iflag = TTYDEF_IFLAG;
98 tp->t_oflag = TTYDEF_OFLAG;
99 tp->t_lflag = TTYDEF_LFLAG;
100 tp->t_cflag = TTYDEF_CFLAG;
101 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
102 ttsetwater(tp); /* would be done in xxparam() */
103 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
104 return (EBUSY);
105 if (tp->t_oproc) /* Ctrlr still around. */
106 tp->t_state |= TS_CARR_ON;
107 while ((tp->t_state & TS_CARR_ON) == 0) {
108 tp->t_state |= TS_WOPEN;
109 if (flag&FNONBLOCK)
110 break;
111 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
112 ttopen, 0))
113 return (error);
114 }
115 error = (*linesw[tp->t_line].l_open)(dev, tp);
116 ptcwakeup(tp, FREAD|FWRITE);
117 return (error);
118 }
119
ptsclose(dev,flag,mode,p)120 ptsclose(dev, flag, mode, p)
121 dev_t dev;
122 int flag, mode;
123 struct proc *p;
124 {
125 register struct tty *tp;
126 int err;
127
128 tp = &pt_tty[minor(dev)];
129 err = (*linesw[tp->t_line].l_close)(tp, flag);
130 err |= ttyclose(tp);
131 ptcwakeup(tp, FREAD|FWRITE);
132 return (err);
133 }
134
ptsread(dev,uio,flag)135 ptsread(dev, uio, flag)
136 dev_t dev;
137 struct uio *uio;
138 int flag;
139 {
140 struct proc *p = curproc;
141 register struct tty *tp = &pt_tty[minor(dev)];
142 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
143 int error = 0;
144
145 again:
146 if (pti->pt_flags & PF_REMOTE) {
147 while (isbackground(p, tp)) {
148 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
149 (p->p_sigmask & sigmask(SIGTTIN)) ||
150 p->p_pgrp->pg_jobc == 0 ||
151 p->p_flag & P_PPWAIT)
152 return (EIO);
153 pgsignal(p->p_pgrp, SIGTTIN, 1);
154 if (error = ttysleep(tp, (caddr_t)&lbolt,
155 TTIPRI | PCATCH, ttybg, 0))
156 return (error);
157 }
158 if (tp->t_canq.c_cc == 0) {
159 if (flag & IO_NDELAY)
160 return (EWOULDBLOCK);
161 if (error = ttysleep(tp, (caddr_t)&tp->t_canq,
162 TTIPRI | PCATCH, ttyin, 0))
163 return (error);
164 goto again;
165 }
166 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
167 if (ureadc(getc(&tp->t_canq), uio) < 0) {
168 error = EFAULT;
169 break;
170 }
171 if (tp->t_canq.c_cc == 1)
172 (void) getc(&tp->t_canq);
173 if (tp->t_canq.c_cc)
174 return (error);
175 } else
176 if (tp->t_oproc)
177 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
178 ptcwakeup(tp, FWRITE);
179 return (error);
180 }
181
182 /*
183 * Write to pseudo-tty.
184 * Wakeups of controlling tty will happen
185 * indirectly, when tty driver calls ptsstart.
186 */
ptswrite(dev,uio,flag)187 ptswrite(dev, uio, flag)
188 dev_t dev;
189 struct uio *uio;
190 int flag;
191 {
192 register struct tty *tp;
193
194 tp = &pt_tty[minor(dev)];
195 if (tp->t_oproc == 0)
196 return (EIO);
197 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
198 }
199
200 /*
201 * Start output on pseudo-tty.
202 * Wake up process selecting or sleeping for input from controlling tty.
203 */
204 void
ptsstart(tp)205 ptsstart(tp)
206 struct tty *tp;
207 {
208 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
209
210 if (tp->t_state & TS_TTSTOP)
211 return;
212 if (pti->pt_flags & PF_STOPPED) {
213 pti->pt_flags &= ~PF_STOPPED;
214 pti->pt_send = TIOCPKT_START;
215 }
216 ptcwakeup(tp, FREAD);
217 }
218
219 ptcwakeup(tp, flag)
220 struct tty *tp;
221 int flag;
222 {
223 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
224
225 if (flag & FREAD) {
226 selwakeup(&pti->pt_selr);
227 wakeup((caddr_t)&tp->t_outq.c_cf);
228 }
229 if (flag & FWRITE) {
230 selwakeup(&pti->pt_selw);
231 wakeup((caddr_t)&tp->t_rawq.c_cf);
232 }
233 }
234
235 /*ARGSUSED*/
236 #ifdef __STDC__
ptcopen(dev_t dev,int flag,int devtype,struct proc * p)237 ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
238 #else
239 ptcopen(dev, flag, devtype, p)
240 dev_t dev;
241 int flag, devtype;
242 struct proc *p;
243 #endif
244 {
245 register struct tty *tp;
246 struct pt_ioctl *pti;
247
248 if (minor(dev) >= npty)
249 return (ENXIO);
250 tp = &pt_tty[minor(dev)];
251 if (tp->t_oproc)
252 return (EIO);
253 tp->t_oproc = ptsstart;
254 #ifdef sun4c
255 tp->t_stop = ptsstop;
256 #endif
257 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
258 tp->t_lflag &= ~EXTPROC;
259 pti = &pt_ioctl[minor(dev)];
260 pti->pt_flags = 0;
261 pti->pt_send = 0;
262 pti->pt_ucntl = 0;
263 return (0);
264 }
265
ptcclose(dev)266 ptcclose(dev)
267 dev_t dev;
268 {
269 register struct tty *tp;
270
271 tp = &pt_tty[minor(dev)];
272 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
273 tp->t_state &= ~TS_CARR_ON;
274 tp->t_oproc = 0; /* mark closed */
275 tp->t_session = 0;
276 return (0);
277 }
278
ptcread(dev,uio,flag)279 ptcread(dev, uio, flag)
280 dev_t dev;
281 struct uio *uio;
282 int flag;
283 {
284 register struct tty *tp = &pt_tty[minor(dev)];
285 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
286 char buf[BUFSIZ];
287 int error = 0, cc;
288
289 /*
290 * We want to block until the slave
291 * is open, and there's something to read;
292 * but if we lost the slave or we're NBIO,
293 * then return the appropriate error instead.
294 */
295 for (;;) {
296 if (tp->t_state&TS_ISOPEN) {
297 if (pti->pt_flags&PF_PKT && pti->pt_send) {
298 error = ureadc((int)pti->pt_send, uio);
299 if (error)
300 return (error);
301 if (pti->pt_send & TIOCPKT_IOCTL) {
302 cc = min(uio->uio_resid,
303 sizeof(tp->t_termios));
304 uiomove(&tp->t_termios, cc, uio);
305 }
306 pti->pt_send = 0;
307 return (0);
308 }
309 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
310 error = ureadc((int)pti->pt_ucntl, uio);
311 if (error)
312 return (error);
313 pti->pt_ucntl = 0;
314 return (0);
315 }
316 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
317 break;
318 }
319 if ((tp->t_state&TS_CARR_ON) == 0)
320 return (0); /* EOF */
321 if (flag & IO_NDELAY)
322 return (EWOULDBLOCK);
323 if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
324 ttyin, 0))
325 return (error);
326 }
327 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
328 error = ureadc(0, uio);
329 while (uio->uio_resid > 0 && error == 0) {
330 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
331 if (cc <= 0)
332 break;
333 error = uiomove(buf, cc, uio);
334 }
335 if (tp->t_outq.c_cc <= tp->t_lowat) {
336 if (tp->t_state&TS_ASLEEP) {
337 tp->t_state &= ~TS_ASLEEP;
338 wakeup((caddr_t)&tp->t_outq);
339 }
340 selwakeup(&tp->t_wsel);
341 }
342 return (error);
343 }
344
345 void
ptsstop(tp,flush)346 ptsstop(tp, flush)
347 register struct tty *tp;
348 int flush;
349 {
350 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
351 int flag;
352
353 /* note: FLUSHREAD and FLUSHWRITE already ok */
354 if (flush == 0) {
355 flush = TIOCPKT_STOP;
356 pti->pt_flags |= PF_STOPPED;
357 } else
358 pti->pt_flags &= ~PF_STOPPED;
359 pti->pt_send |= flush;
360 /* change of perspective */
361 flag = 0;
362 if (flush & FREAD)
363 flag |= FWRITE;
364 if (flush & FWRITE)
365 flag |= FREAD;
366 ptcwakeup(tp, flag);
367 }
368
ptcselect(dev,rw,p)369 ptcselect(dev, rw, p)
370 dev_t dev;
371 int rw;
372 struct proc *p;
373 {
374 register struct tty *tp = &pt_tty[minor(dev)];
375 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
376 int s;
377
378 if ((tp->t_state&TS_CARR_ON) == 0)
379 return (1);
380 switch (rw) {
381
382 case FREAD:
383 /*
384 * Need to block timeouts (ttrstart).
385 */
386 s = spltty();
387 if ((tp->t_state&TS_ISOPEN) &&
388 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
389 splx(s);
390 return (1);
391 }
392 splx(s);
393 /* FALLTHROUGH */
394
395 case 0: /* exceptional */
396 if ((tp->t_state&TS_ISOPEN) &&
397 (pti->pt_flags&PF_PKT && pti->pt_send ||
398 pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
399 return (1);
400 selrecord(p, &pti->pt_selr);
401 break;
402
403
404 case FWRITE:
405 if (tp->t_state&TS_ISOPEN) {
406 if (pti->pt_flags & PF_REMOTE) {
407 if (tp->t_canq.c_cc == 0)
408 return (1);
409 } else {
410 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
411 return (1);
412 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
413 return (1);
414 }
415 }
416 selrecord(p, &pti->pt_selw);
417 break;
418
419 }
420 return (0);
421 }
422
ptcwrite(dev,uio,flag)423 ptcwrite(dev, uio, flag)
424 dev_t dev;
425 register struct uio *uio;
426 int flag;
427 {
428 register struct tty *tp = &pt_tty[minor(dev)];
429 register u_char *cp;
430 register int cc = 0;
431 u_char locbuf[BUFSIZ];
432 int cnt = 0;
433 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
434 int error = 0;
435
436 again:
437 if ((tp->t_state&TS_ISOPEN) == 0)
438 goto block;
439 if (pti->pt_flags & PF_REMOTE) {
440 if (tp->t_canq.c_cc)
441 goto block;
442 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
443 if (cc == 0) {
444 cc = min(uio->uio_resid, BUFSIZ);
445 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
446 cp = locbuf;
447 error = uiomove((caddr_t)cp, cc, uio);
448 if (error)
449 return (error);
450 /* check again for safety */
451 if ((tp->t_state&TS_ISOPEN) == 0)
452 return (EIO);
453 }
454 if (cc)
455 (void) b_to_q((char *)cp, cc, &tp->t_canq);
456 cc = 0;
457 }
458 (void) putc(0, &tp->t_canq);
459 ttwakeup(tp);
460 wakeup((caddr_t)&tp->t_canq);
461 return (0);
462 }
463 while (uio->uio_resid > 0) {
464 if (cc == 0) {
465 cc = min(uio->uio_resid, BUFSIZ);
466 cp = locbuf;
467 error = uiomove((caddr_t)cp, cc, uio);
468 if (error)
469 return (error);
470 /* check again for safety */
471 if ((tp->t_state&TS_ISOPEN) == 0)
472 return (EIO);
473 }
474 while (cc > 0) {
475 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
476 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
477 wakeup((caddr_t)&tp->t_rawq);
478 goto block;
479 }
480 (*linesw[tp->t_line].l_rint)(*cp++, tp);
481 cnt++;
482 cc--;
483 }
484 cc = 0;
485 }
486 return (0);
487 block:
488 /*
489 * Come here to wait for slave to open, for space
490 * in outq, or space in rawq.
491 */
492 if ((tp->t_state&TS_CARR_ON) == 0)
493 return (EIO);
494 if (flag & IO_NDELAY) {
495 /* adjust for data copied in but not written */
496 uio->uio_resid += cc;
497 if (cnt == 0)
498 return (EWOULDBLOCK);
499 return (0);
500 }
501 if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
502 ttyout, 0)) {
503 /* adjust for data copied in but not written */
504 uio->uio_resid += cc;
505 return (error);
506 }
507 goto again;
508 }
509
510 /*ARGSUSED*/
ptyioctl(dev,cmd,data,flag,p)511 ptyioctl(dev, cmd, data, flag, p)
512 dev_t dev;
513 u_long cmd;
514 caddr_t data;
515 int flag;
516 struct proc *p;
517 {
518 register struct tty *tp = &pt_tty[minor(dev)];
519 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
520 register u_char *cc = tp->t_cc;
521 int stop, error;
522
523 /*
524 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
525 * ttywflush(tp) will hang if there are characters in the outq.
526 */
527 if (cmd == TIOCEXT) {
528 /*
529 * When the EXTPROC bit is being toggled, we need
530 * to send an TIOCPKT_IOCTL if the packet driver
531 * is turned on.
532 */
533 if (*(int *)data) {
534 if (pti->pt_flags & PF_PKT) {
535 pti->pt_send |= TIOCPKT_IOCTL;
536 ptcwakeup(tp, FREAD);
537 }
538 tp->t_lflag |= EXTPROC;
539 } else {
540 if ((tp->t_lflag & EXTPROC) &&
541 (pti->pt_flags & PF_PKT)) {
542 pti->pt_send |= TIOCPKT_IOCTL;
543 ptcwakeup(tp, FREAD);
544 }
545 tp->t_lflag &= ~EXTPROC;
546 }
547 return(0);
548 } else
549 if (cdevsw[major(dev)].d_open == ptcopen)
550 switch (cmd) {
551
552 case TIOCGPGRP:
553 /*
554 * We aviod calling ttioctl on the controller since,
555 * in that case, tp must be the controlling terminal.
556 */
557 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
558 return (0);
559
560 case TIOCPKT:
561 if (*(int *)data) {
562 if (pti->pt_flags & PF_UCNTL)
563 return (EINVAL);
564 pti->pt_flags |= PF_PKT;
565 } else
566 pti->pt_flags &= ~PF_PKT;
567 return (0);
568
569 case TIOCUCNTL:
570 if (*(int *)data) {
571 if (pti->pt_flags & PF_PKT)
572 return (EINVAL);
573 pti->pt_flags |= PF_UCNTL;
574 } else
575 pti->pt_flags &= ~PF_UCNTL;
576 return (0);
577
578 case TIOCREMOTE:
579 if (*(int *)data)
580 pti->pt_flags |= PF_REMOTE;
581 else
582 pti->pt_flags &= ~PF_REMOTE;
583 ttyflush(tp, FREAD|FWRITE);
584 return (0);
585
586 #ifdef COMPAT_43
587 case TIOCSETP:
588 case TIOCSETN:
589 #endif
590 case TIOCSETD:
591 case TIOCSETA:
592 case TIOCSETAW:
593 case TIOCSETAF:
594 ndflush(&tp->t_outq, tp->t_outq.c_cc);
595 break;
596
597 case TIOCSIG:
598 if (*(unsigned int *)data >= NSIG)
599 return(EINVAL);
600 if ((tp->t_lflag&NOFLSH) == 0)
601 ttyflush(tp, FREAD|FWRITE);
602 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
603 if ((*(unsigned int *)data == SIGINFO) &&
604 ((tp->t_lflag&NOKERNINFO) == 0))
605 ttyinfo(tp);
606 return(0);
607 }
608 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
609 if (error < 0)
610 error = ttioctl(tp, cmd, data, flag);
611 if (error < 0) {
612 if (pti->pt_flags & PF_UCNTL &&
613 (cmd & ~0xff) == UIOCCMD(0)) {
614 if (cmd & 0xff) {
615 pti->pt_ucntl = (u_char)cmd;
616 ptcwakeup(tp, FREAD);
617 }
618 return (0);
619 }
620 error = ENOTTY;
621 }
622 /*
623 * If external processing and packet mode send ioctl packet.
624 */
625 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
626 switch(cmd) {
627 case TIOCSETA:
628 case TIOCSETAW:
629 case TIOCSETAF:
630 #ifdef COMPAT_43
631 case TIOCSETP:
632 case TIOCSETN:
633 #endif
634 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
635 case TIOCSETC:
636 case TIOCSLTC:
637 case TIOCLBIS:
638 case TIOCLBIC:
639 case TIOCLSET:
640 #endif
641 pti->pt_send |= TIOCPKT_IOCTL;
642 ptcwakeup(tp, FREAD);
643 default:
644 break;
645 }
646 }
647 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
648 && CCEQ(cc[VSTART], CTRL('q'));
649 if (pti->pt_flags & PF_NOSTOP) {
650 if (stop) {
651 pti->pt_send &= ~TIOCPKT_NOSTOP;
652 pti->pt_send |= TIOCPKT_DOSTOP;
653 pti->pt_flags &= ~PF_NOSTOP;
654 ptcwakeup(tp, FREAD);
655 }
656 } else {
657 if (!stop) {
658 pti->pt_send &= ~TIOCPKT_DOSTOP;
659 pti->pt_send |= TIOCPKT_NOSTOP;
660 pti->pt_flags |= PF_NOSTOP;
661 ptcwakeup(tp, FREAD);
662 }
663 }
664 return (error);
665 }
666