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