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*37590Smarc * @(#)tty_pty.c 7.5 (Berkeley) 05/01/89 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*37590Smarc int ptydebug = 0; 49*37590Smarc 5035811Smarc #define PF_RCOLL 0x01 5135811Smarc #define PF_WCOLL 0x02 5235811Smarc #define PF_NBIO 0x04 5335811Smarc #define PF_PKT 0x08 /* packet mode */ 5435811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 5535811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 5635811Smarc #define PF_NOSTOP 0x40 5735811Smarc #define PF_UCNTL 0x80 /* user control mode */ 582281Stoy 592281Stoy /*ARGSUSED*/ 602281Stoy ptsopen(dev, flag) 615396Sroot dev_t dev; 624484Swnj { 632281Stoy register struct tty *tp; 6418651Sbloom int error; 652281Stoy 6618651Sbloom #ifdef lint 6718651Sbloom npty = npty; 6818651Sbloom #endif 698563Sroot if (minor(dev) >= NPTY) 708563Sroot return (ENXIO); 712281Stoy tp = &pt_tty[minor(dev)]; 725408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 732427Swnj ttychars(tp); /* Set up default chars */ 7435811Smarc tp->t_iflag = TTYDEF_IFLAG; 7535811Smarc tp->t_oflag = TTYDEF_OFLAG; 7635811Smarc tp->t_lflag = TTYDEF_LFLAG; 7735811Smarc tp->t_cflag = TTYDEF_CFLAG; 7835811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 7935811Smarc ttsetwater(tp); /* would be done in xxparam() */ 808563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 818563Sroot return (EBUSY); 824484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 835408Swnj tp->t_state |= TS_CARR_ON; 845408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 855408Swnj tp->t_state |= TS_WOPEN; 86*37590Smarc if (flag&FNDELAY) 87*37590Smarc break; 882281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 892281Stoy } 90*37590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 9118651Sbloom ptcwakeup(tp, FREAD|FWRITE); 9218651Sbloom return (error); 932281Stoy } 942281Stoy 952281Stoy ptsclose(dev) 965396Sroot dev_t dev; 975408Swnj { 982281Stoy register struct tty *tp; 992281Stoy 1002281Stoy tp = &pt_tty[minor(dev)]; 1012281Stoy (*linesw[tp->t_line].l_close)(tp); 1026299Swnj ttyclose(tp); 10318651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1042281Stoy } 1052281Stoy 106*37590Smarc ptsread(dev, uio, flag) 1075396Sroot dev_t dev; 1087823Sroot struct uio *uio; 1094484Swnj { 1105894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1115894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1128521Sroot int error = 0; 1132281Stoy 1145894Swnj again: 1155894Swnj if (pti->pt_flags & PF_REMOTE) { 11635811Smarc while (tp == u.u_ttyp && 11735811Smarc u.u_procp->p_pgrp->pg_id != tp->t_pgid){ 11818651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 11918651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 12035811Smarc !u.u_procp->p_pgrp->pg_jobc || 1215894Swnj u.u_procp->p_flag&SVFORK) 1228521Sroot return (EIO); 12335811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1245894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1255408Swnj } 12618651Sbloom if (tp->t_canq.c_cc == 0) { 127*37590Smarc if (flag & FNDELAY) 1288521Sroot return (EWOULDBLOCK); 12918651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1305894Swnj goto again; 1315894Swnj } 13218651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 13318651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1348521Sroot error = EFAULT; 1357823Sroot break; 1367823Sroot } 13718651Sbloom if (tp->t_canq.c_cc == 1) 13818651Sbloom (void) getc(&tp->t_canq); 13918651Sbloom if (tp->t_canq.c_cc) 1408521Sroot return (error); 1415894Swnj } else 1425894Swnj if (tp->t_oproc) 143*37590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 14418651Sbloom ptcwakeup(tp, FWRITE); 1458521Sroot return (error); 1462281Stoy } 1472281Stoy 1485408Swnj /* 1495408Swnj * Write to pseudo-tty. 1505408Swnj * Wakeups of controlling tty will happen 1515408Swnj * indirectly, when tty driver calls ptsstart. 1525408Swnj */ 153*37590Smarc ptswrite(dev, uio, flag) 1545396Sroot dev_t dev; 1557823Sroot struct uio *uio; 1564484Swnj { 15735811Smarc register struct tty *tp; 1582281Stoy 15935811Smarc tp = &pt_tty[minor(dev)]; 1608521Sroot if (tp->t_oproc == 0) 1618521Sroot return (EIO); 162*37590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1632281Stoy } 1642281Stoy 1655408Swnj /* 1665408Swnj * Start output on pseudo-tty. 1675408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1685408Swnj */ 1692281Stoy ptsstart(tp) 1704484Swnj struct tty *tp; 1714484Swnj { 1725574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1734484Swnj 1745408Swnj if (tp->t_state & TS_TTSTOP) 1752281Stoy return; 1765574Swnj if (pti->pt_flags & PF_STOPPED) { 1775574Swnj pti->pt_flags &= ~PF_STOPPED; 1785574Swnj pti->pt_send = TIOCPKT_START; 1795574Swnj } 18018651Sbloom ptcwakeup(tp, FREAD); 1815430Swnj } 1825430Swnj 18318651Sbloom ptcwakeup(tp, flag) 1845430Swnj struct tty *tp; 1855430Swnj { 1865430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1875430Swnj 18818651Sbloom if (flag & FREAD) { 18918651Sbloom if (pti->pt_selr) { 19018651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 19118651Sbloom pti->pt_selr = 0; 19218651Sbloom pti->pt_flags &= ~PF_RCOLL; 19318651Sbloom } 19418651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 1954484Swnj } 19618651Sbloom if (flag & FWRITE) { 19718651Sbloom if (pti->pt_selw) { 19818651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 19918651Sbloom pti->pt_selw = 0; 20018651Sbloom pti->pt_flags &= ~PF_WCOLL; 20118651Sbloom } 202*37590Smarc if (ptydebug) printf("WAKEUP c_cf %d\n", u.u_procp->p_pid); 20318651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 20418651Sbloom } 2052281Stoy } 2062281Stoy 2072281Stoy /*ARGSUSED*/ 2082281Stoy ptcopen(dev, flag) 2094484Swnj dev_t dev; 2104484Swnj int flag; 2114484Swnj { 2122281Stoy register struct tty *tp; 2135427Swnj struct pt_ioctl *pti; 2142281Stoy 2158563Sroot if (minor(dev) >= NPTY) 2168563Sroot return (ENXIO); 2172281Stoy tp = &pt_tty[minor(dev)]; 2188563Sroot if (tp->t_oproc) 2198563Sroot return (EIO); 2204484Swnj tp->t_oproc = ptsstart; 22125390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2225427Swnj pti = &pt_ioctl[minor(dev)]; 2235427Swnj pti->pt_flags = 0; 2245427Swnj pti->pt_send = 0; 22518651Sbloom pti->pt_ucntl = 0; 2268563Sroot return (0); 2272281Stoy } 2282281Stoy 2292281Stoy ptcclose(dev) 2304484Swnj dev_t dev; 2314484Swnj { 2322281Stoy register struct tty *tp; 2332281Stoy 2342281Stoy tp = &pt_tty[minor(dev)]; 23525390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 23632326Skarels tp->t_state &= ~TS_CARR_ON; 2374484Swnj tp->t_oproc = 0; /* mark closed */ 2382281Stoy } 2392281Stoy 240*37590Smarc ptcread(dev, uio, flag) 2415427Swnj dev_t dev; 2427823Sroot struct uio *uio; 2434484Swnj { 2448521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 24518651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 24616788Ssam char buf[BUFSIZ]; 24716788Ssam int error = 0, cc; 2482281Stoy 24918651Sbloom /* 25018651Sbloom * We want to block until the slave 25118651Sbloom * is open, and there's something to read; 25218651Sbloom * but if we lost the slave or we're NBIO, 25318651Sbloom * then return the appropriate error instead. 25418651Sbloom */ 25518651Sbloom for (;;) { 25618651Sbloom if (tp->t_state&TS_ISOPEN) { 25718651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 25826358Skarels error = ureadc((int)pti->pt_send, uio); 25918651Sbloom if (error) 26018651Sbloom return (error); 26118651Sbloom pti->pt_send = 0; 26218651Sbloom return (0); 26318651Sbloom } 26418651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 26526358Skarels error = ureadc((int)pti->pt_ucntl, uio); 26618651Sbloom if (error) 26718651Sbloom return (error); 26818651Sbloom pti->pt_ucntl = 0; 26918651Sbloom return (0); 27018651Sbloom } 27118651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 27218651Sbloom break; 2735427Swnj } 27416788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 275*37590Smarc return (0); /* EOF */ 276*37590Smarc if (flag&FNDELAY) 2778521Sroot return (EWOULDBLOCK); 278*37590Smarc if (ptydebug) printf("SLEEP(1) c_cf %d\n", u.u_procp->p_pid); 2792281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2805411Swnj } 28135811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 28218651Sbloom error = ureadc(0, uio); 28316788Ssam while (uio->uio_resid > 0 && error == 0) { 28416788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 28516788Ssam if (cc <= 0) 2867823Sroot break; 28716788Ssam error = uiomove(buf, cc, UIO_READ, uio); 28816788Ssam } 28935811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 29035811Smarc if (tp->t_state&TS_ASLEEP) { 29135811Smarc tp->t_state &= ~TS_ASLEEP; 29235811Smarc wakeup((caddr_t)&tp->t_outq); 29335811Smarc } 29435811Smarc if (tp->t_wsel) { 29535811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 29635811Smarc tp->t_wsel = 0; 29735811Smarc tp->t_state &= ~TS_WCOLL; 29835811Smarc } 29935811Smarc } 3008521Sroot return (error); 3012281Stoy } 3022281Stoy 3035427Swnj ptsstop(tp, flush) 3045427Swnj register struct tty *tp; 3055427Swnj int flush; 3065427Swnj { 3075427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 30818651Sbloom int flag; 3095427Swnj 3105574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3115574Swnj if (flush == 0) { 3125574Swnj flush = TIOCPKT_STOP; 3135574Swnj pti->pt_flags |= PF_STOPPED; 31418651Sbloom } else 3155574Swnj pti->pt_flags &= ~PF_STOPPED; 3166119Swnj pti->pt_send |= flush; 31718651Sbloom /* change of perspective */ 31818651Sbloom flag = 0; 31918651Sbloom if (flush & FREAD) 32018651Sbloom flag |= FWRITE; 32118651Sbloom if (flush & FWRITE) 32218651Sbloom flag |= FREAD; 32323633Sbloom ptcwakeup(tp, flag); 3245427Swnj } 3255427Swnj 3265408Swnj ptcselect(dev, rw) 3274484Swnj dev_t dev; 3285408Swnj int rw; 3294484Swnj { 3304484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3315894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3324484Swnj struct proc *p; 3335430Swnj int s; 3344484Swnj 33518651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3364484Swnj return (1); 3375408Swnj switch (rw) { 3385408Swnj 3395408Swnj case FREAD: 34025945Skarels /* 34125945Skarels * Need to block timeouts (ttrstart). 34225945Skarels */ 34325945Skarels s = spltty(); 34418651Sbloom if ((tp->t_state&TS_ISOPEN) && 34525436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 34625436Skarels splx(s); 34725436Skarels return (1); 34825436Skarels } 34925945Skarels splx(s); 35025436Skarels /* FALLTHROUGH */ 35125436Skarels 35225436Skarels case 0: /* exceptional */ 35325436Skarels if ((tp->t_state&TS_ISOPEN) && 35418651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 35525945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3565408Swnj return (1); 3575427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3585427Swnj pti->pt_flags |= PF_RCOLL; 3595408Swnj else 3605427Swnj pti->pt_selr = u.u_procp; 3615430Swnj break; 3625408Swnj 36325436Skarels 3645408Swnj case FWRITE: 36525945Skarels if (tp->t_state&TS_ISOPEN) { 36625945Skarels if (pti->pt_flags & PF_REMOTE) { 36725945Skarels if (tp->t_canq.c_cc == 0) 36825945Skarels return (1); 36925945Skarels } else { 37025945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 37125945Skarels return (1); 37235811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 37325945Skarels return (1); 37425945Skarels } 3755430Swnj } 3765427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3775427Swnj pti->pt_flags |= PF_WCOLL; 3785408Swnj else 3795427Swnj pti->pt_selw = u.u_procp; 3805430Swnj break; 38125436Skarels 3825408Swnj } 3835430Swnj return (0); 3845396Sroot } 3854484Swnj 386*37590Smarc ptcwrite(dev, uio, flag) 3875408Swnj dev_t dev; 38818651Sbloom register struct uio *uio; 3894484Swnj { 3908521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 39118651Sbloom register struct iovec *iov; 39218651Sbloom register char *cp; 39318651Sbloom register int cc = 0; 3942281Stoy char locbuf[BUFSIZ]; 3955408Swnj int cnt = 0; 3965894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3978521Sroot int error = 0; 3982281Stoy 39918651Sbloom again: 40018651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 40118651Sbloom goto block; 40223633Sbloom if (pti->pt_flags & PF_REMOTE) { 40318651Sbloom if (tp->t_canq.c_cc) 40418651Sbloom goto block; 40523633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 40623633Sbloom iov = uio->uio_iov; 40723633Sbloom if (iov->iov_len == 0) { 40823633Sbloom uio->uio_iovcnt--; 40923633Sbloom uio->uio_iov++; 41023633Sbloom continue; 41123633Sbloom } 41223633Sbloom if (cc == 0) { 41323633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 41423633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 41523633Sbloom cp = locbuf; 41623633Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 41723633Sbloom if (error) 41823633Sbloom return (error); 41923633Sbloom /* check again for safety */ 42023633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42123633Sbloom return (EIO); 42223633Sbloom } 42323633Sbloom if (cc) 42423633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 42523633Sbloom cc = 0; 4267823Sroot } 42718651Sbloom (void) putc(0, &tp->t_canq); 42818651Sbloom ttwakeup(tp); 42918651Sbloom wakeup((caddr_t)&tp->t_canq); 43018651Sbloom return (0); 43118651Sbloom } 43218651Sbloom while (uio->uio_iovcnt > 0) { 43318651Sbloom iov = uio->uio_iov; 43418651Sbloom if (cc == 0) { 43518651Sbloom if (iov->iov_len == 0) { 43618651Sbloom uio->uio_iovcnt--; 43718651Sbloom uio->uio_iov++; 43818651Sbloom continue; 4395894Swnj } 44018651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 44118651Sbloom cp = locbuf; 44218651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 44318651Sbloom if (error) 44418651Sbloom return (error); 44518651Sbloom /* check again for safety */ 44618651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 44718651Sbloom return (EIO); 4485894Swnj } 44923633Sbloom while (cc > 0) { 45023633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 45135811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 45223633Sbloom wakeup((caddr_t)&tp->t_rawq); 45323633Sbloom goto block; 45423633Sbloom } 455*37590Smarc (*linesw[tp->t_line].l_rint)(*cp++&0377, tp); 4565408Swnj cnt++; 45723633Sbloom cc--; 4582281Stoy } 45918651Sbloom cc = 0; 46018651Sbloom } 46118651Sbloom return (0); 46218651Sbloom block: 46318651Sbloom /* 46423633Sbloom * Come here to wait for slave to open, for space 46523633Sbloom * in outq, or space in rawq. 46618651Sbloom */ 46718651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 46818651Sbloom return (EIO); 469*37590Smarc if ((pti->pt_flags & PF_NBIO) || (flag & FNDELAY)) { 47018651Sbloom iov->iov_base -= cc; 47118651Sbloom iov->iov_len += cc; 47218651Sbloom uio->uio_resid += cc; 47318651Sbloom uio->uio_offset -= cc; 47423633Sbloom if (cnt == 0) 47523633Sbloom return (EWOULDBLOCK); 47618651Sbloom return (0); 47718651Sbloom } 478*37590Smarc if (ptydebug) printf("SLEEP(2) c_cf %d\n", u.u_procp->p_pid); 47918651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 48018651Sbloom goto again; 4812281Stoy } 4822281Stoy 4832281Stoy /*ARGSUSED*/ 4847626Ssam ptyioctl(dev, cmd, data, flag) 4857626Ssam caddr_t data; 4864484Swnj dev_t dev; 4874484Swnj { 4886119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4896119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 49035811Smarc register u_char *cc = tp->t_cc; 49118651Sbloom int stop, error; 49225390Skarels extern ttyinput(); 4932281Stoy 49425390Skarels /* 49525390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 49625390Skarels * ttywflush(tp) will hang if there are characters in the outq. 49725390Skarels */ 49835811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 4997626Ssam switch (cmd) { 5007626Ssam 5017626Ssam case TIOCPKT: 50218651Sbloom if (*(int *)data) { 50318651Sbloom if (pti->pt_flags & PF_UCNTL) 50418651Sbloom return (EINVAL); 5055427Swnj pti->pt_flags |= PF_PKT; 50618651Sbloom } else 5075427Swnj pti->pt_flags &= ~PF_PKT; 5088563Sroot return (0); 5097626Ssam 51018651Sbloom case TIOCUCNTL: 51118651Sbloom if (*(int *)data) { 51218651Sbloom if (pti->pt_flags & PF_PKT) 51318651Sbloom return (EINVAL); 51418651Sbloom pti->pt_flags |= PF_UCNTL; 51518651Sbloom } else 51618651Sbloom pti->pt_flags &= ~PF_UCNTL; 51718651Sbloom return (0); 51818651Sbloom 5197626Ssam case TIOCREMOTE: 5207626Ssam if (*(int *)data) 5215894Swnj pti->pt_flags |= PF_REMOTE; 5225894Swnj else 5235894Swnj pti->pt_flags &= ~PF_REMOTE; 52412753Ssam ttyflush(tp, FREAD|FWRITE); 5258563Sroot return (0); 5267626Ssam 5277626Ssam case FIONBIO: 5287626Ssam if (*(int *)data) 5295427Swnj pti->pt_flags |= PF_NBIO; 5305411Swnj else 5315427Swnj pti->pt_flags &= ~PF_NBIO; 5328563Sroot return (0); 5337626Ssam 53435811Smarc case TIOCSETP: 53525390Skarels case TIOCSETN: 53625390Skarels case TIOCSETD: 53735811Smarc case TIOCSETA: 53835811Smarc case TIOCSETAW: 53935811Smarc case TIOCSETAF: 54035811Smarc case TIOCSETAS: 54135811Smarc case TIOCSETAWS: 54235811Smarc case TIOCSETAFS: 5437626Ssam while (getc(&tp->t_outq) >= 0) 5447626Ssam ; 5457626Ssam break; 5465411Swnj } 54735811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 54835811Smarc if (error < 0) 54935811Smarc error = ttioctl(tp, cmd, data, flag); 55025390Skarels /* 55125390Skarels * Since we use the tty queues internally, 55225390Skarels * pty's can't be switched to disciplines which overwrite 55325390Skarels * the queues. We can't tell anything about the discipline 55425390Skarels * from here... 55525390Skarels */ 55625390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 55725390Skarels (*linesw[tp->t_line].l_close)(tp); 55825390Skarels tp->t_line = 0; 559*37590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 56025390Skarels error = ENOTTY; 56125390Skarels } 56218651Sbloom if (error < 0) { 56318651Sbloom if (pti->pt_flags & PF_UCNTL && 56428285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 56518651Sbloom if (cmd & 0xff) { 56618651Sbloom pti->pt_ucntl = (u_char)cmd; 56718651Sbloom ptcwakeup(tp, FREAD); 56818651Sbloom } 56918651Sbloom return (0); 57018651Sbloom } 5718563Sroot error = ENOTTY; 57218651Sbloom } 57335811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 57435811Smarc && CCEQ(cc[VSTART], CTRL('q')); 5756119Swnj if (pti->pt_flags & PF_NOSTOP) { 5766119Swnj if (stop) { 57725478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5786119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5796119Swnj pti->pt_flags &= ~PF_NOSTOP; 58018651Sbloom ptcwakeup(tp, FREAD); 5816119Swnj } 5826119Swnj } else { 58318651Sbloom if (!stop) { 5846119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5856119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5866119Swnj pti->pt_flags |= PF_NOSTOP; 58718651Sbloom ptcwakeup(tp, FREAD); 5886119Swnj } 5896119Swnj } 5908563Sroot return (error); 5912281Stoy } 5922313Stoy #endif 593