]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/tty_subr.c
   2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */ 
  30  * Copyright (c) 1993, 1994 Theo de Raadt 
  31  * All rights reserved. 
  33  * Redistribution and use in source and binary forms, with or without 
  34  * modification, are permitted provided that the following conditions 
  36  * 1. Redistributions of source code must retain the above copyright 
  37  *    notice unmodified, this list of conditions, and the following 
  39  * 2. Redistributions in binary form must reproduce the above copyright 
  40  *    notice, this list of conditions and the following disclaimer in the 
  41  *    documentation and/or other materials provided with the distribution. 
  43  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
  44  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
  47  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  49  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  50  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  52  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  59  * We use the NetBSD based clist system, it is much more efficient than the 
  60  * old style clist stuff used by free bsd. 
  63 #include <sys/param.h> 
  64 #include <sys/systm.h> 
  65 #include <sys/ioctl.h> 
  67 #include <sys/malloc.h> 
  69 #include <machine/spl.h> 
  72  * At compile time, choose: 
  73  * There are two ways the TTY_QUOTE bit can be stored. If QBITS is 
  74  * defined we allocate an array of bits -- 1/8th as much memory but 
  75  * setbit(), clrbit(), and isset() take more cpu. If QBITS is 
  76  * undefined, we just use an array of bytes. 
  78  * If TTY_QUOTE functionality isn't required by a line discipline, 
  79  * it can free c_cq and set it to NULL. This speeds things up, 
  80  * and also does not use any extra memory. This is useful for (say) 
  81  * a SLIP line discipline that wants a 32K ring buffer for data 
  82  * but doesn't need quoting. 
  87 #define QMEM(n)         ((((n)-1)/NBBY)+1) 
 102  * Initialize a particular clist. Ok, they are really ring buffers, 
 103  * of the specified length, with/without quoting support. 
 106 clalloc(clp
, size
, quot
) 
 112         MALLOC_ZONE(clp
->c_cs
, u_char 
*, size
, M_TTYS
, M_WAITOK
); 
 115         bzero(clp
->c_cs
, size
); 
 118                 MALLOC_ZONE(clp
->c_cq
, u_char 
*, QMEM(size
), M_TTYS
, M_WAITOK
); 
 120                         FREE_ZONE(clp
->c_cs
, size
, M_TTYS
); 
 123                 bzero(clp
->c_cs
, QMEM(size
)); 
 125                 clp
->c_cq 
= (u_char 
*)0; 
 127         clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 128         clp
->c_ce 
= clp
->c_cs 
+ size
; 
 139                 FREE_ZONE(clp
->c_cs
, clp
->c_cn
, M_TTYS
); 
 141                 FREE_ZONE(clp
->c_cq
, QMEM(clp
->c_cn
), M_TTYS
); 
 142         clp
->c_cs 
= clp
->c_cq 
= (u_char 
*)0; 
 147  * Get a character from a clist. 
 160         c 
= *clp
->c_cf 
& 0xff; 
 163                 if (isset(clp
->c_cq
, clp
->c_cf 
- clp
->c_cs
) ) 
 166                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 170         if (++clp
->c_cf 
== clp
->c_ce
) 
 171                 clp
