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.27 2004/03/23 13:22:05 junyoung 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.27 2004/03/23 13:22:05 junyoung 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 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(clp, size, quot)
   74         struct clist *clp;
   75         int size;
   76         int quot;
   77 {
   78 
   79         clp->c_cs = malloc(size, M_TTYS, M_WAITOK);
   80         if (!clp->c_cs)
   81                 return (-1);
   82         memset(clp->c_cs, 0, size);
   83 
   84         if(quot) {
   85                 clp->c_cq = malloc(QMEM(size), M_TTYS, M_WAITOK);
   86                 if (!clp->c_cq) {
   87                         free(clp->c_cs, M_TTYS);
   88                         return (-1);
   89                 }
   90                 memset(clp->c_cq, 0, QMEM(size));
   91         } else
   92                 clp->c_cq = (u_char *)0;
   93 
   94         clp->c_cf = clp->c_cl = (u_char *)0;
   95         clp->c_ce = clp->c_cs + size;
   96         clp->c_cn = size;
   97         clp->c_cc = 0;
   98         return (0);
   99 }
  100 
  101 void
  102 clfree(clp)
  103         struct clist *clp;
  104 {
  105         if(clp->c_cs)
  106                 free(clp->c_cs, M_TTYS);
  107         if(clp->c_cq)
  108                 free(clp->c_cq, M_TTYS);
  109         clp->c_cs = clp->c_cq = (u_char *)0;
  110 }
  111 
  112 
  113 /*
  114  * Get a character from a clist.
  115  */
  116 int
  117 getc(clp)
  118         struct clist *clp;
  119 {
  120         int c = -1;
  121         int s;
  122 
  123         s = spltty();
  124         if (clp->c_cc == 0)
  125                 goto out;
  126 
  127         c = *clp->c_cf & 0xff;
  128         if (clp->c_cq) {
  129 #ifdef QBITS
  130                 if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
  131                         c |= TTY_QUOTE;
  132 #else
  133                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  134                         c |= TTY_QUOTE;
  135 #endif
  136         }
  137         if (++clp->c_cf == clp->c_ce)
  138                 clp->c_cf = clp->c_cs;
  139         if (--clp->c_cc == 0)
  140                 clp->c_cf = clp->c_cl = (u_char *)0;
  141 out:
  142         splx(s);
  143         return c;
  144 }
  145 
  146 /*
  147  * Copy clist to buffer.
  148  * Return number of bytes moved.
  149  */
  150 int
  151 q_to_b(clp, cp, count)
  152         struct clist *clp;
  153         u_char *cp;
  154         int count;
  155 {
  156         int cc;
  157         u_char *p = cp;
  158         int s;
  159 
  160         s = spltty();
  161         /* optimize this while loop */
  162         while (count > 0 && clp->c_cc > 0) {
  163                 cc = clp->c_cl - clp->c_cf;
  164                 if (clp->c_cf >= clp->c_cl)
  165                         cc = clp->c_ce - clp->c_cf;
  166                 if (cc > count)
  167                         cc = count;
  168                 memcpy(p, clp->c_cf, cc);
  169                 count -= cc;
  170                 p += cc;
  171                 clp->c_cc -= cc;
  172                 clp->c_cf += cc;
  173                 if (clp->c_cf == clp->c_ce)
  174                         clp->c_cf = clp->c_cs;
  175         }
  176         if (clp->c_cc == 0)
  177                 clp->c_cf = clp->c_cl = (u_char *)0;
  178         splx(s);
  179         return p - cp;
  180 }
  181 
  182 /*
  183  * Return count of contiguous characters in clist.
  184  * Stop counting if flag&character is non-null.
  185  */
  186 int
  187 ndqb(clp, flag)
  188         struct clist *clp;
  189         int flag;
  190 {
  191         int count = 0;
  192         int i;
  193         int cc;
  194         int s;
  195 
  196         s = spltty();
  197         if ((cc = clp->c_cc) == 0)
  198                 goto out;
  199 
  200         if (flag == 0) {
  201                 count = clp->c_cl - clp->c_cf;
  202                 if (count <= 0)
  203                         count = clp->c_ce - clp->c_cf;
  204                 goto out;
  205         }
  206 
  207         i = clp->c_cf - clp->c_cs;
  208         if (flag & TTY_QUOTE) {
  209                 while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
  210                     isset(clp->c_cq, i))) {
  211                         count++;
  212                         if (i == clp->c_cn)
  213                                 break;
  214                 }
  215         } else {
  216                 while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
  217                         count++;
  218                         if (i == clp->c_cn)
  219                                 break;
  220                 }
  221         }
  222 out:
  223         splx(s);
  224         return count;
  225 }
  226 
  227 /*
  228  * Flush count bytes from clist.
  229  */
  230 void
  231 ndflush(clp, count)
  232         struct clist *clp;
  233         int count;
  234 {
  235         int cc;
  236         int s;
  237 
  238         s = spltty();
  239         if (count == clp->c_cc) {
  240                 clp->c_cc = 0;
  241                 clp->c_cf = clp->c_cl = (u_char *)0;
  242                 goto out;
  243         }
  244         /* optimize this while loop */
  245         while (count > 0 && clp->c_cc > 0) {
  246                 cc = clp->c_cl - clp->c_cf;
  247                 if (clp->c_cf >= clp->c_cl)
  248                         cc = clp->c_ce - clp->c_cf;
  249                 if (cc > count)
  250                         cc = count;
  251                 count -= cc;
  252                 clp->c_cc -= cc;
  253                 clp->c_cf += cc;
  254                 if (clp->c_cf == clp->c_ce)
  255                         clp->c_cf = clp->c_cs;
  256         }
  257         if (clp->c_cc == 0)
  258                 clp->c_cf = clp->c_cl = (u_char *)0;
  259 out:
  260         splx(s);
  261 }
  262 
  263 /*
  264  * Put a character into the output queue.
  265  */
  266 int
  267 putc(c, clp)
  268         int c;
  269         struct clist *clp;
  270 {
  271         int i;
  272         int s;
  273 
  274         s = spltty();
  275         if (clp->c_cc == clp->c_cn)
  276                 goto out;
  277 
  278         if (clp->c_cc == 0) {
  279                 if (!clp->c_cs) {
  280 #if defined(DIAGNOSTIC) || 1
  281                         printf("putc: required clalloc\n");
  282 #endif
  283                         if(clalloc(clp, 1024, 1)) {
  284 out:
  285                                 splx(s);
  286                                 return -1;
  287                         }
  288                 }
  289                 clp->c_cf = clp->c_cl = clp->c_cs;
  290         }
  291 
  292         *clp->c_cl = c & 0xff;
  293         i = clp->c_cl - clp->c_cs;
  294         if (clp->c_cq) {
  295 #ifdef QBITS
  296                 if (c & TTY_QUOTE)
  297                         setbit(clp->c_cq, i); 
  298                 else
  299                         clrbit(clp->c_cq, i);
  300 #else
  301                 q = clp->c_cq + i;
  302                 *q = (c & TTY_QUOTE) ? 1 : 0;
  303 #endif
  304         }
  305         clp->c_cc++;
  306         clp->c_cl++;
  307         if (clp->c_cl == clp->c_ce)
  308                 clp->c_cl = clp->c_cs;
  309         splx(s);
  310         return 0;
  311 }
  312 
  313 #ifdef QBITS
  314 /*
  315  * optimized version of
  316  *
  317  * for (i = 0; i < len; i++)
  318  *      clrbit(cp, off + len);
  319  */
  320 void
  321 clrbits(cp, off, len)
  322         u_char *cp;
  323         int off;
  324         int len;
  325 {
  326         int sby, sbi, eby, ebi;
  327         int i;
  328         u_char mask;
  329 
  330         if(len==1) {
  331                 clrbit(cp, off);
  332                 return;
  333         }
  334 
  335         sby = off / NBBY;
  336         sbi = off % NBBY;
  337         eby = (off+len) / NBBY;
  338         ebi = (off+len) % NBBY;
  339         if (sby == eby) {
  340                 mask = ((1 << (ebi - sbi)) - 1) << sbi;
  341                 cp[sby] &= ~mask;
  342         } else {
  343                 mask = (1<<sbi) - 1;
  344                 cp[sby++] &= mask;
  345 
  346                 mask = (1<<ebi) - 1;
  347                 cp[eby] &= ~mask;
  348 
  349                 for (i = sby; i < eby; i++)
  350                         cp[i] = 0x00;
  351         }
  352 }
  353 #endif
  354 
  355 /*
  356  * Copy buffer to clist.
  357  * Return number of bytes not transfered.
  358  */
  359 int
  360 b_to_q(cp, count, clp)
  361         const u_char *cp;
  362         int count;
  363         struct clist *clp;
  364 {
  365         int cc;
  366         const u_char *p = cp;
  367         int s;
  368 
  369         if (count <= 0)
  370                 return 0;
  371 
  372         s = spltty();
  373         if (clp->c_cc == clp->c_cn)
  374                 goto out;
  375 
  376         if (clp->c_cc == 0) {
  377                 if (!clp->c_cs) {
  378 #if defined(DIAGNOSTIC) || 1
  379                         printf("b_to_q: required clalloc\n");
  380 #endif
  381                         if(clalloc(clp, 1024, 1))
  382                                 goto out;
  383                 }
  384                 clp->c_cf = clp->c_cl = clp->c_cs;
  385         }
  386 
  387         /* optimize this while loop */
  388         while (count > 0 && clp->c_cc < clp->c_cn) {
  389                 cc = clp->c_ce - clp->c_cl;
  390                 if (clp->c_cf > clp->c_cl)
  391                         cc = clp->c_cf - clp->c_cl;
  392                 if (cc > count)
  393                         cc = count;
  394                 memcpy(clp->c_cl, p, cc);
  395                 if (clp->c_cq) {
  396 #ifdef QBITS
  397                         clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
  398 #else
  399                         memset(clp->c_cl - clp->c_cs + clp->c_cq, 0, cc);
  400 #endif
  401                 }
  402                 p += cc;
  403                 count -= cc;
  404                 clp->c_cc += cc;
  405                 clp->c_cl += cc;
  406                 if (clp->c_cl == clp->c_ce)
  407                         clp->c_cl = clp->c_cs;
  408         }
  409 out:
  410         splx(s);
  411         return count;
  412 }
  413 
  414 static int cc;
  415 
  416 /*
  417  * Given a non-NULL pointer into the clist return the pointer
  418  * to the next character in the list or return NULL if no more chars.
  419  *
  420  * Callers must not allow getc's to happen between firstc's and getc's
  421  * so that the pointer becomes invalid.  Note that interrupts are NOT
  422  * masked.
  423  */
  424 u_char *
  425 nextc(clp, cp, c)
  426         struct clist *clp;
  427         u_char *cp;
  428         int *c;
  429 {
  430 
  431         if (clp->c_cf == cp) {
  432                 /*
  433                  * First time initialization.
  434                  */
  435                 cc = clp->c_cc;
  436         }
  437         if (cc == 0 || cp == NULL)
  438                 return NULL;
  439         if (--cc == 0)
  440                 return NULL;
  441         if (++cp == clp->c_ce)
  442                 cp = clp->c_cs;
  443         *c = *cp & 0xff;
  444         if (clp->c_cq) {
  445 #ifdef QBITS
  446                 if (isset(clp->c_cq, cp - clp->c_cs))
  447                         *c |= TTY_QUOTE;
  448 #else
  449                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  450                         *c |= TTY_QUOTE;
  451 #endif
  452         }
  453         return cp;
  454 }
  455 
  456 /*
  457  * Given a non-NULL pointer into the clist return the pointer
  458  * to the first character in the list or return NULL if no more chars.
  459  *
  460  * Callers must not allow getc's to happen between firstc's and getc's
  461  * so that the pointer becomes invalid.  Note that interrupts are NOT
  462  * masked.
  463  *
  464  * *c is set to the NEXT character
  465  */
  466 u_char *
  467 firstc(clp, c)
  468         struct clist *clp;
  469         int *c;
  470 {
  471         u_char *cp;
  472 
  473         cc = clp->c_cc;
  474         if (cc == 0)
  475                 return NULL;
  476         cp = clp->c_cf;
  477         *c = *cp & 0xff;
  478         if(clp->c_cq) {
  479 #ifdef QBITS
  480                 if (isset(clp->c_cq, cp - clp->c_cs))
  481                         *c |= TTY_QUOTE;
  482 #else
  483                 if (*(cp - clp->c_cs + clp->c_cq))
  484                         *c |= TTY_QUOTE;
  485 #endif
  486         }
  487         return clp->c_cf;
  488 }
  489 
  490 /*
  491  * Remove the last character in the clist and return it.
  492  */
  493 int
  494 unputc(clp)
  495         struct clist *clp;
  496 {
  497         unsigned int c = -1;
  498         int s;
  499 
  500         s = spltty();
  501         if (clp->c_cc == 0)
  502                 goto out;
  503 
  504         if (clp->c_cl == clp->c_cs)
  505                 clp->c_cl = clp->c_ce - 1;
  506         else
  507                 --clp->c_cl;
  508         clp->c_cc--;
  509 
  510         c = *clp->c_cl & 0xff;
  511         if (clp->c_cq) {
  512 #ifdef QBITS
  513                 if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
  514                         c |= TTY_QUOTE;
  515 #else
  516                 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
  517                         c |= TTY_QUOTE;
  518 #endif
  519         }
  520         if (clp->c_cc == 0)
  521                 clp->c_cf = clp->c_cl = (u_char *)0;
  522 out:
  523         splx(s);
  524         return c;
  525 }
  526 
  527 /*
  528  * Put the chars in the from queue on the end of the to queue.
  529  */
  530 void
  531 catq(from, to)
  532         struct clist *from, *to;
  533 {
  534         int c;
  535 
  536         while ((c = getc(from)) != -1)
  537                 putc(c, to);
  538 }

Cache object: c328d4fe99e9b2ab3255d7af3bbac7f6


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