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