->c_cf 
= clp
->c_cs
; 
 172         if (--clp
->c_cc 
== 0) 
 173                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 180  * Copy clist to buffer. 
 181  * Return number of bytes moved. 
 184 q_to_b(clp
, cp
, count
) 
 194         /* optimize this while loop */ 
 195         while (count 
> 0 && clp
->c_cc 
> 0) { 
 196                 cc 
= clp
->c_cl 
- clp
->c_cf
; 
 197                 if (clp
->c_cf 
>= clp
->c_cl
) 
 198                         cc 
= clp
->c_ce 
- clp
->c_cf
; 
 201                 bcopy(clp
->c_cf
, p
, cc
); 
 206                 if (clp
->c_cf 
== clp
->c_ce
) 
 207                         clp
->c_cf 
= clp
->c_cs
; 
 210                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 216  * Return count of contiguous characters in clist. 
 217  * Stop counting if flag&character is non-null. 
 230         if ((cc 
= clp
->c_cc
) == 0) 
 234                 count 
= clp
->c_cl 
- clp
->c_cf
; 
 236                         count 
= clp
->c_ce 
- clp
->c_cf
; 
 240         i 
= clp
->c_cf 
- clp
->c_cs
; 
 241         if (flag 
& TTY_QUOTE
) { 
 242                 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & (flag 
& ~TTY_QUOTE
) || 
 243                     isset(clp
->c_cq
, i
))) { 
 249                 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & flag
)) { 
 261  * Flush count bytes from clist. 
 272         if (count 
== clp
->c_cc
) { 
 274                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 277         /* optimize this while loop */ 
 278         while (count 
> 0 && clp
->c_cc 
> 0) { 
 279                 cc 
= clp
->c_cl 
- clp
->c_cf
; 
 280                 if (clp
->c_cf 
>= clp
->c_cl
) 
 281                         cc 
= clp
->c_ce 
- clp
->c_cf
; 
 287                 if (clp
->c_cf 
== clp
->c_ce
) 
 288                         clp
->c_cf 
= clp
->c_cs
; 
 291                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 297  * Put a character into the output queue. 
 308         if (clp
->c_cc 
== 0) { 
 311                         //printf("putc: required clalloc\n"); 
 313                         if(clalloc(clp
, 1024, 1)) { 
 319                 clp
->c_cf 
= clp
->c_cl 
= clp
->c_cs
; 
 322         if (clp
->c_cc 
== clp
->c_cn
) 
 325         *clp
->c_cl 
= c 
& 0xff; 
 326         i 
= clp
->c_cl 
- clp
->c_cs
; 
 330                         setbit(clp
->c_cq
, i
);  
 332                         clrbit(clp
->c_cq
, i
); 
 335                 *q 
= (c 
& TTY_QUOTE
) ? 1 : 0; 
 340         if (clp
->c_cl 
== clp
->c_ce
) 
 341                 clp
->c_cl 
= clp
->c_cs
; 
 348  * optimized version of 
 350  * for (i = 0; i < len; i++) 
 351  *      clrbit(cp, off + len); 
 354 clrbits(u_char 
*cp
, int off
, int len
) 
 356         int sby
, sbi
, eby
, ebi
; 
 367         eby 
= (off
+len
) / NBBY
; 
 368         ebi 
= (off
+len
) % NBBY
; 
 370                 mask 
= ((1 << (ebi 
- sbi
)) - 1) << sbi
; 
 379                 for (i 
= sby
; i 
< eby
; i
++) 
 386  * Copy buffer to clist. 
 387  * Return number of bytes not transfered. 
 390 b_to_q(const u_char 
*cp
, int count
, struct clist 
*clp
) 
 393         const u_char 
*p 
= cp
; 
 401         if (clp
->c_cc 
== 0) { 
 404                         printf("b_to_q: required clalloc\n"); 
 406                         if(clalloc(clp
, 1024, 1)) 
 409                 clp
->c_cf 
= clp
->c_cl 
= clp
->c_cs
; 
 412         if (clp
->c_cc 
== clp
->c_cn
) 
 415         /* optimize this while loop */ 
 416         while (count 
> 0 && clp
->c_cc 
< clp
->c_cn
) { 
 417                 cc 
= clp
->c_ce 
- clp
->c_cl
; 
 418                 if (clp
->c_cf 
> clp
->c_cl
) 
 419                         cc 
= clp
->c_cf 
- clp
->c_cl
; 
 422                 bcopy(p
, clp
->c_cl
, cc
); 
 425                         clrbits(clp
->c_cq
, clp
->c_cl 
- clp
->c_cs
, cc
); 
 427                         bzero(clp
->c_cl 
- clp
->c_cs 
+ clp
->c_cq
, cc
); 
 434                 if (clp
->c_cl 
== clp
->c_ce
) 
 435                         clp
->c_cl 
= clp
->c_cs
; 
 445  * Given a non-NULL pointer into the clist return the pointer 
 446  * to the next character in the list or return NULL if no more chars. 
 448  * Callers must not allow getc's to happen between firstc's and getc's 
 449  * so that the pointer becomes invalid.  Note that interrupts are NOT 
 459         if (clp
->c_cf 
== cp
) { 
 461                  * First time initialization. 
 465         if (cc 
== 0 || cp 
== NULL
) 
 469         if (++cp 
== clp
->c_ce
) 
 474                 if (isset(clp
->c_cq
, cp 
- clp
->c_cs
)) 
 477                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 485  * Given a non-NULL pointer into the clist return the pointer 
 486  * to the first character in the list or return NULL if no more chars. 
 488  * Callers must not allow getc's to happen between firstc's and getc's 
 489  * so that the pointer becomes invalid.  Note that interrupts are NOT 
 492  * *c is set to the NEXT character 
 508                 if (isset(clp
->c_cq
, cp 
- clp
->c_cs
)) 
 511                 if (*(cp 
- clp
->c_cs 
+ clp
->c_cq
)) 
 519  * Remove the last character in the clist and return it. 
 532         if (clp
->c_cl 
== clp
->c_cs
) 
 533                 clp
->c_cl 
= clp
->c_ce 
- 1; 
 538         c 
= *clp
->c_cl 
& 0xff; 
 541                 if (isset(clp
->c_cq
, clp
->c_cl 
- clp
->c_cs
)) 
 544                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 549                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 556  * Put the chars in the from queue on the end of the to queue. 
 560         struct clist 
*from
, *to
; 
 564         while ((c 
= getc(from
)) != -1)