]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/tty_subr.c
2 * Copyright (c) 2000-2006 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
58 * We use the NetBSD based clist system, it is much more efficient than the
59 * old style clist stuff used by free bsd.
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/ioctl.h>
66 #include <sys/malloc.h>
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.
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.
85 #define QMEM(n) ((((n)-1)/NBBY)+1)
100 * Initialize a particular clist. Ok, they are really ring buffers,
101 * of the specified length, with/without quoting support.
104 clalloc(struct clist
*clp
, int size
, int quot
)
106 clp
->c_cs
= kheap_alloc(KHEAP_DATA_BUFFERS
, size
, Z_WAITOK
| Z_ZERO
);
112 clp
->c_cq
= kheap_alloc(KHEAP_DATA_BUFFERS
,
113 QMEM(size
), Z_WAITOK
| Z_ZERO
);
115 kheap_free(KHEAP_DATA_BUFFERS
, clp
->c_cs
, size
);
119 clp
->c_cq
= (u_char
*)0;
122 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
123 clp
->c_ce
= clp
->c_cs
+ size
;
130 clfree(struct clist
*clp
)
133 kheap_free(KHEAP_DATA_BUFFERS
, clp
->c_cs
, clp
->c_cn
);
136 kheap_free(KHEAP_DATA_BUFFERS
, clp
->c_cq
, QMEM(clp
->c_cn
));
138 clp
->c_cs
= clp
->c_cq
= (u_char
*)0;
143 * Get a character from a clist.
146 getc(struct clist
*clp
)
150 if (clp
->c_cc
== 0) {
154 c
= *clp
->c_cf
& 0xff;
157 if (isset(clp
->c_cq
, clp
->c_cf
- clp
->c_cs
)) {
161 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
)) {
166 if (++clp
->c_cf
== clp
->c_ce
) {
167 clp
->c_cf
= clp
->c_cs
;
169 if (--clp
->c_cc
== 0) {
170 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
177 * Copy clist to buffer.
178 * Return number of bytes moved.
181 q_to_b(struct clist
*clp
, u_char
*cp
, int count
)
186 /* optimize this while loop */
187 while (count
> 0 && clp
->c_cc
> 0) {
188 cc
= clp
->c_cl
- clp
->c_cf
;
189 if (clp
->c_cf
>= clp
->c_cl
) {
190 cc
= clp
->c_ce
- clp
->c_cf
;
192 if (cc
> INT_MAX
|| (int)cc
> count
) {
195 bcopy(clp
->c_cf
, p
, cc
);
200 if (clp
->c_cf
== clp
->c_ce
) {
201 clp
->c_cf
= clp
->c_cs
;
204 if (clp
->c_cc
== 0) {
205 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
207 return (int)MIN(INT32_MAX
, p
- cp
);
211 * Return count of contiguous characters in clist.
212 * Stop counting if flag&character is non-null.
215 ndqb(struct clist
*clp
, int flag
)
221 if ((cc
= clp
->c_cc
) == 0) {
226 count
= clp
->c_cl
- clp
->c_cf
;
228 count
= clp
->c_ce
- clp
->c_cf
;
233 i
= clp
->c_cf
- clp
->c_cs
;
237 if (flag
& TTY_QUOTE
) {
238 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & (flag
& ~TTY_QUOTE
) ||
239 isset(clp
->c_cq
, i
))) {
241 if ((int)i
== clp
->c_cn
) {
246 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & flag
)) {
248 if ((int)i
== clp
->c_cn
) {
254 if (count
> INT_MAX
) {
261 * Flush count bytes from clist.
264 ndflush(struct clist
*clp
, int count
)
268 if (count
== clp
->c_cc
) {
270 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
273 /* optimize this while loop */
274 while (count
> 0 && clp
->c_cc
> 0) {
275 cc
= clp
->c_cl
- clp
->c_cf
;
276 if (clp
->c_cf
>= clp
->c_cl
) {
277 cc
= clp
->c_ce
- clp
->c_cf
;
279 if (cc
> INT_MAX
|| (int)cc
> count
) {
285 if (clp
->c_cf
== clp
->c_ce
) {
286 clp
->c_cf
= clp
->c_cs
;
289 if (clp
->c_cc
== 0) {
290 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
295 * Put a character into the output queue.
298 putc(int c
, struct clist
*clp
)
302 if (clp
->c_cc
== 0) {
305 //printf("putc: required clalloc\n");
307 if (clalloc(clp
, 1024, 1)) {
311 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
314 if (clp
->c_cc
== clp
->c_cn
) {
318 *clp
->c_cl
= c
& 0xff;
319 i
= clp
->c_cl
- clp
->c_cs
;
326 setbit(clp
->c_cq
, i
);
328 clrbit(clp
->c_cq
, i
);
332 *q
= (c
& TTY_QUOTE
) ? 1 : 0;
337 if (clp
->c_cl
== clp
->c_ce
) {
338 clp
->c_cl
= clp
->c_cs
;
345 * optimized version of
347 * for (i = 0; i < len; i++)
348 * clrbit(cp, off + len);
351 clrbits(u_char
*cp
, int off
, int len
)
353 int sby
, sbi
, eby
, ebi
;
364 eby
= (off
+ len
) / NBBY
;
365 ebi
= (off
+ len
) % NBBY
;
367 mask
= (u_char
)(((1 << (ebi
- sbi
)) - 1) << sbi
);
370 mask
= (u_char
)((1 << sbi
) - 1);
373 mask
= (u_char
)((1 << ebi
) - 1);
374 /* handle remainder bits, if any, for a non-0 ebi value */
379 for (i
= sby
; i
< eby
; i
++) {
387 * Copy buffer to clist.
388 * Return number of bytes not transfered.
391 b_to_q(const u_char
*cp
, int count
, struct clist
*clp
)
394 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)) {
410 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
413 if (clp
->c_cc
== clp
->c_cn
) {
417 /* optimize this while loop */
418 while (count
> 0 && clp
->c_cc
< clp
->c_cn
) {
419 cc
= clp
->c_ce
- clp
->c_cl
;
420 if (clp
->c_cf
> clp
->c_cl
) {
421 cc
= clp
->c_cf
- clp
->c_cl
;
423 if (cc
> INT_MAX
|| (int)cc
> count
) {
426 bcopy(p
, clp
->c_cl
, cc
);
429 if (clp
->c_cl
- clp
->c_cs
> INT_MAX
|| cc
> INT_MAX
) {
433 clrbits(clp
->c_cq
, (int)(clp
->c_cl
- clp
->c_cs
), (int)cc
);
435 bzero(clp
->c_cl
- clp
->c_cs
+ clp
->c_cq
, cc
);
442 if (clp
->c_cl
== clp
->c_ce
) {
443 clp
->c_cl
= clp
->c_cs
;
453 * Given a non-NULL pointer into the clist return the pointer
454 * to the next character in the list or return NULL if no more chars.
456 * Callers must not allow getc's to happen between firstc's and getc's
457 * so that the pointer becomes invalid. Note that interrupts are NOT
461 nextc(struct clist
*clp
, u_char
*cp
, int *c
)
463 if (clp
->c_cf
== cp
) {
465 * First time initialization.
469 if (cc
== 0 || cp
== NULL
) {
475 if (++cp
== clp
->c_ce
) {
481 if (isset(clp
->c_cq
, cp
- clp
->c_cs
)) {
485 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
)) {
494 * Given a non-NULL pointer into the clist return the pointer
495 * to the first character in the list or return NULL if no more chars.
497 * Callers must not allow getc's to happen between firstc's and getc's
498 * so that the pointer becomes invalid. Note that interrupts are NOT
501 * *c is set to the NEXT character
504 firstc(struct clist
*clp
, int *c
)
516 if (isset(clp
->c_cq
, cp
- clp
->c_cs
)) {
520 if (*(cp
- clp
->c_cs
+ clp
->c_cq
)) {
529 * Remove the last character in the clist and return it.
532 unputc(struct clist
*clp
)
536 if (clp
->c_cc
== 0) {
540 if (clp
->c_cl
== clp
->c_cs
) {
541 clp
->c_cl
= clp
->c_ce
- 1;
547 c
= *clp
->c_cl
& 0xff;
550 if (isset(clp
->c_cq
, clp
->c_cl
- clp
->c_cs
)) {
554 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
)) {
559 if (clp
->c_cc
== 0) {
560 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
567 * Put the chars in the from queue on the end of the to queue.
570 catq(struct clist
*from
, struct clist
*to
)
574 while ((c
= getc(from
)) != -1) {