Sources placed under CVS control.
[become] / src / class.c
1 /* -*-c-*-
2 *
3 * $Id: class.c,v 1.1 1997/07/21 13:47:52 mdw Exp $
4 *
5 * Handling classes of things nicely
6 *
7 * (c) 1997 EBI
8 */
9
10 /*----- Licencing notice --------------------------------------------------*
11 *
12 * This file is part of `become'
13 *
14 * `Become' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * `Become' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with `become'; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*----- Revision history --------------------------------------------------*
30 *
31 * $Log: class.c,v $
32 * Revision 1.1 1997/07/21 13:47:52 mdw
33 * Initial revision
34 *
35 */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 /* --- ANSI headers --- */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 /* --- Unix headers --- */
46
47 #include <sys/types.h>
48 #include <sys/socket.h>
49
50 #include <netinet/in.h>
51
52 #include <arpa/inet.h>
53
54 #include <netdb.h>
55
56 /* --- Local headers --- */
57
58 #include "class.h"
59 #include "set.h"
60 #include "sym.h"
61 #include "utils.h"
62
63 /*----- Global variables --------------------------------------------------*/
64
65 static classdef class__all = { clType_all, -1, 0 };
66 classdef *class_all = &class__all;
67
68 /*----- Wildcard matching -------------------------------------------------*/
69
70 /* --- @class__wildMatch@ --- *
71 *
72 * Arguments: @const char *pat@ = pointer to pattern string
73 * @const char *p@ = pointer to target string
74 *
75 * Returns: Zero if no match, nonzero if match.
76 *
77 * Use: Wildcard-matches the pattern against the target string.
78 */
79
80 static int class__wildMatch(const char *pat, const char *p)
81 {
82 for (;;) {
83 if (*pat == 0 && *p == 0)
84 return (42); /* For sadism's sake */
85 else if (*pat == '*') {
86 while (*pat == '*')
87 pat++;
88 do {
89 if (class__wildMatch(pat, p))
90 return (27); /* Nyahaha */
91 p++;
92 } while (*p);
93 return (0);
94 } else if (*pat == '?' || *pat == *p)
95 p++, pat++;
96 else
97 return (0);
98 }
99 }
100
101 /*----- Main code ---------------------------------------------------------*/
102
103 /* --- @class_create@ --- *
104 *
105 * Arguments: @unsigned type@ = type of the class to create
106 * @sym_table *t@ = pointer to symbol table which stores info
107 *
108 * Returns: Pointer to a @classdef@ which maintains the class's info.
109 *
110 * Use: Creates a new class definition. The new definition has one
111 * reference attached to it (which is the one you get returned).
112 */
113
114 classdef *class_create(unsigned type, sym_table *t)
115 {
116 classdef *c = xmalloc(sizeof(*c));
117 c->type = type;
118 c->ref = 1;
119 c->t = t;
120 return (c);
121 }
122
123 /* --- @class_inc@ --- *
124 *
125 * Arguments: @classdef *c@ = pointer to a class block
126 *
127 * Returns: ---
128 *
129 * Use: Adds a reference to the class definition.
130 */
131
132 void class_inc(classdef *c)
133 {
134 if (c != class_all)
135 c->ref++;
136 }
137
138 /* --- @class_dec@ --- *
139 *
140 * Arguments: @classdef *c@ = pointer to a class block
141 *
142 * Returns: ---
143 *
144 * Use: Removes a reference to a class block.
145 */
146
147 void class_dec(classdef *c)
148 {
149 if (c != class_all && !--c->ref) {
150 sym_destroyTable(c->t);
151 free(c);
152 }
153 }
154
155 /* --- @class_userMatch@ --- *
156 *
157 * Arguments: @classdef *c@ = pointer to a class block
158 * @int u@ = uid number to check against
159 *
160 * Returns: Zero if no match, nonzero if it matched.
161 *
162 * Use: Looks to see if a user is in a group.
163 */
164
165 int class_userMatch(classdef *c, int u)
166 {
167 if (~c->type & clType_user)
168 return (0);
169 else if (c == class_all)
170 return (1);
171 else
172 return (sym_find(c->t, (char *)&u, sizeof(u), 0, 0) != 0);
173 }
174
175 /* --- @class_commandMatch@ --- *
176 *
177 * Arguments: @classdef *c@ = pointer to a class block
178 * @const char *p@ = pointer to command string to match
179 *
180 * Returns: Zero for no match, nonzero if it matched.
181 *
182 * Use: Tries to match a string against the wildcard patterns in the
183 * given class. Note that this involves examining all the
184 * items, so it's not too quick. Then again, you don't have
185 * big command classes, do you...?
186 */
187
188 int class_commandMatch(classdef *c, const char *p)
189 {
190 sym_iter i;
191 sym_base *s;
192
193 if (~c->type & clType_command)
194 return (0);
195 else if (c == class_all)
196 return (1);
197 else {
198 for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
199 if (class__wildMatch(s->name, p))
200 return (1);
201 }
202 return (0);
203 }
204 }
205
206 /* --- @class_hostMatch@ --- *
207 *
208 * Arguments: @classdef *c@ = pointer to class block
209 * @struct in_addr addr@ = IP address to match
210 *
211 * Returns: Zero for no match, nonzero if it matched.
212 *
213 * Use: Tries to match an IP address against the patterns and masks
214 * in the given class.
215 */
216
217 int class_hostMatch(classdef *c, struct in_addr addr)
218 {
219 sym_iter i;
220 sym_base *s;
221 const char *a;
222 struct hostent *he;
223 char **p;
224
225 if (~c->type & clType_host)
226 return (0);
227 else if (c == class_all)
228 return (1);
229 else {
230
231 /* --- Get the dotted-quad and other names for the address --- */
232
233 if ((a = inet_ntoa(addr)) == 0)
234 return (0);
235 if ((he = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == 0)
236 return (0);
237
238 /* --- Now search the list for a match --- *
239 *
240 * This is almost infinitely slow, I'm afraid.
241 */
242
243 for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
244
245 /* --- Check the dotted-quad name first --- */
246
247 if (class__wildMatch(s->name, a))
248 return (1);
249
250 /* --- Now try the host's main name --- */
251
252 if (class__wildMatch(s->name, he->h_name))
253 return (1);
254
255 /* --- Now go through all the names --- */
256
257 for (p = he->h_aliases; *p; p++) {
258 if (class__wildMatch(s->name, *p))
259 return (1);
260 }
261 }
262 return (0);
263 }
264 }
265
266 /* --- @class_dump@ --- *
267 *
268 * Arguments: @classdef *c@ = pointer to a class block
269 * @FILE *fp@ = pointer to a stream object
270 *
271 * Returns: ---
272 *
273 * Use: Dumps the contents of a class to a stream.
274 */
275
276 void class_dump(classdef *c, FILE *fp)
277 {
278 sym_iter i;
279 sym_base *s;
280
281 /* --- Write a little header block --- */
282
283 {
284 const char *typetbl[] = {
285 "bad class",
286 "user",
287 "command",
288 "user/command",
289 "host",
290 "host/user",
291 "host/command",
292 "all",
293 };
294
295 fprintf(fp,
296 "*** Type: %s\n"
297 "*** Refs: %u\n"
298 "*** \n"
299 "*** Items:\n",
300 c->type < clType__limit ? typetbl[c->type] : "bad class",
301 c->ref);
302 }
303
304 /* --- Dump the table --- */
305
306 if (c->type != clType_all) {
307 for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
308 switch (c->type) {
309 case clType_user:
310 fprintf(fp, "*** %i\n", *(int *)s->name);
311 break;
312 case clType_command:
313 case clType_host:
314 fputs("*** ", fp);
315 fwrite(s->name, s->len, 1, fp);
316 putc('\n', fp);
317 break;
318 }
319 }
320 }
321
322 putc('\n', fp);
323 }
324
325 /*----- That's all, folks -------------------------------------------------*/