1*4935Swnj /* tty_pty.c 4.10 81/11/18 */ 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" 194484Swnj #include "../h/proc.h" 202281Stoy 214484Swnj #undef NPTY 224484Swnj #define NPTY 16 234484Swnj 242427Swnj #define BUFSIZ 100 /* Chunk size iomoved from user */ 254484Swnj 262281Stoy /* 274484Swnj * pts == /dev/tty[pP]? 284484Swnj * ptc == /dev/ptp[pP]? 292281Stoy */ 304484Swnj struct tty pt_tty[NPTY]; 314484Swnj struct pt_ioctl { 324484Swnj int pti_flags; 334484Swnj struct clist pti_ioctl, pti_ioans; 344484Swnj int pti_gensym; 354484Swnj struct proc *pti_selr; 364484Swnj } pt_ioctl[NPTY]; 372281Stoy 384484Swnj #define PTCRCOLL 0x01 392281Stoy 402281Stoy /*ARGSUSED*/ 412281Stoy ptsopen(dev, flag) 422281Stoy 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)]; 514484Swnj if ((tp->t_state & ISOPEN) == 0) { 522427Swnj ttychars(tp); /* Set up default chars */ 532427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 544484Swnj } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 552281Stoy u.u_error = EBUSY; 562281Stoy return; 572281Stoy } 584484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 592281Stoy tp->t_state |= CARR_ON; 604484Swnj 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; 784484Swnj { 794484Swnj register struct tty *tp; 802281Stoy 812281Stoy tp = &pt_tty[minor(dev)]; 824484Swnj 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; 904484Swnj { 912281Stoy register struct tty *tp; 922281Stoy 932281Stoy tp = &pt_tty[minor(dev)]; 944484Swnj if (tp->t_oproc) 952281Stoy (*linesw[tp->t_line].l_write)(tp); 962281Stoy } 972281Stoy 982281Stoy ptsstart(tp) 994484Swnj struct tty *tp; 1004484Swnj { 1014484Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1024484Swnj 1034484Swnj if (tp->t_state & TTSTOP) 1042281Stoy return; 1054484Swnj if (pti->pti_selr) { 1064484Swnj selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL); 1074484Swnj pti->pti_selr = 0; 1084484Swnj pti->pti_flags &= ~PTCRCOLL; 1094484Swnj } 1102281Stoy wakeup((caddr_t)&tp->t_outq.c_cf); 1112281Stoy } 1122281Stoy 1132281Stoy /*ARGSUSED*/ 1142281Stoy ptcopen(dev, flag) 1154484Swnj dev_t dev; 1164484Swnj int flag; 1174484Swnj { 1182281Stoy register struct tty *tp; 1192281Stoy 1204484Swnj if (minor(dev) >= NPTY) { 1212281Stoy u.u_error = ENXIO; 1222281Stoy return; 1232281Stoy } 1242281Stoy tp = &pt_tty[minor(dev)]; 1254484Swnj if (tp->t_oproc) { 1262281Stoy u.u_error = EIO; 1272281Stoy return; 1282281Stoy } 1294484Swnj tp->t_oproc = ptsstart; 1304484Swnj if (tp->t_state & WOPEN) 1312281Stoy wakeup((caddr_t)&tp->t_rawq); 1322281Stoy tp->t_state |= CARR_ON; 1332281Stoy } 1342281Stoy 1352281Stoy ptcclose(dev) 1364484Swnj dev_t dev; 1374484Swnj { 1382281Stoy register struct tty *tp; 1392281Stoy 1402281Stoy tp = &pt_tty[minor(dev)]; 1414484Swnj if (tp->t_state & ISOPEN) 1422281Stoy gsignal(tp->t_pgrp, SIGHUP); 1434484Swnj tp->t_state &= ~CARR_ON; /* virtual carrier gone */ 1444484Swnj flushtty(tp, FREAD|FWRITE); 1454484Swnj tp->t_oproc = 0; /* mark closed */ 1462281Stoy } 1472281Stoy 1482281Stoy ptcread(dev) 1492281Stoy dev_t dev; 1504484Swnj { 1512281Stoy register struct tty *tp; 1522281Stoy 1532281Stoy tp = &pt_tty[minor(dev)]; 1544484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1552281Stoy return; 1564484Swnj while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP)) 1572281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 1584484Swnj while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0); 1594484Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp) && (tp->t_state&ASLEEP)) { 1602281Stoy tp->t_state &= ~ASLEEP; 1614484Swnj wakeup((caddr_t)&tp->t_outq); 1622281Stoy } 1632281Stoy } 1642281Stoy 1654484Swnj ptcselect(dev) 1664484Swnj dev_t dev; 1674484Swnj { 1684484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1694484Swnj struct pt_ioctl *pti; 1704484Swnj struct proc *p; 1714484Swnj 1724484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1734484Swnj return (1); 1744484Swnj if (tp->t_outq.c_cc) 1754484Swnj return (1); 1764484Swnj pti = &pt_ioctl[minor(dev)]; 177*4935Swnj if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait) 1784484Swnj pti->pti_flags |= PTCRCOLL; 1794484Swnj else 1804484Swnj pti->pti_selr = u.u_procp; 1814484Swnj return (0); 1824484Swnj } 1834484Swnj 1842281Stoy ptcwrite(dev) 1852281Stoy dev_t dev; 1864484Swnj { 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)]; 1934484Swnj if ((tp->t_state&(CARR_ON|ISOPEN)) == 0) 1942281Stoy return; 1954484Swnj while (u.u_count) { 1962281Stoy cc = MIN(u.u_count, BUFSIZ); 1972281Stoy cp = locbuf; 1982281Stoy iomove(cp, (unsigned)cc, B_WRITE); 1994484Swnj if (u.u_error) 2002281Stoy break; 2012281Stoy ce = cp + cc; 2024484Swnj while (cp < ce) { 2034484Swnj 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) 2164484Swnj caddr_t addr; 2174484Swnj dev_t dev; 2184484Swnj { 2192281Stoy register struct tty *tp; 2202281Stoy 2212281Stoy tp = &pt_tty[minor(dev)]; 2224484Swnj /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 2234484Swnj if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) 2244484Swnj while (getc(&tp->t_outq) >= 0); 2254484Swnj if (ttioctl(tp, cmd, addr, dev) == 0) 2262281Stoy u.u_error = ENOTTY; 2272281Stoy } 2282313Stoy #endif 229