xref: /csrg-svn/lib/libc/gen/getnetgrent.c (revision 68967)
153149Smckusick /*
261111Sbostic  * Copyright (c) 1992, 1993
361111Sbostic  *	The Regents of the University of California.  All rights reserved.
453149Smckusick  *
553149Smckusick  * This code is derived from software contributed to Berkeley by
653149Smckusick  * Rick Macklem at The University of Guelph.
753149Smckusick  *
853149Smckusick  * %sccs.include.redist.c%
953149Smckusick  */
1053149Smckusick 
1153149Smckusick #if defined(LIBC_SCCS) && !defined(lint)
12*68967Sbostic static char sccsid[] = "@(#)getnetgrent.c	8.2 (Berkeley) 04/27/95";
1353149Smckusick #endif /* LIBC_SCCS and not lint */
1453149Smckusick 
1553149Smckusick #include <stdio.h>
1653149Smckusick #include <strings.h>
1753149Smckusick 
1853149Smckusick #define _PATH_NETGROUP "/etc/netgroup"
1953149Smckusick 
2053149Smckusick /*
2153149Smckusick  * Static Variables and functions used by setnetgrent(), getnetgrent() and
2253149Smckusick  * endnetgrent().
2353149Smckusick  * There are two linked lists:
2453149Smckusick  * - linelist is just used by setnetgrent() to parse the net group file via.
2553149Smckusick  *   parse_netgrp()
2653149Smckusick  * - netgrp is the list of entries for the current netgroup
2753149Smckusick  */
2853149Smckusick struct linelist {
2953149Smckusick 	struct linelist	*l_next;	/* Chain ptr. */
3053149Smckusick 	int		l_parsed;	/* Flag for cycles */
3153149Smckusick 	char		*l_groupname;	/* Name of netgroup */
3253149Smckusick 	char		*l_line;	/* Netgroup entrie(s) to be parsed */
3353149Smckusick };
3453149Smckusick 
3553149Smckusick struct netgrp {
3653149Smckusick 	struct netgrp	*ng_next;	/* Chain ptr */
3753166Smckusick 	char		*ng_str[3];	/* Field pointers, see below */
3853149Smckusick };
3953166Smckusick #define NG_HOST		0	/* Host name */
4053166Smckusick #define NG_USER		1	/* User name */
4153166Smckusick #define NG_DOM		2	/* and Domain name */
4253149Smckusick 
4353149Smckusick static struct linelist	*linehead = (struct linelist *)0;
4453149Smckusick static struct netgrp	*nextgrp = (struct netgrp *)0;
4553149Smckusick static struct {
4653149Smckusick 	struct netgrp	*gr;
4753149Smckusick 	char		*grname;
4853149Smckusick } grouphead = {
4953149Smckusick 	(struct netgrp *)0,
5053149Smckusick 	(char *)0,
5153149Smckusick };
5253149Smckusick static FILE *netf = (FILE *)0;
5353149Smckusick static int parse_netgrp();
5453149Smckusick static struct linelist *read_for_group();
5553149Smckusick void setnetgrent(), endnetgrent();
5653149Smckusick int getnetgrent(), innetgr();
5753149Smckusick 
5853149Smckusick #define	LINSIZ	1024	/* Length of netgroup file line */
5953149Smckusick 
6053149Smckusick /*
6153149Smckusick  * setnetgrent()
6253149Smckusick  * Parse the netgroup file looking for the netgroup and build the list
6353149Smckusick  * of netgrp structures. Let parse_netgrp() and read_for_group() do
6453149Smckusick  * most of the work.
6553149Smckusick  */
6653149Smckusick void
setnetgrent(group)6753149Smckusick setnetgrent(group)
6853149Smckusick 	char *group;
6953149Smckusick {
7053149Smckusick 
7153149Smckusick 	if (grouphead.gr == (struct netgrp *)0 ||
7253149Smckusick 		strcmp(group, grouphead.grname)) {
7353149Smckusick 		endnetgrent();
7453149Smckusick 		if (netf = fopen(_PATH_NETGROUP, "r")) {
7553149Smckusick 			if (parse_netgrp(group))
7653149Smckusick 				endnetgrent();
7753149Smckusick 			else {
7853149Smckusick 				grouphead.grname = (char *)
7953149Smckusick 					malloc(strlen(group) + 1);
8053149Smckusick 				strcpy(grouphead.grname, group);
8153149Smckusick 			}
8253149Smckusick 			fclose(netf);
8353149Smckusick 		}
8453149Smckusick 	}
8553149Smckusick 	nextgrp = grouphead.gr;
8653149Smckusick }
8753149Smckusick 
8853149Smckusick /*
8953149Smckusick  * Get the next netgroup off the list.
9053149Smckusick  */
9153149Smckusick int
getnetgrent(hostp,userp,domp)9253149Smckusick getnetgrent(hostp, userp, domp)
9353149Smckusick 	char **hostp, **userp, **domp;
9453149Smckusick {
9553149Smckusick 
9653149Smckusick 	if (nextgrp) {
9753166Smckusick 		*hostp = nextgrp->ng_str[NG_HOST];
9853166Smckusick 		*userp = nextgrp->ng_str[NG_USER];
9953166Smckusick 		*domp = nextgrp->ng_str[NG_DOM];
10053149Smckusick 		nextgrp = nextgrp->ng_next;
10153149Smckusick 		return (1);
10253149Smckusick 	}
10353149Smckusick 	return (0);
10453149Smckusick }
10553149Smckusick 
10653149Smckusick /*
10753149Smckusick  * endnetgrent() - cleanup
10853149Smckusick  */
10953149Smckusick void
endnetgrent()11053149Smckusick endnetgrent()
11153149Smckusick {
11253149Smckusick 	register struct linelist *lp, *olp;
11353149Smckusick 	register struct netgrp *gp, *ogp;
11453149Smckusick 
11553149Smckusick 	lp = linehead;
11653149Smckusick 	while (lp) {
11753149Smckusick 		olp = lp;
11853149Smckusick 		lp = lp->l_next;
11953149Smckusick 		free(olp->l_groupname);
12053149Smckusick 		free(olp->l_line);
12153149Smckusick 		free((char *)olp);
12253149Smckusick 	}
12353149Smckusick 	linehead = (struct linelist *)0;
12453149Smckusick 	if (grouphead.grname) {
12553149Smckusick 		free(grouphead.grname);
12653149Smckusick 		grouphead.grname = (char *)0;
12753149Smckusick 	}
12853149Smckusick 	gp = grouphead.gr;
12953149Smckusick 	while (gp) {
13053149Smckusick 		ogp = gp;
13153149Smckusick 		gp = gp->ng_next;
13253166Smckusick 		if (ogp->ng_str[NG_HOST])
13353166Smckusick 			free(ogp->ng_str[NG_HOST]);
13453166Smckusick 		if (ogp->ng_str[NG_USER])
13553166Smckusick 			free(ogp->ng_str[NG_USER]);
13653166Smckusick 		if (ogp->ng_str[NG_DOM])
13753166Smckusick 			free(ogp->ng_str[NG_DOM]);
13853149Smckusick 		free((char *)ogp);
13953149Smckusick 	}
14053149Smckusick 	grouphead.gr = (struct netgrp *)0;
14153149Smckusick }
14253149Smckusick 
14353149Smckusick /*
14453149Smckusick  * Search for a match in a netgroup.
14553149Smckusick  */
14653149Smckusick int
innetgr(group,host,user,dom)14753149Smckusick innetgr(group, host, user, dom)
14853149Smckusick 	char *group, *host, *user, *dom;
14953149Smckusick {
15053149Smckusick 	char *hst, *usr, *dm;
15153149Smckusick 
15253149Smckusick 	setnetgrent(group);
15353149Smckusick 	while (getnetgrent(&hst, &usr, &dm))
15453149Smckusick 		if ((host == (char *)0 || !strcmp(host, hst)) &&
15553149Smckusick 		    (user == (char *)0 || !strcmp(user, usr)) &&
15653149Smckusick 		    (dom == (char *)0 || !strcmp(dom, dm))) {
15753149Smckusick 			endnetgrent();
15853149Smckusick 			return (1);
15953149Smckusick 		}
16053149Smckusick 	endnetgrent();
16153149Smckusick 	return (0);
16253149Smckusick }
16353149Smckusick 
16453149Smckusick /*
16553149Smckusick  * Parse the netgroup file setting up the linked lists.
16653149Smckusick  */
16753149Smckusick static int
parse_netgrp(group)16853149Smckusick parse_netgrp(group)
16953149Smckusick 	char *group;
17053149Smckusick {
17153166Smckusick 	register char *spos, *epos;
17253166Smckusick 	register int len, strpos;
17353166Smckusick 	char *pos, *gpos;
17453149Smckusick 	struct netgrp *grp;
17553149Smckusick 	struct linelist *lp = linehead;
17653149Smckusick 
17753149Smckusick 	/*
17853149Smckusick 	 * First, see if the line has already been read in.
17953149Smckusick 	 */
18053149Smckusick 	while (lp) {
18153149Smckusick 		if (!strcmp(group, lp->l_groupname))
18253149Smckusick 			break;
18353149Smckusick 		lp = lp->l_next;
18453149Smckusick 	}
18553149Smckusick 	if (lp == (struct linelist *)0 &&
18653149Smckusick 	    (lp = read_for_group(group)) == (struct linelist *)0)
18753149Smckusick 		return (1);
18853149Smckusick 	if (lp->l_parsed) {
18953149Smckusick 		fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
19053149Smckusick 		return (1);
19153149Smckusick 	} else
19253149Smckusick 		lp->l_parsed = 1;
19353149Smckusick 	pos = lp->l_line;
19453149Smckusick 	while (*pos != '\0') {
19553149Smckusick 		if (*pos == '(') {
19653149Smckusick 			grp = (struct netgrp *)malloc(sizeof (struct netgrp));
19753149Smckusick 			bzero((char *)grp, sizeof (struct netgrp));
19853149Smckusick 			grp->ng_next = grouphead.gr;
19953149Smckusick 			grouphead.gr = grp;
20053166Smckusick 			pos++;
20153166Smckusick 			gpos = strsep(&pos, ")");
20253166Smckusick 			for (strpos = 0; strpos < 3; strpos++) {
20353166Smckusick 				if (spos = strsep(&gpos, ",")) {
20453166Smckusick 					while (*spos == ' ' || *spos == '\t')
20553166Smckusick 						spos++;
20653166Smckusick 					if (epos = strpbrk(spos, " \t")) {
20753166Smckusick 						*epos = '\0';
20853166Smckusick 						len = epos - spos;
20953166Smckusick 					} else
21053166Smckusick 						len = strlen(spos);
21153166Smckusick 					if (len > 0) {
21253166Smckusick 						grp->ng_str[strpos] =  (char *)
21353166Smckusick 							malloc(len + 1);
21453166Smckusick 						bcopy(spos, grp->ng_str[strpos],
21553166Smckusick 							len + 1);
21653166Smckusick 					}
21753166Smckusick 				} else
21853166Smckusick 					goto errout;
21953149Smckusick 			}
22053149Smckusick 		} else {
22153166Smckusick 			spos = strsep(&pos, ", \t");
22253149Smckusick 			if (parse_netgrp(spos))
22353149Smckusick 				return (1);
22453149Smckusick 		}
225*68967Sbostic 		if (pos == NULL)
226*68967Sbostic 			break;
22753166Smckusick 		while (*pos == ' ' || *pos == ',' || *pos == '\t')
22853166Smckusick 			pos++;
22953149Smckusick 	}
23053149Smckusick 	return (0);
23153149Smckusick errout:
23253149Smckusick 	fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
23353149Smckusick 		spos);
23453149Smckusick 	return (1);
23553149Smckusick }
23653149Smckusick 
23753149Smckusick /*
23853149Smckusick  * Read the netgroup file and save lines until the line for the netgroup
23953149Smckusick  * is found. Return 1 if eof is encountered.
24053149Smckusick  */
24153149Smckusick static struct linelist *
read_for_group(group)24253149Smckusick read_for_group(group)
24353149Smckusick 	char *group;
24453149Smckusick {
24553166Smckusick 	register char *pos, *spos, *linep, *olinep;
24653166Smckusick 	register int len, olen;
24753166Smckusick 	int cont;
24853149Smckusick 	struct linelist *lp;
24953149Smckusick 	char line[LINSIZ + 1];
25053149Smckusick 
25153149Smckusick 	while (fgets(line, LINSIZ, netf) != NULL) {
25253149Smckusick 		pos = line;
25353166Smckusick 		if (*pos == '#')
25453166Smckusick 			continue;
25553149Smckusick 		while (*pos == ' ' || *pos == '\t')
25653149Smckusick 			pos++;
25753149Smckusick 		spos = pos;
25853149Smckusick 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
25953149Smckusick 			*pos != '\0')
26053149Smckusick 			pos++;
26153149Smckusick 		len = pos - spos;
26253149Smckusick 		while (*pos == ' ' || *pos == '\t')
26353149Smckusick 			pos++;
26453149Smckusick 		if (*pos != '\n' && *pos != '\0') {
26553149Smckusick 			lp = (struct linelist *)malloc(sizeof (*lp));
26653149Smckusick 			lp->l_parsed = 0;
26753149Smckusick 			lp->l_groupname = (char *)malloc(len + 1);
26853149Smckusick 			bcopy(spos, lp->l_groupname, len);
26953149Smckusick 			*(lp->l_groupname + len) = '\0';
27053166Smckusick 			len = strlen(pos);
27153166Smckusick 			olen = 0;
27253166Smckusick 
27353166Smckusick 			/*
27453166Smckusick 			 * Loop around handling line continuations.
27553166Smckusick 			 */
27653166Smckusick 			do {
27753166Smckusick 				if (*(pos + len - 1) == '\n')
27853166Smckusick 					len--;
27953166Smckusick 				if (*(pos + len - 1) == '\\') {
28053166Smckusick 					len--;
28153166Smckusick 					cont = 1;
28253166Smckusick 				} else
28353166Smckusick 					cont = 0;
28453166Smckusick 				if (len > 0) {
28553166Smckusick 					linep = (char *)malloc(olen + len + 1);
28653166Smckusick 					if (olen > 0) {
28753166Smckusick 						bcopy(olinep, linep, olen);
28853166Smckusick 						free(olinep);
28953166Smckusick 					}
29053166Smckusick 					bcopy(pos, linep + olen, len);
29153166Smckusick 					olen += len;
29253166Smckusick 					*(linep + olen) = '\0';
29353166Smckusick 					olinep = linep;
29453166Smckusick 				}
29553166Smckusick 				if (cont) {
29653166Smckusick 					if (fgets(line, LINSIZ, netf)) {
29753166Smckusick 						pos = line;
29853166Smckusick 						len = strlen(pos);
29953166Smckusick 					} else
30053166Smckusick 						cont = 0;
30153166Smckusick 				}
30253166Smckusick 			} while (cont);
30353166Smckusick 			lp->l_line = linep;
30453149Smckusick 			lp->l_next = linehead;
30553149Smckusick 			linehead = lp;
30653149Smckusick 
30753149Smckusick 			/*
30853149Smckusick 			 * If this is the one we wanted, we are done.
30953149Smckusick 			 */
31053149Smckusick 			if (!strcmp(lp->l_groupname, group))
31153149Smckusick 				return (lp);
31253149Smckusick 		}
31353149Smckusick 	}
31453149Smckusick 	return ((struct linelist *)0);
31553149Smckusick }
316