BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / tty_pty.c
index 3fffdc8..eb9bf5f 100644 (file)
@@ -2,22 +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.
  *
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement:  This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software.  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.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 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.15 (Berkeley) 6/28/90
+ * 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
  */
 
 /*
  */
 
 /*
@@ -31,7 +44,6 @@
 #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 "conf.h"
 #include "file.h"
 #include "proc.h"
@@ -59,11 +71,8 @@ struct       pt_ioctl {
 } pt_ioctl[NPTY];
 int    npty = NPTY;            /* for pstat -t */
 
 } pt_ioctl[NPTY];
 int    npty = NPTY;            /* for pstat -t */
 
-int ptydebug = 0;
-
 #define        PF_RCOLL        0x01
 #define        PF_WCOLL        0x02
 #define        PF_RCOLL        0x01
 #define        PF_WCOLL        0x02
-#define        PF_NBIO         0x04
 #define        PF_PKT          0x08            /* packet mode */
 #define        PF_STOPPED      0x10            /* user told stopped */
 #define        PF_REMOTE       0x20            /* remote and flow controlled input */
 #define        PF_PKT          0x08            /* packet mode */
 #define        PF_STOPPED      0x10            /* user told stopped */
 #define        PF_REMOTE       0x20            /* remote and flow controlled input */
@@ -71,8 +80,9 @@ int ptydebug = 0;
 #define PF_UCNTL       0x80            /* user control mode */
 
 /*ARGSUSED*/
 #define PF_UCNTL       0x80            /* user control mode */
 
 /*ARGSUSED*/
-ptsopen(dev, flag)
+ptsopen(dev, flag, devtype, p)
        dev_t dev;
        dev_t dev;
+       struct proc *p;
 {
        register struct tty *tp;
        int error;
 {
        register struct tty *tp;
        int error;
@@ -92,13 +102,13 @@ ptsopen(dev, flag)
                tp->t_cflag = TTYDEF_CFLAG;
                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                ttsetwater(tp);         /* would be done in xxparam() */
                tp->t_cflag = TTYDEF_CFLAG;
                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                ttsetwater(tp);         /* would be done in xxparam() */
-       } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
+       } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
                return (EBUSY);
        if (tp->t_oproc)                        /* Ctrlr still around. */
                tp->t_state |= TS_CARR_ON;
        while ((tp->t_state & TS_CARR_ON) == 0) {
                tp->t_state |= TS_WOPEN;
                return (EBUSY);
        if (tp->t_oproc)                        /* Ctrlr still around. */
                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))
@@ -109,13 +119,15 @@ 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);
 }
