BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / tty_pty.c
index 5a0a0a6..eb9bf5f 100644 (file)
@@ -2,9 +2,35 @@
  * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
  * All rights reserved.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)tty_pty.c   7.18 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tty_pty.c   7.21 (Berkeley) 5/30/91
  */
 
 /*
  */
 
 /*
 #include "systm.h"
 #include "ioctl.h"
 #include "tty.h"
 #include "systm.h"
 #include "ioctl.h"
 #include "tty.h"
-#include "user.h"
 #include "conf.h"
 #include "file.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
 #include "vnode.h"
 #include "conf.h"
 #include "file.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
 #include "vnode.h"
-#include "tsleep.h"
 
 #if NPTY == 1
 #undef NPTY
 
 #if NPTY == 1
 #undef NPTY
@@ -44,31 +68,22 @@ struct      pt_ioctl {
        struct  proc *pt_selr, *pt_selw;
        u_char  pt_send;
        u_char  pt_ucntl;
        struct  proc *pt_selr, *pt_selw;
        u_char  pt_send;
        u_char  pt_ucntl;
-       struct  clist pt_ioc;
 } pt_ioctl[NPTY];
 int    npty = NPTY;            /* for pstat -t */
 
 } pt_ioctl[NPTY];
 int    npty = NPTY;            /* for pstat -t */
 
-int ptydebug = 0;
-
-#define        PF_RCOLL        0x0001
-#define        PF_WCOLL        0x0002
-#define        PF_NBIO         0x0004
-#define        PF_PKT          0x0008          /* packet mode */
-#define        PF_STOPPED      0x0010          /* user told stopped */
-#define        PF_REMOTE       0x0020          /* remote and flow controlled input */
-#define        PF_NOSTOP       0x0040
-#define        PF_UCNTL        0x0080          /* user control mode */
-#define        PF_TIOC         0x0100          /* transparent control mode */
-#define        PF_LIOC         0x0200          /* transparent control locked */
-#define        PF_WIOC         0x0400          /* waiting for PF_LIOC to clear */
-#define        PF_BLOCK        0x0800          /* block writes to slave */
-#define        PF_OWAIT        0x1000          /* waiting for PF_BLOCK to clear */
+#define        PF_RCOLL        0x01
+#define        PF_WCOLL        0x02
+#define        PF_PKT          0x08            /* packet mode */
+#define        PF_STOPPED      0x10            /* user told stopped */
+#define        PF_REMOTE       0x20            /* remote and flow controlled input */
+#define        PF_NOSTOP       0x40
+#define PF_UCNTL       0x80            /* user control mode */
 
 /*ARGSUSED*/
 
 /*ARGSUSED*/
-ptsopen(dev, flag)
+ptsopen(dev, flag, devtype, p)
        dev_t dev;
        dev_t dev;
+       struct proc *p;
 {
 {
-       struct proc *p = curproc;
        register struct tty *tp;
        int error;
 
        register struct tty *tp;
        int error;
 
@@ -93,7 +108,7 @@ ptsopen(dev, flag)
                tp->t_state |= TS_CARR_ON;
        while ((tp->t_state & TS_CARR_ON) == 0) {
                tp->t_state |= TS_WOPEN;
                tp->t_state |= TS_CARR_ON;
        while ((tp->t_state & TS_CARR_ON) == 0) {
                tp->t_state |= TS_WOPEN;
-               if (flag&FNDELAY)
+               if (flag&FNONBLOCK)
                        break;
                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
                    ttopen, 0))
                        break;
                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
                    ttopen, 0))
@@ -104,16 +119,17 @@ ptsopen(dev, flag)
        return (error);
 }
 
        return (error);
 }
 
-ptsclose(dev)
+ptsclose(dev, flag, mode, p)
        dev_t dev;
        dev_t dev;
+       int flag, mode;
+       struct proc *p;
 {
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
 {
        register struct tty *tp;
 
        tp = &pt_tty[minor(dev)];
-       (*linesw[tp->t_line].l_close)(tp);
+       (*linesw[tp->t_line].l_close)(tp, flag);
        ttyclose(tp);
        ptcwakeup(tp, FREAD|FWRITE);
        ttyclose(tp);
        ptcwakeup(tp, FREAD|FWRITE);
-       return (0);
 }
 
 ptsread(dev, uio, flag)
 }
 
 ptsread(dev, uio, flag)
