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