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*48442Skarels * @(#)tty_pty.c 7.19 (Berkeley) 04/20/91 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 "conf.h" 2217096Sbloom #include "file.h" 2317096Sbloom #include "proc.h" 2417096Sbloom #include "uio.h" 2517096Sbloom #include "kernel.h" 2637728Smckusick #include "vnode.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 4835811Smarc #define PF_RCOLL 0x01 4935811Smarc #define PF_WCOLL 0x02 5035811Smarc #define PF_PKT 0x08 /* packet mode */ 5135811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 5235811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 5335811Smarc #define PF_NOSTOP 0x40 5435811Smarc #define PF_UCNTL 0x80 /* user control mode */ 552281Stoy 562281Stoy /*ARGSUSED*/ 57*48442Skarels ptsopen(dev, flag, devtype, p) 585396Sroot dev_t dev; 59*48442Skarels struct proc *p; 604484Swnj { 612281Stoy register struct tty *tp; 6218651Sbloom int error; 632281Stoy 6418651Sbloom #ifdef lint 6518651Sbloom npty = npty; 6618651Sbloom #endif 678563Sroot if (minor(dev) >= NPTY) 688563Sroot return (ENXIO); 692281Stoy tp = &pt_tty[minor(dev)]; 705408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 7144312Smarc tp->t_state |= TS_WOPEN; 722427Swnj ttychars(tp); /* Set up default chars */ 7335811Smarc tp->t_iflag = TTYDEF_IFLAG; 7435811Smarc tp->t_oflag = TTYDEF_OFLAG; 7535811Smarc tp->t_lflag = TTYDEF_LFLAG; 7635811Smarc tp->t_cflag = TTYDEF_CFLAG; 7735811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 7835811Smarc ttsetwater(tp); /* would be done in xxparam() */ 7947548Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 808563Sroot return (EBUSY); 814484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 825408Swnj tp->t_state |= TS_CARR_ON; 835408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 845408Swnj tp->t_state |= TS_WOPEN; 8537590Smarc if (flag&FNDELAY) 8637590Smarc break; 8744312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 8840714Skarels ttopen, 0)) 8940714Skarels return (error); 902281Stoy } 9137590Smarc error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 9218651Sbloom ptcwakeup(tp, FREAD|FWRITE); 9318651Sbloom return (error); 942281Stoy } 952281Stoy 962281Stoy ptsclose(dev) 975396Sroot dev_t dev; 985408Swnj { 992281Stoy register struct tty *tp; 1002281Stoy 1012281Stoy tp = &pt_tty[minor(dev)]; 1022281Stoy (*linesw[tp->t_line].l_close)(tp); 1036299Swnj ttyclose(tp); 10418651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1052281Stoy } 1062281Stoy 10737590Smarc ptsread(dev, uio, flag) 1085396Sroot dev_t dev; 1097823Sroot struct uio *uio; 1104484Swnj { 11147548Skarels struct proc *p = curproc; 1125894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1135894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1148521Sroot int error = 0; 1152281Stoy 1165894Swnj again: 1175894Swnj if (pti->pt_flags & PF_REMOTE) { 11847548Skarels while (isbackground(p, tp)) { 11947548Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 12047548Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 12147548Skarels p->p_pgrp->pg_jobc == 0 || 12247548Skarels p->p_flag&SPPWAIT) 1238521Sroot return (EIO); 12447548Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 12544312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 12644312Smarc TTIPRI | PCATCH, ttybg, 0)) 12740714Skarels return (error); 1285408Swnj } 12918651Sbloom if (tp->t_canq.c_cc == 0) { 13037728Smckusick if (flag & IO_NDELAY) 1318521Sroot return (EWOULDBLOCK); 13244312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 13340714Skarels TTIPRI | PCATCH, ttyin, 0)) 13440714Skarels return (error); 1355894Swnj goto again; 1365894Swnj } 13718651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 13818651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1398521Sroot error = EFAULT; 1407823Sroot break; 1417823Sroot } 14218651Sbloom if (tp->t_canq.c_cc == 1) 14318651Sbloom (void) getc(&tp->t_canq); 14418651Sbloom if (tp->t_canq.c_cc) 1458521Sroot return (error); 1465894Swnj } else 1475894Swnj if (tp->t_oproc) 14837590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 14918651Sbloom ptcwakeup(tp, FWRITE); 1508521Sroot return (error); 1512281Stoy } 1522281Stoy 1535408Swnj /* 1545408Swnj * Write to pseudo-tty. 1555408Swnj * Wakeups of controlling tty will happen 1565408Swnj * indirectly, when tty driver calls ptsstart. 1575408Swnj */ 15837590Smarc ptswrite(dev, uio, flag) 1595396Sroot dev_t dev; 1607823Sroot struct uio *uio; 1614484Swnj { 16235811Smarc register struct tty *tp; 1632281Stoy 16435811Smarc tp = &pt_tty[minor(dev)]; 1658521Sroot if (tp->t_oproc == 0) 1668521Sroot return (EIO); 16737590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1682281Stoy } 1692281Stoy 1705408Swnj /* 1715408Swnj * Start output on pseudo-tty. 1725408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1735408Swnj */ 1742281Stoy ptsstart(tp) 1754484Swnj struct tty *tp; 1764484Swnj { 1775574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1784484Swnj 1795408Swnj if (tp->t_state & TS_TTSTOP) 1802281Stoy return; 1815574Swnj if (pti->pt_flags & PF_STOPPED) { 1825574Swnj pti->pt_flags &= ~PF_STOPPED; 1835574Swnj pti->pt_send = TIOCPKT_START; 1845574Swnj } 18518651Sbloom ptcwakeup(tp, FREAD); 1865430Swnj } 1875430Swnj 18818651Sbloom ptcwakeup(tp, flag) 1895430Swnj struct tty *tp; 1905430Swnj { 1915430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1925430Swnj 19318651Sbloom if (flag & FREAD) { 19418651Sbloom if (pti->pt_selr) { 19518651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 19618651Sbloom pti->pt_selr = 0; 19718651Sbloom pti->pt_flags &= ~PF_RCOLL; 19818651Sbloom } 19918651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2004484Swnj } 20118651Sbloom if (flag & FWRITE) { 20218651Sbloom if (pti->pt_selw) { 20318651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 20418651Sbloom pti->pt_selw = 0; 20518651Sbloom pti->pt_flags &= ~PF_WCOLL; 20618651Sbloom } 20718651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 20818651Sbloom } 2092281Stoy } 2102281Stoy 2112281Stoy /*ARGSUSED*/ 212*48442Skarels #ifdef __STDC__ 213*48442Skarels ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 214*48442Skarels #else 215*48442Skarels ptcopen(dev, flag, devtype, p) 2164484Swnj dev_t dev; 217*48442Skarels int flag, devtype; 218*48442Skarels struct proc *p; 219*48442Skarels #endif 2204484Swnj { 2212281Stoy register struct tty *tp; 2225427Swnj struct pt_ioctl *pti; 2232281Stoy 2248563Sroot if (minor(dev) >= NPTY) 2258563Sroot return (ENXIO); 2262281Stoy tp = &pt_tty[minor(dev)]; 2278563Sroot if (tp->t_oproc) 2288563Sroot return (EIO); 2294484Swnj tp->t_oproc = ptsstart; 23025390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 23142895Smarc tp->t_lflag &= ~EXTPROC; 2325427Swnj pti = &pt_ioctl[minor(dev)]; 2335427Swnj pti->pt_flags = 0; 2345427Swnj pti->pt_send = 0; 23518651Sbloom pti->pt_ucntl = 0; 2368563Sroot return (0); 2372281Stoy } 2382281Stoy 2392281Stoy ptcclose(dev) 2404484Swnj dev_t dev; 2414484Swnj { 2422281Stoy register struct tty *tp; 2432281Stoy 2442281Stoy tp = &pt_tty[minor(dev)]; 24525390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 24632326Skarels tp->t_state &= ~TS_CARR_ON; 2474484Swnj tp->t_oproc = 0; /* mark closed */ 24839497Smarc tp->t_session = 0; 2492281Stoy } 2502281Stoy 25137590Smarc ptcread(dev, uio, flag) 2525427Swnj dev_t dev; 2537823Sroot struct uio *uio; 2544484Swnj { 2558521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 25618651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 25716788Ssam char buf[BUFSIZ]; 25816788Ssam int error = 0, cc; 2592281Stoy 26018651Sbloom /* 26118651Sbloom * We want to block until the slave 26218651Sbloom * is open, and there's something to read; 26318651Sbloom * but if we lost the slave or we're NBIO, 26418651Sbloom * then return the appropriate error instead. 26518651Sbloom */ 26618651Sbloom for (;;) { 26718651Sbloom if (tp->t_state&TS_ISOPEN) { 26818651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 26926358Skarels error = ureadc((int)pti->pt_send, uio); 27018651Sbloom if (error) 27118651Sbloom return (error); 27242895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 27342895Smarc cc = MIN(uio->uio_resid, 27442895Smarc sizeof(tp->t_termios)); 27542895Smarc uiomove(&tp->t_termios, cc, uio); 27642895Smarc } 27718651Sbloom pti->pt_send = 0; 27818651Sbloom return (0); 27918651Sbloom } 28018651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 28126358Skarels error = ureadc((int)pti->pt_ucntl, uio); 28218651Sbloom if (error) 28318651Sbloom return (error); 28418651Sbloom pti->pt_ucntl = 0; 28518651Sbloom return (0); 28618651Sbloom } 28718651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 28818651Sbloom break; 2895427Swnj } 29016788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 29137590Smarc return (0); /* EOF */ 29237728Smckusick if (flag & IO_NDELAY) 2938521Sroot return (EWOULDBLOCK); 29440714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 29540714Skarels ttyin, 0)) 29640714Skarels return (error); 2975411Swnj } 29835811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 29918651Sbloom error = ureadc(0, uio); 30016788Ssam while (uio->uio_resid > 0 && error == 0) { 30116788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 30216788Ssam if (cc <= 0) 3037823Sroot break; 30437728Smckusick error = uiomove(buf, cc, uio); 30516788Ssam } 30635811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 30735811Smarc if (tp->t_state&TS_ASLEEP) { 30835811Smarc tp->t_state &= ~TS_ASLEEP; 30935811Smarc wakeup((caddr_t)&tp->t_outq); 31035811Smarc } 31135811Smarc if (tp->t_wsel) { 31235811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 31335811Smarc tp->t_wsel = 0; 31435811Smarc tp->t_state &= ~TS_WCOLL; 31535811Smarc } 31635811Smarc } 3178521Sroot return (error); 3182281Stoy } 3192281Stoy 3205427Swnj ptsstop(tp, flush) 3215427Swnj register struct tty *tp; 3225427Swnj int flush; 3235427Swnj { 3245427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 32518651Sbloom int flag; 3265427Swnj 3275574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3285574Swnj if (flush == 0) { 3295574Swnj flush = TIOCPKT_STOP; 3305574Swnj pti->pt_flags |= PF_STOPPED; 33118651Sbloom } else 3325574Swnj pti->pt_flags &= ~PF_STOPPED; 3336119Swnj pti->pt_send |= flush; 33418651Sbloom /* change of perspective */ 33518651Sbloom flag = 0; 33618651Sbloom if (flush & FREAD) 33718651Sbloom flag |= FWRITE; 33818651Sbloom if (flush & FWRITE) 33918651Sbloom flag |= FREAD; 34023633Sbloom ptcwakeup(tp, flag); 3415427Swnj } 3425427Swnj 343*48442Skarels ptcselect(dev, rw, p) 3444484Swnj dev_t dev; 3455408Swnj int rw; 346*48442Skarels struct proc *p; 3474484Swnj { 3484484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3495894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 350*48442Skarels struct proc *prev; 3515430Swnj int s; 3524484Swnj 35318651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3544484Swnj return (1); 3555408Swnj switch (rw) { 3565408Swnj 3575408Swnj case FREAD: 35825945Skarels /* 35925945Skarels * Need to block timeouts (ttrstart). 36025945Skarels */ 36125945Skarels s = spltty(); 36218651Sbloom if ((tp->t_state&TS_ISOPEN) && 36325436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 36425436Skarels splx(s); 36525436Skarels return (1); 36625436Skarels } 36725945Skarels splx(s); 36825436Skarels /* FALLTHROUGH */ 36925436Skarels 37025436Skarels case 0: /* exceptional */ 37125436Skarels if ((tp->t_state&TS_ISOPEN) && 37218651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 37325945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3745408Swnj return (1); 375*48442Skarels if ((prev = pti->pt_selr) && prev->p_wchan == (caddr_t)&selwait) 3765427Swnj pti->pt_flags |= PF_RCOLL; 3775408Swnj else 378*48442Skarels pti->pt_selr = p; 3795430Swnj break; 3805408Swnj 38125436Skarels 3825408Swnj case FWRITE: 38325945Skarels if (tp->t_state&TS_ISOPEN) { 38425945Skarels if (pti->pt_flags & PF_REMOTE) { 38525945Skarels if (tp->t_canq.c_cc == 0) 38625945Skarels return (1); 38725945Skarels } else { 38825945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 38925945Skarels return (1); 39035811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 39125945Skarels return (1); 39225945Skarels } 3935430Swnj } 394*48442Skarels if ((prev = pti->pt_selw) && prev->p_wchan == (caddr_t)&selwait) 3955427Swnj pti->pt_flags |= PF_WCOLL; 3965408Swnj else 397*48442Skarels pti->pt_selw = p; 3985430Swnj break; 39925436Skarels 4005408Swnj } 4015430Swnj return (0); 4025396Sroot } 4034484Swnj 40437590Smarc ptcwrite(dev, uio, flag) 4055408Swnj dev_t dev; 40618651Sbloom register struct uio *uio; 4074484Swnj { 4088521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 40945570Skarels register u_char *cp; 41018651Sbloom register int cc = 0; 41145570Skarels u_char locbuf[BUFSIZ]; 4125408Swnj int cnt = 0; 4135894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4148521Sroot int error = 0; 4152281Stoy 41618651Sbloom again: 41718651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41818651Sbloom goto block; 41923633Sbloom if (pti->pt_flags & PF_REMOTE) { 42018651Sbloom if (tp->t_canq.c_cc) 42118651Sbloom goto block; 42245570Skarels while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 42323633Sbloom if (cc == 0) { 42445570Skarels cc = min(uio->uio_resid, BUFSIZ); 42545570Skarels cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 42623633Sbloom cp = locbuf; 42745570Skarels error = uiomove((caddr_t)cp, cc, uio); 42823633Sbloom if (error) 42923633Sbloom return (error); 43023633Sbloom /* check again for safety */ 43123633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43223633Sbloom return (EIO); 43323633Sbloom } 43423633Sbloom if (cc) 43545570Skarels (void) b_to_q((char *)cp, cc, &tp->t_canq); 43623633Sbloom cc = 0; 4377823Sroot } 43818651Sbloom (void) putc(0, &tp->t_canq); 43918651Sbloom ttwakeup(tp); 44018651Sbloom wakeup((caddr_t)&tp->t_canq); 44118651Sbloom return (0); 44218651Sbloom } 44345570Skarels while (uio->uio_resid > 0) { 44418651Sbloom if (cc == 0) { 44545570Skarels cc = min(uio->uio_resid, BUFSIZ); 44618651Sbloom cp = locbuf; 44745570Skarels error = uiomove((caddr_t)cp, cc, uio); 44818651Sbloom if (error) 44918651Sbloom return (error); 45018651Sbloom /* check again for safety */ 45118651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 45218651Sbloom return (EIO); 4535894Swnj } 45423633Sbloom while (cc > 0) { 45523633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 45635811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 45723633Sbloom wakeup((caddr_t)&tp->t_rawq); 45823633Sbloom goto block; 45923633Sbloom } 46045570Skarels (*linesw[tp->t_line].l_rint)(*cp++, tp); 4615408Swnj cnt++; 46223633Sbloom cc--; 4632281Stoy } 46418651Sbloom cc = 0; 46518651Sbloom } 46618651Sbloom return (0); 46718651Sbloom block: 46818651Sbloom /* 46923633Sbloom * Come here to wait for slave to open, for space 47023633Sbloom * in outq, or space in rawq. 47118651Sbloom */ 47218651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 47318651Sbloom return (EIO); 47445570Skarels if (flag & IO_NDELAY) { 47545570Skarels /* adjust for data copied in but not written */ 47618651Sbloom uio->uio_resid += cc; 47723633Sbloom if (cnt == 0) 47823633Sbloom return (EWOULDBLOCK); 47918651Sbloom return (0); 48018651Sbloom } 48140714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 48245570Skarels ttyout, 0)) { 48345570Skarels /* adjust for data copied in but not written */ 48445570Skarels uio->uio_resid += cc; 48540714Skarels return (error); 48645570Skarels } 48718651Sbloom goto again; 4882281Stoy } 4892281Stoy 4902281Stoy /*ARGSUSED*/ 4917626Ssam ptyioctl(dev, cmd, data, flag) 4927626Ssam caddr_t data; 4934484Swnj dev_t dev; 4944484Swnj { 4956119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4966119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 49735811Smarc register u_char *cc = tp->t_cc; 49818651Sbloom int stop, error; 49925390Skarels extern ttyinput(); 5002281Stoy 50125390Skarels /* 50225390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 50325390Skarels * ttywflush(tp) will hang if there are characters in the outq. 50425390Skarels */ 50542895Smarc if (cmd == TIOCEXT) { 50642895Smarc /* 50742895Smarc * When the EXTPROC bit is being toggled, we need 50842895Smarc * to send an TIOCPKT_IOCTL if the packet driver 50942895Smarc * is turned on. 51042895Smarc */ 51142895Smarc if (*(int *)data) { 51242895Smarc if (pti->pt_flags & PF_PKT) { 51342895Smarc pti->pt_send |= TIOCPKT_IOCTL; 51442895Smarc ptcwakeup(tp); 51542895Smarc } 51642895Smarc tp->t_lflag |= EXTPROC; 51742895Smarc } else { 51842895Smarc if ((tp->t_state & EXTPROC) && 51942895Smarc (pti->pt_flags & PF_PKT)) { 52042895Smarc pti->pt_send |= TIOCPKT_IOCTL; 52142895Smarc ptcwakeup(tp); 52242895Smarc } 52342895Smarc tp->t_lflag &= ~EXTPROC; 52442895Smarc } 52542895Smarc return(0); 52642895Smarc } else 52735811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5287626Ssam switch (cmd) { 5297626Ssam 53044313Smarc case TIOCGPGRP: 53144313Smarc /* 53244313Smarc * We aviod calling ttioctl on the controller since, 53344313Smarc * in that case, tp must be the controlling terminal. 53444313Smarc */ 53544313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 53644313Smarc return (0); 53744313Smarc 5387626Ssam case TIOCPKT: 53918651Sbloom if (*(int *)data) { 54018651Sbloom if (pti->pt_flags & PF_UCNTL) 54118651Sbloom return (EINVAL); 5425427Swnj pti->pt_flags |= PF_PKT; 54318651Sbloom } else 5445427Swnj pti->pt_flags &= ~PF_PKT; 5458563Sroot return (0); 5467626Ssam 54718651Sbloom case TIOCUCNTL: 54818651Sbloom if (*(int *)data) { 54918651Sbloom if (pti->pt_flags & PF_PKT) 55018651Sbloom return (EINVAL); 55118651Sbloom pti->pt_flags |= PF_UCNTL; 55218651Sbloom } else 55318651Sbloom pti->pt_flags &= ~PF_UCNTL; 55418651Sbloom return (0); 55518651Sbloom 5567626Ssam case TIOCREMOTE: 5577626Ssam if (*(int *)data) 5585894Swnj pti->pt_flags |= PF_REMOTE; 5595894Swnj else 5605894Swnj pti->pt_flags &= ~PF_REMOTE; 56112753Ssam ttyflush(tp, FREAD|FWRITE); 5628563Sroot return (0); 5637626Ssam 56435811Smarc case TIOCSETP: 56525390Skarels case TIOCSETN: 56625390Skarels case TIOCSETD: 56735811Smarc case TIOCSETA: 56835811Smarc case TIOCSETAW: 56935811Smarc case TIOCSETAF: 5707626Ssam while (getc(&tp->t_outq) >= 0) 5717626Ssam ; 5727626Ssam break; 57342895Smarc 57442895Smarc case TIOCSIG: 57542895Smarc if (*(unsigned int *)data >= NSIG) 57642895Smarc return(EINVAL); 57742895Smarc if ((tp->t_lflag&NOFLSH) == 0) 57842895Smarc ttyflush(tp, FREAD|FWRITE); 57945227Sborman pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 58045227Sborman if ((*(unsigned int *)data == SIGINFO) && 58145227Sborman ((tp->t_lflag&NOKERNINFO) == 0)) 58245227Sborman ttyinfo(tp); 58342895Smarc return(0); 5845411Swnj } 58535811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 58635811Smarc if (error < 0) 58735811Smarc error = ttioctl(tp, cmd, data, flag); 58825390Skarels /* 58925390Skarels * Since we use the tty queues internally, 59025390Skarels * pty's can't be switched to disciplines which overwrite 59125390Skarels * the queues. We can't tell anything about the discipline 59225390Skarels * from here... 59325390Skarels */ 59425390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 59525390Skarels (*linesw[tp->t_line].l_close)(tp); 59645570Skarels tp->t_line = TTYDISC; 59737590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 59825390Skarels error = ENOTTY; 59925390Skarels } 60018651Sbloom if (error < 0) { 60118651Sbloom if (pti->pt_flags & PF_UCNTL && 60228285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 60318651Sbloom if (cmd & 0xff) { 60418651Sbloom pti->pt_ucntl = (u_char)cmd; 60518651Sbloom ptcwakeup(tp, FREAD); 60618651Sbloom } 60718651Sbloom return (0); 60818651Sbloom } 6098563Sroot error = ENOTTY; 61018651Sbloom } 61142895Smarc /* 61242895Smarc * If external processing and packet mode send ioctl packet. 61342895Smarc */ 61442895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 61542895Smarc switch(cmd) { 61642895Smarc case TIOCSETA: 61742895Smarc case TIOCSETAW: 61842895Smarc case TIOCSETAF: 61942895Smarc case TIOCSETP: 62042895Smarc case TIOCSETN: 62142895Smarc #ifdef COMPAT_43 62242895Smarc case TIOCSETC: 62342895Smarc case TIOCSLTC: 62442895Smarc case TIOCLBIS: 62542895Smarc case TIOCLBIC: 62642895Smarc case TIOCLSET: 62742895Smarc #endif 62842895Smarc pti->pt_send |= TIOCPKT_IOCTL; 62942895Smarc default: 63042895Smarc break; 63142895Smarc } 63242895Smarc } 63335811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 63435811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6356119Swnj if (pti->pt_flags & PF_NOSTOP) { 6366119Swnj if (stop) { 63725478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6386119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6396119Swnj pti->pt_flags &= ~PF_NOSTOP; 64018651Sbloom ptcwakeup(tp, FREAD); 6416119Swnj } 6426119Swnj } else { 64318651Sbloom if (!stop) { 6446119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6456119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6466119Swnj pti->pt_flags |= PF_NOSTOP; 64718651Sbloom ptcwakeup(tp, FREAD); 6486119Swnj } 6496119Swnj } 6508563Sroot return (error); 6512281Stoy } 6522313Stoy #endif 653