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