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*40714Skarels * @(#)tty_pty.c 7.10 (Berkeley) 04/03/90 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; 99*40714Skarels if (error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 100*40714Skarels ttopen, 0)) 101*40714Skarels return (error); 1022281Stoy } 10337590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 10418651Sbloom ptcwakeup(tp, FREAD|FWRITE); 10518651Sbloom return (error); 1062281Stoy } 1072281Stoy 1082281Stoy ptsclose(dev) 1095396Sroot dev_t dev; 1105408Swnj { 1112281Stoy register struct tty *tp; 1122281Stoy 1132281Stoy tp = &pt_tty[minor(dev)]; 1142281Stoy (*linesw[tp->t_line].l_close)(tp); 1156299Swnj ttyclose(tp); 11618651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1172281Stoy } 1182281Stoy 11937590Smarc ptsread(dev, uio, flag) 1205396Sroot dev_t dev; 1217823Sroot struct uio *uio; 1224484Swnj { 1235894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1245894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1258521Sroot int error = 0; 1262281Stoy 1275894Swnj again: 1285894Swnj if (pti->pt_flags & PF_REMOTE) { 12939557Smarc while (isbackground(u.u_procp, tp)) { 13018651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 13118651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 13239557Smarc u.u_procp->p_pgrp->pg_jobc == 0 || 1335894Swnj u.u_procp->p_flag&SVFORK) 1348521Sroot return (EIO); 13535811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 136*40714Skarels if (error = tsleep((caddr_t)&lbolt, TTIPRI | PCATCH, 137*40714Skarels ttybg, 0)) 138*40714Skarels return (error); 1395408Swnj } 14018651Sbloom if (tp->t_canq.c_cc == 0) { 14137728Smckusick if (flag & IO_NDELAY) 1428521Sroot return (EWOULDBLOCK); 143*40714Skarels if (error = tsleep((caddr_t)&tp->t_canq, 144*40714Skarels TTIPRI | PCATCH, ttyin, 0)) 145*40714Skarels return (error); 1465894Swnj goto again; 1475894Swnj } 14818651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 14918651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1508521Sroot error = EFAULT; 1517823Sroot break; 1527823Sroot } 15318651Sbloom if (tp->t_canq.c_cc == 1) 15418651Sbloom (void) getc(&tp->t_canq); 15518651Sbloom if (tp->t_canq.c_cc) 1568521Sroot return (error); 1575894Swnj } else 1585894Swnj if (tp->t_oproc) 15937590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 16018651Sbloom ptcwakeup(tp, FWRITE); 1618521Sroot return (error); 1622281Stoy } 1632281Stoy 1645408Swnj /* 1655408Swnj * Write to pseudo-tty. 1665408Swnj * Wakeups of controlling tty will happen 1675408Swnj * indirectly, when tty driver calls ptsstart. 1685408Swnj */ 16937590Smarc ptswrite(dev, uio, flag) 1705396Sroot dev_t dev; 1717823Sroot struct uio *uio; 1724484Swnj { 17335811Smarc register struct tty *tp; 1742281Stoy 17535811Smarc tp = &pt_tty[minor(dev)]; 1768521Sroot if (tp->t_oproc == 0) 1778521Sroot return (EIO); 17837590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1792281Stoy } 1802281Stoy 1815408Swnj /* 1825408Swnj * Start output on pseudo-tty. 1835408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1845408Swnj */ 1852281Stoy ptsstart(tp) 1864484Swnj struct tty *tp; 1874484Swnj { 1885574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1894484Swnj 1905408Swnj if (tp->t_state & TS_TTSTOP) 1912281Stoy return; 1925574Swnj if (pti->pt_flags & PF_STOPPED) { 1935574Swnj pti->pt_flags &= ~PF_STOPPED; 1945574Swnj pti->pt_send = TIOCPKT_START; 1955574Swnj } 19618651Sbloom ptcwakeup(tp, FREAD); 1975430Swnj } 1985430Swnj 19918651Sbloom ptcwakeup(tp, flag) 2005430Swnj struct tty *tp; 2015430Swnj { 2025430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 2035430Swnj 20418651Sbloom if (flag & FREAD) { 20518651Sbloom if (pti->pt_selr) { 20618651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 20718651Sbloom pti->pt_selr = 0; 20818651Sbloom pti->pt_flags &= ~PF_RCOLL; 20918651Sbloom } 21018651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2114484Swnj } 21218651Sbloom if (flag & FWRITE) { 21318651Sbloom if (pti->pt_selw) { 21418651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 21518651Sbloom pti->pt_selw = 0; 21618651Sbloom pti->pt_flags &= ~PF_WCOLL; 21718651Sbloom } 21837590Smarc if (ptydebug) printf("WAKEUP c_cf %d\n", u.u_procp->p_pid); 21918651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 22018651Sbloom } 2212281Stoy } 2222281Stoy 2232281Stoy /*ARGSUSED*/ 2242281Stoy ptcopen(dev, flag) 2254484Swnj dev_t dev; 2264484Swnj int flag; 2274484Swnj { 2282281Stoy register struct tty *tp; 2295427Swnj struct pt_ioctl *pti; 2302281Stoy 2318563Sroot if (minor(dev) >= NPTY) 2328563Sroot return (ENXIO); 2332281Stoy tp = &pt_tty[minor(dev)]; 2348563Sroot if (tp->t_oproc) 2358563Sroot return (EIO); 2364484Swnj tp->t_oproc = ptsstart; 23725390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2385427Swnj pti = &pt_ioctl[minor(dev)]; 2395427Swnj pti->pt_flags = 0; 2405427Swnj pti->pt_send = 0; 24118651Sbloom pti->pt_ucntl = 0; 2428563Sroot return (0); 2432281Stoy } 2442281Stoy 2452281Stoy ptcclose(dev) 2464484Swnj dev_t dev; 2474484Swnj { 2482281Stoy register struct tty *tp; 2492281Stoy 2502281Stoy tp = &pt_tty[minor(dev)]; 25125390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 25232326Skarels tp->t_state &= ~TS_CARR_ON; 2534484Swnj tp->t_oproc = 0; /* mark closed */ 25439497Smarc tp->t_session = 0; 2552281Stoy } 2562281Stoy 25737590Smarc ptcread(dev, uio, flag) 2585427Swnj dev_t dev; 2597823Sroot struct uio *uio; 2604484Swnj { 2618521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 26218651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 26316788Ssam char buf[BUFSIZ]; 26416788Ssam int error = 0, cc; 2652281Stoy 26618651Sbloom /* 26718651Sbloom * We want to block until the slave 26818651Sbloom * is open, and there's something to read; 26918651Sbloom * but if we lost the slave or we're NBIO, 27018651Sbloom * then return the appropriate error instead. 27118651Sbloom */ 27218651Sbloom for (;;) { 27318651Sbloom if (tp->t_state&TS_ISOPEN) { 27418651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 27526358Skarels error = ureadc((int)pti->pt_send, uio); 27618651Sbloom if (error) 27718651Sbloom return (error); 27818651Sbloom pti->pt_send = 0; 27918651Sbloom return (0); 28018651Sbloom } 28118651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 28226358Skarels error = ureadc((int)pti->pt_ucntl, uio); 28318651Sbloom if (error) 28418651Sbloom return (error); 28518651Sbloom pti->pt_ucntl = 0; 28618651Sbloom return (0); 28718651Sbloom } 28818651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 28918651Sbloom break; 2905427Swnj } 29116788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 29237590Smarc return (0); /* EOF */ 29337728Smckusick if (flag & IO_NDELAY) 2948521Sroot return (EWOULDBLOCK); 295*40714Skarels if (ptydebug) printf("SLEEP(1) c_cf %d\n", u.u_procp->p_pid); /* XXX */ 296*40714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 297*40714Skarels ttyin, 0)) 298*40714Skarels return (error); 2995411Swnj } 30035811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 30118651Sbloom error = ureadc(0, uio); 30216788Ssam while (uio->uio_resid > 0 && error == 0) { 30316788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 30416788Ssam if (cc <= 0) 3057823Sroot break; 30637728Smckusick error = uiomove(buf, cc, uio); 30716788Ssam } 30835811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 30935811Smarc if (tp->t_state&TS_ASLEEP) { 31035811Smarc tp->t_state &= ~TS_ASLEEP; 31135811Smarc wakeup((caddr_t)&tp->t_outq); 31235811Smarc } 31335811Smarc if (tp->t_wsel) { 31435811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 31535811Smarc tp->t_wsel = 0; 31635811Smarc tp->t_state &= ~TS_WCOLL; 31735811Smarc } 31835811Smarc } 3198521Sroot return (error); 3202281Stoy } 3212281Stoy 3225427Swnj ptsstop(tp, flush) 3235427Swnj register struct tty *tp; 3245427Swnj int flush; 3255427Swnj { 3265427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 32718651Sbloom int flag; 3285427Swnj 3295574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3305574Swnj if (flush == 0) { 3315574Swnj flush = TIOCPKT_STOP; 3325574Swnj pti->pt_flags |= PF_STOPPED; 33318651Sbloom } else 3345574Swnj pti->pt_flags &= ~PF_STOPPED; 3356119Swnj pti->pt_send |= flush; 33618651Sbloom /* change of perspective */ 33718651Sbloom flag = 0; 33818651Sbloom if (flush & FREAD) 33918651Sbloom flag |= FWRITE; 34018651Sbloom if (flush & FWRITE) 34118651Sbloom flag |= FREAD; 34223633Sbloom ptcwakeup(tp, flag); 3435427Swnj } 3445427Swnj 3455408Swnj ptcselect(dev, rw) 3464484Swnj dev_t dev; 3475408Swnj int rw; 3484484Swnj { 3494484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3505894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3514484Swnj struct proc *p; 3525430Swnj int s; 3534484Swnj 35418651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3554484Swnj return (1); 3565408Swnj switch (rw) { 3575408Swnj 3585408Swnj case FREAD: 35925945Skarels /* 36025945Skarels * Need to block timeouts (ttrstart). 36125945Skarels */ 36225945Skarels s = spltty(); 36318651Sbloom if ((tp->t_state&TS_ISOPEN) && 36425436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 36525436Skarels splx(s); 36625436Skarels return (1); 36725436Skarels } 36825945Skarels splx(s); 36925436Skarels /* FALLTHROUGH */ 37025436Skarels 37125436Skarels case 0: /* exceptional */ 37225436Skarels if ((tp->t_state&TS_ISOPEN) && 37318651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 37425945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3755408Swnj return (1); 3765427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3775427Swnj pti->pt_flags |= PF_RCOLL; 3785408Swnj else 3795427Swnj pti->pt_selr = u.u_procp; 3805430Swnj break; 3815408Swnj 38225436Skarels 3835408Swnj case FWRITE: 38425945Skarels if (tp->t_state&TS_ISOPEN) { 38525945Skarels if (pti->pt_flags & PF_REMOTE) { 38625945Skarels if (tp->t_canq.c_cc == 0) 38725945Skarels return (1); 38825945Skarels } else { 38925945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 39025945Skarels return (1); 39135811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 39225945Skarels return (1); 39325945Skarels } 3945430Swnj } 3955427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3965427Swnj pti->pt_flags |= PF_WCOLL; 3975408Swnj else 3985427Swnj pti->pt_selw = u.u_procp; 3995430Swnj break; 40025436Skarels 4015408Swnj } 4025430Swnj return (0); 4035396Sroot } 4044484Swnj 40537590Smarc ptcwrite(dev, uio, flag) 4065408Swnj dev_t dev; 40718651Sbloom register struct uio *uio; 4084484Swnj { 4098521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 41018651Sbloom register struct iovec *iov; 41118651Sbloom register char *cp; 41218651Sbloom register int cc = 0; 4132281Stoy char locbuf[BUFSIZ]; 4145408Swnj int cnt = 0; 4155894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4168521Sroot int error = 0; 4172281Stoy 41818651Sbloom again: 41918651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42018651Sbloom goto block; 42123633Sbloom if (pti->pt_flags & PF_REMOTE) { 42218651Sbloom if (tp->t_canq.c_cc) 42318651Sbloom goto block; 42423633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 42523633Sbloom iov = uio->uio_iov; 42623633Sbloom if (iov->iov_len == 0) { 42723633Sbloom uio->uio_iovcnt--; 42823633Sbloom uio->uio_iov++; 42923633Sbloom continue; 43023633Sbloom } 43123633Sbloom if (cc == 0) { 43223633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 43323633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 43423633Sbloom cp = locbuf; 43537728Smckusick error = uiomove(cp, cc, uio); 43623633Sbloom if (error) 43723633Sbloom return (error); 43823633Sbloom /* check again for safety */ 43923633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 44023633Sbloom return (EIO); 44123633Sbloom } 44223633Sbloom if (cc) 44323633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 44423633Sbloom cc = 0; 4457823Sroot } 44618651Sbloom (void) putc(0, &tp->t_canq); 44718651Sbloom ttwakeup(tp); 44818651Sbloom wakeup((caddr_t)&tp->t_canq); 44918651Sbloom return (0); 45018651Sbloom } 45118651Sbloom while (uio->uio_iovcnt > 0) { 45218651Sbloom iov = uio->uio_iov; 45318651Sbloom if (cc == 0) { 45418651Sbloom if (iov->iov_len == 0) { 45518651Sbloom uio->uio_iovcnt--; 45618651Sbloom uio->uio_iov++; 45718651Sbloom continue; 4585894Swnj } 45918651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 46018651Sbloom cp = locbuf; 46137728Smckusick error = uiomove(cp, cc, uio); 46218651Sbloom if (error) 46318651Sbloom return (error); 46418651Sbloom /* check again for safety */ 46518651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 46618651Sbloom return (EIO); 4675894Swnj } 46823633Sbloom while (cc > 0) { 46923633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 47035811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 47123633Sbloom wakeup((caddr_t)&tp->t_rawq); 47223633Sbloom goto block; 47323633Sbloom } 47437590Smarc (*linesw[tp->t_line].l_rint)(*cp++&0377, tp); 4755408Swnj cnt++; 47623633Sbloom cc--; 4772281Stoy } 47818651Sbloom cc = 0; 47918651Sbloom } 48018651Sbloom return (0); 48118651Sbloom block: 48218651Sbloom /* 48323633Sbloom * Come here to wait for slave to open, for space 48423633Sbloom * in outq, or space in rawq. 48518651Sbloom */ 48618651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 48718651Sbloom return (EIO); 48837728Smckusick if ((pti->pt_flags & PF_NBIO) || (flag & IO_NDELAY)) { 48918651Sbloom iov->iov_base -= cc; 49018651Sbloom iov->iov_len += cc; 49118651Sbloom uio->uio_resid += cc; 49218651Sbloom uio->uio_offset -= cc; 49323633Sbloom if (cnt == 0) 49423633Sbloom return (EWOULDBLOCK); 49518651Sbloom return (0); 49618651Sbloom } 49737590Smarc if (ptydebug) printf("SLEEP(2) c_cf %d\n", u.u_procp->p_pid); 498*40714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 499*40714Skarels ttyout, 0)) 500*40714Skarels return (error); 50118651Sbloom goto again; 5022281Stoy } 5032281Stoy 5042281Stoy /*ARGSUSED*/ 5057626Ssam ptyioctl(dev, cmd, data, flag) 5067626Ssam caddr_t data; 5074484Swnj dev_t dev; 5084484Swnj { 5096119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5106119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 51135811Smarc register u_char *cc = tp->t_cc; 51218651Sbloom int stop, error; 51325390Skarels extern ttyinput(); 5142281Stoy 51525390Skarels /* 51625390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 51725390Skarels * ttywflush(tp) will hang if there are characters in the outq. 51825390Skarels */ 51935811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5207626Ssam switch (cmd) { 5217626Ssam 5227626Ssam case TIOCPKT: 52318651Sbloom if (*(int *)data) { 52418651Sbloom if (pti->pt_flags & PF_UCNTL) 52518651Sbloom return (EINVAL); 5265427Swnj pti->pt_flags |= PF_PKT; 52718651Sbloom } else 5285427Swnj pti->pt_flags &= ~PF_PKT; 5298563Sroot return (0); 5307626Ssam 53118651Sbloom case TIOCUCNTL: 53218651Sbloom if (*(int *)data) { 53318651Sbloom if (pti->pt_flags & PF_PKT) 53418651Sbloom return (EINVAL); 53518651Sbloom pti->pt_flags |= PF_UCNTL; 53618651Sbloom } else 53718651Sbloom pti->pt_flags &= ~PF_UCNTL; 53818651Sbloom return (0); 53918651Sbloom 5407626Ssam case TIOCREMOTE: 5417626Ssam if (*(int *)data) 5425894Swnj pti->pt_flags |= PF_REMOTE; 5435894Swnj else 5445894Swnj pti->pt_flags &= ~PF_REMOTE; 54512753Ssam ttyflush(tp, FREAD|FWRITE); 5468563Sroot return (0); 5477626Ssam 5487626Ssam case FIONBIO: 5497626Ssam if (*(int *)data) 5505427Swnj pti->pt_flags |= PF_NBIO; 5515411Swnj else 5525427Swnj pti->pt_flags &= ~PF_NBIO; 5538563Sroot return (0); 5547626Ssam 55535811Smarc case TIOCSETP: 55625390Skarels case TIOCSETN: 55725390Skarels case TIOCSETD: 55835811Smarc case TIOCSETA: 55935811Smarc case TIOCSETAW: 56035811Smarc case TIOCSETAF: 56139497Smarc case JUNK_TIOCSETAS: 56239497Smarc case JUNK_TIOCSETAWS: 56339497Smarc case JUNK_TIOCSETAFS: 5647626Ssam while (getc(&tp->t_outq) >= 0) 5657626Ssam ; 5667626Ssam break; 5675411Swnj } 56835811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 56935811Smarc if (error < 0) 57035811Smarc error = ttioctl(tp, cmd, data, flag); 57125390Skarels /* 57225390Skarels * Since we use the tty queues internally, 57325390Skarels * pty's can't be switched to disciplines which overwrite 57425390Skarels * the queues. We can't tell anything about the discipline 57525390Skarels * from here... 57625390Skarels */ 57725390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 57825390Skarels (*linesw[tp->t_line].l_close)(tp); 57925390Skarels tp->t_line = 0; 58037590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 58125390Skarels error = ENOTTY; 58225390Skarels } 58318651Sbloom if (error < 0) { 58418651Sbloom if (pti->pt_flags & PF_UCNTL && 58528285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 58618651Sbloom if (cmd & 0xff) { 58718651Sbloom pti->pt_ucntl = (u_char)cmd; 58818651Sbloom ptcwakeup(tp, FREAD); 58918651Sbloom } 59018651Sbloom return (0); 59118651Sbloom } 5928563Sroot error = ENOTTY; 59318651Sbloom } 59435811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 59535811Smarc && CCEQ(cc[VSTART], CTRL('q')); 5966119Swnj if (pti->pt_flags & PF_NOSTOP) { 5976119Swnj if (stop) { 59825478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5996119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6006119Swnj pti->pt_flags &= ~PF_NOSTOP; 60118651Sbloom ptcwakeup(tp, FREAD); 6026119Swnj } 6036119Swnj } else { 60418651Sbloom if (!stop) { 6056119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6066119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6076119Swnj pti->pt_flags |= PF_NOSTOP; 60818651Sbloom ptcwakeup(tp, FREAD); 6096119Swnj } 6106119Swnj } 6118563Sroot return (error); 6122281Stoy } 6132313Stoy #endif 614