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_subr.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 /*      $NetBSD: tty_subr.c,v 1.34.4.1 2009/11/27 09:15:27 sborrill Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1993, 1994 Theo de Raadt
    5  * All rights reserved.
    6  *
    7  * Per Lindqvist <pgd@compuram.bbt.se> supplied an almost fully working
    8  * set of true clist functions that this is very loosely based on.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __KERNEL_RCSID(0, "$NetBSD: tty_subr.c,v 1.34.4.1 2009/11/27 09:15:27 sborrill Exp $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/buf.h>
   37 #include <sys/ioctl.h>
   38 #include <sys/tty.h>
   39 #include <sys/malloc.h>
   40 
   41 MALLOC_DEFINE(M_TTYS, "ttys", "allocated tty structures");
   42 
   43 /*
   44  * At compile time, choose:
   45  * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
   46  * defined we allocate an array of bits -- 1/8th as much memory but
   47  * setbit(), clrbit(), and isset() take more CPU. If QBITS is
   48  * undefined, we just use an array of bytes.
   49  *
   50  * If TTY_QUOTE functionality isn't required by a line discipline,
   51  * it can free c_cq and set it to NULL. This speeds things up,
   52  * and also does not use any extra memory. This is useful for (say)
   53  * a SLIP line discipline that wants a 32K ring buffer for data
   54  * but doesn't need quoting.
   55  */
   56 #define QBITS
   57 
   58 #ifdef QBITS
   59 #define QMEM(n)         ((((n)-1)/NBBY)+1)
   60 #else
   61 #define QMEM(n)         (n)
   62 #endif
   63 
   64 #ifdef QBITS
   65 static void     clrbits(u_char *, int, int);
   66 #endif
   67 
   68 /*
   69  * Initialize a particular clist. Ok, they are really ring buffers,
   70  * of the specified length, with/without quoting support.
   71  */
   72 int
   73 clalloc(struct clist *clp, int size, int quot)
   74 {
   75 
   76         clp->c_cs = malloc(size, M_TTYS, M_WAITOK);
   77         if (!clp->c_cs)
   78                 return (-1);
   79         memset(clp->c_cs, 0, size);
   80 
   81         if(quot) {
   82                 clp->c_cq = malloc(QMEM(size), M_TTYS, M_WAITOK);
   83                 if (!clp->c_cq) {
   84                         free(clp->c_cs, M_TTYS);
   85                         return (-1);
   86                 }
   87                 memset(clp->c_cq, 0, QMEM(size));
   88         } else
   89                 clp->c_cq = (u_char *)0;
   90 
   91         clp->c_cf = clp->c_cl = (u_char *)0;
   92         clp->c_ce = clp->c_cs + size;
   93         clp->c_cn = size;
   94         clp->c_cc = 0;
   95 
   96         return (0);
   97 }
   98 
   99 void
  100 clfree(struct clist *clp)
  101 {
  102         if(clp->c_cs)
  103                 free(clp->c_cs, M_TTYS);
  104         if(clp->c_cq)
  105                 free(clp->c_cq, M_TTYS);
  106         clp->c_cs = clp->c_cq = (u_char *)0;
  107 }
  108 
  109 /*
  110  * Get a character from a clist.
  111  */
  112 int
  113 getc(struct clist *clp)
  114 {
  115         int c = -1;
  116         int s;
  117 
  118         s = spltty();
  119         if (clp->c_cc == 0)
  120                 goto out;
  121 
  122         c = *clp->c_cf & 0xff;
  123         if (clp->c_cq) {
  124 #ifdef QBITS
  125                 if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
  126                         c |= TTY_QUOTE;
  127 #else
  128                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  129                         c |= TTY_QUOTE;
  130 #endif
  131         }
  132         *clp->c_cf = 0; /* wipe out to avoid information disclosure */
  133         if (++clp->c_cf == clp->c_ce)
  134                 clp->c_cf = clp->c_cs;
  135         if (--clp->c_cc == 0)
  136                 clp->c_cf = clp->c_cl = (u_char *)0;
  137 out:
  138         splx(s);
  139         return c;
  140 }
  141 
  142 /*
  143  * Copy clist to buffer.
  144  * Return number of bytes moved.
  145  */
  146 int
  147 q_to_b(struct clist *clp, u_char *cp, int count)
  148 {
  149         int cc;
  150         u_char *p = cp;
  151         int s;
  152 
  153         s = spltty();
  154         /* optimize this while loop */
  155         while (count > 0 && clp->c_cc > 0) {
  156                 cc = clp->c_cl - clp->c_cf;
  157                 if (clp->c_cf >= clp->c_cl)
  158                         cc = clp->c_ce - clp->c_cf;
  159                 if (cc > count)
  160                         cc = count;
  161                 memcpy(p, clp->c_cf, cc);
  162                 count -= cc;
  163                 p += cc;
  164                 clp->c_cc -= cc;
  165                 clp->c_cf += cc;
  166                 if (clp->c_cf == clp->c_ce)
  167                         clp->c_cf = clp->c_cs;
  168         }
  169         if (clp->c_cc == 0)
  170                 clp->c_cf = clp->c_cl = (u_char *)0;
  171         splx(s);
  172         return p - cp;
  173 }
  174 
  175 /*
  176  * Return count of contiguous characters in clist.
  177  * Stop counting if flag&character is non-null.
  178  */
  179 int
  180 ndqb(struct clist *clp, int flag)
  181 {
  182         int count = 0;
  183         int i;
  184         int cc;
  185         int s;
  186 
  187         s = spltty();
  188         if ((cc = clp->c_cc) == 0)
  189                 goto out;
  190 
  191         if (flag == 0) {
  192                 count = clp->c_cl - clp->c_cf;
  193                 if (count <= 0)
  194                         count = clp->c_ce - clp->c_cf;
  195                 goto out;
  196         }
  197 
  198         i = clp->c_cf - clp->c_cs;
  199         if (flag & TTY_QUOTE) {
  200                 while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
  201                     isset(clp->c_cq, i))) {
  202                         count++;
  203                         if (i == clp->c_cn)
  204                                 break;
  205                 }
  206         } else {
  207                 while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
  208                         count++;
  209                         if (i == clp->c_cn)
  210                                 break;
  211                 }
  212         }
  213 out:
  214         splx(s);
  215         return count;
  216 }
  217 
  218 /*
  219  * Flush count bytes from clist.
  220  */
  221 void
  222 ndflush(struct clist *clp, int count)
  223 {
  224         int cc;
  225         int s;
  226 
  227         s = spltty();
  228         if (count == clp->c_cc) {
  229                 clp->c_cc = 0;
  230                 clp->c_cf = clp->c_cl = (u_char *)0;
  231                 goto out;
  232         }
  233         /* optimize this while loop */
  234         while (count > 0 && clp->c_cc > 0) {
  235                 cc = clp->c_cl - clp->c_cf;
  236                 if (clp->c_cf >= clp->c_cl)
  237                         cc = clp->c_ce - clp->c_cf;
  238                 if (cc > count)
  239                         cc = count;
  240                 count -= cc;
  241                 clp->c_cc -= cc;
  242                 clp->c_cf += cc;
  243                 if (clp->c_cf == clp->c_ce)
  244                         clp->c_cf = clp->c_cs;
  245         }
  246         if (clp->c_cc == 0)
  247                 clp->c_cf = clp->c_cl = (u_char *)0;
  248 out:
  249         splx(s);
  250 }
  251 
  252 /*
  253  * Put a character into the output queue.
  254  */
  255 int
  256 putc(int c, struct clist *clp)
  257 {
  258         int i;
  259         int s;
  260 
  261         s = spltty();
  262         if (clp->c_cc == clp->c_cn)
  263                 goto out;
  264 
  265         if (clp->c_cc == 0) {
  266                 if (!clp->c_cs) {
  267 #if defined(DIAGNOSTIC) || 1
  268                         printf("putc: required clalloc\n");
  269 #endif
  270                         if(clalloc(clp, 1024, 1)) {
  271 out:
  272                                 splx(s);
  273                                 return -1;
  274                         }
  275                 }
  276                 clp->c_cf = clp->c_cl = clp->c_cs;
  277         }
  278 
  279         *clp->c_cl = c & 0xff;
  280         i = clp->c_cl - clp->c_cs;
  281         if (clp->c_cq) {
  282 #ifdef QBITS
  283                 if (c & TTY_QUOTE)
  284                         setbit(clp->c_cq, i);
  285                 else
  286                         clrbit(clp->c_cq, i);
  287 #else
  288                 q = clp->c_cq + i;
  289                 *q = (c & TTY_QUOTE) ? 1 : 0;
  290 #endif
  291         }
  292         clp->c_cc++;
  293         clp->c_cl++;
  294         if (clp->c_cl == clp->c_ce)
  295                 clp->c_cl = clp->c_cs;
  296         splx(s);
  297         return 0;
  298 }
  299 
  300 #ifdef QBITS
  301 /*
  302  * optimized version of
  303  *
  304  * for (i = 0; i < len; i++)
  305  *      clrbit(cp, off + len);
  306  */
  307 static void
  308 clrbits(u_char *cp, int off, int len)
  309 {
  310         int sby, sbi, eby, ebi;
  311         int i;
  312         u_char mask;
  313 
  314         if(len==1) {
  315                 clrbit(cp, off);
  316                 return;
  317         }
  318 
  319         len--;
  320         sby = off / NBBY;
  321         sbi = off % NBBY;
  322         eby = (off+len) / NBBY;
  323         ebi = (off+len) % NBBY + 1;
  324         if (sby == eby) {
  325                 mask = ((1 << (ebi - sbi)) - 1) << sbi;
  326                 cp[sby] &= ~mask;
  327         } else {
  328                 mask = (1<<sbi) - 1;
  329                 cp[sby++] &= mask;
  330 
  331                 mask = (1<<ebi) - 1;
  332                 cp[eby] &= ~mask;
  333 
  334                 for (i = sby; i < eby; i++)
  335                         cp[i] = 0x00;
  336         }
  337 }
  338 #endif
  339 
  340 /*
  341  * Copy buffer to clist.
  342  * Return number of bytes not transfered.
  343  */
  344 int
  345 b_to_q(const u_char *cp, int count, struct clist *clp)
  346 {
  347         int cc;
  348         const u_char *p = cp;
  349         int s;
  350 
  351         if (count <= 0)
  352                 return 0;
  353 
  354         s = spltty();
  355         if (clp->c_cc == clp->c_cn)
  356                 goto out;
  357 
  358         if (clp->c_cc == 0) {
  359                 if (!clp->c_cs) {
  360 #if defined(DIAGNOSTIC) || 1
  361                         printf("b_to_q: required clalloc\n");
  362 #endif
  363                         if(clalloc(clp, 1024, 1))
  364                                 goto out;
  365                 }
  366                 clp->c_cf = clp->c_cl = clp->c_cs;
  367         }
  368 
  369         /* optimize this while loop */
  370         while (count > 0 && clp->c_cc < clp->c_cn) {
  371                 cc = clp->c_ce - clp->c_cl;
  372                 if (clp->c_cf > clp->c_cl)
  373                         cc = clp->c_cf - clp->c_cl;
  374                 if (cc > count)
  375                         cc = count;
  376                 memcpy(clp->c_cl, p, cc);
  377                 if (clp->c_cq) {
  378 #ifdef QBITS
  379                         clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
  380 #else
  381                         memset(clp->c_cl - clp->c_cs + clp->c_cq, 0, cc);
  382 #endif
  383                 }
  384                 p += cc;
  385                 count -= cc;
  386                 clp->c_cc += cc;
  387                 clp->c_cl += cc;
  388                 if (clp->c_cl == clp->c_ce)
  389                         clp->c_cl = clp->c_cs;
  390         }
  391 out:
  392         splx(s);
  393         return count;
  394 }
  395 
  396 static int cc;
  397 
  398 /*
  399  * Given a non-NULL pointer into the clist return the pointer
  400  * to the next character in the list or return NULL if no more chars.
  401  *
  402  * Callers must not allow getc's to happen between firstc's and getc's
  403  * so that the pointer becomes invalid.  Note that interrupts are NOT
  404  * masked.
  405  */
  406 u_char *
  407 nextc(struct clist *clp, u_char *cp, int *c)
  408 {
  409 
  410         if (clp->c_cf == cp) {
  411                 /*
  412                  * First time initialization.
  413                  */
  414                 cc = clp->c_cc;
  415         }
  416         if (cc == 0 || cp == NULL)
  417                 return NULL;
  418         if (--cc == 0)
  419                 return NULL;
  420         if (++cp == clp->c_ce)
  421                 cp = clp->c_cs;
  422         *c = *cp & 0xff;
  423         if (clp->c_cq) {
  424 #ifdef QBITS
  425                 if (isset(clp->c_cq, cp - clp->c_cs))
  426                         *c |= TTY_QUOTE;
  427 #else
  428                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  429                         *c |= TTY_QUOTE;
  430 #endif
  431         }
  432         return cp;
  433 }
  434 
  435 /*
  436  * Given a non-NULL pointer into the clist return the pointer
  437  * to the first character in the list or return NULL if no more chars.
  438  *
  439  * Callers must not allow getc's to happen between firstc's and getc's
  440  * so that the pointer becomes invalid.  Note that interrupts are NOT
  441  * masked.
  442  *
  443  * *c is set to the NEXT character
  444  */
  445 u_char *
  446 firstc(struct clist *clp, int *c)
  447 {
  448         u_char *cp;
  449 
  450         cc = clp->c_cc;
  451         if (cc == 0)
  452                 return NULL;
  453         cp = clp->c_cf;
  454         *c = *cp & 0xff;
  455         if(clp->c_cq) {
  456 #ifdef QBITS
  457                 if (isset(clp->c_cq, cp - clp->c_cs))
  458                         *c |= TTY_QUOTE;
  459 #else
  460                 if (*(cp - clp->c_cs + clp->c_cq))
  461                         *c |= TTY_QUOTE;
  462 #endif
  463         }
  464         return clp->c_cf;
  465 }
  466 
  467 /*
  468  * Remove the last character in the clist and return it.
  469  */
  470 int
  471 unputc(struct clist *clp)
  472 {
  473         unsigned int c = -1;
  474         int s;
  475 
  476         s = spltty();
  477         if (clp->c_cc == 0)
  478                 goto out;
  479 
  480         if (clp->c_cl == clp->c_cs)
  481                 clp->c_cl = clp->c_ce - 1;
  482         else
  483                 --clp->c_cl;
  484         clp->c_cc--;
  485 
  486         c = *clp->c_cl & 0xff;
  487         if (clp->c_cq) {
  488 #ifdef QBITS
  489                 if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
  490                         c |= TTY_QUOTE;
  491 #else
  492                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  493                         c |= TTY_QUOTE;
  494 #endif
  495         }
  496         if (clp->c_cc == 0)
  497                 clp->c_cf = clp->c_cl = (u_char *)0;
  498 out:
  499         splx(s);
  500         return c;
  501 }
  502 
  503 /*
  504  * Put the chars in the from queue on the end of the to queue.
  505  */
  506 void
  507 catq(struct clist *from, struct clist *to)
  508 {
  509         int c;
  510 
  511         while ((c = getc(from)) != -1)
  512                 putc(c, to);
  513 }

Cache object: aa5b8a90130424f4a0c7b842abdbf976


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