The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_pty.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)tty_pty.c   8.4 (Berkeley) 2/20/95
   34  * $FreeBSD: src/sys/kern/tty_pty.c,v 1.39.2.2 1999/09/05 08:15:27 peter Exp $
   35  */
   36 
   37 /*
   38  * Pseudo-teletype Driver
   39  * (Actually two drivers, requiring two entries in 'cdevsw')
   40  */
   41 #include "pty.h"                /* XXX */
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/proc.h>
   47 #include <sys/tty.h>
   48 #include <sys/conf.h>
   49 #include <sys/file.h>
   50 #include <sys/uio.h>
   51 #include <sys/kernel.h>
   52 #include <sys/vnode.h>
   53 #include <sys/signalvar.h>
   54 
   55 #ifdef DEVFS
   56 #include <sys/devfsext.h>
   57 #endif /*DEVFS*/
   58 
   59 #ifdef notyet
   60 static void ptyattach __P((int n));
   61 #endif
   62 static void ptsstart __P((struct tty *tp));
   63 static void ptcwakeup __P((struct tty *tp, int flag));
   64 
   65 static  d_open_t        ptsopen;
   66 static  d_close_t       ptsclose;
   67 static  d_read_t        ptsread;
   68 static  d_write_t       ptswrite;
   69 static  d_ioctl_t       ptyioctl;
   70 static  d_stop_t        ptsstop;
   71 static  d_devtotty_t    ptydevtotty;
   72 static  d_open_t        ptcopen;
   73 static  d_close_t       ptcclose;
   74 static  d_read_t        ptcread;
   75 static  d_write_t       ptcwrite;
   76 static  d_select_t      ptcselect;
   77 
   78 #define CDEV_MAJOR_S 5
   79 #define CDEV_MAJOR_C 6
   80 static struct cdevsw pts_cdevsw = 
   81         { ptsopen,      ptsclose,       ptsread,        ptswrite,       /*5*/
   82           ptyioctl,     ptsstop,        nullreset,      ptydevtotty,/* ttyp */
   83           ttselect,     nommap,         NULL,   "pts",  NULL,   -1 };
   84 
   85 static struct cdevsw ptc_cdevsw = 
   86         { ptcopen,      ptcclose,       ptcread,        ptcwrite,       /*6*/
   87           ptyioctl,     nullstop,       nullreset,      ptydevtotty,/* ptyp */
   88           ptcselect,    nommap,         NULL,   "ptc",  NULL,   -1 };
   89 
   90 
   91 #if NPTY == 1
   92 #undef NPTY
   93 #define NPTY    32              /* crude XXX */
   94 #warning        You have only one pty defined, redefining to 32.
   95 #endif
   96 
   97 #ifdef DEVFS
   98 #define MAXUNITS (8 * 32)
   99 static  void    *devfs_token_pts[MAXUNITS];
  100 static  void    *devfs_token_ptc[MAXUNITS];
  101 static  const   char jnames[] = "pqrsPQRS";
  102 #if NPTY > MAXUNITS
  103 #undef NPTY
  104 #define NPTY MAXUNITS
  105 #warning        Can't have more than 256 pty's with DEVFS defined.
  106 #endif
  107 #endif
  108 
  109 #define BUFSIZ 100              /* Chunk size iomoved to/from user */
  110 
  111 /*
  112  * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
  113  * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
  114  */
  115 static struct   tty pt_tty[NPTY];       /* XXX */
  116 static struct   pt_ioctl {
  117         int     pt_flags;
  118         struct  selinfo pt_selr, pt_selw;
  119         u_char  pt_send;
  120         u_char  pt_ucntl;
  121 } pt_ioctl[NPTY];               /* XXX */
  122 static int      npty = NPTY;            /* for pstat -t */
  123 
  124 #define PF_PKT          0x08            /* packet mode */
  125 #define PF_STOPPED      0x10            /* user told stopped */
  126 #define PF_REMOTE       0x20            /* remote and flow controlled input */
  127 #define PF_NOSTOP       0x40
  128 #define PF_UCNTL        0x80            /* user control mode */
  129 
  130 #ifdef notyet
  131 /*
  132  * Establish n (or default if n is 1) ptys in the system.
  133  *
  134  * XXX cdevsw & pstat require the array `pty[]' to be an array
  135  */
  136 static void
  137 ptyattach(n)
  138         int n;
  139 {
  140         char *mem;
  141         register u_long ntb;
  142 #define DEFAULT_NPTY    32
  143 
  144         /* maybe should allow 0 => none? */
  145         if (n <= 1)
  146                 n = DEFAULT_NPTY;
  147         ntb = n * sizeof(struct tty);
  148         mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
  149             M_DEVBUF, M_WAITOK);
  150         pt_tty = (struct tty *)mem;
  151         mem = (char *)ALIGN(mem + ntb);
  152         pt_ioctl = (struct pt_ioctl *)mem;
  153         npty = n;
  154 }
  155 #endif
  156 
  157 /*ARGSUSED*/
  158 static  int
  159 ptsopen(dev, flag, devtype, p)
  160         dev_t dev;
  161         int flag, devtype;
  162         struct proc *p;
  163 {
  164         register struct tty *tp;
  165         int error;
  166 
  167         if (minor(dev) >= npty)
  168                 return (ENXIO);
  169         tp = &pt_tty[minor(dev)];
  170         if ((tp->t_state & TS_ISOPEN) == 0) {
  171                 ttychars(tp);           /* Set up default chars */
  172                 tp->t_iflag = TTYDEF_IFLAG;
  173                 tp->t_oflag = TTYDEF_OFLAG;
  174                 tp->t_lflag = TTYDEF_LFLAG;
  175                 tp->t_cflag = TTYDEF_CFLAG;
  176                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  177                 ttsetwater(tp);         /* would be done in xxparam() */
  178         } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
  179                 return (EBUSY);
  180         if (tp->t_oproc)                        /* Ctrlr still around. */
  181                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  182         while ((tp->t_state & TS_CARR_ON) == 0) {
  183                 if (flag&FNONBLOCK)
  184                         break;
  185                 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
  186                                  "ptsopn", 0);
  187                 if (error)
  188                         return (error);
  189         }
  190         error = (*linesw[tp->t_line].l_open)(dev, tp);
  191         if (error == 0)
  192                 ptcwakeup(tp, FREAD|FWRITE);
  193         return (error);
  194 }
  195 
  196 static  int
  197 ptsclose(dev, flag, mode, p)
  198         dev_t dev;
  199         int flag, mode;
  200         struct proc *p;
  201 {
  202         register struct tty *tp;
  203         int err;
  204 
  205         tp = &pt_tty[minor(dev)];
  206         err = (*linesw[tp->t_line].l_close)(tp, flag);
  207         ptsstop(tp, FREAD|FWRITE);
  208         (void) ttyclose(tp);
  209         return (err);
  210 }
  211 
  212 static  int
  213 ptsread(dev, uio, flag)
  214         dev_t dev;
  215         struct uio *uio;
  216         int flag;
  217 {
  218         struct proc *p = curproc;
  219         register struct tty *tp = &pt_tty[minor(dev)];
  220         register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
  221         int error = 0;
  222 
  223 again:
  224         if (pti->pt_flags & PF_REMOTE) {
  225                 while (isbackground(p, tp)) {
  226                         if ((p->p_sigignore & sigmask(SIGTTIN)) ||
  227                             (p->p_sigmask & sigmask(SIGTTIN)) ||
  228                             p->p_pgrp->pg_jobc == 0 ||
  229                             p->p_flag & P_PPWAIT)
  230                                 return (EIO);
  231                         pgsignal(p->p_pgrp, SIGTTIN, 1);
  232                         error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
  233                                          0);
  234                         if (error)
  235                                 return (error);
  236                 }
  237                 if (tp->t_canq.c_cc == 0) {
  238                         if (flag & IO_NDELAY)
  239                                 return (EWOULDBLOCK);
  240                         error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
  241                                          "ptsin", 0);
  242                         if (error)
  243                                 return (error);
  244                         goto again;
  245                 }
  246                 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
  247                         if (ureadc(getc(&tp->t_canq), uio) < 0) {
  248                                 error = EFAULT;
  249                                 break;
  250                         }
  251                 if (tp->t_canq.c_cc == 1)
  252                         (void) getc(&tp->t_canq);
  253                 if (tp->t_canq.c_cc)
  254                         return (error);
  255         } else
  256                 if (tp->t_oproc)
  257                         error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
  258         ptcwakeup(tp, FWRITE);
  259         return (error);
  260 }
  261 
  262 /*
  263  * Write to pseudo-tty.
  264  * Wakeups of controlling tty will happen
  265  * indirectly, when tty driver calls ptsstart.
  266  */
  267 static  int
  268 ptswrite(dev, uio, flag)
  269         dev_t dev;
  270         struct uio *uio;
  271         int flag;
  272 {
  273         register struct tty *tp;
  274 
  275         tp = &pt_tty[minor(dev)];
  276         if (tp->t_oproc == 0)
  277                 return (EIO);
  278         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
  279 }
  280 
  281 /*
  282  * Start output on pseudo-tty.
  283  * Wake up process selecting or sleeping for input from controlling tty.
  284  */
  285 static void
  286 ptsstart(tp)
  287         struct tty *tp;
  288 {
  289         register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
  290 
  291         if (tp->t_state & TS_TTSTOP)
  292                 return;
  293         if (pti->pt_flags & PF_STOPPED) {
  294                 pti->pt_flags &= ~PF_STOPPED;
  295                 pti->pt_send = TIOCPKT_START;
  296         }
  297         ptcwakeup(tp, FREAD);
  298 }
  299 
  300 static void
  301 ptcwakeup(tp, flag)
  302         struct tty *tp;
  303         int flag;
  304 {
  305         struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
  306 
  307         if (flag & FREAD) {
  308                 selwakeup(&pti->pt_selr);
  309                 wakeup(TSA_PTC_READ(tp));
  310         }
  311         if (flag & FWRITE) {
  312                 selwakeup(&pti->pt_selw);
  313                 wakeup(TSA_PTC_WRITE(tp));
  314         }
  315 }
  316 
  317 static  int
  318 ptcopen(dev, flag, devtype, p)
  319         dev_t dev;
  320         int flag, devtype;
  321         struct proc *p;
  322 {
  323         register struct tty *tp;
  324         struct pt_ioctl *pti;
  325 
  326         if (minor(dev) >= npty)
  327                 return (ENXIO);
  328         tp = &pt_tty[minor(dev)];
  329         if (tp->t_oproc)
  330                 return (EIO);
  331         tp->t_oproc = ptsstart;
  332 #ifdef sun4c
  333         tp->t_stop = ptsstop;
  334 #endif
  335         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  336         tp->t_lflag &= ~EXTPROC;
  337         pti = &pt_ioctl[minor(dev)];
  338         pti->pt_flags = 0;
  339         pti->pt_send = 0;
  340         pti->pt_ucntl = 0;
  341         return (0);
  342 }
  343 
  344 static  int
  345 ptcclose(dev, flags, fmt, p)
  346         dev_t dev;
  347         int flags;
  348         int fmt;
  349         struct proc *p;
  350 {
  351         register struct tty *tp;
  352 
  353         tp = &pt_tty[minor(dev)];
  354         (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  355 
  356         /*
  357          * XXX MDMBUF makes no sense for ptys but would inhibit the above
  358          * l_modem().  CLOCAL makes sense but isn't supported.   Special
  359          * l_modem()s that ignore carrier drop make no sense for ptys but
  360          * may be in use because other parts of the line discipline make
  361          * sense for ptys.  Recover by doing everything that a normal
  362          * ttymodem() would have done except for sending a SIGHUP.
  363          */
  364         if (tp->t_state & TS_ISOPEN) {
  365                 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
  366                 tp->t_state |= TS_ZOMBIE;
  367                 ttyflush(tp, FREAD | FWRITE);
  368         }
  369 
  370         tp->t_oproc = 0;                /* mark closed */
  371         return (0);
  372 }
  373 
  374 static  int
  375 ptcread(dev, uio, flag)
  376         dev_t dev;
  377         struct uio *uio;
  378         int flag;
  379 {
  380         register struct tty *tp = &pt_tty[minor(dev)];
  381         struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
  382         char buf[BUFSIZ];
  383         int error = 0, cc;
  384 
  385         /*
  386          * We want to block until the slave
  387          * is open, and there's something to read;
  388          * but if we lost the slave or we're NBIO,
  389          * then return the appropriate error instead.
  390          */
  391         for (;;) {
  392                 if (tp->t_state&TS_ISOPEN) {
  393                         if (pti->pt_flags&PF_PKT && pti->pt_send) {
  394                                 error = ureadc((int)pti->pt_send, uio);
  395                                 if (error)
  396                                         return (error);
  397                                 if (pti->pt_send & TIOCPKT_IOCTL) {
  398                                         cc = min(uio->uio_resid,
  399                                                 sizeof(tp->t_termios));
  400                                         uiomove((caddr_t)&tp->t_termios, cc,
  401                                                 uio);
  402                                 }
  403                                 pti->pt_send = 0;
  404                                 return (0);
  405                         }
  406                         if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
  407                                 error = ureadc((int)pti->pt_ucntl, uio);
  408                                 if (error)
  409                                         return (error);
  410                                 pti->pt_ucntl = 0;
  411                                 return (0);
  412                         }
  413                         if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
  414                                 break;
  415                 }
  416                 if ((tp->t_state & TS_CONNECTED) == 0)
  417                         return (0);     /* EOF */
  418                 if (flag & IO_NDELAY)
  419                         return (EWOULDBLOCK);
  420                 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
  421                 if (error)
  422                         return (error);
  423         }
  424         if (pti->pt_flags & (PF_PKT|PF_UCNTL))
  425                 error = ureadc(0, uio);
  426         while (uio->uio_resid > 0 && error == 0) {
  427                 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
  428                 if (cc <= 0)
  429                         break;
  430                 error = uiomove(buf, cc, uio);
  431         }
  432         ttwwakeup(tp);
  433         return (error);
  434 }
  435 
  436 static  void
  437 ptsstop(tp, flush)
  438         register struct tty *tp;
  439         int flush;
  440 {
  441         struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
  442         int flag;
  443 
  444         /* note: FLUSHREAD and FLUSHWRITE already ok */
  445         if (flush == 0) {
  446                 flush = TIOCPKT_STOP;
  447                 pti->pt_flags |= PF_STOPPED;
  448         } else
  449                 pti->pt_flags &= ~PF_STOPPED;
  450         pti->pt_send |= flush;
  451         /* change of perspective */
  452         flag = 0;
  453         if (flush & FREAD)
  454                 flag |= FWRITE;
  455         if (flush & FWRITE)
  456                 flag |= FREAD;
  457         ptcwakeup(tp, flag);
  458 }
  459 
  460 static  int
  461 ptcselect(dev, rw, p)
  462         dev_t dev;
  463         int rw;
  464         struct proc *p;
  465 {
  466         register struct tty *tp = &pt_tty[minor(dev)];
  467         struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
  468         int s;
  469 
  470         if ((tp->t_state & TS_CONNECTED) == 0)
  471                 return (1);
  472         switch (rw) {
  473 
  474         case FREAD:
  475                 /*
  476                  * Need to block timeouts (ttrstart).
  477                  */
  478                 s = spltty();
  479                 if ((tp->t_state&TS_ISOPEN) &&
  480                      tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
  481                         splx(s);
  482                         return (1);
  483                 }
  484                 splx(s);
  485                 /* FALLTHROUGH */
  486 
  487         case 0:                                 /* exceptional */
  488                 if ((tp->t_state&TS_ISOPEN) &&
  489                     ((pti->pt_flags&PF_PKT && pti->pt_send) ||
  490                      (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
  491                         return (1);
  492                 selrecord(p, &pti->pt_selr);
  493                 break;
  494 
  495 
  496         case FWRITE:
  497                 if (tp->t_state&TS_ISOPEN) {
  498                         if (pti->pt_flags & PF_REMOTE) {
  499                             if (tp->t_canq.c_cc == 0)
  500                                 return (1);
  501                         } else {
  502                             if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
  503                                     return (1);
  504                             if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
  505                                     return (1);
  506                         }
  507                 }
  508                 selrecord(p, &pti->pt_selw);
  509                 break;
  510 
  511         }
  512         return (0);
  513 }
  514 
  515 static  int
  516 ptcwrite(dev, uio, flag)
  517         dev_t dev;
  518         register struct uio *uio;
  519         int flag;
  520 {
  521         register struct tty *tp = &pt_tty[minor(dev)];
  522         register u_char *cp = 0;
  523         register int cc = 0;
  524         u_char locbuf[BUFSIZ];
  525         int cnt = 0;
  526         struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
  527         int error = 0;
  528 
  529 again:
  530         if ((tp->t_state&TS_ISOPEN) == 0)
  531                 goto block;
  532         if (pti->pt_flags & PF_REMOTE) {
  533                 if (tp->t_canq.c_cc)
  534                         goto block;
  535                 while ((uio->uio_resid > 0 || cc > 0) &&
  536                        tp->t_canq.c_cc < TTYHOG - 1) {
  537                         if (cc == 0) {
  538                                 cc = min(uio->uio_resid, BUFSIZ);
  539                                 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
  540                                 cp = locbuf;
  541                                 error = uiomove((caddr_t)cp, cc, uio);
  542                                 if (error)
  543                                         return (error);
  544                                 /* check again for safety */
  545                                 if ((tp->t_state & TS_ISOPEN) == 0) {
  546                                         /* adjust as usual */
  547                                         uio->uio_resid += cc;
  548                                         return (EIO);
  549                                 }
  550                         }
  551                         if (cc > 0) {
  552                                 cc = b_to_q((char *)cp, cc, &tp->t_canq);
  553                                 /*
  554                                  * XXX we don't guarantee that the canq size
  555                                  * is >= TTYHOG, so the above b_to_q() may
  556                                  * leave some bytes uncopied.  However, space
  557                                  * is guaranteed for the null terminator if
  558                                  * we don't fail here since (TTYHOG - 1) is
  559                                  * not a multiple of CBSIZE.
  560                                  */
  561                                 if (cc > 0)
  562                                         break;
  563                         }
  564                 }
  565                 /* adjust for data copied in but not written */
  566                 uio->uio_resid += cc;
  567                 (void) putc(0, &tp->t_canq);
  568                 ttwakeup(tp);
  569                 wakeup(TSA_PTS_READ(tp));
  570                 return (0);
  571         }
  572         while (uio->uio_resid > 0 || cc > 0) {
  573                 if (cc == 0) {
  574                         cc = min(uio->uio_resid, BUFSIZ);
  575                         cp = locbuf;
  576                         error = uiomove((caddr_t)cp, cc, uio);
  577                         if (error)
  578                                 return (error);
  579                         /* check again for safety */
  580                         if ((tp->t_state & TS_ISOPEN) == 0) {
  581                                 /* adjust for data copied in but not written */
  582                                 uio->uio_resid += cc;
  583                                 return (EIO);
  584                         }
  585                 }
  586                 while (cc > 0) {
  587                         if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
  588                            (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
  589                                 wakeup(TSA_HUP_OR_INPUT(tp));
  590                                 goto block;
  591                         }
  592                         (*linesw[tp->t_line].l_rint)(*cp++, tp);
  593                         cnt++;
  594                         cc--;
  595                 }
  596                 cc = 0;
  597         }
  598         return (0);
  599 block:
  600         /*
  601          * Come here to wait for slave to open, for space
  602          * in outq, or space in rawq, or an empty canq.
  603          */
  604         if ((tp->t_state & TS_CONNECTED) == 0) {
  605                 /* adjust for data copied in but not written */
  606                 uio->uio_resid += cc;
  607                 return (EIO);
  608         }
  609         if (flag & IO_NDELAY) {
  610                 /* adjust for data copied in but not written */
  611                 uio->uio_resid += cc;
  612                 if (cnt == 0)
  613                         return (EWOULDBLOCK);
  614                 return (0);
  615         }
  616         error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
  617         if (error) {
  618                 /* adjust for data copied in but not written */
  619                 uio->uio_resid += cc;
  620                 return (error);
  621         }
  622         goto again;
  623 }
  624 
  625 static  struct tty *
  626 ptydevtotty(dev)
  627         dev_t           dev;
  628 {
  629         if (minor(dev) >= npty)
  630                 return (NULL);
  631 
  632         return &pt_tty[minor(dev)];
  633 }
  634 
  635 /*ARGSUSED*/
  636 static  int
  637 ptyioctl(dev, cmd, data, flag, p)
  638         dev_t dev;
  639         int cmd;
  640         caddr_t data;
  641         int flag;
  642         struct proc *p;
  643 {
  644         register struct tty *tp = &pt_tty[minor(dev)];
  645         register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
  646         register u_char *cc = tp->t_cc;
  647         int stop, error;
  648 
  649         /*
  650          * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
  651          * ttywflush(tp) will hang if there are characters in the outq.
  652          */
  653         if (cmd == TIOCEXT) {
  654                 /*
  655                  * When the EXTPROC bit is being toggled, we need
  656                  * to send an TIOCPKT_IOCTL if the packet driver
  657                  * is turned on.
  658                  */
  659                 if (*(int *)data) {
  660                         if (pti->pt_flags & PF_PKT) {
  661                                 pti->pt_send |= TIOCPKT_IOCTL;
  662                                 ptcwakeup(tp, FREAD);
  663                         }
  664                         tp->t_lflag |= EXTPROC;
  665                 } else {
  666                         if ((tp->t_lflag & EXTPROC) &&
  667                             (pti->pt_flags & PF_PKT)) {
  668                                 pti->pt_send |= TIOCPKT_IOCTL;
  669                                 ptcwakeup(tp, FREAD);
  670                         }
  671                         tp->t_lflag &= ~EXTPROC;
  672                 }
  673                 return(0);
  674         } else
  675         if (cdevsw[major(dev)]->d_open == ptcopen)
  676                 switch (cmd) {
  677 
  678                 case TIOCGPGRP:
  679                         /*
  680                          * We aviod calling ttioctl on the controller since,
  681                          * in that case, tp must be the controlling terminal.
  682                          */
  683                         *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
  684                         return (0);
  685 
  686                 case TIOCPKT:
  687                         if (*(int *)data) {
  688                                 if (pti->pt_flags & PF_UCNTL)
  689                                         return (EINVAL);
  690                                 pti->pt_flags |= PF_PKT;
  691                         } else
  692                                 pti->pt_flags &= ~PF_PKT;
  693                         return (0);
  694 
  695                 case TIOCUCNTL:
  696                         if (*(int *)data) {
  697                                 if (pti->pt_flags & PF_PKT)
  698                                         return (EINVAL);
  699                                 pti->pt_flags |= PF_UCNTL;
  700                         } else
  701                                 pti->pt_flags &= ~PF_UCNTL;
  702                         return (0);
  703 
  704                 case TIOCREMOTE:
  705                         if (*(int *)data)
  706                                 pti->pt_flags |= PF_REMOTE;
  707                         else
  708                                 pti->pt_flags &= ~PF_REMOTE;
  709                         ttyflush(tp, FREAD|FWRITE);
  710                         return (0);
  711 
  712 #ifdef COMPAT_43
  713                 case TIOCSETP:
  714                 case TIOCSETN:
  715 #endif
  716                 case TIOCSETD:
  717                 case TIOCSETA:
  718                 case TIOCSETAW:
  719                 case TIOCSETAF:
  720                         ndflush(&tp->t_outq, tp->t_outq.c_cc);
  721                         break;
  722 
  723                 case TIOCSIG:
  724                         if (*(unsigned int *)data >= NSIG ||
  725                             *(unsigned int *)data == 0)
  726                                 return(EINVAL);
  727                         if ((tp->t_lflag&NOFLSH) == 0)
  728                                 ttyflush(tp, FREAD|FWRITE);
  729                         pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
  730                         if ((*(unsigned int *)data == SIGINFO) &&
  731                             ((tp->t_lflag&NOKERNINFO) == 0))
  732                                 ttyinfo(tp);
  733                         return(0);
  734                 }
  735         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
  736         if (error < 0)
  737                  error = ttioctl(tp, cmd, data, flag);
  738         if (error < 0) {
  739                 if (pti->pt_flags & PF_UCNTL &&
  740                     (cmd & ~0xff) == UIOCCMD(0)) {
  741                         if (cmd & 0xff) {
  742                                 pti->pt_ucntl = (u_char)cmd;
  743                                 ptcwakeup(tp, FREAD);
  744                         }
  745                         return (0);
  746                 }
  747                 error = ENOTTY;
  748         }
  749         /*
  750          * If external processing and packet mode send ioctl packet.
  751          */
  752         if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
  753                 switch(cmd) {
  754                 case TIOCSETA:
  755                 case TIOCSETAW:
  756                 case TIOCSETAF:
  757 #ifdef COMPAT_43
  758                 case TIOCSETP:
  759                 case TIOCSETN:
  760 #endif
  761 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  762                 case TIOCSETC:
  763                 case TIOCSLTC:
  764                 case TIOCLBIS:
  765                 case TIOCLBIC:
  766                 case TIOCLSET:
  767 #endif
  768                         pti->pt_send |= TIOCPKT_IOCTL;
  769                         ptcwakeup(tp, FREAD);
  770                 default:
  771                         break;
  772                 }
  773         }
  774         stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
  775                 && CCEQ(cc[VSTART], CTRL('q'));
  776         if (pti->pt_flags & PF_NOSTOP) {
  777                 if (stop) {
  778                         pti->pt_send &= ~TIOCPKT_NOSTOP;
  779                         pti->pt_send |= TIOCPKT_DOSTOP;
  780                         pti->pt_flags &= ~PF_NOSTOP;
  781                         ptcwakeup(tp, FREAD);
  782                 }
  783         } else {
  784                 if (!stop) {
  785                         pti->pt_send &= ~TIOCPKT_DOSTOP;
  786                         pti->pt_send |= TIOCPKT_NOSTOP;
  787                         pti->pt_flags |= PF_NOSTOP;
  788                         ptcwakeup(tp, FREAD);
  789                 }
  790         }
  791         return (error);
  792 }
  793 
  794 static ptc_devsw_installed = 0;
  795 
  796 static void
  797 ptc_drvinit(void *unused)
  798 {
  799 #ifdef DEVFS
  800         int i,j,k;
  801 #endif
  802         dev_t dev;
  803 
  804         if( ! ptc_devsw_installed ) {
  805                 dev = makedev(CDEV_MAJOR_S, 0);
  806                 cdevsw_add(&dev, &pts_cdevsw, NULL);
  807                 dev = makedev(CDEV_MAJOR_C, 0);
  808                 cdevsw_add(&dev, &ptc_cdevsw, NULL);
  809                 ptc_devsw_installed = 1;
  810 #ifdef DEVFS
  811                 for ( i = 0 ; i<NPTY ; i++ ) {
  812                         j = i / 32;
  813                         k = i % 32;
  814                         devfs_token_pts[i] = 
  815                                 devfs_add_devswf(&pts_cdevsw,i,
  816                                                 DV_CHR,0,0,0666,
  817                                                 "tty%c%n",jnames[j],k);
  818                         devfs_token_ptc[i] =
  819                                 devfs_add_devswf(&ptc_cdevsw,i,
  820                                                 DV_CHR,0,0,0666,
  821                                                 "pty%c%n",jnames[j],k);
  822                 }
  823 #endif
  824         }
  825 }
  826 
  827 SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)

Cache object: 38c86be03d7fdcd0603aa9fa75e3981e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.