MFC:
[dragonfly.git] / lib / libc / gen / getpwent.c
blob507896af78e7a08414e6119b38aae353977c04ac
1 /*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * @(#)getpwent.c 8.2 (Berkeley) 4/27/95
34 * $FreeBSD: src/lib/libc/gen/getpwent.c,v 1.53.2.2 2001/03/05 09:52:13 obrien Exp $
35 * $DragonFly: src/lib/libc/gen/getpwent.c,v 1.7 2005/11/19 22:32:53 swildner Exp $
38 #include "namespace.h"
39 #include <stdio.h>
40 #include <sys/param.h>
41 #include <fcntl.h>
42 #include <syslog.h>
43 #include <pwd.h>
44 #include <utmp.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <limits.h>
50 #include <grp.h>
51 #include "un-namespace.h"
53 #include <db.h>
55 extern void setnetgrent ( char * );
56 extern int getnetgrent ( char **, char **, char ** );
57 extern int innetgr ( const char *, const char *, const char *, const char * );
60 * The lookup techniques and data extraction code here must be kept
61 * in sync with that in `pwd_mkdb'.
64 static struct passwd _pw_passwd; /* password structure */
65 static DB *_pw_db; /* password database */
66 static int _pw_keynum; /* key counter */
67 static int _pw_stayopen; /* keep fd's open */
68 #ifdef YP
69 #include <rpc/rpc.h>
70 #include <rpcsvc/yp_prot.h>
71 #include <rpcsvc/ypclnt.h>
73 static struct passwd _pw_copy;
74 static DBT empty = { NULL, 0 };
75 static DB *_ypcache = (DB *)NULL;
76 static int _yp_exclusions = 0;
77 static int _yp_enabled = -1;
78 static int _pw_stepping_yp; /* set true when stepping thru map */
79 static char _ypnam[YPMAXRECORD];
80 #define YP_HAVE_MASTER 2
81 #define YP_HAVE_ADJUNCT 1
82 #define YP_HAVE_NONE 0
83 static int _gotmaster;
84 static char *_pw_yp_domain;
85 static inline int unwind ( char * );
86 static void _ypinitdb ( void );
87 static int _havemaster (char *);
88 static int _getyppass (struct passwd *, const char *, const char * );
89 static int _nextyppass (struct passwd *);
90 static inline int lookup (const char *);
91 static inline void store (const char *);
92 static inline int ingr (const char *, const char*);
93 static inline int verf (const char *);
94 static char * _get_adjunct_pw (const char *);
95 #endif
96 static int __hashpw(DBT *);
97 static int __initdb(void);
101 * Parse the + entries in the password database and do appropriate
102 * NIS lookups. While ugly to look at, this is optimized to do only
103 * as many lookups as are absolutely necessary in any given case.
104 * Basically, the getpwent() function will feed us + and - lines
105 * as they appear in the database. For + lines, we do netgroup/group
106 * and user lookups to find all usernames that match the rule and
107 * extract them from the NIS passwd maps. For - lines, we save the
108 * matching names in a database and a) exlude them, and b) make sure
109 * we don't consider them when processing other + lines that appear
110 * later.
112 static inline int
113 unwind(char *grp)
115 char *user, *host, *domain;
116 static int latch = 0;
117 static struct group *gr = NULL;
118 int rv = 0;
120 if (grp[0] == '+') {
121 if (strlen(grp) == 1) {
122 return(_nextyppass(&_pw_passwd));
124 if (grp[1] == '@') {
125 _pw_stepping_yp = 1;
126 grpagain:
127 if (gr != NULL) {
128 if (*gr->gr_mem != NULL) {
129 if (lookup(*gr->gr_mem)) {
130 gr->gr_mem++;
131 goto grpagain;
133 rv = _getyppass(&_pw_passwd,
134 *gr->gr_mem,
135 "passwd.byname");
136 gr->gr_mem++;
137 return(rv);
138 } else {
139 latch = 0;
140 _pw_stepping_yp = 0;
141 gr = NULL;
142 return(0);
145 if (!latch) {
146 setnetgrent(grp+2);
147 latch++;
149 again:
150 if (getnetgrent(&host, &user, &domain) == 0) {
151 if ((gr = getgrnam(grp+2)) != NULL)
152 goto grpagain;
153 latch = 0;
154 _pw_stepping_yp = 0;
155 return(0);
156 } else {
157 if (lookup(user))
158 goto again;
159 if (_getyppass(&_pw_passwd, user,
160 "passwd.byname"))
161 return(1);
162 else
163 goto again;
165 } else {
166 if (lookup(grp+1))
167 return(0);
168 return(_getyppass(&_pw_passwd, grp+1, "passwd.byname"));
170 } else {
171 if (grp[1] == '@') {
172 setnetgrent(grp+2);
173 rv = 0;
174 while(getnetgrent(&host, &user, &domain) != 0) {
175 store(user);
176 rv++;
178 if (!rv && (gr = getgrnam(grp+2)) != NULL) {
179 while(*gr->gr_mem) {
180 store(*gr->gr_mem);
181 gr->gr_mem++;
184 } else {
185 store(grp+1);
188 return(0);
191 struct passwd *
192 getpwent(void)
194 DBT key;
195 char bf[sizeof(_pw_keynum) + 1];
196 int rv;
198 if (!_pw_db && !__initdb())
199 return((struct passwd *)NULL);
201 #ifdef YP
202 if(_pw_stepping_yp) {
203 _pw_passwd = _pw_copy;
204 if (unwind((char *)&_ypnam))
205 return(&_pw_passwd);
207 #endif
208 tryagain:
210 ++_pw_keynum;
211 bf[0] = _PW_KEYBYNUM;
212 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
213 key.data = (u_char *)bf;
214 key.size = sizeof(_pw_keynum) + 1;
215 rv = __hashpw(&key);
216 if(!rv) return (struct passwd *)NULL;
217 #ifdef YP
218 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
219 if (_yp_enabled == -1)
220 _ypinitdb();
221 bzero((char *)&_ypnam, sizeof(_ypnam));
222 bcopy(_pw_passwd.pw_name, _ypnam,
223 strlen(_pw_passwd.pw_name));
224 _pw_copy = _pw_passwd;
225 if (unwind((char *)&_ypnam) == 0)
226 goto tryagain;
227 else
228 return(&_pw_passwd);
230 #else
231 /* Ignore YP password file entries when YP is disabled. */
232 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
233 goto tryagain;
235 #endif
236 return(&_pw_passwd);
239 struct passwd *
240 getpwnam(const char *name)
242 DBT key;
243 int len, rval;
244 char bf[UT_NAMESIZE + 2];
246 if (!_pw_db && !__initdb())
247 return((struct passwd *)NULL);
249 bf[0] = _PW_KEYBYNAME;
250 len = strlen(name);
251 if (len > UT_NAMESIZE)
252 return(NULL);
253 bcopy(name, bf + 1, len);
254 key.data = (u_char *)bf;
255 key.size = len + 1;
256 rval = __hashpw(&key);
258 #ifdef YP
259 if (!rval) {
260 if (_yp_enabled == -1)
261 _ypinitdb();
262 if (_yp_enabled)
263 rval = _getyppass(&_pw_passwd, name, "passwd.byname");
265 #endif
267 * Prevent login attempts when YP is not enabled but YP entries
268 * are in /etc/master.passwd.
270 if (rval && (_pw_passwd.pw_name[0] == '+'||
271 _pw_passwd.pw_name[0] == '-')) rval = 0;
273 if (!_pw_stayopen)
274 endpwent();
275 return(rval ? &_pw_passwd : (struct passwd *)NULL);
278 struct passwd *
279 getpwuid(uid_t uid)
281 DBT key;
282 int keyuid, rval;
283 char bf[sizeof(keyuid) + 1];
285 if (!_pw_db && !__initdb())
286 return((struct passwd *)NULL);
288 bf[0] = _PW_KEYBYUID;
289 keyuid = uid;
290 bcopy(&keyuid, bf + 1, sizeof(keyuid));
291 key.data = (u_char *)bf;
292 key.size = sizeof(keyuid) + 1;
293 rval = __hashpw(&key);
295 #ifdef YP
296 if (!rval) {
297 if (_yp_enabled == -1)
298 _ypinitdb();
299 if (_yp_enabled) {
300 char ypbuf[16]; /* big enough for 32-bit uids */
301 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);
302 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");
305 #endif
307 * Prevent login attempts when YP is not enabled but YP entries
308 * are in /etc/master.passwd.
310 if (rval && (_pw_passwd.pw_name[0] == '+'||
311 _pw_passwd.pw_name[0] == '-')) rval = 0;
313 if (!_pw_stayopen)
314 endpwent();
315 return(rval ? &_pw_passwd : (struct passwd *)NULL);
319 setpassent(int stayopen)
321 _pw_keynum = 0;
322 #ifdef YP
323 _pw_stepping_yp = 0;
324 if (stayopen)
325 setgroupent(1);
326 #endif
327 _pw_stayopen = stayopen;
328 return(1);
331 void
332 setpwent(void)
334 setpassent(0);
337 void
338 endpwent(void)
340 _pw_keynum = 0;
341 #ifdef YP
342 _pw_stepping_yp = 0;
343 #endif
344 if (_pw_db) {
345 (_pw_db->close)(_pw_db);
346 _pw_db = (DB *)NULL;
348 #ifdef YP
349 if (_ypcache) {
350 (_ypcache->close)(_ypcache);
351 _ypcache = (DB *)NULL;
352 _yp_exclusions = 0;
354 /* Fix for PR #12008 */
355 _yp_enabled = -1;
356 #endif
359 static int
360 __initdb(void)
362 static int warned;
363 char *p;
365 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
366 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
367 if (_pw_db)
368 return(1);
369 if (!warned++)
370 syslog(LOG_ERR, "%s: %m", p);
371 return(0);
374 static int
375 __hashpw(DBT *key)
377 char *p, *t;
378 static u_int max;
379 static char *line;
380 DBT data;
382 if ((_pw_db->get)(_pw_db, key, &data, 0))
383 return(0);
384 p = (char *)data.data;
386 /* Increase buffer size for long lines if necessary. */
387 if (data.size > max) {
388 max = data.size + 1024;
389 if (!(line = reallocf(line, max)))
390 return(0);
393 /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
394 t = line;
395 #define EXPAND(e) e = t; while ( (*t++ = *p++) );
396 #define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v
397 EXPAND(_pw_passwd.pw_name);
398 EXPAND(_pw_passwd.pw_passwd);
399 SCALAR(_pw_passwd.pw_uid);
400 SCALAR(_pw_passwd.pw_gid);
401 SCALAR(_pw_passwd.pw_change);
402 EXPAND(_pw_passwd.pw_class);
403 EXPAND(_pw_passwd.pw_gecos);
404 EXPAND(_pw_passwd.pw_dir);
405 EXPAND(_pw_passwd.pw_shell);
406 SCALAR(_pw_passwd.pw_expire);
407 bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);
408 p += sizeof _pw_passwd.pw_fields;
409 return(1);
412 #ifdef YP
414 static void
415 _ypinitdb(void)
417 DBT key, data;
418 char buf[] = { _PW_KEYYPENABLED };
419 key.data = buf;
420 key.size = 1;
421 _yp_enabled = 0;
422 if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) {
423 _yp_enabled = (int)*((char *)data.data) - 2;
424 /* Don't even bother with this if we aren't root. */
425 if (!geteuid()) {
426 if (!_pw_yp_domain)
427 if (yp_get_default_domain(&_pw_yp_domain))
428 return;
429 _gotmaster = _havemaster(_pw_yp_domain);
430 } else _gotmaster = YP_HAVE_NONE;
432 * Create a DB hash database in memory. Bet you didn't know you
433 * could do a dbopen() with a NULL filename, did you.
435 if (_ypcache == (DB *)NULL)
436 _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
441 * See if a user is in the blackballed list.
443 static inline int
444 lookup(const char *name)
446 DBT key;
448 if (!_yp_exclusions)
449 return(0);
451 key.data = (char *)name;
452 key.size = strlen(name);
454 if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {
455 return(0);
458 return(1);
462 * Store a blackballed user in an in-core hash database.
464 static inline void
465 store(const char *key)
467 DBT lkey;
469 if (lookup(key))
470 return;
473 _yp_exclusions = 1;
475 lkey.data = (char *)key;
476 lkey.size = strlen(key);
478 (_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);
482 * See if a user is a member of a particular group.
484 static inline int
485 ingr(const char *grp, const char *name)
487 struct group *gr;
489 if ((gr = getgrnam(grp)) == NULL)
490 return(0);
492 while(*gr->gr_mem) {
493 if (!strcmp(*gr->gr_mem, name))
494 return(1);
495 gr->gr_mem++;
498 return(0);
502 * Check a user against the +@netgroup/-@netgroup lines listed in
503 * the local password database. Also checks +user/-user lines.
504 * If no netgroup exists that matches +@netgroup/-@netgroup,
505 * try searching regular groups with the same name.
507 static inline int
508 verf(const char *name)
510 DBT key;
511 char bf[sizeof(_pw_keynum) + 1];
512 int keynum = 0;
514 again:
515 ++keynum;
516 bf[0] = _PW_KEYYPBYNUM;
517 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
518 key.data = (u_char *)bf;
519 key.size = sizeof(keynum) + 1;
520 if (!__hashpw(&key)) {
521 /* Try again using old format */
522 bf[0] = _PW_KEYBYNUM;
523 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
524 key.data = (u_char *)bf;
525 if (!__hashpw(&key))
526 return(0);
528 if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-'))
529 goto again;
530 if (_pw_passwd.pw_name[0] == '+') {
531 if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */
532 return(1);
533 if (_pw_passwd.pw_name[1] == '@') {
534 if ((innetgr(_pw_passwd.pw_name+2, NULL, name,
535 _pw_yp_domain) ||
536 ingr(_pw_passwd.pw_name+2, name)) && !lookup(name))
537 return(1);
538 else
539 goto again;
540 } else {
541 if (!strcmp(name, _pw_passwd.pw_name+1) &&
542 !lookup(name))
543 return(1);
544 else
545 goto again;
548 if (_pw_passwd.pw_name[0] == '-') {
549 /* Note that a minus wildcard is a no-op. */
550 if (_pw_passwd.pw_name[1] == '@') {
551 if (innetgr(_pw_passwd.pw_name+2, NULL, name,
552 _pw_yp_domain) ||
553 ingr(_pw_passwd.pw_name+2, name)) {
554 store(name);
555 return(0);
556 } else
557 goto again;
558 } else {
559 if (!strcmp(name, _pw_passwd.pw_name+1)) {
560 store(name);
561 return(0);
562 } else
563 goto again;
567 return(0);
570 static char *
571 _get_adjunct_pw(const char *name)
573 static char adjunctbuf[YPMAXRECORD+2];
574 int rval;
575 char *result;
576 int resultlen;
577 char *map = "passwd.adjunct.byname";
578 char *s;
580 if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name),
581 &result, &resultlen)))
582 return(NULL);
584 strncpy(adjunctbuf, result, resultlen);
585 adjunctbuf[resultlen] = '\0';
586 free(result);
587 result = (char *)&adjunctbuf;
589 /* Don't care about the name. */
590 if ((s = strsep(&result, ":")) == NULL)
591 return (NULL); /* name */
592 if ((s = strsep(&result, ":")) == NULL)
593 return (NULL); /* password */
595 return(s);
598 static int
599 _pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master)
601 char *s, *result;
602 static char resbuf[YPMAXRECORD+2];
605 * Be triple, ultra super-duper paranoid: reject entries
606 * that start with a + or -. yp_mkdb and /var/yp/Makefile
607 * are _both_ supposed to strip these out, but you never
608 * know.
610 if (*res == '+' || *res == '-')
611 return 0;
614 * The NIS protocol definition limits the size of an NIS
615 * record to YPMAXRECORD bytes. We need to do a copy to
616 * a static buffer here since the memory pointed to by
617 * res will be free()ed when this function returns.
619 strncpy((char *)&resbuf, res, resultlen);
620 resbuf[resultlen] = '\0';
621 result = (char *)&resbuf;
624 * XXX Sanity check: make sure all fields are valid (no NULLs).
625 * If we find a badly formatted entry, we punt.
627 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
629 * We don't care what pw_fields says: we _always_ want the
630 * username returned to us by NIS.
632 pw->pw_name = s;
633 pw->pw_fields |= _PWF_NAME;
635 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
636 if(!(pw->pw_fields & _PWF_PASSWD)) {
637 /* SunOS passwd.adjunct hack */
638 if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) {
639 char *realpw;
640 realpw = _get_adjunct_pw(pw->pw_name);
641 if (realpw == NULL)
642 pw->pw_passwd = s;
643 else
644 pw->pw_passwd = realpw;
645 } else {
646 pw->pw_passwd = s;
648 pw->pw_fields |= _PWF_PASSWD;
651 if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */
652 if(!(pw->pw_fields & _PWF_UID)) {
653 pw->pw_uid = atoi(s);
654 pw->pw_fields |= _PWF_UID;
657 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
658 if(!(pw->pw_fields & _PWF_GID)) {
659 pw->pw_gid = atoi(s);
660 pw->pw_fields |= _PWF_GID;
663 if (master == YP_HAVE_MASTER) {
664 if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
665 if(!(pw->pw_fields & _PWF_CLASS)) {
666 pw->pw_class = s;
667 pw->pw_fields |= _PWF_CLASS;
670 if ((s = strsep(&result, ":")) == NULL) return 0; /* change */
671 if(!(pw->pw_fields & _PWF_CHANGE)) {
672 pw->pw_change = atol(s);
673 pw->pw_fields |= _PWF_CHANGE;
676 if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */
677 if(!(pw->pw_fields & _PWF_EXPIRE)) {
678 pw->pw_expire = atol(s);
679 pw->pw_fields |= _PWF_EXPIRE;
683 if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */
684 if(!(pw->pw_fields & _PWF_GECOS)) {
685 pw->pw_gecos = s;
686 pw->pw_fields |= _PWF_GECOS;
689 if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */
690 if(!(pw->pw_fields & _PWF_DIR)) {
691 pw->pw_dir = s;
692 pw->pw_fields |= _PWF_DIR;
695 if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */
696 if(!(pw->pw_fields & _PWF_SHELL)) {
697 pw->pw_shell = s;
698 pw->pw_fields |= _PWF_SHELL;
701 /* Be consistent. */
702 if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0';
704 return 1;
707 static int
708 _havemaster(char *_yp_domain)
710 int order;
711 int rval;
713 if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order)))
714 return(YP_HAVE_MASTER);
717 * NIS+ in YP compat mode doesn't support
718 * YPPROC_ORDER -- no point in continuing.
720 if (rval == YPERR_YPERR)
721 return(YP_HAVE_NONE);
723 /* master.passwd doesn't exist -- try passwd.adjunct */
724 if (rval == YPERR_MAP) {
725 rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order);
726 if (!rval)
727 return(YP_HAVE_ADJUNCT);
730 return (YP_HAVE_NONE);
733 static int
734 _getyppass(struct passwd *pw, const char *name, const char *map)
736 char *result, *s;
737 int resultlen;
738 int rv;
739 char mastermap[YPMAXRECORD];
741 if(!_pw_yp_domain) {
742 if(yp_get_default_domain(&_pw_yp_domain))
743 return 0;
746 if (_gotmaster == YP_HAVE_MASTER)
747 snprintf(mastermap, sizeof(mastermap), "master.%s", map);
748 else
749 snprintf(mastermap, sizeof(mastermap), "%s", map);
751 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
752 &result, &resultlen)) {
753 if (_gotmaster != YP_HAVE_MASTER)
754 return 0;
755 snprintf(mastermap, sizeof(mastermap), "%s", map);
756 if (yp_match(_pw_yp_domain, (char *)&mastermap,
757 name, strlen(name), &result, &resultlen))
758 return 0;
759 _gotmaster = YP_HAVE_NONE;
762 if (!_pw_stepping_yp) {
763 s = strchr(result, ':');
764 if (s) {
765 *s = '\0';
766 } else {
767 /* Must be a malformed entry if no colons. */
768 free(result);
769 return(0);
772 if (!verf(result)) {
773 *s = ':';
774 free(result);
775 return(0);
778 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
781 rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster);
782 free(result);
783 return(rv);
786 static int
787 _nextyppass(struct passwd *pw)
789 static char *key;
790 static int keylen;
791 char *lastkey, *result, *s;
792 int resultlen;
793 int rv;
794 char *map = "passwd.byname";
796 if(!_pw_yp_domain) {
797 if(yp_get_default_domain(&_pw_yp_domain))
798 return 0;
801 if (_gotmaster == YP_HAVE_MASTER)
802 map = "master.passwd.byname";
804 if(!_pw_stepping_yp) {
805 if(key) free(key);
806 rv = yp_first(_pw_yp_domain, map,
807 &key, &keylen, &result, &resultlen);
808 if(rv) {
809 return 0;
811 _pw_stepping_yp = 1;
812 goto unpack;
813 } else {
814 tryagain:
815 lastkey = key;
816 rv = yp_next(_pw_yp_domain, map, key, keylen,
817 &key, &keylen, &result, &resultlen);
818 free(lastkey);
819 unpack:
820 if(rv) {
821 _pw_stepping_yp = 0;
822 return 0;
825 s = strchr(result, ':');
826 if (s) {
827 *s = '\0';
828 } else {
829 /* Must be a malformed entry if no colons. */
830 free(result);
831 goto tryagain;
834 if (lookup(result)) {
835 *s = ':';
836 free(result);
837 goto tryagain;
840 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
841 if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) {
842 free(result);
843 return(1);
844 } else {
845 free(result);
846 goto tryagain;
851 #endif /* YP */