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