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

Cache object: 923e9e56b9762640150c770ba599aa6a


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