chiark / gitweb /
Initial revision
[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 -------------------------------------------------*/