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