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*37196Sbostic static char sccsid[] = "@(#)getpwent.c 5.8 (Berkeley) 03/16/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*37196Sbostic static int _pw_rewind = 1, _pw_stayopen; 32*37196Sbostic 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); 5236868Sbostic 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(); 7836868Sbostic 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(); 10436868Sbostic getpw(); 10536855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 10636855Sbostic } 10736855Sbostic 10836215Sbostic static 10936855Sbostic start_pw() 1102019Swnj { 111*37196Sbostic char *p; 112*37196Sbostic 11336855Sbostic if (_pw_db) { 11436855Sbostic _pw_rewind = 1; 11536855Sbostic return(1); 11636855Sbostic } 11736855Sbostic if (_pw_fp) { 11836855Sbostic rewind(_pw_fp); 11936855Sbostic return(1); 12036855Sbostic } 12136855Sbostic if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) 12236855Sbostic return(1); 123*37196Sbostic /* 124*37196Sbostic * special case; if it's the official password file, look in 125*37196Sbostic * the master password file, otherwise, look in the file itself. 126*37196Sbostic */ 127*37196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 128*37196Sbostic if (_pw_fp = fopen(p, "r")) 12936855Sbostic return(1); 13036855Sbostic return(0); 13136855Sbostic } 13236855Sbostic 13336855Sbostic setpwent() 13436855Sbostic { 13536855Sbostic return(setpassent(0)); 13636855Sbostic } 13736855Sbostic 13836855Sbostic setpassent(stayopen) 13936855Sbostic int stayopen; 14036855Sbostic { 14136855Sbostic if (!start_pw()) 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; 15336855Sbostic } else if (_pw_fp) { 15436855Sbostic (void)fclose(_pw_fp); 15536855Sbostic _pw_fp = (FILE *)NULL; 15636855Sbostic } 15736855Sbostic } 15836855Sbostic 15936855Sbostic void 16036855Sbostic setpwfile(file) 16136855Sbostic char *file; 16236855Sbostic { 16336855Sbostic _pw_file = file; 16436855Sbostic } 16536855Sbostic 16636855Sbostic static 16736855Sbostic scanpw() 16836855Sbostic { 16936215Sbostic register char *cp; 17036855Sbostic long atol(); 17136456Sbostic char *fgets(), *strsep(), *index(); 17236215Sbostic 17336215Sbostic for (;;) { 17436855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 17536215Sbostic return(0); 17636456Sbostic /* skip lines that are too big */ 17736855Sbostic if (!index(line, '\n')) { 17836456Sbostic int ch; 17936456Sbostic 18036456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 18136456Sbostic ; 18236456Sbostic continue; 18336456Sbostic } 18436855Sbostic _pw_passwd.pw_name = strsep(line, ":\n"); 18536215Sbostic _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); 18636215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 18736215Sbostic continue; 18836215Sbostic _pw_passwd.pw_uid = atoi(cp); 18936215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19036215Sbostic continue; 19136215Sbostic _pw_passwd.pw_gid = atoi(cp); 19236855Sbostic _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); 19336855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19436855Sbostic continue; 19536855Sbostic _pw_passwd.pw_change = atol(cp); 19636855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19736855Sbostic continue; 19836855Sbostic _pw_passwd.pw_expire = atol(cp); 19936215Sbostic _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); 20036215Sbostic _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); 20136215Sbostic _pw_passwd.pw_shell = strsep((char *)NULL, ":\n"); 20236855Sbostic if (!_pw_passwd.pw_shell) 20336855Sbostic continue; 20436855Sbostic return(1); 20536215Sbostic } 20636215Sbostic /* NOTREACHED */ 2072019Swnj } 2082019Swnj 20936215Sbostic static 21036855Sbostic fetch_pw(key) 21136215Sbostic datum key; 2122019Swnj { 21336855Sbostic register char *p, *t; 21436215Sbostic 21536855Sbostic /* 21636855Sbostic * the .dir file is LOCK_EX locked by programs that are 21736855Sbostic * renaming the various password files. 21836855Sbostic */ 21936855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 22036215Sbostic return(0); 22136855Sbostic if (!key.dptr) 22236855Sbostic if (_pw_rewind) { 22336855Sbostic _pw_rewind = 0; 22436855Sbostic key = dbm_firstkey(_pw_db); 22536855Sbostic } else 22636855Sbostic key = dbm_nextkey(_pw_db); 22736855Sbostic if (key.dptr) 22836855Sbostic key = dbm_fetch(_pw_db, key); 22936215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 23036855Sbostic if (!(p = key.dptr)) 23136215Sbostic return(0); 23236855Sbostic t = line; 23336855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 23436855Sbostic EXPAND(_pw_passwd.pw_name); 23536855Sbostic EXPAND(_pw_passwd.pw_passwd); 23636855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 23736855Sbostic p += sizeof(int); 23836855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 23936855Sbostic p += sizeof(int); 24036855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 24136855Sbostic p += sizeof(time_t); 24236855Sbostic EXPAND(_pw_passwd.pw_class); 24336855Sbostic EXPAND(_pw_passwd.pw_gecos); 24436855Sbostic EXPAND(_pw_passwd.pw_dir); 24536855Sbostic EXPAND(_pw_passwd.pw_shell); 24636855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 24736855Sbostic p += sizeof(time_t); 24836855Sbostic _pw_flag = *p; 24936215Sbostic return(1); 2502019Swnj } 2512019Swnj 25236855Sbostic static 25336855Sbostic getpw() 2542019Swnj { 25536855Sbostic static char pwbuf[50]; 25636868Sbostic off_t lseek(); 25736855Sbostic long pos, atol(); 258*37196Sbostic int fd, n; 25936855Sbostic char *p; 2602019Swnj 26136868Sbostic if (geteuid()) 26236868Sbostic return; 263*37196Sbostic /* 264*37196Sbostic * special case; if it's the official password file, look in 265*37196Sbostic * the master password file, otherwise, look in the file itself. 266*37196Sbostic */ 267*37196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 268*37196Sbostic if ((fd = open(p, O_RDONLY, 0)) < 0) 269*37196Sbostic return; 27036855Sbostic pos = atol(_pw_passwd.pw_passwd); 271*37196Sbostic if (lseek(fd, pos, L_SET) != pos) 27236855Sbostic goto bad; 273*37196Sbostic if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 27436855Sbostic goto bad; 27536855Sbostic pwbuf[n] = '\0'; 27636855Sbostic for (p = pwbuf; *p; ++p) 27736855Sbostic if (*p == ':') { 27836855Sbostic *p = '\0'; 27936855Sbostic _pw_passwd.pw_passwd = pwbuf; 28036855Sbostic break; 28136855Sbostic } 282*37196Sbostic bad: (void)close(fd); 2832019Swnj } 284