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*52411Storek * @(#)tty_pty.c 7.23 (Berkeley) 02/05/92 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 56*52411Storek void ptsstop __P((struct tty *, int)); 57*52411Storek 582281Stoy /*ARGSUSED*/ 5948442Skarels ptsopen(dev, flag, devtype, p) 605396Sroot dev_t dev; 61*52411Storek int flag, devtype; 6248442Skarels struct proc *p; 634484Swnj { 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() */ 8247548Skarels } 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; 8849941Smckusick if (flag&FNONBLOCK) 8937590Smarc break; 9044312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 9140714Skarels ttopen, 0)) 9240714Skarels return (error); 932281Stoy } 94*52411Storek error = (*linesw[tp->t_line].l_open)(dev, tp); 9518651Sbloom ptcwakeup(tp, FREAD|FWRITE); 9618651Sbloom return (error); 972281Stoy } 982281Stoy 9949753Smarc ptsclose(dev, flag, mode, p) 1005396Sroot dev_t dev; 10149753Smarc int flag, mode; 10249753Smarc struct proc *p; 1035408Swnj { 1042281Stoy register struct tty *tp; 1052281Stoy 1062281Stoy tp = &pt_tty[minor(dev)]; 10749753Smarc (*linesw[tp->t_line].l_close)(tp, flag); 1086299Swnj ttyclose(tp); 10918651Sbloom ptcwakeup(tp, FREAD|FWRITE); 1102281Stoy } 1112281Stoy 11237590Smarc ptsread(dev, uio, flag) 1135396Sroot dev_t dev; 1147823Sroot struct uio *uio; 115*52411Storek int flag; 1164484Swnj { 11747548Skarels struct proc *p = curproc; 1185894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1195894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1208521Sroot int error = 0; 1212281Stoy 1225894Swnj again: 1235894Swnj if (pti->pt_flags & PF_REMOTE) { 12447548Skarels while (isbackground(p, tp)) { 12547548Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 12647548Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 12747548Skarels p->p_pgrp->pg_jobc == 0 || 12847548Skarels p->p_flag&SPPWAIT) 1298521Sroot return (EIO); 13047548Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 13144312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 13244312Smarc TTIPRI | PCATCH, ttybg, 0)) 13340714Skarels return (error); 1345408Swnj } 13518651Sbloom if (tp->t_canq.c_cc == 0) { 13637728Smckusick if (flag & IO_NDELAY) 1378521Sroot return (EWOULDBLOCK); 13844312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 13940714Skarels TTIPRI | PCATCH, ttyin, 0)) 14040714Skarels return (error); 1415894Swnj goto again; 1425894Swnj } 14318651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 14418651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1458521Sroot error = EFAULT; 1467823Sroot break; 1477823Sroot } 14818651Sbloom if (tp->t_canq.c_cc == 1) 14918651Sbloom (void) getc(&tp->t_canq); 15018651Sbloom if (tp->t_canq.c_cc) 1518521Sroot return (error); 1525894Swnj } else 1535894Swnj if (tp->t_oproc) 15437590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 15518651Sbloom ptcwakeup(tp, FWRITE); 1568521Sroot return (error); 1572281Stoy } 1582281Stoy 1595408Swnj /* 1605408Swnj * Write to pseudo-tty. 1615408Swnj * Wakeups of controlling tty will happen 1625408Swnj * indirectly, when tty driver calls ptsstart. 1635408Swnj */ 16437590Smarc ptswrite(dev, uio, flag) 1655396Sroot dev_t dev; 1667823Sroot struct uio *uio; 1674484Swnj { 16835811Smarc register struct tty *tp; 1692281Stoy 17035811Smarc tp = &pt_tty[minor(dev)]; 1718521Sroot if (tp->t_oproc == 0) 1728521Sroot return (EIO); 17337590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1742281Stoy } 1752281Stoy 1765408Swnj /* 1775408Swnj * Start output on pseudo-tty. 1785408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1795408Swnj */ 180*52411Storek void 1812281Stoy ptsstart(tp) 1824484Swnj struct tty *tp; 1834484Swnj { 1845574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1854484Swnj 1865408Swnj if (tp->t_state & TS_TTSTOP) 1872281Stoy return; 1885574Swnj if (pti->pt_flags & PF_STOPPED) { 1895574Swnj pti->pt_flags &= ~PF_STOPPED; 1905574Swnj pti->pt_send = TIOCPKT_START; 1915574Swnj } 19218651Sbloom ptcwakeup(tp, FREAD); 1935430Swnj } 1945430Swnj 19518651Sbloom ptcwakeup(tp, flag) 1965430Swnj struct tty *tp; 197*52411Storek int flag; 1985430Swnj { 1995430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 2005430Swnj 20118651Sbloom if (flag & FREAD) { 20218651Sbloom if (pti->pt_selr) { 20318651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 20418651Sbloom pti->pt_selr = 0; 20518651Sbloom pti->pt_flags &= ~PF_RCOLL; 20618651Sbloom } 20718651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2084484Swnj } 20918651Sbloom if (flag & FWRITE) { 21018651Sbloom if (pti->pt_selw) { 21118651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 21218651Sbloom pti->pt_selw = 0; 21318651Sbloom pti->pt_flags &= ~PF_WCOLL; 21418651Sbloom } 21518651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 21618651Sbloom } 2172281Stoy } 2182281Stoy 2192281Stoy /*ARGSUSED*/ 22048442Skarels #ifdef __STDC__ 22148442Skarels ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 22248442Skarels #else 22348442Skarels ptcopen(dev, flag, devtype, p) 2244484Swnj dev_t dev; 22548442Skarels int flag, devtype; 22648442Skarels struct proc *p; 22748442Skarels #endif 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; 238*52411Storek #ifdef sun4c 239*52411Storek tp->t_stop = ptsstop; 240*52411Storek #endif 24125390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 24242895Smarc tp->t_lflag &= ~EXTPROC; 2435427Swnj pti = &pt_ioctl[minor(dev)]; 2445427Swnj pti->pt_flags = 0; 2455427Swnj pti->pt_send = 0; 24618651Sbloom pti->pt_ucntl = 0; 2478563Sroot return (0); 2482281Stoy } 2492281Stoy 2502281Stoy ptcclose(dev) 2514484Swnj dev_t dev; 2524484Swnj { 2532281Stoy register struct tty *tp; 2542281Stoy 2552281Stoy tp = &pt_tty[minor(dev)]; 25625390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 25732326Skarels tp->t_state &= ~TS_CARR_ON; 2584484Swnj tp->t_oproc = 0; /* mark closed */ 25939497Smarc tp->t_session = 0; 2602281Stoy } 2612281Stoy 26237590Smarc ptcread(dev, uio, flag) 2635427Swnj dev_t dev; 2647823Sroot struct uio *uio; 265*52411Storek int flag; 2664484Swnj { 2678521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 26818651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 26916788Ssam char buf[BUFSIZ]; 27016788Ssam int error = 0, cc; 2712281Stoy 27218651Sbloom /* 27318651Sbloom * We want to block until the slave 27418651Sbloom * is open, and there's something to read; 27518651Sbloom * but if we lost the slave or we're NBIO, 27618651Sbloom * then return the appropriate error instead. 27718651Sbloom */ 27818651Sbloom for (;;) { 27918651Sbloom if (tp->t_state&TS_ISOPEN) { 28018651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 28126358Skarels error = ureadc((int)pti->pt_send, uio); 28218651Sbloom if (error) 28318651Sbloom return (error); 28442895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 28542895Smarc cc = MIN(uio->uio_resid, 28642895Smarc sizeof(tp->t_termios)); 28742895Smarc uiomove(&tp->t_termios, cc, uio); 28842895Smarc } 28918651Sbloom pti->pt_send = 0; 29018651Sbloom return (0); 29118651Sbloom } 29218651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 29326358Skarels error = ureadc((int)pti->pt_ucntl, uio); 29418651Sbloom if (error) 29518651Sbloom return (error); 29618651Sbloom pti->pt_ucntl = 0; 29718651Sbloom return (0); 29818651Sbloom } 29918651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 30018651Sbloom break; 3015427Swnj } 30216788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 30337590Smarc return (0); /* EOF */ 30437728Smckusick if (flag & IO_NDELAY) 3058521Sroot return (EWOULDBLOCK); 30640714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 30740714Skarels ttyin, 0)) 30840714Skarels return (error); 3095411Swnj } 31035811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 31118651Sbloom error = ureadc(0, uio); 31216788Ssam while (uio->uio_resid > 0 && error == 0) { 31316788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 31416788Ssam if (cc <= 0) 3157823Sroot break; 31637728Smckusick error = uiomove(buf, cc, uio); 31716788Ssam } 31835811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 31935811Smarc if (tp->t_state&TS_ASLEEP) { 32035811Smarc tp->t_state &= ~TS_ASLEEP; 32135811Smarc wakeup((caddr_t)&tp->t_outq); 32235811Smarc } 32335811Smarc if (tp->t_wsel) { 32435811Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 32535811Smarc tp->t_wsel = 0; 32635811Smarc tp->t_state &= ~TS_WCOLL; 32735811Smarc } 32835811Smarc } 3298521Sroot return (error); 3302281Stoy } 3312281Stoy 332*52411Storek void 3335427Swnj ptsstop(tp, flush) 3345427Swnj register struct tty *tp; 3355427Swnj int flush; 3365427Swnj { 3375427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 33818651Sbloom int flag; 3395427Swnj 3405574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3415574Swnj if (flush == 0) { 3425574Swnj flush = TIOCPKT_STOP; 3435574Swnj pti->pt_flags |= PF_STOPPED; 34418651Sbloom } else 3455574Swnj pti->pt_flags &= ~PF_STOPPED; 3466119Swnj pti->pt_send |= flush; 34718651Sbloom /* change of perspective */ 34818651Sbloom flag = 0; 34918651Sbloom if (flush & FREAD) 35018651Sbloom flag |= FWRITE; 35118651Sbloom if (flush & FWRITE) 35218651Sbloom flag |= FREAD; 35323633Sbloom ptcwakeup(tp, flag); 3545427Swnj } 3555427Swnj 35648442Skarels ptcselect(dev, rw, p) 3574484Swnj dev_t dev; 3585408Swnj int rw; 35948442Skarels struct proc *p; 3604484Swnj { 3614484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3625894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 36348442Skarels struct proc *prev; 3645430Swnj int s; 3654484Swnj 36618651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3674484Swnj return (1); 3685408Swnj switch (rw) { 3695408Swnj 3705408Swnj case FREAD: 37125945Skarels /* 37225945Skarels * Need to block timeouts (ttrstart). 37325945Skarels */ 37425945Skarels s = spltty(); 37518651Sbloom if ((tp->t_state&TS_ISOPEN) && 37625436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 37725436Skarels splx(s); 37825436Skarels return (1); 37925436Skarels } 38025945Skarels splx(s); 38125436Skarels /* FALLTHROUGH */ 38225436Skarels 38325436Skarels case 0: /* exceptional */ 38425436Skarels if ((tp->t_state&TS_ISOPEN) && 38518651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 38625945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3875408Swnj return (1); 38848442Skarels if ((prev = pti->pt_selr) && prev->p_wchan == (caddr_t)&selwait) 3895427Swnj pti->pt_flags |= PF_RCOLL; 3905408Swnj else 39148442Skarels pti->pt_selr = p; 3925430Swnj break; 3935408Swnj 39425436Skarels 3955408Swnj case FWRITE: 39625945Skarels if (tp->t_state&TS_ISOPEN) { 39725945Skarels if (pti->pt_flags & PF_REMOTE) { 39825945Skarels if (tp->t_canq.c_cc == 0) 39925945Skarels return (1); 40025945Skarels } else { 40125945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 40225945Skarels return (1); 40335811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 40425945Skarels return (1); 40525945Skarels } 4065430Swnj } 40748442Skarels if ((prev = pti->pt_selw) && prev->p_wchan == (caddr_t)&selwait) 4085427Swnj pti->pt_flags |= PF_WCOLL; 4095408Swnj else 41048442Skarels pti->pt_selw = p; 4115430Swnj break; 41225436Skarels 4135408Swnj } 4145430Swnj return (0); 4155396Sroot } 4164484Swnj 41737590Smarc ptcwrite(dev, uio, flag) 4185408Swnj dev_t dev; 41918651Sbloom register struct uio *uio; 4204484Swnj { 4218521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 42245570Skarels register u_char *cp; 42318651Sbloom register int cc = 0; 42445570Skarels u_char locbuf[BUFSIZ]; 4255408Swnj int cnt = 0; 4265894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4278521Sroot int error = 0; 4282281Stoy 42918651Sbloom again: 43018651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43118651Sbloom goto block; 43223633Sbloom if (pti->pt_flags & PF_REMOTE) { 43318651Sbloom if (tp->t_canq.c_cc) 43418651Sbloom goto block; 43545570Skarels while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 43623633Sbloom if (cc == 0) { 43745570Skarels cc = min(uio->uio_resid, BUFSIZ); 43845570Skarels cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 43923633Sbloom cp = locbuf; 44045570Skarels error = uiomove((caddr_t)cp, cc, uio); 44123633Sbloom if (error) 44223633Sbloom return (error); 44323633Sbloom /* check again for safety */ 44423633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 44523633Sbloom return (EIO); 44623633Sbloom } 44723633Sbloom if (cc) 44845570Skarels (void) b_to_q((char *)cp, cc, &tp->t_canq); 44923633Sbloom cc = 0; 4507823Sroot } 45118651Sbloom (void) putc(0, &tp->t_canq); 45218651Sbloom ttwakeup(tp); 45318651Sbloom wakeup((caddr_t)&tp->t_canq); 45418651Sbloom return (0); 45518651Sbloom } 45645570Skarels while (uio->uio_resid > 0) { 45718651Sbloom if (cc == 0) { 45845570Skarels cc = min(uio->uio_resid, BUFSIZ); 45918651Sbloom cp = locbuf; 46045570Skarels error = uiomove((caddr_t)cp, cc, uio); 46118651Sbloom if (error) 46218651Sbloom return (error); 46318651Sbloom /* check again for safety */ 46418651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 46518651Sbloom return (EIO); 4665894Swnj } 46723633Sbloom while (cc > 0) { 46823633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 46935811Smarc (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 47023633Sbloom wakeup((caddr_t)&tp->t_rawq); 47123633Sbloom goto block; 47223633Sbloom } 47345570Skarels (*linesw[tp->t_line].l_rint)(*cp++, tp); 4745408Swnj cnt++; 47523633Sbloom cc--; 4762281Stoy } 47718651Sbloom cc = 0; 47818651Sbloom } 47918651Sbloom return (0); 48018651Sbloom block: 48118651Sbloom /* 48223633Sbloom * Come here to wait for slave to open, for space 48323633Sbloom * in outq, or space in rawq. 48418651Sbloom */ 48518651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 48618651Sbloom return (EIO); 48745570Skarels if (flag & IO_NDELAY) { 48845570Skarels /* adjust for data copied in but not written */ 48918651Sbloom uio->uio_resid += cc; 49023633Sbloom if (cnt == 0) 49123633Sbloom return (EWOULDBLOCK); 49218651Sbloom return (0); 49318651Sbloom } 49440714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 49545570Skarels ttyout, 0)) { 49645570Skarels /* adjust for data copied in but not written */ 49745570Skarels uio->uio_resid += cc; 49840714Skarels return (error); 49945570Skarels } 50018651Sbloom goto again; 5012281Stoy } 5022281Stoy 5032281Stoy /*ARGSUSED*/ 504*52411Storek ptyioctl(dev, cmd, data, flag, p) 505*52411Storek dev_t dev; 506*52411Storek int cmd; 5077626Ssam caddr_t data; 508*52411Storek int flag; 509*52411Storek struct proc *p; 5104484Swnj { 5116119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5126119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 51335811Smarc register u_char *cc = tp->t_cc; 51418651Sbloom int stop, error; 5152281Stoy 51625390Skarels /* 51725390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 51825390Skarels * ttywflush(tp) will hang if there are characters in the outq. 51925390Skarels */ 52042895Smarc if (cmd == TIOCEXT) { 52142895Smarc /* 52242895Smarc * When the EXTPROC bit is being toggled, we need 52342895Smarc * to send an TIOCPKT_IOCTL if the packet driver 52442895Smarc * is turned on. 52542895Smarc */ 52642895Smarc if (*(int *)data) { 52742895Smarc if (pti->pt_flags & PF_PKT) { 52842895Smarc pti->pt_send |= TIOCPKT_IOCTL; 52942895Smarc ptcwakeup(tp); 53042895Smarc } 53142895Smarc tp->t_lflag |= EXTPROC; 53242895Smarc } else { 53342895Smarc if ((tp->t_state & EXTPROC) && 53442895Smarc (pti->pt_flags & PF_PKT)) { 53542895Smarc pti->pt_send |= TIOCPKT_IOCTL; 53642895Smarc ptcwakeup(tp); 53742895Smarc } 53842895Smarc tp->t_lflag &= ~EXTPROC; 53942895Smarc } 54042895Smarc return(0); 54142895Smarc } else 54235811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5437626Ssam switch (cmd) { 5447626Ssam 54544313Smarc case TIOCGPGRP: 54644313Smarc /* 54744313Smarc * We aviod calling ttioctl on the controller since, 54844313Smarc * in that case, tp must be the controlling terminal. 54944313Smarc */ 55044313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 55144313Smarc return (0); 55244313Smarc 5537626Ssam case TIOCPKT: 55418651Sbloom if (*(int *)data) { 55518651Sbloom if (pti->pt_flags & PF_UCNTL) 55618651Sbloom return (EINVAL); 5575427Swnj pti->pt_flags |= PF_PKT; 55818651Sbloom } else 5595427Swnj pti->pt_flags &= ~PF_PKT; 5608563Sroot return (0); 5617626Ssam 56218651Sbloom case TIOCUCNTL: 56318651Sbloom if (*(int *)data) { 56418651Sbloom if (pti->pt_flags & PF_PKT) 56518651Sbloom return (EINVAL); 56618651Sbloom pti->pt_flags |= PF_UCNTL; 56718651Sbloom } else 56818651Sbloom pti->pt_flags &= ~PF_UCNTL; 56918651Sbloom return (0); 57018651Sbloom 5717626Ssam case TIOCREMOTE: 5727626Ssam if (*(int *)data) 5735894Swnj pti->pt_flags |= PF_REMOTE; 5745894Swnj else 5755894Swnj pti->pt_flags &= ~PF_REMOTE; 57612753Ssam ttyflush(tp, FREAD|FWRITE); 5778563Sroot return (0); 5787626Ssam 579*52411Storek #ifdef COMPAT_43 58035811Smarc case TIOCSETP: 58125390Skarels case TIOCSETN: 582*52411Storek #endif 58325390Skarels case TIOCSETD: 58435811Smarc case TIOCSETA: 58535811Smarc case TIOCSETAW: 58635811Smarc case TIOCSETAF: 587*52411Storek ndflush(&tp->t_outq, tp->t_outq.c_cc); 5887626Ssam break; 58942895Smarc 59042895Smarc case TIOCSIG: 59142895Smarc if (*(unsigned int *)data >= NSIG) 59242895Smarc return(EINVAL); 59342895Smarc if ((tp->t_lflag&NOFLSH) == 0) 59442895Smarc ttyflush(tp, FREAD|FWRITE); 59545227Sborman pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 59645227Sborman if ((*(unsigned int *)data == SIGINFO) && 59745227Sborman ((tp->t_lflag&NOKERNINFO) == 0)) 59845227Sborman ttyinfo(tp); 59942895Smarc return(0); 6005411Swnj } 601*52411Storek error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 60235811Smarc if (error < 0) 60335811Smarc error = ttioctl(tp, cmd, data, flag); 60418651Sbloom if (error < 0) { 60518651Sbloom if (pti->pt_flags & PF_UCNTL && 60628285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 60718651Sbloom if (cmd & 0xff) { 60818651Sbloom pti->pt_ucntl = (u_char)cmd; 60918651Sbloom ptcwakeup(tp, FREAD); 61018651Sbloom } 61118651Sbloom return (0); 61218651Sbloom } 6138563Sroot error = ENOTTY; 61418651Sbloom } 61542895Smarc /* 61642895Smarc * If external processing and packet mode send ioctl packet. 61742895Smarc */ 61842895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 61942895Smarc switch(cmd) { 62042895Smarc case TIOCSETA: 62142895Smarc case TIOCSETAW: 62242895Smarc case TIOCSETAF: 623*52411Storek #ifdef COMPAT_43 62442895Smarc case TIOCSETP: 62542895Smarc case TIOCSETN: 626*52411Storek #endif 627*52411Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 62842895Smarc case TIOCSETC: 62942895Smarc case TIOCSLTC: 63042895Smarc case TIOCLBIS: 63142895Smarc case TIOCLBIC: 63242895Smarc case TIOCLSET: 63342895Smarc #endif 63442895Smarc pti->pt_send |= TIOCPKT_IOCTL; 63542895Smarc default: 63642895Smarc break; 63742895Smarc } 63842895Smarc } 63935811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 64035811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6416119Swnj if (pti->pt_flags & PF_NOSTOP) { 6426119Swnj if (stop) { 64325478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6446119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6456119Swnj pti->pt_flags &= ~PF_NOSTOP; 64618651Sbloom ptcwakeup(tp, FREAD); 6476119Swnj } 6486119Swnj } else { 64918651Sbloom if (!stop) { 6506119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6516119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6526119Swnj pti->pt_flags |= PF_NOSTOP; 65318651Sbloom ptcwakeup(tp, FREAD); 6546119Swnj } 6556119Swnj } 6568563Sroot return (error); 6572281Stoy } 6582313Stoy #endif 659