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