1*4484Swnj /* tty_pty.c 4.9 81/10/11 */ 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 102314Stoy 112281Stoy #include "../h/param.h" 122281Stoy #include "../h/systm.h" 132281Stoy #include "../h/tty.h" 142281Stoy #include "../h/dir.h" 152281Stoy #include "../h/user.h" 162281Stoy #include "../h/conf.h" 172281Stoy #include "../h/buf.h" 182427Swnj #include "../h/file.h" 19*4484Swnj #include "../h/proc.h" 202281Stoy 21*4484Swnj #undef NPTY 22*4484Swnj #define NPTY 16 23*4484Swnj 242427Swnj #define BUFSIZ 100 /* Chunk size iomoved from user */ 25*4484Swnj 262281Stoy /* 27*4484Swnj * pts == /dev/tty[pP]? 28*4484Swnj * ptc == /dev/ptp[pP]? 292281Stoy */ 30*4484Swnj struct tty pt_tty[NPTY]; 31*4484Swnj struct pt_ioctl { 32*4484Swnj int pti_flags; 33*4484Swnj struct clist pti_ioctl, pti_ioans; 34*4484Swnj int pti_gensym; 35*4484Swnj struct proc *pti_selr; 36*4484Swnj } pt_ioctl[NPTY]; 372281Stoy 38*4484Swnj #define PTCRCOLL 0x01 392281Stoy 402281Stoy /*ARGSUSED*/ 412281Stoy ptsopen(dev, flag) 422281Stoy dev_t dev; 43*4484Swnj { 442281Stoy register struct tty *tp; 452281Stoy 46*4484Swnj if (minor(dev) >= NPTY) { 472281Stoy u.u_error = ENXIO; 482281Stoy return; 492281Stoy } 502281Stoy tp = &pt_tty[minor(dev)]; 51*4484Swnj if ((tp->t_state & ISOPEN) == 0) { 522427Swnj ttychars(tp); /* Set up default chars */ 532427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 54*4484Swnj } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 552281Stoy u.u_error = EBUSY; 562281Stoy return; 572281Stoy } 58*4484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 592281Stoy tp->t_state |= CARR_ON; 60*4484Swnj while ((tp->t_state & CARR_ON) == 0) { 612281Stoy tp->t_state |= WOPEN; 622281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 632281Stoy } 642281Stoy (*linesw[tp->t_line].l_open)(dev, tp); 652281Stoy } 662281Stoy 672281Stoy ptsclose(dev) 682281Stoy dev_t dev; 692427Swnj { /* Close slave part of PTY */ 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) 772281Stoy dev_t dev; 78*4484Swnj { 79*4484Swnj register struct tty *tp; 802281Stoy 812281Stoy tp = &pt_tty[minor(dev)]; 82*4484Swnj if (tp->t_oproc) { 832281Stoy (*linesw[tp->t_line].l_read)(tp); 842281Stoy wakeup((caddr_t)&tp->t_rawq.c_cf); 852281Stoy } 862281Stoy } 872281Stoy 882281Stoy ptswrite(dev) 892281Stoy dev_t dev; 90*4484Swnj { 912281Stoy register struct tty *tp; 922281Stoy 932281Stoy tp = &pt_tty[minor(dev)]; 94*4484Swnj if (tp->t_oproc) 952281Stoy (*linesw[tp->t_line].l_write)(tp); 962281Stoy } 972281Stoy 982281Stoy ptsstart(tp) 99*4484Swnj struct tty *tp; 100*4484Swnj { 101*4484Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 102*4484Swnj 103*4484Swnj if (tp->t_state & TTSTOP) 1042281Stoy return; 105*4484Swnj if (pti->pti_selr) { 106*4484Swnj selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL); 107*4484Swnj pti->pti_selr = 0; 108*4484Swnj pti->pti_flags &= ~PTCRCOLL; 109*4484Swnj } 1102281Stoy wakeup((caddr_t)&tp->t_outq.c_cf); 1112281Stoy } 1122281Stoy 1132281Stoy /*ARGSUSED*/ 1142281Stoy ptcopen(dev, flag) 115*4484Swnj dev_t dev; 116*4484Swnj int flag; 117*4484Swnj { 1182281Stoy register struct tty *tp; 1192281Stoy 120*4484Swnj if (minor(dev) >= NPTY) { 1212281Stoy u.u_error = ENXIO; 1222281Stoy return; 1232281Stoy } 1242281Stoy tp = &pt_tty[minor(dev)]; 125*4484Swnj if (tp->t_oproc) { 1262281Stoy u.u_error = EIO; 1272281Stoy return; 1282281Stoy } 129*4484Swnj tp->t_oproc = ptsstart; 130*4484Swnj if (tp->t_state & WOPEN) 1312281Stoy wakeup((caddr_t)&tp->t_rawq); 1322281Stoy tp->t_state |= CARR_ON; 1332281Stoy } 1342281Stoy 1352281Stoy ptcclose(dev) 136*4484Swnj dev_t dev; 137*4484Swnj { 1382281Stoy register struct tty *tp; 1392281Stoy 1402281Stoy tp = &pt_tty[minor(dev)]; 141*4484Swnj if (tp->t_state & ISOPEN) 1422281Stoy gsignal(tp->t_pgrp, SIGHUP); 143*4484Swnj tp->t_state &= ~CARR_ON; /* virtual carrier gone */ 144*4484Swnj flushtty(tp, FREAD|FWRITE); 145*4484Swnj tp->t_oproc = 0; /* mark closed */ 1462281Stoy } 1472281Stoy 1482281Stoy ptcread(dev) 1492281Stoy dev_t dev; 150*4484Swnj { 1512281Stoy register struct tty *tp; 1522281Stoy 1532281Stoy tp = &pt_tty[minor(dev)]; 154*4484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1552281Stoy return; 156*4484Swnj while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP)) 1572281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 158*4484Swnj while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0); 159*4484Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp) && (tp->t_state&ASLEEP)) { 1602281Stoy tp->t_state &= ~ASLEEP; 161*4484Swnj wakeup((caddr_t)&tp->t_outq); 1622281Stoy } 1632281Stoy } 1642281Stoy 165*4484Swnj ptcselect(dev) 166*4484Swnj dev_t dev; 167*4484Swnj { 168*4484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 169*4484Swnj struct pt_ioctl *pti; 170*4484Swnj struct proc *p; 171*4484Swnj 172*4484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 173*4484Swnj return (1); 174*4484Swnj if (tp->t_outq.c_cc) 175*4484Swnj return (1); 176*4484Swnj pti = &pt_ioctl[minor(dev)]; 177*4484Swnj if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)select) 178*4484Swnj pti->pti_flags |= PTCRCOLL; 179*4484Swnj else 180*4484Swnj pti->pti_selr = u.u_procp; 181*4484Swnj return (0); 182*4484Swnj } 183*4484Swnj 1842281Stoy ptcwrite(dev) 1852281Stoy dev_t dev; 186*4484Swnj { 1872281Stoy register struct tty *tp; 1882281Stoy register char *cp, *ce; 1892281Stoy register int cc; 1902281Stoy char locbuf[BUFSIZ]; 1912281Stoy 1922281Stoy tp = &pt_tty[minor(dev)]; 193*4484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1942281Stoy return; 195*4484Swnj while (u.u_count) { 1962281Stoy cc = MIN(u.u_count, BUFSIZ); 1972281Stoy cp = locbuf; 1982281Stoy iomove(cp, (unsigned)cc, B_WRITE); 199*4484Swnj if (u.u_error) 2002281Stoy break; 2012281Stoy ce = cp + cc; 202*4484Swnj while (cp < ce) { 203*4484Swnj while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 2042281Stoy wakeup((caddr_t)&tp->t_rawq); 2052281Stoy /* Better than just flushing it! */ 2062281Stoy /* Wait for something to be read */ 2072281Stoy sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 2082281Stoy } 2094141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 2102281Stoy } 2112281Stoy } 2122281Stoy } 2132281Stoy 2142281Stoy /*ARGSUSED*/ 2152281Stoy ptyioctl(dev, cmd, addr, flag) 216*4484Swnj caddr_t addr; 217*4484Swnj dev_t dev; 218*4484Swnj { 2192281Stoy register struct tty *tp; 2202281Stoy register int tbd; 2212281Stoy 2222281Stoy tp = &pt_tty[minor(dev)]; 223*4484Swnj /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 224*4484Swnj if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) 225*4484Swnj while (getc(&tp->t_outq) >= 0); 226*4484Swnj if (ttioctl(tp, cmd, addr, dev) == 0) 2272281Stoy u.u_error = ENOTTY; 2282281Stoy } 2292313Stoy #endif 230