1*5411Swnj /* tty_pty.c 4.13 82/01/15 */ 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" 195408Swnj #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; 345408Swnj struct proc *pti_selr, *pti_selw; 354484Swnj } pt_ioctl[NPTY]; 362281Stoy 374484Swnj #define PTCRCOLL 0x01 385408Swnj #define PTCWCOLL 0x02 39*5411Swnj #define PTCNBIO 0x04 402281Stoy 412281Stoy /*ARGSUSED*/ 422281Stoy ptsopen(dev, flag) 435396Sroot dev_t dev; 444484Swnj { 452281Stoy register struct tty *tp; 462281Stoy 474484Swnj if (minor(dev) >= NPTY) { 482281Stoy u.u_error = ENXIO; 492281Stoy return; 502281Stoy } 512281Stoy tp = &pt_tty[minor(dev)]; 525408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 532427Swnj ttychars(tp); /* Set up default chars */ 542427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 555408Swnj } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { 562281Stoy u.u_error = EBUSY; 572281Stoy return; 582281Stoy } 594484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 605408Swnj tp->t_state |= TS_CARR_ON; 615408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 625408Swnj tp->t_state |= TS_WOPEN; 632281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 642281Stoy } 652281Stoy (*linesw[tp->t_line].l_open)(dev, tp); 662281Stoy } 672281Stoy 682281Stoy ptsclose(dev) 695396Sroot dev_t dev; 705408Swnj { 712281Stoy register struct tty *tp; 722281Stoy 732281Stoy tp = &pt_tty[minor(dev)]; 742281Stoy (*linesw[tp->t_line].l_close)(tp); 752281Stoy } 762281Stoy 772281Stoy ptsread(dev) 785396Sroot dev_t dev; 794484Swnj { 804484Swnj register struct tty *tp; 815408Swnj register struct pt_ioctl *pti; 822281Stoy 832281Stoy tp = &pt_tty[minor(dev)]; 844484Swnj if (tp->t_oproc) { 852281Stoy (*linesw[tp->t_line].l_read)(tp); 862281Stoy wakeup((caddr_t)&tp->t_rawq.c_cf); 875408Swnj if (tp->t_rawq.c_cc < TTYHOG/2 && 885408Swnj (pti = &pt_ioctl[minor(tp->t_dev)])->pti_selw) { 895408Swnj selwakeup(pti->pti_selw, pti->pti_flags & PTCWCOLL); 905408Swnj pti->pti_selw = 0; 915408Swnj pti->pti_flags &= ~PTCWCOLL; 925408Swnj } 932281Stoy } 942281Stoy } 952281Stoy 965408Swnj /* 975408Swnj * Write to pseudo-tty. 985408Swnj * Wakeups of controlling tty will happen 995408Swnj * indirectly, when tty driver calls ptsstart. 1005408Swnj */ 1012281Stoy ptswrite(dev) 1025396Sroot dev_t dev; 1034484Swnj { 1042281Stoy register struct tty *tp; 1052281Stoy 1062281Stoy tp = &pt_tty[minor(dev)]; 1074484Swnj if (tp->t_oproc) 1082281Stoy (*linesw[tp->t_line].l_write)(tp); 1092281Stoy } 1102281Stoy 1115408Swnj /* 1125408Swnj * Start output on pseudo-tty. 1135408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1145408Swnj */ 1152281Stoy ptsstart(tp) 1164484Swnj struct tty *tp; 1174484Swnj { 1184484Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1194484Swnj 1205408Swnj if (tp->t_state & TS_TTSTOP) 1212281Stoy return; 1224484Swnj if (pti->pti_selr) { 1234484Swnj selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL); 1244484Swnj pti->pti_selr = 0; 1254484Swnj pti->pti_flags &= ~PTCRCOLL; 1264484Swnj } 1272281Stoy wakeup((caddr_t)&tp->t_outq.c_cf); 1282281Stoy } 1292281Stoy 1302281Stoy /*ARGSUSED*/ 1312281Stoy ptcopen(dev, flag) 1324484Swnj dev_t dev; 1334484Swnj int flag; 1344484Swnj { 1352281Stoy register struct tty *tp; 1362281Stoy 1374484Swnj if (minor(dev) >= NPTY) { 1382281Stoy u.u_error = ENXIO; 1392281Stoy return; 1402281Stoy } 1412281Stoy tp = &pt_tty[minor(dev)]; 1424484Swnj if (tp->t_oproc) { 1432281Stoy u.u_error = EIO; 1442281Stoy return; 1452281Stoy } 1464484Swnj tp->t_oproc = ptsstart; 1475408Swnj if (tp->t_state & TS_WOPEN) 1482281Stoy wakeup((caddr_t)&tp->t_rawq); 1495408Swnj tp->t_state |= TS_CARR_ON; 1502281Stoy } 1512281Stoy 1522281Stoy ptcclose(dev) 1534484Swnj dev_t dev; 1544484Swnj { 1552281Stoy register struct tty *tp; 1562281Stoy 1572281Stoy tp = &pt_tty[minor(dev)]; 1585408Swnj if (tp->t_state & TS_ISOPEN) 1592281Stoy gsignal(tp->t_pgrp, SIGHUP); 1605408Swnj tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ 1614484Swnj flushtty(tp, FREAD|FWRITE); 1624484Swnj tp->t_oproc = 0; /* mark closed */ 1632281Stoy } 1642281Stoy 1652281Stoy ptcread(dev) 1662281Stoy dev_t dev; 1674484Swnj { 1682281Stoy register struct tty *tp; 1692281Stoy 1702281Stoy tp = &pt_tty[minor(dev)]; 1715408Swnj if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 1722281Stoy return; 173*5411Swnj while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) { 174*5411Swnj if (pt_ioctl[minor(dev)].pti_flags&PTCNBIO) { 175*5411Swnj u.u_error = EWOULDBLOCK; 176*5411Swnj return; 177*5411Swnj } 1782281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 179*5411Swnj } 1805408Swnj while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0) 1815408Swnj ; 1825408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 1835408Swnj if (tp->t_state&TS_ASLEEP) { 1845408Swnj tp->t_state &= ~TS_ASLEEP; 1855408Swnj wakeup((caddr_t)&tp->t_outq); 1865408Swnj } 1875408Swnj if (tp->t_wsel) { 1885408Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 1895408Swnj tp->t_wsel = 0; 1905408Swnj tp->t_state &= ~TS_WCOLL; 1915408Swnj } 1922281Stoy } 1932281Stoy } 1942281Stoy 1955408Swnj ptcselect(dev, rw) 1964484Swnj dev_t dev; 1975408Swnj int rw; 1984484Swnj { 1994484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 2004484Swnj struct pt_ioctl *pti; 2014484Swnj struct proc *p; 2024484Swnj 2035408Swnj if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 2044484Swnj return (1); 2055408Swnj switch (rw) { 2065408Swnj 2075408Swnj case FREAD: 2085408Swnj if (tp->t_outq.c_cc) 2095408Swnj return (1); 2105408Swnj pti = &pt_ioctl[minor(dev)]; 2115408Swnj if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait) 2125408Swnj pti->pti_flags |= PTCRCOLL; 2135408Swnj else 2145408Swnj pti->pti_selr = u.u_procp; 2155408Swnj return (0); 2165408Swnj 2175408Swnj case FWRITE: 2185408Swnj if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG/2) 2195408Swnj return (1); 2205408Swnj pti = &pt_ioctl[minor(dev)]; 2215408Swnj if ((p = pti->pti_selw) && p->p_wchan == (caddr_t)&selwait) 2225408Swnj pti->pti_flags |= PTCWCOLL; 2235408Swnj else 2245408Swnj pti->pti_selw = u.u_procp; 2255408Swnj } 2265396Sroot } 2274484Swnj 2282281Stoy ptcwrite(dev) 2295408Swnj dev_t dev; 2304484Swnj { 2312281Stoy register struct tty *tp; 2322281Stoy register char *cp, *ce; 2332281Stoy register int cc; 2342281Stoy char locbuf[BUFSIZ]; 2355408Swnj int cnt = 0; 2362281Stoy 2372281Stoy tp = &pt_tty[minor(dev)]; 2385408Swnj if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 2392281Stoy return; 2404484Swnj while (u.u_count) { 2412281Stoy cc = MIN(u.u_count, BUFSIZ); 2422281Stoy cp = locbuf; 2432281Stoy iomove(cp, (unsigned)cc, B_WRITE); 2444484Swnj if (u.u_error) 2452281Stoy break; 2462281Stoy ce = cp + cc; 2474484Swnj while (cp < ce) { 2484484Swnj while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 2492281Stoy wakeup((caddr_t)&tp->t_rawq); 2505408Swnj if (tp->t_state & TS_NBIO) { 2515408Swnj u.u_count += ce - cp; 2525408Swnj if (cnt == 0) 2535408Swnj u.u_error = EWOULDBLOCK; 2545408Swnj return; 2555408Swnj } 2562281Stoy /* Better than just flushing it! */ 2572281Stoy /* Wait for something to be read */ 2582281Stoy sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 2592281Stoy } 2604141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 2615408Swnj cnt++; 2622281Stoy } 2632281Stoy } 2642281Stoy } 2652281Stoy 2662281Stoy /*ARGSUSED*/ 2672281Stoy ptyioctl(dev, cmd, addr, flag) 2684484Swnj caddr_t addr; 2694484Swnj dev_t dev; 2704484Swnj { 2712281Stoy register struct tty *tp; 2722281Stoy 2732281Stoy tp = &pt_tty[minor(dev)]; 2744484Swnj /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 275*5411Swnj if (cdevsw[major(dev)].d_open == ptcopen) { 276*5411Swnj if (cmd == FIONBIO) { 277*5411Swnj int nbio; 278*5411Swnj register struct pt_ioctl *pti; 279*5411Swnj if (copyin(addr, &nbio, sizeof (nbio))) { 280*5411Swnj u.u_error = EFAULT; 281*5411Swnj return; 282*5411Swnj } 283*5411Swnj pti = &pt_ioctl[minor(dev)]; 284*5411Swnj if (nbio) 285*5411Swnj pti->pti_flags |= PTCNBIO; 286*5411Swnj else 287*5411Swnj pti->pti_flags &= ~PTCNBIO; 288*5411Swnj return; 289*5411Swnj } 290*5411Swnj if (cmd == TIOCSETP) 291*5411Swnj while (getc(&tp->t_outq) >= 0); 292*5411Swnj } 2934484Swnj if (ttioctl(tp, cmd, addr, dev) == 0) 2942281Stoy u.u_error = ENOTTY; 2952281Stoy } 2962313Stoy #endif 297