Home | History | Annotate | Line # | Download | only in gen
getnetgrent.c revision 1.2
      1 /*
      2  * Copyright (c) 1992, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Rick Macklem at The University of Guelph.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #if defined(LIBC_SCCS) && !defined(lint)
     38 /*static char sccsid[] = "from: @(#)getnetgrent.c	8.1 (Berkeley) 6/4/93";*/
     39 static char *rcsid = "$Id: getnetgrent.c,v 1.2 1994/09/19 04:32:45 mycroft Exp $";
     40 #endif /* LIBC_SCCS and not lint */
     41 
     42 #include <stdio.h>
     43 #include <strings.h>
     44 
     45 #define _PATH_NETGROUP "/etc/netgroup"
     46 
     47 /*
     48  * Static Variables and functions used by setnetgrent(), getnetgrent() and
     49  * endnetgrent().
     50  * There are two linked lists:
     51  * - linelist is just used by setnetgrent() to parse the net group file via.
     52  *   parse_netgrp()
     53  * - netgrp is the list of entries for the current netgroup
     54  */
     55 struct linelist {
     56 	struct linelist	*l_next;	/* Chain ptr. */
     57 	int		l_parsed;	/* Flag for cycles */
     58 	char		*l_groupname;	/* Name of netgroup */
     59 	char		*l_line;	/* Netgroup entrie(s) to be parsed */
     60 };
     61 
     62 struct netgrp {
     63 	struct netgrp	*ng_next;	/* Chain ptr */
     64 	char		*ng_str[3];	/* Field pointers, see below */
     65 };
     66 #define NG_HOST		0	/* Host name */
     67 #define NG_USER		1	/* User name */
     68 #define NG_DOM		2	/* and Domain name */
     69 
     70 static struct linelist	*linehead = (struct linelist *)0;
     71 static struct netgrp	*nextgrp = (struct netgrp *)0;
     72 static struct {
     73 	struct netgrp	*gr;
     74 	char		*grname;
     75 } grouphead = {
     76 	(struct netgrp *)0,
     77 	(char *)0,
     78 };
     79 static FILE *netf = (FILE *)0;
     80 static int parse_netgrp();
     81 static struct linelist *read_for_group();
     82 void setnetgrent(), endnetgrent();
     83 int getnetgrent(), innetgr();
     84 
     85 #define	LINSIZ	1024	/* Length of netgroup file line */
     86 
     87 /*
     88  * setnetgrent()
     89  * Parse the netgroup file looking for the netgroup and build the list
     90  * of netgrp structures. Let parse_netgrp() and read_for_group() do
     91  * most of the work.
     92  */
     93 void
     94 setnetgrent(group)
     95 	char *group;
     96 {
     97 
     98 	if (grouphead.gr == (struct netgrp *)0 ||
     99 		strcmp(group, grouphead.grname)) {
    100 		endnetgrent();
    101 		if (netf = fopen(_PATH_NETGROUP, "r")) {
    102 			if (parse_netgrp(group))
    103 				endnetgrent();
    104 			else {
    105 				grouphead.grname = (char *)
    106 					malloc(strlen(group) + 1);
    107 				strcpy(grouphead.grname, group);
    108 			}
    109 			fclose(netf);
    110 		}
    111 	}
    112 	nextgrp = grouphead.gr;
    113 }
    114 
    115 /*
    116  * Get the next netgroup off the list.
    117  */
    118 int
    119 getnetgrent(hostp, userp, domp)
    120 	char **hostp, **userp, **domp;
    121 {
    122 
    123 	if (nextgrp) {
    124 		*hostp = nextgrp->ng_str[NG_HOST];
    125 		*userp = nextgrp->ng_str[NG_USER];
    126 		*domp = nextgrp->ng_str[NG_DOM];
    127 		nextgrp = nextgrp->ng_next;
    128 		return (1);
    129 	}
    130 	return (0);
    131 }
    132 
    133 /*
    134  * endnetgrent() - cleanup
    135  */
    136 void
    137 endnetgrent()
    138 {
    139 	register struct linelist *lp, *olp;
    140 	register struct netgrp *gp, *ogp;
    141 
    142 	lp = linehead;
    143 	while (lp) {
    144 		olp = lp;
    145 		lp = lp->l_next;
    146 		free(olp->l_groupname);
    147 		free(olp->l_line);
    148 		free((char *)olp);
    149 	}
    150 	linehead = (struct linelist *)0;
    151 	if (grouphead.grname) {
    152 		free(grouphead.grname);
    153 		grouphead.grname = (char *)0;
    154 	}
    155 	gp = grouphead.gr;
    156 	while (gp) {
    157 		ogp = gp;
    158 		gp = gp->ng_next;
    159 		if (ogp->ng_str[NG_HOST])
    160 			free(ogp->ng_str[NG_HOST]);
    161 		if (ogp->ng_str[NG_USER])
    162 			free(ogp->ng_str[NG_USER]);
    163 		if (ogp->ng_str[NG_DOM])
    164 			free(ogp->ng_str[NG_DOM]);
    165 		free((char *)ogp);
    166 	}
    167 	grouphead.gr = (struct netgrp *)0;
    168 }
    169 
    170 /*
    171  * Search for a match in a netgroup.
    172  */
    173 int
    174 innetgr(group, host, user, dom)
    175 	char *group, *host, *user, *dom;
    176 {
    177 	char *hst, *usr, *dm;
    178 
    179 	setnetgrent(group);
    180 	while (getnetgrent(&hst, &usr, &dm))
    181 		if ((host == (char *)0 || !strcmp(host, hst)) &&
    182 		    (user == (char *)0 || !strcmp(user, usr)) &&
    183 		    (dom == (char *)0 || !strcmp(dom, dm))) {
    184 			endnetgrent();
    185 			return (1);
    186 		}
    187 	endnetgrent();
    188 	return (0);
    189 }
    190 
    191 /*
    192  * Parse the netgroup file setting up the linked lists.
    193  */
    194 static int
    195 parse_netgrp(group)
    196 	char *group;
    197 {
    198 	register char *spos, *epos;
    199 	register int len, strpos;
    200 	char *pos, *gpos;
    201 	struct netgrp *grp;
    202 	struct linelist *lp = linehead;
    203 
    204 	/*
    205 	 * First, see if the line has already been read in.
    206 	 */
    207 	while (lp) {
    208 		if (!strcmp(group, lp->l_groupname))
    209 			break;
    210 		lp = lp->l_next;
    211 	}
    212 	if (lp == (struct linelist *)0 &&
    213 	    (lp = read_for_group(group)) == (struct linelist *)0)
    214 		return (1);
    215 	if (lp->l_parsed) {
    216 		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
    217 		return (1);
    218 	} else
    219 		lp->l_parsed = 1;
    220 	pos = lp->l_line;
    221 	while (*pos != '\0') {
    222 		if (*pos == '(') {
    223 			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
    224 			bzero((char *)grp, sizeof (struct netgrp));
    225 			grp->ng_next = grouphead.gr;
    226 			grouphead.gr = grp;
    227 			pos++;
    228 			gpos = strsep(&pos, ")");
    229 			for (strpos = 0; strpos < 3; strpos++) {
    230 				if (spos = strsep(&gpos, ",")) {
    231 					while (*spos == ' ' || *spos == '\t')
    232 						spos++;
    233 					if (epos = strpbrk(spos, " \t")) {
    234 						*epos = '\0';
    235 						len = epos - spos;
    236 					} else
    237 						len = strlen(spos);
    238 					if (len > 0) {
    239 						grp->ng_str[strpos] =  (char *)
    240 							malloc(len + 1);
    241 						bcopy(spos, grp->ng_str[strpos],
    242 							len + 1);
    243 					}
    244 				} else
    245 					goto errout;
    246 			}
    247 		} else {
    248 			spos = strsep(&pos, ", \t");
    249 			if (parse_netgrp(spos))
    250 				return (1);
    251 		}
    252 		if (pos == 0)
    253 			break;
    254 		while (*pos == ' ' || *pos == ',' || *pos == '\t')
    255 			pos++;
    256 	}
    257 	return (0);
    258 errout:
    259 	fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
    260 		spos);
    261 	return (1);
    262 }
    263 
    264 /*
    265  * Read the netgroup file and save lines until the line for the netgroup
    266  * is found. Return 1 if eof is encountered.
    267  */
    268 static struct linelist *
    269 read_for_group(group)
    270 	char *group;
    271 {
    272 	register char *pos, *spos, *linep, *olinep;
    273 	register int len, olen;
    274 	int cont;
    275 	struct linelist *lp;
    276 	char line[LINSIZ + 1];
    277 
    278 	while (fgets(line, LINSIZ, netf) != NULL) {
    279 		pos = line;
    280 		if (*pos == '#')
    281 			continue;
    282 		while (*pos == ' ' || *pos == '\t')
    283 			pos++;
    284 		spos = pos;
    285 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
    286 			*pos != '\0')
    287 			pos++;
    288 		len = pos - spos;
    289 		while (*pos == ' ' || *pos == '\t')
    290 			pos++;
    291 		if (*pos != '\n' && *pos != '\0') {
    292 			lp = (struct linelist *)malloc(sizeof (*lp));
    293 			lp->l_parsed = 0;
    294 			lp->l_groupname = (char *)malloc(len + 1);
    295 			bcopy(spos, lp->l_groupname, len);
    296 			*(lp->l_groupname + len) = '\0';
    297 			len = strlen(pos);
    298 			olen = 0;
    299 
    300 			/*
    301 			 * Loop around handling line continuations.
    302 			 */
    303 			do {
    304 				if (*(pos + len - 1) == '\n')
    305 					len--;
    306 				if (*(pos + len - 1) == '\\') {
    307 					len--;
    308 					cont = 1;
    309 				} else
    310 					cont = 0;
    311 				if (len > 0) {
    312 					linep = (char *)malloc(olen + len + 1);
    313 					if (olen > 0) {
    314 						bcopy(olinep, linep, olen);
    315 						free(olinep);
    316 					}
    317 					bcopy(pos, linep + olen, len);
    318 					olen += len;
    319 					*(linep + olen) = '\0';
    320 					olinep = linep;
    321 				}
    322 				if (cont) {
    323 					if (fgets(line, LINSIZ, netf)) {
    324 						pos = line;
    325 						len = strlen(pos);
    326 					} else
    327 						cont = 0;
    328 				}
    329 			} while (cont);
    330 			lp->l_line = linep;
    331 			lp->l_next = linehead;
    332 			linehead = lp;
    333 
    334 			/*
    335 			 * If this is the one we wanted, we are done.
    336 			 */
    337 			if (!strcmp(lp->l_groupname, group))
    338 				return (lp);
    339 		}
    340 	}
    341 	return ((struct linelist *)0);
    342 }
    343