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