123390Smckusick /* 263690Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363690Sbostic * The Regents of the University of California. All rights reserved. 423390Smckusick * 544446Sbostic * %sccs.include.redist.c% 638007Sbostic * 7*68171Scgd * @(#)tty_pty.c 8.3 (Berkeley) 01/09/95 823390Smckusick */ 92283Stoy 102281Stoy /* 112281Stoy * Pseudo-teletype Driver 122281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 132281Stoy */ 1459119Storek #include "pty.h" /* XXX */ 152314Stoy 1656517Sbostic #include <sys/param.h> 1756517Sbostic #include <sys/systm.h> 1856517Sbostic #include <sys/ioctl.h> 1956517Sbostic #include <sys/proc.h> 2056517Sbostic #include <sys/tty.h> 2156517Sbostic #include <sys/conf.h> 2256517Sbostic #include <sys/file.h> 2356517Sbostic #include <sys/uio.h> 2456517Sbostic #include <sys/kernel.h> 2556517Sbostic #include <sys/vnode.h> 266239Sroot 277475Ssam #if NPTY == 1 2818651Sbloom #undef NPTY 296239Sroot #define NPTY 32 /* crude XXX */ 307475Ssam #endif 312281Stoy 3216788Ssam #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 334484Swnj 342281Stoy /* 3518651Sbloom * pts == /dev/tty[pqrs]? 3618651Sbloom * ptc == /dev/pty[pqrs]? 372281Stoy */ 3859119Storek struct tty pt_tty[NPTY]; /* XXX */ 394484Swnj struct pt_ioctl { 405427Swnj int pt_flags; 4152523Smckusick struct selinfo pt_selr, pt_selw; 4218651Sbloom u_char pt_send; 4318651Sbloom u_char pt_ucntl; 4459119Storek } pt_ioctl[NPTY]; /* XXX */ 4518651Sbloom int npty = NPTY; /* for pstat -t */ 462281Stoy 4735811Smarc #define PF_PKT 0x08 /* packet mode */ 4835811Smarc #define PF_STOPPED 0x10 /* user told stopped */ 4935811Smarc #define PF_REMOTE 0x20 /* remote and flow controlled input */ 5035811Smarc #define PF_NOSTOP 0x40 5135811Smarc #define PF_UCNTL 0x80 /* user control mode */ 522281Stoy 5352411Storek void ptsstop __P((struct tty *, int)); 5452411Storek 5559119Storek /* 5659119Storek * Establish n (or default if n is 1) ptys in the system. 5759119Storek * 5859119Storek * XXX cdevsw & pstat require the array `pty[]' to be an array 5959119Storek */ 6059119Storek void 6159119Storek ptyattach(n) 6259119Storek int n; 6359119Storek { 6459119Storek #ifdef notyet 6559119Storek char *mem; 6659119Storek register u_long ntb; 6759119Storek #define DEFAULT_NPTY 32 6859119Storek 6959119Storek /* maybe should allow 0 => none? */ 7059119Storek if (n <= 1) 7159119Storek n = DEFAULT_NPTY; 7259119Storek ntb = n * sizeof(struct tty); 7359119Storek mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl), 7459119Storek M_DEVBUF, M_WAITOK); 7559119Storek pt_tty = (struct tty *)mem; 7659119Storek mem = (char *)ALIGN(mem + ntb); 7759119Storek pt_ioctl = (struct pt_ioctl *)mem; 7859119Storek npty = n; 7959119Storek #endif 8059119Storek } 8159119Storek 822281Stoy /*ARGSUSED*/ 8348442Skarels ptsopen(dev, flag, devtype, p) 845396Sroot dev_t dev; 8552411Storek int flag, devtype; 8648442Skarels struct proc *p; 874484Swnj { 882281Stoy register struct tty *tp; 8918651Sbloom int error; 902281Stoy 9159119Storek if (minor(dev) >= npty) 928563Sroot return (ENXIO); 932281Stoy tp = &pt_tty[minor(dev)]; 945408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 9544312Smarc tp->t_state |= TS_WOPEN; 962427Swnj ttychars(tp); /* Set up default chars */ 9735811Smarc tp->t_iflag = TTYDEF_IFLAG; 9835811Smarc tp->t_oflag = TTYDEF_OFLAG; 9935811Smarc tp->t_lflag = TTYDEF_LFLAG; 10035811Smarc tp->t_cflag = TTYDEF_CFLAG; 10135811Smarc tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 10235811Smarc ttsetwater(tp); /* would be done in xxparam() */ 10347548Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 1048563Sroot return (EBUSY); 1054484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 1065408Swnj tp->t_state |= TS_CARR_ON; 1075408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 1085408Swnj tp->t_state |= TS_WOPEN; 10949941Smckusick if (flag&FNONBLOCK) 11037590Smarc break; 11144312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 11240714Skarels ttopen, 0)) 11340714Skarels return (error); 1142281Stoy } 11552411Storek error = (*linesw[tp->t_line].l_open)(dev, tp); 11618651Sbloom ptcwakeup(tp, FREAD|FWRITE); 11718651Sbloom return (error); 1182281Stoy } 1192281Stoy 12049753Smarc ptsclose(dev, flag, mode, p) 1215396Sroot dev_t dev; 12249753Smarc int flag, mode; 12349753Smarc struct proc *p; 1245408Swnj { 1252281Stoy register struct tty *tp; 12653645Smarc int err; 1272281Stoy 1282281Stoy tp = &pt_tty[minor(dev)]; 12953645Smarc err = (*linesw[tp->t_line].l_close)(tp, flag); 13053645Smarc err |= ttyclose(tp); 13118651Sbloom ptcwakeup(tp, FREAD|FWRITE); 13253645Smarc return (err); 1332281Stoy } 1342281Stoy 13537590Smarc ptsread(dev, uio, flag) 1365396Sroot dev_t dev; 1377823Sroot struct uio *uio; 13852411Storek int flag; 1394484Swnj { 14047548Skarels struct proc *p = curproc; 1415894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1425894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1438521Sroot int error = 0; 1442281Stoy 1455894Swnj again: 1465894Swnj if (pti->pt_flags & PF_REMOTE) { 14747548Skarels while (isbackground(p, tp)) { 14847548Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 14947548Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 15047548Skarels p->p_pgrp->pg_jobc == 0 || 15164576Sbostic p->p_flag & P_PPWAIT) 1528521Sroot return (EIO); 15347548Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 15444312Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 15544312Smarc TTIPRI | PCATCH, ttybg, 0)) 15640714Skarels return (error); 1575408Swnj } 15818651Sbloom if (tp->t_canq.c_cc == 0) { 15937728Smckusick if (flag & IO_NDELAY) 1608521Sroot return (EWOULDBLOCK); 16144312Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 16240714Skarels TTIPRI | PCATCH, ttyin, 0)) 16340714Skarels return (error); 1645894Swnj goto again; 1655894Swnj } 16618651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 16718651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1688521Sroot error = EFAULT; 1697823Sroot break; 1707823Sroot } 17118651Sbloom if (tp->t_canq.c_cc == 1) 17218651Sbloom (void) getc(&tp->t_canq); 17318651Sbloom if (tp->t_canq.c_cc) 1748521Sroot return (error); 1755894Swnj } else 1765894Swnj if (tp->t_oproc) 17737590Smarc error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 17818651Sbloom ptcwakeup(tp, FWRITE); 1798521Sroot return (error); 1802281Stoy } 1812281Stoy 1825408Swnj /* 1835408Swnj * Write to pseudo-tty. 1845408Swnj * Wakeups of controlling tty will happen 1855408Swnj * indirectly, when tty driver calls ptsstart. 1865408Swnj */ 18737590Smarc ptswrite(dev, uio, flag) 1885396Sroot dev_t dev; 1897823Sroot struct uio *uio; 19052944Storek int flag; 1914484Swnj { 19235811Smarc register struct tty *tp; 1932281Stoy 19435811Smarc tp = &pt_tty[minor(dev)]; 1958521Sroot if (tp->t_oproc == 0) 1968521Sroot return (EIO); 19737590Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1982281Stoy } 1992281Stoy 2005408Swnj /* 2015408Swnj * Start output on pseudo-tty. 2025408Swnj * Wake up process selecting or sleeping for input from controlling tty. 2035408Swnj */ 20452411Storek void 2052281Stoy ptsstart(tp) 2064484Swnj struct tty *tp; 2074484Swnj { 2085574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 2094484Swnj 2105408Swnj if (tp->t_state & TS_TTSTOP) 2112281Stoy return; 2125574Swnj if (pti->pt_flags & PF_STOPPED) { 2135574Swnj pti->pt_flags &= ~PF_STOPPED; 2145574Swnj pti->pt_send = TIOCPKT_START; 2155574Swnj } 21618651Sbloom ptcwakeup(tp, FREAD); 2175430Swnj } 2185430Swnj 21918651Sbloom ptcwakeup(tp, flag) 2205430Swnj struct tty *tp; 22152411Storek int flag; 2225430Swnj { 2235430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 2245430Swnj 22518651Sbloom if (flag & FREAD) { 22652523Smckusick selwakeup(&pti->pt_selr); 22718651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 2284484Swnj } 22918651Sbloom if (flag & FWRITE) { 23052523Smckusick selwakeup(&pti->pt_selw); 23118651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 23218651Sbloom } 2332281Stoy } 2342281Stoy 2352281Stoy /*ARGSUSED*/ 23648442Skarels #ifdef __STDC__ 23748442Skarels ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 23848442Skarels #else 23948442Skarels ptcopen(dev, flag, devtype, p) 2404484Swnj dev_t dev; 24148442Skarels int flag, devtype; 24248442Skarels struct proc *p; 24348442Skarels #endif 2444484Swnj { 2452281Stoy register struct tty *tp; 2465427Swnj struct pt_ioctl *pti; 2472281Stoy 24859119Storek if (minor(dev) >= npty) 2498563Sroot return (ENXIO); 2502281Stoy tp = &pt_tty[minor(dev)]; 2518563Sroot if (tp->t_oproc) 2528563Sroot return (EIO); 2534484Swnj tp->t_oproc = ptsstart; 25452411Storek #ifdef sun4c 25552411Storek tp->t_stop = ptsstop; 25652411Storek #endif 25725390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 25842895Smarc tp->t_lflag &= ~EXTPROC; 2595427Swnj pti = &pt_ioctl[minor(dev)]; 2605427Swnj pti->pt_flags = 0; 2615427Swnj pti->pt_send = 0; 26218651Sbloom pti->pt_ucntl = 0; 2638563Sroot return (0); 2642281Stoy } 2652281Stoy 2662281Stoy ptcclose(dev) 2674484Swnj dev_t dev; 2684484Swnj { 2692281Stoy register struct tty *tp; 2702281Stoy 2712281Stoy tp = &pt_tty[minor(dev)]; 27225390Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 27332326Skarels tp->t_state &= ~TS_CARR_ON; 2744484Swnj tp->t_oproc = 0; /* mark closed */ 27539497Smarc tp->t_session = 0; 27653645Smarc return (0); 2772281Stoy } 2782281Stoy 27937590Smarc ptcread(dev, uio, flag) 2805427Swnj dev_t dev; 2817823Sroot struct uio *uio; 28252411Storek int flag; 2834484Swnj { 2848521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 28518651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 28616788Ssam char buf[BUFSIZ]; 28716788Ssam int error = 0, cc; 2882281Stoy 28918651Sbloom /* 29018651Sbloom * We want to block until the slave 29118651Sbloom * is open, and there's something to read; 29218651Sbloom * but if we lost the slave or we're NBIO, 29318651Sbloom * then return the appropriate error instead. 29418651Sbloom */ 29518651Sbloom for (;;) { 29618651Sbloom if (tp->t_state&TS_ISOPEN) { 29718651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 29826358Skarels error = ureadc((int)pti->pt_send, uio); 29918651Sbloom if (error) 30018651Sbloom return (error); 30142895Smarc if (pti->pt_send & TIOCPKT_IOCTL) { 30255060Spendry cc = min(uio->uio_resid, 30342895Smarc sizeof(tp->t_termios)); 30442895Smarc uiomove(&tp->t_termios, cc, uio); 30542895Smarc } 30618651Sbloom pti->pt_send = 0; 30718651Sbloom return (0); 30818651Sbloom } 30918651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 31026358Skarels error = ureadc((int)pti->pt_ucntl, uio); 31118651Sbloom if (error) 31218651Sbloom return (error); 31318651Sbloom pti->pt_ucntl = 0; 31418651Sbloom return (0); 31518651Sbloom } 31618651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 31718651Sbloom break; 3185427Swnj } 31916788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 32037590Smarc return (0); /* EOF */ 32137728Smckusick if (flag & IO_NDELAY) 3228521Sroot return (EWOULDBLOCK); 32340714Skarels if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 32440714Skarels ttyin, 0)) 32540714Skarels return (error); 3265411Swnj } 32735811Smarc if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 32818651Sbloom error = ureadc(0, uio); 32916788Ssam while (uio->uio_resid > 0 && error == 0) { 33055060Spendry cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 33116788Ssam if (cc <= 0) 3327823Sroot break; 33337728Smckusick error = uiomove(buf, cc, uio); 33416788Ssam } 33535811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 33635811Smarc if (tp->t_state&TS_ASLEEP) { 33735811Smarc tp->t_state &= ~TS_ASLEEP; 33835811Smarc wakeup((caddr_t)&tp->t_outq); 33935811Smarc } 34052523Smckusick selwakeup(&tp->t_wsel); 34135811Smarc } 3428521Sroot return (error); 3432281Stoy } 3442281Stoy 34552411Storek void 3465427Swnj ptsstop(tp, flush) 3475427Swnj register struct tty *tp; 3485427Swnj int flush; 3495427Swnj { 3505427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 35118651Sbloom int flag; 3525427Swnj 3535574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3545574Swnj if (flush == 0) { 3555574Swnj flush = TIOCPKT_STOP; 3565574Swnj pti->pt_flags |= PF_STOPPED; 35718651Sbloom } else 3585574Swnj pti->pt_flags &= ~PF_STOPPED; 3596119Swnj pti->pt_send |= flush; 36018651Sbloom /* change of perspective */ 36118651Sbloom flag = 0; 36218651Sbloom if (flush & FREAD) 36318651Sbloom flag |= FWRITE; 36418651Sbloom if (flush & FWRITE) 36518651Sbloom flag |= FREAD; 36623633Sbloom ptcwakeup(tp, flag); 3675427Swnj } 3685427Swnj 36948442Skarels ptcselect(dev, rw, p) 3704484Swnj dev_t dev; 3715408Swnj int rw; 37248442Skarels struct proc *p; 3734484Swnj { 3744484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3755894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3765430Swnj int s; 3774484Swnj 37818651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3794484Swnj return (1); 3805408Swnj switch (rw) { 3815408Swnj 3825408Swnj case FREAD: 38325945Skarels /* 38425945Skarels * Need to block timeouts (ttrstart). 38525945Skarels */ 38625945Skarels s = spltty(); 38718651Sbloom if ((tp->t_state&TS_ISOPEN) && 38825436Skarels tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 38925436Skarels splx(s); 39025436Skarels return (1); 39125436Skarels } 39225945Skarels splx(s); 39325436Skarels /* FALLTHROUGH */ 39425436Skarels 39525436Skarels case 0: /* exceptional */ 39625436Skarels if ((tp->t_state&TS_ISOPEN) && 39718651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 39825945Skarels pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 3995408Swnj return (1); 40052523Smckusick selrecord(p, &pti->pt_selr); 4015430Swnj break; 4025408Swnj 40325436Skarels 4045408Swnj case FWRITE: 40525945Skarels if (tp->t_state&TS_ISOPEN) { 40625945Skarels if (pti->pt_flags & PF_REMOTE) { 40725945Skarels if (tp->t_canq.c_cc == 0) 40825945Skarels return (1); 40925945Skarels } else { 41025945Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 41125945Skarels return (1); 41235811Smarc if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 41325945Skarels return (1); 41425945Skarels } 4155430Swnj } 41652523Smckusick selrecord(p, &pti->pt_selw); 4175430Swnj break; 41825436Skarels 4195408Swnj } 4205430Swnj return (0); 4215396Sroot } 4224484Swnj 42337590Smarc ptcwrite(dev, uio, flag) 4245408Swnj dev_t dev; 42518651Sbloom register struct uio *uio; 42652944Storek int flag; 4274484Swnj { 4288521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 42945570Skarels register u_char *cp; 43018651Sbloom register int cc = 0; 43145570Skarels u_char locbuf[BUFSIZ]; 4325408Swnj int cnt = 0; 4335894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 4348521Sroot int error = 0; 4352281Stoy 43618651Sbloom again: 43718651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 43818651Sbloom goto block; 43923633Sbloom if (pti->pt_flags & PF_REMOTE) { 44018651Sbloom if (tp->t_canq.c_cc) 44118651Sbloom goto block; 44245570Skarels while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 44323633Sbloom if (cc == 0) { 44445570Skarels cc = min(uio->uio_resid, BUFSIZ); 44545570Skarels cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 44623633Sbloom cp = locbuf; 44745570Skarels error = uiomove((caddr_t)cp, cc, uio); 44823633Sbloom if (error) 44923633Sbloom return (error); 45023633Sbloom /* check again for safety */ 45123633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 45223633Sbloom return (EIO); 45323633Sbloom } 45423633Sbloom if (cc) 45545570Skarels (void) b_to_q((char *)cp, cc, &tp->t_canq); 45623633Sbloom cc = 0; 4577823Sroot } 45818651Sbloom (void) putc(0, &tp->t_canq); 45918651Sbloom ttwakeup(tp); 46018651Sbloom wakeup((caddr_t)&tp->t_canq); 46118651Sbloom return (0); 46218651Sbloom } 46345570Skarels while (uio->uio_resid > 0) { 46418651Sbloom if (cc == 0) { 46545570Skarels cc = min(uio->uio_resid, BUFSIZ); 46618651Sbloom cp = locbuf; 46745570Skarels error = uiomove((caddr_t)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 } 48045570Skarels (*linesw[tp->t_line].l_rint)(*cp++, 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); 49445570Skarels if (flag & IO_NDELAY) { 49545570Skarels /* adjust for data copied in but not written */ 49618651Sbloom uio->uio_resid += cc; 49723633Sbloom if (cnt == 0) 49823633Sbloom return (EWOULDBLOCK); 49918651Sbloom return (0); 50018651Sbloom } 50140714Skarels if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 50245570Skarels ttyout, 0)) { 50345570Skarels /* adjust for data copied in but not written */ 50445570Skarels uio->uio_resid += cc; 50540714Skarels return (error); 50645570Skarels } 50718651Sbloom goto again; 5082281Stoy } 5092281Stoy 5102281Stoy /*ARGSUSED*/ 51152411Storek ptyioctl(dev, cmd, data, flag, p) 51252411Storek dev_t dev; 513*68171Scgd u_long cmd; 5147626Ssam caddr_t data; 51552411Storek int flag; 51652411Storek struct proc *p; 5174484Swnj { 5186119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 5196119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 52035811Smarc register u_char *cc = tp->t_cc; 52118651Sbloom int stop, error; 5222281Stoy 52325390Skarels /* 52425390Skarels * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 52525390Skarels * ttywflush(tp) will hang if there are characters in the outq. 52625390Skarels */ 52742895Smarc if (cmd == TIOCEXT) { 52842895Smarc /* 52942895Smarc * When the EXTPROC bit is being toggled, we need 53042895Smarc * to send an TIOCPKT_IOCTL if the packet driver 53142895Smarc * is turned on. 53242895Smarc */ 53342895Smarc if (*(int *)data) { 53442895Smarc if (pti->pt_flags & PF_PKT) { 53542895Smarc pti->pt_send |= TIOCPKT_IOCTL; 53663689Smckusick ptcwakeup(tp, FREAD); 53742895Smarc } 53842895Smarc tp->t_lflag |= EXTPROC; 53942895Smarc } else { 54042895Smarc if ((tp->t_state & EXTPROC) && 54142895Smarc (pti->pt_flags & PF_PKT)) { 54242895Smarc pti->pt_send |= TIOCPKT_IOCTL; 54363689Smckusick ptcwakeup(tp, FREAD); 54442895Smarc } 54542895Smarc tp->t_lflag &= ~EXTPROC; 54642895Smarc } 54742895Smarc return(0); 54842895Smarc } else 54935811Smarc if (cdevsw[major(dev)].d_open == ptcopen) 5507626Ssam switch (cmd) { 5517626Ssam 55244313Smarc case TIOCGPGRP: 55344313Smarc /* 55444313Smarc * We aviod calling ttioctl on the controller since, 55544313Smarc * in that case, tp must be the controlling terminal. 55644313Smarc */ 55744313Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 55844313Smarc return (0); 55944313Smarc 5607626Ssam case TIOCPKT: 56118651Sbloom if (*(int *)data) { 56218651Sbloom if (pti->pt_flags & PF_UCNTL) 56318651Sbloom return (EINVAL); 5645427Swnj pti->pt_flags |= PF_PKT; 56518651Sbloom } else 5665427Swnj pti->pt_flags &= ~PF_PKT; 5678563Sroot return (0); 5687626Ssam 56918651Sbloom case TIOCUCNTL: 57018651Sbloom if (*(int *)data) { 57118651Sbloom if (pti->pt_flags & PF_PKT) 57218651Sbloom return (EINVAL); 57318651Sbloom pti->pt_flags |= PF_UCNTL; 57418651Sbloom } else 57518651Sbloom pti->pt_flags &= ~PF_UCNTL; 57618651Sbloom return (0); 57718651Sbloom 5787626Ssam case TIOCREMOTE: 5797626Ssam if (*(int *)data) 5805894Swnj pti->pt_flags |= PF_REMOTE; 5815894Swnj else 5825894Swnj pti->pt_flags &= ~PF_REMOTE; 58312753Ssam ttyflush(tp, FREAD|FWRITE); 5848563Sroot return (0); 5857626Ssam 58652411Storek #ifdef COMPAT_43 58735811Smarc case TIOCSETP: 58825390Skarels case TIOCSETN: 58952411Storek #endif 59025390Skarels case TIOCSETD: 59135811Smarc case TIOCSETA: 59235811Smarc case TIOCSETAW: 59335811Smarc case TIOCSETAF: 59452411Storek ndflush(&tp->t_outq, tp->t_outq.c_cc); 5957626Ssam break; 59642895Smarc 59742895Smarc case TIOCSIG: 59842895Smarc if (*(unsigned int *)data >= NSIG) 59942895Smarc return(EINVAL); 60042895Smarc if ((tp->t_lflag&NOFLSH) == 0) 60142895Smarc ttyflush(tp, FREAD|FWRITE); 60245227Sborman pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 60345227Sborman if ((*(unsigned int *)data == SIGINFO) && 60445227Sborman ((tp->t_lflag&NOKERNINFO) == 0)) 60545227Sborman ttyinfo(tp); 60642895Smarc return(0); 6075411Swnj } 60852411Storek error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 60935811Smarc if (error < 0) 61035811Smarc error = ttioctl(tp, cmd, data, flag); 61118651Sbloom if (error < 0) { 61218651Sbloom if (pti->pt_flags & PF_UCNTL && 61328285Skarels (cmd & ~0xff) == UIOCCMD(0)) { 61418651Sbloom if (cmd & 0xff) { 61518651Sbloom pti->pt_ucntl = (u_char)cmd; 61618651Sbloom ptcwakeup(tp, FREAD); 61718651Sbloom } 61818651Sbloom return (0); 61918651Sbloom } 6208563Sroot error = ENOTTY; 62118651Sbloom } 62242895Smarc /* 62342895Smarc * If external processing and packet mode send ioctl packet. 62442895Smarc */ 62542895Smarc if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 62642895Smarc switch(cmd) { 62742895Smarc case TIOCSETA: 62842895Smarc case TIOCSETAW: 62942895Smarc case TIOCSETAF: 63052411Storek #ifdef COMPAT_43 63142895Smarc case TIOCSETP: 63242895Smarc case TIOCSETN: 63352411Storek #endif 63452411Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 63542895Smarc case TIOCSETC: 63642895Smarc case TIOCSLTC: 63742895Smarc case TIOCLBIS: 63842895Smarc case TIOCLBIC: 63942895Smarc case TIOCLSET: 64042895Smarc #endif 64142895Smarc pti->pt_send |= TIOCPKT_IOCTL; 64263689Smckusick ptcwakeup(tp, FREAD); 64342895Smarc default: 64442895Smarc break; 64542895Smarc } 64642895Smarc } 64735811Smarc stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 64835811Smarc && CCEQ(cc[VSTART], CTRL('q')); 6496119Swnj if (pti->pt_flags & PF_NOSTOP) { 6506119Swnj if (stop) { 65125478Skarels pti->pt_send &= ~TIOCPKT_NOSTOP; 6526119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 6536119Swnj pti->pt_flags &= ~PF_NOSTOP; 65418651Sbloom ptcwakeup(tp, FREAD); 6556119Swnj } 6566119Swnj } else { 65718651Sbloom if (!stop) { 6586119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 6596119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 6606119Swnj pti->pt_flags |= PF_NOSTOP; 66118651Sbloom ptcwakeup(tp, FREAD); 6626119Swnj } 6636119Swnj } 6648563Sroot return (error); 6652281Stoy } 666