123390Smckusick /* 229109Smckusick * 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*35811Smarc * @(#)tty_pty.c 7.4 (Berkeley) 10/18/88 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 48*35811Smarc #define PF_RCOLL 0x01 49*35811Smarc #define PF_WCOLL 0x02 50*35811Smarc #define PF_NBIO 0x04 51*35811Smarc #define PF_PKT 0x08 /* packet mode */ 52*35811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 53*35811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 54*35811Smarc #define PF_NOSTOP 0x40 55*35811Smarc #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 */ 72*35811Smarc tp->t_iflag = TTYDEF_IFLAG; 73*35811Smarc tp->t_oflag = TTYDEF_OFLAG; 74*35811Smarc tp->t_lflag = TTYDEF_LFLAG; 75*35811Smarc tp->t_cflag = TTYDEF_CFLAG; 76*35811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 77*35811Smarc ttsetwater(tp); /* would be done in xxparam() */ 788563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 798563Sroot return (EBUSY); 804484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 815408Swnj tp->t_state |= TS_CARR_ON; 825408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 835408Swnj tp->t_state |= TS_WOPEN; 842281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 852281Stoy } 8618651Sbloom error = (*linesw[tp->t_line].l_open)(dev, tp); 8718651Sbloom ptcwakeup(tp, FREAD|FWRITE); 8818651Sbloom return (error); 892281Stoy } 902281Stoy 912281Stoy ptsclose(dev) 925396Sroot dev_t dev; 935408Swnj { 942281Stoy register struct tty *tp; 952281Stoy 962281Stoy tp = &pt_tty[minor(dev)]; 972281Stoy (*linesw[tp->t_line].l_close)(tp); 986299Swnj ttyclose(tp); 9918651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1002281Stoy } 1012281Stoy 1027823Sroot ptsread(dev, uio) 1035396Sroot dev_t dev; 1047823Sroot struct uio *uio; 1054484Swnj { 1065894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1075894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1088521Sroot int error = 0; 1092281Stoy 1105894Swnj again: 1115894Swnj if (pti->pt_flags & PF_REMOTE) { 112*35811Smarc while (tp == u.u_ttyp && 113*35811Smarc u.u_procp->p_pgrp->pg_id != tp->t_pgid){ 11418651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 11518651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 116*35811Smarc !u.u_procp->p_pgrp->pg_jobc || 1175894Swnj u.u_procp->p_flag&SVFORK) 1188521Sroot return (EIO); 119*35811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1205894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1215408Swnj } 12218651Sbloom if (tp->t_canq.c_cc == 0) { 1238521Sroot if (tp->t_state & TS_NBIO) 1248521Sroot return (EWOULDBLOCK); 12518651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1265894Swnj goto again; 1275894Swnj } 12818651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 12918651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1308521Sroot error = EFAULT; 1317823Sroot break; 1327823Sroot } 13318651Sbloom if (tp->t_canq.c_cc == 1) 13418651Sbloom (void) getc(&tp->t_canq); 13518651Sbloom if (tp->t_canq.c_cc) 1368521Sroot return (error); 1375894Swnj } else 1385894Swnj if (tp->t_oproc) 1398521Sroot error = (*linesw[tp->t_line].l_read)(tp, uio); 14018651Sbloom ptcwakeup(tp, FWRITE); 1418521Sroot return (error); 1422281Stoy } 1432281Stoy 1445408Swnj /* 1455408Swnj * Write to pseudo-tty. 1465408Swnj * Wakeups of controlling tty will happen 1475408Swnj * indirectly, when tty driver calls ptsstart. 1485408Swnj */ 1497823Sroot ptswrite(dev, uio) 1505396Sroot dev_t dev; 1517823Sroot struct uio *uio; 1524484Swnj { 153*35811Smarc register struct tty *tp; 1542281Stoy 155*35811Smarc tp = &pt_tty[minor(dev)]; 1568521Sroot if (tp->t_oproc == 0) 1578521Sroot return (EIO); 1588521Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 1592281Stoy } 1602281Stoy 1615408Swnj /* 1625408Swnj * Start output on pseudo-tty. 1635408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1645408Swnj */ 1652281Stoy ptsstart(tp) 1664484Swnj struct tty *tp; 1674484Swnj { 1685574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1694484Swnj 1705408Swnj if (tp->t_state & TS_TTSTOP) 1712281Stoy return; 1725574Swnj if (pti->pt_flags & PF_STOPPED) { 1735574Swnj pti->pt_flags &= ~PF_STOPPED; 1745574Swnj pti->pt_send = TIOCPKT_START; 1755574Swnj } 17618651Sbloom ptcwakeup(tp, FREAD); 1775430Swnj } 1785430Swnj 17918651Sbloom ptcwakeup(tp, flag) 1805430Swnj struct tty *tp; 1815430Swnj { 1825430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1835430Swnj 18418651Sbloom if (flag & FREAD) { 18518651Sbloom if (pti->pt_selr) { 18618651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 18718651Sbloom pti->pt_selr = 0; 18818651Sbloom pti->pt_flags &= ~PF_RCOLL; 18918651Sbloom } 19018651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 1914484Swnj } 19218651Sbloom if (flag & FWRITE) { 19318651Sbloom if (pti->pt_selw) { 19418651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 19518651Sbloom pti->pt_selw = 0; 19618651Sbloom pti->pt_flags &= ~PF_WCOLL; 19718651Sbloom } 19818651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 19918651Sbloom } 2002281Stoy } 2012281Stoy 2022281Stoy /*ARGSUSED*/ 2032281Stoy ptcopen(dev, flag) 2044484Swnj dev_t dev; 2054484Swnj int flag; 2064484Swnj { 2072281Stoy register struct tty *tp; 2085427Swnj struct pt_ioctl *pti; 2092281Stoy 2108563Sroot if (minor(dev) >= NPTY) 2118563Sroot return (ENXIO); 2122281Stoy tp = &pt_tty[minor(dev)]; 2138563Sroot if (tp->t_oproc) 2148563Sroot return (EIO); 2154484Swnj tp->t_oproc = ptsstart; 21625390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2175427Swnj pti = &pt_ioctl[minor(dev)]; 2185427Swnj pti->pt_flags = 0; 2195427Swnj pti->pt_send = 0; 22018651Sbloom pti->pt_ucntl = 0; 2218563Sroot return (0); 2222281Stoy } 2232281Stoy 2242281Stoy ptcclose(dev) 2254484Swnj dev_t dev; 2264484Swnj { 2272281Stoy register struct tty *tp; 2282281Stoy 2292281Stoy tp = &pt_tty[minor(dev)]; 23025390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 23132326Skarels tp->t_state &= ~TS_CARR_ON; 2324484Swnj tp->t_oproc = 0; /* mark closed */ 2332281Stoy } 2342281Stoy 2357823Sroot ptcread(dev, uio) 2365427Swnj dev_t dev; 2377823Sroot struct uio *uio; 2384484Swnj { 2398521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 24018651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 24116788Ssam char buf[BUFSIZ]; 24216788Ssam int error = 0, cc; 2432281Stoy 24418651Sbloom /* 24518651Sbloom * We want to block until the slave 24618651Sbloom * is open, and there's something to read; 24718651Sbloom * but if we lost the slave or we're NBIO, 24818651Sbloom * then return the appropriate error instead. 24918651Sbloom */ 25018651Sbloom for (;;) { 25118651Sbloom if (tp->t_state&TS_ISOPEN) { 25218651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 25326358Skarels error = ureadc((int)pti->pt_send, uio); 25418651Sbloom if (error) 25518651Sbloom return (error); 25618651Sbloom pti->pt_send = 0; 25718651Sbloom return (0); 25818651Sbloom } 25918651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 26026358Skarels error = ureadc((int)pti->pt_ucntl, uio); 26118651Sbloom if (error) 26218651Sbloom return (error); 26318651Sbloom pti->pt_ucntl = 0; 26418651Sbloom return (0); 26518651Sbloom } 26618651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 26718651Sbloom break; 2685427Swnj } 26916788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 27016788Ssam return (EIO); 2718521Sroot if (pti->pt_flags&PF_NBIO) 2728521Sroot return (EWOULDBLOCK); 2732281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2745411Swnj } 275*35811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 27618651Sbloom error = ureadc(0, uio); 27716788Ssam while (uio->uio_resid > 0 && error == 0) { 27816788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 27916788Ssam if (cc <= 0) 2807823Sroot break; 28116788Ssam error = uiomove(buf, cc, UIO_READ, uio); 28216788Ssam } 283*35811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 284*35811Smarc if (tp->t_state&TS_ASLEEP) { 285*35811Smarc tp->t_state &= ~TS_ASLEEP; 286*35811Smarc wakeup((caddr_t)&tp->t_outq); 287*35811Smarc } 288*35811Smarc if (tp->t_wsel) { 289*35811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 290*35811Smarc tp->t_wsel = 0; 291*35811Smarc tp->t_state &= ~TS_WCOLL; 292*35811Smarc } 293*35811Smarc } 2948521Sroot return (error); 2952281Stoy } 2962281Stoy 2975427Swnj ptsstop(tp, flush) 2985427Swnj register struct tty *tp; 2995427Swnj int flush; 3005427Swnj { 3015427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 30218651Sbloom int flag; 3035427Swnj 3045574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3055574Swnj if (flush == 0) { 3065574Swnj flush = TIOCPKT_STOP; 3075574Swnj pti->pt_flags |= PF_STOPPED; 30818651Sbloom } else 3095574Swnj pti->pt_flags &= ~PF_STOPPED; 3106119Swnj pti->pt_send |= flush; 31118651Sbloom /* change of perspective */ 31218651Sbloom flag = 0; 31318651Sbloom if (flush & FREAD) 31418651Sbloom flag |= FWRITE; 31518651Sbloom if (flush & FWRITE) 31618651Sbloom flag |= FREAD; 31723633Sbloom ptcwakeup(tp, flag); 3185427Swnj } 3195427Swnj 3205408Swnj ptcselect(dev, rw) 3214484Swnj dev_t dev; 3225408Swnj int rw; 3234484Swnj { 3244484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3255894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3264484Swnj struct proc *p; 3275430Swnj int s; 3284484Swnj 32918651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3304484Swnj return (1); 3315408Swnj switch (rw) { 3325408Swnj 3335408Swnj case FREAD: 33425945Skarels /* 33525945Skarels * Need to block timeouts (ttrstart). 33625945Skarels */ 33725945Skarels s = spltty(); 33818651Sbloom if ((tp->t_state&TS_ISOPEN) && 33925436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 34025436Skarels splx(s); 34125436Skarels return (1); 34225436Skarels } 34325945Skarels splx(s); 34425436Skarels /* FALLTHROUGH */ 34525436Skarels 34625436Skarels case 0: /* exceptional */ 34725436Skarels if ((tp->t_state&TS_ISOPEN) && 34818651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 34925945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3505408Swnj return (1); 3515427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3525427Swnj pti->pt_flags |= PF_RCOLL; 3535408Swnj else 3545427Swnj pti->pt_selr = u.u_procp; 3555430Swnj break; 3565408Swnj 35725436Skarels 3585408Swnj case FWRITE: 35925945Skarels if (tp->t_state&TS_ISOPEN) { 36025945Skarels if (pti->pt_flags & PF_REMOTE) { 36125945Skarels if (tp->t_canq.c_cc == 0) 36225945Skarels return (1); 36325945Skarels } else { 36425945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 36525945Skarels return (1); 366*35811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 36725945Skarels return (1); 36825945Skarels } 3695430Swnj } 3705427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3715427Swnj pti->pt_flags |= PF_WCOLL; 3725408Swnj else 3735427Swnj pti->pt_selw = u.u_procp; 3745430Swnj break; 37525436Skarels 3765408Swnj } 3775430Swnj return (0); 3785396Sroot } 3794484Swnj 3807823Sroot ptcwrite(dev, uio) 3815408Swnj dev_t dev; 38218651Sbloom register struct uio *uio; 3834484Swnj { 3848521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 38518651Sbloom register struct iovec *iov; 38618651Sbloom register char *cp; 38718651Sbloom register int cc = 0; 3882281Stoy char locbuf[BUFSIZ]; 3895408Swnj int cnt = 0; 3905894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3918521Sroot int error = 0; 3922281Stoy 39318651Sbloom again: 39418651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 39518651Sbloom goto block; 39623633Sbloom if (pti->pt_flags & PF_REMOTE) { 39718651Sbloom if (tp->t_canq.c_cc) 39818651Sbloom goto block; 39923633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 40023633Sbloom iov = uio->uio_iov; 40123633Sbloom if (iov->iov_len == 0) { 40223633Sbloom uio->uio_iovcnt--; 40323633Sbloom uio->uio_iov++; 40423633Sbloom continue; 40523633Sbloom } 40623633Sbloom if (cc == 0) { 40723633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 40823633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 40923633Sbloom cp = locbuf; 41023633Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 41123633Sbloom if (error) 41223633Sbloom return (error); 41323633Sbloom /* check again for safety */ 41423633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41523633Sbloom return (EIO); 41623633Sbloom } 41723633Sbloom if (cc) 41823633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 41923633Sbloom cc = 0; 4207823Sroot } 42118651Sbloom (void) putc(0, &tp->t_canq); 42218651Sbloom ttwakeup(tp); 42318651Sbloom wakeup((caddr_t)&tp->t_canq); 42418651Sbloom return (0); 42518651Sbloom } 42618651Sbloom while (uio->uio_iovcnt > 0) { 42718651Sbloom iov = uio->uio_iov; 42818651Sbloom if (cc == 0) { 42918651Sbloom if (iov->iov_len == 0) { 43018651Sbloom uio->uio_iovcnt--; 43118651Sbloom uio->uio_iov++; 43218651Sbloom continue; 4335894Swnj } 43418651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 43518651Sbloom cp = locbuf; 43618651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 43718651Sbloom if (error) 43818651Sbloom return (error); 43918651Sbloom /* check again for safety */ 44018651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 44118651Sbloom return (EIO); 4425894Swnj } 44323633Sbloom while (cc > 0) { 44423633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 445*35811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 44623633Sbloom wakeup((caddr_t)&tp->t_rawq); 44723633Sbloom goto block; 44823633Sbloom } 4494141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 4505408Swnj cnt++; 45123633Sbloom cc--; 4522281Stoy } 45318651Sbloom cc = 0; 45418651Sbloom } 45518651Sbloom return (0); 45618651Sbloom block: 45718651Sbloom /* 45823633Sbloom * Come here to wait for slave to open, for space 45923633Sbloom * in outq, or space in rawq. 46018651Sbloom */ 46118651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 46218651Sbloom return (EIO); 46318651Sbloom if (pti->pt_flags & PF_NBIO) { 46418651Sbloom iov->iov_base -= cc; 46518651Sbloom iov->iov_len += cc; 46618651Sbloom uio->uio_resid += cc; 46718651Sbloom uio->uio_offset -= cc; 46823633Sbloom if (cnt == 0) 46923633Sbloom return (EWOULDBLOCK); 47018651Sbloom return (0); 47118651Sbloom } 47218651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 47318651Sbloom goto again; 4742281Stoy } 4752281Stoy 4762281Stoy /*ARGSUSED*/ 4777626Ssam ptyioctl(dev, cmd, data, flag) 4787626Ssam caddr_t data; 4794484Swnj dev_t dev; 4804484Swnj { 4816119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4826119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 483*35811Smarc register u_char *cc = tp->t_cc; 48418651Sbloom int stop, error; 48525390Skarels extern ttyinput(); 4862281Stoy 48725390Skarels /* 48825390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 48925390Skarels * ttywflush(tp) will hang if there are characters in the outq. 49025390Skarels */ 491*35811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 4927626Ssam switch (cmd) { 4937626Ssam 4947626Ssam case TIOCPKT: 49518651Sbloom if (*(int *)data) { 49618651Sbloom if (pti->pt_flags & PF_UCNTL) 49718651Sbloom return (EINVAL); 4985427Swnj pti->pt_flags |= PF_PKT; 49918651Sbloom } else 5005427Swnj pti->pt_flags &= ~PF_PKT; 5018563Sroot return (0); 5027626Ssam 50318651Sbloom case TIOCUCNTL: 50418651Sbloom if (*(int *)data) { 50518651Sbloom if (pti->pt_flags & PF_PKT) 50618651Sbloom return (EINVAL); 50718651Sbloom pti->pt_flags |= PF_UCNTL; 50818651Sbloom } else 50918651Sbloom pti->pt_flags &= ~PF_UCNTL; 51018651Sbloom return (0); 51118651Sbloom 5127626Ssam case TIOCREMOTE: 5137626Ssam if (*(int *)data) 5145894Swnj pti->pt_flags |= PF_REMOTE; 5155894Swnj else 5165894Swnj pti->pt_flags &= ~PF_REMOTE; 51712753Ssam ttyflush(tp, FREAD|FWRITE); 5188563Sroot return (0); 5197626Ssam 5207626Ssam case FIONBIO: 5217626Ssam if (*(int *)data) 5225427Swnj pti->pt_flags |= PF_NBIO; 5235411Swnj else 5245427Swnj pti->pt_flags &= ~PF_NBIO; 5258563Sroot return (0); 5267626Ssam 527*35811Smarc case TIOCSETP: 52825390Skarels case TIOCSETN: 52925390Skarels case TIOCSETD: 530*35811Smarc case TIOCSETA: 531*35811Smarc case TIOCSETAW: 532*35811Smarc case TIOCSETAF: 533*35811Smarc case TIOCSETAS: 534*35811Smarc case TIOCSETAWS: 535*35811Smarc case TIOCSETAFS: 5367626Ssam while (getc(&tp->t_outq) >= 0) 5377626Ssam ; 5387626Ssam break; 5395411Swnj } 540*35811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 541*35811Smarc if (error < 0) 542*35811Smarc error = ttioctl(tp, cmd, data, flag); 54325390Skarels /* 54425390Skarels * Since we use the tty queues internally, 54525390Skarels * pty's can't be switched to disciplines which overwrite 54625390Skarels * the queues. We can't tell anything about the discipline 54725390Skarels * from here... 54825390Skarels */ 54925390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 55025390Skarels (*linesw[tp->t_line].l_close)(tp); 55125390Skarels tp->t_line = 0; 55225390Skarels (void)(*linesw[tp->t_line].l_open)(dev, tp); 55325390Skarels error = ENOTTY; 55425390Skarels } 55518651Sbloom if (error < 0) { 55618651Sbloom if (pti->pt_flags & PF_UCNTL && 55728285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 55818651Sbloom if (cmd & 0xff) { 55918651Sbloom pti->pt_ucntl = (u_char)cmd; 56018651Sbloom ptcwakeup(tp, FREAD); 56118651Sbloom } 56218651Sbloom return (0); 56318651Sbloom } 5648563Sroot error = ENOTTY; 56518651Sbloom } 566*35811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 567*35811Smarc && CCEQ(cc[VSTART], CTRL('q')); 5686119Swnj if (pti->pt_flags & PF_NOSTOP) { 5696119Swnj if (stop) { 57025478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5716119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5726119Swnj pti->pt_flags &= ~PF_NOSTOP; 57318651Sbloom ptcwakeup(tp, FREAD); 5746119Swnj } 5756119Swnj } else { 57618651Sbloom if (!stop) { 5776119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5786119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5796119Swnj pti->pt_flags |= PF_NOSTOP; 58018651Sbloom ptcwakeup(tp, FREAD); 5816119Swnj } 5826119Swnj } 5838563Sroot return (error); 5842281Stoy } 5852313Stoy #endif 586