@@ -171,17 +187,11 @@ ptswrite(dev, uio, flag)
        dev_t dev;
        struct uio *uio;
 {
        dev_t dev;
        struct uio *uio;
 {
-       register struct tty *tp = &pt_tty[minor(dev)];
-       register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
+       register struct tty *tp;
 
 
+       tp = &pt_tty[minor(dev)];
        if (tp->t_oproc == 0)
                return (EIO);
        if (tp->t_oproc == 0)
                return (EIO);
-
-       while (pti->pt_flags & PF_BLOCK) {
-               pti->pt_flags |= PF_OWAIT;
-               sleep((caddr_t)pti + 1, TTOPRI);
-       }
-
        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
 
        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
 
@@ -222,15 +232,19 @@ ptcwakeup(tp, flag)
                        pti->pt_selw = 0;
                        pti->pt_flags &= ~PF_WCOLL;
                }
                        pti->pt_selw = 0;
                        pti->pt_flags &= ~PF_WCOLL;
                }
-if (ptydebug) printf("WAKEUP c_cf %d\n", curproc->p_pid);
                wakeup((caddr_t)&tp->t_rawq.c_cf);
        }
 }
 
 /*ARGSUSED*/
                wakeup((caddr_t)&tp->t_rawq.c_cf);
        }
 }
 
 /*ARGSUSED*/
-ptcopen(dev, flag)
+#ifdef __STDC__
+ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
+#else
+ptcopen(dev, flag, devtype, p)
        dev_t dev;
        dev_t dev;
-       int flag;
+       int flag, devtype;
+       struct proc *p;
+#endif
 {
        register struct tty *tp;
        struct pt_ioctl *pti;
 {
        register struct tty *tp;
        struct pt_ioctl *pti;
@@ -260,7 +274,6 @@ ptcclose(dev)
        tp->t_state &= ~TS_CARR_ON;
        tp->t_oproc = 0;                /* mark closed */
        tp->t_session = 0;
        tp->t_state &= ~TS_CARR_ON;
        tp->t_oproc = 0;                /* mark closed */
        tp->t_session = 0;
-       return (0);
 }
 
 ptcread(dev, uio, flag)
 }
 
 ptcread(dev, uio, flag)
@@ -299,19 +312,6 @@ ptcread(dev, uio, flag)
                                pti->pt_ucntl = 0;
                                return (0);
                        }
                                pti->pt_ucntl = 0;
                                return (0);
                        }
-                       if (pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc) {
-                               if (uio->uio_resid < pti->pt_ioc.c_cc + 1)
-                                       return (E2BIG);
-                               error = ureadc(TIOCPKT_TIOC, uio);
-                               while (error == 0 && pti->pt_ioc.c_cc > 0) {
-                                       cc = q_to_b(&pti->pt_ioc, buf,
-                                           MIN(pti->pt_ioc.c_cc, BUFSIZ));
-                                       if (cc <= 0)    /* impossible? */
-                                               break;
-                                       error = uiomove(buf, cc, UIO_READ, uio);
-                               }
-                               return (error);
-                       }
                        if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
                                break;
                }
                        if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
                                break;
                }
@@ -323,7 +323,7 @@ ptcread(dev, uio, flag)
                    ttyin, 0))
                        return (error);
        }
                    ttyin, 0))
                        return (error);
        }
-       if (pti->pt_flags & (PF_PKT|PF_UCNTL|PF_TIOC))
+       if (pti->pt_flags & (PF_PKT|PF_UCNTL))
                error = ureadc(0, uio);
        while (uio->uio_resid > 0 && error == 0) {
                cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
                error = ureadc(0, uio);
        while (uio->uio_resid > 0 && error == 0) {
                cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
@@ -331,23 +331,18 @@ ptcread(dev, uio, flag)
                        break;
                error = uiomove(buf, cc, uio);
        }
                        break;
                error = uiomove(buf, cc, uio);
        }
-       if (tp->t_outq.c_cc <= TTLOWAT(tp) && !(pti->pt_flags & PF_BLOCK))
-               ptswake(tp);
-       return (error);
-}
-
-ptswake(tp)
-       register struct tty *tp;
-{
-       if (tp->t_state&TS_ASLEEP) {
-               tp->t_state &= ~TS_ASLEEP;
-               wakeup((caddr_t)&tp->t_outq);
-       }
-       if (tp->t_wsel) {
-               selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
-               tp->t_wsel = 0;
-               tp->t_state &= ~TS_WCOLL;
+       if (tp->t_outq.c_cc <= tp->t_lowat) {
+               if (tp->t_state&TS_ASLEEP) {
+                       tp->t_state &= ~TS_ASLEEP;
+                       wakeup((caddr_t)&tp->t_outq);
+               }
+               if (tp->t_wsel) {
+                       selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
+                       tp->t_wsel = 0;
+                       tp->t_state &= ~TS_WCOLL;
+               }
        }
        }
+       return (error);
 }
 
 ptsstop(tp, flush)
 }
 
 ptsstop(tp, flush)
