122095Smckusick /* 236215Sbostic * Copyright (c) 1988 The Regents of the University of California. 336215Sbostic * All rights reserved. 436215Sbostic * 536215Sbostic * Redistribution and use in source and binary forms are permitted 636215Sbostic * provided that the above copyright notice and this paragraph are 736215Sbostic * duplicated in all such forms and that any documentation, 836215Sbostic * advertising materials, and other materials related to such 936215Sbostic * distribution and use acknowledge that the software was developed 1036215Sbostic * by the University of California, Berkeley. The name of the 1136215Sbostic * University may not be used to endorse or promote products derived 1236215Sbostic * from this software without specific prior written permission. 1336215Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436215Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536855Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622095Smckusick */ 1722095Smckusick 1826560Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*36868Sbostic static char sccsid[] = "@(#)getpwent.c 5.6 (Berkeley) 02/22/89"; 2036215Sbostic #endif /* LIBC_SCCS and not lint */ 2122095Smckusick 2236215Sbostic #include <sys/types.h> 2336215Sbostic #include <sys/file.h> 242019Swnj #include <stdio.h> 252019Swnj #include <pwd.h> 2616416Sralph #include <ndbm.h> 272019Swnj 2836215Sbostic static DBM *_pw_db; 2936215Sbostic static FILE *_pw_fp; 3036215Sbostic static struct passwd _pw_passwd; 31*36868Sbostic static int _pw_fd, _pw_rewind = 1, _pw_set, _pw_stayopen; 3236855Sbostic static char _pw_flag, *_pw_file = _PATH_MASTERPASSWD; 332019Swnj 3436456Sbostic #define MAXLINELENGTH 1024 3536215Sbostic static char line[MAXLINELENGTH]; 3617759Sserge 3736855Sbostic struct passwd * 3836855Sbostic getpwent() 3936855Sbostic { 4036855Sbostic datum key; 4136855Sbostic int rval; 4236855Sbostic 4336855Sbostic if (!_pw_db && !_pw_fp && !start_pw()) 4436855Sbostic return((struct passwd *)NULL); 4536855Sbostic do { 4636855Sbostic if (_pw_db) { 4736855Sbostic key.dptr = NULL; 4836855Sbostic rval = fetch_pw(key); 4936855Sbostic } else /* _pw_fp */ 5036855Sbostic rval = scanpw(); 5136855Sbostic } while (rval && _pw_flag != _PW_KEYBYNAME); 52*36868Sbostic getpw(); 5336855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 5436855Sbostic } 5536855Sbostic 5636855Sbostic struct passwd * 5736855Sbostic getpwnam(nam) 5836855Sbostic char *nam; 5936855Sbostic { 6036855Sbostic int rval; 6136855Sbostic 6236855Sbostic if (!start_pw()) 6336855Sbostic return((struct passwd *)NULL); 6436855Sbostic if (_pw_db) { 6536855Sbostic datum key; 6636855Sbostic 6736855Sbostic key.dptr = nam; 6836855Sbostic key.dsize = strlen(nam); 6936855Sbostic rval = fetch_pw(key); 7036855Sbostic } else /* _pw_fp */ 7136855Sbostic while (scanpw()) 7236855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 7336855Sbostic rval = 1; 7436855Sbostic break; 7536855Sbostic } 7636855Sbostic if (!_pw_stayopen) 7736855Sbostic endpwent(); 78*36868Sbostic getpw(); 7936855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 8036855Sbostic } 8136855Sbostic 8236855Sbostic struct passwd * 8336855Sbostic getpwuid(uid) 8436855Sbostic int uid; 8536855Sbostic { 8636855Sbostic int rval; 8736855Sbostic 8836855Sbostic if (!start_pw()) 8936855Sbostic return((struct passwd *)NULL); 9036855Sbostic if (_pw_db) { 9136855Sbostic datum key; 9236855Sbostic 9336855Sbostic key.dptr = (char *)&uid; 9436855Sbostic key.dsize = sizeof(uid); 9536855Sbostic rval = fetch_pw(key); 9636855Sbostic } else /* _pw_fp */ 9736855Sbostic while (scanpw()) 9836855Sbostic if (_pw_passwd.pw_uid == uid) { 9936855Sbostic rval = 1; 10036855Sbostic break; 10136855Sbostic } 10236855Sbostic if (!_pw_stayopen) 10336855Sbostic endpwent(); 104*36868Sbostic getpw(); 10536855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 10636855Sbostic } 10736855Sbostic 10836215Sbostic static 10936855Sbostic start_pw() 1102019Swnj { 11136855Sbostic if (_pw_db) { 11236855Sbostic _pw_rewind = 1; 11336855Sbostic return(1); 11436855Sbostic } 11536855Sbostic if (_pw_fp) { 11636855Sbostic rewind(_pw_fp); 11736855Sbostic return(1); 11836855Sbostic } 11936855Sbostic if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) 12036855Sbostic return(1); 12136855Sbostic if (_pw_fp = fopen(_pw_file, "r")) 12236855Sbostic return(1); 12336855Sbostic return(0); 12436855Sbostic } 12536855Sbostic 12636855Sbostic setpwent() 12736855Sbostic { 12836855Sbostic return(setpassent(0)); 12936855Sbostic } 13036855Sbostic 13136855Sbostic setpassent(stayopen) 13236855Sbostic int stayopen; 13336855Sbostic { 13436855Sbostic if (!start_pw()) 13536855Sbostic return(0); 13636855Sbostic _pw_stayopen = stayopen; 13736855Sbostic return(1); 13836855Sbostic } 13936855Sbostic 14036855Sbostic void 14136855Sbostic endpwent() 14236855Sbostic { 14336855Sbostic if (_pw_db) { 14436855Sbostic dbm_close(_pw_db); 14536855Sbostic _pw_db = (DBM *)NULL; 14636855Sbostic } else if (_pw_fp) { 14736855Sbostic (void)fclose(_pw_fp); 14836855Sbostic _pw_fp = (FILE *)NULL; 14936855Sbostic } 15036855Sbostic if (_pw_fd) { 15136855Sbostic (void)close(_pw_fd); 15236855Sbostic _pw_fd = NULL; 15336855Sbostic } 15436855Sbostic } 15536855Sbostic 15636855Sbostic void 15736855Sbostic setpwfile(file) 15836855Sbostic char *file; 15936855Sbostic { 16036855Sbostic _pw_file = file; 16136855Sbostic _pw_set = 1; 16236855Sbostic } 16336855Sbostic 16436855Sbostic static 16536855Sbostic scanpw() 16636855Sbostic { 16736215Sbostic register char *cp; 16836855Sbostic long atol(); 16936456Sbostic char *fgets(), *strsep(), *index(); 17036215Sbostic 17136215Sbostic for (;;) { 17236855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 17336215Sbostic return(0); 17436456Sbostic /* skip lines that are too big */ 17536855Sbostic if (!index(line, '\n')) { 17636456Sbostic int ch; 17736456Sbostic 17836456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 17936456Sbostic ; 18036456Sbostic continue; 18136456Sbostic } 18236855Sbostic _pw_passwd.pw_name = strsep(line, ":\n"); 18336215Sbostic _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); 18436215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 18536215Sbostic continue; 18636215Sbostic _pw_passwd.pw_uid = atoi(cp); 18736215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 18836215Sbostic continue; 18936215Sbostic _pw_passwd.pw_gid = atoi(cp); 19036855Sbostic _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); 19136855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19236855Sbostic continue; 19336855Sbostic _pw_passwd.pw_change = atol(cp); 19436855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19536855Sbostic continue; 19636855Sbostic _pw_passwd.pw_expire = atol(cp); 19736215Sbostic _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); 19836215Sbostic _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); 19936215Sbostic _pw_passwd.pw_shell = strsep((char *)NULL, ":\n"); 20036855Sbostic if (!_pw_passwd.pw_shell) 20136855Sbostic continue; 20236855Sbostic return(1); 20336215Sbostic } 20436215Sbostic /* NOTREACHED */ 2052019Swnj } 2062019Swnj 20736215Sbostic static 20836855Sbostic fetch_pw(key) 20936215Sbostic datum key; 2102019Swnj { 21136855Sbostic register char *p, *t; 21236215Sbostic 21336855Sbostic /* 21436855Sbostic * the .dir file is LOCK_EX locked by programs that are 21536855Sbostic * renaming the various password files. 21636855Sbostic */ 21736855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 21836215Sbostic return(0); 21936855Sbostic if (!key.dptr) 22036855Sbostic if (_pw_rewind) { 22136855Sbostic _pw_rewind = 0; 22236855Sbostic key = dbm_firstkey(_pw_db); 22336855Sbostic } else 22436855Sbostic key = dbm_nextkey(_pw_db); 22536855Sbostic if (key.dptr) 22636855Sbostic key = dbm_fetch(_pw_db, key); 22736215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 22836855Sbostic if (!(p = key.dptr)) 22936215Sbostic return(0); 23036855Sbostic t = line; 23136855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 23236855Sbostic EXPAND(_pw_passwd.pw_name); 23336855Sbostic EXPAND(_pw_passwd.pw_passwd); 23436855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 23536855Sbostic p += sizeof(int); 23636855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 23736855Sbostic p += sizeof(int); 23836855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 23936855Sbostic p += sizeof(time_t); 24036855Sbostic EXPAND(_pw_passwd.pw_class); 24136855Sbostic EXPAND(_pw_passwd.pw_gecos); 24236855Sbostic EXPAND(_pw_passwd.pw_dir); 24336855Sbostic EXPAND(_pw_passwd.pw_shell); 24436855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 24536855Sbostic p += sizeof(time_t); 24636855Sbostic _pw_flag = *p; 24736215Sbostic return(1); 2482019Swnj } 2492019Swnj 25036855Sbostic static 25136855Sbostic getpw() 2522019Swnj { 25336855Sbostic static char pwbuf[50]; 254*36868Sbostic off_t lseek(); 25536855Sbostic long pos, atol(); 25636855Sbostic int n; 25736855Sbostic char *p; 2582019Swnj 259*36868Sbostic if (geteuid()) 260*36868Sbostic return; 26136855Sbostic if (!_pw_fd && (_pw_fd = open(_pw_file, O_RDONLY, 0)) < 0) 26236855Sbostic goto bad; 26336855Sbostic pos = atol(_pw_passwd.pw_passwd); 26436855Sbostic if (lseek(_pw_fd, pos, L_SET) != pos) 26536855Sbostic goto bad; 26636855Sbostic if ((n = read(_pw_fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 26736855Sbostic goto bad; 26836855Sbostic pwbuf[n] = '\0'; 26936855Sbostic for (p = pwbuf; *p; ++p) 27036855Sbostic if (*p == ':') { 27136855Sbostic *p = '\0'; 27236855Sbostic _pw_passwd.pw_passwd = pwbuf; 27336855Sbostic break; 27436855Sbostic } 275*36868Sbostic bad: (void)close(_pw_fd); 2762019Swnj } 277