123390Smckusick /* 238007Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 338007Sbostic * All rights reserved. 423390Smckusick * 544446Sbostic * %sccs.include.redist.c% 638007Sbostic * 7*45227Sborman * @(#)tty_pty.c 7.16 (Berkeley) 09/11/90 823390Smckusick */ 92283Stoy 102281Stoy /* 112281Stoy * Pseudo-teletype Driver 122281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 132281Stoy */ 142314Stoy #include "pty.h" 152314Stoy 163206Swnj #if NPTY > 0 1717096Sbloom #include "param.h" 1817096Sbloom #include "systm.h" 1917096Sbloom #include "ioctl.h" 2017096Sbloom #include "tty.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" 2737728Smckusick #include "vnode.h" 286239Sroot 297475Ssam #if NPTY == 1 3018651Sbloom #undef NPTY 316239Sroot #define NPTY 32 /* crude XXX */ 327475Ssam #endif 332281Stoy 3416788Ssam #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 354484Swnj 362281Stoy /* 3718651Sbloom * pts == /dev/tty[pqrs]? 3818651Sbloom * ptc == /dev/pty[pqrs]? 392281Stoy */ 404484Swnj struct tty pt_tty[NPTY]; 414484Swnj struct pt_ioctl { 425427Swnj int pt_flags; 435427Swnj struct proc *pt_selr, *pt_selw; 4418651Sbloom u_char pt_send; 4518651Sbloom u_char pt_ucntl; 464484Swnj } pt_ioctl[NPTY]; 4718651Sbloom int npty = NPTY; /* for pstat -t */ 482281Stoy 4937590Smarc int ptydebug = 0; 5037590Smarc 5135811Smarc #define PF_RCOLL 0x01 5235811Smarc #define PF_WCOLL 0x02 5335811Smarc #define PF_NBIO 0x04 5435811Smarc #define PF_PKT 0x08 /* packet mode */ 5535811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 5635811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 5735811Smarc #define PF_NOSTOP 0x40 5835811Smarc #define PF_UCNTL 0x80 /* user control mode */ 592281Stoy 602281Stoy /*ARGSUSED*/ 612281Stoy ptsopen(dev, flag) 625396Sroot dev_t dev; 634484Swnj { 642281Stoy register struct tty *tp; 6518651Sbloom int error; 662281Stoy 6718651Sbloom #ifdef lint 6818651Sbloom npty = npty; 6918651Sbloom #endif 708563Sroot if (minor(dev) >= NPTY) 718563Sroot return (ENXIO); 722281Stoy tp = &pt_tty[minor(dev)]; 735408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 7444312Smarc tp->t_state |= TS_WOPEN; 752427Swnj ttychars(tp); /* Set up default chars */ 7635811Smarc tp->t_iflag = TTYDEF_IFLAG; 7735811Smarc tp->t_oflag = TTYDEF_OFLAG; 7835811Smarc tp->t_lflag = TTYDEF_LFLAG; 7935811Smarc tp->t_cflag = TTYDEF_CFLAG; 8035811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 8135811Smarc ttsetwater(tp); /* would be done in xxparam() */ 828563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 838563Sroot return (EBUSY); 844484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 855408Swnj tp->t_state |= TS_CARR_ON; 865408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 875408Swnj tp->t_state |= TS_WOPEN; 8837590Smarc if (flag&FNDELAY) 8937590Smarc break; 9044312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 9140714Skarels ttopen, 0)) 9240714Skarels return (error); 932281Stoy } 9437590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 9518651Sbloom ptcwakeup(tp, FREAD|FWRITE); 9618651Sbloom return (error); 972281Stoy } 982281Stoy 992281Stoy ptsclose(dev) 1005396Sroot dev_t dev; 1015408Swnj { 1022281Stoy register struct tty *tp; 1032281Stoy 1042281Stoy tp = &pt_tty[minor(dev)]; 1052281Stoy (*linesw[tp->t_line].l_close)(tp); 1066299Swnj ttyclose(tp); 10718651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1082281Stoy } 1092281Stoy 11037590Smarc ptsread(dev, uio, flag) 1115396Sroot dev_t dev; 1127823Sroot struct uio *uio; 1134484Swnj { 1145894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1155894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1168521Sroot int error = 0; 1172281Stoy 1185894Swnj again: 1195894Swnj if (pti->pt_flags & PF_REMOTE) { 12039557Smarc while (isbackground(u.u_procp, tp)) { 12118651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 12218651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 12339557Smarc u.u_procp->p_pgrp->pg_jobc == 0 || 1245894Swnj u.u_procp->p_flag&SVFORK) 1258521Sroot return (EIO); 12642194Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN, 1); 12744312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 12844312Smarc TTIPRI | PCATCH, ttybg, 0)) 12940714Skarels return (error); 1305408Swnj } 13118651Sbloom if (tp->t_canq.c_cc == 0) { 13237728Smckusick if (flag & IO_NDELAY) 1338521Sroot return (EWOULDBLOCK); 13444312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 13540714Skarels TTIPRI | PCATCH, ttyin, 0)) 13640714Skarels return (error); 1375894Swnj goto again; 1385894Swnj } 13918651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 14018651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1418521Sroot error = EFAULT; 1427823Sroot break; 1437823Sroot } 14418651Sbloom if (tp->t_canq.c_cc == 1) 14518651Sbloom (void) getc(&tp->t_canq); 14618651Sbloom if (tp->t_canq.c_cc) 1478521Sroot return (error); 1485894Swnj } else 1495894Swnj if (tp->t_oproc) 15037590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 15118651Sbloom ptcwakeup(tp, FWRITE); 1528521Sroot return (error); 1532281Stoy } 1542281Stoy 1555408Swnj /* 1565408Swnj * Write to pseudo-tty. 1575408Swnj * Wakeups of controlling tty will happen 1585408Swnj * indirectly, when tty driver calls ptsstart. 1595408Swnj */ 16037590Smarc ptswrite(dev, uio, flag) 1615396Sroot dev_t dev; 1627823Sroot struct uio *uio; 1634484Swnj { 16435811Smarc register struct tty *tp; 1652281Stoy 16635811Smarc tp = &pt_tty[minor(dev)]; 1678521Sroot if (tp->t_oproc == 0) 1688521Sroot return (EIO); 16937590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1702281Stoy } 1712281Stoy 1725408Swnj /* 1735408Swnj * Start output on pseudo-tty. 1745408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1755408Swnj */ 1762281Stoy ptsstart(tp) 1774484Swnj struct tty *tp; 1784484Swnj { 1795574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1804484Swnj 1815408Swnj if (tp->t_state & TS_TTSTOP) 1822281Stoy return; 1835574Swnj if (pti->pt_flags & PF_STOPPED) { 1845574Swnj pti->pt_flags &= ~PF_STOPPED; 1855574Swnj pti->pt_send = TIOCPKT_START; 1865574Swnj } 18718651Sbloom ptcwakeup(tp, FREAD); 1885430Swnj } 1895430Swnj 19018651Sbloom ptcwakeup(tp, flag) 1915430Swnj struct tty *tp; 1925430Swnj { 1935430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1945430Swnj 19518651Sbloom if (flag & FREAD) { 19618651Sbloom if (pti->pt_selr) { 19718651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 19818651Sbloom pti->pt_selr = 0; 19918651Sbloom pti->pt_flags &= ~PF_RCOLL; 20018651Sbloom } 20118651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2024484Swnj } 20318651Sbloom if (flag & FWRITE) { 20418651Sbloom if (pti->pt_selw) { 20518651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 20618651Sbloom pti->pt_selw = 0; 20718651Sbloom pti->pt_flags &= ~PF_WCOLL; 20818651Sbloom } 20937590Smarc if (ptydebug) printf("WAKEUP c_cf %d\n", u.u_procp->p_pid); 21018651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 21118651Sbloom } 2122281Stoy } 2132281Stoy 2142281Stoy /*ARGSUSED*/ 2152281Stoy ptcopen(dev, flag) 2164484Swnj dev_t dev; 2174484Swnj int flag; 2184484Swnj { 2192281Stoy register struct tty *tp; 2205427Swnj struct pt_ioctl *pti; 2212281Stoy 2228563Sroot if (minor(dev) >= NPTY) 2238563Sroot return (ENXIO); 2242281Stoy tp = &pt_tty[minor(dev)]; 2258563Sroot if (tp->t_oproc) 2268563Sroot return (EIO); 2274484Swnj tp->t_oproc = ptsstart; 22825390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 22942895Smarc tp->t_lflag &= ~EXTPROC; 2305427Swnj pti = &pt_ioctl[minor(dev)]; 2315427Swnj pti->pt_flags = 0; 2325427Swnj pti->pt_send = 0; 23318651Sbloom pti->pt_ucntl = 0; 2348563Sroot return (0); 2352281Stoy } 2362281Stoy 2372281Stoy ptcclose(dev) 2384484Swnj dev_t dev; 2394484Swnj { 2402281Stoy register struct tty *tp; 2412281Stoy 2422281Stoy tp = &pt_tty[minor(dev)]; 24325390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 24432326Skarels tp->t_state &= ~TS_CARR_ON; 2454484Swnj tp->t_oproc = 0; /* mark closed */ 24639497Smarc tp->t_session = 0; 2472281Stoy } 2482281Stoy 24937590Smarc ptcread(dev, uio, flag) 2505427Swnj dev_t dev; 2517823Sroot struct uio *uio; 2524484Swnj { 2538521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 25418651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 25516788Ssam char buf[BUFSIZ]; 25616788Ssam int error = 0, cc; 2572281Stoy 25818651Sbloom /* 25918651Sbloom * We want to block until the slave 26018651Sbloom * is open, and there's something to read; 26118651Sbloom * but if we lost the slave or we're NBIO, 26218651Sbloom * then return the appropriate error instead. 26318651Sbloom */ 26418651Sbloom for (;;) { 26518651Sbloom if (tp->t_state&TS_ISOPEN) { 26618651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 26726358Skarels error = ureadc((int)pti->pt_send, uio); 26818651Sbloom if (error) 26918651Sbloom return (error); 27042895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 27142895Smarc cc = MIN(uio->uio_resid, 27242895Smarc sizeof(tp->t_termios)); 27342895Smarc uiomove(&tp->t_termios, cc, uio); 27442895Smarc } 27518651Sbloom pti->pt_send = 0; 27618651Sbloom return (0); 27718651Sbloom } 27818651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 27926358Skarels error = ureadc((int)pti->pt_ucntl, uio); 28018651Sbloom if (error) 28118651Sbloom return (error); 28218651Sbloom pti->pt_ucntl = 0; 28318651Sbloom return (0); 28418651Sbloom } 28518651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 28618651Sbloom break; 2875427Swnj } 28816788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 28937590Smarc return (0); /* EOF */ 29037728Smckusick if (flag & IO_NDELAY) 2918521Sroot return (EWOULDBLOCK); 29240714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 29340714Skarels ttyin, 0)) 29440714Skarels return (error); 2955411Swnj } 29635811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 29718651Sbloom error = ureadc(0, uio); 29816788Ssam while (uio->uio_resid > 0 && error == 0) { 29916788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 30016788Ssam if (cc <= 0) 3017823Sroot break; 30237728Smckusick error = uiomove(buf, cc, uio); 30316788Ssam } 30435811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 30535811Smarc if (tp->t_state&TS_ASLEEP) { 30635811Smarc tp->t_state &= ~TS_ASLEEP; 30735811Smarc wakeup((caddr_t)&tp->t_outq); 30835811Smarc } 30935811Smarc if (tp->t_wsel) { 31035811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 31135811Smarc tp->t_wsel = 0; 31235811Smarc tp->t_state &= ~TS_WCOLL; 31335811Smarc } 31435811Smarc } 3158521Sroot return (error); 3162281Stoy } 3172281Stoy 3185427Swnj ptsstop(tp, flush) 3195427Swnj register struct tty *tp; 3205427Swnj int flush; 3215427Swnj { 3225427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 32318651Sbloom int flag; 3245427Swnj 3255574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3265574Swnj if (flush == 0) { 3275574Swnj flush = TIOCPKT_STOP; 3285574Swnj pti->pt_flags |= PF_STOPPED; 32918651Sbloom } else 3305574Swnj pti->pt_flags &= ~PF_STOPPED; 3316119Swnj pti->pt_send |= flush; 33218651Sbloom /* change of perspective */ 33318651Sbloom flag = 0; 33418651Sbloom if (flush & FREAD) 33518651Sbloom flag |= FWRITE; 33618651Sbloom if (flush & FWRITE) 33718651Sbloom flag |= FREAD; 33823633Sbloom ptcwakeup(tp, flag); 3395427Swnj } 3405427Swnj 3415408Swnj ptcselect(dev, rw) 3424484Swnj dev_t dev; 3435408Swnj int rw; 3444484Swnj { 3454484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3465894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3474484Swnj struct proc *p; 3485430Swnj int s; 3494484Swnj 35018651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3514484Swnj return (1); 3525408Swnj switch (rw) { 3535408Swnj 3545408Swnj case FREAD: 35525945Skarels /* 35625945Skarels * Need to block timeouts (ttrstart). 35725945Skarels */ 35825945Skarels s = spltty(); 35918651Sbloom if ((tp->t_state&TS_ISOPEN) && 36025436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 36125436Skarels splx(s); 36225436Skarels return (1); 36325436Skarels } 36425945Skarels splx(s); 36525436Skarels /* FALLTHROUGH */ 36625436Skarels 36725436Skarels case 0: /* exceptional */ 36825436Skarels if ((tp->t_state&TS_ISOPEN) && 36918651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 37025945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3715408Swnj return (1); 3725427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3735427Swnj pti->pt_flags |= PF_RCOLL; 3745408Swnj else 3755427Swnj pti->pt_selr = u.u_procp; 3765430Swnj break; 3775408Swnj 37825436Skarels 3795408Swnj case FWRITE: 38025945Skarels if (tp->t_state&TS_ISOPEN) { 38125945Skarels if (pti->pt_flags & PF_REMOTE) { 38225945Skarels if (tp->t_canq.c_cc == 0) 38325945Skarels return (1); 38425945Skarels } else { 38525945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 38625945Skarels return (1); 38735811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 38825945Skarels return (1); 38925945Skarels } 3905430Swnj } 3915427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3925427Swnj pti->pt_flags |= PF_WCOLL; 3935408Swnj else 3945427Swnj pti->pt_selw = u.u_procp; 3955430Swnj break; 39625436Skarels 3975408Swnj } 3985430Swnj return (0); 3995396Sroot } 4004484Swnj 40137590Smarc ptcwrite(dev, uio, flag) 4025408Swnj dev_t dev; 40318651Sbloom register struct uio *uio; 4044484Swnj { 4058521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 40618651Sbloom register struct iovec *iov; 40718651Sbloom register char *cp; 40818651Sbloom register int cc = 0; 4092281Stoy char locbuf[BUFSIZ]; 4105408Swnj int cnt = 0; 4115894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4128521Sroot int error = 0; 4132281Stoy 41418651Sbloom again: 41518651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41618651Sbloom goto block; 41723633Sbloom if (pti->pt_flags & PF_REMOTE) { 41818651Sbloom if (tp->t_canq.c_cc) 41918651Sbloom goto block; 42023633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 42123633Sbloom iov = uio->uio_iov; 42223633Sbloom if (iov->iov_len == 0) { 42323633Sbloom uio->uio_iovcnt--; 42423633Sbloom uio->uio_iov++; 42523633Sbloom continue; 42623633Sbloom } 42723633Sbloom if (cc == 0) { 42823633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 42923633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 43023633Sbloom cp = locbuf; 43137728Smckusick error = uiomove(cp, cc, uio); 43223633Sbloom if (error) 43323633Sbloom return (error); 43423633Sbloom /* check again for safety */ 43523633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43623633Sbloom return (EIO); 43723633Sbloom } 43823633Sbloom if (cc) 43923633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 44023633Sbloom cc = 0; 4417823Sroot } 44218651Sbloom (void) putc(0, &tp->t_canq); 44318651Sbloom ttwakeup(tp); 44418651Sbloom wakeup((caddr_t)&tp->t_canq); 44518651Sbloom return (0); 44618651Sbloom } 44718651Sbloom while (uio->uio_iovcnt > 0) { 44818651Sbloom iov = uio->uio_iov; 44918651Sbloom if (cc == 0) { 45018651Sbloom if (iov->iov_len == 0) { 45118651Sbloom uio->uio_iovcnt--; 45218651Sbloom uio->uio_iov++; 45318651Sbloom continue; 4545894Swnj } 45518651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 45618651Sbloom cp = locbuf; 45737728Smckusick error = uiomove(cp, cc, uio); 45818651Sbloom if (error) 45918651Sbloom return (error); 46018651Sbloom /* check again for safety */ 46118651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 46218651Sbloom return (EIO); 4635894Swnj } 46423633Sbloom while (cc > 0) { 46523633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 46635811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 46723633Sbloom wakeup((caddr_t)&tp->t_rawq); 46823633Sbloom goto block; 46923633Sbloom } 47037590Smarc (*linesw[tp->t_line].l_rint)(*cp++&0377, tp); 4715408Swnj cnt++; 47223633Sbloom cc--; 4732281Stoy } 47418651Sbloom cc = 0; 47518651Sbloom } 47618651Sbloom return (0); 47718651Sbloom block: 47818651Sbloom /* 47923633Sbloom * Come here to wait for slave to open, for space 48023633Sbloom * in outq, or space in rawq. 48118651Sbloom */ 48218651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 48318651Sbloom return (EIO); 48437728Smckusick if ((pti->pt_flags & PF_NBIO) || (flag & IO_NDELAY)) { 48518651Sbloom iov->iov_base -= cc; 48618651Sbloom iov->iov_len += cc; 48718651Sbloom uio->uio_resid += cc; 48818651Sbloom uio->uio_offset -= cc; 48923633Sbloom if (cnt == 0) 49023633Sbloom return (EWOULDBLOCK); 49118651Sbloom return (0); 49218651Sbloom } 49340714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 49440714Skarels ttyout, 0)) 49540714Skarels return (error); 49618651Sbloom goto again; 4972281Stoy } 4982281Stoy 4992281Stoy /*ARGSUSED*/ 5007626Ssam ptyioctl(dev, cmd, data, flag) 5017626Ssam caddr_t data; 5024484Swnj dev_t dev; 5034484Swnj { 5046119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5056119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 50635811Smarc register u_char *cc = tp->t_cc; 50718651Sbloom int stop, error; 50825390Skarels extern ttyinput(); 5092281Stoy 51025390Skarels /* 51125390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 51225390Skarels * ttywflush(tp) will hang if there are characters in the outq. 51325390Skarels */ 51442895Smarc if (cmd == TIOCEXT) { 51542895Smarc /* 51642895Smarc * When the EXTPROC bit is being toggled, we need 51742895Smarc * to send an TIOCPKT_IOCTL if the packet driver 51842895Smarc * is turned on. 51942895Smarc */ 52042895Smarc if (*(int *)data) { 52142895Smarc if (pti->pt_flags & PF_PKT) { 52242895Smarc pti->pt_send |= TIOCPKT_IOCTL; 52342895Smarc ptcwakeup(tp); 52442895Smarc } 52542895Smarc tp->t_lflag |= EXTPROC; 52642895Smarc } else { 52742895Smarc if ((tp->t_state & EXTPROC) && 52842895Smarc (pti->pt_flags & PF_PKT)) { 52942895Smarc pti->pt_send |= TIOCPKT_IOCTL; 53042895Smarc ptcwakeup(tp); 53142895Smarc } 53242895Smarc tp->t_lflag &= ~EXTPROC; 53342895Smarc } 53442895Smarc return(0); 53542895Smarc } else 53635811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5377626Ssam switch (cmd) { 5387626Ssam 53944313Smarc case TIOCGPGRP: 54044313Smarc /* 54144313Smarc * We aviod calling ttioctl on the controller since, 54244313Smarc * in that case, tp must be the controlling terminal. 54344313Smarc */ 54444313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 54544313Smarc return (0); 54644313Smarc 5477626Ssam case TIOCPKT: 54818651Sbloom if (*(int *)data) { 54918651Sbloom if (pti->pt_flags & PF_UCNTL) 55018651Sbloom return (EINVAL); 5515427Swnj pti->pt_flags |= PF_PKT; 55218651Sbloom } else 5535427Swnj pti->pt_flags &= ~PF_PKT; 5548563Sroot return (0); 5557626Ssam 55618651Sbloom case TIOCUCNTL: 55718651Sbloom if (*(int *)data) { 55818651Sbloom if (pti->pt_flags & PF_PKT) 55918651Sbloom return (EINVAL); 56018651Sbloom pti->pt_flags |= PF_UCNTL; 56118651Sbloom } else 56218651Sbloom pti->pt_flags &= ~PF_UCNTL; 56318651Sbloom return (0); 56418651Sbloom 5657626Ssam case TIOCREMOTE: 5667626Ssam if (*(int *)data) 5675894Swnj pti->pt_flags |= PF_REMOTE; 5685894Swnj else 5695894Swnj pti->pt_flags &= ~PF_REMOTE; 57012753Ssam ttyflush(tp, FREAD|FWRITE); 5718563Sroot return (0); 5727626Ssam 5737626Ssam case FIONBIO: 5747626Ssam if (*(int *)data) 5755427Swnj pti->pt_flags |= PF_NBIO; 5765411Swnj else 5775427Swnj pti->pt_flags &= ~PF_NBIO; 5788563Sroot return (0); 5797626Ssam 58035811Smarc case TIOCSETP: 58125390Skarels case TIOCSETN: 58225390Skarels case TIOCSETD: 58335811Smarc case TIOCSETA: 58435811Smarc case TIOCSETAW: 58535811Smarc case TIOCSETAF: 58639497Smarc case JUNK_TIOCSETAS: 58739497Smarc case JUNK_TIOCSETAWS: 58839497Smarc case JUNK_TIOCSETAFS: 5897626Ssam while (getc(&tp->t_outq) >= 0) 5907626Ssam ; 5917626Ssam break; 59242895Smarc 59342895Smarc case TIOCSIG: 59442895Smarc if (*(unsigned int *)data >= NSIG) 59542895Smarc return(EINVAL); 59642895Smarc if ((tp->t_lflag&NOFLSH) == 0) 59742895Smarc ttyflush(tp, FREAD|FWRITE); 598*45227Sborman pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 599*45227Sborman if ((*(unsigned int *)data == SIGINFO) && 600*45227Sborman ((tp->t_lflag&NOKERNINFO) == 0)) 601*45227Sborman ttyinfo(tp); 60242895Smarc return(0); 6035411Swnj } 60435811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 60535811Smarc if (error < 0) 60635811Smarc error = ttioctl(tp, cmd, data, flag); 60725390Skarels /* 60825390Skarels * Since we use the tty queues internally, 60925390Skarels * pty's can't be switched to disciplines which overwrite 61025390Skarels * the queues. We can't tell anything about the discipline 61125390Skarels * from here... 61225390Skarels */ 61325390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 61425390Skarels (*linesw[tp->t_line].l_close)(tp); 61525390Skarels tp->t_line = 0; 61637590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 61725390Skarels error = ENOTTY; 61825390Skarels } 61918651Sbloom if (error < 0) { 62018651Sbloom if (pti->pt_flags & PF_UCNTL && 62128285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 62218651Sbloom if (cmd & 0xff) { 62318651Sbloom pti->pt_ucntl = (u_char)cmd; 62418651Sbloom ptcwakeup(tp, FREAD); 62518651Sbloom } 62618651Sbloom return (0); 62718651Sbloom } 6288563Sroot error = ENOTTY; 62918651Sbloom } 63042895Smarc /* 63142895Smarc * If external processing and packet mode send ioctl packet. 63242895Smarc */ 63342895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 63442895Smarc switch(cmd) { 63542895Smarc case TIOCSETA: 63642895Smarc case TIOCSETAW: 63742895Smarc case TIOCSETAF: 63842895Smarc case JUNK_TIOCSETAS: 63942895Smarc case JUNK_TIOCSETAWS: 64042895Smarc case JUNK_TIOCSETAFS: 64142895Smarc case TIOCSETP: 64242895Smarc case TIOCSETN: 64342895Smarc #ifdef COMPAT_43 64442895Smarc case TIOCSETC: 64542895Smarc case TIOCSLTC: 64642895Smarc case TIOCLBIS: 64742895Smarc case TIOCLBIC: 64842895Smarc case TIOCLSET: 64942895Smarc #endif 65042895Smarc pti->pt_send |= TIOCPKT_IOCTL; 65142895Smarc default: 65242895Smarc break; 65342895Smarc } 65442895Smarc } 65535811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 65635811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6576119Swnj if (pti->pt_flags & PF_NOSTOP) { 6586119Swnj if (stop) { 65925478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6606119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6616119Swnj pti->pt_flags &= ~PF_NOSTOP; 66218651Sbloom ptcwakeup(tp, FREAD); 6636119Swnj } 6646119Swnj } else { 66518651Sbloom if (!stop) { 6666119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6676119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6686119Swnj pti->pt_flags |= PF_NOSTOP; 66918651Sbloom ptcwakeup(tp, FREAD); 6706119Swnj } 6716119Swnj } 6728563Sroot return (error); 6732281Stoy } 6742313Stoy #endif 675