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*41756Smarc static char sccsid[] = "@(#)getpwent.c 5.13 (Berkeley) 05/11/90"; 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; 3139174Sbostic static int _pw_getfirstkey, _pw_stayopen; 3241572Sedward static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master; 332019Swnj 3436456Sbostic #define MAXLINELENGTH 1024 3536215Sbostic static char line[MAXLINELENGTH]; 3617759Sserge 3736855Sbostic struct passwd * 3836855Sbostic getpwent() 3936855Sbostic { 4036855Sbostic 4141572Sedward if (!_pw_fp && !start_pw(1)) 4236855Sbostic return((struct passwd *)NULL); 4341572Sedward if (!scanpw()) 4441572Sedward return((struct passwd *)NULL); 4541572Sedward getpw(); 4641572Sedward return(&_pw_passwd); 4736855Sbostic } 4836855Sbostic 4936855Sbostic struct passwd * 5036855Sbostic getpwnam(nam) 5136855Sbostic char *nam; 5236855Sbostic { 5336855Sbostic int rval; 5436855Sbostic 5541572Sedward if (!start_pw(0)) 5636855Sbostic return((struct passwd *)NULL); 5736855Sbostic if (_pw_db) { 5836855Sbostic datum key; 5936855Sbostic 6036855Sbostic key.dptr = nam; 6136855Sbostic key.dsize = strlen(nam); 6236855Sbostic rval = fetch_pw(key); 6336855Sbostic } else /* _pw_fp */ 6437243Sbostic for (rval = 0; scanpw();) 6536855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 6636855Sbostic rval = 1; 6736855Sbostic break; 6836855Sbostic } 6936855Sbostic if (!_pw_stayopen) 7036855Sbostic endpwent(); 7137243Sbostic if (rval) 7237243Sbostic getpw(); 7336855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 7436855Sbostic } 7536855Sbostic 7636855Sbostic struct passwd * 7736855Sbostic getpwuid(uid) 7836855Sbostic int uid; 7936855Sbostic { 8036855Sbostic int rval; 8136855Sbostic 8241572Sedward if (!start_pw(0)) 8336855Sbostic return((struct passwd *)NULL); 8436855Sbostic if (_pw_db) { 8536855Sbostic datum key; 8636855Sbostic 8736855Sbostic key.dptr = (char *)&uid; 8836855Sbostic key.dsize = sizeof(uid); 8936855Sbostic rval = fetch_pw(key); 9036855Sbostic } else /* _pw_fp */ 9137243Sbostic for (rval = 0; scanpw();) 9236855Sbostic if (_pw_passwd.pw_uid == uid) { 9336855Sbostic rval = 1; 9436855Sbostic break; 9536855Sbostic } 9636855Sbostic if (!_pw_stayopen) 9736855Sbostic endpwent(); 9837243Sbostic if (rval) 9937243Sbostic getpw(); 10036855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 10136855Sbostic } 10236855Sbostic 10336215Sbostic static 10441572Sedward start_pw(want_fp) 10541572Sedward char want_fp; /* open _pw_fp also */ 1062019Swnj { 10737196Sbostic char *p; 10837196Sbostic 10936855Sbostic if (_pw_db) { 11039174Sbostic _pw_getfirstkey = 1; 11141572Sedward if (!want_fp) 11241572Sedward return(1); 11336855Sbostic } 11436855Sbostic if (_pw_fp) { 11536855Sbostic rewind(_pw_fp); 11636855Sbostic return(1); 11736855Sbostic } 11841572Sedward if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) { 11939174Sbostic _pw_getfirstkey = 1; 12041572Sedward if (!want_fp) 12141572Sedward return(1); 12239174Sbostic } 12337196Sbostic /* 12437196Sbostic * special case; if it's the official password file, look in 12537196Sbostic * the master password file, otherwise, look in the file itself. 12637196Sbostic */ 12737196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 12841572Sedward if (_pw_fp = fopen(p, "r")) { 12941572Sedward _pw_master = 1; 13036855Sbostic return(1); 13141572Sedward } 13241572Sedward /* 13341572Sedward * If we really want to set up _pw_fp, then try again 13441572Sedward * with the old file. 13541572Sedward */ 13641572Sedward if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) { 13741572Sedward _pw_master = 0; 13841572Sedward return(1); 13941572Sedward } 14036855Sbostic return(0); 14136855Sbostic } 14236855Sbostic 14336855Sbostic setpwent() 14436855Sbostic { 14536855Sbostic return(setpassent(0)); 14636855Sbostic } 14736855Sbostic 14836855Sbostic setpassent(stayopen) 14936855Sbostic int stayopen; 15036855Sbostic { 15141572Sedward if (!start_pw(0)) 15236855Sbostic return(0); 15336855Sbostic _pw_stayopen = stayopen; 15436855Sbostic return(1); 15536855Sbostic } 15636855Sbostic 15736855Sbostic void 15836855Sbostic endpwent() 15936855Sbostic { 16036855Sbostic if (_pw_db) { 16136855Sbostic dbm_close(_pw_db); 16236855Sbostic _pw_db = (DBM *)NULL; 16341572Sedward } 16441572Sedward if (_pw_fp) { 16536855Sbostic (void)fclose(_pw_fp); 16636855Sbostic _pw_fp = (FILE *)NULL; 16736855Sbostic } 16836855Sbostic } 16936855Sbostic 17036855Sbostic void 17136855Sbostic setpwfile(file) 17236855Sbostic char *file; 17336855Sbostic { 17436855Sbostic _pw_file = file; 17536855Sbostic } 17636855Sbostic 17736855Sbostic static 17836855Sbostic scanpw() 17936855Sbostic { 18036215Sbostic register char *cp; 18136855Sbostic long atol(); 182*41756Smarc char *bp; 18336456Sbostic char *fgets(), *strsep(), *index(); 18436215Sbostic 18536215Sbostic for (;;) { 18636855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 18736215Sbostic return(0); 188*41756Smarc bp = line; 18936456Sbostic /* skip lines that are too big */ 19036855Sbostic if (!index(line, '\n')) { 19136456Sbostic int ch; 19236456Sbostic 19336456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 19436456Sbostic ; 19536456Sbostic continue; 19636456Sbostic } 197*41756Smarc _pw_passwd.pw_name = strsep(&bp, ":\n"); 198*41756Smarc _pw_passwd.pw_passwd = strsep(&bp, ":\n"); 199*41756Smarc if (!(cp = strsep(&bp, ":\n"))) 20036215Sbostic continue; 20136215Sbostic _pw_passwd.pw_uid = atoi(cp); 202*41756Smarc if (!(cp = strsep(&bp, ":\n"))) 20336215Sbostic continue; 20436215Sbostic _pw_passwd.pw_gid = atoi(cp); 20541572Sedward if (_pw_master) { 206*41756Smarc _pw_passwd.pw_class = strsep(&bp, ":\n"); 207*41756Smarc if (!(cp = strsep(&bp, ":\n"))) 20841572Sedward continue; 20941572Sedward _pw_passwd.pw_change = atol(cp); 210*41756Smarc if (!(cp = strsep(&bp, ":\n"))) 21141572Sedward continue; 21241572Sedward _pw_passwd.pw_expire = atol(cp); 21341572Sedward } 214*41756Smarc _pw_passwd.pw_gecos = strsep(&bp, ":\n"); 215*41756Smarc _pw_passwd.pw_dir = strsep(&bp, ":\n"); 216*41756Smarc _pw_passwd.pw_shell = strsep(&bp, ":\n"); 21736855Sbostic if (!_pw_passwd.pw_shell) 21836855Sbostic continue; 21936855Sbostic return(1); 22036215Sbostic } 22136215Sbostic /* NOTREACHED */ 2222019Swnj } 2232019Swnj 22436215Sbostic static 22536855Sbostic fetch_pw(key) 22636215Sbostic datum key; 2272019Swnj { 22836855Sbostic register char *p, *t; 22936215Sbostic 23036855Sbostic /* 23136855Sbostic * the .dir file is LOCK_EX locked by programs that are 23236855Sbostic * renaming the various password files. 23336855Sbostic */ 23436855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 23536215Sbostic return(0); 23636855Sbostic if (!key.dptr) 23739174Sbostic if (_pw_getfirstkey) { 23839174Sbostic _pw_getfirstkey = 0; 23936855Sbostic key = dbm_firstkey(_pw_db); 24036855Sbostic } else 24136855Sbostic key = dbm_nextkey(_pw_db); 24236855Sbostic if (key.dptr) 24336855Sbostic key = dbm_fetch(_pw_db, key); 24436215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 24536855Sbostic if (!(p = key.dptr)) 24636215Sbostic return(0); 24736855Sbostic t = line; 24836855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 24936855Sbostic EXPAND(_pw_passwd.pw_name); 25036855Sbostic EXPAND(_pw_passwd.pw_passwd); 25136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 25236855Sbostic p += sizeof(int); 25336855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 25436855Sbostic p += sizeof(int); 25536855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 25636855Sbostic p += sizeof(time_t); 25736855Sbostic EXPAND(_pw_passwd.pw_class); 25836855Sbostic EXPAND(_pw_passwd.pw_gecos); 25936855Sbostic EXPAND(_pw_passwd.pw_dir); 26036855Sbostic EXPAND(_pw_passwd.pw_shell); 26136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 26236855Sbostic p += sizeof(time_t); 26336855Sbostic _pw_flag = *p; 26436215Sbostic return(1); 2652019Swnj } 2662019Swnj 26738037Sbostic #define _MAX_PASSWD_SIZE 50 26838037Sbostic static char pwbuf[_MAX_PASSWD_SIZE]; 26938037Sbostic 27036855Sbostic static 27136855Sbostic getpw() 2722019Swnj { 27336855Sbostic long pos, atol(); 27437196Sbostic int fd, n; 27536855Sbostic char *p; 27638037Sbostic off_t lseek(); 2772019Swnj 27836868Sbostic if (geteuid()) 27936868Sbostic return; 28037196Sbostic /* 28137196Sbostic * special case; if it's the official password file, look in 28237196Sbostic * the master password file, otherwise, look in the file itself. 28337196Sbostic */ 28437196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 28537196Sbostic if ((fd = open(p, O_RDONLY, 0)) < 0) 28637196Sbostic return; 28736855Sbostic pos = atol(_pw_passwd.pw_passwd); 28837196Sbostic if (lseek(fd, pos, L_SET) != pos) 28936855Sbostic goto bad; 29037196Sbostic if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 29136855Sbostic goto bad; 29236855Sbostic pwbuf[n] = '\0'; 29336855Sbostic for (p = pwbuf; *p; ++p) 29436855Sbostic if (*p == ':') { 29536855Sbostic *p = '\0'; 29636855Sbostic _pw_passwd.pw_passwd = pwbuf; 29736855Sbostic break; 29836855Sbostic } 29937196Sbostic bad: (void)close(fd); 3002019Swnj } 301