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