LCOV - code coverage report
Current view: top level - kern - tty_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 234 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13