Light fixes for strange building.
[become] / src / userdb.c
CommitLineData
c4f2d992 1/* -*-c-*-
2 *
8bdddfb7 3 * $Id: userdb.c,v 1.10 2003/10/12 00:39:16 mdw Exp $
c4f2d992 4 *
5 * User database management
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: userdb.c,v $
8bdddfb7 32 * Revision 1.10 2003/10/12 00:39:16 mdw
33 * Light fixes for strange building.
34 *
f60a3434 35 * Revision 1.9 2003/10/12 00:14:55 mdw
36 * Major overhaul. Now uses DSA signatures rather than the bogus symmetric
37 * encrypt-and-hope thing. Integrated with mLib and Catacomb.
38 *
e171c3bf 39 * Revision 1.8 1998/06/08 11:21:22 mdw
40 * Fixed bug in password and group file reading: strtok doesn't handle
41 * double colons nicely.
42 *
a340752b 43 * Revision 1.7 1998/04/23 13:27:46 mdw
44 * Switch to using the ypstuff interface to YP server.
45 *
c758e654 46 * Revision 1.6 1998/01/12 16:46:33 mdw
47 * Fix copyright date.
48 *
49 * Revision 1.5 1997/09/17 10:24:08 mdw
d8cd61fe 50 * Use `uid_t' instead of `int' for uids and gids. Not quite sure why I
51 * didn't do this before.
52 *
53 * Revision 1.4 1997/08/20 16:24:58 mdw
46cc26eb 54 * Patch memory leak. Rename `userdb_reinit' to `userdb_end' for more
55 * sensible restart.
56 *
e893b83f 57 * Revision 1.3 1997/08/07 09:44:29 mdw
58 * Read NIS-based passwords from the YP server directly, rather than using
59 * `popen(ypcat)', which is probably both slower and less secure.
60 *
03f996bd 61 * Revision 1.2 1997/08/04 10:24:26 mdw
62 * Sources placed under CVS control.
63 *
64 * Revision 1.1 1997/07/21 13:47:43 mdw
c4f2d992 65 * Initial revision
66 *
67 */
68
69/*----- Header files ------------------------------------------------------*/
70
71/* --- ANSI headers --- */
72
73#include <ctype.h>
74#include <errno.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <string.h>
78
79/* --- Unix headers --- */
80
03f996bd 81#include "config.h"
82
c4f2d992 83#include <sys/types.h>
84
85#include <grp.h>
86#include <pwd.h>
87#include <unistd.h>
88
f60a3434 89/* --- mLib headers --- */
90
91#include <mLib/alloc.h>
92#include <mLib/sym.h>
93#include <mLib/trace.h>
94
c4f2d992 95/* --- Local headers --- */
96
e893b83f 97#include "become.h"
c4f2d992 98#include "userdb.h"
a340752b 99#include "ypstuff.h"
c4f2d992 100
101/*----- Type definitions --------------------------------------------------*/
102
103/* --- A map link --- */
104
105typedef struct userdb__node {
106 struct userdb__node *next;
107 void *rec;
108} userdb__node;
109
110/* --- A reference to a real record --- */
111
112typedef struct userdb__sym {
113 sym_base _base;
114 void *rec;
115} userdb__sym;
116
117/* --- A name- and number-mapping --- */
118
119typedef struct userdb__map {
120 sym_table nmap;
121 sym_table idmap;
122 userdb__node *list;
123} userdb__map;
124
125/*----- Static variables --------------------------------------------------*/
126
127static userdb__map userdb__users; /* Map of user info blocks */
128static sym_iter userdb__useri; /* Iterator for users */
129static userdb__map userdb__groups; /* Map of group info blocks */
130static sym_iter userdb__groupi; /* Iterator for groups */
131
132/*----- Map management functions ------------------------------------------*/
133
134/* --- @userdb__createMap@ --- *
135 *
136 * Arguments: @userdb__map *m@ = pointer to a map block
137 *
138 * Returns: ---
139 *
140 * Use: Initialises a map table.
141 */
142
143static void userdb__createMap(userdb__map *m)
144{
f60a3434 145 sym_create(&m->nmap);
146 sym_create(&m->idmap);
c4f2d992 147 m->list = 0;
148}
149
150/* --- @userdb__addToMap@ --- *
151 *
152 * Arguments: @userdb__map *m@ = pointer to the map block
153 * @const char *name@ = pointer to the item's name
d8cd61fe 154 * @uid_t id@ = the item's id number
c4f2d992 155 * @void *rec@ = pointer to the actual record
156 *
157 * Returns: ---
158 *
159 * Use: Adds an item to the given map.
160 */
161
162static void userdb__addToMap(userdb__map *m,
163 const char *name,
d8cd61fe 164 uid_t id, void *rec)
c4f2d992 165{
166 unsigned f;
167 userdb__sym *s;
168 userdb__node *n;
169
170 s = sym_find(&m->nmap, name, -1, sizeof(*s), &f);
171 if (!f)
172 s->rec = rec;
173
174 s = sym_find(&m->idmap, (char *)&id, sizeof(id), sizeof(*s), &f);
175 if (!f)
176 s->rec = rec;
177
178 n = xmalloc(sizeof(*n));
179 n->rec = rec;
180 n->next = m->list;
181 m->list = n;
182}
183
184/* --- @userdb__byName@ --- *
185 *
186 * Arguments: @userdb__map *m@ = pointer to a map block
187 * @const char *name@ = name to look up
188 *
189 * Returns: A pointer to the appropriate block, or zero if not found.
190 *
191 * Use: Looks up a name in a mapping and returns the result.
192 */
193
194static void *userdb__byName(userdb__map *m, const char *name)
195{
196 userdb__sym *s = sym_find(&m->nmap, name, -1, 0, 0);
197 return (s ? s->rec : 0);
198}
199
200/* --- @userdb__byId@ --- *
201 *
202 * Arguments: @userdb__map *m@ = pointer to a map block
d8cd61fe 203 * @uid_t id@ = id number to find
c4f2d992 204 *
205 * Returns: A pointer to the appropriate block, or zero if not found.
206 *
207 * Use: Looks up an ID in a mapping, and returns the result.
208 */
209
d8cd61fe 210static void *userdb__byId(userdb__map *m, uid_t id)
c4f2d992 211{
212 userdb__sym *s = sym_find(&m->idmap, (char *)&id, sizeof(id), 0, 0);
213 return (s ? s->rec : 0);
214}
215
216/* --- @userdb__clearMap@ --- *
217 *
218 * Arguments: @userdb__map *m@ = pointer to a map block
219 * @void (*freerec)(void *rec)@ = pointer to a free-record proc
220 *
221 * Returns: ---
222 *
223 * Use: Clears a map, emptying it and releasing the memory it
224 * occupied.
225 */
226
227static void userdb__clearMap(userdb__map *m, void (*freerec)(void *rec))
228{
229 userdb__node *n, *t;
230
f60a3434 231 sym_destroy(&m->nmap);
232 sym_destroy(&m->idmap);
c4f2d992 233
234 for (n = m->list; n; n = t) {
235 t = n->next;
236 freerec(n->rec);
237 free(n);
238 }
239}
240
241/*----- User and group block management -----------------------------------*/
242
243/* --- @userdb__dumpUser@ --- *
244 *
245 * Arguments: @const struct passwd *pw@ = pointer to a user block
c4f2d992 246 *
247 * Returns: ---
248 *
249 * Use: Writes a user's informationt to a stream.
250 */
251
f60a3434 252#ifndef NTRACE
c4f2d992 253
e893b83f 254static void userdb__dumpUser(const struct passwd *pw)
c4f2d992 255{
e893b83f 256 trace(TRACE_DEBUG,
257 "debug: name `%s' passwd `%s' uid %i gid %i",
258 pw->pw_name, pw->pw_passwd, (int)pw->pw_uid, (int)pw->pw_gid);
259 trace(TRACE_DEBUG,
260 "debug: ... gecos `%s' home `%s' shell `%s'",
261 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
c4f2d992 262}
263
c4f2d992 264#endif
265
e171c3bf 266/* --- @userdb__split@ --- *
267 *
268 * Arguments: @char *p@ = pointer to string
269 * @char **v@ = pointer to vector to fill in
270 * @int sz@ = maximum number of fields to split
271 *
272 * Returns: Number of fields extracted.
273 *
274 * Use: Splits a string into fields at colon characters.
275 */
276
277static int userdb__split(char *p, char **v, int sz)
278{
279 int count = 0;
280
281 *v++ = p; sz--; count++;
282 if (!sz)
283 goto done;
284 while (*p) {
285 if (*p++ == ':') {
286 p[-1] = 0;
287 *v++ = p; sz--; count++;
288 if (!sz)
289 goto done;
290 }
291 }
292 while (sz--)
293 *v++ = 0;
294
295done:
296 return (count);
297}
298
c4f2d992 299/* --- @userdb_copyUser@ --- *
300 *
301 * Arguments: @struct passwd *pw@ = pointer to block to copy
302 *
303 * Returns: Pointer to the copy.
304 *
305 * Use: Copies a user block. The copy is `deep' so all the strings
306 * are copied too. Free the copy with @userdb_freeUser@ when
307 * you don't want it any more.
308 */
309
310struct passwd *userdb_copyUser(struct passwd *pw)
311{
312 struct passwd *npw;
313
314 if (!pw)
315 return (0);
316
317 npw = xmalloc(sizeof(*npw));
318
319 npw->pw_name = xstrdup(pw->pw_name);
320 npw->pw_passwd = xstrdup(pw->pw_passwd);
321 npw->pw_uid = pw->pw_uid;
322 npw->pw_gid = pw->pw_gid;
323 npw->pw_gecos = xstrdup(pw->pw_gecos);
324 npw->pw_dir = xstrdup(pw->pw_dir);
325 npw->pw_shell = xstrdup(pw->pw_shell);
326
327 return (npw);
328}
329
330/* --- @userdb__buildUser@ --- *
331 *
332 * Arguments: @char *s@ = pointer to user string
333 *
334 * Returns: Pointer to a user block.
335 *
336 * Use: Converts a line from a user file into a password entry.
337 * Note that the string is corrupted by @strtok@ while it gets
338 * parsed.
339 */
340
341static struct passwd *userdb__buildUser(char *s)
342{
343 struct passwd *pw = xmalloc(sizeof(*pw));
e171c3bf 344 char *v[7];
c4f2d992 345
e171c3bf 346 if (userdb__split(s, v, 7) < 7) {
347 free(pw);
348 return (0);
349 }
c4f2d992 350
e171c3bf 351 pw->pw_name = xstrdup(v[0]);
352 pw->pw_passwd = xstrdup(v[1]);
353 pw->pw_uid = (uid_t)atol(v[2]);
354 pw->pw_gid = (gid_t)atol(v[3]);
355 pw->pw_gecos = xstrdup(v[4]);
356 pw->pw_dir = xstrdup(v[5]);
357 pw->pw_shell = xstrdup(v[6]);
358 return (pw);
c4f2d992 359}
360
361/* --- @userdb_freeUser@ --- *
362 *
363 * Arguments: @void *rec@ = pointer to a user record
364 *
365 * Returns: ---
366 *
367 * Use: Frees a user record.
368 */
369
370void userdb_freeUser(void *rec)
371{
372 struct passwd *pw;
373
374 if (!rec)
375 return;
376
377 pw = rec;
378 free(pw->pw_name);
379 free(pw->pw_passwd);
380 free(pw->pw_gecos);
381 free(pw->pw_dir);
382 free(pw->pw_shell);
383 free(pw);
384}
385
386/* --- @userdb__dumpGroup@ --- *
387 *
388 * Arguments: @const struct group *gr@ = pointer to a group block
389 * @FILE *fp@ = pointer to stream to write on
390 *
391 * Returns: ---
392 *
393 * Use: Writes a group's information to a stream.
394 */
395
f60a3434 396#ifndef NTRACE
c4f2d992 397
e893b83f 398static void userdb__dumpGroup(const struct group *gr)
c4f2d992 399{
400 char *const *p;
401
e893b83f 402 trace(TRACE_DEBUG,
403 "debug: name `%s' passwd `%s' gid %i",
c4f2d992 404 gr->gr_name, gr->gr_passwd, (int)gr->gr_gid);
405 for (p = gr->gr_mem; *p; p++)
e893b83f 406 trace(TRACE_DEBUG,"debug: ... `%s'", *p);
c4f2d992 407}
408
c4f2d992 409#endif
410
411/* --- @userdb_copyGroup@ --- *
412 *
413 * Arguments: @struct group *gr@ = pointer to group block
414 *
415 * Returns: Pointer to copied block
416 *
417 * Use: Copies a group block. The copy is `deep' so all the strings
418 * are copied too. Free the copy with @userdb_freeGroup@ when
419 * you don't want it any more.
420 */
421
422struct group *userdb_copyGroup(struct group *gr)
423{
424 struct group *ngr;
425 int i, max;
426
427 if (!gr)
428 return (0);
429
430 ngr = xmalloc(sizeof(*ngr));
431
432 ngr->gr_name = xstrdup(gr->gr_name);
433 ngr->gr_passwd = xstrdup(gr->gr_passwd);
434 ngr->gr_gid = gr->gr_gid;
435
436 for (max = 0; gr->gr_mem[max]; max++)
437 ;
438 ngr->gr_mem = xmalloc((max + 1) * sizeof(char *));
439 for (i = 0; i < max; i++)
440 ngr->gr_mem[i] = xstrdup(gr->gr_mem[i]);
441 ngr->gr_mem[max] = 0;
442
443 return (ngr);
444}
445
446/* --- @userdb__buildGroup@ --- *
447 *
448 * Arguments: @char *s@ = pointer to group line string
449 *
450 * Returns: Pointer to a group block
451 *
452 * Use: Parses an entry in the groups file. The string is garbled
453 * by @strtok@ as we go.
454 */
455
456static struct group *userdb__buildGroup(char *s)
457{
458 struct group *gr = xmalloc(sizeof(*gr));
e171c3bf 459 char *v[4];
c4f2d992 460 int i;
461
462 /* --- Do the easy bits --- */
463
e171c3bf 464 if (userdb__split(s, v, 4) < 3) {
465 free(gr);
466 return (0);
467 }
468 gr->gr_name = xstrdup(v[0]);
469 gr->gr_passwd = xstrdup(v[1]);
470 gr->gr_gid = (gid_t)atol(v[2]);
c4f2d992 471
472 /* --- Count the number of members --- */
473
e171c3bf 474 s = v[3];
c4f2d992 475 i = 0;
e171c3bf 476 if (s && s[0]) {
477 for (;;) {
478 i++;
479 if ((s = strpbrk(s, ",")) == 0)
480 break;
481 s++;
482 }
c4f2d992 483 }
484
485 /* --- Allocate the block and fill it --- */
486
487 gr->gr_mem = xmalloc((i + 1) * sizeof(char *));
488 i = 0;
e171c3bf 489 if (v[3]) {
490 s = strtok(v[3], ",");
491 while (s) {
492 gr->gr_mem[i++] = xstrdup(s);
493 s = strtok(0, ",");
494 }
495 }
c4f2d992 496 gr->gr_mem[i] = 0;
497
498 return (gr);
c4f2d992 499}
500
501/* --- @userdb_freeGroup@ --- *
502 *
503 * Arguments: @void *rec@ = pointer to a group record
504 *
505 * Returns: ---
506 *
507 * Use: Frees a group record.
508 */
509
510void userdb_freeGroup(void *rec)
511{
512 struct group *gr;
513 char **p;
514
515 if (!rec)
516 return;
517
518 gr = rec;
519 free(gr->gr_name);
520 free(gr->gr_passwd);
521 for (p = gr->gr_mem; *p; p++)
522 free(*p);
523 free(gr->gr_mem);
524 free(gr);
525}
526
03f996bd 527/*----- Answering queries -------------------------------------------------*/
c4f2d992 528
529/* --- @userdb_userByName@, @userdb_userById@ --- *
530 *
531 * Arguments: @const char *name@ = pointer to user's name
532 * @uid_t id@ = user id to find
533 *
534 * Returns: Pointer to user block, or zero if not found.
535 *
536 * Use: Looks up a user by name or id.
537 */
538
539struct passwd *userdb_userByName(const char *name)
540{ return (userdb__byName(&userdb__users, name)); }
541
542struct passwd *userdb_userById(uid_t id)
543{ return (userdb__byId(&userdb__users, id)); }
544
545/* --- @userdb_iterateUsers@, @userdb_iterateUsers_r@ --- *
546 *
547 * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator object
548 *
549 * Returns: ---
550 *
551 * Use: Initialises an iteration for the user database.
552 */
553
554void userdb_iterateUsers(void)
555{ userdb_iterateUsers_r(&userdb__useri); }
556
557void userdb_iterateUsers_r(userdb_iter *i)
f60a3434 558{ sym_mkiter(i, &userdb__users.nmap); }
c4f2d992 559
560/* --- @userdb_nextUser@, @userdb_nextUser_r@ --- *
561 *
562 * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator oject
563 *
564 * Returns: Pointer to the next user block, or null.
565 *
566 * Use: Returns another user block.
567 */
568
569struct passwd *userdb_nextUser(void)
570{ return (userdb_nextUser_r(&userdb__useri)); }
571
572struct passwd *userdb_nextUser_r(userdb_iter *i)
573{
574 userdb__sym *s = sym_next(i);
575 return (s ? s->rec : 0);
576}
577
578/* --- @userdb_groupByName@, @userdb_groupById@ --- *
579 *
580 * Arguments: @const char *name@ = pointer to group's name
581 * @gid_t id@ = group id to find
582 *
583 * Returns: Pointer to group block, or zero if not found.
584 *
585 * Use: Looks up a group by name or id.
586 */
587
588struct group *userdb_groupByName(const char *name)
589{ return (userdb__byName(&userdb__groups, name)); }
590
591struct group *userdb_groupById(gid_t id)
592{ return (userdb__byId(&userdb__groups, id)); }
593
594/* --- @userdb_iterateGroups@, @userdb_iterateGroups_r@ --- *
595 *
596 * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator object
597 *
598 * Returns: ---
599 *
600 * Use: Initialises an iteration for the group database.
601 */
602
603void userdb_iterateGroups(void)
604{ userdb_iterateGroups_r(&userdb__groupi); }
605
606void userdb_iterateGroups_r(userdb_iter *i)
f60a3434 607{ sym_mkiter(i, &userdb__groups.nmap); }
c4f2d992 608
609/* --- @userdb_nextGroup@, @userdb_nextGroup_r@ --- *
610 *
611 * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator oject
612 *
613 * Returns: Pointer to the next group block, or null.
614 *
615 * Use: Returns another group block.
616 */
617
618struct group *userdb_nextGroup(void)
619{ return (userdb_nextGroup_r(&userdb__groupi)); }
620
621struct group *userdb_nextGroup_r(userdb_iter *i)
622{
623 userdb__sym *s = sym_next(i);
624 return (s ? s->rec : 0);
625}
626
03f996bd 627/*----- Yellow pages support ----------------------------------------------*/
628
629#ifdef HAVE_YP
630
631/* --- @userdb__foreachUser@ --- *
632 *
633 * Arguments: @int st@ = YP protocol-level status code
634 * @char *k@ = address of the key for this record
635 * @int ksz@ = size of the key
636 * @char *v@ = address of the value for this record
637 * @int vsz@ = size of the value
638 * @char *data@ = pointer to some data passed to me
639 *
640 * Returns: Zero to be called again, nonzero to end the enumeration.
641 *
642 * Use: Handles an incoming user record.
643 */
644
645static int userdb__foreachUser(int st, char *k, int ksz,
646 char *v, int vsz, char *data)
647{
648 char *cv;
649 struct passwd *pw;
650
651 if (st != YP_TRUE)
652 return (-1);
653 cv = xmalloc(vsz + 1);
654 memcpy(cv, v, vsz);
655 cv[vsz] = 0;
e893b83f 656 T( trace(TRACE_DEBUG, "debug: nis string: `%s'", cv); )
03f996bd 657 pw = userdb__buildUser(cv);
e893b83f 658 if (pw && !userdb__byName(&userdb__users, pw->pw_name)) {
659 IF_TRACING(TRACE_DEBUG, userdb__dumpUser(pw); )
03f996bd 660 userdb__addToMap(&userdb__users, pw->pw_name, pw->pw_uid, pw);
46cc26eb 661 } else
662 userdb_freeUser(pw);
03f996bd 663 free(cv);
664 return (0);
665}
666
667/* --- @userdb__foreachGroup@ --- *
668 *
669 * Arguments: @int st@ = YP protocol-level status code
670 * @char *k@ = address of the key for this record
671 * @int ksz@ = size of the key
672 * @char *v@ = address of the value for this record
673 * @int vsz@ = size of the value
674 * @char *data@ = pointer to some data passed to me
675 *
676 * Returns: Zero to be called again, nonzero to end the enumeration.
677 *
678 * Use: Handles an incoming user record.
679 */
680
681static int userdb__foreachGroup(int st, char *k, int ksz,
682 char *v, int vsz, char *data)
683{
684 char *cv;
685 struct group *gr;
686
687 if (st != YP_TRUE)
688 return (-1);
689 cv = xmalloc(vsz + 1);
690 memcpy(cv, v, vsz);
691 cv[vsz] = 0;
e893b83f 692 T( trace(TRACE_DEBUG, "debug: nis string: `%s'", cv); )
03f996bd 693 gr = userdb__buildGroup(cv);
e893b83f 694 if (gr && !userdb__byName(&userdb__groups, gr->gr_name)) {
695 IF_TRACING(TRACE_DEBUG, userdb__dumpGroup(gr); )
03f996bd 696 userdb__addToMap(&userdb__groups, gr->gr_name, gr->gr_gid, gr);
46cc26eb 697 } else
698 userdb_freeGroup(gr);
03f996bd 699 free(cv);
700 return (0);
701}
702
703/* --- @userdb_yp@ --- *
704 *
705 * Arguments: ---
706 *
707 * Returns: ---
708 *
709 * Use: Fetches the YP database of users.
710 */
711
712void userdb_yp(void)
713{
03f996bd 714 /* --- Bind to a server --- */
715
a340752b 716 ypstuff_bind();
717 if (!yp_domain)
03f996bd 718 return;
719
e893b83f 720 T( trace(TRACE_DEBUG, "debug: adding NIS users"); )
721
03f996bd 722 /* --- Fetch the users map --- */
723
724 {
725 static struct ypall_callback ucb = { userdb__foreachUser, 0 };
a340752b 726 yp_all(yp_domain, "passwd.byuid", &ucb);
03f996bd 727 }
728
729 /* --- Fetch the groups map --- */
730
731 {
732 static struct ypall_callback gcb = { userdb__foreachGroup, 0 };
a340752b 733 yp_all(yp_domain, "group.bygid", &gcb);
03f996bd 734 }
03f996bd 735}
736
737#else
738
739void userdb_yp(void) { ; }
740
741#endif
742
743/*----- Building the databases --------------------------------------------*/
744
745/* --- @userdb_local@ --- *
746 *
747 * Arguments: ---
748 *
749 * Returns: ---
750 *
751 * Use: Reads the local list of users into the maps.
752 */
753
754void userdb_local(void)
755{
e893b83f 756 T( trace(TRACE_DEBUG, "debug: adding local users"); )
03f996bd 757
758 /* --- Fetch users first --- */
759
760 {
761 struct passwd *pw;
762
763 setpwent();
764 while ((pw = getpwent()) != 0) {
e893b83f 765 IF_TRACING(TRACE_DEBUG, userdb__dumpUser(pw); )
03f996bd 766 if (!userdb__byName(&userdb__users, pw->pw_name))
767 userdb__addToMap(&userdb__users, pw->pw_name, pw->pw_uid,
768 userdb_copyUser(pw));
769 }
770 endpwent();
771 }
772
773 /* --- Then fetch groups --- */
774
775 {
776 struct group *gr;
777
778 setgrent();
779 while ((gr = getgrent()) != 0) {
e893b83f 780 IF_TRACING(TRACE_DEBUG, userdb__dumpGroup(gr); )
03f996bd 781 if (!userdb__byName(&userdb__groups, gr->gr_name))
782 userdb__addToMap(&userdb__groups, gr->gr_name, gr->gr_gid,
783 userdb_copyGroup(gr));
784 }
785 endgrent();
786 }
787}
788
c4f2d992 789/* --- @userdb_init@ --- *
790 *
791 * Arguments: ---
792 *
793 * Returns: ---
794 *
795 * Use: Initialises the user database.
796 */
797
798void userdb_init(void)
799{
800 userdb__createMap(&userdb__users);
801 userdb__createMap(&userdb__groups);
802}
803
46cc26eb 804/* --- @userdb_end@ --- *
c4f2d992 805 *
806 * Arguments: ---
807 *
808 * Returns: ---
809 *
46cc26eb 810 * Use: Closes down the user database.
c4f2d992 811 */
812
46cc26eb 813void userdb_end(void)
c4f2d992 814{
815 userdb__clearMap(&userdb__users, userdb_freeUser);
816 userdb__clearMap(&userdb__groups, userdb_freeGroup);
c4f2d992 817}
818
819/*----- Test rig ----------------------------------------------------------*/
820
821#ifdef TEST_RIG
822
823void dumpit(const char *msg)
824{
e893b83f 825 trace(TRACE_DEBUG, "debug: %s", msg);
c4f2d992 826
827 {
828 struct passwd *pw;
829 for (userdb_iterateUsers(); (pw = userdb_nextUser()) != 0; )
e893b83f 830 userdb__dumpUser(pw);
c4f2d992 831 }
832
833 {
834 struct group *gr;
835 for (userdb_iterateGroups(); (gr = userdb_nextGroup()) != 0; )
e893b83f 836 userdb__dumpGroup(gr);
c4f2d992 837 }
838}
839
840int main(void)
841{
e893b83f 842 ego("userdb-test");
8bdddfb7 843 trace_on(stdout, TRACE_ALL);
c4f2d992 844 userdb_init();
e893b83f 845 userdb_local();
46cc26eb 846 userdb_yp();
a340752b 847 dumpit("spong");
848/* printf("loaded (%lu)\n", track_memused()); */
46cc26eb 849 getchar();
850 for (;;) {
851 userdb_end();
a340752b 852/* printf("cleared (%lu)\n", track_memused()); */
46cc26eb 853/* track_memlist(); */
854 userdb_init();
855 userdb_local();
856 userdb_yp();
a340752b 857/* printf("reloaded (%lu)\n", track_memused()); */
46cc26eb 858 getchar();
859 }
c4f2d992 860 return (0);
861}
862
863#endif
864
865/*----- That's all, folks -------------------------------------------------*/