123390Smckusick /* 238007Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 338007Sbostic * All rights reserved. 423390Smckusick * 538007Sbostic * Redistribution and use in source and binary forms are permitted 638007Sbostic * provided that the above copyright notice and this paragraph are 738007Sbostic * duplicated in all such forms and that any documentation, 838007Sbostic * advertising materials, and other materials related to such 938007Sbostic * distribution and use acknowledge that the software was developed 1038007Sbostic * by the University of California, Berkeley. The name of the 1138007Sbostic * University may not be used to endorse or promote products derived 1238007Sbostic * from this software without specific prior written permission. 1338007Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1438007Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538007Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1638007Sbostic * 17*39497Smarc * @(#)tty_pty.c 7.8 (Berkeley) 11/09/89 1823390Smckusick */ 192283Stoy 202281Stoy /* 212281Stoy * Pseudo-teletype Driver 222281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 232281Stoy */ 242314Stoy #include "pty.h" 252314Stoy 263206Swnj #if NPTY > 0 2717096Sbloom #include "param.h" 2817096Sbloom #include "systm.h" 2917096Sbloom #include "ioctl.h" 3017096Sbloom #include "tty.h" 3117096Sbloom #include "user.h" 3217096Sbloom #include "conf.h" 3317096Sbloom #include "file.h" 3417096Sbloom #include "proc.h" 3517096Sbloom #include "uio.h" 3617096Sbloom #include "kernel.h" 3737728Smckusick #include "vnode.h" 386239Sroot 397475Ssam #if NPTY == 1 4018651Sbloom #undef NPTY 416239Sroot #define NPTY 32 /* crude XXX */ 427475Ssam #endif 432281Stoy 4416788Ssam #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 454484Swnj 462281Stoy /* 4718651Sbloom * pts == /dev/tty[pqrs]? 4818651Sbloom * ptc == /dev/pty[pqrs]? 492281Stoy */ 504484Swnj struct tty pt_tty[NPTY]; 514484Swnj struct pt_ioctl { 525427Swnj int pt_flags; 535427Swnj struct proc *pt_selr, *pt_selw; 5418651Sbloom u_char pt_send; 5518651Sbloom u_char pt_ucntl; 564484Swnj } pt_ioctl[NPTY]; 5718651Sbloom int npty = NPTY; /* for pstat -t */ 582281Stoy 5937590Smarc int ptydebug = 0; 6037590Smarc 6135811Smarc #define PF_RCOLL 0x01 6235811Smarc #define PF_WCOLL 0x02 6335811Smarc #define PF_NBIO 0x04 6435811Smarc #define PF_PKT 0x08 /* packet mode */ 6535811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 6635811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 6735811Smarc #define PF_NOSTOP 0x40 6835811Smarc #define PF_UCNTL 0x80 /* user control mode */ 692281Stoy 702281Stoy /*ARGSUSED*/ 712281Stoy ptsopen(dev, flag) 725396Sroot dev_t dev; 734484Swnj { 742281Stoy register struct tty *tp; 7518651Sbloom int error; 762281Stoy 7718651Sbloom #ifdef lint 7818651Sbloom npty = npty; 7918651Sbloom #endif 808563Sroot if (minor(dev) >= NPTY) 818563Sroot return (ENXIO); 822281Stoy tp = &pt_tty[minor(dev)]; 835408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 842427Swnj ttychars(tp); /* Set up default chars */ 8535811Smarc tp->t_iflag = TTYDEF_IFLAG; 8635811Smarc tp->t_oflag = TTYDEF_OFLAG; 8735811Smarc tp->t_lflag = TTYDEF_LFLAG; 8835811Smarc tp->t_cflag = TTYDEF_CFLAG; 8935811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 9035811Smarc ttsetwater(tp); /* would be done in xxparam() */ 918563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 928563Sroot return (EBUSY); 934484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 945408Swnj tp->t_state |= TS_CARR_ON; 955408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 965408Swnj tp->t_state |= TS_WOPEN; 9737590Smarc if (flag&FNDELAY) 9837590Smarc break; 992281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 1002281Stoy } 10137590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 10218651Sbloom ptcwakeup(tp, FREAD|FWRITE); 10318651Sbloom return (error); 1042281Stoy } 1052281Stoy 1062281Stoy ptsclose(dev) 1075396Sroot dev_t dev; 1085408Swnj { 1092281Stoy register struct tty *tp; 1102281Stoy 1112281Stoy tp = &pt_tty[minor(dev)]; 1122281Stoy (*linesw[tp->t_line].l_close)(tp); 1136299Swnj ttyclose(tp); 11418651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1152281Stoy } 1162281Stoy 11737590Smarc ptsread(dev, uio, flag) 1185396Sroot dev_t dev; 1197823Sroot struct uio *uio; 1204484Swnj { 1215894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1225894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1238521Sroot int error = 0; 1242281Stoy 1255894Swnj again: 1265894Swnj if (pti->pt_flags & PF_REMOTE) { 12735811Smarc while (tp == u.u_ttyp && 12835811Smarc u.u_procp->p_pgrp->pg_id != tp->t_pgid){ 12918651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 13018651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 13135811Smarc !u.u_procp->p_pgrp->pg_jobc || 1325894Swnj u.u_procp->p_flag&SVFORK) 1338521Sroot return (EIO); 13435811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1355894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1365408Swnj } 13718651Sbloom if (tp->t_canq.c_cc == 0) { 13837728Smckusick if (flag & IO_NDELAY) 1398521Sroot return (EWOULDBLOCK); 14018651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1415894Swnj goto again; 1425894Swnj } 14318651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 14418651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1458521Sroot error = EFAULT; 1467823Sroot break; 1477823Sroot } 14818651Sbloom if (tp->t_canq.c_cc == 1) 14918651Sbloom (void) getc(&tp->t_canq); 15018651Sbloom if (tp->t_canq.c_cc) 1518521Sroot return (error); 1525894Swnj } else 1535894Swnj if (tp->t_oproc) 15437590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 15518651Sbloom ptcwakeup(tp, FWRITE); 1568521Sroot return (error); 1572281Stoy } 1582281Stoy 1595408Swnj /* 1605408Swnj * Write to pseudo-tty. 1615408Swnj * Wakeups of controlling tty will happen 1625408Swnj * indirectly, when tty driver calls ptsstart. 1635408Swnj */ 16437590Smarc ptswrite(dev, uio, flag) 1655396Sroot dev_t dev; 1667823Sroot struct uio *uio; 1674484Swnj { 16835811Smarc register struct tty *tp; 1692281Stoy 17035811Smarc tp = &pt_tty[minor(dev)]; 1718521Sroot if (tp->t_oproc == 0) 1728521Sroot return (EIO); 17337590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1742281Stoy } 1752281Stoy 1765408Swnj /* 1775408Swnj * Start output on pseudo-tty. 1785408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1795408Swnj */ 1802281Stoy ptsstart(tp) 1814484Swnj struct tty *tp; 1824484Swnj { 1835574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1844484Swnj 1855408Swnj if (tp->t_state & TS_TTSTOP) 1862281Stoy return; 1875574Swnj if (pti->pt_flags & PF_STOPPED) { 1885574Swnj pti->pt_flags &= ~PF_STOPPED; 1895574Swnj pti->pt_send = TIOCPKT_START; 1905574Swnj } 19118651Sbloom ptcwakeup(tp, FREAD); 1925430Swnj } 1935430Swnj 19418651Sbloom ptcwakeup(tp, flag) 1955430Swnj struct tty *tp; 1965430Swnj { 1975430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1985430Swnj 19918651Sbloom if (flag & FREAD) { 20018651Sbloom if (pti->pt_selr) { 20118651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 20218651Sbloom pti->pt_selr = 0; 20318651Sbloom pti->pt_flags &= ~PF_RCOLL; 20418651Sbloom } 20518651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2064484Swnj } 20718651Sbloom if (flag & FWRITE) { 20818651Sbloom if (pti->pt_selw) { 20918651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 21018651Sbloom pti->pt_selw = 0; 21118651Sbloom pti->pt_flags &= ~PF_WCOLL; 21218651Sbloom } 21337590Smarc if (ptydebug) printf("WAKEUP c_cf %d\n", u.u_procp->p_pid); 21418651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 21518651Sbloom } 2162281Stoy } 2172281Stoy 2182281Stoy /*ARGSUSED*/ 2192281Stoy ptcopen(dev, flag) 2204484Swnj dev_t dev; 2214484Swnj int flag; 2224484Swnj { 2232281Stoy register struct tty *tp; 2245427Swnj struct pt_ioctl *pti; 2252281Stoy 2268563Sroot if (minor(dev) >= NPTY) 2278563Sroot return (ENXIO); 2282281Stoy tp = &pt_tty[minor(dev)]; 2298563Sroot if (tp->t_oproc) 2308563Sroot return (EIO); 2314484Swnj tp->t_oproc = ptsstart; 23225390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2335427Swnj pti = &pt_ioctl[minor(dev)]; 2345427Swnj pti->pt_flags = 0; 2355427Swnj pti->pt_send = 0; 23618651Sbloom pti->pt_ucntl = 0; 2378563Sroot return (0); 2382281Stoy } 2392281Stoy 2402281Stoy ptcclose(dev) 2414484Swnj dev_t dev; 2424484Swnj { 2432281Stoy register struct tty *tp; 2442281Stoy 2452281Stoy tp = &pt_tty[minor(dev)]; 24625390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 24732326Skarels tp->t_state &= ~TS_CARR_ON; 2484484Swnj tp->t_oproc = 0; /* mark closed */ 249*39497Smarc tp->t_session = 0; 2502281Stoy } 2512281Stoy 25237590Smarc ptcread(dev, uio, flag) 2535427Swnj dev_t dev; 2547823Sroot struct uio *uio; 2554484Swnj { 2568521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 25718651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 25816788Ssam char buf[BUFSIZ]; 25916788Ssam int error = 0, cc; 2602281Stoy 26118651Sbloom /* 26218651Sbloom * We want to block until the slave 26318651Sbloom * is open, and there's something to read; 26418651Sbloom * but if we lost the slave or we're NBIO, 26518651Sbloom * then return the appropriate error instead. 26618651Sbloom */ 26718651Sbloom for (;;) { 26818651Sbloom if (tp->t_state&TS_ISOPEN) { 26918651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 27026358Skarels error = ureadc((int)pti->pt_send, uio); 27118651Sbloom if (error) 27218651Sbloom return (error); 27318651Sbloom pti->pt_send = 0; 27418651Sbloom return (0); 27518651Sbloom } 27618651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 27726358Skarels error = ureadc((int)pti->pt_ucntl, uio); 27818651Sbloom if (error) 27918651Sbloom return (error); 28018651Sbloom pti->pt_ucntl = 0; 28118651Sbloom return (0); 28218651Sbloom } 28318651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 28418651Sbloom break; 2855427Swnj } 28616788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 28737590Smarc return (0); /* EOF */ 28837728Smckusick if (flag & IO_NDELAY) 2898521Sroot return (EWOULDBLOCK); 29037590Smarc if (ptydebug) printf("SLEEP(1) c_cf %d\n", u.u_procp->p_pid); 2912281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2925411Swnj } 29335811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 29418651Sbloom error = ureadc(0, uio); 29516788Ssam while (uio->uio_resid > 0 && error == 0) { 29616788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 29716788Ssam if (cc <= 0) 2987823Sroot break; 29937728Smckusick error = uiomove(buf, cc, uio); 30016788Ssam } 30135811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 30235811Smarc if (tp->t_state&TS_ASLEEP) { 30335811Smarc tp->t_state &= ~TS_ASLEEP; 30435811Smarc wakeup((caddr_t)&tp->t_outq); 30535811Smarc } 30635811Smarc if (tp->t_wsel) { 30735811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 30835811Smarc tp->t_wsel = 0; 30935811Smarc tp->t_state &= ~TS_WCOLL; 31035811Smarc } 31135811Smarc } 3128521Sroot return (error); 3132281Stoy } 3142281Stoy 3155427Swnj ptsstop(tp, flush) 3165427Swnj register struct tty *tp; 3175427Swnj int flush; 3185427Swnj { 3195427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 32018651Sbloom int flag; 3215427Swnj 3225574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3235574Swnj if (flush == 0) { 3245574Swnj flush = TIOCPKT_STOP; 3255574Swnj pti->pt_flags |= PF_STOPPED; 32618651Sbloom } else 3275574Swnj pti->pt_flags &= ~PF_STOPPED; 3286119Swnj pti->pt_send |= flush; 32918651Sbloom /* change of perspective */ 33018651Sbloom flag = 0; 33118651Sbloom if (flush & FREAD) 33218651Sbloom flag |= FWRITE; 33318651Sbloom if (flush & FWRITE) 33418651Sbloom flag |= FREAD; 33523633Sbloom ptcwakeup(tp, flag); 3365427Swnj } 3375427Swnj 3385408Swnj ptcselect(dev, rw) 3394484Swnj dev_t dev; 3405408Swnj int rw; 3414484Swnj { 3424484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3435894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3444484Swnj struct proc *p; 3455430Swnj int s; 3464484Swnj 34718651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3484484Swnj return (1); 3495408Swnj switch (rw) { 3505408Swnj 3515408Swnj case FREAD: 35225945Skarels /* 35325945Skarels * Need to block timeouts (ttrstart). 35425945Skarels */ 35525945Skarels s = spltty(); 35618651Sbloom if ((tp->t_state&TS_ISOPEN) && 35725436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 35825436Skarels splx(s); 35925436Skarels return (1); 36025436Skarels } 36125945Skarels splx(s); 36225436Skarels /* FALLTHROUGH */ 36325436Skarels 36425436Skarels case 0: /* exceptional */ 36525436Skarels if ((tp->t_state&TS_ISOPEN) && 36618651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 36725945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3685408Swnj return (1); 3695427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3705427Swnj pti->pt_flags |= PF_RCOLL; 3715408Swnj else 3725427Swnj pti->pt_selr = u.u_procp; 3735430Swnj break; 3745408Swnj 37525436Skarels 3765408Swnj case FWRITE: 37725945Skarels if (tp->t_state&TS_ISOPEN) { 37825945Skarels if (pti->pt_flags & PF_REMOTE) { 37925945Skarels if (tp->t_canq.c_cc == 0) 38025945Skarels return (1); 38125945Skarels } else { 38225945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 38325945Skarels return (1); 38435811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 38525945Skarels return (1); 38625945Skarels } 3875430Swnj } 3885427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3895427Swnj pti->pt_flags |= PF_WCOLL; 3905408Swnj else 3915427Swnj pti->pt_selw = u.u_procp; 3925430Swnj break; 39325436Skarels 3945408Swnj } 3955430Swnj return (0); 3965396Sroot } 3974484Swnj 39837590Smarc ptcwrite(dev, uio, flag) 3995408Swnj dev_t dev; 40018651Sbloom register struct uio *uio; 4014484Swnj { 4028521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 40318651Sbloom register struct iovec *iov; 40418651Sbloom register char *cp; 40518651Sbloom register int cc = 0; 4062281Stoy char locbuf[BUFSIZ]; 4075408Swnj int cnt = 0; 4085894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4098521Sroot int error = 0; 4102281Stoy 41118651Sbloom again: 41218651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41318651Sbloom goto block; 41423633Sbloom if (pti->pt_flags & PF_REMOTE) { 41518651Sbloom if (tp->t_canq.c_cc) 41618651Sbloom goto block; 41723633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 41823633Sbloom iov = uio->uio_iov; 41923633Sbloom if (iov->iov_len == 0) { 42023633Sbloom uio->uio_iovcnt--; 42123633Sbloom uio->uio_iov++; 42223633Sbloom continue; 42323633Sbloom } 42423633Sbloom if (cc == 0) { 42523633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 42623633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 42723633Sbloom cp = locbuf; 42837728Smckusick error = uiomove(cp, cc, uio); 42923633Sbloom if (error) 43023633Sbloom return (error); 43123633Sbloom /* check again for safety */ 43223633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43323633Sbloom return (EIO); 43423633Sbloom } 43523633Sbloom if (cc) 43623633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 43723633Sbloom cc = 0; 4387823Sroot } 43918651Sbloom (void) putc(0, &tp->t_canq); 44018651Sbloom ttwakeup(tp); 44118651Sbloom wakeup((caddr_t)&tp->t_canq); 44218651Sbloom return (0); 44318651Sbloom } 44418651Sbloom while (uio->uio_iovcnt > 0) { 44518651Sbloom iov = uio->uio_iov; 44618651Sbloom if (cc == 0) { 44718651Sbloom if (iov->iov_len == 0) { 44818651Sbloom uio->uio_iovcnt--; 44918651Sbloom uio->uio_iov++; 45018651Sbloom continue; 4515894Swnj } 45218651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 45318651Sbloom cp = locbuf; 45437728Smckusick error = uiomove(cp, cc, uio); 45518651Sbloom if (error) 45618651Sbloom return (error); 45718651Sbloom /* check again for safety */ 45818651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 45918651Sbloom return (EIO); 4605894Swnj } 46123633Sbloom while (cc > 0) { 46223633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 46335811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 46423633Sbloom wakeup((caddr_t)&tp->t_rawq); 46523633Sbloom goto block; 46623633Sbloom } 46737590Smarc (*linesw[tp->t_line].l_rint)(*cp++&0377, tp); 4685408Swnj cnt++; 46923633Sbloom cc--; 4702281Stoy } 47118651Sbloom cc = 0; 47218651Sbloom } 47318651Sbloom return (0); 47418651Sbloom block: 47518651Sbloom /* 47623633Sbloom * Come here to wait for slave to open, for space 47723633Sbloom * in outq, or space in rawq. 47818651Sbloom */ 47918651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 48018651Sbloom return (EIO); 48137728Smckusick if ((pti->pt_flags & PF_NBIO) || (flag & IO_NDELAY)) { 48218651Sbloom iov->iov_base -= cc; 48318651Sbloom iov->iov_len += cc; 48418651Sbloom uio->uio_resid += cc; 48518651Sbloom uio->uio_offset -= cc; 48623633Sbloom if (cnt == 0) 48723633Sbloom return (EWOULDBLOCK); 48818651Sbloom return (0); 48918651Sbloom } 49037590Smarc if (ptydebug) printf("SLEEP(2) c_cf %d\n", u.u_procp->p_pid); 49118651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 49218651Sbloom goto again; 4932281Stoy } 4942281Stoy 4952281Stoy /*ARGSUSED*/ 4967626Ssam ptyioctl(dev, cmd, data, flag) 4977626Ssam caddr_t data; 4984484Swnj dev_t dev; 4994484Swnj { 5006119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5016119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 50235811Smarc register u_char *cc = tp->t_cc; 50318651Sbloom int stop, error; 50425390Skarels extern ttyinput(); 5052281Stoy 50625390Skarels /* 50725390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 50825390Skarels * ttywflush(tp) will hang if there are characters in the outq. 50925390Skarels */ 51035811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5117626Ssam switch (cmd) { 5127626Ssam 5137626Ssam case TIOCPKT: 51418651Sbloom if (*(int *)data) { 51518651Sbloom if (pti->pt_flags & PF_UCNTL) 51618651Sbloom return (EINVAL); 5175427Swnj pti->pt_flags |= PF_PKT; 51818651Sbloom } else 5195427Swnj pti->pt_flags &= ~PF_PKT; 5208563Sroot return (0); 5217626Ssam 52218651Sbloom case TIOCUCNTL: 52318651Sbloom if (*(int *)data) { 52418651Sbloom if (pti->pt_flags & PF_PKT) 52518651Sbloom return (EINVAL); 52618651Sbloom pti->pt_flags |= PF_UCNTL; 52718651Sbloom } else 52818651Sbloom pti->pt_flags &= ~PF_UCNTL; 52918651Sbloom return (0); 53018651Sbloom 5317626Ssam case TIOCREMOTE: 5327626Ssam if (*(int *)data) 5335894Swnj pti->pt_flags |= PF_REMOTE; 5345894Swnj else 5355894Swnj pti->pt_flags &= ~PF_REMOTE; 53612753Ssam ttyflush(tp, FREAD|FWRITE); 5378563Sroot return (0); 5387626Ssam 5397626Ssam case FIONBIO: 5407626Ssam if (*(int *)data) 5415427Swnj pti->pt_flags |= PF_NBIO; 5425411Swnj else 5435427Swnj pti->pt_flags &= ~PF_NBIO; 5448563Sroot return (0); 5457626Ssam 54635811Smarc case TIOCSETP: 54725390Skarels case TIOCSETN: 54825390Skarels case TIOCSETD: 54935811Smarc case TIOCSETA: 55035811Smarc case TIOCSETAW: 55135811Smarc case TIOCSETAF: 552*39497Smarc case JUNK_TIOCSETAS: 553*39497Smarc case JUNK_TIOCSETAWS: 554*39497Smarc case JUNK_TIOCSETAFS: 5557626Ssam while (getc(&tp->t_outq) >= 0) 5567626Ssam ; 5577626Ssam break; 5585411Swnj } 55935811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 56035811Smarc if (error < 0) 56135811Smarc error = ttioctl(tp, cmd, data, flag); 56225390Skarels /* 56325390Skarels * Since we use the tty queues internally, 56425390Skarels * pty's can't be switched to disciplines which overwrite 56525390Skarels * the queues. We can't tell anything about the discipline 56625390Skarels * from here... 56725390Skarels */ 56825390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 56925390Skarels (*linesw[tp->t_line].l_close)(tp); 57025390Skarels tp->t_line = 0; 57137590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 57225390Skarels error = ENOTTY; 57325390Skarels } 57418651Sbloom if (error < 0) { 57518651Sbloom if (pti->pt_flags & PF_UCNTL && 57628285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 57718651Sbloom if (cmd & 0xff) { 57818651Sbloom pti->pt_ucntl = (u_char)cmd; 57918651Sbloom ptcwakeup(tp, FREAD); 58018651Sbloom } 58118651Sbloom return (0); 58218651Sbloom } 5838563Sroot error = ENOTTY; 58418651Sbloom } 58535811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 58635811Smarc && CCEQ(cc[VSTART], CTRL('q')); 5876119Swnj if (pti->pt_flags & PF_NOSTOP) { 5886119Swnj if (stop) { 58925478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5906119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5916119Swnj pti->pt_flags &= ~PF_NOSTOP; 59218651Sbloom ptcwakeup(tp, FREAD); 5936119Swnj } 5946119Swnj } else { 59518651Sbloom if (!stop) { 5966119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5976119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5986119Swnj pti->pt_flags |= PF_NOSTOP; 59918651Sbloom ptcwakeup(tp, FREAD); 6006119Swnj } 6016119Swnj } 6028563Sroot return (error); 6032281Stoy } 6042313Stoy #endif 605