@@ -124,19 +136,20 @@ ptsread(dev, uio, flag)
        dev_t dev;
        struct uio *uio;
 {
        dev_t dev;
        struct uio *uio;
 {
+       struct proc *p = curproc;
        register struct tty *tp = &pt_tty[minor(dev)];
        register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
        int error = 0;
 
 again:
        if (pti->pt_flags & PF_REMOTE) {
        register struct tty *tp = &pt_tty[minor(dev)];
        register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
        int error = 0;
 
 again:
        if (pti->pt_flags & PF_REMOTE) {
-               while (isbackground(u.u_procp, tp)) {
-                       if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
-                           (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
-                           u.u_procp->p_pgrp->pg_jobc == 0 ||
-                           u.u_procp->p_flag&SVFORK)
+               while (isbackground(p, tp)) {
+                       if ((p->p_sigignore & sigmask(SIGTTIN)) ||
+                           (p->p_sigmask & sigmask(SIGTTIN)) ||
+                           p->p_pgrp->pg_jobc == 0 ||
+                           p->p_flag&SPPWAIT)
                                return (EIO);
                                return (EIO);
-                       pgsignal(u.u_procp->p_pgrp, SIGTTIN, 1);
+                       pgsignal(p->p_pgrp, SIGTTIN, 1);
                        if (error = ttysleep(tp, (caddr_t)&lbolt, 
                            TTIPRI | PCATCH, ttybg, 0))
                                return (error);
                        if (error = ttysleep(tp, (caddr_t)&lbolt, 
                            TTIPRI | PCATCH, ttybg, 0))
                                return (error);
@@ -219,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", u.u_procp->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;
@@ -351,13 +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;
 {
        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)
@@ -382,10 +400,10 @@ ptcselect(dev, rw)
                    (pti->pt_flags&PF_PKT && pti->pt_send ||
                     pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
                        return (1);
                    (pti->pt_flags&PF_PKT && pti->pt_send ||
                     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 = u.u_procp;
+                       pti->pt_selr = p;
                break;
 
 
                break;
 
 
@@ -401,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 = u.u_procp;
+                       pti->pt_selw = p;
                break;
 
        }
                break;
 
        }
@@ -416,10 +434,9 @@ ptcwrite(dev, uio, flag)
        register struct uio *uio;
 {
        register struct tty *tp = &pt_tty[minor(dev)];
        register struct uio *uio;
 {
        register struct tty *tp = &pt_tty[minor(dev)];
-       register struct iovec *iov;
-       register char *cp;
+       register u_char *cp;
        register int cc = 0;
        register int cc = 0;
-       char locbuf[BUFSIZ];
+       u_char locbuf[BUFSIZ];
        int cnt = 0;
        struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
        int error = 0;
        int cnt = 0;
        struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
        int error = 0;
@@ -430,18 +447,12 @@ again:
        if (pti->pt_flags & PF_REMOTE) {
                if (tp->t_canq.c_cc)
                        goto block;
        if (pti->pt_flags & PF_REMOTE) {
                if (tp->t_canq.c_cc)
                        goto block;
-               while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
-                       iov = uio->uio_iov;
-                       if (iov->iov_len == 0) {
-                               uio->uio_iovcnt--;      
-                               uio->uio_iov++;
-                               continue;
-                       }
+               while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
                        if (cc == 0) {
                        if (cc == 0) {
-                               cc = MIN(iov->iov_len, BUFSIZ);
-                               cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc);
+                               cc = min(uio->uio_resid, BUFSIZ);
+                               cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
                                cp = locbuf;
                                cp = locbuf;
-                               error = uiomove(cp, cc, uio);
+                               error = uiomove((caddr_t)cp, cc, uio);
                                if (error)
                                        return (error);
                                /* check again for safety */
                                if (error)
                                        return (error);
                                /* check again for safety */
@@ -449,7 +460,7 @@ again:
                                        return (EIO);
                        }
                        if (cc)
                                        return (EIO);
                        }
                        if (cc)
-                               (void) b_to_q(cp, cc, &tp->t_canq);
+                               (void) b_to_q((char *)cp, cc, &tp->t_canq);
                        cc = 0;
                }
                (void) putc(0, &tp->t_canq);
                        cc = 0;
                }
                (void) putc(0, &tp->t_canq);
@@ -457,17 +468,11 @@ again:
                wakeup((caddr_t)&tp->t_canq);
                return (0);
        }
                wakeup((caddr_t)&tp->t_canq);
                return (0);
        }
-       while (uio->uio_iovcnt > 0) {
-               iov = uio->uio_iov;
+       while (uio->uio_resid > 0) {
                if (cc == 0) {
                if (cc == 0) {
-                       if (iov->iov_len == 0) {
-                               uio->uio_iovcnt--;      
-                               uio->uio_iov++;
-                               continue;
-                       }
-                       cc = MIN(iov->iov_len, BUFSIZ);
+                       cc = min(uio->uio_resid, BUFSIZ);
                        cp = locbuf;
                        cp = locbuf;
-                       error = uiomove(cp, cc, uio);
+                       error = uiomove((caddr_t)cp, cc, uio);
                        if (error)
                                return (error);
                        /* check again for safety */
                        if (error)
                                return (error);
                        /* check again for safety */
@@ -480,7 +485,7 @@ again:
                                wakeup((caddr_t)&tp->t_rawq);
                                goto block;
                        }
                                wakeup((caddr_t)&tp->t_rawq);
                                goto block;
                        }
-                       (*linesw[tp->t_line].l_rint)(*cp++&0377, tp);
+                       (*linesw[tp->t_line].l_rint)(*cp++, tp);
                        cnt++;
                        cc--;
                }
                        cnt++;
                        cc--;
                }
@@ -494,18 +499,19 @@ block:
         */
        if ((tp->t_state&TS_CARR_ON) == 0)
                return (EIO);
         */
        if ((tp->t_state&TS_CARR_ON) == 0)
                return (EIO);
-       if ((pti->pt_flags & PF_NBIO) || (flag & IO_NDELAY)) {
-               iov->iov_base -= cc;
-               iov->iov_len += cc;
+       if (flag & IO_NDELAY) {
+               /* adjust for data copied in but not written */
                uio->uio_resid += cc;
                uio->uio_resid += cc;
-               uio->uio_offset -= cc;
                if (cnt == 0)
                        return (EWOULDBLOCK);
                return (0);
        }
        if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
                if (cnt == 0)
                        return (EWOULDBLOCK);
                return (0);
        }
        if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
-           ttyout, 0))
+           ttyout, 0)) {
+               /* adjust for data copied in but not written */
+               uio->uio_resid += cc;
                return (error);
                return (error);
+       }
        goto again;
 }
 
        goto again;
 }
 
