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