123390Smckusick /* 223390Smckusick * Copyright (c) 1982 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*25478Skarels * @(#)tty_pty.c 6.17 (Berkeley) 11/14/85 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 int pt_gensym; 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 495427Swnj #define PF_RCOLL 0x01 505427Swnj #define PF_WCOLL 0x02 515427Swnj #define PF_NBIO 0x04 525427Swnj #define PF_PKT 0x08 /* packet mode */ 535574Swnj #define PF_STOPPED 0x10 /* user told stopped */ 545894Swnj #define PF_REMOTE 0x20 /* remote and flow controlled input */ 556119Swnj #define PF_NOSTOP 0x40 5618651Sbloom #define PF_UCNTL 0x80 /* user control mode */ 572281Stoy 582281Stoy /*ARGSUSED*/ 592281Stoy ptsopen(dev, flag) 605396Sroot dev_t dev; 614484Swnj { 622281Stoy register struct tty *tp; 6318651Sbloom int error; 642281Stoy 6518651Sbloom #ifdef lint 6618651Sbloom npty = npty; 6718651Sbloom #endif 688563Sroot if (minor(dev) >= NPTY) 698563Sroot return (ENXIO); 702281Stoy tp = &pt_tty[minor(dev)]; 715408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 722427Swnj ttychars(tp); /* Set up default chars */ 7312642Ssam tp->t_ispeed = tp->t_ospeed = EXTB; 742427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 758563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 768563Sroot return (EBUSY); 774484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 785408Swnj tp->t_state |= TS_CARR_ON; 795408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 805408Swnj tp->t_state |= TS_WOPEN; 812281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 822281Stoy } 8318651Sbloom error = (*linesw[tp->t_line].l_open)(dev, tp); 8418651Sbloom ptcwakeup(tp, FREAD|FWRITE); 8518651Sbloom return (error); 862281Stoy } 872281Stoy 882281Stoy ptsclose(dev) 895396Sroot dev_t dev; 905408Swnj { 912281Stoy register struct tty *tp; 922281Stoy 932281Stoy tp = &pt_tty[minor(dev)]; 942281Stoy (*linesw[tp->t_line].l_close)(tp); 956299Swnj ttyclose(tp); 9618651Sbloom ptcwakeup(tp, FREAD|FWRITE); 972281Stoy } 982281Stoy 997823Sroot ptsread(dev, uio) 1005396Sroot dev_t dev; 1017823Sroot struct uio *uio; 1024484Swnj { 1035894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1045894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1058521Sroot int error = 0; 1062281Stoy 1075894Swnj again: 1085894Swnj if (pti->pt_flags & PF_REMOTE) { 1095894Swnj while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 11018651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 11118651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1125894Swnj u.u_procp->p_flag&SVFORK) 1138521Sroot return (EIO); 1145894Swnj gsignal(u.u_procp->p_pgrp, SIGTTIN); 1155894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1165408Swnj } 11718651Sbloom if (tp->t_canq.c_cc == 0) { 1188521Sroot if (tp->t_state & TS_NBIO) 1198521Sroot return (EWOULDBLOCK); 12018651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1215894Swnj goto again; 1225894Swnj } 12318651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 12418651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1258521Sroot error = EFAULT; 1267823Sroot break; 1277823Sroot } 12818651Sbloom if (tp->t_canq.c_cc == 1) 12918651Sbloom (void) getc(&tp->t_canq); 13018651Sbloom if (tp->t_canq.c_cc) 1318521Sroot return (error); 1325894Swnj } else 1335894Swnj if (tp->t_oproc) 1348521Sroot error = (*linesw[tp->t_line].l_read)(tp, uio); 13518651Sbloom ptcwakeup(tp, FWRITE); 1368521Sroot return (error); 1372281Stoy } 1382281Stoy 1395408Swnj /* 1405408Swnj * Write to pseudo-tty. 1415408Swnj * Wakeups of controlling tty will happen 1425408Swnj * indirectly, when tty driver calls ptsstart. 1435408Swnj */ 1447823Sroot ptswrite(dev, uio) 1455396Sroot dev_t dev; 1467823Sroot struct uio *uio; 1474484Swnj { 1482281Stoy register struct tty *tp; 1492281Stoy 1502281Stoy tp = &pt_tty[minor(dev)]; 1518521Sroot if (tp->t_oproc == 0) 1528521Sroot return (EIO); 1538521Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 1542281Stoy } 1552281Stoy 1565408Swnj /* 1575408Swnj * Start output on pseudo-tty. 1585408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1595408Swnj */ 1602281Stoy ptsstart(tp) 1614484Swnj struct tty *tp; 1624484Swnj { 1635574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1644484Swnj 1655408Swnj if (tp->t_state & TS_TTSTOP) 1662281Stoy return; 1675574Swnj if (pti->pt_flags & PF_STOPPED) { 1685574Swnj pti->pt_flags &= ~PF_STOPPED; 1695574Swnj pti->pt_send = TIOCPKT_START; 1705574Swnj } 17118651Sbloom ptcwakeup(tp, FREAD); 1725430Swnj } 1735430Swnj 17418651Sbloom ptcwakeup(tp, flag) 1755430Swnj struct tty *tp; 1765430Swnj { 1775430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1785430Swnj 17918651Sbloom if (flag & FREAD) { 18018651Sbloom if (pti->pt_selr) { 18118651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 18218651Sbloom pti->pt_selr = 0; 18318651Sbloom pti->pt_flags &= ~PF_RCOLL; 18418651Sbloom } 18518651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 1864484Swnj } 18718651Sbloom if (flag & FWRITE) { 18818651Sbloom if (pti->pt_selw) { 18918651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 19018651Sbloom pti->pt_selw = 0; 19118651Sbloom pti->pt_flags &= ~PF_WCOLL; 19218651Sbloom } 19318651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 19418651Sbloom } 1952281Stoy } 1962281Stoy 1972281Stoy /*ARGSUSED*/ 1982281Stoy ptcopen(dev, flag) 1994484Swnj dev_t dev; 2004484Swnj int flag; 2014484Swnj { 2022281Stoy register struct tty *tp; 2035427Swnj struct pt_ioctl *pti; 2042281Stoy 2058563Sroot if (minor(dev) >= NPTY) 2068563Sroot return (ENXIO); 2072281Stoy tp = &pt_tty[minor(dev)]; 2088563Sroot if (tp->t_oproc) 2098563Sroot return (EIO); 2104484Swnj tp->t_oproc = ptsstart; 21125390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 2125408Swnj tp->t_state |= TS_CARR_ON; 2135427Swnj pti = &pt_ioctl[minor(dev)]; 2145427Swnj pti->pt_flags = 0; 2155427Swnj pti->pt_send = 0; 21618651Sbloom pti->pt_ucntl = 0; 2178563Sroot return (0); 2182281Stoy } 2192281Stoy 2202281Stoy ptcclose(dev) 2214484Swnj dev_t dev; 2224484Swnj { 2232281Stoy register struct tty *tp; 2242281Stoy 2252281Stoy tp = &pt_tty[minor(dev)]; 22625390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 2274484Swnj tp->t_oproc = 0; /* mark closed */ 2282281Stoy } 2292281Stoy 2307823Sroot ptcread(dev, uio) 2315427Swnj dev_t dev; 2327823Sroot struct uio *uio; 2334484Swnj { 2348521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 23518651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 23616788Ssam char buf[BUFSIZ]; 23716788Ssam int error = 0, cc; 2382281Stoy 23918651Sbloom /* 24018651Sbloom * We want to block until the slave 24118651Sbloom * is open, and there's something to read; 24218651Sbloom * but if we lost the slave or we're NBIO, 24318651Sbloom * then return the appropriate error instead. 24418651Sbloom */ 24518651Sbloom for (;;) { 24618651Sbloom if (tp->t_state&TS_ISOPEN) { 24718651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 24818651Sbloom error = ureadc(pti->pt_send, uio); 24918651Sbloom if (error) 25018651Sbloom return (error); 25118651Sbloom pti->pt_send = 0; 25218651Sbloom return (0); 25318651Sbloom } 25418651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 25518651Sbloom error = ureadc(pti->pt_ucntl, uio); 25618651Sbloom if (error) 25718651Sbloom return (error); 25818651Sbloom pti->pt_ucntl = 0; 25918651Sbloom return (0); 26018651Sbloom } 26118651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 26218651Sbloom break; 2635427Swnj } 26416788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 26516788Ssam return (EIO); 2668521Sroot if (pti->pt_flags&PF_NBIO) 2678521Sroot return (EWOULDBLOCK); 2682281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2695411Swnj } 27018651Sbloom if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 27118651Sbloom error = ureadc(0, uio); 27216788Ssam while (uio->uio_resid > 0 && error == 0) { 27316788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 27416788Ssam if (cc <= 0) 2757823Sroot break; 27616788Ssam error = uiomove(buf, cc, UIO_READ, uio); 27716788Ssam } 2785408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 2795408Swnj if (tp->t_state&TS_ASLEEP) { 2805408Swnj tp->t_state &= ~TS_ASLEEP; 2815408Swnj wakeup((caddr_t)&tp->t_outq); 2825408Swnj } 2835408Swnj if (tp->t_wsel) { 2845408Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 2855408Swnj tp->t_wsel = 0; 2865408Swnj tp->t_state &= ~TS_WCOLL; 2875408Swnj } 2882281Stoy } 2898521Sroot return (error); 2902281Stoy } 2912281Stoy 2925427Swnj ptsstop(tp, flush) 2935427Swnj register struct tty *tp; 2945427Swnj int flush; 2955427Swnj { 2965427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 29718651Sbloom int flag; 2985427Swnj 2995574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3005574Swnj if (flush == 0) { 3015574Swnj flush = TIOCPKT_STOP; 3025574Swnj pti->pt_flags |= PF_STOPPED; 30318651Sbloom } else 3045574Swnj pti->pt_flags &= ~PF_STOPPED; 3056119Swnj pti->pt_send |= flush; 30618651Sbloom /* change of perspective */ 30718651Sbloom flag = 0; 30818651Sbloom if (flush & FREAD) 30918651Sbloom flag |= FWRITE; 31018651Sbloom if (flush & FWRITE) 31118651Sbloom flag |= FREAD; 31223633Sbloom ptcwakeup(tp, flag); 3135427Swnj } 3145427Swnj 3155408Swnj ptcselect(dev, rw) 3164484Swnj dev_t dev; 3175408Swnj int rw; 3184484Swnj { 3194484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3205894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3214484Swnj struct proc *p; 3225430Swnj int s; 3234484Swnj 32418651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3254484Swnj return (1); 3265430Swnj s = spl5(); 3275408Swnj switch (rw) { 3285408Swnj 3295408Swnj case FREAD: 33018651Sbloom if ((tp->t_state&TS_ISOPEN) && 33125436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 33225436Skarels splx(s); 33325436Skarels return (1); 33425436Skarels } 33525436Skarels /* FALLTHROUGH */ 33625436Skarels 33725436Skarels case 0: /* exceptional */ 33825436Skarels if ((tp->t_state&TS_ISOPEN) && 33918651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 34025436Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) { 3415430Swnj splx(s); 3425408Swnj return (1); 3435430Swnj } 3445427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3455427Swnj pti->pt_flags |= PF_RCOLL; 3465408Swnj else 3475427Swnj pti->pt_selr = u.u_procp; 3485430Swnj break; 3495408Swnj 35025436Skarels 3515408Swnj case FWRITE: 35218651Sbloom if ((tp->t_state&TS_ISOPEN) && 35322731Skarels ((pti->pt_flags&PF_REMOTE) == 0 || tp->t_canq.c_cc == 0)) { 3545430Swnj splx(s); 3555408Swnj return (1); 3565430Swnj } 3575427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3585427Swnj pti->pt_flags |= PF_WCOLL; 3595408Swnj else 3605427Swnj pti->pt_selw = u.u_procp; 3615430Swnj break; 36225436Skarels 3635408Swnj } 3645430Swnj splx(s); 3655430Swnj return (0); 3665396Sroot } 3674484Swnj 3687823Sroot ptcwrite(dev, uio) 3695408Swnj dev_t dev; 37018651Sbloom register struct uio *uio; 3714484Swnj { 3728521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 37318651Sbloom register struct iovec *iov; 37418651Sbloom register char *cp; 37518651Sbloom register int cc = 0; 3762281Stoy char locbuf[BUFSIZ]; 3775408Swnj int cnt = 0; 3785894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3798521Sroot int error = 0; 3802281Stoy 38118651Sbloom again: 38218651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 38318651Sbloom goto block; 38423633Sbloom if (pti->pt_flags & PF_REMOTE) { 38518651Sbloom if (tp->t_canq.c_cc) 38618651Sbloom goto block; 38723633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 38823633Sbloom iov = uio->uio_iov; 38923633Sbloom if (iov->iov_len == 0) { 39023633Sbloom uio->uio_iovcnt--; 39123633Sbloom uio->uio_iov++; 39223633Sbloom continue; 39323633Sbloom } 39423633Sbloom if (cc == 0) { 39523633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 39623633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 39723633Sbloom cp = locbuf; 39823633Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 39923633Sbloom if (error) 40023633Sbloom return (error); 40123633Sbloom /* check again for safety */ 40223633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 40323633Sbloom return (EIO); 40423633Sbloom } 40523633Sbloom if (cc) 40623633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 40723633Sbloom cc = 0; 4087823Sroot } 40918651Sbloom (void) putc(0, &tp->t_canq); 41018651Sbloom ttwakeup(tp); 41118651Sbloom wakeup((caddr_t)&tp->t_canq); 41218651Sbloom return (0); 41318651Sbloom } 41418651Sbloom while (uio->uio_iovcnt > 0) { 41518651Sbloom iov = uio->uio_iov; 41618651Sbloom if (cc == 0) { 41718651Sbloom if (iov->iov_len == 0) { 41818651Sbloom uio->uio_iovcnt--; 41918651Sbloom uio->uio_iov++; 42018651Sbloom continue; 4215894Swnj } 42218651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 42318651Sbloom cp = locbuf; 42418651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 42518651Sbloom if (error) 42618651Sbloom return (error); 42718651Sbloom /* check again for safety */ 42818651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42918651Sbloom return (EIO); 4305894Swnj } 43123633Sbloom while (cc > 0) { 43223633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 43323633Sbloom (tp->t_canq.c_cc > 0)) { 43423633Sbloom wakeup((caddr_t)&tp->t_rawq); 43523633Sbloom goto block; 43623633Sbloom } 4374141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 4385408Swnj cnt++; 43923633Sbloom cc--; 4402281Stoy } 44118651Sbloom cc = 0; 44218651Sbloom } 44318651Sbloom return (0); 44418651Sbloom block: 44518651Sbloom /* 44623633Sbloom * Come here to wait for slave to open, for space 44723633Sbloom * in outq, or space in rawq. 44818651Sbloom */ 44918651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 45018651Sbloom return (EIO); 45118651Sbloom if (pti->pt_flags & PF_NBIO) { 45218651Sbloom iov->iov_base -= cc; 45318651Sbloom iov->iov_len += cc; 45418651Sbloom uio->uio_resid += cc; 45518651Sbloom uio->uio_offset -= cc; 45623633Sbloom if (cnt == 0) 45723633Sbloom return (EWOULDBLOCK); 45818651Sbloom return (0); 45918651Sbloom } 46018651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 46118651Sbloom goto again; 4622281Stoy } 4632281Stoy 4642281Stoy /*ARGSUSED*/ 4657626Ssam ptyioctl(dev, cmd, data, flag) 4667626Ssam caddr_t data; 4674484Swnj dev_t dev; 4684484Swnj { 4696119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4706119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 47118651Sbloom int stop, error; 47225390Skarels extern ttyinput(); 4732281Stoy 47425390Skarels /* 47525390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 47625390Skarels * ttywflush(tp) will hang if there are characters in the outq. 47725390Skarels */ 4787626Ssam if (cdevsw[major(dev)].d_open == ptcopen) 4797626Ssam switch (cmd) { 4807626Ssam 4817626Ssam case TIOCPKT: 48218651Sbloom if (*(int *)data) { 48318651Sbloom if (pti->pt_flags & PF_UCNTL) 48418651Sbloom return (EINVAL); 4855427Swnj pti->pt_flags |= PF_PKT; 48618651Sbloom } else 4875427Swnj pti->pt_flags &= ~PF_PKT; 4888563Sroot return (0); 4897626Ssam 49018651Sbloom case TIOCUCNTL: 49118651Sbloom if (*(int *)data) { 49218651Sbloom if (pti->pt_flags & PF_PKT) 49318651Sbloom return (EINVAL); 49418651Sbloom pti->pt_flags |= PF_UCNTL; 49518651Sbloom } else 49618651Sbloom pti->pt_flags &= ~PF_UCNTL; 49718651Sbloom return (0); 49818651Sbloom 4997626Ssam case TIOCREMOTE: 5007626Ssam if (*(int *)data) 5015894Swnj pti->pt_flags |= PF_REMOTE; 5025894Swnj else 5035894Swnj pti->pt_flags &= ~PF_REMOTE; 50412753Ssam ttyflush(tp, FREAD|FWRITE); 5058563Sroot return (0); 5067626Ssam 5077626Ssam case FIONBIO: 5087626Ssam if (*(int *)data) 5095427Swnj pti->pt_flags |= PF_NBIO; 5105411Swnj else 5115427Swnj pti->pt_flags &= ~PF_NBIO; 5128563Sroot return (0); 5137626Ssam 5147626Ssam case TIOCSETP: 51525390Skarels case TIOCSETN: 51625390Skarels case TIOCSETD: 5177626Ssam while (getc(&tp->t_outq) >= 0) 5187626Ssam ; 5197626Ssam break; 5205411Swnj } 52117182Smckusick error = ttioctl(tp, cmd, data, flag); 52225390Skarels /* 52325390Skarels * Since we use the tty queues internally, 52425390Skarels * pty's can't be switched to disciplines which overwrite 52525390Skarels * the queues. We can't tell anything about the discipline 52625390Skarels * from here... 52725390Skarels */ 52825390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 52925390Skarels (*linesw[tp->t_line].l_close)(tp); 53025390Skarels tp->t_line = 0; 53125390Skarels (void)(*linesw[tp->t_line].l_open)(dev, tp); 53225390Skarels error = ENOTTY; 53325390Skarels } 53418651Sbloom if (error < 0) { 53518651Sbloom if (pti->pt_flags & PF_UCNTL && 53618651Sbloom (cmd & ~0xff) == _IO(u,0)) { 53718651Sbloom if (cmd & 0xff) { 53818651Sbloom pti->pt_ucntl = (u_char)cmd; 53918651Sbloom ptcwakeup(tp, FREAD); 54018651Sbloom } 54118651Sbloom return (0); 54218651Sbloom } 5438563Sroot error = ENOTTY; 54418651Sbloom } 54518651Sbloom stop = (tp->t_flags & RAW) == 0 && 54618651Sbloom tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 5476119Swnj if (pti->pt_flags & PF_NOSTOP) { 5486119Swnj if (stop) { 549*25478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 5506119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5516119Swnj pti->pt_flags &= ~PF_NOSTOP; 55218651Sbloom ptcwakeup(tp, FREAD); 5536119Swnj } 5546119Swnj } else { 55518651Sbloom if (!stop) { 5566119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5576119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5586119Swnj pti->pt_flags |= PF_NOSTOP; 55918651Sbloom ptcwakeup(tp, FREAD); 5606119Swnj } 5616119Swnj } 5628563Sroot return (error); 5632281Stoy } 5642313Stoy #endif 565