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