122095Smckusick /* 236215Sbostic * Copyright (c) 1988 The Regents of the University of California. 336215Sbostic * All rights reserved. 436215Sbostic * 5*42624Sbostic * %sccs.include.redist.c% 622095Smckusick */ 722095Smckusick 826560Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*42624Sbostic static char sccsid[] = "@(#)getpwent.c 5.14 (Berkeley) 06/01/90"; 1036215Sbostic #endif /* LIBC_SCCS and not lint */ 1122095Smckusick 1236215Sbostic #include <sys/types.h> 1336215Sbostic #include <sys/file.h> 142019Swnj #include <stdio.h> 152019Swnj #include <pwd.h> 1616416Sralph #include <ndbm.h> 172019Swnj 1836215Sbostic static DBM *_pw_db; 1936215Sbostic static FILE *_pw_fp; 2036215Sbostic static struct passwd _pw_passwd; 2139174Sbostic static int _pw_getfirstkey, _pw_stayopen; 2241572Sedward static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master; 232019Swnj 2436456Sbostic #define MAXLINELENGTH 1024 2536215Sbostic static char line[MAXLINELENGTH]; 2617759Sserge 2736855Sbostic struct passwd * 2836855Sbostic getpwent() 2936855Sbostic { 3036855Sbostic 3141572Sedward if (!_pw_fp && !start_pw(1)) 3236855Sbostic return((struct passwd *)NULL); 3341572Sedward if (!scanpw()) 3441572Sedward return((struct passwd *)NULL); 3541572Sedward getpw(); 3641572Sedward return(&_pw_passwd); 3736855Sbostic } 3836855Sbostic 3936855Sbostic struct passwd * 4036855Sbostic getpwnam(nam) 4136855Sbostic char *nam; 4236855Sbostic { 4336855Sbostic int rval; 4436855Sbostic 4541572Sedward if (!start_pw(0)) 4636855Sbostic return((struct passwd *)NULL); 4736855Sbostic if (_pw_db) { 4836855Sbostic datum key; 4936855Sbostic 5036855Sbostic key.dptr = nam; 5136855Sbostic key.dsize = strlen(nam); 5236855Sbostic rval = fetch_pw(key); 5336855Sbostic } else /* _pw_fp */ 5437243Sbostic for (rval = 0; scanpw();) 5536855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 5636855Sbostic rval = 1; 5736855Sbostic break; 5836855Sbostic } 5936855Sbostic if (!_pw_stayopen) 6036855Sbostic endpwent(); 6137243Sbostic if (rval) 6237243Sbostic getpw(); 6336855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 6436855Sbostic } 6536855Sbostic 6636855Sbostic struct passwd * 6736855Sbostic getpwuid(uid) 6836855Sbostic int uid; 6936855Sbostic { 7036855Sbostic int rval; 7136855Sbostic 7241572Sedward if (!start_pw(0)) 7336855Sbostic return((struct passwd *)NULL); 7436855Sbostic if (_pw_db) { 7536855Sbostic datum key; 7636855Sbostic 7736855Sbostic key.dptr = (char *)&uid; 7836855Sbostic key.dsize = sizeof(uid); 7936855Sbostic rval = fetch_pw(key); 8036855Sbostic } else /* _pw_fp */ 8137243Sbostic for (rval = 0; scanpw();) 8236855Sbostic if (_pw_passwd.pw_uid == uid) { 8336855Sbostic rval = 1; 8436855Sbostic break; 8536855Sbostic } 8636855Sbostic if (!_pw_stayopen) 8736855Sbostic endpwent(); 8837243Sbostic if (rval) 8937243Sbostic getpw(); 9036855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 9136855Sbostic } 9236855Sbostic 9336215Sbostic static 9441572Sedward start_pw(want_fp) 9541572Sedward char want_fp; /* open _pw_fp also */ 962019Swnj { 9737196Sbostic char *p; 9837196Sbostic 9936855Sbostic if (_pw_db) { 10039174Sbostic _pw_getfirstkey = 1; 10141572Sedward if (!want_fp) 10241572Sedward return(1); 10336855Sbostic } 10436855Sbostic if (_pw_fp) { 10536855Sbostic rewind(_pw_fp); 10636855Sbostic return(1); 10736855Sbostic } 10841572Sedward if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) { 10939174Sbostic _pw_getfirstkey = 1; 11041572Sedward if (!want_fp) 11141572Sedward return(1); 11239174Sbostic } 11337196Sbostic /* 11437196Sbostic * special case; if it's the official password file, look in 11537196Sbostic * the master password file, otherwise, look in the file itself. 11637196Sbostic */ 11737196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 11841572Sedward if (_pw_fp = fopen(p, "r")) { 11941572Sedward _pw_master = 1; 12036855Sbostic return(1); 12141572Sedward } 12241572Sedward /* 12341572Sedward * If we really want to set up _pw_fp, then try again 12441572Sedward * with the old file. 12541572Sedward */ 12641572Sedward if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) { 12741572Sedward _pw_master = 0; 12841572Sedward return(1); 12941572Sedward } 13036855Sbostic return(0); 13136855Sbostic } 13236855Sbostic 13336855Sbostic setpwent() 13436855Sbostic { 13536855Sbostic return(setpassent(0)); 13636855Sbostic } 13736855Sbostic 13836855Sbostic setpassent(stayopen) 13936855Sbostic int stayopen; 14036855Sbostic { 14141572Sedward if (!start_pw(0)) 14236855Sbostic return(0); 14336855Sbostic _pw_stayopen = stayopen; 14436855Sbostic return(1); 14536855Sbostic } 14636855Sbostic 14736855Sbostic void 14836855Sbostic endpwent() 14936855Sbostic { 15036855Sbostic if (_pw_db) { 15136855Sbostic dbm_close(_pw_db); 15236855Sbostic _pw_db = (DBM *)NULL; 15341572Sedward } 15441572Sedward if (_pw_fp) { 15536855Sbostic (void)fclose(_pw_fp); 15636855Sbostic _pw_fp = (FILE *)NULL; 15736855Sbostic } 15836855Sbostic } 15936855Sbostic 16036855Sbostic void 16136855Sbostic setpwfile(file) 16236855Sbostic char *file; 16336855Sbostic { 16436855Sbostic _pw_file = file; 16536855Sbostic } 16636855Sbostic 16736855Sbostic static 16836855Sbostic scanpw() 16936855Sbostic { 17036215Sbostic register char *cp; 17136855Sbostic long atol(); 17241756Smarc char *bp; 17336456Sbostic char *fgets(), *strsep(), *index(); 17436215Sbostic 17536215Sbostic for (;;) { 17636855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 17736215Sbostic return(0); 17841756Smarc bp = line; 17936456Sbostic /* skip lines that are too big */ 18036855Sbostic if (!index(line, '\n')) { 18136456Sbostic int ch; 18236456Sbostic 18336456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 18436456Sbostic ; 18536456Sbostic continue; 18636456Sbostic } 18741756Smarc _pw_passwd.pw_name = strsep(&bp, ":\n"); 18841756Smarc _pw_passwd.pw_passwd = strsep(&bp, ":\n"); 18941756Smarc if (!(cp = strsep(&bp, ":\n"))) 19036215Sbostic continue; 19136215Sbostic _pw_passwd.pw_uid = atoi(cp); 19241756Smarc if (!(cp = strsep(&bp, ":\n"))) 19336215Sbostic continue; 19436215Sbostic _pw_passwd.pw_gid = atoi(cp); 19541572Sedward if (_pw_master) { 19641756Smarc _pw_passwd.pw_class = strsep(&bp, ":\n"); 19741756Smarc if (!(cp = strsep(&bp, ":\n"))) 19841572Sedward continue; 19941572Sedward _pw_passwd.pw_change = atol(cp); 20041756Smarc if (!(cp = strsep(&bp, ":\n"))) 20141572Sedward continue; 20241572Sedward _pw_passwd.pw_expire = atol(cp); 20341572Sedward } 20441756Smarc _pw_passwd.pw_gecos = strsep(&bp, ":\n"); 20541756Smarc _pw_passwd.pw_dir = strsep(&bp, ":\n"); 20641756Smarc _pw_passwd.pw_shell = strsep(&bp, ":\n"); 20736855Sbostic if (!_pw_passwd.pw_shell) 20836855Sbostic continue; 20936855Sbostic return(1); 21036215Sbostic } 21136215Sbostic /* NOTREACHED */ 2122019Swnj } 2132019Swnj 21436215Sbostic static 21536855Sbostic fetch_pw(key) 21636215Sbostic datum key; 2172019Swnj { 21836855Sbostic register char *p, *t; 21936215Sbostic 22036855Sbostic /* 22136855Sbostic * the .dir file is LOCK_EX locked by programs that are 22236855Sbostic * renaming the various password files. 22336855Sbostic */ 22436855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 22536215Sbostic return(0); 22636855Sbostic if (!key.dptr) 22739174Sbostic if (_pw_getfirstkey) { 22839174Sbostic _pw_getfirstkey = 0; 22936855Sbostic key = dbm_firstkey(_pw_db); 23036855Sbostic } else 23136855Sbostic key = dbm_nextkey(_pw_db); 23236855Sbostic if (key.dptr) 23336855Sbostic key = dbm_fetch(_pw_db, key); 23436215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 23536855Sbostic if (!(p = key.dptr)) 23636215Sbostic return(0); 23736855Sbostic t = line; 23836855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 23936855Sbostic EXPAND(_pw_passwd.pw_name); 24036855Sbostic EXPAND(_pw_passwd.pw_passwd); 24136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 24236855Sbostic p += sizeof(int); 24336855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 24436855Sbostic p += sizeof(int); 24536855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 24636855Sbostic p += sizeof(time_t); 24736855Sbostic EXPAND(_pw_passwd.pw_class); 24836855Sbostic EXPAND(_pw_passwd.pw_gecos); 24936855Sbostic EXPAND(_pw_passwd.pw_dir); 25036855Sbostic EXPAND(_pw_passwd.pw_shell); 25136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 25236855Sbostic p += sizeof(time_t); 25336855Sbostic _pw_flag = *p; 25436215Sbostic return(1); 2552019Swnj } 2562019Swnj 25738037Sbostic #define _MAX_PASSWD_SIZE 50 25838037Sbostic static char pwbuf[_MAX_PASSWD_SIZE]; 25938037Sbostic 26036855Sbostic static 26136855Sbostic getpw() 2622019Swnj { 26336855Sbostic long pos, atol(); 26437196Sbostic int fd, n; 26536855Sbostic char *p; 26638037Sbostic off_t lseek(); 2672019Swnj 26836868Sbostic if (geteuid()) 26936868Sbostic return; 27037196Sbostic /* 27137196Sbostic * special case; if it's the official password file, look in 27237196Sbostic * the master password file, otherwise, look in the file itself. 27337196Sbostic */ 27437196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 27537196Sbostic if ((fd = open(p, O_RDONLY, 0)) < 0) 27637196Sbostic return; 27736855Sbostic pos = atol(_pw_passwd.pw_passwd); 27837196Sbostic if (lseek(fd, pos, L_SET) != pos) 27936855Sbostic goto bad; 28037196Sbostic if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 28136855Sbostic goto bad; 28236855Sbostic pwbuf[n] = '\0'; 28336855Sbostic for (p = pwbuf; *p; ++p) 28436855Sbostic if (*p == ':') { 28536855Sbostic *p = '\0'; 28636855Sbostic _pw_passwd.pw_passwd = pwbuf; 28736855Sbostic break; 28836855Sbostic } 28937196Sbostic bad: (void)close(fd); 2902019Swnj } 291