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