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