1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 /*
29 * This module fetches group and passwd structs for the caller. It
30 * uses a hash table to speed up retrieval of repeated entries. If
31 * the attempts to initialize the hash tables fail, this just
32 * continues the slow way.
33 */
34
35 #include <pwd.h>
36 #include <grp.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include "pkglib.h"
42 #include "pkglocale.h"
43 #include "nhash.h"
44
45 #define HASHSIZE 151
46 #define BSZ 4
47
48 #define ERR_DUPFAIL "%s: strdup(%s) failed.\n"
49 #define ERR_ADDFAIL "%s: add_cache() failed.\n"
50 #define ERR_BADMEMB "%s: %s in \"%s\" %s structure is invalid.\n"
51 #define ERR_NOGRP "dup_gr_ent(): no group entry provided.\n"
52 #define ERR_NOPWD "dup_pw_ent(): no passwd entry provided.\n"
53 #define ERR_NOINIT "%s: init_cache() failed.\n"
54 #define ERR_MALLOC "%s: malloc(%d) failed for %s.\n"
55
56 static Cache *pwnam_cache = (Cache *) NULL;
57 static Cache *grnam_cache = (Cache *) NULL;
58 static Cache *pwuid_cache = (Cache *) NULL;
59 static Cache *grgid_cache = (Cache *) NULL;
60
61 static int dup_gr_ent(struct group *grp);
62 static int dup_pw_ent(struct passwd *pwp);
63
64 /*
65 * These indicate whether the hash table has been initialized for the four
66 * categories.
67 */
68 static int is_a_pwnam_cache;
69 static int is_a_grnam_cache;
70 static int is_a_pwuid_cache;
71 static int is_a_grgid_cache;
72
73 extern char *get_install_root(void);
74
75 /*
76 * If there's a grnam cache, then update it with this new
77 * group, otherwise, skip it.
78 */
79 static Item *
cache_alloc(char * fname,int len,size_t struct_size)80 cache_alloc(char *fname, int len, size_t struct_size)
81 {
82 Item *itemp;
83
84 /*
85 * Allocate space for the Item pointer, key and data.
86 */
87 if ((itemp = (Item *) malloc(sizeof (*itemp))) ==
88 Null_Item) {
89 (void) fprintf(stderr,
90 pkg_gt(ERR_MALLOC), fname,
91 sizeof (*itemp), "itemp");
92 } else if ((itemp->key = (char *)malloc(len)) == NULL) {
93 (void) fprintf(stderr, pkg_gt(ERR_MALLOC), fname, len,
94 "itemp->key");
95 free(itemp);
96 } else if ((itemp->data = malloc(struct_size)) == NULL) {
97 (void) fprintf(stderr, pkg_gt(ERR_MALLOC), fname,
98 struct_size, "itemp->data");
99 free(itemp->key);
100 free(itemp);
101 } else {
102 /* Set length parameters. */
103 itemp->keyl = len;
104 itemp->datal = struct_size;
105
106 return (itemp);
107 }
108
109 return ((Item *) NULL);
110 }
111
112 /* Get the required group structure based upon the group name. */
113 struct group *
cgrnam(char * nam)114 cgrnam(char *nam)
115 {
116 struct group *grp;
117 Item *itemp;
118 int len;
119 static int cache_failed;
120
121 /* Attempt to initialize the grname cache. */
122 if (!is_a_grnam_cache && !cache_failed) {
123 if (init_cache(&grnam_cache, HASHSIZE, BSZ,
124 (int (*)())NULL, (int (*)())NULL) == -1) {
125 (void) fprintf(stderr, pkg_gt(ERR_NOINIT), "cgrnam()");
126 grnam_cache = (Cache *) NULL;
127 cache_failed = 1;
128 } else
129 is_a_grnam_cache = 1;
130 }
131
132 len = strlen(nam) + 1;
133
134 /* First look in the cache. Failing that, do it the hard way. */
135 if ((itemp = lookup_cache(grnam_cache, nam, len)) == Null_Item) {
136
137 /* Get the group by name. */
138 if ((grp = clgrnam(nam)) != NULL ||
139 (grp = getgrnam(nam)) != NULL) {
140 /* A group by that name exists on this machine. */
141 if (dup_gr_ent(grp))
142 /*
143 * Effectively no such group since struct
144 * couldn't be duplicated.
145 */
146 grp = (struct group *)NULL;
147 /*
148 * If there's a grnam cache, then update it with this
149 * new group, otherwise, skip it.
150 */
151 else if (is_a_grnam_cache) {
152 if ((itemp = cache_alloc("cgrnam()", len,
153 sizeof (struct group))) != Null_Item) {
154 /*
155 * With that allocated, insert the
156 * group name as key and set the key
157 * length.
158 */
159 (void) memmove(itemp->key, nam, len);
160
161 /*
162 * Insert the data associated with
163 * the key and the data length.
164 */
165 (void) memmove(itemp->data, grp,
166 sizeof (struct group));
167
168 /* Insert the Item into the cache. */
169 if (add_cache(grnam_cache, itemp) == -1)
170 (void) fprintf(stderr,
171 pkg_gt(ERR_ADDFAIL),
172 "cgrnam()");
173 }
174 }
175 }
176 return (grp);
177 } else /* Found it in the cache. */
178 return ((struct group *)itemp->data);
179 }
180
181 struct passwd *
cpwnam(char * nam)182 cpwnam(char *nam)
183 {
184 struct passwd *pwd;
185 Item *itemp;
186 int len;
187 static int cache_failed;
188
189 if (!is_a_pwnam_cache && !cache_failed) {
190 if (init_cache(&pwnam_cache, HASHSIZE, BSZ,
191 (int (*)())NULL, (int (*)())NULL) == -1) {
192 (void) fprintf(stderr, pkg_gt(ERR_NOINIT), "cpwnam()");
193 pwnam_cache = (Cache *) NULL;
194 cache_failed = 1;
195 } else
196 is_a_pwnam_cache = 1;
197 }
198
199 len = strlen(nam) + 1;
200
201 /* First look in the cache. Failing that, do it the hard way. */
202 if ((itemp = lookup_cache(pwnam_cache, nam, len)) == Null_Item) {
203
204 /* Get the passwd by name. */
205 if ((pwd = clpwnam(nam)) != NULL ||
206 (pwd = getpwnam(nam)) != NULL) {
207 /* A passwd by that name exists on this machine. */
208 if (dup_pw_ent(pwd))
209 /*
210 * Effectively no such passwd since struct
211 * couldn't be duplicated.
212 */
213 pwd = (struct passwd *)NULL;
214 /*
215 * If there's a pwnam cache, then update it with this
216 * new passwd, otherwise, skip it.
217 */
218 else if (is_a_pwnam_cache) {
219 /*
220 * Allocate space for the Item pointer, key
221 * and data.
222 */
223 if ((itemp = cache_alloc("cpwnam()", len,
224 sizeof (struct passwd))) != Null_Item) {
225 /*
226 * With that allocated, insert the
227 * group name as key and set the key
228 * length.
229 */
230 (void) memmove(itemp->key, nam, len);
231
232 /*
233 * Insert the data associated with
234 * the key and the data length.
235 */
236 (void) memmove(itemp->data, pwd,
237 sizeof (struct passwd));
238
239 if (add_cache(pwnam_cache, itemp) == -1)
240 (void) fprintf(stderr,
241 pkg_gt(ERR_ADDFAIL),
242 "cpwnam()");
243 }
244 }
245 }
246 return (pwd);
247 } else /* Found it in the cache. */
248 return ((struct passwd *)itemp->data);
249 }
250
251 static int
uid_hash(void * datap,int datalen,int hsz)252 uid_hash(void *datap, int datalen, int hsz)
253 {
254 #ifdef lint
255 int i = datalen;
256 datalen = i;
257 #endif /* lint */
258
259 return (*((uid_t *)datap) % hsz);
260 }
261
262 static int
uid_comp(void * datap1,void * datap2,int datalen)263 uid_comp(void *datap1, void *datap2, int datalen)
264 {
265 #ifdef lint
266 int i = datalen;
267 datalen = i;
268 #endif /* lint */
269
270 return (*((uid_t *)datap1) - *((uid_t *)datap2));
271 }
272
273 struct group *
cgrgid(gid_t gid)274 cgrgid(gid_t gid)
275 {
276 struct group *grp;
277 Item *itemp;
278 int len;
279 static int cache_failed;
280
281 if (!is_a_grgid_cache && !cache_failed) {
282 if (init_cache(&grgid_cache, HASHSIZE, BSZ,
283 uid_hash, uid_comp) == -1) {
284 (void) fprintf(stderr, pkg_gt(ERR_NOINIT), "cgrgid()");
285 grgid_cache = (Cache *) NULL;
286 cache_failed = 1;
287 } else
288 is_a_grgid_cache = 1;
289 }
290
291 len = sizeof (uid_t);
292
293 /* First look in the cache. Failing that, do it the hard way. */
294 if ((itemp = lookup_cache(grgid_cache, &gid, len)) == Null_Item) {
295 if ((grp = clgrgid(gid)) != NULL ||
296 (grp = getgrgid(gid)) != NULL) {
297 /* A group by that number exists on this machine. */
298 if (dup_gr_ent(grp))
299 /*
300 * Effectively no such group since struct
301 * couldn't be duplicated.
302 */
303 grp = (struct group *)NULL;
304 /*
305 * If there's a grnam cache, then update it with this
306 * new group, otherwise, skip it.
307 */
308 else if (is_a_grgid_cache) {
309 if ((itemp = cache_alloc("cgrgid()", len,
310 sizeof (struct group))) != Null_Item) {
311 /*
312 * With that allocated, insert the
313 * group name as key and set the key
314 * length.
315 */
316 (void) memmove(itemp->key, &gid, len);
317
318 /*
319 * Insert the data associated with
320 * the key and the data length.
321 */
322 (void) memmove(itemp->data, grp,
323 sizeof (struct group));
324
325 if (add_cache(grgid_cache, itemp) == -1)
326 (void) fprintf(stderr,
327 pkg_gt(ERR_ADDFAIL),
328 "cgrgid()");
329 }
330 }
331 }
332 return (grp);
333 } else /* Found it in the cache. */
334 return ((struct group *)itemp->data);
335 }
336
337 struct passwd *
cpwuid(uid_t uid)338 cpwuid(uid_t uid)
339 {
340 struct passwd *pwd;
341 Item *itemp;
342 int len;
343 static int cache_failed;
344
345 if (!is_a_pwuid_cache && !cache_failed) {
346 if (init_cache(&pwuid_cache, HASHSIZE, BSZ,
347 uid_hash, uid_comp) == -1) {
348 (void) fprintf(stderr,
349 pkg_gt(ERR_NOINIT), "cpwuid()");
350 pwuid_cache = (Cache *) NULL;
351 cache_failed = 1;
352 } else
353 is_a_pwuid_cache = 1;
354 }
355
356 len = sizeof (uid_t);
357
358 /* First look in the cache. Failing that, do it the hard way. */
359 if ((itemp = lookup_cache(pwuid_cache, &uid, len)) == Null_Item) {
360
361 /* Get the passwd by number. */
362 if ((pwd = clpwuid(uid)) != NULL ||
363 (pwd = getpwuid(uid)) != NULL) {
364 /* A passwd by that user ID exists on this machine. */
365 if (dup_pw_ent(pwd))
366 /*
367 * Effectively no such passwd since struct
368 * couldn't be duplicated.
369 */
370 pwd = (struct passwd *)NULL;
371 /*
372 * If there's a pwuid cache, then update it with this
373 * new passwd, otherwise, skip it.
374 */
375 else if (is_a_pwuid_cache) {
376 if ((itemp = cache_alloc("cpwuid()", len,
377 sizeof (struct passwd))) != Null_Item) {
378 /*
379 * With that allocated, insert the
380 * group name as key and set the key
381 * length.
382 */
383 (void) memmove(itemp->key, &uid, len);
384
385 /*
386 * Insert the data associated with
387 * the key and the data length.
388 */
389 (void) memmove(itemp->data, pwd,
390 sizeof (struct passwd));
391
392 if (add_cache(pwuid_cache, itemp) == -1)
393 (void) fprintf(stderr,
394 pkg_gt(ERR_ADDFAIL),
395 "cpwuid()");
396 }
397 }
398 }
399 return (pwd);
400 } else /* Found it in the cache. */
401 return ((struct passwd *)itemp->data);
402 }
403
404 /*
405 * This function duplicates the group structure provided from kernel static
406 * memory. There is a lot of defensive coding here because there have been
407 * problems with the getgr*() functions. They will sometimes provide NULL
408 * values instead of pointers to NULL values. There has been no explanation
409 * for the reason behind this; but, this function takes a NULL to be an
410 * invalid (char *) and returns an error.
411 */
412 static int
dup_gr_ent(struct group * grp)413 dup_gr_ent(struct group *grp)
414 {
415 char **tp = NULL;
416 char **memp = NULL;
417 int nent = 0; /* Number of entries in the member list. */
418
419 if (grp) {
420 if (grp->gr_name == NULL) {
421 (void) fprintf(stderr,
422 pkg_gt(ERR_BADMEMB), "dup_gr_ent()", "gr_name",
423 "unknown", "group");
424 return (-1);
425 } else if ((grp->gr_name = strdup(grp->gr_name)) == NULL) {
426 (void) fprintf(stderr,
427 pkg_gt(ERR_DUPFAIL), "dup_gr_ent()", "gr_name");
428 return (-1);
429 }
430 if (grp->gr_passwd == NULL) {
431 (void) fprintf(stderr,
432 pkg_gt(ERR_BADMEMB), "dup_gr_ent()", "gr_passwd",
433 grp->gr_name, "group");
434 return (-1);
435 } else if ((grp->gr_passwd = strdup(grp->gr_passwd)) == NULL) {
436 (void) fprintf(stderr,
437 pkg_gt(ERR_DUPFAIL), "dup_gr_ent()", "gr_passwd");
438 return (-1);
439 }
440 /*
441 * Allocate space for the member list and move the members
442 * into it.
443 */
444 if (grp->gr_mem) {
445 /*
446 * First count the members. The nent variable will be
447 * the number of members + 1 for the terminator.
448 */
449 for (tp = grp->gr_mem; *tp; nent++, tp++);
450
451 /* Now allocate room for the pointers. */
452 memp = malloc(sizeof (char **)* (nent+1));
453
454 if (memp == NULL) {
455 (void) fprintf(stderr,
456 pkg_gt(ERR_MALLOC), "dup_gr_ent()",
457 (sizeof (char **)* (nent+1)),
458 "memp");
459 return (-1);
460 }
461
462 /*
463 * Now copy over the pointers and entries. It should
464 * be noted that if the structure is messed up here,
465 * the resulting member list will be truncated at the
466 * NULL entry.
467 */
468 for (nent = 0, tp = grp->gr_mem; *tp; tp++) {
469 if ((memp[nent++] = strdup(*tp)) == NULL) {
470 (void) fprintf(stderr,
471 pkg_gt(ERR_DUPFAIL), "dup_gr_ent()",
472 "gr_mem");
473 return (-1);
474 }
475 }
476 } else {
477 (void) fprintf(stderr,
478 pkg_gt(ERR_BADMEMB), "dup_gr_ent()", "gr_mem",
479 grp->gr_name, "group");
480 return (-1);
481 }
482 } else {
483 (void) fprintf(stderr, pkg_gt(ERR_NOGRP));
484 return (-1);
485 }
486 memp[nent++] = '\0';
487 return (0);
488 }
489
490 /*
491 * This function duplicates the passwd structure provided from kernel static
492 * memory. As in the above function, since there have been problems with the
493 * getpw*() functions, the structure provided is rigorously scrubbed. This
494 * function takes a NULL to be an invalid (char *) and returns an error if
495 * one is detected.
496 */
497 static int
dup_pw_ent(struct passwd * pwd)498 dup_pw_ent(struct passwd *pwd)
499 {
500 if (pwd) {
501 if (pwd->pw_name == NULL) {
502 (void) fprintf(stderr,
503 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_name",
504 "unknown", "passwd");
505 return (-1);
506 } else if ((pwd->pw_name = strdup(pwd->pw_name)) == NULL) {
507 (void) fprintf(stderr,
508 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_name");
509 return (-1);
510 }
511
512 if (pwd->pw_passwd == NULL) {
513 (void) fprintf(stderr,
514 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_passwd",
515 pwd->pw_name, "passwd");
516 return (-1);
517 } else if ((pwd->pw_passwd = strdup(pwd->pw_passwd)) == NULL) {
518 (void) fprintf(stderr,
519 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_passwd");
520 return (-1);
521 }
522
523 if (pwd->pw_age == NULL) {
524 (void) fprintf(stderr,
525 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_age",
526 pwd->pw_name, "passwd");
527 return (-1);
528 } else if ((pwd->pw_age = strdup(pwd->pw_age)) == NULL) {
529 (void) fprintf(stderr,
530 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_age");
531 return (-1);
532 }
533
534 if (pwd->pw_comment == NULL) {
535 (void) fprintf(stderr,
536 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_comment",
537 pwd->pw_name, "passwd");
538 return (-1);
539 } else if ((pwd->pw_comment = strdup(pwd->pw_comment)) ==
540 NULL) {
541 (void) fprintf(stderr,
542 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_comment");
543 return (-1);
544 }
545
546 if (pwd->pw_gecos == NULL) {
547 (void) fprintf(stderr,
548 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_gecos",
549 pwd->pw_name, "passwd");
550 return (-1);
551 } else if ((pwd->pw_gecos = strdup(pwd->pw_gecos)) == NULL) {
552 (void) fprintf(stderr,
553 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_gecos");
554 return (-1);
555 }
556
557 if (pwd->pw_dir == NULL) {
558 (void) fprintf(stderr,
559 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_dir",
560 pwd->pw_name, "passwd");
561 return (-1);
562 } else if ((pwd->pw_dir = strdup(pwd->pw_dir)) == NULL) {
563 (void) fprintf(stderr,
564 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_dir");
565 return (-1);
566 }
567
568 if (pwd->pw_shell == NULL) {
569 (void) fprintf(stderr,
570 pkg_gt(ERR_BADMEMB), "dup_pw_ent()", "pw_shell",
571 pwd->pw_name, "passwd");
572 return (-1);
573 } else if ((pwd->pw_shell = strdup(pwd->pw_shell)) == NULL) {
574 (void) fprintf(stderr,
575 pkg_gt(ERR_DUPFAIL), "dup_pw_ent()", "pw_shell");
576 return (-1);
577 }
578 } else {
579 (void) fprintf(stderr, pkg_gt(ERR_NOPWD));
580 return (-1);
581 }
582
583 return (0);
584 }
585
586 /*
587 * Check the client's etc/group file for the group name
588 *
589 * returns a pointer to the group structure if the group is found
590 * returns NULL if not found
591 */
592 struct group *
clgrnam(char * nam)593 clgrnam(char *nam)
594 {
595 struct group *gr;
596 char *instroot, *buf;
597 FILE *gr_ptr;
598 size_t bufsz;
599
600 if ((instroot = get_install_root()) != NULL) {
601 bufsz = strlen(instroot) + strlen(GROUP) + 1;
602 if ((buf = (char *)malloc(bufsz)) == NULL) {
603 (void) fprintf(stderr,
604 pkg_gt(ERR_MALLOC), "clgrnam()",
605 strlen(instroot) + strlen(GROUP), "buf");
606 }
607 (void) snprintf(buf, bufsz, "%s%s", instroot, GROUP);
608 if ((gr_ptr = fopen(buf, "r")) == NULL) {
609 free(buf);
610 return (NULL);
611 } else {
612 while ((gr = fgetgrent(gr_ptr)) != NULL) {
613 if (strcmp(gr->gr_name, nam) == 0) {
614 break;
615 }
616 }
617 }
618 free(buf);
619 (void) fclose(gr_ptr);
620 return (gr);
621 } else {
622 return (NULL);
623 }
624 }
625
626 /*
627 * Check the client's etc/passwd file for the user name
628 *
629 * returns a pointer to the passwd structure if the passwd is found
630 * returns NULL if not found
631 */
632 struct passwd *
clpwnam(char * nam)633 clpwnam(char *nam)
634 {
635 struct passwd *pw;
636 char *instroot, *buf;
637 FILE *pw_ptr;
638
639 if ((instroot = get_install_root()) != NULL) {
640 if (asprintf(&buf, "%s%s", instroot, PASSWD) < 0) {
641 (void) fprintf(stderr,
642 pkg_gt(ERR_MALLOC), "clpwnam()",
643 strlen(instroot) + strlen(PASSWD), "buf");
644 return (NULL);
645 }
646 if ((pw_ptr = fopen(buf, "r")) == NULL) {
647 free(buf);
648 return (NULL);
649 } else {
650 while ((pw = fgetpwent(pw_ptr)) != NULL) {
651 if (strcmp(pw->pw_name, nam) == 0) {
652 break;
653 }
654 }
655 }
656 free(buf);
657 (void) fclose(pw_ptr);
658 return (pw);
659 } else {
660 return (NULL);
661 }
662 }
663
664 /*
665 * Check the client's etc/group file for the group id
666 *
667 * returns a pointer to the group structure if the group id is found
668 * returns NULL if not found
669 */
670 struct group *
clgrgid(gid_t gid)671 clgrgid(gid_t gid)
672 {
673 struct group *gr;
674 char *instroot, *buf;
675 FILE *gr_ptr;
676
677 if ((instroot = get_install_root()) != NULL) {
678 if (asprintf(&buf, "%s%s", instroot, GROUP) < 0) {
679 (void) fprintf(stderr,
680 pkg_gt(ERR_MALLOC), "clgrgid()",
681 strlen(instroot) + strlen(GROUP), "buf");
682 return (NULL);
683 }
684
685 if ((gr_ptr = fopen(buf, "r")) == NULL) {
686 free(buf);
687 return (NULL);
688 } else {
689 while ((gr = fgetgrent(gr_ptr)) != NULL) {
690 if (gr->gr_gid == gid) {
691 break;
692 }
693 }
694 }
695 free(buf);
696 (void) fclose(gr_ptr);
697 return (gr);
698 } else {
699 return (NULL);
700 }
701 }
702
703 /*
704 * Check the client's etc/passwd file for the user id
705 *
706 * returns a pointer to the passwd structure if the user id is found
707 * returns NULL if not found
708 */
709 struct passwd *
clpwuid(uid_t uid)710 clpwuid(uid_t uid)
711 {
712 struct passwd *pw;
713 char *instroot, *buf;
714 FILE *pw_ptr;
715
716 if ((instroot = get_install_root()) != NULL) {
717 if (asprintf(&buf, "%s%s", instroot, PASSWD) < 0) {
718 (void) fprintf(stderr, pkg_gt(ERR_MALLOC), "clpwuid()",
719 strlen(instroot) + strlen(PASSWD), "buf");
720 return (NULL);
721 }
722 if ((pw_ptr = fopen(buf, "r")) == NULL) {
723 free(buf);
724 return (NULL);
725 } else {
726 while ((pw = fgetpwent(pw_ptr)) != NULL) {
727 if (pw->pw_uid == uid) {
728 break;
729 }
730 }
731 }
732 free(buf);
733 (void) fclose(pw_ptr);
734 return (pw);
735 } else {
736 return (NULL);
737 }
738 }
739