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_tty.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, 1991, 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_tty.c   8.2 (Berkeley) 9/23/93
   34  * $FreeBSD: releng/5.0/sys/kern/tty_tty.c 102129 2002-08-19 19:04:53Z rwatson $
   35  */
   36 
   37 /*
   38  * Indirect driver for controlling tty.
   39  */
   40 
   41 #include "opt_mac.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/conf.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/mac.h>
   49 #include <sys/mutex.h>
   50 #include <sys/sx.h>
   51 #include <sys/proc.h>
   52 #include <sys/ttycom.h>
   53 #include <sys/vnode.h>
   54 
   55 static  d_open_t        cttyopen;
   56 static  d_read_t        cttyread;
   57 static  d_write_t       cttywrite;
   58 static  d_ioctl_t       cttyioctl;
   59 static  d_poll_t        cttypoll;
   60 
   61 #define CDEV_MAJOR      1
   62 
   63 static struct cdevsw ctty_cdevsw = {
   64         /* open */      cttyopen,
   65         /* close */     nullclose,
   66         /* read */      cttyread,
   67         /* write */     cttywrite,
   68         /* ioctl */     cttyioctl,
   69         /* poll */      cttypoll,
   70         /* mmap */      nommap,
   71         /* strategy */  nostrategy,
   72         /* name */      "ctty",
   73         /* maj */       CDEV_MAJOR,
   74         /* dump */      nodump,
   75         /* psize */     nopsize,
   76         /* flags */     D_TTY,
   77 };
   78 
   79 #define cttyvp(td) ((td)->td_proc->p_flag & P_CONTROLT ? (td)->td_proc->p_session->s_ttyvp : NULL)
   80 
   81 /*ARGSUSED*/
   82 static  int
   83 cttyopen(dev, flag, mode, td)
   84         dev_t dev;
   85         int flag, mode;
   86         struct thread *td;
   87 {
   88         struct vnode *ttyvp;
   89         int error;
   90 
   91         PROC_LOCK(td->td_proc);
   92         SESS_LOCK(td->td_proc->p_session);
   93         ttyvp = cttyvp(td);
   94         SESS_UNLOCK(td->td_proc->p_session);
   95         PROC_UNLOCK(td->td_proc);
   96 
   97         if (ttyvp == NULL)
   98                 return (ENXIO);
   99         vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
  100 #ifdef MAC
  101         error = mac_check_vnode_open(td->td_ucred, ttyvp, flag);
  102         if (error) {
  103                 VOP_UNLOCK(ttyvp, 0, td);
  104                 return (error);
  105         }
  106 #endif
  107         /* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */
  108         error = VOP_OPEN(ttyvp, flag, NOCRED, td);
  109         VOP_UNLOCK(ttyvp, 0, td);
  110         return (error);
  111 }
  112 
  113 /*ARGSUSED*/
  114 static  int
  115 cttyread(dev, uio, flag)
  116         dev_t dev;
  117         struct uio *uio;
  118         int flag;
  119 {
  120         struct thread *td = uio->uio_td;
  121         register struct vnode *ttyvp;
  122         int error;
  123 
  124         PROC_LOCK(td->td_proc);
  125         SESS_LOCK(td->td_proc->p_session);
  126         ttyvp = cttyvp(td);
  127         SESS_UNLOCK(td->td_proc->p_session);
  128         PROC_UNLOCK(td->td_proc);
  129 
  130         if (ttyvp == NULL)
  131                 return (EIO);
  132         vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
  133 #ifdef MAC
  134         error = mac_check_vnode_read(td->td_ucred, NOCRED, ttyvp);
  135         if (error == 0)
  136 #endif
  137                 /* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */
  138                 error = VOP_READ(ttyvp, uio, flag, NOCRED);
  139         VOP_UNLOCK(ttyvp, 0, td);
  140         return (error);
  141 }
  142 
  143 /*ARGSUSED*/
  144 static  int
  145 cttywrite(dev, uio, flag)
  146         dev_t dev;
  147         struct uio *uio;
  148         int flag;
  149 {
  150         struct thread *td = uio->uio_td;
  151         struct vnode *ttyvp;
  152         struct mount *mp;
  153         int error;
  154 
  155         PROC_LOCK(td->td_proc);
  156         SESS_LOCK(td->td_proc->p_session);
  157         ttyvp = cttyvp(td);
  158         SESS_UNLOCK(td->td_proc->p_session);
  159         PROC_UNLOCK(td->td_proc);
  160 
  161         if (ttyvp == NULL)
  162                 return (EIO);
  163         mp = NULL;
  164         if (ttyvp->v_type != VCHR &&
  165             (error = vn_start_write(ttyvp, &mp, V_WAIT | PCATCH)) != 0)
  166                 return (error);
  167         vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
  168 #ifdef MAC
  169         error = mac_check_vnode_write(td->td_ucred, NOCRED, ttyvp);
  170         if (error == 0)
  171 #endif
  172                 /* XXX: shouldn't this cred be td->td_ucred not NOCRED? */
  173                 error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
  174         VOP_UNLOCK(ttyvp, 0, td);
  175         vn_finished_write(mp);
  176         return (error);
  177 }
  178 
  179 /*ARGSUSED*/
  180 static  int
  181 cttyioctl(dev, cmd, addr, flag, td)
  182         dev_t dev;
  183         u_long cmd;
  184         caddr_t addr;
  185         int flag;
  186         struct thread *td;
  187 {
  188         struct vnode *ttyvp;
  189         int error;
  190 
  191         PROC_LOCK(td->td_proc);
  192         SESS_LOCK(td->td_proc->p_session);
  193         ttyvp = cttyvp(td);
  194         SESS_UNLOCK(td->td_proc->p_session);
  195         PROC_UNLOCK(td->td_proc);
  196 
  197         if (ttyvp == NULL)
  198                 return (EIO);
  199         if (cmd == TIOCSCTTY)  /* don't allow controlling tty to be set    */
  200                 return EINVAL; /* to controlling tty -- infinite recursion */
  201         if (cmd == TIOCNOTTY) {
  202                 PROC_LOCK(td->td_proc);
  203                 SESS_LOCK(td->td_proc->p_session);
  204                 error = 0;
  205                 if (!SESS_LEADER(td->td_proc))
  206                         td->td_proc->p_flag &= ~P_CONTROLT;
  207                 else
  208                         error = EINVAL;
  209                 SESS_UNLOCK(td->td_proc->p_session);
  210                 PROC_UNLOCK(td->td_proc);
  211                 return (error);
  212         }
  213         /* XXXMAC: Should this be td->td_ucred below? */
  214         return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td));
  215 }
  216 
  217 /*ARGSUSED*/
  218 static  int
  219 cttypoll(dev, events, td)
  220         dev_t dev;
  221         int events;
  222         struct thread *td;
  223 {
  224         struct vnode *ttyvp;
  225 #ifdef MAC
  226         int error;
  227 #endif
  228 
  229         PROC_LOCK(td->td_proc);
  230         SESS_LOCK(td->td_proc->p_session);
  231         ttyvp = cttyvp(td);
  232         SESS_UNLOCK(td->td_proc->p_session);
  233         PROC_UNLOCK(td->td_proc);
  234 
  235         if (ttyvp == NULL)
  236                 /* try operation to get EOF/failure */
  237                 return (seltrue(dev, events, td));
  238 #ifdef MAC
  239         vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
  240         error = mac_check_vnode_poll(td->td_ucred, NOCRED, ttyvp);
  241         VOP_UNLOCK(ttyvp, 0, td);
  242         if (error)
  243                 return (error);
  244 #endif
  245         return (VOP_POLL(ttyvp, events, td->td_ucred, td));
  246 }
  247 
  248 static void ctty_clone(void *arg, char *name, int namelen, dev_t *dev);
  249 
  250 static dev_t ctty;
  251 
  252 static void
  253 ctty_clone(void *arg, char *name, int namelen, dev_t *dev)
  254 {
  255         struct vnode *vp;
  256 
  257         if (*dev != NODEV)
  258                 return;
  259         if (strcmp(name, "tty"))
  260                 return;
  261         vp = cttyvp(curthread);
  262         if (vp == NULL) {
  263                 if (ctty)
  264                         *dev = ctty;
  265         } else
  266                 *dev = vp->v_rdev;
  267 }
  268 
  269 
  270 static void ctty_drvinit(void *unused);
  271 static void
  272 ctty_drvinit(unused)
  273         void *unused;
  274 {
  275 
  276         if (devfs_present) {
  277                 EVENTHANDLER_REGISTER(dev_clone, ctty_clone, 0, 1000);
  278                 ctty = make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "ctty");
  279         } else {
  280                 make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty");
  281         }
  282 }
  283 
  284 SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)

Cache object: 8eae6d0be3cc0a78b40face877641364


[ 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.