Home | History | Annotate | Line # | Download | only in gen
getnetgrent.c revision 1.1.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[] = "@(#)getnetgrent.c	8.2 (Berkeley) 4/27/95";
     39 #endif /* LIBC_SCCS and not lint */
     40 
     41 #include <stdio.h>
     42 #include <strings.h>
     43 
     44 #define _PATH_NETGROUP "/etc/netgroup"
     45 
     46 /*
     47  * Static Variables and functions used by setnetgrent(), getnetgrent() and
     48  * endnetgrent().
     49  * There are two linked lists:
     50  * - linelist is just used by setnetgrent() to parse the net group file via.
     51  *   parse_netgrp()
     52  * - netgrp is the list of entries for the current netgroup
     53  */
     54 struct linelist {
     55 	struct linelist	*l_next;	/* Chain ptr. */
     56 	int		l_parsed;	/* Flag for cycles */
     57 	char		*l_groupname;	/* Name of netgroup */
     58 	char		*l_line;	/* Netgroup entrie(s) to be parsed */
     59 };
     60 
     61 struct netgrp {
     62 	struct netgrp	*ng_next;	/* Chain ptr */
     63 	char		*ng_str[3];	/* Field pointers, see below */
     64 };
     65 #define NG_HOST		0	/* Host name */
     66 #define NG_USER		1	/* User name */
     67 #define NG_DOM		2	/* and Domain name */
     68 
     69 static struct linelist	*linehead = (struct linelist *)0;
     70 static struct netgrp	*nextgrp = (struct netgrp *)0;
     71 static struct {
     72 	struct netgrp	*gr;
     73 	char		*grname;
     74 } grouphead = {
     75 	(struct netgrp *)0,
     76 	(char *)0,
     77 };
     78 static FILE *netf = (FILE *)0;
     79 static int parse_netgrp();
     80 static struct linelist *read_for_group();
     81 void setnetgrent(), endnetgrent();
     82 int getnetgrent(), innetgr();
     83 
     84 #define	LINSIZ	1024	/* Length of netgroup file line */
     85 
     86 /*
     87  * setnetgrent()
     88  * Parse the netgroup file looking for the netgroup and build the list
     89  * of netgrp structures. Let parse_netgrp() and read_for_group() do
     90  * most of the work.
     91  */
     92 void
     93 setnetgrent(group)
     94 	char *group;
     95 {
     96 
     97 	if (grouphead.gr == (struct netgrp *)0 ||
     98 		strcmp(group, grouphead.grname)) {
     99 		endnetgrent();
    100 		if (netf = fopen(_PATH_NETGROUP, "r")) {
    101 			if (parse_netgrp(group))
    102 				endnetgrent();
    103 			else {
    104 				grouphead.grname = (char *)
    105 					malloc(strlen(group) + 1);
    106 				strcpy(grouphead.grname, group);
    107 			}
    108 			fclose(netf);
    109 		}
    110 	}
    111 	nextgrp = grouphead.gr;
    112 }
    113 
    114 /*
    115  * Get the next netgroup off the list.
    116  */
    117 int
    118 getnetgrent(hostp, userp, domp)
    119 	char **hostp, **userp, **domp;
    120 {
    121 
    122 	if (nextgrp) {
    123 		*hostp = nextgrp->ng_str[NG_HOST];
    124 		*userp = nextgrp->ng_str[NG_USER];
    125 		*domp = nextgrp->ng_str[NG_DOM];
    126 		nextgrp = nextgrp->ng_next;
    127 		return (1);
    128 	}
    129 	return (0);
    130 }
    131 
    132 /*
    133  * endnetgrent() - cleanup
    134  */
    135 void
    136 endnetgrent()
    137 {
    138 	register struct linelist *lp, *olp;
    139 	register struct netgrp *gp, *ogp;
    140 
    141 	lp = linehead;
    142 	while (lp) {
    143 		olp = lp;
    144 		lp = lp->l_next;
    145 		free(olp->l_groupname);
    146 		free(olp->l_line);
    147 		free((char *)olp);
    148 	}
    149 	linehead = (struct linelist *)0;
    150 	if (grouphead.grname) {
    151 		free(grouphead.grname);
    152 		grouphead.grname = (char *)0;
    153 	}
    154 	gp = grouphead.gr;
    155 	while (gp) {
    156 		ogp = gp;
    157 		gp = gp->ng_next;
    158 		if (ogp->ng_str[NG_HOST])
    159 			free(ogp->ng_str[NG_HOST]);
    160 		if (ogp->ng_str[NG_USER])
    161 			free(ogp->ng_str[NG_USER]);
    162 		if (ogp->ng_str[NG_DOM])
    163 			free(ogp->ng_str[NG_DOM]);
    164 		free((char *)ogp);
    165 	}
    166 	grouphead.gr = (struct netgrp *)0;
    167 }
    168 
    169 /*
    170  * Search for a match in a netgroup.
    171  */
    172 int
    173 innetgr(group, host, user, dom)
    174 	char *group, *host, *user, *dom;
    175 {
    176 	char *hst, *usr, *dm;
    177 
    178 	setnetgrent(group);
    179 	while (getnetgrent(&hst, &usr, &dm))
    180 		if ((host == (char *)0 || !strcmp(host, hst)) &&
    181 		    (user == (char *)0 || !strcmp(user, usr)) &&
    182 		    (dom == (char *)0 || !strcmp(dom, dm))) {
    183 			endnetgrent();
    184 			return (1);
    185 		}
    186 	endnetgrent();
    187 	return (0);
    188 }
    189 
    190 /*
    191  * Parse the netgroup file setting up the linked lists.
    192  */
    193 static int
    194 parse_netgrp(group)
    195 	char *group;
    196 {
    197 	register char *spos, *epos;
    198 	register int len, strpos;
    199 	char *pos, *gpos;
    200 	struct netgrp *grp;
    201 	struct linelist *lp = linehead;
    202 
    203 	/*
    204 	 * First, see if the line has already been read in.
    205 	 */
    206 	while (lp) {
    207 		if (!strcmp(group, lp->l_groupname))
    208 			break;
    209 		lp = lp->l_next;
    210 	}
    211 	if (lp == (struct linelist *)0 &&
    212 	    (lp = read_for_group(group)) == (struct linelist *)0)
    213 		return (1);
    214 	if (lp->l_parsed) {
    215 		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
    216 		return (1);
    217 	} else
    218 		lp->l_parsed = 1;
    219 	pos = lp->l_line;
    220 	while (*pos != '\0') {
    221 		if (*pos == '(') {
    222 			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
    223 			bzero((char *)grp, sizeof (struct netgrp));
    224 			grp->ng_next = grouphead.gr;
    225 			grouphead.gr = grp;
    226 			pos++;
    227 			gpos = strsep(&pos, ")");
    228 			for (strpos = 0; strpos < 3; strpos++) {
    229 				if (spos = strsep(&gpos, ",")) {
    230 					while (*spos == ' ' || *spos == '\t')
    231 						spos++;
    232 					if (epos = strpbrk(spos, " \t")) {
    233 						*epos = '\0';
    234 						len = epos - spos;
    235 					} else
    236 						len = strlen(spos);
    237 					if (len > 0) {
    238 						grp->ng_str[strpos] =  (char *)
    239 							malloc(len + 1);
    240 						bcopy(spos, grp->ng_str[strpos],
    241 							len + 1);
    242 					}
    243 				} else
    244 					goto errout;
    245 			}
    246 		} else {
    247 			spos = strsep(&pos, ", \t");
    248 			if (parse_netgrp(spos))
    249 				return (1);
    250 		}
    251 		if (pos == NULL)
    252 			break;
    253 		while (*pos == ' ' || *pos == ',' || *pos == '\t')
    254 			pos++;
    255 	}
    256 	return (0);
    257 errout:
    258 	fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
    259 		spos);
    260 	return (1);
    261 }
    262 
    263 /*
    264  * Read the netgroup file and save lines until the line for the netgroup
    265  * is found. Return 1 if eof is encountered.
    266  */
    267 static struct linelist *
    268 read_for_group(group)
    269 	char *group;
    270 {
    271 	register char *pos, *spos, *linep, *olinep;
    272 	register int len, olen;
    273 	int cont;
    274 	struct linelist *lp;
    275 	char line[LINSIZ + 1];
    276 
    277 	while (fgets(line, LINSIZ, netf) != NULL) {
    278 		pos = line;
    279 		if (*pos == '#')
    280 			continue;
    281 		while (*pos == ' ' || *pos == '\t')
    282 			pos++;
    283 		spos = pos;
    284 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
    285 			*pos != '\0')
    286 			pos++;
    287 		len = pos - spos;
    288 		while (*pos == ' ' || *pos == '\t')
    289 			pos++;
    290 		if (*pos != '\n' && *pos != '\0') {
    291 			lp = (struct linelist *)malloc(sizeof (*lp));
    292 			lp->l_parsed = 0;
    293 			lp->l_groupname = (char *)malloc(len + 1);
    294 			bcopy(spos, lp->l_groupname, len);
    295 			*(lp->l_groupname + len) = '\0';
    296 			len = strlen(pos);
    297 			olen = 0;
    298 
    299 			/*
    300 			 * Loop around handling line continuations.
    301 			 */
    302 			do {
    303 				if (*(pos + len - 1) == '\n')
    304 					len--;
    305 				if (*(pos + len - 1) == '\\') {
    306 					len--;
    307 					cont = 1;
    308 				} else
    309 					cont = 0;
    310 				if (len > 0) {
    311 					linep = (char *)malloc(olen + len + 1);
    312 					if (olen > 0) {
    313 						bcopy(olinep, linep, olen);
    314 						free(olinep);
    315 					}
    316 					bcopy(pos, linep + olen, len);
    317 					olen += len;
    318 					*(linep + olen) = '\0';
    319 					olinep = linep;
    320 				}
    321 				if (cont) {
    322 					if (fgets(line, LINSIZ, netf)) {
    323 						pos = line;
    324 						len = strlen(pos);
    325 					} else
    326 						cont = 0;
    327 				}
    328 			} while (cont);
    329 			lp->l_line = linep;
    330 			lp->l_next = linehead;
    331 			linehead = lp;
    332 
    333 			/*
    334 			 * If this is the one we wanted, we are done.
    335 			 */
    336 			if (!strcmp(lp->l_groupname, group))
    337 				return (lp);
    338 		}
    339 	}
    340 	return ((struct linelist *)0);
    341 }
    342