1a44e4d14SBill Paul /* 2a44e4d14SBill Paul * Copyright (c) 1992, 1993 3a44e4d14SBill Paul * The Regents of the University of California. All rights reserved. 4a44e4d14SBill Paul * 5a44e4d14SBill Paul * This code is derived from software contributed to Berkeley by 6a44e4d14SBill Paul * Rick Macklem at The University of Guelph. 7a44e4d14SBill Paul * 8a44e4d14SBill Paul * Redistribution and use in source and binary forms, with or without 9a44e4d14SBill Paul * modification, are permitted provided that the following conditions 10a44e4d14SBill Paul * are met: 11a44e4d14SBill Paul * 1. Redistributions of source code must retain the above copyright 12a44e4d14SBill Paul * notice, this list of conditions and the following disclaimer. 13a44e4d14SBill Paul * 2. Redistributions in binary form must reproduce the above copyright 14a44e4d14SBill Paul * notice, this list of conditions and the following disclaimer in the 15a44e4d14SBill Paul * documentation and/or other materials provided with the distribution. 16a44e4d14SBill Paul * 3. All advertising materials mentioning features or use of this software 17a44e4d14SBill Paul * must display the following acknowledgement: 18a44e4d14SBill Paul * This product includes software developed by the University of 19a44e4d14SBill Paul * California, Berkeley and its contributors. 20a44e4d14SBill Paul * 4. Neither the name of the University nor the names of its contributors 21a44e4d14SBill Paul * may be used to endorse or promote products derived from this software 22a44e4d14SBill Paul * without specific prior written permission. 23a44e4d14SBill Paul * 24a44e4d14SBill Paul * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25a44e4d14SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26a44e4d14SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27a44e4d14SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28a44e4d14SBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29a44e4d14SBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30a44e4d14SBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31a44e4d14SBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32a44e4d14SBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33a44e4d14SBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34a44e4d14SBill Paul * SUCH DAMAGE. 35a44e4d14SBill Paul */ 36a44e4d14SBill Paul 37a44e4d14SBill Paul #if defined(LIBC_SCCS) && !defined(lint) 3879cc85d3SBill Paul static char sccsid[] = "$Id: parse_netgroup.c,v 1.2 1996/05/12 17:17:44 wpaul Exp $"; 39a44e4d14SBill Paul #endif /* LIBC_SCCS and not lint */ 40a44e4d14SBill Paul 41a44e4d14SBill Paul /* 42a44e4d14SBill Paul * This is a specially hacked-up version of getnetgrent.c used to parse 43a44e4d14SBill Paul * data from the stored hash table of netgroup info rather than from a 44a44e4d14SBill Paul * file. It's used mainly for the parse_netgroup() function. All the YP 45a44e4d14SBill Paul * stuff and file support has been stripped out since it isn't needed. 46a44e4d14SBill Paul */ 47a44e4d14SBill Paul 48a44e4d14SBill Paul #include <stdio.h> 49a44e4d14SBill Paul #include <strings.h> 50a44e4d14SBill Paul #include <stdlib.h> 51a44e4d14SBill Paul #include <unistd.h> 52a44e4d14SBill Paul #include "hash.h" 53a44e4d14SBill Paul 54d7b71c67SBill Paul #ifndef lint 5579cc85d3SBill Paul static const char rcsid[] = "$Id: parse_netgroup.c,v 1.2 1996/05/12 17:17:44 wpaul Exp $"; 56d7b71c67SBill Paul #endif 57d7b71c67SBill Paul 58a44e4d14SBill Paul /* 59a44e4d14SBill Paul * Static Variables and functions used by setnetgrent(), getnetgrent() and 60a44e4d14SBill Paul * __endnetgrent(). 61a44e4d14SBill Paul * There are two linked lists: 62a44e4d14SBill Paul * - linelist is just used by setnetgrent() to parse the net group file via. 63a44e4d14SBill Paul * parse_netgrp() 64a44e4d14SBill Paul * - netgrp is the list of entries for the current netgroup 65a44e4d14SBill Paul */ 66a44e4d14SBill Paul struct linelist { 67a44e4d14SBill Paul struct linelist *l_next; /* Chain ptr. */ 68a44e4d14SBill Paul int l_parsed; /* Flag for cycles */ 69a44e4d14SBill Paul char *l_groupname; /* Name of netgroup */ 70a44e4d14SBill Paul char *l_line; /* Netgroup entrie(s) to be parsed */ 71a44e4d14SBill Paul }; 72a44e4d14SBill Paul 73a44e4d14SBill Paul struct netgrp { 74a44e4d14SBill Paul struct netgrp *ng_next; /* Chain ptr */ 75a44e4d14SBill Paul char *ng_str[3]; /* Field pointers, see below */ 76a44e4d14SBill Paul }; 77a44e4d14SBill Paul #define NG_HOST 0 /* Host name */ 78a44e4d14SBill Paul #define NG_USER 1 /* User name */ 79a44e4d14SBill Paul #define NG_DOM 2 /* and Domain name */ 80a44e4d14SBill Paul 81a44e4d14SBill Paul static struct linelist *linehead = (struct linelist *)0; 82a44e4d14SBill Paul static struct netgrp *nextgrp = (struct netgrp *)0; 83a44e4d14SBill Paul static struct { 84a44e4d14SBill Paul struct netgrp *gr; 85a44e4d14SBill Paul char *grname; 86a44e4d14SBill Paul } grouphead = { 87a44e4d14SBill Paul (struct netgrp *)0, 88a44e4d14SBill Paul (char *)0, 89a44e4d14SBill Paul }; 90a44e4d14SBill Paul static int parse_netgrp(); 91a44e4d14SBill Paul static struct linelist *read_for_group(); 92a44e4d14SBill Paul void __setnetgrent(), __endnetgrent(); 93a44e4d14SBill Paul int __getnetgrent(); 94a44e4d14SBill Paul extern struct group_entry *gtable[]; 95a44e4d14SBill Paul 96a44e4d14SBill Paul /* 97a44e4d14SBill Paul * setnetgrent() 98a44e4d14SBill Paul * Parse the netgroup file looking for the netgroup and build the list 99a44e4d14SBill Paul * of netgrp structures. Let parse_netgrp() and read_for_group() do 100a44e4d14SBill Paul * most of the work. 101a44e4d14SBill Paul */ 102a44e4d14SBill Paul void 103a44e4d14SBill Paul __setnetgrent(group) 104a44e4d14SBill Paul char *group; 105a44e4d14SBill Paul { 106a44e4d14SBill Paul /* Sanity check */ 107a44e4d14SBill Paul 108a44e4d14SBill Paul if (group == NULL || !strlen(group)) 109a44e4d14SBill Paul return; 110a44e4d14SBill Paul 111a44e4d14SBill Paul if (grouphead.gr == (struct netgrp *)0 || 112a44e4d14SBill Paul strcmp(group, grouphead.grname)) { 113a44e4d14SBill Paul __endnetgrent(); 114a44e4d14SBill Paul if (parse_netgrp(group)) 115a44e4d14SBill Paul __endnetgrent(); 116a44e4d14SBill Paul else { 117a44e4d14SBill Paul grouphead.grname = (char *) 118a44e4d14SBill Paul malloc(strlen(group) + 1); 119a44e4d14SBill Paul strcpy(grouphead.grname, group); 120a44e4d14SBill Paul } 121a44e4d14SBill Paul } 122a44e4d14SBill Paul nextgrp = grouphead.gr; 123a44e4d14SBill Paul } 124a44e4d14SBill Paul 125a44e4d14SBill Paul /* 126a44e4d14SBill Paul * Get the next netgroup off the list. 127a44e4d14SBill Paul */ 128a44e4d14SBill Paul int 129a44e4d14SBill Paul __getnetgrent(hostp, userp, domp) 130a44e4d14SBill Paul char **hostp, **userp, **domp; 131a44e4d14SBill Paul { 132a44e4d14SBill Paul if (nextgrp) { 133a44e4d14SBill Paul *hostp = nextgrp->ng_str[NG_HOST]; 134a44e4d14SBill Paul *userp = nextgrp->ng_str[NG_USER]; 135a44e4d14SBill Paul *domp = nextgrp->ng_str[NG_DOM]; 136a44e4d14SBill Paul nextgrp = nextgrp->ng_next; 137a44e4d14SBill Paul return (1); 138a44e4d14SBill Paul } 139a44e4d14SBill Paul return (0); 140a44e4d14SBill Paul } 141a44e4d14SBill Paul 142a44e4d14SBill Paul /* 143a44e4d14SBill Paul * __endnetgrent() - cleanup 144a44e4d14SBill Paul */ 145a44e4d14SBill Paul void 146a44e4d14SBill Paul __endnetgrent() 147a44e4d14SBill Paul { 148a44e4d14SBill Paul register struct linelist *lp, *olp; 149a44e4d14SBill Paul register struct netgrp *gp, *ogp; 150a44e4d14SBill Paul 151a44e4d14SBill Paul lp = linehead; 152a44e4d14SBill Paul while (lp) { 153a44e4d14SBill Paul olp = lp; 154a44e4d14SBill Paul lp = lp->l_next; 155a44e4d14SBill Paul free(olp->l_groupname); 156a44e4d14SBill Paul free(olp->l_line); 157a44e4d14SBill Paul free((char *)olp); 158a44e4d14SBill Paul } 159a44e4d14SBill Paul linehead = (struct linelist *)0; 160a44e4d14SBill Paul if (grouphead.grname) { 161a44e4d14SBill Paul free(grouphead.grname); 162a44e4d14SBill Paul grouphead.grname = (char *)0; 163a44e4d14SBill Paul } 164a44e4d14SBill Paul gp = grouphead.gr; 165a44e4d14SBill Paul while (gp) { 166a44e4d14SBill Paul ogp = gp; 167a44e4d14SBill Paul gp = gp->ng_next; 168a44e4d14SBill Paul if (ogp->ng_str[NG_HOST]) 169a44e4d14SBill Paul free(ogp->ng_str[NG_HOST]); 170a44e4d14SBill Paul if (ogp->ng_str[NG_USER]) 171a44e4d14SBill Paul free(ogp->ng_str[NG_USER]); 172a44e4d14SBill Paul if (ogp->ng_str[NG_DOM]) 173a44e4d14SBill Paul free(ogp->ng_str[NG_DOM]); 174a44e4d14SBill Paul free((char *)ogp); 175a44e4d14SBill Paul } 176a44e4d14SBill Paul grouphead.gr = (struct netgrp *)0; 177a44e4d14SBill Paul } 178a44e4d14SBill Paul 179a44e4d14SBill Paul /* 180a44e4d14SBill Paul * Parse the netgroup file setting up the linked lists. 181a44e4d14SBill Paul */ 182a44e4d14SBill Paul static int 183a44e4d14SBill Paul parse_netgrp(group) 184a44e4d14SBill Paul char *group; 185a44e4d14SBill Paul { 186a44e4d14SBill Paul register char *spos, *epos; 187a44e4d14SBill Paul register int len, strpos; 188a44e4d14SBill Paul #ifdef DEBUG 189a44e4d14SBill Paul register int fields; 190a44e4d14SBill Paul #endif 191a44e4d14SBill Paul char *pos, *gpos; 192a44e4d14SBill Paul struct netgrp *grp; 193a44e4d14SBill Paul struct linelist *lp = linehead; 194a44e4d14SBill Paul 195a44e4d14SBill Paul /* 196a44e4d14SBill Paul * First, see if the line has already been read in. 197a44e4d14SBill Paul */ 198a44e4d14SBill Paul while (lp) { 199a44e4d14SBill Paul if (!strcmp(group, lp->l_groupname)) 200a44e4d14SBill Paul break; 201a44e4d14SBill Paul lp = lp->l_next; 202a44e4d14SBill Paul } 203a44e4d14SBill Paul if (lp == (struct linelist *)0 && 204a44e4d14SBill Paul (lp = read_for_group(group)) == (struct linelist *)0) 205a44e4d14SBill Paul return (1); 206a44e4d14SBill Paul if (lp->l_parsed) { 207a44e4d14SBill Paul #ifdef DEBUG 208a44e4d14SBill Paul /* 209a44e4d14SBill Paul * This error message is largely superflous since the 210a44e4d14SBill Paul * code handles the error condition sucessfully, and 211a44e4d14SBill Paul * spewing it out from inside libc can actually hose 212a44e4d14SBill Paul * certain programs. 213a44e4d14SBill Paul */ 214a44e4d14SBill Paul fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 215a44e4d14SBill Paul #endif 216a44e4d14SBill Paul return (1); 217a44e4d14SBill Paul } else 218a44e4d14SBill Paul lp->l_parsed = 1; 219a44e4d14SBill Paul pos = lp->l_line; 220a44e4d14SBill Paul /* Watch for null pointer dereferences, dammit! */ 221a44e4d14SBill Paul while (pos != NULL && *pos != '\0') { 222a44e4d14SBill Paul if (*pos == '(') { 223a44e4d14SBill Paul grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 224a44e4d14SBill Paul bzero((char *)grp, sizeof (struct netgrp)); 225a44e4d14SBill Paul grp->ng_next = grouphead.gr; 226a44e4d14SBill Paul grouphead.gr = grp; 227a44e4d14SBill Paul pos++; 228a44e4d14SBill Paul gpos = strsep(&pos, ")"); 229a44e4d14SBill Paul #ifdef DEBUG 230a44e4d14SBill Paul fields = 0; 231a44e4d14SBill Paul #endif 232a44e4d14SBill Paul for (strpos = 0; strpos < 3; strpos++) { 233a44e4d14SBill Paul if ((spos = strsep(&gpos, ","))) { 234a44e4d14SBill Paul #ifdef DEBUG 235a44e4d14SBill Paul fields++; 236a44e4d14SBill Paul #endif 237a44e4d14SBill Paul while (*spos == ' ' || *spos == '\t') 238a44e4d14SBill Paul spos++; 239a44e4d14SBill Paul if ((epos = strpbrk(spos, " \t"))) { 240a44e4d14SBill Paul *epos = '\0'; 241a44e4d14SBill Paul len = epos - spos; 242a44e4d14SBill Paul } else 243a44e4d14SBill Paul len = strlen(spos); 244a44e4d14SBill Paul if (len > 0) { 245a44e4d14SBill Paul grp->ng_str[strpos] = (char *) 246a44e4d14SBill Paul malloc(len + 1); 247a44e4d14SBill Paul bcopy(spos, grp->ng_str[strpos], 248a44e4d14SBill Paul len + 1); 249a44e4d14SBill Paul } 250a44e4d14SBill Paul } else { 251a44e4d14SBill Paul /* 252a44e4d14SBill Paul * All other systems I've tested 253a44e4d14SBill Paul * return NULL for empty netgroup 254a44e4d14SBill Paul * fields. It's up to user programs 255a44e4d14SBill Paul * to handle the NULLs appropriately. 256a44e4d14SBill Paul */ 257a44e4d14SBill Paul grp->ng_str[strpos] = NULL; 258a44e4d14SBill Paul } 259a44e4d14SBill Paul } 260a44e4d14SBill Paul #ifdef DEBUG 261a44e4d14SBill Paul /* 262a44e4d14SBill Paul * Note: on other platforms, malformed netgroup 263a44e4d14SBill Paul * entries are not normally flagged. While we 264a44e4d14SBill Paul * can catch bad entries and report them, we should 265a44e4d14SBill Paul * stay silent by default for compatibility's sake. 266a44e4d14SBill Paul */ 267a44e4d14SBill Paul if (fields < 3) 268a44e4d14SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 269a44e4d14SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 270a44e4d14SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 271a44e4d14SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 272a44e4d14SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 273a44e4d14SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 274a44e4d14SBill Paul lp->l_groupname); 275a44e4d14SBill Paul #endif 276a44e4d14SBill Paul } else { 277a44e4d14SBill Paul spos = strsep(&pos, ", \t"); 278a44e4d14SBill Paul if (parse_netgrp(spos)) 279a44e4d14SBill Paul continue; 280a44e4d14SBill Paul } 281a44e4d14SBill Paul /* Watch for null pointer dereferences, dammit! */ 282a44e4d14SBill Paul if (pos != NULL) 283a44e4d14SBill Paul while (*pos == ' ' || *pos == ',' || *pos == '\t') 284a44e4d14SBill Paul pos++; 285a44e4d14SBill Paul } 286a44e4d14SBill Paul return (0); 287a44e4d14SBill Paul } 288a44e4d14SBill Paul 289a44e4d14SBill Paul /* 290a44e4d14SBill Paul * Read the netgroup file and save lines until the line for the netgroup 291a44e4d14SBill Paul * is found. Return 1 if eof is encountered. 292a44e4d14SBill Paul */ 293a44e4d14SBill Paul static struct linelist * 294a44e4d14SBill Paul read_for_group(group) 295a44e4d14SBill Paul char *group; 296a44e4d14SBill Paul { 29779cc85d3SBill Paul register char *pos, *spos, *linep = NULL, *olinep = NULL; 298a44e4d14SBill Paul register int len, olen; 299a44e4d14SBill Paul int cont; 300a44e4d14SBill Paul struct linelist *lp; 301a44e4d14SBill Paul char line[LINSIZ + 1]; 30279cc85d3SBill Paul char *data = NULL; 303a44e4d14SBill Paul 304a44e4d14SBill Paul data = lookup (gtable, group); 305a44e4d14SBill Paul sprintf(line, "%s %s", group, data); 306a44e4d14SBill Paul pos = (char *)&line; 307a44e4d14SBill Paul #ifdef CANT_HAPPEN 308a44e4d14SBill Paul if (*pos == '#') 309a44e4d14SBill Paul continue; 310a44e4d14SBill Paul #endif 311a44e4d14SBill Paul while (*pos == ' ' || *pos == '\t') 312a44e4d14SBill Paul pos++; 313a44e4d14SBill Paul spos = pos; 314a44e4d14SBill Paul while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 315a44e4d14SBill Paul *pos != '\0') 316a44e4d14SBill Paul pos++; 317a44e4d14SBill Paul len = pos - spos; 318a44e4d14SBill Paul while (*pos == ' ' || *pos == '\t') 319a44e4d14SBill Paul pos++; 320a44e4d14SBill Paul if (*pos != '\n' && *pos != '\0') { 321a44e4d14SBill Paul lp = (struct linelist *)malloc(sizeof (*lp)); 322a44e4d14SBill Paul lp->l_parsed = 0; 323a44e4d14SBill Paul lp->l_groupname = (char *)malloc(len + 1); 324a44e4d14SBill Paul bcopy(spos, lp->l_groupname, len); 325a44e4d14SBill Paul *(lp->l_groupname + len) = '\0'; 326a44e4d14SBill Paul len = strlen(pos); 327a44e4d14SBill Paul olen = 0; 328a44e4d14SBill Paul /* 329a44e4d14SBill Paul * Loop around handling line continuations. 330a44e4d14SBill Paul */ 331a44e4d14SBill Paul do { 332a44e4d14SBill Paul if (*(pos + len - 1) == '\n') 333a44e4d14SBill Paul len--; 334a44e4d14SBill Paul if (*(pos + len - 1) == '\\') { 335a44e4d14SBill Paul len--; 336a44e4d14SBill Paul cont = 1; 337a44e4d14SBill Paul } else 338a44e4d14SBill Paul cont = 0; 339a44e4d14SBill Paul if (len > 0) { 340a44e4d14SBill Paul linep = (char *)malloc(olen + len + 1); 341a44e4d14SBill Paul if (olen > 0) { 342a44e4d14SBill Paul bcopy(olinep, linep, olen); 343a44e4d14SBill Paul free(olinep); 344a44e4d14SBill Paul } 345a44e4d14SBill Paul bcopy(pos, linep + olen, len); 346a44e4d14SBill Paul olen += len; 347a44e4d14SBill Paul *(linep + olen) = '\0'; 348a44e4d14SBill Paul olinep = linep; 349a44e4d14SBill Paul } 350a44e4d14SBill Paul #ifdef CANT_HAPPEN 351a44e4d14SBill Paul if (cont) { 352a44e4d14SBill Paul if (fgets(line, LINSIZ, netf)) { 353a44e4d14SBill Paul pos = line; 354a44e4d14SBill Paul len = strlen(pos); 355a44e4d14SBill Paul } else 356a44e4d14SBill Paul cont = 0; 357a44e4d14SBill Paul } 358a44e4d14SBill Paul #endif 359a44e4d14SBill Paul } while (cont); 360a44e4d14SBill Paul lp->l_line = linep; 361a44e4d14SBill Paul lp->l_next = linehead; 362a44e4d14SBill Paul linehead = lp; 363a44e4d14SBill Paul #ifdef CANT_HAPPEN 364a44e4d14SBill Paul /* 365a44e4d14SBill Paul * If this is the one we wanted, we are done. 366a44e4d14SBill Paul */ 367a44e4d14SBill Paul if (!strcmp(lp->l_groupname, group)) 368a44e4d14SBill Paul #endif 369a44e4d14SBill Paul return (lp); 370a44e4d14SBill Paul } 371a44e4d14SBill Paul return ((struct linelist *)0); 372a44e4d14SBill Paul } 373