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

Cache object: b61cd25876f600ce40e1537d429f31ce


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