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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if defined(LIBC_SCCS) && !defined(lint) 38 static char sccsid[] = "@(#)getnetgrent.c 8.1 (Berkeley) 6/4/93"; 39 #endif /* LIBC_SCCS and not lint */ 40 41 #include <stdio.h> 42 #include <strings.h> 43 44 #define _PATH_NETGROUP "/etc/netgroup" 45 46 /* 47 * Static Variables and functions used by setnetgrent(), getnetgrent() and 48 * endnetgrent(). 49 * There are two linked lists: 50 * - linelist is just used by setnetgrent() to parse the net group file via. 51 * parse_netgrp() 52 * - netgrp is the list of entries for the current netgroup 53 */ 54 struct linelist { 55 struct linelist *l_next; /* Chain ptr. */ 56 int l_parsed; /* Flag for cycles */ 57 char *l_groupname; /* Name of netgroup */ 58 char *l_line; /* Netgroup entrie(s) to be parsed */ 59 }; 60 61 struct netgrp { 62 struct netgrp *ng_next; /* Chain ptr */ 63 char *ng_str[3]; /* Field pointers, see below */ 64 }; 65 #define NG_HOST 0 /* Host name */ 66 #define NG_USER 1 /* User name */ 67 #define NG_DOM 2 /* and Domain name */ 68 69 static struct linelist *linehead = (struct linelist *)0; 70 static struct netgrp *nextgrp = (struct netgrp *)0; 71 static struct { 72 struct netgrp *gr; 73 char *grname; 74 } grouphead = { 75 (struct netgrp *)0, 76 (char *)0, 77 }; 78 static FILE *netf = (FILE *)0; 79 static int parse_netgrp(); 80 static struct linelist *read_for_group(); 81 void setnetgrent(), endnetgrent(); 82 int getnetgrent(), innetgr(); 83 84 #define LINSIZ 1024 /* Length of netgroup file line */ 85 86 /* 87 * setnetgrent() 88 * Parse the netgroup file looking for the netgroup and build the list 89 * of netgrp structures. Let parse_netgrp() and read_for_group() do 90 * most of the work. 91 */ 92 void 93 setnetgrent(group) 94 char *group; 95 { 96 97 if (grouphead.gr == (struct netgrp *)0 || 98 strcmp(group, grouphead.grname)) { 99 endnetgrent(); 100 if (netf = fopen(_PATH_NETGROUP, "r")) { 101 if (parse_netgrp(group)) 102 endnetgrent(); 103 else { 104 grouphead.grname = (char *) 105 malloc(strlen(group) + 1); 106 strcpy(grouphead.grname, group); 107 } 108 fclose(netf); 109 } 110 } 111 nextgrp = grouphead.gr; 112 } 113 114 /* 115 * Get the next netgroup off the list. 116 */ 117 int 118 getnetgrent(hostp, userp, domp) 119 char **hostp, **userp, **domp; 120 { 121 122 if (nextgrp) { 123 *hostp = nextgrp->ng_str[NG_HOST]; 124 *userp = nextgrp->ng_str[NG_USER]; 125 *domp = nextgrp->ng_str[NG_DOM]; 126 nextgrp = nextgrp->ng_next; 127 return (1); 128 } 129 return (0); 130 } 131 132 /* 133 * endnetgrent() - cleanup 134 */ 135 void 136 endnetgrent() 137 { 138 register struct linelist *lp, *olp; 139 register struct netgrp *gp, *ogp; 140 141 lp = linehead; 142 while (lp) { 143 olp = lp; 144 lp = lp->l_next; 145 free(olp->l_groupname); 146 free(olp->l_line); 147 free((char *)olp); 148 } 149 linehead = (struct linelist *)0; 150 if (grouphead.grname) { 151 free(grouphead.grname); 152 grouphead.grname = (char *)0; 153 } 154 gp = grouphead.gr; 155 while (gp) { 156 ogp = gp; 157 gp = gp->ng_next; 158 if (ogp->ng_str[NG_HOST]) 159 free(ogp->ng_str[NG_HOST]); 160 if (ogp->ng_str[NG_USER]) 161 free(ogp->ng_str[NG_USER]); 162 if (ogp->ng_str[NG_DOM]) 163 free(ogp->ng_str[NG_DOM]); 164 free((char *)ogp); 165 } 166 grouphead.gr = (struct netgrp *)0; 167 } 168 169 /* 170 * Search for a match in a netgroup. 171 */ 172 int 173 innetgr(group, host, user, dom) 174 char *group, *host, *user, *dom; 175 { 176 char *hst, *usr, *dm; 177 178 setnetgrent(group); 179 while (getnetgrent(&hst, &usr, &dm)) 180 if ((host == (char *)0 || !strcmp(host, hst)) && 181 (user == (char *)0 || !strcmp(user, usr)) && 182 (dom == (char *)0 || !strcmp(dom, dm))) { 183 endnetgrent(); 184 return (1); 185 } 186 endnetgrent(); 187 return (0); 188 } 189 190 /* 191 * Parse the netgroup file setting up the linked lists. 192 */ 193 static int 194 parse_netgrp(group) 195 char *group; 196 { 197 register char *spos, *epos; 198 register int len, strpos; 199 char *pos, *gpos; 200 struct netgrp *grp; 201 struct linelist *lp = linehead; 202 203 /* 204 * First, see if the line has already been read in. 205 */ 206 while (lp) { 207 if (!strcmp(group, lp->l_groupname)) 208 break; 209 lp = lp->l_next; 210 } 211 if (lp == (struct linelist *)0 && 212 (lp = read_for_group(group)) == (struct linelist *)0) 213 return (1); 214 if (lp->l_parsed) { 215 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 216 return (1); 217 } else 218 lp->l_parsed = 1; 219 pos = lp->l_line; 220 while (*pos != '\0') { 221 if (*pos == '(') { 222 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 223 bzero((char *)grp, sizeof (struct netgrp)); 224 grp->ng_next = grouphead.gr; 225 grouphead.gr = grp; 226 pos++; 227 gpos = strsep(&pos, ")"); 228 for (strpos = 0; strpos < 3; strpos++) { 229 if (spos = strsep(&gpos, ",")) { 230 while (*spos == ' ' || *spos == '\t') 231 spos++; 232 if (epos = strpbrk(spos, " \t")) { 233 *epos = '\0'; 234 len = epos - spos; 235 } else 236 len = strlen(spos); 237 if (len > 0) { 238 grp->ng_str[strpos] = (char *) 239 malloc(len + 1); 240 bcopy(spos, grp->ng_str[strpos], 241 len + 1); 242 } 243 } else 244 goto errout; 245 } 246 } else { 247 spos = strsep(&pos, ", \t"); 248 if (parse_netgrp(spos)) 249 return (1); 250 } 251 while (*pos == ' ' || *pos == ',' || *pos == '\t') 252 pos++; 253 } 254 return (0); 255 errout: 256 fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 257 spos); 258 return (1); 259 } 260 261 /* 262 * Read the netgroup file and save lines until the line for the netgroup 263 * is found. Return 1 if eof is encountered. 264 */ 265 static struct linelist * 266 read_for_group(group) 267 char *group; 268 { 269 register char *pos, *spos, *linep, *olinep; 270 register int len, olen; 271 int cont; 272 struct linelist *lp; 273 char line[LINSIZ + 1]; 274 275 while (fgets(line, LINSIZ, netf) != NULL) { 276 pos = line; 277 if (*pos == '#') 278 continue; 279 while (*pos == ' ' || *pos == '\t') 280 pos++; 281 spos = pos; 282 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 283 *pos != '\0') 284 pos++; 285 len = pos - spos; 286 while (*pos == ' ' || *pos == '\t') 287 pos++; 288 if (*pos != '\n' && *pos != '\0') { 289 lp = (struct linelist *)malloc(sizeof (*lp)); 290 lp->l_parsed = 0; 291 lp->l_groupname = (char *)malloc(len + 1); 292 bcopy(spos, lp->l_groupname, len); 293 *(lp->l_groupname + len) = '\0'; 294 len = strlen(pos); 295 olen = 0; 296 297 /* 298 * Loop around handling line continuations. 299 */ 300 do { 301 if (*(pos + len - 1) == '\n') 302 len--; 303 if (*(pos + len - 1) == '\\') { 304 len--; 305 cont = 1; 306 } else 307 cont = 0; 308 if (len > 0) { 309 linep = (char *)malloc(olen + len + 1); 310 if (olen > 0) { 311 bcopy(olinep, linep, olen); 312 free(olinep); 313 } 314 bcopy(pos, linep + olen, len); 315 olen += len; 316 *(linep + olen) = '\0'; 317 olinep = linep; 318 } 319 if (cont) { 320 if (fgets(line, LINSIZ, netf)) { 321 pos = line; 322 len = strlen(pos); 323 } else 324 cont = 0; 325 } 326 } while (cont); 327 lp->l_line = linep; 328 lp->l_next = linehead; 329 linehead = lp; 330 331 /* 332 * If this is the one we wanted, we are done. 333 */ 334 if (!strcmp(lp->l_groupname, group)) 335 return (lp); 336 } 337 } 338 return ((struct linelist *)0); 339 } 340