3 * $Id: name.c,v 1.7 1998/04/23 13:23:56 mdw Exp $
5 * Looking up of names in symbol tables
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of `become'
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.
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.
24 * You should have received a copy of the GNU General Public License
25 * along with `become'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.7 1998/04/23 13:23:56 mdw
33 * Fix bugs involving empty classes.
35 * Revision 1.6 1998/01/12 16:46:14 mdw
38 * Revision 1.5 1997/09/17 10:26:11 mdw
39 * Use rewritten class handler. Support `none' class.
41 * Revision 1.4 1997/08/20 16:17:59 mdw
42 * Replace `name_reinit' by `name_end' for more sensible restart.
44 * Revision 1.3 1997/08/07 09:49:39 mdw
45 * Extensive modifications to handle netgroups. Also sanitise user and group
46 * names before adding them to the symbol table.
48 * Revision 1.2 1997/08/04 10:24:24 mdw
49 * Sources placed under CVS control.
51 * Revision 1.1 1997/07/21 13:47:46 mdw
56 /*----- Header files ------------------------------------------------------*/
58 /* --- ANSI headers --- */
65 /* --- Unix headers --- */
67 #include <sys/types.h>
68 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include <arpa/inet.h>
78 /* --- Local headers --- */
90 /*----- Static variables --------------------------------------------------*/
92 static sym_table name__table; /* Symbol table for everything */
94 /*----- Main code ---------------------------------------------------------*/
96 /* --- @name__get@ --- *
98 * Arguments: @const char *p@ = pointer to the name we want
99 * @unsigned type@ = type of class it should have
101 * Returns: A pointer to a name ready to use, or zero if there's a type
104 * Use: Creates a name of the appropriate type all ready to use.
107 static name *name__get(const char *p, unsigned type)
110 name *n = sym_find(&name__table, p, -1, sizeof(*n), &f);
113 return ((n->c && !(n->c->type & type)) ? 0 : n);
116 /* --- @name__sanitise@ --- *
118 * Arguments: @const char *n@ = pointer to a name
119 * @char *buf@ = pointer to a buffer of space
120 * @size_t sz@ = size of the buffer
122 * Returns: A pointer to the transformed name in the buffer, or null
123 * if there wasn't enough space.
125 * Use: Transforms a name so that it only contains nice characters.
128 static char *name__sanitise(const char *n, char *buf, size_t sz)
132 if (strlen(n) + 1 > sz)
136 if (isalnum((unsigned char)*n))
146 /* --- @name__users@ --- *
152 * Use: Adds all of the users registered with the user database to
153 * the name table. Also adds the users' primary groups.
156 static void name__users(void)
162 userdb_iterateUsers();
163 while ((pw = userdb_nextUser()) != 0) {
165 uid_t u = pw->pw_uid;
167 /* --- First, add the user to the table --- */
169 if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
170 (n = name__get(buf, clType_user)) != 0)
171 n->c = class_addUser(n->c, u);
173 /* --- Now handle the user's default group --- */
175 if ((gr = userdb_groupById(pw->pw_gid)) != 0 &&
176 name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
177 (n = name__get(buf, clType_user)) != 0)
178 n->c = class_addUser(n->c, u);
182 /* --- @name__groups@ --- *
188 * Use: Adds users into all of their supplementary groups.
191 static void name__groups(void)
198 userdb_iterateGroups();
199 while ((gr = userdb_nextGroup()) != 0) {
202 if (name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
203 (n = name__get(buf, clType_user)) != 0) {
205 /* --- Now add all of the members --- */
207 for (p = gr->gr_mem; *p; p++) {
208 if ((pw = userdb_userByName(*p)) != 0)
209 n->c = class_addUser(n->c, pw->pw_uid);
217 /* --- @name__scan@ --- *
219 * Arguments: @netg *n@ = the netgroup handle we're scanning
220 * @const char *host@ = the host name
221 * @const char *user@ = the user name
222 * @const char *domain@ = the (NIS?) domain name
223 * @void *ctx@ = some context pointer
225 * Returns: Zero to continue scanning.
227 * Use: Scans a netgroup, adding items to the name table.
230 /* --- A data type --- */
232 typedef struct name__scanctx {
233 char *name; /* Netgroup name prefixed with `?_'*/
234 unsigned f; /* Various interesting flags */
235 name *h; /* Name entry for hosts */
236 name *u; /* Name entry for users */
239 enum { f_host = 1, f_user = 2 };
241 /* --- And now for the real code --- */
243 static int name__scan(netg *n, const char *host, const char *user,
244 const char *domain, void *ctx)
246 name__scanctx *sc = ctx;
248 /* --- Add the host to the hosts class --- */
250 if (sc->f & f_host && host) {
255 /* --- First ensure that I have a host class --- */
259 sc->h = name__get(sc->name, clType_host);
266 /* --- Now that I've done that, try to add the host --- *
268 * I'll turn it into an IP address. There's less chance of confusion
272 if ((h = gethostbyname(host)) == 0)
274 memcpy(&in, h->h_addr, sizeof(in));
275 if ((a = inet_ntoa(in)) == 0)
277 sc->h->c = class_addString(sc->h->c, a);
281 /* --- Add the user to the users class --- */
283 if (sc->f & f_user && user) {
286 /* --- First ensure that I have a user class --- */
290 sc->u = name__get(sc->name, clType_user);
297 /* --- Add the user to the list --- */
299 if ((pw = userdb_userByName(user)) == 0)
301 sc->u->c = class_addUser(sc->u->c, pw->pw_uid);
308 /* --- @name__netgroups@ --- *
314 * Use: Populates the name table with netgroup information.
317 void name__netgroups(void)
326 while ((n = netg_next()) != 0) {
328 if (name__sanitise(p, buf + 2, sizeof(buf) - 2) == 0)
332 sc.f = f_host | f_user;
333 netg_scan(n, name__scan, &sc);
337 /* --- @name_init@ --- *
343 * Use: Initialises the name table. Requires the user database to
344 * be populated (see @userdb_local@ and @userdb_yp@, and
350 /* --- Initialise the name table --- */
352 sym_createTable(&name__table);
354 /* --- Add everyone into the table --- */
360 /* --- Finally add in the `all' and `none' classes --- *
362 * Do that now, to prevent them being overwritten by the above.
369 n = sym_find(&name__table, "all", -1, sizeof(name), &f);
374 n = sym_find(&name__table, "none", -1, sizeof(name), &f);
381 /* --- @name_end@ --- *
387 * Use: Closes down the name database, so that it can be
393 /* --- Empty the symbol table --- */
399 for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
405 /* --- Destroy and recreate the table --- */
407 sym_destroyTable(&name__table);
410 /* --- @name_find@ --- *
412 * Arguments: @const char *p@ = pointer to name to look up
413 * @unsigned create@ = whether to create the item
414 * @unsigned *f@ = whether the item was created
416 * Returns: Pointer to a @name@ block containing the symbol, or
417 * zero if it wasn't found and we didn't want to create a
420 * Use: Looks up a name in the symbol table and returns the
424 name *name_find(const char *p, unsigned create, unsigned *f)
426 /* --- This is a trivial veneer onto @sym_find@ --- */
428 return (sym_find(&name__table, p, -1, create ? sizeof(name) : 0, f));
431 /* --- @name_dump@ --- *
437 * Use: Dumps a complete listing of the symbol table.
446 trace(TRACE_DEBUG, "name: dumping names");
447 for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
448 trace(TRACE_DEBUG, "name: dumping `%s'", n->base.name);
450 trace(TRACE_DEBUG, "name: <empty>");
457 /*----- Test driver -------------------------------------------------------*/
464 traceon(stdout, TRACE_ALL);
470 /* printf("loaded (%lu)\n", track_memused()); */
477 /* printf("cleared (%lu)\n", track_memused()); */
478 /* track_memlist(); */
484 /* printf("reloaded (%lu)\n", track_memused()); */