|
|
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.