getnetgrent.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 633 行 · 第 1/2 页
C
633 行
/* * 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.2 (Berkeley) 4/27/95";#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, *cptr; int glen = strlen(group); /* skip possible leading whitespace */ while(isspace(*ptr)) ptr++; while (ptr < list + len) { cptr = ptr; while(*ptr != ',' && *ptr != '\0' && !isspace(*ptr)) ptr++; if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) return(1); while(*ptr == ',' || isspace(*ptr)) ptr++; } 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 : "*"); break; case(4): sprintf((char *)key, "*.*"); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?