getnetgrent.c

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

C
612
字号
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * 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[] = "@(#)getnetgrent.c	8.1 (Berkeley) 6/4/93";#endif /* LIBC_SCCS and not lint */#include <stdio.h>#include <strings.h>#include <stdlib.h>#include <unistd.h>#ifdef YP/* * Notes: * We want to be able to use NIS netgroups properly while retaining * the ability to use a local /etc/netgroup file. Unfortunately, you * can't really do both at the same time - at least, not efficiently. * NetBSD deals with this problem by creating a netgroup database * using Berkeley DB (just like the password database) that allows * for lookups using netgroup, netgroup.byuser or netgroup.byhost * searches. This is a neat idea, but I don't have time to implement * something like that now. (I think ultimately it would be nice * if we DB-fied the group and netgroup stuff all in one shot, but * for now I'm satisfied just to have something that works well * without requiring massive code changes.) *  * Therefore, to still permit the use of the local file and maintain * optimum NIS performance, we allow for the following conditions: * * - If /etc/netgroup does not exist and NIS is turned on, we use *   NIS netgroups only. * * - If /etc/netgroup exists but is empty, we use NIS netgroups *   only. * * - If /etc/netgroup exists and contains _only_ a '+', we use *   NIS netgroups only. * * - If /etc/netgroup exists, contains locally defined netgroups *   and a '+', we use a mixture of NIS and the local entries. *   This method should return the same NIS data as just using *   NIS alone, but it will be slower if the NIS netgroup database *   is large (innetgr() in particular will suffer since extra *   processing has to be done in order to determine memberships *   using just the raw netgroup data). * * - If /etc/netgroup exists and contains only locally defined *   netgroup entries, we use just those local entries and ignore *   NIS (this is the original, pre-NIS behavior). */#include <rpc/rpc.h>#include <rpcsvc/yp_prot.h>#include <rpcsvc/ypclnt.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/param.h>#include <sys/errno.h>static char *_netgr_yp_domain;int _use_only_yp;static int _netgr_yp_enabled;static int _yp_innetgr;#endif#ifndef _PATH_NETGROUP#define _PATH_NETGROUP "/etc/netgroup"#endif/* * Static Variables and functions used by setnetgrent(), getnetgrent() and * endnetgrent(). * There are two linked lists: * - linelist is just used by setnetgrent() to parse the net group file via. *   parse_netgrp() * - netgrp is the list of entries for the current netgroup */struct linelist {	struct linelist	*l_next;	/* Chain ptr. */	int		l_parsed;	/* Flag for cycles */	char		*l_groupname;	/* Name of netgroup */	char		*l_line;	/* Netgroup entrie(s) to be parsed */};struct netgrp {	struct netgrp	*ng_next;	/* Chain ptr */	char		*ng_str[3];	/* Field pointers, see below */};#define NG_HOST		0	/* Host name */#define NG_USER		1	/* User name */#define NG_DOM		2	/* and Domain name */static struct linelist	*linehead = (struct linelist *)0;static struct netgrp	*nextgrp = (struct netgrp *)0;static struct {	struct netgrp	*gr;	char		*grname;} grouphead = {	(struct netgrp *)0,	(char *)0,};static FILE *netf = (FILE *)0;static int parse_netgrp();static struct linelist *read_for_group();void setnetgrent(), endnetgrent();int getnetgrent(), innetgr();#define	LINSIZ	1024	/* Length of netgroup file line *//* * setnetgrent() * Parse the netgroup file looking for the netgroup and build the list * of netgrp structures. Let parse_netgrp() and read_for_group() do * most of the work. */voidsetnetgrent(group)	char *group;{#ifdef YP	struct stat _yp_statp;	char _yp_plus;#endif	/* Sanity check */	if (group == NULL || !strlen(group))		return;	if (grouphead.gr == (struct netgrp *)0 ||		strcmp(group, grouphead.grname)) {		endnetgrent();#ifdef YP		/* Presumed guilty until proven innocent. */		_use_only_yp = 0;		/*		 * If /etc/netgroup doesn't exist or is empty,		 * use NIS exclusively.		 */		if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) &&			errno == ENOENT) || _yp_statp.st_size == 0)			_use_only_yp = _netgr_yp_enabled = 1;		if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){		/*		 * Icky: grab the first character of the netgroup file		 * and turn on NIS if it's a '+'. rewind the stream		 * afterwards so we don't goof up read_for_group() later.		 */			if (netf) {				fscanf(netf, "%c", &_yp_plus);				rewind(netf);				if (_yp_plus == '+')					_use_only_yp = _netgr_yp_enabled = 1;			}		/*		 * If we were called specifically for an innetgr()		 * lookup and we're in NIS-only mode, short-circuit		 * parse_netgroup() and cut directly to the chase.		 */			if (_use_only_yp && _yp_innetgr) {				/* dohw! */				if (netf != NULL)					fclose(netf);				return;			}#else		if (netf = fopen(_PATH_NETGROUP, "r")) {#endif			if (parse_netgrp(group))				endnetgrent();			else {				grouphead.grname = (char *)					malloc(strlen(group) + 1);				strcpy(grouphead.grname, group);			}			if (netf)				fclose(netf);		}	}	nextgrp = grouphead.gr;}/* * Get the next netgroup off the list. */intgetnetgrent(hostp, userp, domp)	char **hostp, **userp, **domp;{#ifdef YP	_yp_innetgr = 0;#endif	if (nextgrp) {		*hostp = nextgrp->ng_str[NG_HOST];		*userp = nextgrp->ng_str[NG_USER];		*domp = nextgrp->ng_str[NG_DOM];		nextgrp = nextgrp->ng_next;		return (1);	}	return (0);}/* * endnetgrent() - cleanup */voidendnetgrent(){	register struct linelist *lp, *olp;	register struct netgrp *gp, *ogp;	lp = linehead;	while (lp) {		olp = lp;		lp = lp->l_next;		free(olp->l_groupname);		free(olp->l_line);		free((char *)olp);	}	linehead = (struct linelist *)0;	if (grouphead.grname) {		free(grouphead.grname);		grouphead.grname = (char *)0;	}	gp = grouphead.gr;	while (gp) {		ogp = gp;		gp = gp->ng_next;		if (ogp->ng_str[NG_HOST])			free(ogp->ng_str[NG_HOST]);		if (ogp->ng_str[NG_USER])			free(ogp->ng_str[NG_USER]);		if (ogp->ng_str[NG_DOM])			free(ogp->ng_str[NG_DOM]);		free((char *)ogp);	}	grouphead.gr = (struct netgrp *)0;#ifdef YP	_netgr_yp_enabled = 0;#endif}#ifdef YPstatic int _listmatch(list, group, len)char *list, *group;int len;{	char *ptr = list;	while ( (ptr = strstr(ptr, group)) ) {		ptr += strlen(group);		if (*ptr == ',' || *ptr == '\0')			return(1);	}	return(0);}static int _buildkey(key, str, dom, rotation)char *key, *str, *dom;int *rotation;{	(*rotation)++;	if (*rotation > 4)		return(0);	switch(*rotation) {		case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*");			 break;		case(2): sprintf((char *)key, "%s.*", str);			 break;		case(3): sprintf((char *)key, "*.%s", dom ? dom : "*");

⌨️ 快捷键说明

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