153149Smckusick /* 253149Smckusick * Copyright (c) 1992 The Regents of the University of California. 353149Smckusick * 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*53166Smckusick static char sccsid[] = "@(#)getnetgrent.c 5.2 (Berkeley) 04/14/92"; 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 */ 37*53166Smckusick char *ng_str[3]; /* Field pointers, see below */ 3853149Smckusick }; 39*53166Smckusick #define NG_HOST 0 /* Host name */ 40*53166Smckusick #define NG_USER 1 /* User name */ 41*53166Smckusick #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 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 9253149Smckusick getnetgrent(hostp, userp, domp) 9353149Smckusick char **hostp, **userp, **domp; 9453149Smckusick { 9553149Smckusick 9653149Smckusick if (nextgrp) { 97*53166Smckusick *hostp = nextgrp->ng_str[NG_HOST]; 98*53166Smckusick *userp = nextgrp->ng_str[NG_USER]; 99*53166Smckusick *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 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; 132*53166Smckusick if (ogp->ng_str[NG_HOST]) 133*53166Smckusick free(ogp->ng_str[NG_HOST]); 134*53166Smckusick if (ogp->ng_str[NG_USER]) 135*53166Smckusick free(ogp->ng_str[NG_USER]); 136*53166Smckusick if (ogp->ng_str[NG_DOM]) 137*53166Smckusick 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 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 16853149Smckusick parse_netgrp(group) 16953149Smckusick char *group; 17053149Smckusick { 171*53166Smckusick register char *spos, *epos; 172*53166Smckusick register int len, strpos; 173*53166Smckusick 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; 200*53166Smckusick pos++; 201*53166Smckusick gpos = strsep(&pos, ")"); 202*53166Smckusick for (strpos = 0; strpos < 3; strpos++) { 203*53166Smckusick if (spos = strsep(&gpos, ",")) { 204*53166Smckusick while (*spos == ' ' || *spos == '\t') 205*53166Smckusick spos++; 206*53166Smckusick if (epos = strpbrk(spos, " \t")) { 207*53166Smckusick *epos = '\0'; 208*53166Smckusick len = epos - spos; 209*53166Smckusick } else 210*53166Smckusick len = strlen(spos); 211*53166Smckusick if (len > 0) { 212*53166Smckusick grp->ng_str[strpos] = (char *) 213*53166Smckusick malloc(len + 1); 214*53166Smckusick bcopy(spos, grp->ng_str[strpos], 215*53166Smckusick len + 1); 216*53166Smckusick } 217*53166Smckusick } else 218*53166Smckusick goto errout; 21953149Smckusick } 22053149Smckusick } else { 221*53166Smckusick spos = strsep(&pos, ", \t"); 22253149Smckusick if (parse_netgrp(spos)) 22353149Smckusick return (1); 22453149Smckusick } 225*53166Smckusick while (*pos == ' ' || *pos == ',' || *pos == '\t') 226*53166Smckusick pos++; 22753149Smckusick } 22853149Smckusick return (0); 22953149Smckusick errout: 23053149Smckusick fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 23153149Smckusick spos); 23253149Smckusick return (1); 23353149Smckusick } 23453149Smckusick 23553149Smckusick /* 23653149Smckusick * Read the netgroup file and save lines until the line for the netgroup 23753149Smckusick * is found. Return 1 if eof is encountered. 23853149Smckusick */ 23953149Smckusick static struct linelist * 24053149Smckusick read_for_group(group) 24153149Smckusick char *group; 24253149Smckusick { 243*53166Smckusick register char *pos, *spos, *linep, *olinep; 244*53166Smckusick register int len, olen; 245*53166Smckusick int cont; 24653149Smckusick struct linelist *lp; 24753149Smckusick char line[LINSIZ + 1]; 24853149Smckusick 24953149Smckusick while (fgets(line, LINSIZ, netf) != NULL) { 25053149Smckusick pos = line; 251*53166Smckusick if (*pos == '#') 252*53166Smckusick continue; 25353149Smckusick while (*pos == ' ' || *pos == '\t') 25453149Smckusick pos++; 25553149Smckusick spos = pos; 25653149Smckusick while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 25753149Smckusick *pos != '\0') 25853149Smckusick pos++; 25953149Smckusick len = pos - spos; 26053149Smckusick while (*pos == ' ' || *pos == '\t') 26153149Smckusick pos++; 26253149Smckusick if (*pos != '\n' && *pos != '\0') { 26353149Smckusick lp = (struct linelist *)malloc(sizeof (*lp)); 26453149Smckusick lp->l_parsed = 0; 26553149Smckusick lp->l_groupname = (char *)malloc(len + 1); 26653149Smckusick bcopy(spos, lp->l_groupname, len); 26753149Smckusick *(lp->l_groupname + len) = '\0'; 268*53166Smckusick len = strlen(pos); 269*53166Smckusick olen = 0; 270*53166Smckusick 271*53166Smckusick /* 272*53166Smckusick * Loop around handling line continuations. 273*53166Smckusick */ 274*53166Smckusick do { 275*53166Smckusick if (*(pos + len - 1) == '\n') 276*53166Smckusick len--; 277*53166Smckusick if (*(pos + len - 1) == '\\') { 278*53166Smckusick len--; 279*53166Smckusick cont = 1; 280*53166Smckusick } else 281*53166Smckusick cont = 0; 282*53166Smckusick if (len > 0) { 283*53166Smckusick linep = (char *)malloc(olen + len + 1); 284*53166Smckusick if (olen > 0) { 285*53166Smckusick bcopy(olinep, linep, olen); 286*53166Smckusick free(olinep); 287*53166Smckusick } 288*53166Smckusick bcopy(pos, linep + olen, len); 289*53166Smckusick olen += len; 290*53166Smckusick *(linep + olen) = '\0'; 291*53166Smckusick olinep = linep; 292*53166Smckusick } 293*53166Smckusick if (cont) { 294*53166Smckusick if (fgets(line, LINSIZ, netf)) { 295*53166Smckusick pos = line; 296*53166Smckusick len = strlen(pos); 297*53166Smckusick } else 298*53166Smckusick cont = 0; 299*53166Smckusick } 300*53166Smckusick } while (cont); 301*53166Smckusick lp->l_line = linep; 30253149Smckusick lp->l_next = linehead; 30353149Smckusick linehead = lp; 30453149Smckusick 30553149Smckusick /* 30653149Smckusick * If this is the one we wanted, we are done. 30753149Smckusick */ 30853149Smckusick if (!strcmp(lp->l_groupname, group)) 30953149Smckusick return (lp); 31053149Smckusick } 31153149Smckusick } 31253149Smckusick return ((struct linelist *)0); 31353149Smckusick } 314