@@ -373,14 +368,14 @@ ptsstop(tp, flush)
        ptcwakeup(tp, flag);
 }
 
        ptcwakeup(tp, flag);
 }
 
-ptcselect(dev, rw)
+ptcselect(dev, rw, p)
        dev_t dev;
        int rw;
        dev_t dev;
        int rw;
+       struct proc *p;
 {
 {
-       struct proc *curp = curproc;
        register struct tty *tp = &pt_tty[minor(dev)];
        struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
        register struct tty *tp = &pt_tty[minor(dev)];
        struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
-       struct proc *p;
+       struct proc *prev;
        int s;
 
        if ((tp->t_state&TS_CARR_ON) == 0)
        int s;
 
        if ((tp->t_state&TS_CARR_ON) == 0)
@@ -403,13 +398,12 @@ ptcselect(dev, rw)
        case 0:                                 /* exceptional */
                if ((tp->t_state&TS_ISOPEN) &&
                    (pti->pt_flags&PF_PKT && pti->pt_send ||
        case 0:                                 /* exceptional */
                if ((tp->t_state&TS_ISOPEN) &&
                    (pti->pt_flags&PF_PKT && pti->pt_send ||
-                    pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc ||
                     pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
                        return (1);
                     pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
                        return (1);
-               if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait)
+               if ((prev = pti->pt_selr) && prev->p_wchan == (caddr_t)&selwait)
                        pti->pt_flags |= PF_RCOLL;
                else
                        pti->pt_flags |= PF_RCOLL;
                else
-                       pti->pt_selr = curp;
+                       pti->pt_selr = p;
                break;
 
 
                break;
 
 
@@ -425,10 +419,10 @@ ptcselect(dev, rw)
                                    return (1);
                        }
                }
                                    return (1);
                        }
                }
-               if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait)
+               if ((prev = pti->pt_selw) && prev->p_wchan == (caddr_t)&selwait)
                        pti->pt_flags |= PF_WCOLL;
                else
                        pti->pt_flags |= PF_WCOLL;
                else
-                       pti->pt_selw = curp;
+                       pti->pt_selw = p;
                break;
 
        }
                break;
 
        }
@@ -558,14 +552,7 @@ ptyioctl(dev, cmd, data, flag)
                }
                return(0);
        } else
                }
                return(0);
        } else
