1*53149Smckusick /* 2*53149Smckusick * Copyright (c) 1992 The Regents of the University of California. 3*53149Smckusick * All rights reserved. 4*53149Smckusick * 5*53149Smckusick * This code is derived from software contributed to Berkeley by 6*53149Smckusick * Rick Macklem at The University of Guelph. 7*53149Smckusick * 8*53149Smckusick * %sccs.include.redist.c% 9*53149Smckusick */ 10*53149Smckusick 11*53149Smckusick #if defined(LIBC_SCCS) && !defined(lint) 12*53149Smckusick static char sccsid[] = "@(#)getnetgrent.c 5.1 (Berkeley) 04/09/92"; 13*53149Smckusick #endif /* LIBC_SCCS and not lint */ 14*53149Smckusick 15*53149Smckusick #include <stdio.h> 16*53149Smckusick #include <strings.h> 17*53149Smckusick 18*53149Smckusick #define _PATH_NETGROUP "/etc/netgroup" 19*53149Smckusick 20*53149Smckusick /* 21*53149Smckusick * Static Variables and functions used by setnetgrent(), getnetgrent() and 22*53149Smckusick * endnetgrent(). 23*53149Smckusick * There are two linked lists: 24*53149Smckusick * - linelist is just used by setnetgrent() to parse the net group file via. 25*53149Smckusick * parse_netgrp() 26*53149Smckusick * - netgrp is the list of entries for the current netgroup 27*53149Smckusick */ 28*53149Smckusick struct linelist { 29*53149Smckusick struct linelist *l_next; /* Chain ptr. */ 30*53149Smckusick int l_parsed; /* Flag for cycles */ 31*53149Smckusick char *l_groupname; /* Name of netgroup */ 32*53149Smckusick char *l_line; /* Netgroup entrie(s) to be parsed */ 33*53149Smckusick }; 34*53149Smckusick 35*53149Smckusick struct netgrp { 36*53149Smckusick struct netgrp *ng_next; /* Chain ptr */ 37*53149Smckusick char *ng_host; /* Host name */ 38*53149Smckusick char *ng_user; /* User name */ 39*53149Smckusick char *ng_dom; /* and Domain name */ 40*53149Smckusick }; 41*53149Smckusick 42*53149Smckusick static struct linelist *linehead = (struct linelist *)0; 43*53149Smckusick static struct netgrp *nextgrp = (struct netgrp *)0; 44*53149Smckusick static struct { 45*53149Smckusick struct netgrp *gr; 46*53149Smckusick char *grname; 47*53149Smckusick } grouphead = { 48*53149Smckusick (struct netgrp *)0, 49*53149Smckusick (char *)0, 50*53149Smckusick }; 51*53149Smckusick static FILE *netf = (FILE *)0; 52*53149Smckusick static int parse_netgrp(); 53*53149Smckusick static struct linelist *read_for_group(); 54*53149Smckusick void setnetgrent(), endnetgrent(); 55*53149Smckusick int getnetgrent(), innetgr(); 56*53149Smckusick 57*53149Smckusick #define LINSIZ 1024 /* Length of netgroup file line */ 58*53149Smckusick 59*53149Smckusick /* 60*53149Smckusick * setnetgrent() 61*53149Smckusick * Parse the netgroup file looking for the netgroup and build the list 62*53149Smckusick * of netgrp structures. Let parse_netgrp() and read_for_group() do 63*53149Smckusick * most of the work. 64*53149Smckusick */ 65*53149Smckusick void 66*53149Smckusick setnetgrent(group) 67*53149Smckusick char *group; 68*53149Smckusick { 69*53149Smckusick 70*53149Smckusick if (grouphead.gr == (struct netgrp *)0 || 71*53149Smckusick strcmp(group, grouphead.grname)) { 72*53149Smckusick endnetgrent(); 73*53149Smckusick if (netf = fopen(_PATH_NETGROUP, "r")) { 74*53149Smckusick if (parse_netgrp(group)) 75*53149Smckusick endnetgrent(); 76*53149Smckusick else { 77*53149Smckusick grouphead.grname = (char *) 78*53149Smckusick malloc(strlen(group) + 1); 79*53149Smckusick strcpy(grouphead.grname, group); 80*53149Smckusick } 81*53149Smckusick fclose(netf); 82*53149Smckusick } 83*53149Smckusick } 84*53149Smckusick nextgrp = grouphead.gr; 85*53149Smckusick } 86*53149Smckusick 87*53149Smckusick /* 88*53149Smckusick * Get the next netgroup off the list. 89*53149Smckusick */ 90*53149Smckusick int 91*53149Smckusick getnetgrent(hostp, userp, domp) 92*53149Smckusick char **hostp, **userp, **domp; 93*53149Smckusick { 94*53149Smckusick 95*53149Smckusick if (nextgrp) { 96*53149Smckusick *hostp = nextgrp->ng_host; 97*53149Smckusick *userp = nextgrp->ng_user; 98*53149Smckusick *domp = nextgrp->ng_dom; 99*53149Smckusick nextgrp = nextgrp->ng_next; 100*53149Smckusick return (1); 101*53149Smckusick } 102*53149Smckusick return (0); 103*53149Smckusick } 104*53149Smckusick 105*53149Smckusick /* 106*53149Smckusick * endnetgrent() - cleanup 107*53149Smckusick */ 108*53149Smckusick void 109*53149Smckusick endnetgrent() 110*53149Smckusick { 111*53149Smckusick register struct linelist *lp, *olp; 112*53149Smckusick register struct netgrp *gp, *ogp; 113*53149Smckusick 114*53149Smckusick lp = linehead; 115*53149Smckusick while (lp) { 116*53149Smckusick olp = lp; 117*53149Smckusick lp = lp->l_next; 118*53149Smckusick free(olp->l_groupname); 119*53149Smckusick free(olp->l_line); 120*53149Smckusick free((char *)olp); 121*53149Smckusick } 122*53149Smckusick linehead = (struct linelist *)0; 123*53149Smckusick if (grouphead.grname) { 124*53149Smckusick free(grouphead.grname); 125*53149Smckusick grouphead.grname = (char *)0; 126*53149Smckusick } 127*53149Smckusick gp = grouphead.gr; 128*53149Smckusick while (gp) { 129*53149Smckusick ogp = gp; 130*53149Smckusick gp = gp->ng_next; 131*53149Smckusick if (ogp->ng_host) 132*53149Smckusick free(ogp->ng_host); 133*53149Smckusick if (ogp->ng_user) 134*53149Smckusick free(ogp->ng_user); 135*53149Smckusick if (ogp->ng_dom) 136*53149Smckusick free(ogp->ng_dom); 137*53149Smckusick free((char *)ogp); 138*53149Smckusick } 139*53149Smckusick grouphead.gr = (struct netgrp *)0; 140*53149Smckusick } 141*53149Smckusick 142*53149Smckusick /* 143*53149Smckusick * Search for a match in a netgroup. 144*53149Smckusick */ 145*53149Smckusick int 146*53149Smckusick innetgr(group, host, user, dom) 147*53149Smckusick char *group, *host, *user, *dom; 148*53149Smckusick { 149*53149Smckusick char *hst, *usr, *dm; 150*53149Smckusick 151*53149Smckusick setnetgrent(group); 152*53149Smckusick while (getnetgrent(&hst, &usr, &dm)) 153*53149Smckusick if ((host == (char *)0 || !strcmp(host, hst)) && 154*53149Smckusick (user == (char *)0 || !strcmp(user, usr)) && 155*53149Smckusick (dom == (char *)0 || !strcmp(dom, dm))) { 156*53149Smckusick endnetgrent(); 157*53149Smckusick return (1); 158*53149Smckusick } 159*53149Smckusick endnetgrent(); 160*53149Smckusick return (0); 161*53149Smckusick } 162*53149Smckusick 163*53149Smckusick /* 164*53149Smckusick * Parse the netgroup file setting up the linked lists. 165*53149Smckusick */ 166*53149Smckusick static int 167*53149Smckusick parse_netgrp(group) 168*53149Smckusick char *group; 169*53149Smckusick { 170*53149Smckusick register char *pos, *spos; 171*53149Smckusick register int len; 172*53149Smckusick struct netgrp *grp; 173*53149Smckusick struct linelist *lp = linehead; 174*53149Smckusick 175*53149Smckusick /* 176*53149Smckusick * First, see if the line has already been read in. 177*53149Smckusick */ 178*53149Smckusick while (lp) { 179*53149Smckusick if (!strcmp(group, lp->l_groupname)) 180*53149Smckusick break; 181*53149Smckusick lp = lp->l_next; 182*53149Smckusick } 183*53149Smckusick if (lp == (struct linelist *)0 && 184*53149Smckusick (lp = read_for_group(group)) == (struct linelist *)0) 185*53149Smckusick return (1); 186*53149Smckusick if (lp->l_parsed) { 187*53149Smckusick fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 188*53149Smckusick return (1); 189*53149Smckusick } else 190*53149Smckusick lp->l_parsed = 1; 191*53149Smckusick pos = lp->l_line; 192*53149Smckusick while (*pos != '\0') { 193*53149Smckusick if (*pos == '(') { 194*53149Smckusick grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 195*53149Smckusick bzero((char *)grp, sizeof (struct netgrp)); 196*53149Smckusick grp->ng_next = grouphead.gr; 197*53149Smckusick grouphead.gr = grp; 198*53149Smckusick spos = ++pos; 199*53149Smckusick while (*pos != ',' && *pos != '\0') 200*53149Smckusick pos++; 201*53149Smckusick if (*pos == '\0') 202*53149Smckusick goto errout; 203*53149Smckusick len = pos - spos; 204*53149Smckusick if (len > 0) { 205*53149Smckusick grp->ng_host = (char *)malloc(len + 1); 206*53149Smckusick bcopy(spos, grp->ng_host, len); 207*53149Smckusick *(grp->ng_host + len) = '\0'; 208*53149Smckusick } 209*53149Smckusick spos = ++pos; 210*53149Smckusick while (*pos != ',' && *pos != '\0') 211*53149Smckusick pos++; 212*53149Smckusick if (*pos == '\0') 213*53149Smckusick goto errout; 214*53149Smckusick len = pos - spos; 215*53149Smckusick if (len > 0) { 216*53149Smckusick grp->ng_user = (char *)malloc(len + 1); 217*53149Smckusick bcopy(spos, grp->ng_user, len); 218*53149Smckusick *(grp->ng_user + len) = '\0'; 219*53149Smckusick } 220*53149Smckusick spos = ++pos; 221*53149Smckusick while (*pos != ')' && *pos != '\0') 222*53149Smckusick pos++; 223*53149Smckusick if (*pos == '\0') 224*53149Smckusick goto errout; 225*53149Smckusick len = pos - spos; 226*53149Smckusick if (len > 0) { 227*53149Smckusick grp->ng_dom = (char *)malloc(len + 1); 228*53149Smckusick bcopy(spos, grp->ng_dom, len); 229*53149Smckusick *(grp->ng_dom + len) = '\0'; 230*53149Smckusick } 231*53149Smckusick if (*++pos != '\0' && 232*53149Smckusick (*pos != ',' || *++pos == ',' || *pos == '\0')) 233*53149Smckusick goto errout; 234*53149Smckusick } else { 235*53149Smckusick spos = pos; 236*53149Smckusick while (*pos != ',' && *pos != '\0') 237*53149Smckusick pos++; 238*53149Smckusick if (*pos == ',') 239*53149Smckusick *pos++ = '\0'; 240*53149Smckusick if (parse_netgrp(spos)) 241*53149Smckusick return (1); 242*53149Smckusick } 243*53149Smckusick } 244*53149Smckusick return (0); 245*53149Smckusick errout: 246*53149Smckusick fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 247*53149Smckusick spos); 248*53149Smckusick return (1); 249*53149Smckusick } 250*53149Smckusick 251*53149Smckusick /* 252*53149Smckusick * Read the netgroup file and save lines until the line for the netgroup 253*53149Smckusick * is found. Return 1 if eof is encountered. 254*53149Smckusick */ 255*53149Smckusick static struct linelist * 256*53149Smckusick read_for_group(group) 257*53149Smckusick char *group; 258*53149Smckusick { 259*53149Smckusick register char *pos, *spos; 260*53149Smckusick register int len; 261*53149Smckusick struct linelist *lp; 262*53149Smckusick char line[LINSIZ + 1]; 263*53149Smckusick 264*53149Smckusick while (fgets(line, LINSIZ, netf) != NULL) { 265*53149Smckusick pos = line; 266*53149Smckusick while (*pos == ' ' || *pos == '\t') 267*53149Smckusick pos++; 268*53149Smckusick spos = pos; 269*53149Smckusick while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 270*53149Smckusick *pos != '\0') 271*53149Smckusick pos++; 272*53149Smckusick len = pos - spos; 273*53149Smckusick while (*pos == ' ' || *pos == '\t') 274*53149Smckusick pos++; 275*53149Smckusick if (*pos != '\n' && *pos != '\0') { 276*53149Smckusick lp = (struct linelist *)malloc(sizeof (*lp)); 277*53149Smckusick lp->l_parsed = 0; 278*53149Smckusick lp->l_groupname = (char *)malloc(len + 1); 279*53149Smckusick bcopy(spos, lp->l_groupname, len); 280*53149Smckusick *(lp->l_groupname + len) = '\0'; 281*53149Smckusick spos = lp->l_line = (char *)malloc(LINSIZ); 282*53149Smckusick while (*pos != '\n' && *pos != '\0') { 283*53149Smckusick if (*pos != ' ' && *pos != '\t') 284*53149Smckusick *spos++ = *pos++; 285*53149Smckusick else 286*53149Smckusick pos++; 287*53149Smckusick } 288*53149Smckusick *spos = '\0'; 289*53149Smckusick lp->l_next = linehead; 290*53149Smckusick linehead = lp; 291*53149Smckusick 292*53149Smckusick /* 293*53149Smckusick * If this is the one we wanted, we are done. 294*53149Smckusick */ 295*53149Smckusick if (!strcmp(lp->l_groupname, group)) 296*53149Smckusick return (lp); 297*53149Smckusick } 298*53149Smckusick } 299*53149Smckusick return ((struct linelist *)0); 300*53149Smckusick } 301