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