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*44313Smarc * @(#)tty_pty.c 7.14 (Berkeley) 06/26/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) { 8444312Smarc tp->t_state |= TS_WOPEN; 852427Swnj ttychars(tp); /* Set up default chars */ 8635811Smarc tp->t_iflag = TTYDEF_IFLAG; 8735811Smarc tp->t_oflag = TTYDEF_OFLAG; 8835811Smarc tp->t_lflag = TTYDEF_LFLAG; 8935811Smarc tp->t_cflag = TTYDEF_CFLAG; 9035811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 9135811Smarc ttsetwater(tp); /* would be done in xxparam() */ 928563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 938563Sroot return (EBUSY); 944484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 955408Swnj tp->t_state |= TS_CARR_ON; 965408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 975408Swnj tp->t_state |= TS_WOPEN; 9837590Smarc if (flag&FNDELAY) 9937590Smarc break; 10044312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 10140714Skarels ttopen, 0)) 10240714Skarels return (error); 1032281Stoy } 10437590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 10518651Sbloom ptcwakeup(tp, FREAD|FWRITE); 10618651Sbloom return (error); 1072281Stoy } 1082281Stoy 1092281Stoy ptsclose(dev) 1105396Sroot dev_t dev; 1115408Swnj { 1122281Stoy register struct tty *tp; 1132281Stoy 1142281Stoy tp = &pt_tty[minor(dev)]; 1152281Stoy (*linesw[tp->t_line].l_close)(tp); 1166299Swnj ttyclose(tp); 11718651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1182281Stoy } 1192281Stoy 12037590Smarc ptsread(dev, uio, flag) 1215396Sroot dev_t dev; 1227823Sroot struct uio *uio; 1234484Swnj { 1245894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1255894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1268521Sroot int error = 0; 1272281Stoy 1285894Swnj again: 1295894Swnj if (pti->pt_flags & PF_REMOTE) { 13039557Smarc while (isbackground(u.u_procp, tp)) { 13118651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 13218651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 13339557Smarc u.u_procp->p_pgrp->pg_jobc == 0 || 1345894Swnj u.u_procp->p_flag&SVFORK) 1358521Sroot return (EIO); 13642194Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN, 1); 13744312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 13844312Smarc TTIPRI | PCATCH, ttybg, 0)) 13940714Skarels return (error); 1405408Swnj } 14118651Sbloom if (tp->t_canq.c_cc == 0) { 14237728Smckusick if (flag & IO_NDELAY) 1438521Sroot return (EWOULDBLOCK); 14444312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 14540714Skarels TTIPRI | PCATCH, ttyin, 0)) 14640714Skarels return (error); 1475894Swnj goto again; 1485894Swnj } 14918651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 15018651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1518521Sroot error = EFAULT; 1527823Sroot break; 1537823Sroot } 15418651Sbloom if (tp->t_canq.c_cc == 1) 15518651Sbloom (void) getc(&tp->t_canq); 15618651Sbloom if (tp->t_canq.c_cc) 1578521Sroot return (error); 1585894Swnj } else 1595894Swnj if (tp->t_oproc) 16037590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 16118651Sbloom ptcwakeup(tp, FWRITE); 1628521Sroot return (error); 1632281Stoy } 1642281Stoy 1655408Swnj /* 1665408Swnj * Write to pseudo-tty. 1675408Swnj * Wakeups of controlling tty will happen 1685408Swnj * indirectly, when tty driver calls ptsstart. 1695408Swnj */ 17037590Smarc ptswrite(dev, uio, flag) 1715396Sroot dev_t dev; 1727823Sroot struct uio *uio; 1734484Swnj { 17435811Smarc register struct tty *tp; 1752281Stoy 17635811Smarc tp = &pt_tty[minor(dev)]; 1778521Sroot if (tp->t_oproc == 0) 1788521Sroot return (EIO); 17937590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1802281Stoy } 1812281Stoy 1825408Swnj /* 1835408Swnj * Start output on pseudo-tty. 1845408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1855408Swnj */ 1862281Stoy ptsstart(tp) 1874484Swnj struct tty *tp; 1884484Swnj { 1895574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1904484Swnj 1915408Swnj if (tp->t_state & TS_TTSTOP) 1922281Stoy return; 1935574Swnj if (pti->pt_flags & PF_STOPPED) { 1945574Swnj pti->pt_flags &= ~PF_STOPPED; 1955574Swnj pti->pt_send = TIOCPKT_START; 1965574Swnj } 19718651Sbloom ptcwakeup(tp, FREAD); 1985430Swnj } 1995430Swnj 20018651Sbloom ptcwakeup(tp, flag) 2015430Swnj struct tty *tp; 2025430Swnj { 2035430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 2045430Swnj 20518651Sbloom if (flag & FREAD) { 20618651Sbloom if (pti->pt_selr) { 20718651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 20818651Sbloom pti->pt_selr = 0; 20918651Sbloom pti->pt_flags &= ~PF_RCOLL; 21018651Sbloom } 21118651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2124484Swnj } 21318651Sbloom if (flag & FWRITE) { 21418651Sbloom if (pti->pt_selw) { 21518651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 21618651Sbloom pti->pt_selw = 0; 21718651Sbloom pti->pt_flags &= ~PF_WCOLL; 21818651Sbloom } 21937590Smarc if (ptydebug) printf("WAKEUP c_cf %d\n", u.u_procp->p_pid); 22018651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 22118651Sbloom } 2222281Stoy } 2232281Stoy 2242281Stoy /*ARGSUSED*/ 2252281Stoy ptcopen(dev, flag) 2264484Swnj dev_t dev; 2274484Swnj int flag; 2284484Swnj { 2292281Stoy register struct tty *tp; 2305427Swnj struct pt_ioctl *pti; 2312281Stoy 2328563Sroot if (minor(dev) >= NPTY) 2338563Sroot return (ENXIO); 2342281Stoy tp = &pt_tty[minor(dev)]; 2358563Sroot if (tp->t_oproc) 2368563Sroot return (EIO); 2374484Swnj tp->t_oproc = ptsstart; 23825390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 23942895Smarc tp->t_lflag &= ~EXTPROC; 2405427Swnj pti = &pt_ioctl[minor(dev)]; 2415427Swnj pti->pt_flags = 0; 2425427Swnj pti->pt_send = 0; 24318651Sbloom pti->pt_ucntl = 0; 2448563Sroot return (0); 2452281Stoy } 2462281Stoy 2472281Stoy ptcclose(dev) 2484484Swnj dev_t dev; 2494484Swnj { 2502281Stoy register struct tty *tp; 2512281Stoy 2522281Stoy tp = &pt_tty[minor(dev)]; 25325390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 25432326Skarels tp->t_state &= ~TS_CARR_ON; 2554484Swnj tp->t_oproc = 0; /* mark closed */ 25639497Smarc tp->t_session = 0; 2572281Stoy } 2582281Stoy 25937590Smarc ptcread(dev, uio, flag) 2605427Swnj dev_t dev; 2617823Sroot struct uio *uio; 2624484Swnj { 2638521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 26418651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 26516788Ssam char buf[BUFSIZ]; 26616788Ssam int error = 0, cc; 2672281Stoy 26818651Sbloom /* 26918651Sbloom * We want to block until the slave 27018651Sbloom * is open, and there's something to read; 27118651Sbloom * but if we lost the slave or we're NBIO, 27218651Sbloom * then return the appropriate error instead. 27318651Sbloom */ 27418651Sbloom for (;;) { 27518651Sbloom if (tp->t_state&TS_ISOPEN) { 27618651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 27726358Skarels error = ureadc((int)pti->pt_send, uio); 27818651Sbloom if (error) 27918651Sbloom return (error); 28042895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 28142895Smarc cc = MIN(uio->uio_resid, 28242895Smarc sizeof(tp->t_termios)); 28342895Smarc uiomove(&tp->t_termios, cc, uio); 28442895Smarc } 28518651Sbloom pti->pt_send = 0; 28618651Sbloom return (0); 28718651Sbloom } 28818651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 28926358Skarels error = ureadc((int)pti->pt_ucntl, uio); 29018651Sbloom if (error) 29118651Sbloom return (error); 29218651Sbloom pti->pt_ucntl = 0; 29318651Sbloom return (0); 29418651Sbloom } 29518651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 29618651Sbloom break; 2975427Swnj } 29816788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 29937590Smarc return (0); /* EOF */ 30037728Smckusick if (flag & IO_NDELAY) 3018521Sroot return (EWOULDBLOCK); 30240714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 30340714Skarels ttyin, 0)) 30440714Skarels return (error); 3055411Swnj } 30635811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 30718651Sbloom error = ureadc(0, uio); 30816788Ssam while (uio->uio_resid > 0 && error == 0) { 30916788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 31016788Ssam if (cc <= 0) 3117823Sroot break; 31237728Smckusick error = uiomove(buf, cc, uio); 31316788Ssam } 31435811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 31535811Smarc if (tp->t_state&TS_ASLEEP) { 31635811Smarc tp->t_state &= ~TS_ASLEEP; 31735811Smarc wakeup((caddr_t)&tp->t_outq); 31835811Smarc } 31935811Smarc if (tp->t_wsel) { 32035811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 32135811Smarc tp->t_wsel = 0; 32235811Smarc tp->t_state &= ~TS_WCOLL; 32335811Smarc } 32435811Smarc } 3258521Sroot return (error); 3262281Stoy } 3272281Stoy 3285427Swnj ptsstop(tp, flush) 3295427Swnj register struct tty *tp; 3305427Swnj int flush; 3315427Swnj { 3325427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 33318651Sbloom int flag; 3345427Swnj 3355574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3365574Swnj if (flush == 0) { 3375574Swnj flush = TIOCPKT_STOP; 3385574Swnj pti->pt_flags |= PF_STOPPED; 33918651Sbloom } else 3405574Swnj pti->pt_flags &= ~PF_STOPPED; 3416119Swnj pti->pt_send |= flush; 34218651Sbloom /* change of perspective */ 34318651Sbloom flag = 0; 34418651Sbloom if (flush & FREAD) 34518651Sbloom flag |= FWRITE; 34618651Sbloom if (flush & FWRITE) 34718651Sbloom flag |= FREAD; 34823633Sbloom ptcwakeup(tp, flag); 3495427Swnj } 3505427Swnj 3515408Swnj ptcselect(dev, rw) 3524484Swnj dev_t dev; 3535408Swnj int rw; 3544484Swnj { 3554484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3565894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3574484Swnj struct proc *p; 3585430Swnj int s; 3594484Swnj 36018651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3614484Swnj return (1); 3625408Swnj switch (rw) { 3635408Swnj 3645408Swnj case FREAD: 36525945Skarels /* 36625945Skarels * Need to block timeouts (ttrstart). 36725945Skarels */ 36825945Skarels s = spltty(); 36918651Sbloom if ((tp->t_state&TS_ISOPEN) && 37025436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 37125436Skarels splx(s); 37225436Skarels return (1); 37325436Skarels } 37425945Skarels splx(s); 37525436Skarels /* FALLTHROUGH */ 37625436Skarels 37725436Skarels case 0: /* exceptional */ 37825436Skarels if ((tp->t_state&TS_ISOPEN) && 37918651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 38025945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3815408Swnj return (1); 3825427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3835427Swnj pti->pt_flags |= PF_RCOLL; 3845408Swnj else 3855427Swnj pti->pt_selr = u.u_procp; 3865430Swnj break; 3875408Swnj 38825436Skarels 3895408Swnj case FWRITE: 39025945Skarels if (tp->t_state&TS_ISOPEN) { 39125945Skarels if (pti->pt_flags & PF_REMOTE) { 39225945Skarels if (tp->t_canq.c_cc == 0) 39325945Skarels return (1); 39425945Skarels } else { 39525945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 39625945Skarels return (1); 39735811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 39825945Skarels return (1); 39925945Skarels } 4005430Swnj } 4015427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 4025427Swnj pti->pt_flags |= PF_WCOLL; 4035408Swnj else 4045427Swnj pti->pt_selw = u.u_procp; 4055430Swnj break; 40625436Skarels 4075408Swnj } 4085430Swnj return (0); 4095396Sroot } 4104484Swnj 41137590Smarc ptcwrite(dev, uio, flag) 4125408Swnj dev_t dev; 41318651Sbloom register struct uio *uio; 4144484Swnj { 4158521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 41618651Sbloom register struct iovec *iov; 41718651Sbloom register char *cp; 41818651Sbloom register int cc = 0; 4192281Stoy char locbuf[BUFSIZ]; 4205408Swnj int cnt = 0; 4215894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4228521Sroot int error = 0; 4232281Stoy 42418651Sbloom again: 42518651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42618651Sbloom goto block; 42723633Sbloom if (pti->pt_flags & PF_REMOTE) { 42818651Sbloom if (tp->t_canq.c_cc) 42918651Sbloom goto block; 43023633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 43123633Sbloom iov = uio->uio_iov; 43223633Sbloom if (iov->iov_len == 0) { 43323633Sbloom uio->uio_iovcnt--; 43423633Sbloom uio->uio_iov++; 43523633Sbloom continue; 43623633Sbloom } 43723633Sbloom if (cc == 0) { 43823633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 43923633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 44023633Sbloom cp = locbuf; 44137728Smckusick error = uiomove(cp, cc, uio); 44223633Sbloom if (error) 44323633Sbloom return (error); 44423633Sbloom /* check again for safety */ 44523633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 44623633Sbloom return (EIO); 44723633Sbloom } 44823633Sbloom if (cc) 44923633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 45023633Sbloom cc = 0; 4517823Sroot } 45218651Sbloom (void) putc(0, &tp->t_canq); 45318651Sbloom ttwakeup(tp); 45418651Sbloom wakeup((caddr_t)&tp->t_canq); 45518651Sbloom return (0); 45618651Sbloom } 45718651Sbloom while (uio->uio_iovcnt > 0) { 45818651Sbloom iov = uio->uio_iov; 45918651Sbloom if (cc == 0) { 46018651Sbloom if (iov->iov_len == 0) { 46118651Sbloom uio->uio_iovcnt--; 46218651Sbloom uio->uio_iov++; 46318651Sbloom continue; 4645894Swnj } 46518651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 46618651Sbloom cp = locbuf; 46737728Smckusick error = uiomove(cp, cc, uio); 46818651Sbloom if (error) 46918651Sbloom return (error); 47018651Sbloom /* check again for safety */ 47118651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 47218651Sbloom return (EIO); 4735894Swnj } 47423633Sbloom while (cc > 0) { 47523633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 47635811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 47723633Sbloom wakeup((caddr_t)&tp->t_rawq); 47823633Sbloom goto block; 47923633Sbloom } 48037590Smarc (*linesw[tp->t_line].l_rint)(*cp++&0377, tp); 4815408Swnj cnt++; 48223633Sbloom cc--; 4832281Stoy } 48418651Sbloom cc = 0; 48518651Sbloom } 48618651Sbloom return (0); 48718651Sbloom block: 48818651Sbloom /* 48923633Sbloom * Come here to wait for slave to open, for space 49023633Sbloom * in outq, or space in rawq. 49118651Sbloom */ 49218651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 49318651Sbloom return (EIO); 49437728Smckusick if ((pti->pt_flags & PF_NBIO) || (flag & IO_NDELAY)) { 49518651Sbloom iov->iov_base -= cc; 49618651Sbloom iov->iov_len += cc; 49718651Sbloom uio->uio_resid += cc; 49818651Sbloom uio->uio_offset -= cc; 49923633Sbloom if (cnt == 0) 50023633Sbloom return (EWOULDBLOCK); 50118651Sbloom return (0); 50218651Sbloom } 50340714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 50440714Skarels ttyout, 0)) 50540714Skarels return (error); 50618651Sbloom goto again; 5072281Stoy } 5082281Stoy 5092281Stoy /*ARGSUSED*/ 5107626Ssam ptyioctl(dev, cmd, data, flag) 5117626Ssam caddr_t data; 5124484Swnj dev_t dev; 5134484Swnj { 5146119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5156119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 51635811Smarc register u_char *cc = tp->t_cc; 51718651Sbloom int stop, error; 51825390Skarels extern ttyinput(); 5192281Stoy 52025390Skarels /* 52125390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 52225390Skarels * ttywflush(tp) will hang if there are characters in the outq. 52325390Skarels */ 52442895Smarc if (cmd == TIOCEXT) { 52542895Smarc /* 52642895Smarc * When the EXTPROC bit is being toggled, we need 52742895Smarc * to send an TIOCPKT_IOCTL if the packet driver 52842895Smarc * is turned on. 52942895Smarc */ 53042895Smarc if (*(int *)data) { 53142895Smarc if (pti->pt_flags & PF_PKT) { 53242895Smarc pti->pt_send |= TIOCPKT_IOCTL; 53342895Smarc ptcwakeup(tp); 53442895Smarc } 53542895Smarc tp->t_lflag |= EXTPROC; 53642895Smarc } else { 53742895Smarc if ((tp->t_state & EXTPROC) && 53842895Smarc (pti->pt_flags & PF_PKT)) { 53942895Smarc pti->pt_send |= TIOCPKT_IOCTL; 54042895Smarc ptcwakeup(tp); 54142895Smarc } 54242895Smarc tp->t_lflag &= ~EXTPROC; 54342895Smarc } 54442895Smarc return(0); 54542895Smarc } else 54635811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5477626Ssam switch (cmd) { 5487626Ssam 549*44313Smarc case TIOCGPGRP: 550*44313Smarc /* 551*44313Smarc * We aviod calling ttioctl on the controller since, 552*44313Smarc * in that case, tp must be the controlling terminal. 553*44313Smarc */ 554*44313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 555*44313Smarc return (0); 556*44313Smarc 5577626Ssam case TIOCPKT: 55818651Sbloom if (*(int *)data) { 55918651Sbloom if (pti->pt_flags & PF_UCNTL) 56018651Sbloom return (EINVAL); 5615427Swnj pti->pt_flags |= PF_PKT; 56218651Sbloom } else 5635427Swnj pti->pt_flags &= ~PF_PKT; 5648563Sroot return (0); 5657626Ssam 56618651Sbloom case TIOCUCNTL: 56718651Sbloom if (*(int *)data) { 56818651Sbloom if (pti->pt_flags & PF_PKT) 56918651Sbloom return (EINVAL); 57018651Sbloom pti->pt_flags |= PF_UCNTL; 57118651Sbloom } else 57218651Sbloom pti->pt_flags &= ~PF_UCNTL; 57318651Sbloom return (0); 57418651Sbloom 5757626Ssam case TIOCREMOTE: 5767626Ssam if (*(int *)data) 5775894Swnj pti->pt_flags |= PF_REMOTE; 5785894Swnj else 5795894Swnj pti->pt_flags &= ~PF_REMOTE; 58012753Ssam ttyflush(tp, FREAD|FWRITE); 5818563Sroot return (0); 5827626Ssam 5837626Ssam case FIONBIO: 5847626Ssam if (*(int *)data) 5855427Swnj pti->pt_flags |= PF_NBIO; 5865411Swnj else 5875427Swnj pti->pt_flags &= ~PF_NBIO; 5888563Sroot return (0); 5897626Ssam 59035811Smarc case TIOCSETP: 59125390Skarels case TIOCSETN: 59225390Skarels case TIOCSETD: 59335811Smarc case TIOCSETA: 59435811Smarc case TIOCSETAW: 59535811Smarc case TIOCSETAF: 59639497Smarc case JUNK_TIOCSETAS: 59739497Smarc case JUNK_TIOCSETAWS: 59839497Smarc case JUNK_TIOCSETAFS: 5997626Ssam while (getc(&tp->t_outq) >= 0) 6007626Ssam ; 6017626Ssam break; 60242895Smarc 60342895Smarc case TIOCSIG: 60442895Smarc if (*(unsigned int *)data >= NSIG) 60542895Smarc return(EINVAL); 60642895Smarc if ((tp->t_lflag&NOFLSH) == 0) 60742895Smarc ttyflush(tp, FREAD|FWRITE); 60842895Smarc pgsignal(tp->t_pgrp, *(unsigned int *)data); 60942895Smarc return(0); 6105411Swnj } 61135811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 61235811Smarc if (error < 0) 61335811Smarc error = ttioctl(tp, cmd, data, flag); 61425390Skarels /* 61525390Skarels * Since we use the tty queues internally, 61625390Skarels * pty's can't be switched to disciplines which overwrite 61725390Skarels * the queues. We can't tell anything about the discipline 61825390Skarels * from here... 61925390Skarels */ 62025390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 62125390Skarels (*linesw[tp->t_line].l_close)(tp); 62225390Skarels tp->t_line = 0; 62337590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 62425390Skarels error = ENOTTY; 62525390Skarels } 62618651Sbloom if (error < 0) { 62718651Sbloom if (pti->pt_flags & PF_UCNTL && 62828285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 62918651Sbloom if (cmd & 0xff) { 63018651Sbloom pti->pt_ucntl = (u_char)cmd; 63118651Sbloom ptcwakeup(tp, FREAD); 63218651Sbloom } 63318651Sbloom return (0); 63418651Sbloom } 6358563Sroot error = ENOTTY; 63618651Sbloom } 63742895Smarc /* 63842895Smarc * If external processing and packet mode send ioctl packet. 63942895Smarc */ 64042895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 64142895Smarc switch(cmd) { 64242895Smarc case TIOCSETA: 64342895Smarc case TIOCSETAW: 64442895Smarc case TIOCSETAF: 64542895Smarc case JUNK_TIOCSETAS: 64642895Smarc case JUNK_TIOCSETAWS: 64742895Smarc case JUNK_TIOCSETAFS: 64842895Smarc case TIOCSETP: 64942895Smarc case TIOCSETN: 65042895Smarc #ifdef COMPAT_43 65142895Smarc case TIOCSETC: 65242895Smarc case TIOCSLTC: 65342895Smarc case TIOCLBIS: 65442895Smarc case TIOCLBIC: 65542895Smarc case TIOCLSET: 65642895Smarc #endif 65742895Smarc pti->pt_send |= TIOCPKT_IOCTL; 65842895Smarc default: 65942895Smarc break; 66042895Smarc } 66142895Smarc } 66235811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 66335811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6646119Swnj if (pti->pt_flags & PF_NOSTOP) { 6656119Swnj if (stop) { 66625478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6676119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6686119Swnj pti->pt_flags &= ~PF_NOSTOP; 66918651Sbloom ptcwakeup(tp, FREAD); 6706119Swnj } 6716119Swnj } else { 67218651Sbloom if (!stop) { 6736119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6746119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6756119Swnj pti->pt_flags |= PF_NOSTOP; 67618651Sbloom ptcwakeup(tp, FREAD); 6776119Swnj } 6786119Swnj } 6798563Sroot return (error); 6802281Stoy } 6812313Stoy #endif 682