root/kern/tty_pty.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ptydevname
  2. ptyarralloc
  3. check_pty
  4. ptyattach
  5. ptsopen
  6. ptsclose
  7. ptsread
  8. ptswrite
  9. ptsstart
  10. ptsstop
  11. ptcwakeup
  12. ptcopen
  13. ptcclose
  14. ptcread
  15. ptcwrite
  16. ptcpoll
  17. filt_ptcrdetach
  18. filt_ptcread
  19. filt_ptcwdetach
  20. filt_ptcwrite
  21. ptckqfilter
  22. ptytty
  23. ptyioctl
  24. sysctl_pty
  25. pty_isfree_locked
  26. pty_isfree
  27. pty_getfree
  28. ptm_vn_open
  29. ptmattach
  30. ptmopen
  31. ptmclose
  32. ptmread
  33. ptmwrite
  34. ptmioctl
  35. ptmpoll

    1 /*      $OpenBSD: tty_pty.c,v 1.34 2007/05/29 00:17:32 thib Exp $       */
    2 /*      $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $     */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)tty_pty.c   8.4 (Berkeley) 2/20/95
   33  */
   34 
   35 /*
   36  * Pseudo-teletype Driver
   37  * (Actually two drivers, requiring two entries in 'cdevsw')
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/namei.h>
   43 #include <sys/mount.h>
   44 #include <sys/ioctl.h>
   45 #include <sys/proc.h>
   46 #include <sys/tty.h>
   47 #include <sys/file.h>
   48 #include <sys/filedesc.h>
   49 #include <sys/uio.h>
   50 #include <sys/kernel.h>
   51 #include <sys/malloc.h>
   52 #include <sys/vnode.h>
   53 #include <sys/signalvar.h>
   54 #include <sys/uio.h>
   55 #include <sys/conf.h>
   56 #include <sys/stat.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/poll.h>
   59 #include <sys/rwlock.h>
   60 
   61 #define BUFSIZ 100              /* Chunk size iomoved to/from user */
   62 
   63 /*
   64  * pts == /dev/tty[p-zP-T][0-9a-zA-Z]
   65  * ptc == /dev/pty[p-zP-T][0-9a-zA-Z]
   66  */
   67 
   68 /* XXX this needs to come from somewhere sane, and work with MAKEDEV */
   69 #define TTY_LETTERS "pqrstuvwxyzPQRST"
   70 #define TTY_SUFFIX "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
   71 
   72 static int pts_major;
   73 
   74 struct  pt_softc {
   75         struct  tty *pt_tty;
   76         int     pt_flags;
   77         struct  selinfo pt_selr, pt_selw;
   78         u_char  pt_send;
   79         u_char  pt_ucntl;
   80         char    pty_pn[11];
   81         char    pty_sn[11];
   82 };
   83 
   84 #define NPTY_MIN                8       /* number of initial ptys */
   85 #define NPTY_MAX                992     /* maximum number of ptys supported */
   86 
   87 static struct pt_softc **pt_softc = NULL;       /* pty array */
   88 static int npty = 0;                            /* size of pty array */
   89 static int maxptys = NPTY_MAX;                  /* maximum number of ptys */
   90 /* for pty array */
   91 struct rwlock pt_softc_lock = RWLOCK_INITIALIZER("ptarrlk");
   92 
   93 #define PF_PKT          0x08            /* packet mode */
   94 #define PF_STOPPED      0x10            /* user told stopped */
   95 #define PF_REMOTE       0x20            /* remote and flow controlled input */
   96 #define PF_NOSTOP       0x40
   97 #define PF_UCNTL        0x80            /* user control mode */
   98 
   99 void    ptyattach(int);
  100 void    ptcwakeup(struct tty *, int);
  101 struct tty *ptytty(dev_t);
  102 void    ptsstart(struct tty *);
  103 int     sysctl_pty(int *, u_int, void *, size_t *, void *, size_t);
  104 
  105 void    filt_ptcrdetach(struct knote *);
  106 int     filt_ptcread(struct knote *, long);
  107 void    filt_ptcwdetach(struct knote *);
  108 int     filt_ptcwrite(struct knote *, long);
  109 
  110 static struct pt_softc **ptyarralloc(int);
  111 static int check_pty(int);
  112 
  113 static gid_t tty_gid = TTY_GID;
  114 
  115 void    ptydevname(int, struct pt_softc *);
  116 dev_t   pty_getfree(void);
  117 
  118 void    ptmattach(int);
  119 int     ptmopen(dev_t, int, int, struct proc *);
  120 int     ptmclose(dev_t, int, int, struct proc *);
  121 int     ptmread(dev_t, struct uio *, int);
  122 int     ptmwrite(dev_t, struct uio *, int);
  123 int     ptmwrite(dev_t, struct uio *, int);
  124 int     ptmioctl(dev_t, u_long, caddr_t, int, struct proc *p);
  125 int     ptmpoll(dev_t, int, struct proc *p);
  126 static int ptm_vn_open(struct nameidata *);
  127 
  128 void
  129 ptydevname(int minor, struct pt_softc *pti)
  130 {
  131         char buf[11] = "/dev/XtyXX";
  132         int i, j;
  133 
  134         i = minor / (sizeof(TTY_SUFFIX) - 1);
  135         j = minor % (sizeof(TTY_SUFFIX) - 1);
  136         if (i >= sizeof(TTY_LETTERS) - 1) {
  137                 pti->pty_pn[0] = '\0';
  138                 pti->pty_sn[0] = '\0';
  139                 return;
  140         }
  141         buf[5] = 'p';
  142         buf[8] = TTY_LETTERS[i];
  143         buf[9] = TTY_SUFFIX[j];
  144         memcpy(pti->pty_pn, buf, sizeof(buf));
  145         buf[5] = 't';
  146         memcpy(pti->pty_sn, buf, sizeof(buf));
  147 }
  148 
  149 /*
  150  * Allocate and zero array of nelem elements.
  151  */
  152 struct pt_softc **
  153 ptyarralloc(int nelem)
  154 {
  155         struct pt_softc **pt;
  156 
  157         pt = malloc(nelem * sizeof(struct pt_softc *), M_DEVBUF, M_WAITOK);
  158         bzero(pt, nelem * sizeof(struct pt_softc *));
  159         return pt;
  160 }
  161 
  162 /*
  163  * Check if the minor is correct and ensure necessary structures
  164  * are properly allocated.
  165  */
  166 int
  167 check_pty(int minor)
  168 {
  169         struct pt_softc *pti;
  170 
  171         rw_enter_write(&pt_softc_lock);
  172         if (minor >= npty) {
  173                 struct pt_softc **newpt;
  174                 int newnpty;
  175 
  176                 /* check if the requested pty can be granted */
  177                 if (minor >= maxptys)
  178                         goto limit_reached;
  179 
  180                 /* grow pty array by powers of two, up to maxptys */
  181                 for (newnpty = npty; newnpty <= minor; newnpty *= 2)
  182                         ;
  183 
  184                 if (newnpty > maxptys)
  185                         newnpty = maxptys;
  186                 newpt = ptyarralloc(newnpty);
  187 
  188                 if (maxptys == npty) {
  189                         goto limit_reached;
  190                 }
  191 
  192                 memcpy(newpt, pt_softc, npty * sizeof(struct pt_softc *));
  193                 free(pt_softc, M_DEVBUF);
  194                 pt_softc = newpt;
  195                 npty = newnpty;
  196         }
  197 
  198         /*
  199          * If the entry is not yet allocated, allocate one.
  200          */
  201         if (!pt_softc[minor]) {
  202                 MALLOC(pti, struct pt_softc *, sizeof(struct pt_softc),
  203                     M_DEVBUF, M_WAITOK);
  204                 bzero(pti, sizeof(struct pt_softc));
  205                 pti->pt_tty = ttymalloc();
  206                 ptydevname(minor, pti);
  207                 pt_softc[minor] = pti;
  208         }
  209         rw_exit_write(&pt_softc_lock);
  210         return (0);
  211 limit_reached:
  212         rw_exit_write(&pt_softc_lock);
  213         tablefull("pty");
  214         return (ENXIO);
  215 }
  216 
  217 /*
  218  * Establish n (or default if n is 1) ptys in the system.
  219  */
  220 void
  221 ptyattach(int n)
  222 {
  223         /* maybe should allow 0 => none? */
  224         if (n <= 1)
  225                 n = NPTY_MIN;
  226         pt_softc = ptyarralloc(n);
  227         npty = n;
  228 
  229         /*
  230          * If we have pty, we need ptm too.
  231          */
  232         ptmattach(1);
  233 }
  234 
  235 /*ARGSUSED*/
  236 int
  237 ptsopen(dev_t dev, int flag, int devtype, struct proc *p)
  238 {
  239         struct pt_softc *pti;
  240         struct tty *tp;
  241         int error;
  242 
  243         if ((error = check_pty(minor(dev))))
  244                 return (error);
  245 
  246         pti = pt_softc[minor(dev)];
  247         if (!pti->pt_tty) {
  248                 tp = pti->pt_tty = ttymalloc();
  249         } else
  250                 tp = pti->pt_tty;
  251         if ((tp->t_state & TS_ISOPEN) == 0) {
  252                 tp->t_state |= TS_WOPEN;
  253                 ttychars(tp);           /* Set up default chars */
  254                 tp->t_iflag = TTYDEF_IFLAG;
  255                 tp->t_oflag = TTYDEF_OFLAG;
  256                 tp->t_lflag = TTYDEF_LFLAG;
  257                 tp->t_cflag = TTYDEF_CFLAG;
  258                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  259                 ttsetwater(tp);         /* would be done in xxparam() */
  260         } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
  261                 return (EBUSY);
  262         if (tp->t_oproc)                        /* Ctrlr still around. */
  263                 tp->t_state |= TS_CARR_ON;
  264         while ((tp->t_state & TS_CARR_ON) == 0) {
  265                 tp->t_state |= TS_WOPEN;
  266                 if (flag&FNONBLOCK)
  267                         break;
  268                 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
  269                                  ttopen, 0);
  270                 if (error)
  271                         return (error);
  272         }
  273         error = (*linesw[tp->t_line].l_open)(dev, tp);
  274         ptcwakeup(tp, FREAD|FWRITE);
  275         return (error);
  276 }
  277 
  278 int
  279 ptsclose(dev_t dev, int flag, int mode, struct proc *p)
  280 {
  281         struct pt_softc *pti = pt_softc[minor(dev)];
  282         struct tty *tp = pti->pt_tty;
  283         int error;
  284 
  285         error = (*linesw[tp->t_line].l_close)(tp, flag);
  286         error |= ttyclose(tp);
  287         ptcwakeup(tp, FREAD|FWRITE);
  288         return (error);
  289 }
  290 
  291 int
  292 ptsread(dev_t dev, struct uio *uio, int flag)
  293 {
  294         struct proc *p = curproc;
  295         struct pt_softc *pti = pt_softc[minor(dev)];
  296         struct tty *tp = pti->pt_tty;
  297         int error = 0;
  298 
  299 again:
  300         if (pti->pt_flags & PF_REMOTE) {
  301                 while (isbackground(p, tp)) {
  302                         if ((p->p_sigignore & sigmask(SIGTTIN)) ||
  303                             (p->p_sigmask & sigmask(SIGTTIN)) ||
  304                             p->p_pgrp->pg_jobc == 0 ||
  305                             p->p_flag & P_PPWAIT)
  306                                 return (EIO);
  307                         pgsignal(p->p_pgrp, SIGTTIN, 1);
  308                         error = ttysleep(tp, &lbolt,
  309                             TTIPRI | PCATCH, ttybg, 0);
  310                         if (error)
  311                                 return (error);
  312                 }
  313                 if (tp->t_canq.c_cc == 0) {
  314                         if (flag & IO_NDELAY)
  315                                 return (EWOULDBLOCK);
  316                         error = ttysleep(tp, &tp->t_canq,
  317                             TTIPRI | PCATCH, ttyin, 0);
  318                         if (error)
  319                                 return (error);
  320                         goto again;
  321                 }
  322                 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
  323                         if (ureadc(getc(&tp->t_canq), uio) < 0) {
  324                                 error = EFAULT;
  325                                 break;
  326                         }
  327                 if (tp->t_canq.c_cc == 1)
  328                         (void) getc(&tp->t_canq);
  329                 if (tp->t_canq.c_cc)
  330                         return (error);
  331         } else
  332                 if (tp->t_oproc)
  333                         error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
  334         ptcwakeup(tp, FWRITE);
  335         return (error);
  336 }
  337 
  338 /*
  339  * Write to pseudo-tty.
  340  * Wakeups of controlling tty will happen
  341  * indirectly, when tty driver calls ptsstart.
  342  */
  343 int
  344 ptswrite(dev_t dev, struct uio *uio, int flag)
  345 {
  346         struct pt_softc *pti = pt_softc[minor(dev)];
  347         struct tty *tp = pti->pt_tty;
  348 
  349         if (tp->t_oproc == 0)
  350                 return (EIO);
  351         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
  352 }
  353 
  354 /*
  355  * Start output on pseudo-tty.
  356  * Wake up process polling or sleeping for input from controlling tty.
  357  */
  358 void
  359 ptsstart(struct tty *tp)
  360 {
  361         struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
  362 
  363         if (tp->t_state & TS_TTSTOP)
  364                 return;
  365         if (pti->pt_flags & PF_STOPPED) {
  366                 pti->pt_flags &= ~PF_STOPPED;
  367                 pti->pt_send = TIOCPKT_START;
  368         }
  369         ptcwakeup(tp, FREAD);
  370 }
  371 
  372 int
  373 ptsstop(struct tty *tp, int flush)
  374 {
  375         struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
  376         int flag;
  377 
  378         /* note: FLUSHREAD and FLUSHWRITE already ok */
  379         if (flush == 0) {
  380                 flush = TIOCPKT_STOP;
  381                 pti->pt_flags |= PF_STOPPED;
  382         } else
  383                 pti->pt_flags &= ~PF_STOPPED;
  384         pti->pt_send |= flush;
  385         /* change of perspective */
  386         flag = 0;
  387         if (flush & FREAD)
  388                 flag |= FWRITE;
  389         if (flush & FWRITE)
  390                 flag |= FREAD;
  391         ptcwakeup(tp, flag);
  392         return 0;
  393 }
  394 
  395 void
  396 ptcwakeup(struct tty *tp, int flag)
  397 {
  398         struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
  399 
  400         if (flag & FREAD) {
  401                 selwakeup(&pti->pt_selr);
  402                 wakeup(&tp->t_outq.c_cf);
  403                 KNOTE(&pti->pt_selr.si_note, 0);
  404         }
  405         if (flag & FWRITE) {
  406                 selwakeup(&pti->pt_selw);
  407                 wakeup(&tp->t_rawq.c_cf);
  408                 KNOTE(&pti->pt_selw.si_note, 0);
  409         }
  410 }
  411 
  412 int ptcopen(dev_t, int, int, struct proc *);
  413 
  414 /*ARGSUSED*/
  415 int
  416 ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
  417 {
  418         struct pt_softc *pti;
  419         struct tty *tp;
  420         int error;
  421 
  422         if ((error = check_pty(minor(dev))))
  423                 return (error);
  424 
  425         pti = pt_softc[minor(dev)];
  426         if (!pti->pt_tty) {
  427                 tp = pti->pt_tty = ttymalloc();
  428         } else
  429                 tp = pti->pt_tty;
  430         if (tp->t_oproc)
  431                 return (EIO);
  432         tp->t_oproc = ptsstart;
  433         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  434         tp->t_lflag &= ~EXTPROC;
  435         pti->pt_flags = 0;
  436         pti->pt_send = 0;
  437         pti->pt_ucntl = 0;
  438         return (0);
  439 }
  440 
  441 /*ARGSUSED*/
  442 int
  443 ptcclose(dev_t dev, int flag, int devtype, struct proc *p)
  444 {
  445         struct pt_softc *pti = pt_softc[minor(dev)];
  446         struct tty *tp = pti->pt_tty;
  447 
  448         (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  449         tp->t_state &= ~TS_CARR_ON;
  450         tp->t_oproc = 0;                /* mark closed */
  451         return (0);
  452 }
  453 
  454 int
  455 ptcread(dev_t dev, struct uio *uio, int flag)
  456 {
  457         struct pt_softc *pti = pt_softc[minor(dev)];
  458         struct tty *tp = pti->pt_tty;
  459         char buf[BUFSIZ];
  460         int error = 0, cc;
  461 
  462         /*
  463          * We want to block until the slave
  464          * is open, and there's something to read;
  465          * but if we lost the slave or we're NBIO,
  466          * then return the appropriate error instead.
  467          */
  468         for (;;) {
  469                 if (tp->t_state&TS_ISOPEN) {
  470                         if (pti->pt_flags&PF_PKT && pti->pt_send) {
  471                                 error = ureadc((int)pti->pt_send, uio);
  472                                 if (error)
  473                                         return (error);
  474                                 if (pti->pt_send & TIOCPKT_IOCTL) {
  475                                         cc = min(uio->uio_resid,
  476                                                 sizeof(tp->t_termios));
  477                                         uiomove(&tp->t_termios, cc, uio);
  478                                 }
  479                                 pti->pt_send = 0;
  480                                 return (0);
  481                         }
  482                         if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
  483                                 error = ureadc((int)pti->pt_ucntl, uio);
  484                                 if (error)
  485                                         return (error);
  486                                 pti->pt_ucntl = 0;
  487                                 return (0);
  488                         }
  489                         if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
  490                                 break;
  491                 }
  492                 if ((tp->t_state&TS_CARR_ON) == 0)
  493                         return (0);     /* EOF */
  494                 if (flag & IO_NDELAY)
  495                         return (EWOULDBLOCK);
  496                 error = tsleep(&tp->t_outq.c_cf, TTIPRI | PCATCH,
  497                     ttyin, 0);
  498                 if (error)
  499                         return (error);
  500         }
  501         if (pti->pt_flags & (PF_PKT|PF_UCNTL))
  502                 error = ureadc(0, uio);
  503         while (uio->uio_resid > 0 && error == 0) {
  504                 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
  505                 if (cc <= 0)
  506                         break;
  507                 error = uiomove(buf, cc, uio);
  508         }
  509         if (tp->t_outq.c_cc <= tp->t_lowat) {
  510                 if (tp->t_state&TS_ASLEEP) {
  511                         tp->t_state &= ~TS_ASLEEP;
  512                         wakeup(&tp->t_outq);
  513                 }
  514                 selwakeup(&tp->t_wsel);
  515         }
  516         return (error);
  517 }
  518 
  519 
  520 int
  521 ptcwrite(dev_t dev, struct uio *uio, int flag)
  522 {
  523         struct pt_softc *pti = pt_softc[minor(dev)];
  524         struct tty *tp = pti->pt_tty;
  525         u_char *cp = NULL;
  526         int cc = 0;
  527         u_char locbuf[BUFSIZ];
  528         int cnt = 0;
  529         int error = 0;
  530 
  531 again:
  532         if ((tp->t_state&TS_ISOPEN) == 0)
  533                 goto block;
  534         if (pti->pt_flags & PF_REMOTE) {
  535                 if (tp->t_canq.c_cc)
  536                         goto block;
  537                 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
  538                         if (cc == 0) {
  539                                 cc = min(uio->uio_resid, BUFSIZ);
  540                                 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
  541                                 cp = locbuf;
  542                                 error = uiomove(cp, cc, uio);
  543                                 if (error)
  544                                         return (error);
  545                                 /* check again for safety */
  546                                 if ((tp->t_state&TS_ISOPEN) == 0)
  547                                         return (EIO);
  548                         }
  549                         if (cc)
  550                                 (void) b_to_q((char *)cp, cc, &tp->t_canq);
  551                         cc = 0;
  552                 }
  553                 (void) putc(0, &tp->t_canq);
  554                 ttwakeup(tp);
  555                 wakeup(&tp->t_canq);
  556                 return (0);
  557         }
  558         while (uio->uio_resid > 0) {
  559                 if (cc == 0) {
  560                         cc = min(uio->uio_resid, BUFSIZ);
  561                         cp = locbuf;
  562                         error = uiomove(cp, cc, uio);
  563                         if (error)
  564                                 return (error);
  565                         /* check again for safety */
  566                         if ((tp->t_state&TS_ISOPEN) == 0)
  567                                 return (EIO);
  568                 }
  569                 while (cc > 0) {
  570                         if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
  571                            (tp->t_canq.c_cc > 0 || !ISSET(tp->t_lflag, ICANON))) {
  572                                 wakeup(&tp->t_rawq);
  573                                 goto block;
  574                         }
  575                         (*linesw[tp->t_line].l_rint)(*cp++, tp);
  576                         cnt++;
  577                         cc--;
  578                 }
  579                 cc = 0;
  580         }
  581         return (0);
  582 block:
  583         /*
  584          * Come here to wait for slave to open, for space
  585          * in outq, or space in rawq.
  586          */
  587         if ((tp->t_state&TS_CARR_ON) == 0)
  588                 return (EIO);
  589         if (flag & IO_NDELAY) {
  590                 /* adjust for data copied in but not written */
  591                 uio->uio_resid += cc;
  592                 if (cnt == 0)
  593                         return (EWOULDBLOCK);
  594                 return (0);
  595         }
  596         error = tsleep(&tp->t_rawq.c_cf, TTOPRI | PCATCH,
  597             ttyout, 0);
  598         if (error) {
  599                 /* adjust for data copied in but not written */
  600                 uio->uio_resid += cc;
  601                 return (error);
  602         }
  603         goto again;
  604 }
  605 
  606 int
  607 ptcpoll(dev_t dev, int events, struct proc *p)
  608 {
  609         struct pt_softc *pti = pt_softc[minor(dev)];
  610         struct tty *tp = pti->pt_tty;
  611         int revents = 0, s;
  612 
  613         if (!ISSET(tp->t_state, TS_CARR_ON))
  614                 return (POLLHUP);
  615 
  616         if (!ISSET(tp->t_state, TS_ISOPEN))
  617                 goto notopen;
  618 
  619         if (events & (POLLIN | POLLRDNORM)) {
  620                 /*
  621                  * Need to protect access to t_outq
  622                  */
  623                 s = spltty();
  624                 if ((tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP)) ||
  625                     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
  626                     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))
  627                         revents |= events & (POLLIN | POLLRDNORM);
  628                 splx(s);
  629         }
  630         if (events & (POLLOUT | POLLWRNORM)) {
  631                 if ((pti->pt_flags & PF_REMOTE) ?
  632                     (tp->t_canq.c_cc == 0) :
  633                     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
  634                     (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))))
  635                         revents |= events & (POLLOUT | POLLWRNORM);
  636         }
  637         if (events & (POLLPRI | POLLRDBAND)) {
  638                 /* If in packet or user control mode, check for data. */
  639                 if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
  640                     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))
  641                         revents |= events & (POLLPRI | POLLRDBAND);
  642         }
  643 
  644         if (revents == 0) {
  645 notopen:
  646                 if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND))
  647                         selrecord(p, &pti->pt_selr);
  648                 if (events & (POLLOUT | POLLWRNORM))
  649                         selrecord(p, &pti->pt_selw);
  650         }
  651 
  652         return (revents);
  653 }
  654 
  655 void
  656 filt_ptcrdetach(struct knote *kn)
  657 {
  658         struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
  659         int s;
  660 
  661         s = spltty();
  662         SLIST_REMOVE(&pti->pt_selr.si_note, kn, knote, kn_selnext);
  663         splx(s);
  664 }
  665 
  666 int
  667 filt_ptcread(struct knote *kn, long hint)
  668 {
  669         struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
  670         struct tty *tp;
  671 
  672         tp = pti->pt_tty;
  673         kn->kn_data = 0;
  674 
  675         if (ISSET(tp->t_state, TS_ISOPEN)) {
  676                 if (!ISSET(tp->t_state, TS_TTSTOP))
  677                         kn->kn_data = tp->t_outq.c_cc;
  678                 if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
  679                     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))
  680                         kn->kn_data++;
  681         }
  682         return (kn->kn_data > 0);
  683 }
  684 
  685 void
  686 filt_ptcwdetach(struct knote *kn)
  687 {
  688         struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
  689         int s;
  690 
  691         s = spltty();
  692         SLIST_REMOVE(&pti->pt_selw.si_note, kn, knote, kn_selnext);
  693         splx(s);
  694 }
  695 
  696 int
  697 filt_ptcwrite(struct knote *kn, long hint)
  698 {
  699         struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
  700         struct tty *tp;
  701 
  702         tp = pti->pt_tty;
  703         kn->kn_data = 0;
  704 
  705         if (ISSET(tp->t_state, TS_ISOPEN)) {
  706                 if (ISSET(pti->pt_flags, PF_REMOTE)) {
  707                         if (tp->t_canq.c_cc == 0)
  708                                 kn->kn_data = tp->t_canq.c_cn;
  709                 } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
  710                         kn->kn_data = tp->t_canq.c_cn -
  711                             (tp->t_rawq.c_cc + tp->t_canq.c_cc);
  712         }
  713 
  714         return (kn->kn_data > 0);
  715 }
  716 
  717 struct filterops ptcread_filtops =
  718         { 1, NULL, filt_ptcrdetach, filt_ptcread };
  719 struct filterops ptcwrite_filtops =
  720         { 1, NULL, filt_ptcwdetach, filt_ptcwrite };
  721 
  722 int
  723 ptckqfilter(dev_t dev, struct knote *kn)
  724 {
  725         struct pt_softc *pti = pt_softc[minor(dev)];
  726         struct klist *klist;
  727         int s;
  728 
  729         switch (kn->kn_filter) {
  730         case EVFILT_READ:
  731                 klist = &pti->pt_selr.si_note;
  732                 kn->kn_fop = &ptcread_filtops;
  733                 break;
  734         case EVFILT_WRITE:
  735                 klist = &pti->pt_selw.si_note;
  736                 kn->kn_fop = &ptcwrite_filtops;
  737                 break;
  738         default:
  739                 return (1);
  740         }
  741 
  742         kn->kn_hook = (caddr_t)pti;
  743 
  744         s = spltty();
  745         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  746         splx(s);
  747 
  748         return (0);
  749 }
  750 
  751 struct tty *
  752 ptytty(dev_t dev)
  753 {
  754         struct pt_softc *pti = pt_softc[minor(dev)];
  755         struct tty *tp = pti->pt_tty;
  756 
  757         return (tp);
  758 }
  759 
  760 /*ARGSUSED*/
  761 int
  762 ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  763 {
  764         struct pt_softc *pti = pt_softc[minor(dev)];
  765         struct tty *tp = pti->pt_tty;
  766         u_char *cc = tp->t_cc;
  767         int stop, error;
  768 
  769         /*
  770          * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
  771          * ttywflush(tp) will hang if there are characters in the outq.
  772          */
  773         if (cmd == TIOCEXT) {
  774                 /*
  775                  * When the EXTPROC bit is being toggled, we need
  776                  * to send an TIOCPKT_IOCTL if the packet driver
  777                  * is turned on.
  778                  */
  779                 if (*(int *)data) {
  780                         if (pti->pt_flags & PF_PKT) {
  781                                 pti->pt_send |= TIOCPKT_IOCTL;
  782                                 ptcwakeup(tp, FREAD);
  783                         }
  784                         tp->t_lflag |= EXTPROC;
  785                 } else {
  786                         if ((tp->t_lflag & EXTPROC) &&
  787                             (pti->pt_flags & PF_PKT)) {
  788                                 pti->pt_send |= TIOCPKT_IOCTL;
  789                                 ptcwakeup(tp, FREAD);
  790                         }
  791                         tp->t_lflag &= ~EXTPROC;
  792                 }
  793                 return(0);
  794         } else
  795         if (cdevsw[major(dev)].d_open == ptcopen)
  796                 switch (cmd) {
  797 
  798                 case TIOCGPGRP:
  799 #ifdef COMPAT_SUNOS
  800                     {
  801                         /*
  802                          * I'm not sure about SunOS TIOCGPGRP semantics
  803                          * on PTYs, but it's something like this:
  804                          */
  805                         extern struct emul emul_sunos;
  806                         if (p->p_emul == &emul_sunos) {
  807                                 if (tp->t_pgrp == 0)
  808                                         return (EIO);
  809                                 *(int *)data = tp->t_pgrp->pg_id;
  810                                 return (0);
  811                         }
  812                     }
  813 #endif
  814                         /*
  815                          * We avoid calling ttioctl on the controller since,
  816                          * in that case, tp must be the controlling terminal.
  817                          */
  818                         *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
  819                         return (0);
  820 
  821                 case TIOCPKT:
  822                         if (*(int *)data) {
  823                                 if (pti->pt_flags & PF_UCNTL)
  824                                         return (EINVAL);
  825                                 pti->pt_flags |= PF_PKT;
  826                         } else
  827                                 pti->pt_flags &= ~PF_PKT;
  828                         return (0);
  829 
  830                 case TIOCUCNTL:
  831                         if (*(int *)data) {
  832                                 if (pti->pt_flags & PF_PKT)
  833                                         return (EINVAL);
  834                                 pti->pt_flags |= PF_UCNTL;
  835                         } else
  836                                 pti->pt_flags &= ~PF_UCNTL;
  837                         return (0);
  838 
  839                 case TIOCREMOTE:
  840                         if (*(int *)data)
  841                                 pti->pt_flags |= PF_REMOTE;
  842                         else
  843                                 pti->pt_flags &= ~PF_REMOTE;
  844                         ttyflush(tp, FREAD|FWRITE);
  845                         return (0);
  846 
  847 #ifdef COMPAT_OLDTTY
  848                 case TIOCSETP:
  849                 case TIOCSETN:
  850 #endif
  851                 case TIOCSETD:
  852                 case TIOCSETA:
  853                 case TIOCSETAW:
  854                 case TIOCSETAF:
  855                         ndflush(&tp->t_outq, tp->t_outq.c_cc);
  856                         break;
  857 
  858                 case TIOCSIG:
  859                         if (*(unsigned int *)data >= NSIG)
  860                                 return(EINVAL);
  861                         if ((tp->t_lflag&NOFLSH) == 0)
  862                                 ttyflush(tp, FREAD|FWRITE);
  863                         pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
  864                         if ((*(unsigned int *)data == SIGINFO) &&
  865                             ((tp->t_lflag&NOKERNINFO) == 0))
  866                                 ttyinfo(tp);
  867                         return(0);
  868                 }
  869         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
  870         if (error < 0)
  871                  error = ttioctl(tp, cmd, data, flag, p);
  872         if (error < 0) {
  873                 if (pti->pt_flags & PF_UCNTL &&
  874                     (cmd & ~0xff) == UIOCCMD(0)) {
  875                         if (cmd & 0xff) {
  876                                 pti->pt_ucntl = (u_char)cmd;
  877                                 ptcwakeup(tp, FREAD);
  878                         }
  879                         return (0);
  880                 }
  881                 error = ENOTTY;
  882         }
  883         /*
  884          * If external processing and packet mode send ioctl packet.
  885          */
  886         if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
  887                 switch (cmd) {
  888                 case TIOCSETA:
  889                 case TIOCSETAW:
  890                 case TIOCSETAF:
  891 #ifdef COMPAT_OLDTTY
  892                 case TIOCSETP:
  893                 case TIOCSETN:
  894                 case TIOCSETC:
  895                 case TIOCSLTC:
  896                 case TIOCLBIS:
  897                 case TIOCLBIC:
  898                 case TIOCLSET:
  899 #endif
  900                         pti->pt_send |= TIOCPKT_IOCTL;
  901                         ptcwakeup(tp, FREAD);
  902                 default:
  903                         break;
  904                 }
  905         }
  906         stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) &&
  907             CCEQ(cc[VSTART], CTRL('q'));
  908         if (pti->pt_flags & PF_NOSTOP) {
  909                 if (stop) {
  910                         pti->pt_send &= ~TIOCPKT_NOSTOP;
  911                         pti->pt_send |= TIOCPKT_DOSTOP;
  912                         pti->pt_flags &= ~PF_NOSTOP;
  913                         ptcwakeup(tp, FREAD);
  914                 }
  915         } else {
  916                 if (!stop) {
  917                         pti->pt_send &= ~TIOCPKT_DOSTOP;
  918                         pti->pt_send |= TIOCPKT_NOSTOP;
  919                         pti->pt_flags |= PF_NOSTOP;
  920                         ptcwakeup(tp, FREAD);
  921                 }
  922         }
  923         return (error);
  924 }
  925 
  926 /*
  927  * Return pty-related information.
  928  */
  929 int
  930 sysctl_pty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  931     size_t newlen)
  932 {
  933         int error, oldmax;
  934 
  935         if (namelen != 1)
  936                 return (ENOTDIR);
  937 
  938         switch (name[0]) {
  939         case KERN_TTY_MAXPTYS:
  940                 if (!newp)
  941                         return (sysctl_rdint(oldp, oldlenp, newp, maxptys));
  942                 rw_enter_write(&pt_softc_lock);
  943                 oldmax = maxptys;
  944                 error = sysctl_int(oldp, oldlenp, newp, newlen, &maxptys);
  945                 /*
  946                  * We can't set the max lower than the current active
  947                  * value or to a value bigger than NPTY_MAX.
  948                  */
  949                 if (error == 0 && (maxptys > NPTY_MAX || maxptys < npty)) {
  950                         maxptys = oldmax;
  951                         error = ERANGE;
  952                 }
  953                 rw_exit_write(&pt_softc_lock);
  954                 return (error);
  955         case KERN_TTY_NPTYS:
  956                 return (sysctl_rdint(oldp, oldlenp, newp, npty));
  957 #ifdef notyet
  958         case KERN_TTY_GID:
  959                 return (sysctl_int(oldp, oldlenp, newp, newlen, &tty_gid));
  960 #endif
  961         default:
  962                 return (EOPNOTSUPP);
  963         }
  964         /* NOTREACHED */
  965 }
  966 
  967 /*
  968  * Check if a pty is free to use.
  969  */
  970 static __inline int
  971 pty_isfree_locked(int minor)
  972 {
  973         struct pt_softc *pt = pt_softc[minor];
  974         return (pt == NULL || pt->pt_tty == NULL ||
  975             pt->pt_tty->t_oproc == NULL);
  976 }
  977 
  978 static int
  979 pty_isfree(int minor)
  980 {
  981         int isfree;
  982 
  983         rw_enter_read(&pt_softc_lock);
  984         isfree = pty_isfree_locked(minor);
  985         rw_exit_read(&pt_softc_lock);
  986         return(isfree);
  987 }
  988 
  989 dev_t
  990 pty_getfree(void)
  991 {
  992         int i;
  993 
  994         rw_enter_read(&pt_softc_lock);
  995         for (i = 0; i < npty; i++) {
  996                 if (pty_isfree_locked(i))
  997                         break;
  998         }
  999         rw_exit_read(&pt_softc_lock);
 1000         return (makedev(pts_major, i));
 1001 }
 1002 
 1003 /*
 1004  * Hacked up version of vn_open. We _only_ handle ptys and only open
 1005  * them with FREAD|FWRITE and never deal with creat or stuff like that.
 1006  *
 1007  * We need it because we have to fake up root credentials to open the pty.
 1008  */
 1009 static int
 1010 ptm_vn_open(struct nameidata *ndp)
 1011 {
 1012         struct proc *p = ndp->ni_cnd.cn_proc;
 1013         struct ucred *cred;
 1014         struct vattr vattr;
 1015         struct vnode *vp;
 1016         int error;
 1017 
 1018         if ((error = namei(ndp)) != 0)
 1019                 return (error);
 1020         vp = ndp->ni_vp;
 1021         if (vp->v_type != VCHR) {
 1022                 error = EINVAL;
 1023                 goto bad;
 1024         }
 1025 
 1026         /*
 1027          * Get us a fresh cred with root privileges.
 1028          */
 1029         cred = crget();
 1030         error = VOP_OPEN(vp, FREAD|FWRITE, cred, p);
 1031         if (!error) {
 1032                 /* update atime/mtime */
 1033                 VATTR_NULL(&vattr);
 1034                 getnanotime(&vattr.va_atime);
 1035                 vattr.va_mtime = vattr.va_atime;
 1036                 vattr.va_vaflags |= VA_UTIMES_NULL;
 1037                 (void)VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 1038         }
 1039         crfree(cred);
 1040 
 1041         if (error)
 1042                 goto bad;
 1043 
 1044         vp->v_writecount++;
 1045 
 1046         return (0);
 1047 bad:
 1048         vput(vp);
 1049         return (error);
 1050 }
 1051 
 1052 void
 1053 ptmattach(int n)
 1054 {
 1055         /* find the major and minor of the pty devices */
 1056         int i;
 1057 
 1058         for (i = 0; i < nchrdev; i++)
 1059                 if (cdevsw[i].d_open == ptsopen)
 1060                         break;
 1061 
 1062         if (i == nchrdev)
 1063                 panic("ptmattach: Can't find pty slave in cdevsw");
 1064 
 1065         pts_major = i;
 1066 }
 1067 
 1068 int
 1069 ptmopen(dev_t dev, int flag, int mode, struct proc *p)
 1070 {
 1071         return(0);
 1072 }
 1073 
 1074 
 1075 int
 1076 ptmclose(dev_t dev, int flag, int mode, struct proc *p)
 1077 {
 1078         return (0);
 1079 }
 1080 
 1081 int
 1082 ptmread(dev_t dev, struct uio *uio, int ioflag)
 1083 {
 1084         return (EIO);
 1085 }
 1086 
 1087 int
 1088 ptmwrite(dev_t dev, struct uio *uio, int ioflag)
 1089 {
 1090         return (EIO);
 1091 }
 1092 
 1093 int
 1094 ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 1095 {
 1096         dev_t newdev, error;
 1097         struct pt_softc * pti;
 1098         struct nameidata cnd, snd;
 1099         struct filedesc *fdp = p->p_fd;
 1100         struct file *cfp = NULL, *sfp = NULL;
 1101         int cindx, sindx;
 1102         uid_t uid;
 1103         gid_t gid;
 1104         struct vattr vattr;
 1105         struct ucred *cred;
 1106         struct ptmget *ptm = (struct ptmget *)data;
 1107 
 1108         error = 0;
 1109         switch (cmd) {
 1110         case PTMGET:
 1111                 fdplock(fdp);
 1112                 /* Grab two filedescriptors. */
 1113                 if ((error = falloc(p, &cfp, &cindx)) != 0) {
 1114                         fdpunlock(fdp);
 1115                         break;
 1116                 }
 1117                 if ((error = falloc(p, &sfp, &sindx)) != 0) {
 1118                         fdremove(fdp, cindx);
 1119                         closef(cfp, p);
 1120                         fdpunlock(fdp);
 1121                         break;
 1122                 }
 1123 
 1124 retry:
 1125                 /* Find and open a free master pty. */
 1126                 newdev = pty_getfree();
 1127                 if ((error = check_pty(minor(newdev))))
 1128                         goto bad;
 1129                 pti = pt_softc[minor(newdev)];
 1130                 NDINIT(&cnd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE,
 1131                     pti->pty_pn, p);
 1132                 if ((error = ptm_vn_open(&cnd)) != 0) {
 1133                         /*
 1134                          * Check if the master open failed because we lost
 1135                          * the race to grab it.
 1136                          */
 1137                         if (error == EIO && !pty_isfree(minor(newdev)))
 1138                                 goto retry;
 1139                         goto bad;
 1140                 }
 1141                 cfp->f_flag = FREAD|FWRITE;
 1142                 cfp->f_type = DTYPE_VNODE;
 1143                 cfp->f_ops = &vnops;
 1144                 cfp->f_data = (caddr_t) cnd.ni_vp;
 1145                 VOP_UNLOCK(cnd.ni_vp, 0, p);
 1146 
 1147                 /*
 1148                  * Open the slave.
 1149                  * namei -> setattr -> unlock -> revoke -> vrele ->
 1150                  * namei -> open -> unlock
 1151                  * Three stage rocket:
 1152                  * 1. Change the owner and permissions on the slave.
 1153                  * 2. Revoke all the users of the slave.
 1154                  * 3. open the slave.
 1155                  */
 1156                 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE,
 1157                     pti->pty_sn, p);
 1158                 if ((error = namei(&snd)) != 0)
 1159                         goto bad;
 1160                 if ((snd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 1161                         gid = tty_gid;
 1162                         /* get real uid */
 1163                         uid = p->p_cred->p_ruid;
 1164 
 1165                         VATTR_NULL(&vattr);
 1166                         vattr.va_uid = uid;
 1167                         vattr.va_gid = gid;
 1168                         vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS;
 1169                         /* Get a fake cred to pretend we're root. */
 1170                         cred = crget();
 1171                         error = VOP_SETATTR(snd.ni_vp, &vattr, cred, p);
 1172                         crfree(cred);
 1173                         if (error) {
 1174                                 vput(snd.ni_vp);
 1175                                 goto bad;
 1176                         }
 1177                 }
 1178                 VOP_UNLOCK(snd.ni_vp, 0, p);
 1179                 if (snd.ni_vp->v_usecount > 1 ||
 1180                     (snd.ni_vp->v_flag & (VALIASED)))
 1181                         VOP_REVOKE(snd.ni_vp, REVOKEALL);
 1182 
 1183                 /*
 1184                  * The vnode is useless after the revoke, we need to
 1185                  * namei again.
 1186                  */
 1187                 vrele(snd.ni_vp);
 1188 
 1189                 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE,
 1190                     pti->pty_sn, p);
 1191                 /* now open it */
 1192                 if ((error = ptm_vn_open(&snd)) != 0)
 1193                         goto bad;
 1194                 sfp->f_flag = FREAD|FWRITE;
 1195                 sfp->f_type = DTYPE_VNODE;
 1196                 sfp->f_ops = &vnops;
 1197                 sfp->f_data = (caddr_t) snd.ni_vp;
 1198                 VOP_UNLOCK(snd.ni_vp, 0, p);
 1199 
 1200                 /* now, put the indexen and names into struct ptmget */
 1201                 ptm->cfd = cindx;
 1202                 ptm->sfd = sindx;
 1203                 memcpy(ptm->cn, pti->pty_pn, sizeof(pti->pty_pn));
 1204                 memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn));
 1205 
 1206                 /* mark the files mature now that we've passed all errors */
 1207                 FILE_SET_MATURE(cfp);
 1208                 FILE_SET_MATURE(sfp);
 1209 
 1210                 fdpunlock(fdp);
 1211                 break;
 1212         default:
 1213                 error = EINVAL;
 1214                 break;
 1215         }
 1216         return (error);
 1217 bad:
 1218         fdremove(fdp, cindx);
 1219         closef(cfp, p);
 1220         fdremove(fdp, sindx);
 1221         closef(sfp, p);
 1222         fdpunlock(fdp);
 1223         return (error);
 1224 }
 1225 
 1226 int
 1227 ptmpoll(dev_t dev, int events, struct proc *p)
 1228 {
 1229         return (seltrue(dev, events, p));
 1230 }

/* [<][>][^][v][top][bottom][index][help] */