xref: /csrg-svn/usr.bin/tip/remcap.c (revision 3694)
1*3694Sroot /*	remcap.c	4.1	81/05/09	*/
2*3694Sroot /* Copyright (c) 1979 Regents of the University of California */
3*3694Sroot #define	BUFSIZ	512
4*3694Sroot 
5*3694Sroot #include <ctype.h>
6*3694Sroot /*
7*3694Sroot  * remcap - routines for dealing with the remote host description
8*3694Sroot  *	    data base
9*3694Sroot  *
10*3694Sroot  * BUG:		Should use a "last" pointer in tbuf, so that searching
11*3694Sroot  *		for capabilities alphabetically would not be a n**2/2
12*3694Sroot  *		process when large numbers of capabilities are given.
13*3694Sroot  *
14*3694Sroot  * Essentially all the work here is scanning and decoding escapes
15*3694Sroot  * in string capabilities.*/
16*3694Sroot 
17*3694Sroot static	char *rbuf;
18*3694Sroot char	*rskip();
19*3694Sroot char	*rgetstr();
20*3694Sroot char	*rdecode();
21*3694Sroot char	*getenv();
22*3694Sroot char	*RM;		/* remote file */
23*3694Sroot 
24*3694Sroot /*
25*3694Sroot  * Get an entry for host name in buffer bp,
26*3694Sroot  * from the remcap file.  Parse is very rudimentary;
27*3694Sroot  * we just notice escaped newlines.
28*3694Sroot  */
29*3694Sroot rgetent(bp, name)
30*3694Sroot 	char *bp, *name;
31*3694Sroot {
32*3694Sroot 	register char *cp;
33*3694Sroot 	register int c;
34*3694Sroot 	register int i = 0, cnt = 0;
35*3694Sroot 	char ibuf[BUFSIZ];
36*3694Sroot 	int tf;
37*3694Sroot 
38*3694Sroot 	rbuf = bp;
39*3694Sroot 	if ((RM = getenv("REMOTE")) == (char *)0)
40*3694Sroot 		RM = "/etc/remote";
41*3694Sroot 	if ((tf = open(RM, 0)) < 0)
42*3694Sroot 		return (-1);
43*3694Sroot 	for (;;) {
44*3694Sroot 		cp = bp;
45*3694Sroot 		for (;;) {
46*3694Sroot 			if (i == cnt) {
47*3694Sroot 				cnt = read(tf, ibuf, BUFSIZ);
48*3694Sroot 				if (cnt <= 0) {
49*3694Sroot 					close(tf);
50*3694Sroot 					return (0);
51*3694Sroot 				}
52*3694Sroot 				i = 0;
53*3694Sroot 			}
54*3694Sroot 			c = ibuf[i++];
55*3694Sroot 			if (c == '\n') {
56*3694Sroot 				if (cp > bp && cp[-1] == '\\'){
57*3694Sroot 					cp--;
58*3694Sroot 					continue;
59*3694Sroot 				}
60*3694Sroot 				break;
61*3694Sroot 			}
62*3694Sroot 			*cp++ = c;
63*3694Sroot 		}
64*3694Sroot 		*cp = 0;
65*3694Sroot 
66*3694Sroot 		/*
67*3694Sroot 		 * The real work for the match.
68*3694Sroot 		 */
69*3694Sroot 		if (rnamatch(name)) {
70*3694Sroot 			close(tf);
71*3694Sroot 			return (1);
72*3694Sroot 		}
73*3694Sroot 	}
74*3694Sroot }
75*3694Sroot 
76*3694Sroot /*
77*3694Sroot  * Rnamatch deals with name matching.  The first field of the remcap
78*3694Sroot  * entry is a sequence of names separated by |'s, so we compare
79*3694Sroot  * against each such name.  The normal : terminator after the last
80*3694Sroot  * name (before the first field) stops us.
81*3694Sroot  */
82*3694Sroot rnamatch(np)
83*3694Sroot 	char *np;
84*3694Sroot {
85*3694Sroot 	register char *Np, *Bp;
86*3694Sroot 
87*3694Sroot 	Bp = rbuf;
88*3694Sroot 	for (;;) {
89*3694Sroot 		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
90*3694Sroot 			continue;
91*3694Sroot 		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
92*3694Sroot 			return (1);
93*3694Sroot 		while (*Bp && *Bp != ':' && *Bp != '|')
94*3694Sroot 			Bp++;
95*3694Sroot 		if (*Bp == 0 || *Bp == ':')
96*3694Sroot 			return (0);
97*3694Sroot 		Bp++;
98*3694Sroot 	}
99*3694Sroot }
100*3694Sroot 
101*3694Sroot /*
102*3694Sroot  * Skip to the next field.  Notice that this is very dumb, not
103*3694Sroot  * knowing about \: escapes or any such.  If necessary, :'s can be put
104*3694Sroot  * into the printcap file in octal.
105*3694Sroot  */
106*3694Sroot static char *
107*3694Sroot rskip(bp)
108*3694Sroot 	register char *bp;
109*3694Sroot {
110*3694Sroot 
111*3694Sroot 	while (*bp && *bp != ':')
112*3694Sroot 		bp++;
113*3694Sroot 	if (*bp == ':')
114*3694Sroot 		bp++;
115*3694Sroot 	return (bp);
116*3694Sroot }
117*3694Sroot 
118*3694Sroot /*
119*3694Sroot  * Return the (numeric) option id.
120*3694Sroot  * Numeric options look like
121*3694Sroot  *	li#80
122*3694Sroot  * i.e. the option string is separated from the numeric value by
123*3694Sroot  * a # character.  If the option is not found we return -1.
124*3694Sroot  * Note that we handle octal numbers beginning with 0.
125*3694Sroot  */
126*3694Sroot rgetnum(id)
127*3694Sroot 	char *id;
128*3694Sroot {
129*3694Sroot 	register int i, base;
130*3694Sroot 	register char *bp = rbuf;
131*3694Sroot 
132*3694Sroot 	for (;;) {
133*3694Sroot 		bp = rskip(bp);
134*3694Sroot 		if (*bp == 0)
135*3694Sroot 			return (-1);
136*3694Sroot 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
137*3694Sroot 			continue;
138*3694Sroot 		if (*bp != '#')
139*3694Sroot 			continue;
140*3694Sroot 		bp++;
141*3694Sroot 		base = 10;
142*3694Sroot 		if (*bp == '0')
143*3694Sroot 			base = 8;
144*3694Sroot 		i = 0;
145*3694Sroot 		while (isdigit(*bp))
146*3694Sroot 			i *= base, i += *bp++ - '0';
147*3694Sroot 		return (i);
148*3694Sroot 	}
149*3694Sroot }
150*3694Sroot 
151*3694Sroot /*
152*3694Sroot  * Handle a flag option.
153*3694Sroot  * Flag options are given "naked", i.e. followed by a : or the end
154*3694Sroot  * of the buffer.  Return 1 if we find the option, or 0 if it is
155*3694Sroot  * not given.
156*3694Sroot  */
157*3694Sroot rgetflag(id)
158*3694Sroot 	char *id;
159*3694Sroot {
160*3694Sroot 	register char *bp = rbuf;
161*3694Sroot 
162*3694Sroot 	for (;;) {
163*3694Sroot 		bp = rskip(bp);
164*3694Sroot 		if (!*bp)
165*3694Sroot 			return (0);
166*3694Sroot 		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1] && (!*bp || *bp == ':'))
167*3694Sroot 			return (1);
168*3694Sroot 	}
169*3694Sroot }
170*3694Sroot 
171*3694Sroot /*
172*3694Sroot  * Get a string valued option.
173*3694Sroot  * These are given as
174*3694Sroot  *	cl=^Z
175*3694Sroot  * Much decoding is done on the strings, and the strings are
176*3694Sroot  * placed in area, which is a ref parameter which is updated.
177*3694Sroot  * No checking on area overflow.
178*3694Sroot  */
179*3694Sroot char *
180*3694Sroot rgetstr(id, area)
181*3694Sroot 	char *id, **area;
182*3694Sroot {
183*3694Sroot 	register char *bp = rbuf;
184*3694Sroot 
185*3694Sroot 	for (;;) {
186*3694Sroot 		bp = rskip(bp);
187*3694Sroot 		if (!*bp)
188*3694Sroot 			return (0);
189*3694Sroot 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
190*3694Sroot 			continue;
191*3694Sroot 		if (*bp != '=')
192*3694Sroot 			continue;
193*3694Sroot 		bp++;
194*3694Sroot 		return (rdecode(bp, area));
195*3694Sroot 	}
196*3694Sroot }
197*3694Sroot 
198*3694Sroot /*
199*3694Sroot  * Tdecode does the grung work to decode the
200*3694Sroot  * string capability escapes.
201*3694Sroot  */
202*3694Sroot char *
203*3694Sroot rdecode(str, area)
204*3694Sroot 	register char *str;
205*3694Sroot 	char **area;
206*3694Sroot {
207*3694Sroot 	register char *cp;
208*3694Sroot 	register int c;
209*3694Sroot 	register char *dp;
210*3694Sroot 	int i;
211*3694Sroot 
212*3694Sroot 	cp = *area;
213*3694Sroot 	while ((c = *str++) && c != ':') {
214*3694Sroot 		switch (c) {
215*3694Sroot 
216*3694Sroot 		case '^':
217*3694Sroot 			c = *str++ & 037;
218*3694Sroot 			break;
219*3694Sroot 
220*3694Sroot 		case '\\':
221*3694Sroot 			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
222*3694Sroot 			c = *str++;
223*3694Sroot nextc:
224*3694Sroot 			if (*dp++ == c) {
225*3694Sroot 				c = *dp++;
226*3694Sroot 				break;
227*3694Sroot 			}
228*3694Sroot 			dp++;
229*3694Sroot 			if (*dp)
230*3694Sroot 				goto nextc;
231*3694Sroot 			if (isdigit(c)) {
232*3694Sroot 				c -= '0', i = 2;
233*3694Sroot 				do
234*3694Sroot 					c <<= 3, c |= *str++ - '0';
235*3694Sroot 				while (--i && isdigit(*str));
236*3694Sroot 			}
237*3694Sroot 			break;
238*3694Sroot 		}
239*3694Sroot 		*cp++ = c;
240*3694Sroot 	}
241*3694Sroot 	*cp++ = 0;
242*3694Sroot 	str = *area;
243*3694Sroot 	*area = cp;
244*3694Sroot 	return (str);
245*3694Sroot }
246