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*37243Sbostic static char sccsid[] = "@(#)getpwent.c 5.9 (Berkeley) 04/01/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; 3137196Sbostic static int _pw_rewind = 1, _pw_stayopen; 3237196Sbostic static char _pw_flag, *_pw_file = _PATH_PASSWD; 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*37243Sbostic if (rval) 53*37243Sbostic getpw(); 5436855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 5536855Sbostic } 5636855Sbostic 5736855Sbostic struct passwd * 5836855Sbostic getpwnam(nam) 5936855Sbostic char *nam; 6036855Sbostic { 6136855Sbostic int rval; 6236855Sbostic 6336855Sbostic if (!start_pw()) 6436855Sbostic return((struct passwd *)NULL); 6536855Sbostic if (_pw_db) { 6636855Sbostic datum key; 6736855Sbostic 6836855Sbostic key.dptr = nam; 6936855Sbostic key.dsize = strlen(nam); 7036855Sbostic rval = fetch_pw(key); 7136855Sbostic } else /* _pw_fp */ 72*37243Sbostic for (rval = 0; scanpw();) 7336855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 7436855Sbostic rval = 1; 7536855Sbostic break; 7636855Sbostic } 7736855Sbostic if (!_pw_stayopen) 7836855Sbostic endpwent(); 79*37243Sbostic if (rval) 80*37243Sbostic getpw(); 8136855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 8236855Sbostic } 8336855Sbostic 8436855Sbostic struct passwd * 8536855Sbostic getpwuid(uid) 8636855Sbostic int uid; 8736855Sbostic { 8836855Sbostic int rval; 8936855Sbostic 9036855Sbostic if (!start_pw()) 9136855Sbostic return((struct passwd *)NULL); 9236855Sbostic if (_pw_db) { 9336855Sbostic datum key; 9436855Sbostic 9536855Sbostic key.dptr = (char *)&uid; 9636855Sbostic key.dsize = sizeof(uid); 9736855Sbostic rval = fetch_pw(key); 9836855Sbostic } else /* _pw_fp */ 99*37243Sbostic for (rval = 0; scanpw();) 10036855Sbostic if (_pw_passwd.pw_uid == uid) { 10136855Sbostic rval = 1; 10236855Sbostic break; 10336855Sbostic } 10436855Sbostic if (!_pw_stayopen) 10536855Sbostic endpwent(); 106*37243Sbostic if (rval) 107*37243Sbostic getpw(); 10836855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 10936855Sbostic } 11036855Sbostic 11136215Sbostic static 11236855Sbostic start_pw() 1132019Swnj { 11437196Sbostic char *p; 11537196Sbostic 11636855Sbostic if (_pw_db) { 11736855Sbostic _pw_rewind = 1; 11836855Sbostic return(1); 11936855Sbostic } 12036855Sbostic if (_pw_fp) { 12136855Sbostic rewind(_pw_fp); 12236855Sbostic return(1); 12336855Sbostic } 12436855Sbostic if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) 12536855Sbostic return(1); 12637196Sbostic /* 12737196Sbostic * special case; if it's the official password file, look in 12837196Sbostic * the master password file, otherwise, look in the file itself. 12937196Sbostic */ 13037196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 13137196Sbostic if (_pw_fp = fopen(p, "r")) 13236855Sbostic return(1); 13336855Sbostic return(0); 13436855Sbostic } 13536855Sbostic 13636855Sbostic setpwent() 13736855Sbostic { 13836855Sbostic return(setpassent(0)); 13936855Sbostic } 14036855Sbostic 14136855Sbostic setpassent(stayopen) 14236855Sbostic int stayopen; 14336855Sbostic { 14436855Sbostic if (!start_pw()) 14536855Sbostic return(0); 14636855Sbostic _pw_stayopen = stayopen; 14736855Sbostic return(1); 14836855Sbostic } 14936855Sbostic 15036855Sbostic void 15136855Sbostic endpwent() 15236855Sbostic { 15336855Sbostic if (_pw_db) { 15436855Sbostic dbm_close(_pw_db); 15536855Sbostic _pw_db = (DBM *)NULL; 15636855Sbostic } else if (_pw_fp) { 15736855Sbostic (void)fclose(_pw_fp); 15836855Sbostic _pw_fp = (FILE *)NULL; 15936855Sbostic } 16036855Sbostic } 16136855Sbostic 16236855Sbostic void 16336855Sbostic setpwfile(file) 16436855Sbostic char *file; 16536855Sbostic { 16636855Sbostic _pw_file = file; 16736855Sbostic } 16836855Sbostic 16936855Sbostic static 17036855Sbostic scanpw() 17136855Sbostic { 17236215Sbostic register char *cp; 17336855Sbostic long atol(); 17436456Sbostic char *fgets(), *strsep(), *index(); 17536215Sbostic 17636215Sbostic for (;;) { 17736855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 17836215Sbostic return(0); 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 } 18736855Sbostic _pw_passwd.pw_name = strsep(line, ":\n"); 18836215Sbostic _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); 18936215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19036215Sbostic continue; 19136215Sbostic _pw_passwd.pw_uid = atoi(cp); 19236215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19336215Sbostic continue; 19436215Sbostic _pw_passwd.pw_gid = atoi(cp); 19536855Sbostic _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); 19636855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19736855Sbostic continue; 19836855Sbostic _pw_passwd.pw_change = atol(cp); 19936855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 20036855Sbostic continue; 20136855Sbostic _pw_passwd.pw_expire = atol(cp); 20236215Sbostic _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); 20336215Sbostic _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); 20436215Sbostic _pw_passwd.pw_shell = strsep((char *)NULL, ":\n"); 20536855Sbostic if (!_pw_passwd.pw_shell) 20636855Sbostic continue; 20736855Sbostic return(1); 20836215Sbostic } 20936215Sbostic /* NOTREACHED */ 2102019Swnj } 2112019Swnj 21236215Sbostic static 21336855Sbostic fetch_pw(key) 21436215Sbostic datum key; 2152019Swnj { 21636855Sbostic register char *p, *t; 21736215Sbostic 21836855Sbostic /* 21936855Sbostic * the .dir file is LOCK_EX locked by programs that are 22036855Sbostic * renaming the various password files. 22136855Sbostic */ 22236855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 22336215Sbostic return(0); 22436855Sbostic if (!key.dptr) 22536855Sbostic if (_pw_rewind) { 22636855Sbostic _pw_rewind = 0; 22736855Sbostic key = dbm_firstkey(_pw_db); 22836855Sbostic } else 22936855Sbostic key = dbm_nextkey(_pw_db); 23036855Sbostic if (key.dptr) 23136855Sbostic key = dbm_fetch(_pw_db, key); 23236215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 23336855Sbostic if (!(p = key.dptr)) 23436215Sbostic return(0); 23536855Sbostic t = line; 23636855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 23736855Sbostic EXPAND(_pw_passwd.pw_name); 23836855Sbostic EXPAND(_pw_passwd.pw_passwd); 23936855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 24036855Sbostic p += sizeof(int); 24136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 24236855Sbostic p += sizeof(int); 24336855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 24436855Sbostic p += sizeof(time_t); 24536855Sbostic EXPAND(_pw_passwd.pw_class); 24636855Sbostic EXPAND(_pw_passwd.pw_gecos); 24736855Sbostic EXPAND(_pw_passwd.pw_dir); 24836855Sbostic EXPAND(_pw_passwd.pw_shell); 24936855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 25036855Sbostic p += sizeof(time_t); 25136855Sbostic _pw_flag = *p; 25236215Sbostic return(1); 2532019Swnj } 2542019Swnj 25536855Sbostic static 25636855Sbostic getpw() 2572019Swnj { 25836855Sbostic static char pwbuf[50]; 25936868Sbostic off_t lseek(); 26036855Sbostic long pos, atol(); 26137196Sbostic int fd, n; 26236855Sbostic char *p; 2632019Swnj 26436868Sbostic if (geteuid()) 26536868Sbostic return; 26637196Sbostic /* 26737196Sbostic * special case; if it's the official password file, look in 26837196Sbostic * the master password file, otherwise, look in the file itself. 26937196Sbostic */ 27037196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 27137196Sbostic if ((fd = open(p, O_RDONLY, 0)) < 0) 27237196Sbostic return; 27336855Sbostic pos = atol(_pw_passwd.pw_passwd); 27437196Sbostic if (lseek(fd, pos, L_SET) != pos) 27536855Sbostic goto bad; 27637196Sbostic if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 27736855Sbostic goto bad; 27836855Sbostic pwbuf[n] = '\0'; 27936855Sbostic for (p = pwbuf; *p; ++p) 28036855Sbostic if (*p == ':') { 28136855Sbostic *p = '\0'; 28236855Sbostic _pw_passwd.pw_passwd = pwbuf; 28336855Sbostic break; 28436855Sbostic } 28537196Sbostic bad: (void)close(fd); 2862019Swnj } 287