getpwent.c

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

C
779
字号
/* * 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.1 (Berkeley) 6/4/93";#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 * ));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;			/* set true when yp enabled */static int _pw_stepping_yp;		/* set true when stepping thru map */static char _ypnam[YPMAXRECORD];static int _gotmaster;static char *_pw_yp_domain;static inline int unwind __P(( char * ));static inline 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 *));#endifstatic int __hashpw(), __initdb();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] == '-') {		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);	bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));	key.data = (u_char *)bf;	key.size = len + 1;	rval = __hashpw(&key);#ifdef YP	if (!rval && _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 *#ifdef __STDC__getpwuid(uid_t uid)#elsegetpwuid(uid)	int uid;#endif{	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 && _yp_enabled) {		char ypbuf[16];	/* big enough for 32-bit uids and then some */		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);}intsetpwent(){	_pw_keynum = 0;#ifdef YP	_pw_stepping_yp = 0;#endif	_pw_stayopen = 0;	return(1);}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) {#ifdef YP		DBT key, data;		char buf[] = { _PW_KEYYPENABLED };		key.data = buf;		key.size = 1;		if ((_pw_db->get)(_pw_db, &key, &data, 0)) {			_yp_enabled = 0;		} else {			_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(1);				_gotmaster = _havemaster(_pw_yp_domain);			} else _gotmaster = 0;			if (!_ypcache)				_ypinitdb();		}#endif		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;	if (data.size > max && !(line = realloc(line, max += 1024)))		return(0);	t = line;#define	EXPAND(e)	e = t; while ( (*t++ = *p++) );	EXPAND(_pw_passwd.pw_name);	EXPAND(_pw_passwd.pw_passwd);	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));	p += sizeof(int);	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));	p += sizeof(int);	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));	p += sizeof(time_t);	EXPAND(_pw_passwd.pw_class);	EXPAND(_pw_passwd.pw_gecos);	EXPAND(_pw_passwd.pw_dir);	EXPAND(_pw_passwd.pw_shell);	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));	p += sizeof(time_t);	bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);	p += sizeof _pw_passwd.pw_fields;	return(1);}#ifdef YP/* * Create a DB hash database in memory. Bet you didn't know you * could do a dbopen() will a NULL filename, did you. */static inline void _ypinitdb(){	if (_ypcache == (DB *)NULL)		_ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);	return;}/* * See if a user is in the blackballed list. */static inline int lookup(name)	char *name;{	DBT key;	if (!_yp_exclusions)		return(0);	key.data = 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 void store(key)	char *key;{	DBT lkey;/*	if (lookup(key))		return;*/	_yp_exclusions = 1;	lkey.data = 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 int unwind(grp)	char *grp;{	char *user, *host, *domain;	static int latch = 0;	static struct group *gr = NULL;	int rv = 0;	if (grp[0] == '+') {

⌨️ 快捷键说明

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