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*47548Skarels * @(#)tty_pty.c 7.18 (Berkeley) 03/17/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 "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_PKT 0x08 /* packet mode */ 5435811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 5535811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 5635811Smarc #define PF_NOSTOP 0x40 5735811Smarc #define PF_UCNTL 0x80 /* user control mode */ 582281Stoy 592281Stoy /*ARGSUSED*/ 602281Stoy ptsopen(dev, flag) 615396Sroot dev_t dev; 624484Swnj { 63*47548Skarels struct proc *p = curproc; 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() */ 82*47548Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_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 { 114*47548Skarels struct proc *p = curproc; 1155894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1165894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1178521Sroot int error = 0; 1182281Stoy 1195894Swnj again: 1205894Swnj if (pti->pt_flags & PF_REMOTE) { 121*47548Skarels while (isbackground(p, tp)) { 122*47548Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 123*47548Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 124*47548Skarels p->p_pgrp->pg_jobc == 0 || 125*47548Skarels p->p_flag&SPPWAIT) 1268521Sroot return (EIO); 127*47548Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 12844312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 12944312Smarc TTIPRI | PCATCH, ttybg, 0)) 13040714Skarels return (error); 1315408Swnj } 13218651Sbloom if (tp->t_canq.c_cc == 0) { 13337728Smckusick if (flag & IO_NDELAY) 1348521Sroot return (EWOULDBLOCK); 13544312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 13640714Skarels TTIPRI | PCATCH, ttyin, 0)) 13740714Skarels return (error); 1385894Swnj goto again; 1395894Swnj } 14018651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 14118651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1428521Sroot error = EFAULT; 1437823Sroot break; 1447823Sroot } 14518651Sbloom if (tp->t_canq.c_cc == 1) 14618651Sbloom (void) getc(&tp->t_canq); 14718651Sbloom if (tp->t_canq.c_cc) 1488521Sroot return (error); 1495894Swnj } else 1505894Swnj if (tp->t_oproc) 15137590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 15218651Sbloom ptcwakeup(tp, FWRITE); 1538521Sroot return (error); 1542281Stoy } 1552281Stoy 1565408Swnj /* 1575408Swnj * Write to pseudo-tty. 1585408Swnj * Wakeups of controlling tty will happen 1595408Swnj * indirectly, when tty driver calls ptsstart. 1605408Swnj */ 16137590Smarc ptswrite(dev, uio, flag) 1625396Sroot dev_t dev; 1637823Sroot struct uio *uio; 1644484Swnj { 16535811Smarc register struct tty *tp; 1662281Stoy 16735811Smarc tp = &pt_tty[minor(dev)]; 1688521Sroot if (tp->t_oproc == 0) 1698521Sroot return (EIO); 17037590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1712281Stoy } 1722281Stoy 1735408Swnj /* 1745408Swnj * Start output on pseudo-tty. 1755408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1765408Swnj */ 1772281Stoy ptsstart(tp) 1784484Swnj struct tty *tp; 1794484Swnj { 1805574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1814484Swnj 1825408Swnj if (tp->t_state & TS_TTSTOP) 1832281Stoy return; 1845574Swnj if (pti->pt_flags & PF_STOPPED) { 1855574Swnj pti->pt_flags &= ~PF_STOPPED; 1865574Swnj pti->pt_send = TIOCPKT_START; 1875574Swnj } 18818651Sbloom ptcwakeup(tp, FREAD); 1895430Swnj } 1905430Swnj 19118651Sbloom ptcwakeup(tp, flag) 1925430Swnj struct tty *tp; 1935430Swnj { 1945430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1955430Swnj 19618651Sbloom if (flag & FREAD) { 19718651Sbloom if (pti->pt_selr) { 19818651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 19918651Sbloom pti->pt_selr = 0; 20018651Sbloom pti->pt_flags &= ~PF_RCOLL; 20118651Sbloom } 20218651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2034484Swnj } 20418651Sbloom if (flag & FWRITE) { 20518651Sbloom if (pti->pt_selw) { 20618651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 20718651Sbloom pti->pt_selw = 0; 20818651Sbloom pti->pt_flags &= ~PF_WCOLL; 20918651Sbloom } 210*47548Skarels if (ptydebug) printf("WAKEUP c_cf %d\n", curproc->p_pid); 21118651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 21218651Sbloom } 2132281Stoy } 2142281Stoy 2152281Stoy /*ARGSUSED*/ 2162281Stoy ptcopen(dev, flag) 2174484Swnj dev_t dev; 2184484Swnj int flag; 2194484Swnj { 2202281Stoy register struct tty *tp; 2215427Swnj struct pt_ioctl *pti; 2222281Stoy 2238563Sroot if (minor(dev) >= NPTY) 2248563Sroot return (ENXIO); 2252281Stoy tp = &pt_tty[minor(dev)]; 2268563Sroot if (tp->t_oproc) 2278563Sroot return (EIO); 2284484Swnj tp->t_oproc = ptsstart; 22925390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 23042895Smarc tp->t_lflag &= ~EXTPROC; 2315427Swnj pti = &pt_ioctl[minor(dev)]; 2325427Swnj pti->pt_flags = 0; 2335427Swnj pti->pt_send = 0; 23418651Sbloom pti->pt_ucntl = 0; 2358563Sroot return (0); 2362281Stoy } 2372281Stoy 2382281Stoy ptcclose(dev) 2394484Swnj dev_t dev; 2404484Swnj { 2412281Stoy register struct tty *tp; 2422281Stoy 2432281Stoy tp = &pt_tty[minor(dev)]; 24425390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 24532326Skarels tp->t_state &= ~TS_CARR_ON; 2464484Swnj tp->t_oproc = 0; /* mark closed */ 24739497Smarc tp->t_session = 0; 2482281Stoy } 2492281Stoy 25037590Smarc ptcread(dev, uio, flag) 2515427Swnj dev_t dev; 2527823Sroot struct uio *uio; 2534484Swnj { 2548521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 25518651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 25616788Ssam char buf[BUFSIZ]; 25716788Ssam int error = 0, cc; 2582281Stoy 25918651Sbloom /* 26018651Sbloom * We want to block until the slave 26118651Sbloom * is open, and there's something to read; 26218651Sbloom * but if we lost the slave or we're NBIO, 26318651Sbloom * then return the appropriate error instead. 26418651Sbloom */ 26518651Sbloom for (;;) { 26618651Sbloom if (tp->t_state&TS_ISOPEN) { 26718651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 26826358Skarels error = ureadc((int)pti->pt_send, uio); 26918651Sbloom if (error) 27018651Sbloom return (error); 27142895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 27242895Smarc cc = MIN(uio->uio_resid, 27342895Smarc sizeof(tp->t_termios)); 27442895Smarc uiomove(&tp->t_termios, cc, uio); 27542895Smarc } 27618651Sbloom pti->pt_send = 0; 27718651Sbloom return (0); 27818651Sbloom } 27918651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 28026358Skarels error = ureadc((int)pti->pt_ucntl, uio); 28118651Sbloom if (error) 28218651Sbloom return (error); 28318651Sbloom pti->pt_ucntl = 0; 28418651Sbloom return (0); 28518651Sbloom } 28618651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 28718651Sbloom break; 2885427Swnj } 28916788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 29037590Smarc return (0); /* EOF */ 29137728Smckusick if (flag & IO_NDELAY) 2928521Sroot return (EWOULDBLOCK); 29340714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 29440714Skarels ttyin, 0)) 29540714Skarels return (error); 2965411Swnj } 29735811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 29818651Sbloom error = ureadc(0, uio); 29916788Ssam while (uio->uio_resid > 0 && error == 0) { 30016788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 30116788Ssam if (cc <= 0) 3027823Sroot break; 30337728Smckusick error = uiomove(buf, cc, uio); 30416788Ssam } 30535811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 30635811Smarc if (tp->t_state&TS_ASLEEP) { 30735811Smarc tp->t_state &= ~TS_ASLEEP; 30835811Smarc wakeup((caddr_t)&tp->t_outq); 30935811Smarc } 31035811Smarc if (tp->t_wsel) { 31135811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 31235811Smarc tp->t_wsel = 0; 31335811Smarc tp->t_state &= ~TS_WCOLL; 31435811Smarc } 31535811Smarc } 3168521Sroot return (error); 3172281Stoy } 3182281Stoy 3195427Swnj ptsstop(tp, flush) 3205427Swnj register struct tty *tp; 3215427Swnj int flush; 3225427Swnj { 3235427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 32418651Sbloom int flag; 3255427Swnj 3265574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3275574Swnj if (flush == 0) { 3285574Swnj flush = TIOCPKT_STOP; 3295574Swnj pti->pt_flags |= PF_STOPPED; 33018651Sbloom } else 3315574Swnj pti->pt_flags &= ~PF_STOPPED; 3326119Swnj pti->pt_send |= flush; 33318651Sbloom /* change of perspective */ 33418651Sbloom flag = 0; 33518651Sbloom if (flush & FREAD) 33618651Sbloom flag |= FWRITE; 33718651Sbloom if (flush & FWRITE) 33818651Sbloom flag |= FREAD; 33923633Sbloom ptcwakeup(tp, flag); 3405427Swnj } 3415427Swnj 3425408Swnj ptcselect(dev, rw) 3434484Swnj dev_t dev; 3445408Swnj int rw; 3454484Swnj { 346*47548Skarels struct proc *curp = curproc; 3474484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3485894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3494484Swnj struct proc *p; 3505430Swnj int s; 3514484Swnj 35218651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3534484Swnj return (1); 3545408Swnj switch (rw) { 3555408Swnj 3565408Swnj case FREAD: 35725945Skarels /* 35825945Skarels * Need to block timeouts (ttrstart). 35925945Skarels */ 36025945Skarels s = spltty(); 36118651Sbloom if ((tp->t_state&TS_ISOPEN) && 36225436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 36325436Skarels splx(s); 36425436Skarels return (1); 36525436Skarels } 36625945Skarels splx(s); 36725436Skarels /* FALLTHROUGH */ 36825436Skarels 36925436Skarels case 0: /* exceptional */ 37025436Skarels if ((tp->t_state&TS_ISOPEN) && 37118651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 37225945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3735408Swnj return (1); 3745427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3755427Swnj pti->pt_flags |= PF_RCOLL; 3765408Swnj else 377*47548Skarels pti->pt_selr = curp; 3785430Swnj break; 3795408Swnj 38025436Skarels 3815408Swnj case FWRITE: 38225945Skarels if (tp->t_state&TS_ISOPEN) { 38325945Skarels if (pti->pt_flags & PF_REMOTE) { 38425945Skarels if (tp->t_canq.c_cc == 0) 38525945Skarels return (1); 38625945Skarels } else { 38725945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 38825945Skarels return (1); 38935811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 39025945Skarels return (1); 39125945Skarels } 3925430Swnj } 3935427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3945427Swnj pti->pt_flags |= PF_WCOLL; 3955408Swnj else 396*47548Skarels pti->pt_selw = curp; 3975430Swnj break; 39825436Skarels 3995408Swnj } 4005430Swnj return (0); 4015396Sroot } 4024484Swnj 40337590Smarc ptcwrite(dev, uio, flag) 4045408Swnj dev_t dev; 40518651Sbloom register struct uio *uio; 4064484Swnj { 4078521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 40845570Skarels register u_char *cp; 40918651Sbloom register int cc = 0; 41045570Skarels u_char locbuf[BUFSIZ]; 4115408Swnj int cnt = 0; 4125894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4138521Sroot int error = 0; 4142281Stoy 41518651Sbloom again: 41618651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 41718651Sbloom goto block; 41823633Sbloom if (pti->pt_flags & PF_REMOTE) { 41918651Sbloom if (tp->t_canq.c_cc) 42018651Sbloom goto block; 42145570Skarels while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 42223633Sbloom if (cc == 0) { 42345570Skarels cc = min(uio->uio_resid, BUFSIZ); 42445570Skarels cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 42523633Sbloom cp = locbuf; 42645570Skarels error = uiomove((caddr_t)cp, cc, uio); 42723633Sbloom if (error) 42823633Sbloom return (error); 42923633Sbloom /* check again for safety */ 43023633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43123633Sbloom return (EIO); 43223633Sbloom } 43323633Sbloom if (cc) 43445570Skarels (void) b_to_q((char *)cp, cc, &tp->t_canq); 43523633Sbloom cc = 0; 4367823Sroot } 43718651Sbloom (void) putc(0, &tp->t_canq); 43818651Sbloom ttwakeup(tp); 43918651Sbloom wakeup((caddr_t)&tp->t_canq); 44018651Sbloom return (0); 44118651Sbloom } 44245570Skarels while (uio->uio_resid > 0) { 44318651Sbloom if (cc == 0) { 44445570Skarels cc = min(uio->uio_resid, BUFSIZ); 44518651Sbloom cp = locbuf; 44645570Skarels error = uiomove((caddr_t)cp, cc, uio); 44718651Sbloom if (error) 44818651Sbloom return (error); 44918651Sbloom /* check again for safety */ 45018651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 45118651Sbloom return (EIO); 4525894Swnj } 45323633Sbloom while (cc > 0) { 45423633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 45535811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 45623633Sbloom wakeup((caddr_t)&tp->t_rawq); 45723633Sbloom goto block; 45823633Sbloom } 45945570Skarels (*linesw[tp->t_line].l_rint)(*cp++, tp); 4605408Swnj cnt++; 46123633Sbloom cc--; 4622281Stoy } 46318651Sbloom cc = 0; 46418651Sbloom } 46518651Sbloom return (0); 46618651Sbloom block: 46718651Sbloom /* 46823633Sbloom * Come here to wait for slave to open, for space 46923633Sbloom * in outq, or space in rawq. 47018651Sbloom */ 47118651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 47218651Sbloom return (EIO); 47345570Skarels if (flag & IO_NDELAY) { 47445570Skarels /* adjust for data copied in but not written */ 47518651Sbloom uio->uio_resid += cc; 47623633Sbloom if (cnt == 0) 47723633Sbloom return (EWOULDBLOCK); 47818651Sbloom return (0); 47918651Sbloom } 48040714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 48145570Skarels ttyout, 0)) { 48245570Skarels /* adjust for data copied in but not written */ 48345570Skarels uio->uio_resid += cc; 48440714Skarels return (error); 48545570Skarels } 48618651Sbloom goto again; 4872281Stoy } 4882281Stoy 4892281Stoy /*ARGSUSED*/ 4907626Ssam ptyioctl(dev, cmd, data, flag) 4917626Ssam caddr_t data; 4924484Swnj dev_t dev; 4934484Swnj { 4946119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4956119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 49635811Smarc register u_char *cc = tp->t_cc; 49718651Sbloom int stop, error; 49825390Skarels extern ttyinput(); 4992281Stoy 50025390Skarels /* 50125390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 50225390Skarels * ttywflush(tp) will hang if there are characters in the outq. 50325390Skarels */ 50442895Smarc if (cmd == TIOCEXT) { 50542895Smarc /* 50642895Smarc * When the EXTPROC bit is being toggled, we need 50742895Smarc * to send an TIOCPKT_IOCTL if the packet driver 50842895Smarc * is turned on. 50942895Smarc */ 51042895Smarc if (*(int *)data) { 51142895Smarc if (pti->pt_flags & PF_PKT) { 51242895Smarc pti->pt_send |= TIOCPKT_IOCTL; 51342895Smarc ptcwakeup(tp); 51442895Smarc } 51542895Smarc tp->t_lflag |= EXTPROC; 51642895Smarc } else { 51742895Smarc if ((tp->t_state & EXTPROC) && 51842895Smarc (pti->pt_flags & PF_PKT)) { 51942895Smarc pti->pt_send |= TIOCPKT_IOCTL; 52042895Smarc ptcwakeup(tp); 52142895Smarc } 52242895Smarc tp->t_lflag &= ~EXTPROC; 52342895Smarc } 52442895Smarc return(0); 52542895Smarc } else 52635811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5277626Ssam switch (cmd) { 5287626Ssam 52944313Smarc case TIOCGPGRP: 53044313Smarc /* 53144313Smarc * We aviod calling ttioctl on the controller since, 53244313Smarc * in that case, tp must be the controlling terminal. 53344313Smarc */ 53444313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 53544313Smarc return (0); 53644313Smarc 5377626Ssam case TIOCPKT: 53818651Sbloom if (*(int *)data) { 53918651Sbloom if (pti->pt_flags & PF_UCNTL) 54018651Sbloom return (EINVAL); 5415427Swnj pti->pt_flags |= PF_PKT; 54218651Sbloom } else 5435427Swnj pti->pt_flags &= ~PF_PKT; 5448563Sroot return (0); 5457626Ssam 54618651Sbloom case TIOCUCNTL: 54718651Sbloom if (*(int *)data) { 54818651Sbloom if (pti->pt_flags & PF_PKT) 54918651Sbloom return (EINVAL); 55018651Sbloom pti->pt_flags |= PF_UCNTL; 55118651Sbloom } else 55218651Sbloom pti->pt_flags &= ~PF_UCNTL; 55318651Sbloom return (0); 55418651Sbloom 5557626Ssam case TIOCREMOTE: 5567626Ssam if (*(int *)data) 5575894Swnj pti->pt_flags |= PF_REMOTE; 5585894Swnj else 5595894Swnj pti->pt_flags &= ~PF_REMOTE; 56012753Ssam ttyflush(tp, FREAD|FWRITE); 5618563Sroot return (0); 5627626Ssam 56335811Smarc case TIOCSETP: 56425390Skarels case TIOCSETN: 56525390Skarels case TIOCSETD: 56635811Smarc case TIOCSETA: 56735811Smarc case TIOCSETAW: 56835811Smarc case TIOCSETAF: 5697626Ssam while (getc(&tp->t_outq) >= 0) 5707626Ssam ; 5717626Ssam break; 57242895Smarc 57342895Smarc case TIOCSIG: 57442895Smarc if (*(unsigned int *)data >= NSIG) 57542895Smarc return(EINVAL); 57642895Smarc if ((tp->t_lflag&NOFLSH) == 0) 57742895Smarc ttyflush(tp, FREAD|FWRITE); 57845227Sborman pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 57945227Sborman if ((*(unsigned int *)data == SIGINFO) && 58045227Sborman ((tp->t_lflag&NOKERNINFO) == 0)) 58145227Sborman ttyinfo(tp); 58242895Smarc return(0); 5835411Swnj } 58435811Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 58535811Smarc if (error < 0) 58635811Smarc error = ttioctl(tp, cmd, data, flag); 58725390Skarels /* 58825390Skarels * Since we use the tty queues internally, 58925390Skarels * pty's can't be switched to disciplines which overwrite 59025390Skarels * the queues. We can't tell anything about the discipline 59125390Skarels * from here... 59225390Skarels */ 59325390Skarels if (linesw[tp->t_line].l_rint != ttyinput) { 59425390Skarels (*linesw[tp->t_line].l_close)(tp); 59545570Skarels tp->t_line = TTYDISC; 59637590Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 59725390Skarels error = ENOTTY; 59825390Skarels } 59918651Sbloom if (error < 0) { 60018651Sbloom if (pti->pt_flags & PF_UCNTL && 60128285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 60218651Sbloom if (cmd & 0xff) { 60318651Sbloom pti->pt_ucntl = (u_char)cmd; 60418651Sbloom ptcwakeup(tp, FREAD); 60518651Sbloom } 60618651Sbloom return (0); 60718651Sbloom } 6088563Sroot error = ENOTTY; 60918651Sbloom } 61042895Smarc /* 61142895Smarc * If external processing and packet mode send ioctl packet. 61242895Smarc */ 61342895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 61442895Smarc switch(cmd) { 61542895Smarc case TIOCSETA: 61642895Smarc case TIOCSETAW: 61742895Smarc case TIOCSETAF: 61842895Smarc case TIOCSETP: 61942895Smarc case TIOCSETN: 62042895Smarc #ifdef COMPAT_43 62142895Smarc case TIOCSETC: 62242895Smarc case TIOCSLTC: 62342895Smarc case TIOCLBIS: 62442895Smarc case TIOCLBIC: 62542895Smarc case TIOCLSET: 62642895Smarc #endif 62742895Smarc pti->pt_send |= TIOCPKT_IOCTL; 62842895Smarc default: 62942895Smarc break; 63042895Smarc } 63142895Smarc } 63235811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 63335811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6346119Swnj if (pti->pt_flags & PF_NOSTOP) { 6356119Swnj if (stop) { 63625478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6376119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6386119Swnj pti->pt_flags &= ~PF_NOSTOP; 63918651Sbloom ptcwakeup(tp, FREAD); 6406119Swnj } 6416119Swnj } else { 64218651Sbloom if (!stop) { 6436119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6446119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6456119Swnj pti->pt_flags |= PF_NOSTOP; 64618651Sbloom ptcwakeup(tp, FREAD); 6476119Swnj } 6486119Swnj } 6498563Sroot return (error); 6502281Stoy } 6512313Stoy #endif 652