xref: /csrg-svn/sys/kern/tty_pty.c (revision 5408)
1*5408Swnj /*	tty_pty.c	4.12	82/01/14	*/
22283Stoy 
32281Stoy /*
42281Stoy  * Pseudo-teletype Driver
52281Stoy  * (Actually two drivers, requiring two entries in 'cdevsw')
62281Stoy  */
72314Stoy #include "pty.h"
82314Stoy 
93206Swnj #if NPTY > 0
102281Stoy #include "../h/param.h"
112281Stoy #include "../h/systm.h"
122281Stoy #include "../h/tty.h"
132281Stoy #include "../h/dir.h"
142281Stoy #include "../h/user.h"
152281Stoy #include "../h/conf.h"
162281Stoy #include "../h/buf.h"
172427Swnj #include "../h/file.h"
184484Swnj #include "../h/proc.h"
19*5408Swnj #undef	NPTY
202281Stoy 
214484Swnj #define NPTY 16
224484Swnj 
232427Swnj #define BUFSIZ 100		/* Chunk size iomoved from user */
244484Swnj 
252281Stoy /*
264484Swnj  * pts == /dev/tty[pP]?
274484Swnj  * ptc == /dev/ptp[pP]?
282281Stoy  */
294484Swnj struct	tty pt_tty[NPTY];
304484Swnj struct	pt_ioctl {
314484Swnj 	int	pti_flags;
324484Swnj 	struct	clist pti_ioctl, pti_ioans;
334484Swnj 	int	pti_gensym;
34*5408Swnj 	struct	proc *pti_selr, *pti_selw;
354484Swnj } pt_ioctl[NPTY];
362281Stoy 
374484Swnj #define	PTCRCOLL	0x01
38*5408Swnj #define	PTCWCOLL	0x02
392281Stoy 
402281Stoy /*ARGSUSED*/
412281Stoy ptsopen(dev, flag)
425396Sroot 	dev_t dev;
434484Swnj {
442281Stoy 	register struct tty *tp;
452281Stoy 
464484Swnj 	if (minor(dev) >= NPTY) {
472281Stoy 		u.u_error = ENXIO;
482281Stoy 		return;
492281Stoy 	}
502281Stoy 	tp = &pt_tty[minor(dev)];
51*5408Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
522427Swnj 		ttychars(tp);		/* Set up default chars */
532427Swnj 		tp->t_flags = 0;	/* No features (nor raw mode) */
54*5408Swnj 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {
552281Stoy 		u.u_error = EBUSY;
562281Stoy 		return;
572281Stoy 	}
584484Swnj 	if (tp->t_oproc)			/* Ctrlr still around. */
59*5408Swnj 		tp->t_state |= TS_CARR_ON;
60*5408Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
61*5408Swnj 		tp->t_state |= TS_WOPEN;
622281Stoy 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
632281Stoy 	}
642281Stoy 	(*linesw[tp->t_line].l_open)(dev, tp);
652281Stoy }
662281Stoy 
672281Stoy ptsclose(dev)
685396Sroot 	dev_t dev;
69*5408Swnj {
702281Stoy 	register struct tty *tp;
712281Stoy 
722281Stoy 	tp = &pt_tty[minor(dev)];
732281Stoy 	(*linesw[tp->t_line].l_close)(tp);
742281Stoy }
752281Stoy 
762281Stoy ptsread(dev)
775396Sroot 	dev_t dev;
784484Swnj {
794484Swnj 	register struct tty *tp;
80*5408Swnj 	register struct pt_ioctl *pti;
812281Stoy 
822281Stoy 	tp = &pt_tty[minor(dev)];
834484Swnj 	if (tp->t_oproc) {
842281Stoy 		(*linesw[tp->t_line].l_read)(tp);
852281Stoy 		wakeup((caddr_t)&tp->t_rawq.c_cf);
86*5408Swnj 		if (tp->t_rawq.c_cc < TTYHOG/2 &&
87*5408Swnj 		    (pti = &pt_ioctl[minor(tp->t_dev)])->pti_selw) {
88*5408Swnj 			selwakeup(pti->pti_selw, pti->pti_flags & PTCWCOLL);
89*5408Swnj 			pti->pti_selw = 0;
90*5408Swnj 			pti->pti_flags &= ~PTCWCOLL;
91*5408Swnj 		}
922281Stoy 	}
932281Stoy }
942281Stoy 
95*5408Swnj /*
96*5408Swnj  * Write to pseudo-tty.
97*5408Swnj  * Wakeups of controlling tty will happen
98*5408Swnj  * indirectly, when tty driver calls ptsstart.
99*5408Swnj  */
1002281Stoy ptswrite(dev)
1015396Sroot 	dev_t dev;
1024484Swnj {
1032281Stoy 	register struct tty *tp;
1042281Stoy 
1052281Stoy 	tp = &pt_tty[minor(dev)];
1064484Swnj 	if (tp->t_oproc)
1072281Stoy 		(*linesw[tp->t_line].l_write)(tp);
1082281Stoy }
1092281Stoy 
110*5408Swnj /*
111*5408Swnj  * Start output on pseudo-tty.
112*5408Swnj  * Wake up process selecting or sleeping for input from controlling tty.
113*5408Swnj  */
1142281Stoy ptsstart(tp)
1154484Swnj 	struct tty *tp;
1164484Swnj {
1174484Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
1184484Swnj 
119*5408Swnj 	if (tp->t_state & TS_TTSTOP)
1202281Stoy 		return;
1214484Swnj 	if (pti->pti_selr) {
1224484Swnj 		selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL);
1234484Swnj 		pti->pti_selr = 0;
1244484Swnj 		pti->pti_flags &= ~PTCRCOLL;
1254484Swnj 	}
1262281Stoy 	wakeup((caddr_t)&tp->t_outq.c_cf);
1272281Stoy }
1282281Stoy 
1292281Stoy /*ARGSUSED*/
1302281Stoy ptcopen(dev, flag)
1314484Swnj 	dev_t dev;
1324484Swnj 	int flag;
1334484Swnj {
1342281Stoy 	register struct tty *tp;
1352281Stoy 
1364484Swnj 	if (minor(dev) >= NPTY) {
1372281Stoy 		u.u_error = ENXIO;
1382281Stoy 		return;
1392281Stoy 	}
1402281Stoy 	tp = &pt_tty[minor(dev)];
1414484Swnj 	if (tp->t_oproc) {
1422281Stoy 		u.u_error = EIO;
1432281Stoy 		return;
1442281Stoy 	}
1454484Swnj 	tp->t_oproc = ptsstart;
146*5408Swnj 	if (tp->t_state & TS_WOPEN)
1472281Stoy 		wakeup((caddr_t)&tp->t_rawq);
148*5408Swnj 	tp->t_state |= TS_CARR_ON;
1492281Stoy }
1502281Stoy 
1512281Stoy ptcclose(dev)
1524484Swnj 	dev_t dev;
1534484Swnj {
1542281Stoy 	register struct tty *tp;
1552281Stoy 
1562281Stoy 	tp = &pt_tty[minor(dev)];
157*5408Swnj 	if (tp->t_state & TS_ISOPEN)
1582281Stoy 		gsignal(tp->t_pgrp, SIGHUP);
159*5408Swnj 	tp->t_state &= ~TS_CARR_ON;	/* virtual carrier gone */
1604484Swnj 	flushtty(tp, FREAD|FWRITE);
1614484Swnj 	tp->t_oproc = 0;		/* mark closed */
1622281Stoy }
1632281Stoy 
1642281Stoy ptcread(dev)
1652281Stoy dev_t dev;
1664484Swnj {
1672281Stoy 	register struct tty *tp;
1682281Stoy 
1692281Stoy 	tp = &pt_tty[minor(dev)];
170*5408Swnj 	if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
1712281Stoy 		return;
172*5408Swnj 	while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP))
1732281Stoy 		sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
174*5408Swnj 	while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0)
175*5408Swnj 		;
176*5408Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
177*5408Swnj 		if (tp->t_state&TS_ASLEEP) {
178*5408Swnj 			tp->t_state &= ~TS_ASLEEP;
179*5408Swnj 			wakeup((caddr_t)&tp->t_outq);
180*5408Swnj 		}
181*5408Swnj 		if (tp->t_wsel) {
182*5408Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
183*5408Swnj 			tp->t_wsel = 0;
184*5408Swnj 			tp->t_state &= ~TS_WCOLL;
185*5408Swnj 		}
1862281Stoy 	}
1872281Stoy }
1882281Stoy 
189*5408Swnj ptcselect(dev, rw)
1904484Swnj 	dev_t dev;
191*5408Swnj 	int rw;
1924484Swnj {
1934484Swnj 	register struct tty *tp = &pt_tty[minor(dev)];
1944484Swnj 	struct pt_ioctl *pti;
1954484Swnj 	struct proc *p;
1964484Swnj 
197*5408Swnj 	if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
1984484Swnj 		return (1);
199*5408Swnj 	switch (rw) {
200*5408Swnj 
201*5408Swnj 	case FREAD:
202*5408Swnj 		if (tp->t_outq.c_cc)
203*5408Swnj 			return (1);
204*5408Swnj 		pti = &pt_ioctl[minor(dev)];
205*5408Swnj 		if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait)
206*5408Swnj 			pti->pti_flags |= PTCRCOLL;
207*5408Swnj 		else
208*5408Swnj 			pti->pti_selr = u.u_procp;
209*5408Swnj 		return (0);
210*5408Swnj 
211*5408Swnj 	case FWRITE:
212*5408Swnj 		if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG/2)
213*5408Swnj 			return (1);
214*5408Swnj 		pti = &pt_ioctl[minor(dev)];
215*5408Swnj 		if ((p = pti->pti_selw) && p->p_wchan == (caddr_t)&selwait)
216*5408Swnj 			pti->pti_flags |= PTCWCOLL;
217*5408Swnj 		else
218*5408Swnj 			pti->pti_selw = u.u_procp;
219*5408Swnj 	}
2205396Sroot }
2214484Swnj 
2222281Stoy ptcwrite(dev)
223*5408Swnj 	dev_t dev;
2244484Swnj {
2252281Stoy 	register struct tty *tp;
2262281Stoy 	register char *cp, *ce;
2272281Stoy 	register int cc;
2282281Stoy 	char locbuf[BUFSIZ];
229*5408Swnj 	int cnt = 0;
2302281Stoy 
2312281Stoy 	tp = &pt_tty[minor(dev)];
232*5408Swnj 	if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0)
2332281Stoy 		return;
2344484Swnj 	while (u.u_count) {
2352281Stoy 		cc = MIN(u.u_count, BUFSIZ);
2362281Stoy 		cp = locbuf;
2372281Stoy 		iomove(cp, (unsigned)cc, B_WRITE);
2384484Swnj 		if (u.u_error)
2392281Stoy 			break;
2402281Stoy 		ce = cp + cc;
2414484Swnj 		while (cp < ce) {
2424484Swnj 			while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) {
2432281Stoy 				wakeup((caddr_t)&tp->t_rawq);
244*5408Swnj 				if (tp->t_state & TS_NBIO) {
245*5408Swnj 					u.u_count += ce - cp;
246*5408Swnj 					if (cnt == 0)
247*5408Swnj 						u.u_error = EWOULDBLOCK;
248*5408Swnj 					return;
249*5408Swnj 				}
2502281Stoy 				/* Better than just flushing it! */
2512281Stoy 				/* Wait for something to be read */
2522281Stoy 				sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
2532281Stoy 			}
2544141Secc 			(*linesw[tp->t_line].l_rint)(*cp++, tp);
255*5408Swnj 			cnt++;
2562281Stoy 		}
2572281Stoy 	}
2582281Stoy }
2592281Stoy 
2602281Stoy /*ARGSUSED*/
2612281Stoy ptyioctl(dev, cmd, addr, flag)
2624484Swnj 	caddr_t addr;
2634484Swnj 	dev_t dev;
2644484Swnj {
2652281Stoy 	register struct tty *tp;
2662281Stoy 
2672281Stoy 	tp = &pt_tty[minor(dev)];
2684484Swnj 	/* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
2694484Swnj 	if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP)
2704484Swnj 		while (getc(&tp->t_outq) >= 0);
2714484Swnj 	if (ttioctl(tp, cmd, addr, dev) == 0)
2722281Stoy 		u.u_error = ENOTTY;
2732281Stoy }
2742313Stoy #endif
275