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