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/dev/cons.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cons.c,v 1.52 2003/10/18 21:26:22 cdi Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1990, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * the Systems Programming Group of the University of Utah Computer
    9  * Science Department.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  * from: Utah $Hdr: cons.c 1.7 92/01/21$
   36  *
   37  *      @(#)cons.c      8.2 (Berkeley) 1/12/94
   38  */
   39 
   40 /*
   41  * Copyright (c) 1988 University of Utah.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * the Systems Programming Group of the University of Utah Computer
   45  * Science Department.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. All advertising materials mentioning features or use of this software
   56  *    must display the following acknowledgement:
   57  *      This product includes software developed by the University of
   58  *      California, Berkeley and its contributors.
   59  * 4. Neither the name of the University nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  *
   75  * from: Utah $Hdr: cons.c 1.7 92/01/21$
   76  *
   77  *      @(#)cons.c      8.2 (Berkeley) 1/12/94
   78  */
   79 
   80 #include <sys/cdefs.h>
   81 __KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.52 2003/10/18 21:26:22 cdi Exp $");
   82 
   83 #include <sys/param.h>
   84 #include <sys/proc.h>
   85 #include <sys/user.h>
   86 #include <sys/systm.h>
   87 #include <sys/buf.h>
   88 #include <sys/ioctl.h>
   89 #include <sys/tty.h>
   90 #include <sys/file.h>
   91 #include <sys/conf.h>
   92 #include <sys/vnode.h>
   93 
   94 #include <dev/cons.h>
   95 
   96 dev_type_open(cnopen);
   97 dev_type_close(cnclose);
   98 dev_type_read(cnread);
   99 dev_type_write(cnwrite);
  100 dev_type_ioctl(cnioctl);
  101 dev_type_poll(cnpoll);
  102 dev_type_kqfilter(cnkqfilter);
  103 
  104 static const struct cdevsw *cn_redirect(dev_t *, int, int *);
  105 
  106 const struct cdevsw cons_cdevsw = {
  107         cnopen, cnclose, cnread, cnwrite, cnioctl,
  108         nostop, notty, cnpoll, nommap, cnkqfilter, D_TTY
  109 };
  110 
  111 struct  tty *constty = NULL;    /* virtual console output device */
  112 struct  consdev *cn_tab;        /* physical console device info */
  113 struct  vnode *cn_devvp[2];     /* vnode for underlying device. */
  114 
  115 int
  116 cnopen(dev_t dev, int flag, int mode, struct proc *p)
  117 {
  118         const struct cdevsw *cdev;
  119         dev_t cndev;
  120         int unit;
  121 
  122         unit = minor(dev);
  123         if (unit > 1)
  124                 return ENODEV;
  125 
  126         if (cn_tab == NULL)
  127                 return (0);
  128 
  129         /*
  130          * always open the 'real' console device, so we don't get nailed
  131          * later.  This follows normal device semantics; they always get
  132          * open() calls.
  133          */
  134         cndev = cn_tab->cn_dev;
  135         if (cndev == NODEV) {
  136                 /*
  137                  * This is most likely an error in the console attach
  138                  * code. Panicing looks better than jumping into nowhere
  139                  * through cdevsw below....
  140                  */
  141                 panic("cnopen: no console device");
  142         }
  143         if (dev == cndev) {
  144                 /*
  145                  * This causes cnopen() to be called recursively, which
  146                  * is generally a bad thing.  It is often caused when
  147                  * dev == 0 and cn_dev has not been set, but was probably
  148                  * initialised to 0.
  149                  */
  150                 panic("cnopen: cn_tab->cn_dev == dev");
  151         }
  152         cdev = cdevsw_lookup(cndev);
  153         if (cdev == NULL)
  154                 return (ENXIO);
  155 
  156         if (cn_devvp[unit] == NULLVP) {
  157                 /* try to get a reference on its vnode, but fail silently */
  158                 cdevvp(cndev, &cn_devvp[unit]);
  159         }
  160         return ((*cdev->d_open)(cndev, flag, mode, p));
  161 }
  162  
  163 int
  164 cnclose(dev_t dev, int flag, int mode, struct proc *p)
  165 {
  166         const struct cdevsw *cdev;
  167         struct vnode *vp;
  168         int unit;
  169 
  170         unit = minor(dev);
  171 
  172         if (cn_tab == NULL)
  173                 return (0);
  174 
  175         /*
  176          * If the real console isn't otherwise open, close it.
  177          * If it's otherwise open, don't close it, because that'll
  178          * screw up others who have it open.
  179          */
  180         dev = cn_tab->cn_dev;
  181         cdev = cdevsw_lookup(dev);
  182         if (cdev == NULL)
  183                 return (ENXIO);
  184         if (cn_devvp[unit] != NULLVP) {
  185                 /* release our reference to real dev's vnode */
  186                 vrele(cn_devvp[unit]);
  187                 cn_devvp[unit] = NULLVP;
  188         }
  189         if (vfinddev(dev, VCHR, &vp) && vcount(vp))
  190                 return (0);
  191         return ((*cdev->d_close)(dev, flag, mode, p));
  192 }
  193  
  194 int
  195 cnread(dev_t dev, struct uio *uio, int flag)
  196 {
  197         const struct cdevsw *cdev;
  198         int error;
  199 
  200         /*
  201          * If we would redirect input, punt.  This will keep strange
  202          * things from happening to people who are using the real
  203          * console.  Nothing should be using /dev/console for
  204          * input (except a shell in single-user mode, but then,
  205          * one wouldn't TIOCCONS then).
  206          */
  207         cdev = cn_redirect(&dev, 1, &error);
  208         if (cdev == NULL)
  209                 return error;
  210         return ((*cdev->d_read)(dev, uio, flag));
  211 }
  212  
  213 int
  214 cnwrite(dev_t dev, struct uio *uio, int flag)
  215 {
  216         const struct cdevsw *cdev;
  217         int error;
  218 
  219         /* Redirect output, if that's appropriate. */
  220         cdev = cn_redirect(&dev, 0, &error);
  221         if (cdev == NULL)
  222                 return error;
  223 
  224         return ((*cdev->d_write)(dev, uio, flag));
  225 }
  226 
  227 int
  228 cnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  229 {
  230         const struct cdevsw *cdev;
  231         int error;
  232 
  233         /*
  234          * Superuser can always use this to wrest control of console
  235          * output from the "virtual" console.
  236          */
  237         if (cmd == TIOCCONS && constty != NULL) {
  238                 error = suser(p->p_ucred, (u_short *) NULL);
  239                 if (error)
  240                         return (error);
  241                 constty = NULL;
  242                 return (0);
  243         }
  244 
  245         /*
  246          * Redirect the ioctl, if that's appropriate.
  247          * Note that strange things can happen, if a program does
  248          * ioctls on /dev/console, then the console is redirected
  249          * out from under it.
  250          */
  251         cdev = cn_redirect(&dev, 0, &error);
  252         if (cdev == NULL)
  253                 return error;
  254         return ((*cdev->d_ioctl)(dev, cmd, data, flag, p));
  255 }
  256 
  257 /*ARGSUSED*/
  258 int
  259 cnpoll(dev_t dev, int events, struct proc *p)
  260 {
  261         const struct cdevsw *cdev;
  262         int error;
  263 
  264         /*
  265          * Redirect the poll, if that's appropriate.
  266          * I don't want to think of the possible side effects
  267          * of console redirection here.
  268          */
  269         cdev = cn_redirect(&dev, 0, &error);
  270         if (cdev == NULL)
  271                 return error;
  272         return ((*cdev->d_poll)(dev, events, p));
  273 }
  274 
  275 /*ARGSUSED*/
  276 int
  277 cnkqfilter(dev_t dev, struct knote *kn)
  278 {
  279         const struct cdevsw *cdev;
  280         int error;
  281 
  282         /*
  283          * Redirect the kqfilter, if that's appropriate.
  284          * I don't want to think of the possible side effects
  285          * of console redirection here.
  286          */
  287         cdev = cn_redirect(&dev, 0, &error);
  288         if (cdev == NULL)
  289                 return error;
  290         return ((*cdev->d_kqfilter)(dev, kn));
  291 }
  292 
  293 int
  294 cngetc(void)
  295 {
  296         if (cn_tab == NULL)
  297                 return (0);
  298         return ((*cn_tab->cn_getc)(cn_tab->cn_dev));
  299 }
  300 
  301 int
  302 cngetsn(char *cp, int size)
  303 {
  304         char *lp;
  305         int c, len;
  306 
  307         cnpollc(1);
  308 
  309         lp = cp;
  310         len = 0;
  311         for (;;) {
  312                 c = cngetc();
  313                 switch (c) {
  314                 case '\n':
  315                 case '\r':
  316                         printf("\n");
  317                         *lp++ = '\0';
  318                         cnpollc(0);
  319                         return (len);
  320                 case '\b':
  321                 case '\177':
  322                 case '#':
  323                         if (len) {
  324                                 --len;
  325                                 --lp;
  326                                 printf("\b \b");
  327                         }
  328                         continue;
  329                 case '@':
  330                 case 'u'&037:   /* CTRL-u */
  331                         len = 0;
  332                         lp = cp;
  333                         printf("\n");
  334                         continue;
  335                 default:
  336                         if (len + 1 >= size || c < ' ') {
  337                                 printf("\007");
  338                                 continue;
  339                         }
  340                         printf("%c", c);
  341                         ++len;
  342                         *lp++ = c;
  343                 }
  344         }
  345 }
  346 
  347 void
  348 cnputc(int c)
  349 {
  350 
  351         if (cn_tab == NULL)
  352                 return;                 
  353 
  354         if (c) {
  355                 (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
  356                 if (c == '\n')
  357                         (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
  358         }
  359 }
  360 
  361 void
  362 cnpollc(int on)
  363 {
  364         static int refcount = 0;
  365 
  366         if (cn_tab == NULL)
  367                 return;
  368         if (!on)
  369                 --refcount;
  370         if (refcount == 0)
  371                 (*cn_tab->cn_pollc)(cn_tab->cn_dev, on);
  372         if (on)
  373                 ++refcount;
  374 }
  375 
  376 void
  377 nullcnpollc(dev_t dev, int on)
  378 {
  379 
  380 }
  381 
  382 void
  383 cnbell(u_int pitch, u_int period, u_int volume)
  384 {
  385 
  386         if (cn_tab == NULL || cn_tab->cn_bell == NULL)
  387                 return;
  388         (*cn_tab->cn_bell)(cn_tab->cn_dev, pitch, period, volume);
  389 }
  390 
  391 void
  392 cnflush(void)
  393 {
  394         if (cn_tab == NULL || cn_tab->cn_flush == NULL)
  395                 return;
  396         (*cn_tab->cn_flush)(cn_tab->cn_dev);
  397 }
  398   
  399 void
  400 cnhalt(void)
  401 {
  402         if (cn_tab == NULL || cn_tab->cn_halt == NULL)
  403                 return;
  404         (*cn_tab->cn_halt)(cn_tab->cn_dev);
  405 }
  406 
  407 static const struct cdevsw *
  408 cn_redirect(dev_t *devp, int is_read, int *error)
  409 {
  410         dev_t dev = *devp;
  411 
  412         /*
  413          * Redirect output, if that's appropriate.
  414          * If there's no real console, return ENXIO.
  415          */
  416         *error = ENXIO;
  417         if (constty != NULL && minor(dev) == 0 &&
  418             (cn_tab == NULL || (cn_tab->cn_pri != CN_REMOTE ))) {
  419                 if (is_read) {
  420                         *error = 0;
  421                         return NULL;
  422                 }
  423                 dev = constty->t_dev;
  424         } else if (cn_tab == NULL)
  425                 return NULL;
  426         else
  427                 dev = cn_tab->cn_dev;
  428         *devp = dev;
  429         return cdevsw_lookup(dev);
  430 }

Cache object: 1d8828bfffb40d946bcfe1f5c5e671bb


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