@@ -583,22 +589,12 @@ ptyioctl(dev, cmd, data, flag)
                        ttyflush(tp, FREAD|FWRITE);
                        return (0);
 
                        ttyflush(tp, FREAD|FWRITE);
                        return (0);
 
-               case FIONBIO:
-                       if (*(int *)data)
-                               pti->pt_flags |= PF_NBIO;
-                       else
-                               pti->pt_flags &= ~PF_NBIO;
-                       return (0);
-
                case TIOCSETP:          
                case TIOCSETN:
                case TIOCSETD:
                case TIOCSETA:
                case TIOCSETAW:
                case TIOCSETAF:
                case TIOCSETP:          
                case TIOCSETN:
                case TIOCSETD:
                case TIOCSETA:
                case TIOCSETAW:
                case TIOCSETAF:
-               case JUNK_TIOCSETAS:
-               case JUNK_TIOCSETAWS:
-               case JUNK_TIOCSETAFS:
                        while (getc(&tp->t_outq) >= 0)
                                ;
                        break;
                        while (getc(&tp->t_outq) >= 0)
                                ;
                        break;
@@ -608,7 +604,10 @@ ptyioctl(dev, cmd, data, flag)
                                return(EINVAL);
                        if ((tp->t_lflag&NOFLSH) == 0)
                                ttyflush(tp, FREAD|FWRITE);
                                return(EINVAL);
                        if ((tp->t_lflag&NOFLSH) == 0)
                                ttyflush(tp, FREAD|FWRITE);
-                       pgsignal(tp->t_pgrp, *(unsigned int *)data);
+                       pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
+                       if ((*(unsigned int *)data == SIGINFO) &&
+                           ((tp->t_lflag&NOKERNINFO) == 0))
+                               ttyinfo(tp);
                        return(0);
                }
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
                        return(0);
                }
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
@@ -621,8 +620,8 @@ ptyioctl(dev, cmd, data, flag)
         * from here...
         */
        if (linesw[tp->t_line].l_rint != ttyinput) {
         * from here...
         */
        if (linesw[tp->t_line].l_rint != ttyinput) {
-               (*linesw[tp->t_line].l_close)(tp);
-               tp->t_line = 0;
+               (*linesw[tp->t_line].l_close)(tp, flag);
+               tp->t_line = TTYDISC;
                (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
                error = ENOTTY;
        }
                (void)(*linesw[tp->t_line].l_open)(dev, tp, flag);
                error = ENOTTY;
        }
@@ -645,9 +644,6 @@ ptyioctl(dev, cmd, data, flag)
                case TIOCSETA:
                case TIOCSETAW:
                case TIOCSETAF:
                case TIOCSETA:
                case TIOCSETAW:
                case TIOCSETAF:
-               case JUNK_TIOCSETAS:
-               case JUNK_TIOCSETAWS:
-               case JUNK_TIOCSETAFS:
                case TIOCSETP:
                case TIOCSETN:
 #ifdef COMPAT_43
                case TIOCSETP:
                case TIOCSETN:
 #ifdef COMPAT_43