Fix copyright date.
[become] / src / name.c
CommitLineData
c4f2d992 1/* -*-c-*-
2 *
c758e654 3 * $Id: name.c,v 1.6 1998/01/12 16:46:14 mdw Exp $
c4f2d992 4 *
5 * Looking up of names in symbol tables
6 *
c758e654 7 * (c) 1998 EBI
c4f2d992 8 */
9
03f996bd 10/*----- Licensing notice --------------------------------------------------*
c4f2d992 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
03f996bd 25 * along with `become'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
c4f2d992 27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: name.c,v $
c758e654 32 * Revision 1.6 1998/01/12 16:46:14 mdw
33 * Fix copyright date.
34 *
35 * Revision 1.5 1997/09/17 10:26:11 mdw
2e11036b 36 * Use rewritten class handler. Support `none' class.
37 *
38 * Revision 1.4 1997/08/20 16:17:59 mdw
e6677daf 39 * Replace `name_reinit' by `name_end' for more sensible restart.
40 *
607937a4 41 * Revision 1.3 1997/08/07 09:49:39 mdw
42 * Extensive modifications to handle netgroups. Also sanitise user and group
43 * names before adding them to the symbol table.
44 *
03f996bd 45 * Revision 1.2 1997/08/04 10:24:24 mdw
46 * Sources placed under CVS control.
47 *
48 * Revision 1.1 1997/07/21 13:47:46 mdw
c4f2d992 49 * Initial revision
50 *
51 */
52
53/*----- Header files ------------------------------------------------------*/
54
55/* --- ANSI headers --- */
56
607937a4 57#include <ctype.h>
c4f2d992 58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61
62/* --- Unix headers --- */
63
607937a4 64#include <sys/types.h>
65#include <sys/socket.h>
03f996bd 66
607937a4 67#include <netinet/in.h>
03f996bd 68
607937a4 69#include <arpa/inet.h>
70
71#include <netdb.h>
c4f2d992 72#include <grp.h>
73#include <pwd.h>
74
75/* --- Local headers --- */
76
607937a4 77#include "config.h"
78
03f996bd 79#include "become.h"
c4f2d992 80#include "class.h"
81#include "name.h"
607937a4 82#include "netg.h"
c4f2d992 83#include "sym.h"
84#include "userdb.h"
85#include "utils.h"
86
87/*----- Static variables --------------------------------------------------*/
88
89static sym_table name__table; /* Symbol table for everything */
90
91/*----- Main code ---------------------------------------------------------*/
92
607937a4 93/* --- @name__get@ --- *
94 *
95 * Arguments: @const char *p@ = pointer to the name we want
96 * @unsigned type@ = type of class it should have
97 *
98 * Returns: A pointer to a name ready to use, or zero if there's a type
99 * conflict.
100 *
101 * Use: Creates a name of the appropriate type all ready to use.
102 */
103
104static name *name__get(const char *p, unsigned type)
105{
106 unsigned f;
107 name *n = sym_find(&name__table, p, -1, sizeof(*n), &f);
2e11036b 108 if (!f)
109 n->c = 0;
110 return ((n->c && !(n->c->type & type)) ? 0 : n);
607937a4 111}
112
113/* --- @name__sanitise@ --- *
114 *
115 * Arguments: @const char *n@ = pointer to a name
116 * @char *buf@ = pointer to a buffer of space
117 * @size_t sz@ = size of the buffer
118 *
119 * Returns: A pointer to the transformed name in the buffer, or null
120 * if there wasn't enough space.
121 *
122 * Use: Transforms a name so that it only contains nice characters.
123 */
124
125static char *name__sanitise(const char *n, char *buf, size_t sz)
126{
127 char *p = buf;
128
129 if (strlen(n) + 1 > sz)
130 return (0);
131
132 while (*n) {
133 if (isalnum((unsigned char)*n))
134 *p++ = *n;
135 else
136 *p++ = '_';
137 n++;
138 }
139 *p++ = 0;
140 return (buf);
141}
142
03f996bd 143/* --- @name__users@ --- *
c4f2d992 144 *
145 * Arguments: ---
146 *
147 * Returns: ---
148 *
03f996bd 149 * Use: Adds all of the users registered with the user database to
150 * the name table. Also adds the users' primary groups.
c4f2d992 151 */
152
03f996bd 153static void name__users(void)
c4f2d992 154{
03f996bd 155 struct passwd *pw;
156 struct group *gr;
607937a4 157 char buf[32];
c4f2d992 158
03f996bd 159 userdb_iterateUsers();
160 while ((pw = userdb_nextUser()) != 0) {
03f996bd 161 name *n;
2e11036b 162 uid_t u = pw->pw_uid;
607937a4 163
03f996bd 164 /* --- First, add the user to the table --- */
c4f2d992 165
607937a4 166 if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
167 (n = name__get(buf, clType_user)) != 0)
2e11036b 168 n->c = class_addUser(n->c, u);
c4f2d992 169
03f996bd 170 /* --- Now handle the user's default group --- */
c4f2d992 171
607937a4 172 if ((gr = userdb_groupById(pw->pw_gid)) != 0 &&
173 name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
174 (n = name__get(buf, clType_user)) != 0)
2e11036b 175 n->c = class_addUser(n->c, u);
03f996bd 176 }
177}
c4f2d992 178
03f996bd 179/* --- @name__groups@ --- *
180 *
181 * Arguments: ---
182 *
183 * Returns: ---
184 *
185 * Use: Adds users into all of their supplementary groups.
186 */
187
188static void name__groups(void)
189{
190 struct group *gr;
191 struct passwd *pw;
192 char **p;
607937a4 193 char buf[32];
03f996bd 194
195 userdb_iterateGroups();
196 while ((gr = userdb_nextGroup()) != 0) {
03f996bd 197 name *n;
c4f2d992 198
607937a4 199 if (name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
200 (n = name__get(buf, clType_user)) != 0) {
03f996bd 201
607937a4 202 /* --- Now add all of the members --- */
203
204 for (p = gr->gr_mem; *p; p++) {
2e11036b 205 if ((pw = userdb_userByName(*p)) != 0)
206 n->c = class_addUser(n->c, pw->pw_uid);
607937a4 207 }
03f996bd 208 }
607937a4 209 }
210}
03f996bd 211
607937a4 212/* --- @name__scan@ --- *
213 *
214 * Arguments: @netg *n@ = the netgroup handle we're scanning
215 * @const char *host@ = the host name
216 * @const char *user@ = the user name
217 * @const char *domain@ = the (NIS?) domain name
218 * @void *ctx@ = some context pointer
219 *
220 * Returns: Zero to continue scanning.
221 *
222 * Use: Scans a netgroup, adding items to the name table.
223 */
224
225/* --- A data type --- */
226
227typedef struct name__scanctx {
228 char *name; /* Netgroup name prefixed with `?_'*/
229 unsigned f; /* Various interesting flags */
230 name *h; /* Name entry for hosts */
231 name *u; /* Name entry for users */
232} name__scanctx;
233
234enum { f_host = 1, f_user = 2 };
235
236/* --- And now for the real code --- */
237
238static int name__scan(netg *n, const char *host, const char *user,
239 const char *domain, void *ctx)
240{
241 name__scanctx *sc = ctx;
242
243 /* --- Add the host to the hosts class --- */
244
245 if (sc->f & f_host && host) {
246 struct hostent *h;
247 struct in_addr in;
248 const char *a;
249
250 /* --- First ensure that I have a host class --- */
251
252 if (!sc->h) {
253 sc->name[0] = 'h';
254 sc->h = name__get(sc->name, clType_host);
255 if (!sc->h) {
256 sc->f &= ~f_host;
257 goto done_host;
258 }
259 }
260
261 /* --- Now that I've done that, try to add the host --- *
262 *
263 * I'll turn it into an IP address. There's less chance of confusion
264 * that way.
265 */
266
267 if ((h = gethostbyname(host)) == 0)
268 goto done_host;
269 memcpy(&in, h->h_addr, sizeof(in));
270 if ((a = inet_ntoa(in)) == 0)
271 goto done_host;
2e11036b 272 sc->h->c = class_addString(sc->h->c, a);
607937a4 273 done_host:;
274 }
275
276 /* --- Add the user to the users class --- */
03f996bd 277
607937a4 278 if (sc->f & f_user && user) {
279 struct passwd *pw;
607937a4 280
281 /* --- First ensure that I have a user class --- */
282
283 if (!sc->u) {
284 sc->name[0] = 'u';
285 sc->u = name__get(sc->name, clType_user);
286 if (!sc->u) {
287 sc->f &= ~f_user;
288 goto done_user;
c4f2d992 289 }
290 }
607937a4 291
292 /* --- Add the user to the list --- */
293
294 if ((pw = userdb_userByName(user)) == 0)
295 goto done_user;
2e11036b 296 sc->u->c = class_addUser(sc->u->c, pw->pw_uid);
607937a4 297 done_user:;
298 }
299
300 return (0);
301}
302
303/* --- @name__netgroups@ --- *
304 *
305 * Arguments: ---
306 *
307 * Returns: ---
308 *
309 * Use: Populates the name table with netgroup information.
310 */
311
312void name__netgroups(void)
313{
314 netg *n;
315 char buf[32];
316 const char *p;
317 name__scanctx sc;
318
319 netg_iterate();
320 buf[1] = '_';
321 while ((n = netg_next()) != 0) {
322 p = netg_name(n);
323 if (name__sanitise(p, buf + 2, sizeof(buf) - 2) == 0)
324 continue;
325 sc.name = buf;
326 sc.u = sc.h = 0;
327 sc.f = f_host | f_user;
328 netg_scan(n, name__scan, &sc);
c4f2d992 329 }
03f996bd 330}
c4f2d992 331
03f996bd 332/* --- @name_init@ --- *
333 *
334 * Arguments: ---
335 *
336 * Returns: ---
337 *
338 * Use: Initialises the name table. Requires the user database to
607937a4 339 * be populated (see @userdb_local@ and @userdb_yp@, and
340 * @netg_init@).
03f996bd 341 */
c4f2d992 342
03f996bd 343void name_init(void)
344{
345 /* --- Initialise the name table --- */
c4f2d992 346
03f996bd 347 sym_createTable(&name__table);
c4f2d992 348
03f996bd 349 /* --- Add everyone into the table --- */
c4f2d992 350
03f996bd 351 name__users();
352 name__groups();
607937a4 353 name__netgroups();
c4f2d992 354
2e11036b 355 /* --- Finally add in the `all' and `none' classes --- *
c4f2d992 356 *
2e11036b 357 * Do that now, to prevent them being overwritten by the above.
c4f2d992 358 */
359
360 {
361 name *n;
362 unsigned f;
363
364 n = sym_find(&name__table, "all", -1, sizeof(name), &f);
365 if (f)
366 class_dec(n->c);
367 n->c = class_all;
2e11036b 368
369 n = sym_find(&name__table, "none", -1, sizeof(name), &f);
370 if (f)
371 class_dec(n->c);
372 n->c = class_none;
c4f2d992 373 }
374}
375
e6677daf 376/* --- @name_end@ --- *
c4f2d992 377 *
378 * Arguments: ---
379 *
380 * Returns: ---
381 *
e6677daf 382 * Use: Closes down the name database, so that it can be
383 * reinitialised.
c4f2d992 384 */
385
e6677daf 386void name_end(void)
c4f2d992 387{
388 /* --- Empty the symbol table --- */
389
390 {
391 sym_iter i;
392 name *n;
393
394 for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
395 if (n->c)
396 class_dec(n->c);
397 }
398 }
399
400 /* --- Destroy and recreate the table --- */
401
402 sym_destroyTable(&name__table);
c4f2d992 403}
404
405/* --- @name_find@ --- *
406 *
407 * Arguments: @const char *p@ = pointer to name to look up
408 * @unsigned create@ = whether to create the item
409 * @unsigned *f@ = whether the item was created
410 *
411 * Returns: Pointer to a @name@ block containing the symbol, or
412 * zero if it wasn't found and we didn't want to create a
413 * new one.
414 *
415 * Use: Looks up a name in the symbol table and returns the
416 * item so located.
417 */
418
419name *name_find(const char *p, unsigned create, unsigned *f)
420{
421 /* --- This is a trivial veneer onto @sym_find@ --- */
422
423 return (sym_find(&name__table, p, -1, create ? sizeof(name) : 0, f));
424}
425
426/* --- @name_dump@ --- *
427 *
03f996bd 428 * Arguments: ---
c4f2d992 429 *
430 * Returns: ---
431 *
432 * Use: Dumps a complete listing of the symbol table.
433 */
434
03f996bd 435void name_dump(void)
c4f2d992 436{
e6677daf 437#ifdef TRACING
c4f2d992 438 sym_iter i;
439 name *n;
440
03f996bd 441 trace(TRACE_DEBUG, "name: dumping names");
c4f2d992 442 for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
03f996bd 443 trace(TRACE_DEBUG, "name: dumping `%s'", n->base.name);
2e11036b 444 class_dump(n->c, 1);
c4f2d992 445 }
e6677daf 446#endif
c4f2d992 447}
448
449/*----- Test driver -------------------------------------------------------*/
450
451#ifdef TEST_RIG
452
453int main(void)
454{
607937a4 455 ego("name-test");
e6677daf 456 /* traceon(stdout, TRACE_ALL); */
c4f2d992 457 userdb_init();
458 userdb_local();
459 userdb_yp();
607937a4 460 netg_init();
c4f2d992 461 name_init();
e6677daf 462 printf("loaded (%lu)\n", track_memused());
463 getchar();
464 for (;;) {
465 name_end();
466 netg_end();
467 userdb_end();
468 printf("cleared (%lu)\n", track_memused());
469 track_memlist();
470 userdb_init();
471 userdb_local();
472 userdb_yp();
473 netg_init();
474 name_init();
475 printf("reloaded (%lu)\n", track_memused());
476 getchar();
477 }
c4f2d992 478 return (0);
479}
480
481#endif