|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)gettytab.c 5.1 (Berkeley) 4/29/85"; ! 9: #endif not lint ! 10: ! 11: #include <ctype.h> ! 12: ! 13: #define TABBUFSIZ 512 ! 14: ! 15: static char *tbuf; ! 16: int hopcount; /* detect infinite loops in termcap, init 0 */ ! 17: char *skip(); ! 18: char *getstr(); ! 19: char *decode(); ! 20: ! 21: /* ! 22: * Get an entry for terminal name in buffer bp, ! 23: * from the termcap file. Parse is very rudimentary; ! 24: * we just notice escaped newlines. ! 25: */ ! 26: getent(bp, name) ! 27: char *bp, *name; ! 28: { ! 29: register char *cp; ! 30: register int c; ! 31: register int i = 0, cnt = 0; ! 32: char ibuf[TABBUFSIZ]; ! 33: char *cp2; ! 34: int tf; ! 35: ! 36: tbuf = bp; ! 37: tf = open("/etc/gettytab", 0); ! 38: if (tf < 0) ! 39: return (-1); ! 40: for (;;) { ! 41: cp = bp; ! 42: for (;;) { ! 43: if (i == cnt) { ! 44: cnt = read(tf, ibuf, TABBUFSIZ); ! 45: if (cnt <= 0) { ! 46: close(tf); ! 47: return (0); ! 48: } ! 49: i = 0; ! 50: } ! 51: c = ibuf[i++]; ! 52: if (c == '\n') { ! 53: if (cp > bp && cp[-1] == '\\'){ ! 54: cp--; ! 55: continue; ! 56: } ! 57: break; ! 58: } ! 59: if (cp >= bp+TABBUFSIZ) { ! 60: write(2,"Gettytab entry too long\n", 24); ! 61: break; ! 62: } else ! 63: *cp++ = c; ! 64: } ! 65: *cp = 0; ! 66: ! 67: /* ! 68: * The real work for the match. ! 69: */ ! 70: if (namatch(name)) { ! 71: close(tf); ! 72: return(nchktc()); ! 73: } ! 74: } ! 75: } ! 76: ! 77: /* ! 78: * tnchktc: check the last entry, see if it's tc=xxx. If so, ! 79: * recursively find xxx and append that entry (minus the names) ! 80: * to take the place of the tc=xxx entry. This allows termcap ! 81: * entries to say "like an HP2621 but doesn't turn on the labels". ! 82: * Note that this works because of the left to right scan. ! 83: */ ! 84: #define MAXHOP 32 ! 85: nchktc() ! 86: { ! 87: register char *p, *q; ! 88: char tcname[16]; /* name of similar terminal */ ! 89: char tcbuf[TABBUFSIZ]; ! 90: char *holdtbuf = tbuf; ! 91: int l; ! 92: ! 93: p = tbuf + strlen(tbuf) - 2; /* before the last colon */ ! 94: while (*--p != ':') ! 95: if (p<tbuf) { ! 96: write(2, "Bad gettytab entry\n", 19); ! 97: return (0); ! 98: } ! 99: p++; ! 100: /* p now points to beginning of last field */ ! 101: if (p[0] != 't' || p[1] != 'c') ! 102: return(1); ! 103: strcpy(tcname,p+3); ! 104: q = tcname; ! 105: while (q && *q != ':') ! 106: q++; ! 107: *q = 0; ! 108: if (++hopcount > MAXHOP) { ! 109: write(2, "Getty: infinite tc= loop\n", 25); ! 110: return (0); ! 111: } ! 112: if (getent(tcbuf, tcname) != 1) ! 113: return(0); ! 114: for (q=tcbuf; *q != ':'; q++) ! 115: ; ! 116: l = p - holdtbuf + strlen(q); ! 117: if (l > TABBUFSIZ) { ! 118: write(2, "Gettytab entry too long\n", 24); ! 119: q[TABBUFSIZ - (p-tbuf)] = 0; ! 120: } ! 121: strcpy(p, q+1); ! 122: tbuf = holdtbuf; ! 123: return(1); ! 124: } ! 125: ! 126: /* ! 127: * Tnamatch deals with name matching. The first field of the termcap ! 128: * entry is a sequence of names separated by |'s, so we compare ! 129: * against each such name. The normal : terminator after the last ! 130: * name (before the first field) stops us. ! 131: */ ! 132: namatch(np) ! 133: char *np; ! 134: { ! 135: register char *Np, *Bp; ! 136: ! 137: Bp = tbuf; ! 138: if (*Bp == '#') ! 139: return(0); ! 140: for (;;) { ! 141: for (Np = np; *Np && *Bp == *Np; Bp++, Np++) ! 142: continue; ! 143: if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) ! 144: return (1); ! 145: while (*Bp && *Bp != ':' && *Bp != '|') ! 146: Bp++; ! 147: if (*Bp == 0 || *Bp == ':') ! 148: return (0); ! 149: Bp++; ! 150: } ! 151: } ! 152: ! 153: /* ! 154: * Skip to the next field. Notice that this is very dumb, not ! 155: * knowing about \: escapes or any such. If necessary, :'s can be put ! 156: * into the termcap file in octal. ! 157: */ ! 158: static char * ! 159: skip(bp) ! 160: register char *bp; ! 161: { ! 162: ! 163: while (*bp && *bp != ':') ! 164: bp++; ! 165: if (*bp == ':') ! 166: bp++; ! 167: return (bp); ! 168: } ! 169: ! 170: /* ! 171: * Return the (numeric) option id. ! 172: * Numeric options look like ! 173: * li#80 ! 174: * i.e. the option string is separated from the numeric value by ! 175: * a # character. If the option is not found we return -1. ! 176: * Note that we handle octal numbers beginning with 0. ! 177: */ ! 178: long ! 179: getnum(id) ! 180: char *id; ! 181: { ! 182: register long i, base; ! 183: register char *bp = tbuf; ! 184: ! 185: for (;;) { ! 186: bp = skip(bp); ! 187: if (*bp == 0) ! 188: return (-1); ! 189: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) ! 190: continue; ! 191: if (*bp == '@') ! 192: return(-1); ! 193: if (*bp != '#') ! 194: continue; ! 195: bp++; ! 196: base = 10; ! 197: if (*bp == '0') ! 198: base = 8; ! 199: i = 0; ! 200: while (isdigit(*bp)) ! 201: i *= base, i += *bp++ - '0'; ! 202: return (i); ! 203: } ! 204: } ! 205: ! 206: /* ! 207: * Handle a flag option. ! 208: * Flag options are given "naked", i.e. followed by a : or the end ! 209: * of the buffer. Return 1 if we find the option, or 0 if it is ! 210: * not given. ! 211: */ ! 212: getflag(id) ! 213: char *id; ! 214: { ! 215: register char *bp = tbuf; ! 216: ! 217: for (;;) { ! 218: bp = skip(bp); ! 219: if (!*bp) ! 220: return (-1); ! 221: if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { ! 222: if (!*bp || *bp == ':') ! 223: return (1); ! 224: else if (*bp == '!') ! 225: return (0); ! 226: else if (*bp == '@') ! 227: return(-1); ! 228: } ! 229: } ! 230: } ! 231: ! 232: /* ! 233: * Get a string valued option. ! 234: * These are given as ! 235: * cl=^Z ! 236: * Much decoding is done on the strings, and the strings are ! 237: * placed in area, which is a ref parameter which is updated. ! 238: * No checking on area overflow. ! 239: */ ! 240: char * ! 241: getstr(id, area) ! 242: char *id, **area; ! 243: { ! 244: register char *bp = tbuf; ! 245: ! 246: for (;;) { ! 247: bp = skip(bp); ! 248: if (!*bp) ! 249: return (0); ! 250: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) ! 251: continue; ! 252: if (*bp == '@') ! 253: return(0); ! 254: if (*bp != '=') ! 255: continue; ! 256: bp++; ! 257: return (decode(bp, area)); ! 258: } ! 259: } ! 260: ! 261: /* ! 262: * Tdecode does the grung work to decode the ! 263: * string capability escapes. ! 264: */ ! 265: static char * ! 266: decode(str, area) ! 267: register char *str; ! 268: char **area; ! 269: { ! 270: register char *cp; ! 271: register int c; ! 272: register char *dp; ! 273: int i; ! 274: ! 275: cp = *area; ! 276: while ((c = *str++) && c != ':') { ! 277: switch (c) { ! 278: ! 279: case '^': ! 280: c = *str++ & 037; ! 281: break; ! 282: ! 283: case '\\': ! 284: dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; ! 285: c = *str++; ! 286: nextc: ! 287: if (*dp++ == c) { ! 288: c = *dp++; ! 289: break; ! 290: } ! 291: dp++; ! 292: if (*dp) ! 293: goto nextc; ! 294: if (isdigit(c)) { ! 295: c -= '0', i = 2; ! 296: do ! 297: c <<= 3, c |= *str++ - '0'; ! 298: while (--i && isdigit(*str)); ! 299: } ! 300: break; ! 301: } ! 302: *cp++ = c; ! 303: } ! 304: *cp++ = 0; ! 305: str = *area; ! 306: *area = cp; ! 307: return (str); ! 308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.