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