]>
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_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
32 * Copyright (c) 1993, 1994 Theo de Raadt
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice unmodified, this list of conditions, and the following
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * We use the NetBSD based clist system, it is much more efficient than the
62 * old style clist stuff used by free bsd.
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/ioctl.h>
69 #include <sys/malloc.h>
71 #include <machine/spl.h>
74 * At compile time, choose:
75 * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
76 * defined we allocate an array of bits -- 1/8th as much memory but
77 * setbit(), clrbit(), and isset() take more cpu. If QBITS is
78 * undefined, we just use an array of bytes.
80 * If TTY_QUOTE functionality isn't required by a line discipline,
81 * it can free c_cq and set it to NULL. This speeds things up,
82 * and also does not use any extra memory. This is useful for (say)
83 * a SLIP line discipline that wants a 32K ring buffer for data
84 * but doesn't need quoting.
89 #define QMEM(n) ((((n)-1)/NBBY)+1)
104 * Initialize a particular clist. Ok, they are really ring buffers,
105 * of the specified length, with/without quoting support.
108 clalloc(clp
, size
, quot
)
114 MALLOC_ZONE(clp
->c_cs
, u_char
*, size
, M_TTYS
, M_WAITOK
);
117 bzero(clp
->c_cs
, size
);
120 MALLOC_ZONE(clp
->c_cq
, u_char
*, QMEM(size
), M_TTYS
, M_WAITOK
);
122 FREE_ZONE(clp
->c_cs
, size
, M_TTYS
);
125 bzero(clp
->c_cs
, QMEM(size
));
127 clp
->c_cq
= (u_char
*)0;
129 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
130 clp
->c_ce
= clp
->c_cs
+ size
;
141 FREE_ZONE(clp
->c_cs
, clp
->c_cn
, M_TTYS
);
143 FREE_ZONE(clp
->c_cq
, QMEM(clp
->c_cn
), M_TTYS
);
144 clp
->c_cs
= clp
->c_cq
= (u_char
*)0;
149 * Get a character from a clist.
162 c
= *clp
->c_cf
& 0xff;
165 if (isset(clp
->c_cq
, clp
->c_cf
- clp
->c_cs
) )
168 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
172 if (++clp
->c_cf
== clp
->c_ce
)
173 clp
->c_cf
= clp
->c_cs
;
174 if (--clp
->c_cc
== 0)
175 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
182 * Copy clist to buffer.
183 * Return number of bytes moved.
186 q_to_b(clp
, cp
, count
)
196 /* optimize this while loop */
197 while (count
> 0 && clp
->c_cc
> 0) {
198 cc
= clp
->c_cl
- clp
->c_cf
;
199 if (clp
->c_cf
>= clp
->c_cl
)
200 cc
= clp
->c_ce
- clp
->c_cf
;
203 bcopy(clp
->c_cf
, p
, cc
);
208 if (clp
->c_cf
== clp
->c_ce
)
209 clp
->c_cf
= clp
->c_cs
;
212 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
218 * Return count of contiguous characters in clist.
219 * Stop counting if flag&character is non-null.
232 if ((cc
= clp
->c_cc
) == 0)
236 count
= clp
->c_cl
- clp
->c_cf
;
238 count
= clp
->c_ce
- clp
->c_cf
;
242 i
= clp
->c_cf
- clp
->c_cs
;
243 if (flag
& TTY_QUOTE
) {
244 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & (flag
& ~TTY_QUOTE
) ||
245 isset(clp
->c_cq
, i
))) {
251 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & flag
)) {
263 * Flush count bytes from clist.
274 if (count
== clp
->c_cc
) {
276 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
279 /* optimize this while loop */
280 while (count
> 0 && clp
->c_cc
> 0) {
281 cc
= clp
->c_cl
- clp
->c_cf
;
282 if (clp
->c_cf
>= clp
->c_cl
)
283 cc
= clp
->c_ce
- clp
->c_cf
;
289 if (clp
->c_cf
== clp
->c_ce
)
290 clp
->c_cf
= clp
->c_cs
;
293 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
299 * Put a character into the output queue.
310 if (clp
->c_cc
== 0) {
313 //printf("putc: required clalloc\n");
315 if(clalloc(clp
, 1024, 1)) {
321 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
324 if (clp
->c_cc
== clp
->c_cn
)
327 *clp
->c_cl
= c
& 0xff;
328 i
= clp
->c_cl
- clp
->c_cs
;
332 setbit(clp
->c_cq
, i
);
334 clrbit(clp
->c_cq
, i
);
337 *q
= (c
& TTY_QUOTE
) ? 1 : 0;
342 if (clp
->c_cl
== clp
->c_ce
)
343 clp
->c_cl
= clp
->c_cs
;
350 * optimized version of
352 * for (i = 0; i < len; i++)
353 * clrbit(cp, off + len);
356 clrbits(u_char
*cp
, int off
, int len
)
358 int sby
, sbi
, eby
, ebi
;
369 eby
= (off
+len
) / NBBY
;
370 ebi
= (off
+len
) % NBBY
;
372 mask
= ((1 << (ebi
- sbi
)) - 1) << sbi
;
381 for (i
= sby
; i
< eby
; i
++)
388 * Copy buffer to clist.
389 * Return number of bytes not transfered.
392 b_to_q(const u_char
*cp
, int count
, struct clist
*clp
)
395 const u_char
*p
= cp
;
403 if (clp
->c_cc
== 0) {
406 printf("b_to_q: required clalloc\n");
408 if(clalloc(clp
, 1024, 1))
411 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
414 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
;
424 bcopy(p
, clp
->c_cl
, cc
);
427 clrbits(clp
->c_cq
, clp
->c_cl
- clp
->c_cs
, cc
);
429 bzero(clp
->c_cl
- clp
->c_cs
+ clp
->c_cq
, cc
);
436 if (clp
->c_cl
== clp
->c_ce
)
437 clp
->c_cl
= clp
->c_cs
;
447 * Given a non-NULL pointer into the clist return the pointer
448 * to the next character in the list or return NULL if no more chars.
450 * Callers must not allow getc's to happen between firstc's and getc's
451 * so that the pointer becomes invalid. Note that interrupts are NOT
461 if (clp
->c_cf
== cp
) {
463 * First time initialization.
467 if (cc
== 0 || cp
== NULL
)
471 if (++cp
== clp
->c_ce
)
476 if (isset(clp
->c_cq
, cp
- clp
->c_cs
))
479 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
487 * Given a non-NULL pointer into the clist return the pointer
488 * to the first character in the list or return NULL if no more chars.
490 * Callers must not allow getc's to happen between firstc's and getc's
491 * so that the pointer becomes invalid. Note that interrupts are NOT
494 * *c is set to the NEXT character
510 if (isset(clp
->c_cq
, cp
- clp
->c_cs
))
513 if (*(cp
- clp
->c_cs
+ clp
->c_cq
))
521 * Remove the last character in the clist and return it.
534 if (clp
->c_cl
== clp
->c_cs
)
535 clp
->c_cl
= clp
->c_ce
- 1;
540 c
= *clp
->c_cl
& 0xff;
543 if (isset(clp
->c_cq
, clp
->c_cl
- clp
->c_cs
))
546 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
551 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
558 * Put the chars in the from queue on the end of the to queue.
562 struct clist
*from
, *to
;
566 while ((c
= getc(from
)) != -1)