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

Cache object: 5c7f009af4cd5093318a4531cc13f580


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