123390Smckusick /* 2*29109Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323390Smckusick * All rights reserved. The Berkeley software License Agreement 423390Smckusick * specifies the terms and conditions for redistribution. 523390Smckusick * 6*29109Smckusick * @(#)tty_pty.c 7.1 (Berkeley) 06/05/86 723390Smckusick */ 82283Stoy 92281Stoy /* 102281Stoy * Pseudo-teletype Driver 112281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 122281Stoy */ 132314Stoy #include "pty.h" 142314Stoy 153206Swnj #if NPTY > 0 1617096Sbloom #include "param.h" 1717096Sbloom #include "systm.h" 1817096Sbloom #include "ioctl.h" 1917096Sbloom #include "tty.h" 2017096Sbloom #include "dir.h" 2117096Sbloom #include "user.h" 2217096Sbloom #include "conf.h" 2317096Sbloom #include "file.h" 2417096Sbloom #include "proc.h" 2517096Sbloom #include "uio.h" 2617096Sbloom #include "kernel.h" 276239Sroot 287475Ssam #if NPTY == 1 2918651Sbloom #undef NPTY 306239Sroot #define NPTY 32 /* crude XXX */ 317475Ssam #endif 322281Stoy 3316788Ssam #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 344484Swnj 352281Stoy /* 3618651Sbloom * pts == /dev/tty[pqrs]? 3718651Sbloom * ptc == /dev/pty[pqrs]? 382281Stoy */ 394484Swnj struct tty pt_tty[NPTY]; 404484Swnj struct pt_ioctl { 415427Swnj int pt_flags; 425427Swnj struct proc *pt_selr, *pt_selw; 4318651Sbloom u_char pt_send; 4418651Sbloom u_char pt_ucntl; 454484Swnj } pt_ioctl[NPTY]; 4618651Sbloom int npty = NPTY; /* for pstat -t */ 472281Stoy 485427Swnj #define PF_RCOLL 0x01 495427Swnj #define PF_WCOLL 0x02 505427Swnj #define PF_NBIO 0x04 515427Swnj #define PF_PKT 0x08 /* packet mode */ 525574Swnj #define PF_STOPPED 0x10 /* user told stopped */ 535894Swnj #define PF_REMOTE 0x20 /* remote and flow controlled input */ 546119Swnj #define PF_NOSTOP 0x40 5518651Sbloom #define PF_UCNTL 0x80 /* user control mode */ 562281Stoy 572281Stoy /*ARGSUSED*/ 582281Stoy ptsopen(dev, flag) 595396Sroot dev_t dev; 604484Swnj { 612281Stoy register struct tty *tp; 6218651Sbloom int error; 632281Stoy 6418651Sbloom #ifdef lint 6518651Sbloom npty = npty; 6618651Sbloom #endif 678563Sroot if (minor(dev) >= NPTY) 688563Sroot return (ENXIO); 692281Stoy tp = &pt_tty[minor(dev)]; 705408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 712427Swnj ttychars(tp); /* Set up default chars */ 7212642Ssam tp->t_ispeed = tp->t_ospeed = EXTB; 732427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 748563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 758563Sroot return (EBUSY); 764484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 775408Swnj tp->t_state |= TS_CARR_ON; 785408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 795408Swnj tp->t_state |= TS_WOPEN; 802281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 812281Stoy } 8218651Sbloom error = (*linesw[tp->t_line].l_open)(dev, tp); 8318651Sbloom ptcwakeup(tp, FREAD|FWRITE); 8418651Sbloom return (error); 852281Stoy } 862281Stoy 872281Stoy ptsclose(dev) 885396Sroot dev_t dev; 895408Swnj { 902281Stoy register struct tty *tp; 912281Stoy 922281Stoy tp = &pt_tty[minor(dev)]; 932281Stoy (*linesw[tp->t_line].l_close)(tp); 946299Swnj ttyclose(tp); 9518651Sbloom ptcwakeup(tp, FREAD|FWRITE); 962281Stoy } 972281Stoy 987823Sroot ptsread(dev, uio) 995396Sroot dev_t dev; 1007823Sroot struct uio *uio; 1014484Swnj { 1025894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1035894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1048521Sroot int error = 0; 1052281Stoy 1065894Swnj again: 1075894Swnj if (pti->pt_flags & PF_REMOTE) { 1085894Swnj while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 10918651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 11018651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1115894Swnj u.u_procp->p_flag&SVFORK) 1128521Sroot return (EIO); 1135894Swnj gsignal(u.u_procp->p_pgrp, SIGTTIN); 1145894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1155408Swnj } 11618651Sbloom if (tp->t_canq.c_cc == 0) { 1178521Sroot if (tp->t_state & TS_NBIO) 1188521Sroot return (EWOULDBLOCK); 11918651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1205894Swnj goto again; 1215894Swnj } 12218651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 12318651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1248521Sroot error = EFAULT; 1257823Sroot break; 1267823Sroot } 12718651Sbloom if (tp->t_canq.c_cc == 1) 12818651Sbloom (void) getc(&tp->t_canq); 12918651Sbloom if (tp->t_canq.c_cc) 1308521Sroot return (error); 1315894Swnj } else 1325894Swnj if (tp->t_oproc) 1338521Sroot error = (*linesw[tp->t_line].l_read)(tp, uio); 13418651Sbloom ptcwakeup(tp, FWRITE); 1358521Sroot return (error); 1362281Stoy } 1372281Stoy 1385408Swnj /* 1395408Swnj * Write to pseudo-tty. 1405408Swnj * Wakeups of controlling tty will happen 1415408Swnj * indirectly, when tty driver calls ptsstart. 1425408Swnj */ 1437823Sroot ptswrite(dev, uio) 1445396Sroot dev_t dev; 1457823Sroot struct uio *uio; 1464484Swnj { 1472281Stoy register struct tty *tp; 1482281Stoy 1492281Stoy tp = &pt_tty[minor(dev)]; 1508521Sroot if (tp->t_oproc == 0) 1518521Sroot return (EIO); 1528521Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 1532281Stoy } 1542281Stoy 1555408Swnj /* 1565408Swnj * Start output on pseudo-tty. 1575408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1585408Swnj */ 1592281Stoy ptsstart(tp) 1604484Swnj struct tty *tp; 1614484Swnj { 1625574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1634484Swnj 1645408Swnj if (tp->t_state & TS_TTSTOP) 1652281Stoy return; 1665574Swnj if (pti->pt_flags & PF_STOPPED) { 1675574Swnj pti->pt_flags &= ~PF_STOPPED; 1685574Swnj pti->pt_send = TIOCPKT_START; 1695574Swnj } 17018651Sbloom ptcwakeup(tp, FREAD); 1715430Swnj } 1725430Swnj 17318651Sbloom ptcwakeup(tp, flag) 1745430Swnj struct tty *tp; 1755430Swnj { 1765430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1775430Swnj 17818651Sbloom if (flag & FREAD) { 17918651Sbloom if (pti->pt_selr) { 18018651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 18118651Sbloom pti->pt_selr = 0; 18218651Sbloom pti->pt_flags &= ~PF_RCOLL; 18318651Sbloom } 18418651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 1854484Swnj } 18618651Sbloom if (flag & FWRITE) { 18718651Sbloom if (pti->pt_selw) { 18818651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 18918651Sbloom pti->pt_selw = 0; 19018651Sbloom pti->pt_flags &= ~PF_WCOLL; 19118651Sbloom } 19218651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 19318651Sbloom } 1942281Stoy } 1952281Stoy 1962281Stoy /*ARGSUSED*/ 1972281Stoy ptcopen(dev, flag) 1984484Swnj dev_t dev; 1994484Swnj int flag; 2004484Swnj { 2012281Stoy register struct tty *tp; 2025427Swnj struct pt_ioctl *pti; 2032281Stoy 2048563Sroot if (minor(dev) >= NPTY) 2058563Sroot return (ENXIO); 2062281Stoy tp = &pt_tty[minor(dev)]; 2078563Sroot if (tp->t_oproc) 2088563Sroot return (EIO); 2094484Swnj tp->t_oproc = ptsstart; 21025390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2115408Swnj tp->t_state |= TS_CARR_ON; 2125427Swnj pti = &pt_ioctl[minor(dev)]; 2135427Swnj pti->pt_flags = 0; 2145427Swnj pti->pt_send = 0; 21518651Sbloom pti->pt_ucntl = 0; 2168563Sroot return (0); 2172281Stoy } 2182281Stoy 2192281Stoy ptcclose(dev) 2204484Swnj dev_t dev; 2214484Swnj { 2222281Stoy register struct tty *tp; 2232281Stoy 2242281Stoy tp = &pt_tty[minor(dev)]; 22525390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 2264484Swnj tp->t_oproc = 0; /* mark closed */ 2272281Stoy } 2282281Stoy 2297823Sroot ptcread(dev, uio) 2305427Swnj dev_t dev; 2317823Sroot struct uio *uio; 2324484Swnj { 2338521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 23418651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 23516788Ssam char buf[BUFSIZ]; 23616788Ssam int error = 0, cc; 2372281Stoy 23818651Sbloom /* 23918651Sbloom * We want to block until the slave 24018651Sbloom * is open, and there's something to read; 24118651Sbloom * but if we lost the slave or we're NBIO, 24218651Sbloom * then return the appropriate error instead. 24318651Sbloom */ 24418651Sbloom for (;;) { 24518651Sbloom if (tp->t_state&TS_ISOPEN) { 24618651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 24726358Skarels error = ureadc((int)pti->pt_send, uio); 24818651Sbloom if (error) 24918651Sbloom return (error); 25018651Sbloom pti->pt_send = 0; 25118651Sbloom return (0); 25218651Sbloom } 25318651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 25426358Skarels error = ureadc((int)pti->pt_ucntl, uio); 25518651Sbloom if (error) 25618651Sbloom return (error); 25718651Sbloom pti->pt_ucntl = 0; 25818651Sbloom return (0); 25918651Sbloom } 26018651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 26118651Sbloom break; 2625427Swnj } 26316788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 26416788Ssam return (EIO); 2658521Sroot if (pti->pt_flags&PF_NBIO) 2668521Sroot return (EWOULDBLOCK); 2672281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2685411Swnj } 26918651Sbloom if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 27018651Sbloom error = ureadc(0, uio); 27116788Ssam while (uio->uio_resid > 0 && error == 0) { 27216788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 27316788Ssam if (cc <= 0) 2747823Sroot break; 27516788Ssam error = uiomove(buf, cc, UIO_READ, uio); 27616788Ssam } 2775408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 2785408Swnj if (tp->t_state&TS_ASLEEP) { 2795408Swnj tp->t_state &= ~TS_ASLEEP; 2805408Swnj wakeup((caddr_t)&tp->t_outq); 2815408Swnj } 2825408Swnj if (tp->t_wsel) { 2835408Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 2845408Swnj tp->t_wsel = 0; 2855408Swnj tp->t_state &= ~TS_WCOLL; 2865408Swnj } 2872281Stoy } 2888521Sroot return (error); 2892281Stoy } 2902281Stoy 2915427Swnj ptsstop(tp, flush) 2925427Swnj register struct tty *tp; 2935427Swnj int flush; 2945427Swnj { 2955427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 29618651Sbloom int flag; 2975427Swnj 2985574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 2995574Swnj if (flush == 0) { 3005574Swnj flush = TIOCPKT_STOP; 3015574Swnj pti->pt_flags |= PF_STOPPED; 30218651Sbloom } else 3035574Swnj pti->pt_flags &= ~PF_STOPPED; 3046119Swnj pti->pt_send |= flush; 30518651Sbloom /* change of perspective */ 30618651Sbloom flag = 0; 30718651Sbloom if (flush & FREAD) 30818651Sbloom flag |= FWRITE; 30918651Sbloom if (flush & FWRITE) 31018651Sbloom flag |= FREAD; 31123633Sbloom ptcwakeup(tp, flag); 3125427Swnj } 3135427Swnj 3145408Swnj ptcselect(dev, rw) 3154484Swnj dev_t dev; 3165408Swnj int rw; 3174484Swnj { 3184484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3195894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3204484Swnj struct proc *p; 3215430Swnj int s; 3224484Swnj 32318651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3244484Swnj return (1); 3255408Swnj switch (rw) { 3265408Swnj 3275408Swnj case FREAD: 32825945Skarels /* 32925945Skarels * Need to block timeouts (ttrstart). 33025945Skarels */ 33125945Skarels s = spltty(); 33218651Sbloom if ((tp->t_state&TS_ISOPEN) && 33325436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 33425436Skarels splx(s); 33525436Skarels return (1); 33625436Skarels } 33725945Skarels splx(s); 33825436Skarels /* FALLTHROUGH */ 33925436Skarels 34025436Skarels case 0: /* exceptional */ 34125436Skarels if ((tp->t_state&TS_ISOPEN) && 34218651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 34325945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3445408Swnj return (1); 3455427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3465427Swnj pti->pt_flags |= PF_RCOLL; 3475408Swnj else 3485427Swnj pti->pt_selr = u.u_procp; 3495430Swnj break; 3505408Swnj 35125436Skarels 3525408Swnj case FWRITE: 35325945Skarels if (tp->t_state&TS_ISOPEN) { 35425945Skarels if (pti->pt_flags & PF_REMOTE) { 35525945Skarels if (tp->t_canq.c_cc == 0) 35625945Skarels return (1); 35725945Skarels } else { 35825945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 35925945Skarels return (1); 36025945Skarels if (tp->t_canq.c_cc == 0 && 36126251Skarels (tp->t_flags & (RAW|CBREAK)) == 0) 36225945Skarels return (1); 36325945Skarels } 3645430Swnj } 3655427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3665427Swnj pti->pt_flags |= PF_WCOLL; 3675408Swnj else 3685427Swnj pti->pt_selw = u.u_procp; 3695430Swnj break; 37025436Skarels 3715408Swnj } 3725430Swnj return (0); 3735396Sroot } 3744484Swnj 3757823Sroot ptcwrite(dev, uio) 3765408Swnj dev_t dev; 37718651Sbloom register struct uio *uio; 3784484Swnj { 3798521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 38018651Sbloom register struct iovec *iov; 38118651Sbloom register char *cp; 38218651Sbloom register int cc = 0; 3832281Stoy char locbuf[BUFSIZ]; 3845408Swnj int cnt = 0; 3855894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3868521Sroot int error = 0; 3872281Stoy 38818651Sbloom again: 38918651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 39018651Sbloom goto block; 39123633Sbloom if (pti->pt_flags & PF_REMOTE) { 39218651Sbloom if (tp->t_canq.c_cc) 39318651Sbloom goto block; 39423633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 39523633Sbloom iov = uio->uio_iov; 39623633Sbloom if (iov->iov_len == 0) { 39723633Sbloom uio->uio_iovcnt--; 39823633Sbloom uio->uio_iov++; 39923633Sbloom continue; 40023633Sbloom } 40123633Sbloom if (cc == 0) { 40223633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 40323633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 40423633Sbloom cp = locbuf; 40523633Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 40623633Sbloom if (error) 40723633Sbloom return (error); 40823633Sbloom /* check again for safety */ 40923633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41023633Sbloom return (EIO); 41123633Sbloom } 41223633Sbloom if (cc) 41323633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 41423633Sbloom cc = 0; 4157823Sroot } 41618651Sbloom (void) putc(0, &tp->t_canq); 41718651Sbloom ttwakeup(tp); 41818651Sbloom wakeup((caddr_t)&tp->t_canq); 41918651Sbloom return (0); 42018651Sbloom } 42118651Sbloom while (uio->uio_iovcnt > 0) { 42218651Sbloom iov = uio->uio_iov; 42318651Sbloom if (cc == 0) { 42418651Sbloom if (iov->iov_len == 0) { 42518651Sbloom uio->uio_iovcnt--; 42618651Sbloom uio->uio_iov++; 42718651Sbloom continue; 4285894Swnj } 42918651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 43018651Sbloom cp = locbuf; 43118651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 43218651Sbloom if (error) 43318651Sbloom return (error); 43418651Sbloom /* check again for safety */ 43518651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43618651Sbloom return (EIO); 4375894Swnj } 43823633Sbloom while (cc > 0) { 43923633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 44025945Skarels (tp->t_canq.c_cc > 0 || 44125945Skarels tp->t_flags & (RAW|CBREAK))) { 44223633Sbloom wakeup((caddr_t)&tp->t_rawq); 44323633Sbloom goto block; 44423633Sbloom } 4454141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 4465408Swnj cnt++; 44723633Sbloom cc--; 4482281Stoy } 44918651Sbloom cc = 0; 45018651Sbloom } 45118651Sbloom return (0); 45218651Sbloom block: 45318651Sbloom /* 45423633Sbloom * Come here to wait for slave to open, for space 45523633Sbloom * in outq, or space in rawq. 45618651Sbloom */ 45718651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 45818651Sbloom return (EIO); 45918651Sbloom if (pti->pt_flags & PF_NBIO) { 46018651Sbloom iov->iov_base -= cc; 46118651Sbloom iov->iov_len += cc; 46218651Sbloom uio->uio_resid += cc; 46318651Sbloom uio->uio_offset -= cc; 46423633Sbloom if (cnt == 0) 46523633Sbloom return (EWOULDBLOCK); 46618651Sbloom return (0); 46718651Sbloom } 46818651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 46918651Sbloom goto again; 4702281Stoy } 4712281Stoy 4722281Stoy /*ARGSUSED*/ 4737626Ssam ptyioctl(dev, cmd, data, flag) 4747626Ssam caddr_t data; 4754484Swnj dev_t dev; 4764484Swnj { 4776119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4786119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 47918651Sbloom int stop, error; 48025390Skarels extern ttyinput(); 4812281Stoy 48225390Skarels /* 48325390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 48425390Skarels * ttywflush(tp) will hang if there are characters in the outq. 48525390Skarels */ 4867626Ssam if (cdevsw[major(dev)].d_open == ptcopen) 4877626Ssam switch (cmd) { 4887626Ssam 4897626Ssam case TIOCPKT: 49018651Sbloom if (*(int *)data) { 49118651Sbloom if (pti->pt_flags & PF_UCNTL) 49218651Sbloom return (EINVAL); 4935427Swnj pti->pt_flags |= PF_PKT; 49418651Sbloom } else 4955427Swnj pti->pt_flags &= ~PF_PKT; 4968563Sroot return (0); 4977626Ssam 49818651Sbloom case TIOCUCNTL: 49918651Sbloom if (*(int *)data) { 50018651Sbloom if (pti->pt_flags & PF_PKT) 50118651Sbloom return (EINVAL); 50218651Sbloom pti->pt_flags |= PF_UCNTL; 50318651Sbloom } else 50418651Sbloom pti->pt_flags &= ~PF_UCNTL; 50518651Sbloom return (0); 50618651Sbloom 5077626Ssam case TIOCREMOTE: 5087626Ssam if (*(int *)data) 5095894Swnj pti->pt_flags |= PF_REMOTE; 5105894Swnj else 5115894Swnj pti->pt_flags &= ~PF_REMOTE; 51212753Ssam ttyflush(tp, FREAD|FWRITE); 5138563Sroot return (0); 5147626Ssam 5157626Ssam case FIONBIO: 5167626Ssam if (*(int *)data) 5175427Swnj pti->pt_flags |= PF_NBIO; 5185411Swnj else 5195427Swnj pti->pt_flags &= ~PF_NBIO; 5208563Sroot return (0); 5217626Ssam 5227626Ssam case TIOCSETP: 52325390Skarels case TIOCSETN: 52425390Skarels case TIOCSETD: 5257626Ssam while (getc(&tp->t_outq) >= 0) 5267626Ssam ; 5277626Ssam break; 5285411Swnj } 52917182Smckusick error = ttioctl(tp, cmd, data, flag); 53025390Skarels /* 53125390Skarels * Since we use the tty queues internally, 53225390Skarels * pty's can't be switched to disciplines which overwrite 53325390Skarels * the queues. We can't tell anything about the discipline 53425390Skarels * from here... 53525390Skarels */ 53625390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 53725390Skarels (*linesw[tp->t_line].l_close)(tp); 53825390Skarels tp->t_line = 0; 53925390Skarels (void)(*linesw[tp->t_line].l_open)(dev, tp); 54025390Skarels error = ENOTTY; 54125390Skarels } 54218651Sbloom if (error < 0) { 54318651Sbloom if (pti->pt_flags & PF_UCNTL && 54428285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 54518651Sbloom if (cmd & 0xff) { 54618651Sbloom pti->pt_ucntl = (u_char)cmd; 54718651Sbloom ptcwakeup(tp, FREAD); 54818651Sbloom } 54918651Sbloom return (0); 55018651Sbloom } 5518563Sroot error = ENOTTY; 55218651Sbloom } 55318651Sbloom stop = (tp->t_flags & RAW) == 0 && 55418651Sbloom tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 5556119Swnj if (pti->pt_flags & PF_NOSTOP) { 5566119Swnj if (stop) { 55725478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5586119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5596119Swnj pti->pt_flags &= ~PF_NOSTOP; 56018651Sbloom ptcwakeup(tp, FREAD); 5616119Swnj } 5626119Swnj } else { 56318651Sbloom if (!stop) { 5646119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5656119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5666119Swnj pti->pt_flags |= PF_NOSTOP; 56718651Sbloom ptcwakeup(tp, FREAD); 5686119Swnj } 5696119Swnj } 5708563Sroot return (error); 5712281Stoy } 5722313Stoy #endif 573