1: /* 2: * Copyright (c) 1988 The Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that the above copyright notice and this paragraph are 7: * duplicated in all such forms and that any documentation, 8: * advertising materials, and other materials related to such 9: * distribution and use acknowledge that the software was developed 10: * by the University of California, Berkeley. The name of the 11: * University may not be used to endorse or promote products derived 12: * from this software without specific prior written permission. 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16: */ 17: 18: #if defined(LIBC_SCCS) && !defined(lint) 19: static char sccsid[] = "@(#)getpwent.c 5.9.1 (2.11BSD) 1996/1/12"; 20: #endif /* LIBC_SCCS and not lint */ 21: 22: #include <sys/types.h> 23: #include <string.h> 24: #include <stdlib.h> 25: #include <sys/file.h> 26: #include <stdio.h> 27: #include <pwd.h> 28: #include <ndbm.h> 29: 30: static DBM *_pw_db; 31: static FILE *_pw_fp; 32: static struct passwd _pw_passwd; 33: static int _pw_rewind = 1, _pw_stayopen; 34: static char _pw_flag, *_pw_file = _PATH_PASSWD; 35: 36: #define MAXLINELENGTH 256 37: static char line[MAXLINELENGTH]; 38: 39: struct passwd * 40: getpwent() 41: { 42: datum key; 43: register int rval; 44: 45: if (!_pw_db && !_pw_fp && !start_pw()) 46: return((struct passwd *)NULL); 47: do { 48: if (_pw_db) { 49: key.dptr = NULL; 50: rval = fetch_pw(key); 51: } else /* _pw_fp */ 52: rval = scanpw(); 53: } while (rval && _pw_flag != _PW_KEYBYNAME); 54: if (rval) 55: getpw(); 56: return(rval ? &_pw_passwd : (struct passwd *)NULL); 57: } 58: 59: struct passwd * 60: getpwnam(nam) 61: char *nam; 62: { 63: register int rval; 64: 65: if (!start_pw()) 66: return((struct passwd *)NULL); 67: if (_pw_db) { 68: datum key; 69: 70: key.dptr = nam; 71: key.dsize = strlen(nam); 72: rval = fetch_pw(key); 73: } else /* _pw_fp */ 74: for (rval = 0; scanpw();) 75: if (!strcmp(nam, _pw_passwd.pw_name)) { 76: rval = 1; 77: break; 78: } 79: if (!_pw_stayopen) 80: endpwent(); 81: if (rval) 82: getpw(); 83: return(rval ? &_pw_passwd : (struct passwd *)NULL); 84: } 85: 86: struct passwd * 87: getpwuid(uid) 88: int uid; 89: { 90: register int rval; 91: 92: if (!start_pw()) 93: return((struct passwd *)NULL); 94: if (_pw_db) { 95: datum key; 96: 97: key.dptr = (char *)&uid; 98: key.dsize = sizeof(uid); 99: rval = fetch_pw(key); 100: } else /* _pw_fp */ 101: for (rval = 0; scanpw();) 102: if (_pw_passwd.pw_uid == uid) { 103: rval = 1; 104: break; 105: } 106: if (!_pw_stayopen) 107: endpwent(); 108: if (rval) 109: getpw(); 110: return(rval ? &_pw_passwd : (struct passwd *)NULL); 111: } 112: 113: static 114: start_pw() 115: { 116: register char *p; 117: 118: if (_pw_db) { 119: _pw_rewind = 1; 120: return(1); 121: } 122: if (_pw_fp) { 123: rewind(_pw_fp); 124: return(1); 125: } 126: if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) { 127: _pw_rewind = 1; 128: return(1); 129: } 130: /* 131: * special case; if it's the official password file, look in 132: * the master password file, otherwise, look in the file itself. 133: */ 134: p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 135: if (_pw_fp = fopen(p, "r")) 136: return(1); 137: return(0); 138: } 139: 140: setpwent() 141: { 142: return(setpassent(0)); 143: } 144: 145: setpassent(stayopen) 146: int stayopen; 147: { 148: if (!start_pw()) 149: return(0); 150: _pw_stayopen = stayopen; 151: return(1); 152: } 153: 154: void 155: endpwent() 156: { 157: if (_pw_db) { 158: dbm_close(_pw_db); 159: _pw_db = (DBM *)NULL; 160: } else if (_pw_fp) { 161: (void)fclose(_pw_fp); 162: _pw_fp = (FILE *)NULL; 163: } 164: } 165: 166: void 167: setpwfile(file) 168: char *file; 169: { 170: _pw_file = file; 171: } 172: 173: static 174: scanpw() 175: { 176: register char *cp; 177: char *bp = line; 178: register int ch; 179: 180: for (;;) { 181: if (!(fgets(line, sizeof(line), _pw_fp))) 182: return(0); 183: /* skip lines that are too big */ 184: if (!(cp = index(line, '\n'))) { 185: while ((ch = fgetc(_pw_fp)) != '\n' && ch != EOF) 186: ; 187: continue; 188: } 189: *cp = '\0'; 190: _pw_passwd.pw_name = strsep(&bp, ":"); 191: _pw_passwd.pw_passwd = strsep(&bp, ":"); 192: if (!(cp = strsep(&bp, ":"))) 193: continue; 194: _pw_passwd.pw_uid = atoi(cp); 195: if (!(cp = strsep(&bp, ":"))) 196: continue; 197: _pw_passwd.pw_gid = atoi(cp); 198: _pw_passwd.pw_class = strsep(&bp, ":"); 199: if (!(cp = strsep(&bp, ":"))) 200: continue; 201: _pw_passwd.pw_change = atol(cp); 202: if (!(cp = strsep(&bp, ":"))) 203: continue; 204: _pw_passwd.pw_expire = atol(cp); 205: _pw_passwd.pw_gecos = strsep(&bp, ":"); 206: _pw_passwd.pw_dir = strsep(&bp, ":"); 207: _pw_passwd.pw_shell = strsep(&bp, ":"); 208: if (!_pw_passwd.pw_shell) 209: continue; 210: return(1); 211: } 212: /* NOTREACHED */ 213: } 214: 215: static 216: fetch_pw(key) 217: datum key; 218: { 219: register char *p, *t; 220: 221: /* 222: * the .dir file is LOCK_EX locked by programs that are 223: * renaming the various password files. 224: */ 225: if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 226: return(0); 227: if (!key.dptr) 228: if (_pw_rewind) { 229: _pw_rewind = 0; 230: key = dbm_firstkey(_pw_db); 231: } else 232: key = dbm_nextkey(_pw_db); 233: if (key.dptr) 234: key = dbm_fetch(_pw_db, key); 235: (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 236: if (!(p = key.dptr)) 237: return(0); 238: t = line; 239: #define EXPAND(e) e = t; while (*t++ = *p++); 240: EXPAND(_pw_passwd.pw_name); 241: EXPAND(_pw_passwd.pw_passwd); 242: bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 243: p += sizeof(int); 244: bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 245: p += sizeof(int); 246: bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 247: p += sizeof(time_t); 248: EXPAND(_pw_passwd.pw_class); 249: EXPAND(_pw_passwd.pw_gecos); 250: EXPAND(_pw_passwd.pw_dir); 251: EXPAND(_pw_passwd.pw_shell); 252: bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 253: p += sizeof(time_t); 254: _pw_flag = *p; 255: return(1); 256: } 257: 258: static 259: getpw() 260: { 261: static char pwbuf[50]; 262: off_t lseek(); 263: long pos; 264: int fd, n; 265: register char *p; 266: 267: if (geteuid()) 268: return; 269: /* 270: * special case; if it's the official password file, look in 271: * the master password file, otherwise, look in the file itself. 272: */ 273: p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 274: if ((fd = open(p, O_RDONLY, 0)) < 0) 275: return; 276: pos = atol(_pw_passwd.pw_passwd); 277: if (lseek(fd, pos, L_SET) != pos) 278: goto bad; 279: if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 280: goto bad; 281: pwbuf[n] = '\0'; 282: for (p = pwbuf; *p; ++p) 283: if (*p == ':') { 284: *p = '\0'; 285: _pw_passwd.pw_passwd = pwbuf; 286: break; 287: } 288: bad: (void)close(fd); 289: }