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