-       if (cdevsw[major(dev)].d_open == ptcopen) {
-               if ((cmd & 0xffff) == (TIOCIOANS(0) & 0xffff)) {
-                       if (!(pti->pt_flags & PF_LIOC) || pti->pt_ioc.c_cc)
-                               return (EINVAL);
-                       (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
-                       wakeup((caddr_t)&pti->pt_ioc);
-                       return (0);
-               }
+       if (cdevsw[major(dev)].d_open == ptcopen)
                switch (cmd) {
 
                case TIOCGPGRP:
                switch (cmd) {
 
                case TIOCGPGRP:
@@ -594,30 +581,6 @@ ptyioctl(dev, cmd, data, flag)
                                pti->pt_flags &= ~PF_UCNTL;
                        return (0);
 
                                pti->pt_flags &= ~PF_UCNTL;
                        return (0);
 
-               case TIOCTIOC:
-                       if (*(int *)data) {
-                               if (pti->pt_flags & PF_UCNTL)
-                                       return (EINVAL);
-                               pti->pt_flags |= PF_TIOC;
-                       } else {
-                               pti->pt_flags &= ~(PF_TIOC|PF_LIOC|PF_WIOC);
-                               while (pti->pt_ioc.c_cc)
-                                       (void) getc(&pti->pt_ioc);
-                               wakeup((caddr_t)&pti->pt_ioc);
-                       }
-                       return (0);
-
-               case TIOCBLK:
-                       if (*(int *)data)
-                               pti->pt_flags |= PF_BLOCK;
-                       else {
-                               if (pti->pt_flags & PF_OWAIT)
-                                       wakeup((caddr_t)pti + 1);
-                               pti->pt_flags &= ~(PF_BLOCK|PF_OWAIT);
-                               ptswake(tp);
-                       }
-                       return (0);
-
                case TIOCREMOTE:
                        if (*(int *)data)
                                pti->pt_flags |= PF_REMOTE;
                case TIOCREMOTE:
                        if (*(int *)data)
                                pti->pt_flags |= PF_REMOTE;
@@ -626,10 +589,6 @@ ptyioctl(dev, cmd, data, flag)
                        ttyflush(tp, FREAD|FWRITE);
                        return (0);
 
                        ttyflush(tp, FREAD|FWRITE);
                        return (0);
 
-               case FIONREAD:
-                       *(int *)data = tp->t_outq.c_cc;
-                       return (0);
-
                case TIOCSETP:          
                case TIOCSETN:
                case TIOCSETD:
                case TIOCSETP:          
                case TIOCSETN:
                case TIOCSETD:
@@ -651,69 +610,6 @@ ptyioctl(dev, cmd, data, flag)
                                ttyinfo(tp);
                        return(0);
                }
                                ttyinfo(tp);
                        return(0);
                }
-       } else if (pti->pt_flags & PF_TIOC) {
-               while (pti->pt_flags & PF_LIOC) {
-                       pti->pt_flags |= PF_WIOC;
-                       switch (tsleep((caddr_t)&pti->pt_flags,TTIPRI-1,5*hz)) {
-                       case TS_OK:
-                               continue;
-                       case TS_SIG:
-                       case TS_TIME:
-                               return (EBUSY);
-                       }
-               }
-               pti->pt_flags |= PF_LIOC | PF_BLOCK;
-               while (pti->pt_ioc.c_cc)
-                       (void) getc(&pti->pt_ioc);
-               (void) b_to_q(&cmd, sizeof cmd, &pti->pt_ioc);
-               if (cmd & IOC_IN)
-                       (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc);
-               ptcwakeup(tp, FREAD);
-               switch (tsleep((caddr_t)&pti->pt_ioc, TTIPRI-1, 5*hz)) {
-               case TS_SIG:
-               case TS_TIME:
-                       while (pti->pt_ioc.c_cc)
-                               (void) getc(&pti->pt_ioc);
-                       if (pti->pt_flags & PF_WIOC)
-                               wakeup((caddr_t)&pti->pt_flags);
-                       if (pti->pt_flags & PF_OWAIT)
-                               wakeup((caddr_t)pti + 1);
-                       pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
-                       ptswake(tp);
-                       return (EBUSY);
-               case TS_OK:
-                       break;
-               }
-               if (pti->pt_ioc.c_cc == 0) {
-                       if (pti->pt_flags & PF_WIOC)
-                               wakeup((caddr_t)&pti->pt_flags);
-                       if (pti->pt_flags & PF_OWAIT)
-                               wakeup((caddr_t)pti + 1);
-                       pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
-                       ptswake(tp);
-                       goto doioctl;
-               }
-               if (q_to_b(&pti->pt_ioc, &error, sizeof error) != sizeof error)
-                       error = EINVAL;
-               if (error == 0 && cmd & IOC_OUT) {
-                       if (IOCPARM_LEN(cmd) != pti->pt_ioc.c_cc)
-                               error = EINVAL;
-                       else
-                               (void) q_to_b(&pti->pt_ioc, data,
-                                   pti->pt_ioc.c_cc);
-               }
-               while (pti->pt_ioc.c_cc)
-                       (void) getc(&pti->pt_ioc);
-               if (pti->pt_flags & PF_WIOC)
-                       wakeup((caddr_t)&pti->pt_flags);
-               if (pti->pt_flags & PF_OWAIT)
-                       wakeup((caddr_t)pti + 1);
-               pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT);
-               ptswake(tp);
-               return (error);
-       }
-
- doioctl:
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        if (error < 0)
                 error = ttioctl(tp, cmd, data, flag);
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        if (error < 0)
                 error = ttioctl(tp, cmd, data, flag);
@@ -722,22 +618,13 @@ ptyioctl(dev, cmd, data, flag)
         * pty's can't be switched to disciplines which overwrite
         * the queues.  We can't tell anything about the discipline
         * from here...
         * pty's can't be switched to disciplines which overwrite
         * the queues.  We can't tell anything about the discipline
         * from here...
-        *
-        * Nb: this is not really good enough, the line disc open routine
-        * may have done anything at all, no guarantees that close
-        * will fix it.  This also has the effect of losing the
-        * previous discipline, which an error on a TIOCSETD shouldn't
-        * do...  Sometime it should be done via an explicit check
-        * for TIOCSETD, then check to see what linesw[new_number].l_rint
-        * really is.
         */
        if (linesw[tp->t_line].l_rint != ttyinput) {
         */
        if (linesw[tp->t_line].l_rint != ttyinput) {
-               (*linesw[tp->t_line].l_close)(tp);
+               (*linesw[tp->t_line].l_close)(tp, flag);
                tp->t_line = TTYDISC;
                (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
                error = ENOTTY;
        }
                tp->t_line = TTYDISC;
                (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
                error = ENOTTY;
        }
-
        if (error < 0) {
                if (pti->pt_flags & PF_UCNTL &&
                    (cmd & ~0xff) == UIOCCMD(0)) {
        if (error < 0) {
                if (pti->pt_flags & PF_UCNTL &&
                    (cmd & ~0xff) == UIOCCMD(0)) {