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.2 (Berkeley) 04/14/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_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 while (*pos == ' ' || *pos == ',' || *pos == '\t') 226 pos++; 227 } 228 return (0); 229 errout: 230 fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 231 spos); 232 return (1); 233 } 234 235 /* 236 * Read the netgroup file and save lines until the line for the netgroup 237 * is found. Return 1 if eof is encountered. 238 */ 239 static struct linelist * 240 read_for_group(group) 241 char *group; 242 { 243 register char *pos, *spos, *linep, *olinep; 244 register int len, olen; 245 int cont; 246 struct linelist *lp; 247 char line[LINSIZ + 1]; 248 249 while (fgets(line, LINSIZ, netf) != NULL) { 250 pos = line; 251 if (*pos == '#') 252 continue; 253 while (*pos == ' ' || *pos == '\t') 254 pos++; 255 spos = pos; 256 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 257 *pos != '\0') 258 pos++; 259 len = pos - spos; 260 while (*pos == ' ' || *pos == '\t') 261 pos++; 262 if (*pos != '\n' && *pos != '\0') { 263 lp = (struct linelist *)malloc(sizeof (*lp)); 264 lp->l_parsed = 0; 265 lp->l_groupname = (char *)malloc(len + 1); 266 bcopy(spos, lp->l_groupname, len); 267 *(lp->l_groupname + len) = '\0'; 268 len = strlen(pos); 269 olen = 0; 270 271 /* 272 * Loop around handling line continuations. 273 */ 274 do { 275 if (*(pos + len - 1) == '\n') 276 len--; 277 if (*(pos + len - 1) == '\\') { 278 len--; 279 cont = 1; 280 } else 281 cont = 0; 282 if (len > 0) { 283 linep = (char *)malloc(olen + len + 1); 284 if (olen > 0) { 285 bcopy(olinep, linep, olen); 286 free(olinep); 287 } 288 bcopy(pos, linep + olen, len); 289 olen += len; 290 *(linep + olen) = '\0'; 291 olinep = linep; 292 } 293 if (cont) { 294 if (fgets(line, LINSIZ, netf)) { 295 pos = line; 296 len = strlen(pos); 297 } else 298 cont = 0; 299 } 300 } while (cont); 301 lp->l_line = linep; 302 lp->l_next = linehead; 303 linehead = lp; 304 305 /* 306 * If this is the one we wanted, we are done. 307 */ 308 if (!strcmp(lp->l_groupname, group)) 309 return (lp); 310 } 311 } 312 return ((struct linelist *)0); 313 } 314