getpwent.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 849 行 · 第 1/2 页

C
849
字号
/* * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)getpwent.c	8.2 (Berkeley) 4/27/95";#endif /* LIBC_SCCS and not lint */#include <stdio.h>#include <sys/param.h>#include <fcntl.h>#include <db.h>#include <syslog.h>#include <pwd.h>#include <utmp.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include <grp.h>extern void setnetgrent __P(( char * ));extern int getnetgrent __P(( char **, char **, char ** ));extern int innetgr __P(( const char *, const char *, const char *, const char * ));/* * The lookup techniques and data extraction code here must be kept * in sync with that in `pwd_mkdb'. */static struct passwd _pw_passwd;	/* password structure */static DB *_pw_db;			/* password database */static int _pw_keynum;			/* key counter */static int _pw_stayopen;		/* keep fd's open */#ifdef YP#include <rpc/rpc.h>#include <rpcsvc/yp_prot.h>#include <rpcsvc/ypclnt.h>static struct passwd _pw_copy;static DBT empty = { NULL, 0 };static DB *_ypcache = (DB *)NULL;static int _yp_exclusions = 0;static int _yp_enabled = -1;static int _pw_stepping_yp;		/* set true when stepping thru map */static char _ypnam[YPMAXRECORD];#define YP_HAVE_MASTER 2#define YP_HAVE_ADJUNCT 1#define YP_HAVE_NONE 0static int _gotmaster;static char *_pw_yp_domain;static inline int unwind __P(( char * ));static void _ypinitdb __P(( void ));static int _havemaster __P((char *));static int _getyppass __P((struct passwd *, const char *, const char * ));static int _nextyppass __P((struct passwd *));static inline int lookup __P((const char *));static inline void store __P((const char *));static inline int ingr __P((const char *, const char*));static inline int verf __P((const char *));static char * _get_adjunct_pw __P((const char *));#endifstatic int __hashpw(DBT *);static int __initdb(void);struct passwd *getpwent(){	DBT key;	char bf[sizeof(_pw_keynum) + 1];	int rv;	if (!_pw_db && !__initdb())		return((struct passwd *)NULL);#ifdef YP	if(_pw_stepping_yp) {		_pw_passwd = _pw_copy;		if (unwind((char *)&_ypnam))			return(&_pw_passwd);	}#endiftryagain:	++_pw_keynum;	bf[0] = _PW_KEYBYNUM;	bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));	key.data = (u_char *)bf;	key.size = sizeof(_pw_keynum) + 1;	rv = __hashpw(&key);	if(!rv) return (struct passwd *)NULL;#ifdef YP	if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {		if (_yp_enabled == -1)			_ypinitdb();		bzero((char *)&_ypnam, sizeof(_ypnam));		bcopy(_pw_passwd.pw_name, _ypnam,			strlen(_pw_passwd.pw_name));		_pw_copy = _pw_passwd;		if (unwind((char *)&_ypnam) == 0)			goto tryagain;		else			return(&_pw_passwd);	}#else	/* Ignore YP password file entries when YP is disabled. */	if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {		goto tryagain;	}#endif	return(&_pw_passwd);}struct passwd *getpwnam(name)	const char *name;{	DBT key;	int len, rval;	char bf[UT_NAMESIZE + 2];	if (!_pw_db && !__initdb())		return((struct passwd *)NULL);	bf[0] = _PW_KEYBYNAME;	len = strlen(name);	if (len > UT_NAMESIZE)		return(NULL);	bcopy(name, bf + 1, len);	key.data = (u_char *)bf;	key.size = len + 1;	rval = __hashpw(&key);#ifdef YP	if (!rval) {		if (_yp_enabled == -1)			_ypinitdb();		if (_yp_enabled)			rval = _getyppass(&_pw_passwd, name, "passwd.byname");	}#endif	/*	 * Prevent login attempts when YP is not enabled but YP entries	 * are in /etc/master.passwd.	 */	if (rval && (_pw_passwd.pw_name[0] == '+'||			_pw_passwd.pw_name[0] == '-')) rval = 0;	endpwent();	return(rval ? &_pw_passwd : (struct passwd *)NULL);}struct passwd *getpwuid(uid)	uid_t uid;{	DBT key;	int keyuid, rval;	char bf[sizeof(keyuid) + 1];	if (!_pw_db && !__initdb())		return((struct passwd *)NULL);	bf[0] = _PW_KEYBYUID;	keyuid = uid;	bcopy(&keyuid, bf + 1, sizeof(keyuid));	key.data = (u_char *)bf;	key.size = sizeof(keyuid) + 1;	rval = __hashpw(&key);#ifdef YP	if (!rval) {		if (_yp_enabled == -1)			_ypinitdb();		if (_yp_enabled) {			char ypbuf[16];	/* big enough for 32-bit uids */			snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);			rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");		}	}#endif	/*	 * Prevent login attempts when YP is not enabled but YP entries	 * are in /etc/master.passwd.	 */	if (rval && (_pw_passwd.pw_name[0] == '+'||			_pw_passwd.pw_name[0] == '-')) rval = 0;	endpwent();	return(rval ? &_pw_passwd : (struct passwd *)NULL);}intsetpassent(stayopen)	int stayopen;{	_pw_keynum = 0;#ifdef YP	_pw_stepping_yp = 0;#endif	_pw_stayopen = stayopen;	return(1);}voidsetpwent(){	(void)setpassent(0);}voidendpwent(){	_pw_keynum = 0;#ifdef YP	_pw_stepping_yp = 0;#endif	if (_pw_db) {		(void)(_pw_db->close)(_pw_db);		_pw_db = (DB *)NULL;	}#ifdef YP	if (_ypcache) {		(void)(_ypcache->close)(_ypcache);		_ypcache = (DB *)NULL;		_yp_exclusions = 0;	}#endif}static int__initdb(){	static int warned;	char *p;	p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;	_pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);	if (_pw_db)		return(1);	if (!warned++)		syslog(LOG_ERR, "%s: %m", p);	return(0);}static int__hashpw(key)	DBT *key;{	register char *p, *t;	static u_int max;	static char *line;	DBT data;	if ((_pw_db->get)(_pw_db, key, &data, 0))		return(0);	p = (char *)data.data;	/* Increase buffer size for long lines if necessary. */	if (data.size > max) {		max = data.size + 1024;		if (!(line = reallocf(line, max)))			return(0);	}	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */	t = line;#define	EXPAND(e)	e = t; while ( (*t++ = *p++) );#define	SCALAR(v)	memmove(&(v), p, sizeof v); p += sizeof v	EXPAND(_pw_passwd.pw_name);	EXPAND(_pw_passwd.pw_passwd);	SCALAR(_pw_passwd.pw_uid);	SCALAR(_pw_passwd.pw_gid);	SCALAR(_pw_passwd.pw_change);	EXPAND(_pw_passwd.pw_class);	EXPAND(_pw_passwd.pw_gecos);	EXPAND(_pw_passwd.pw_dir);	EXPAND(_pw_passwd.pw_shell);	SCALAR(_pw_passwd.pw_expire);	bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);	p += sizeof _pw_passwd.pw_fields;	return(1);}#ifdef YPstatic void_ypinitdb(){	DBT key, data;	char buf[] = { _PW_KEYYPENABLED };	key.data = buf;	key.size = 1;	_yp_enabled = 0;	if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) {		_yp_enabled = (int)*((char *)data.data) - 2;		/* Don't even bother with this if we aren't root. */		if (!geteuid()) {			if (!_pw_yp_domain)				if (yp_get_default_domain(&_pw_yp_domain))					return;			_gotmaster = _havemaster(_pw_yp_domain);		} else _gotmaster = YP_HAVE_NONE;		/*		 * Create a DB hash database in memory. Bet you didn't know you		 * could do a dbopen() with a NULL filename, did you.		 */		if (_ypcache == (DB *)NULL)			_ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);	}}/* * See if a user is in the blackballed list. */static inline intlookup(name)	const char *name;{	DBT key;	if (!_yp_exclusions)		return(0);	key.data = (char *)name;	key.size = strlen(name);	if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {		return(0);	}	return(1);}/* * Store a blackballed user in an in-core hash database. */static inline voidstore(key)	const char *key;{	DBT lkey;/*	if (lookup(key))		return;*/	_yp_exclusions = 1;	lkey.data = (char *)key;	lkey.size = strlen(key);	(void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);}/* * Parse the + entries in the password database and do appropriate * NIS lookups. While ugly to look at, this is optimized to do only * as many lookups as are absolutely necessary in any given case. * Basically, the getpwent() function will feed us + and - lines * as they appear in the database. For + lines, we do netgroup/group * and user lookups to find all usernames that match the rule and * extract them from the NIS passwd maps. For - lines, we save the * matching names in a database and a) exlude them, and b) make sure * we don't consider them when processing other + lines that appear * later. */static inline intunwind(grp)	char *grp;{	char *user, *host, *domain;	static int latch = 0;	static struct group *gr = NULL;	int rv = 0;	if (grp[0] == '+') {		if (strlen(grp) == 1) {			return(_nextyppass(&_pw_passwd));		}		if (grp[1] == '@') {			_pw_stepping_yp = 1;grpagain:			if (gr != NULL) {				if (*gr->gr_mem != NULL) {					if (lookup(*gr->gr_mem)) {						gr->gr_mem++;						goto grpagain;					}					rv = _getyppass(&_pw_passwd,							*gr->gr_mem,							"passwd.byname");					gr->gr_mem++;					return(rv);				} else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?