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: while (*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: }
Defined functions
skip
defined in line
158; used 4 times
Defined variables
sccsid
defined in line
8;
never used
tbuf
defined in line
15; used 11 times
Defined macros