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