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