getpwent.c revision 7615
1/* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 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. 20 * 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. 32 */ 33 34#if defined(LIBC_SCCS) && !defined(lint) 35static char sccsid[] = "@(#)getpwent.c 8.1 (Berkeley) 6/4/93"; 36#endif /* LIBC_SCCS and not lint */ 37 38#include <stdio.h> 39#include <sys/param.h> 40#include <fcntl.h> 41#include <db.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 52static struct passwd _pw_passwd; /* password structure */ 53static DB *_pw_db; /* password database */ 54static int _pw_keynum; /* key counter */ 55static int _pw_stayopen; /* keep fd's open */ 56#ifdef YP 57#include <rpc/rpc.h> 58#include <rpcsvc/yp_prot.h> 59#include <rpcsvc/ypclnt.h> 60struct _namelist { 61 char *name; 62 struct _namelist *next; 63}; 64static struct passwd _pw_copy; 65struct _pw_cache { 66 struct passwd pw_entry; 67 struct _namelist *namelist; 68 struct _pw_cache *next; 69}; 70static int _pluscnt, _minuscnt; 71static struct _pw_cache *_plushead = NULL, *_minushead = NULL; 72static void _createcaches(), _freecaches(); 73static int _yp_enabled; /* set true when yp enabled */ 74static int _pw_stepping_yp; /* set true when stepping thru map */ 75#endif 76static int __hashpw(), __initdb(); 77 78static int _havemaster(char *); 79static int _getyppass(struct passwd *, const char *, const char *); 80static int _nextyppass(struct passwd *); 81 82struct passwd * 83getpwent() 84{ 85 DBT key; 86 char bf[sizeof(_pw_keynum) + 1]; 87 int rv; 88 89 if (!_pw_db && !__initdb()) 90 return((struct passwd *)NULL); 91 92#ifdef YP 93 if(_pw_stepping_yp) { 94 _pw_passwd = _pw_copy; 95 return (_nextyppass(&_pw_passwd) ? &_pw_passwd : 0); 96 } 97#else 98tryagain: 99#endif 100 ++_pw_keynum; 101 bf[0] = _PW_KEYBYNUM; 102 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 103 key.data = (u_char *)bf; 104 key.size = sizeof(_pw_keynum) + 1; 105 rv = __hashpw(&key); 106 if(!rv) return (struct passwd *)NULL; 107#ifdef YP 108 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 109 _pw_copy = _pw_passwd; 110 return (_nextyppass(&_pw_passwd) ? &_pw_passwd : 0); 111 } 112#else 113 /* Ignore YP password file entries when YP is disabled. */ 114 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { 115 goto tryagain; 116 } 117#endif 118 return(&_pw_passwd); 119} 120 121struct passwd * 122getpwnam(name) 123 const char *name; 124{ 125 DBT key; 126 int len, rval; 127 char bf[UT_NAMESIZE + 2]; 128 129 if (!_pw_db && !__initdb()) 130 return((struct passwd *)NULL); 131 132 bf[0] = _PW_KEYBYNAME; 133 len = strlen(name); 134 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 135 key.data = (u_char *)bf; 136 key.size = len + 1; 137 rval = __hashpw(&key); 138 139#ifdef YP 140 if (!rval && _yp_enabled) 141 rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 142#endif 143 /* 144 * Prevent login attempts when YP is not enabled but YP entries 145 * are in /etc/master.passwd. 146 */ 147 if (rval && (_pw_passwd.pw_name[0] == '+'|| 148 _pw_passwd.pw_name[0] == '-')) rval = 0; 149 150 endpwent(); 151 return(rval ? &_pw_passwd : (struct passwd *)NULL); 152} 153 154struct passwd * 155#ifdef __STDC__ 156getpwuid(uid_t uid) 157#else 158getpwuid(uid) 159 int uid; 160#endif 161{ 162 DBT key; 163 int keyuid, rval; 164 char bf[sizeof(keyuid) + 1]; 165 166 if (!_pw_db && !__initdb()) 167 return((struct passwd *)NULL); 168 169 bf[0] = _PW_KEYBYUID; 170 keyuid = uid; 171 bcopy(&keyuid, bf + 1, sizeof(keyuid)); 172 key.data = (u_char *)bf; 173 key.size = sizeof(keyuid) + 1; 174 rval = __hashpw(&key); 175 176#ifdef YP 177 if (!rval && _yp_enabled) { 178 char ypbuf[16]; /* big enough for 32-bit uids and then some */ 179 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 180 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 181 } 182#endif 183 /* 184 * Prevent login attempts when YP is not enabled but YP entries 185 * are in /etc/master.passwd. 186 */ 187 if (rval && (_pw_passwd.pw_name[0] == '+'|| 188 _pw_passwd.pw_name[0] == '-')) rval = 0; 189 190 endpwent(); 191 return(rval ? &_pw_passwd : (struct passwd *)NULL); 192} 193 194int 195setpassent(stayopen) 196 int stayopen; 197{ 198 _pw_keynum = 0; 199#ifdef YP 200 _pw_stepping_yp = 0; 201#endif 202 _pw_stayopen = stayopen; 203 return(1); 204} 205 206int 207setpwent() 208{ 209 _pw_keynum = 0; 210#ifdef YP 211 _pw_stepping_yp = 0; 212#endif 213 _pw_stayopen = 0; 214 return(1); 215} 216 217void 218endpwent() 219{ 220 _pw_keynum = 0; 221#ifdef YP 222 _pw_stepping_yp = 0; 223#endif 224 if (_pw_db) { 225 (void)(_pw_db->close)(_pw_db); 226 _pw_db = (DB *)NULL; 227#ifdef YP 228 _freecaches(); 229#endif 230 } 231} 232 233static 234__initdb() 235{ 236 static int warned; 237 char *p; 238 239 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 240 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 241 if (_pw_db) { 242#ifdef YP 243 DBT key, data; 244 char buf[] = { _PW_KEYYPENABLED }; 245 key.data = buf; 246 key.size = 1; 247 if ((_pw_db->get)(_pw_db, &key, &data, 0)) { 248 _yp_enabled = 0; 249 } else { 250 _yp_enabled = (int)*((char *)data.data) - 2; 251 _createcaches(); 252 } 253#endif 254 return(1); 255 } 256 if (!warned) 257 syslog(LOG_ERR, "%s: %m", p); 258 return(0); 259} 260 261static 262__hashpw(key) 263 DBT *key; 264{ 265 register char *p, *t; 266 static u_int max; 267 static char *line; 268 DBT data; 269 270 if ((_pw_db->get)(_pw_db, key, &data, 0)) 271 return(0); 272 p = (char *)data.data; 273 if (data.size > max && !(line = realloc(line, max += 1024))) 274 return(0); 275 276 t = line; 277#define EXPAND(e) e = t; while (*t++ = *p++); 278 EXPAND(_pw_passwd.pw_name); 279 EXPAND(_pw_passwd.pw_passwd); 280 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 281 p += sizeof(int); 282 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 283 p += sizeof(int); 284 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 285 p += sizeof(time_t); 286 EXPAND(_pw_passwd.pw_class); 287 EXPAND(_pw_passwd.pw_gecos); 288 EXPAND(_pw_passwd.pw_dir); 289 EXPAND(_pw_passwd.pw_shell); 290 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 291 p += sizeof(time_t); 292 bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); 293 p += sizeof _pw_passwd.pw_fields; 294 return(1); 295} 296 297#ifdef YP 298/* 299 * Build special +@netgroup and -@netgroup caches. We also handle ordinary 300 * +user/-user entries, *and* +@group/-@group entries, which are special 301 * cases of the +@netgroup/-@netgroup substitutions: if we can't find 302 * netgroup 'foo', we look for a regular user group called 'foo' and 303 * match against that instead. The netgroup takes precedence since the 304 * +group/-group support is basically just a hack to make Justin T. Gibbs 305 * happy. :) Sorting out all the funny business here lets us have a 306 * yp_enabled flag with a simple on or off value instead of the somewhat 307 * bogus setup we had before. 308 * 309 * We cache everything here in one shot so that we only have to scan 310 * each netgroup/group once. The alternative is to use innetgr() inside the 311 * NIS lookup functions, which would make retrieving the whole password 312 * database though getpwent() very slow. +user/-user entries are treated 313 * like @groups/@netgroups with only one member. 314 */ 315static void 316_createcaches() 317{ 318 DBT key, data; 319 int i; 320 char bf[UT_NAMESIZE + 2]; 321 struct _pw_cache *p, *m; 322 struct _namelist *n, *namehead; 323 char *user, *host, *domain; 324 struct group *grp; 325 326 /* 327 * Assume that the database has already been initialized 328 * but be paranoid and check that YP is in fact enabled. 329 */ 330 331 if (!_yp_enabled) 332 return; 333 /* 334 * For the plus list, we have to store both the linked list of 335 * names and the +entries from the password database so we can 336 * do the substitution later if we find a match. 337 */ 338 bf[0] = _PW_KEYPLUSCNT; 339 key.data = (u_char*)bf; 340 key.size = 1; 341 if (!(_pw_db->get)(_pw_db, &key, &data, 0)) { 342 _pluscnt = (int)*((char *)data.data); 343 for (i = 0; i < _pluscnt; i++) { 344 bf[0] = _PW_KEYPLUSBYNUM; 345 bcopy(&i, bf + 1, sizeof(i) + 1); 346 key.size = (sizeof(i)) + 1; 347 if (__hashpw(&key)) { 348 p = (struct _pw_cache *)malloc(sizeof (struct _pw_cache)); 349 if (strlen(_pw_passwd.pw_name) > 2 && _pw_passwd.pw_name[1] == '@') { 350 setnetgrent(_pw_passwd.pw_name+2); 351 namehead = NULL; 352 while(getnetgrent(&host, &user, &domain)) { 353 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 354 n->name = strdup(user); 355 n->next = namehead; 356 namehead = n; 357 } 358 /* 359 * If netgroup 'foo' doesn't exist, 360 * try group 'foo' instead. 361 */ 362 if (namehead == NULL && (grp = getgrnam(_pw_passwd.pw_name+2)) != NULL) { 363 while(*grp->gr_mem) { 364 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 365 n->name = strdup(*grp->gr_mem); 366 n->next = namehead; 367 namehead = n; 368 grp->gr_mem++; 369 } 370 } 371 } else { 372 if (_pw_passwd.pw_name[1] != '@') { 373 namehead = (struct _namelist *)malloc(sizeof (struct _namelist)); 374 namehead->name = strdup(_pw_passwd.pw_name+1); 375 namehead->next = NULL; 376 } 377 } 378 p->namelist = namehead; 379 p->pw_entry.pw_name = strdup(_pw_passwd.pw_name); 380 p->pw_entry.pw_passwd = strdup(_pw_passwd.pw_passwd); 381 p->pw_entry.pw_uid = _pw_passwd.pw_uid; 382 p->pw_entry.pw_gid = _pw_passwd.pw_gid; 383 p->pw_entry.pw_expire = _pw_passwd.pw_expire; 384 p->pw_entry.pw_change = _pw_passwd.pw_change; 385 p->pw_entry.pw_class = strdup(_pw_passwd.pw_class); 386 p->pw_entry.pw_gecos = strdup(_pw_passwd.pw_gecos); 387 p->pw_entry.pw_dir = strdup(_pw_passwd.pw_dir); 388 p->pw_entry.pw_shell = strdup(_pw_passwd.pw_shell); 389 p->pw_entry.pw_fields = _pw_passwd.pw_fields; 390 p->next = _plushead; 391 _plushead = p; 392 } 393 } 394 } 395 396 /* 397 * All we need for the minuslist is the usernames. 398 * The actual -entries data can be ignored since no substitution 399 * will be done: anybody on the minus list is treated like a 400 * non-person. 401 */ 402 bf[0] = _PW_KEYMINUSCNT; 403 key.data = (u_char*)bf; 404 key.size = 1; 405 if (!(_pw_db->get)(_pw_db, &key, &data, 0)) { 406 _minuscnt = (int)*((char *)data.data); 407 for (i = 0; i < _minuscnt; i++) { 408 bf[0] = _PW_KEYMINUSBYNUM; 409 bcopy(&i, bf + 1, sizeof(i) + 1); 410 key.size = (sizeof(i)) + 1; 411 if (__hashpw(&key)) { 412 m = (struct _pw_cache *)malloc(sizeof (struct _pw_cache)); 413 if (strlen (_pw_passwd.pw_name) > 2 && _pw_passwd.pw_name[1] == '@') { 414 namehead = NULL; 415 setnetgrent(_pw_passwd.pw_name+2); 416 while(getnetgrent(&host, &user, &domain)) { 417 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 418 n->name = strdup(user); 419 n->next = namehead; 420 namehead = n; 421 } 422 /* 423 * If netgroup 'foo' doesn't exist, 424 * try group 'foo' instead. 425 */ 426 if (namehead == NULL && (grp = getgrnam(_pw_passwd.pw_name+2)) != NULL) { 427 while(*grp->gr_mem) { 428 n = (struct _namelist *)malloc(sizeof (struct _namelist)); 429 n->name = strdup(*grp->gr_mem); 430 n->next = namehead; 431 namehead = n; 432 grp->gr_mem++; 433 } 434 } 435 } else { 436 if (_pw_passwd.pw_name[1] != '@') { 437 namehead = (struct _namelist *)malloc(sizeof (struct _namelist)); 438 namehead->name = strdup(_pw_passwd.pw_name+1); 439 namehead->next = NULL; 440 } 441 } 442 m->namelist = namehead; 443 m->next = _minushead; 444 _minushead = m; 445 } 446 } 447 } 448 endgrent(); 449 endnetgrent(); 450} 451 452/* 453 * Free the +@netgroup/-@netgroup caches. Should be called 454 * from endpwent(). We have to blow away both the list of 455 * netgroups and the attached linked lists of usernames. 456 */ 457static void 458_freecaches() 459{ 460struct _pw_cache *p, *m; 461struct _namelist *n; 462 463 while (_plushead) { 464 while(_plushead->namelist) { 465 n = _plushead->namelist->next; 466 free(_plushead->namelist); 467 _plushead->namelist = n; 468 } 469 p = _plushead->next; 470 free(_plushead); 471 _plushead = p; 472 } 473 474 while(_minushead) { 475 while(_minushead->namelist) { 476 n = _minushead->namelist->next; 477 free(_minushead->namelist); 478 _minushead->namelist = n; 479 } 480 m = _minushead->next; 481 free(_minushead); 482 _minushead = m; 483 } 484 _pluscnt = _minuscnt = 0; 485} 486 487static void 488_pw_breakout_yp(struct passwd *pw, char *result, int master) 489{ 490 char *s; 491 492 s = strsep(&result, ":"); /* name */ 493 if(!(pw->pw_fields & _PWF_NAME) || (pw->pw_name[0] == '+')) { 494 pw->pw_name = s; 495 pw->pw_fields |= _PWF_NAME; 496 } 497 498 s = strsep(&result, ":"); /* password */ 499 if(!(pw->pw_fields & _PWF_PASSWD)) { 500 pw->pw_passwd = s; 501 pw->pw_fields |= _PWF_PASSWD; 502 } 503 504 s = strsep(&result, ":"); /* uid */ 505 if(!(pw->pw_fields & _PWF_UID)) { 506 pw->pw_uid = atoi(s); 507 pw->pw_fields |= _PWF_UID; 508 } 509 510 s = strsep(&result, ":"); /* gid */ 511 if(!(pw->pw_fields & _PWF_GID)) { 512 pw->pw_gid = atoi(s); 513 pw->pw_fields |= _PWF_GID; 514 } 515 516 if (master) { 517 s = strsep(&result, ":"); /* class */ 518 if(!(pw->pw_fields & _PWF_CLASS)) { 519 pw->pw_class = s; 520 pw->pw_fields |= _PWF_CLASS; 521 } 522 523 s = strsep(&result, ":"); /* change */ 524 if(!(pw->pw_fields & _PWF_CHANGE)) { 525 pw->pw_change = atol(s); 526 pw->pw_fields |= _PWF_CHANGE; 527 } 528 529 s = strsep(&result, ":"); /* expire */ 530 if(!(pw->pw_fields & _PWF_EXPIRE)) { 531 pw->pw_expire = atol(s); 532 pw->pw_fields |= _PWF_EXPIRE; 533 } 534 } 535 536 s = strsep(&result, ":"); /* gecos */ 537 if(!(pw->pw_fields & _PWF_GECOS)) { 538 pw->pw_gecos = s; 539 pw->pw_fields |= _PWF_GECOS; 540 } 541 542 s = strsep(&result, ":"); /* dir */ 543 if(!(pw->pw_fields & _PWF_DIR)) { 544 pw->pw_dir = s; 545 pw->pw_fields |= _PWF_DIR; 546 } 547 548 s = strsep(&result, ":"); /* shell */ 549 if(!(pw->pw_fields & _PWF_SHELL)) { 550 pw->pw_shell = s; 551 pw->pw_fields |= _PWF_SHELL; 552 } 553} 554 555static char *_pw_yp_domain; 556 557static int 558_havemaster(char *_pw_yp_domain) 559{ 560 int *order; 561 562 if (yp_order(_pw_yp_domain, "master.passwd.byname", (int *)&order)) { 563 free(order); 564 return 0; 565 } 566 567 free(order); 568 return 1; 569} 570 571static int 572_getyppass(struct passwd *pw, const char *name, const char *map) 573{ 574 char *result, *s; 575 static char resultbuf[1024]; 576 int resultlen; 577 char mastermap[1024]; 578 int gotmaster = 0; 579 struct _pw_cache *m, *p; 580 struct _namelist *n; 581 char user[UT_NAMESIZE]; 582 583 if(!_pw_yp_domain) { 584 if(yp_get_default_domain(&_pw_yp_domain)) 585 return 0; 586 } 587 588 sprintf(mastermap,"%s",map); 589 590 /* Don't even bother with this if we aren't root. */ 591 if (!geteuid()) 592 if (_havemaster(_pw_yp_domain)) { 593 sprintf(mastermap,"master.%s", map); 594 gotmaster++; 595 } 596 597 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), 598 &result, &resultlen)) 599 return 0; 600 601 s = strchr(result, '\n'); 602 if(s) *s = '\0'; 603 604 if(resultlen >= sizeof resultbuf) return 0; 605 strcpy(resultbuf, result); 606 sprintf (user, "%.*s", (strchr(result, ':') - result), result); 607 _pw_passwd.pw_fields = 0; 608 if (_minuscnt && _minushead) { 609 m = _minushead; 610 while (m) { 611 n = m->namelist; 612 while (n) { 613 if (!strcmp(n->name,user) || *n->name == '\0') { 614 free(result); 615 return (0); 616 } 617 n = n->next; 618 } 619 m = m->next; 620 } 621 } 622 if (_pluscnt && _plushead) { 623 p = _plushead; 624 while (p) { 625 n = p->namelist; 626 while (n) { 627 if (!strcmp(n->name, user) || *n->name == '\0') 628 bcopy((char *)&p->pw_entry, 629 (char *)&_pw_passwd, sizeof(p->pw_entry)); 630 n = n->next; 631 } 632 p = p->next; 633 } 634 } 635 free(result); 636 result = resultbuf; 637 _pw_breakout_yp(pw, resultbuf, gotmaster); 638 639 return 1; 640} 641 642static int 643_nextyppass(struct passwd *pw) 644{ 645 static char *key; 646 static int keylen; 647 char *lastkey, *result; 648 static char resultbuf[1024]; 649 int resultlen; 650 int rv; 651 char *map = "passwd.byname"; 652 int gotmaster = 0; 653 struct _pw_cache *m, *p; 654 struct _namelist *n; 655 char user[UT_NAMESIZE]; 656 657 if(!_pw_yp_domain) { 658 if(yp_get_default_domain(&_pw_yp_domain)) 659 return 0; 660 } 661 662 /* Don't even bother with this if we aren't root. */ 663 if (!geteuid()) 664 if(_havemaster(_pw_yp_domain)) { 665 map = "master.passwd.byname"; 666 gotmaster++; 667 } 668 669 if(!_pw_stepping_yp) { 670 if(key) free(key); 671 rv = yp_first(_pw_yp_domain, map, 672 &key, &keylen, &result, &resultlen); 673 if(rv) { 674 return 0; 675 } 676 _pw_stepping_yp = 1; 677 goto unpack; 678 } else { 679tryagain: 680 lastkey = key; 681 rv = yp_next(_pw_yp_domain, map, key, keylen, 682 &key, &keylen, &result, &resultlen); 683 free(lastkey); 684unpack: 685 if(rv) { 686 _pw_stepping_yp = 0; 687 return 0; 688 } 689 690 if(resultlen > sizeof(resultbuf)) { 691 free(result); 692 goto tryagain; 693 } 694 695 strcpy(resultbuf, result); 696 sprintf(user, "%.*s", (strchr(result, ':') - result), result); 697 _pw_passwd.pw_fields = 0; 698 if (_minuscnt && _minushead) { 699 m = _minushead; 700 while (m) { 701 n = m->namelist; 702 while (n) { 703 if (!strcmp(n->name, user) || *n->name == '\0') { 704 free(result); 705 goto tryagain; 706 } 707 n = n->next; 708 } 709 m = m->next; 710 } 711 } 712 if (_pluscnt && _plushead) { 713 p = _plushead; 714 while (p) { 715 n = p->namelist; 716 while (n) { 717 if (!strcmp(n->name, user) || *n->name == '\0') 718 bcopy((char *)&p->pw_entry, 719 (char*)&_pw_passwd, sizeof(p->pw_entry)); 720 n = n->next; 721 } 722 p = p->next; 723 } 724 } 725 free(result); 726 if(result = strchr(resultbuf, '\n')) *result = '\0'; 727 _pw_breakout_yp(pw, resultbuf, gotmaster); 728 } 729 return 1; 730} 731 732#endif /* YP */ 733