11556Srgrimes/* 21556Srgrimes * Copyright (c) 1992, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Rick Macklem at The University of Guelph. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 3436150Scharnierstatic char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95"; 3536150Scharnier#endif /* LIBC_SCCS and not lint */ 3636150Scharnier#include <sys/cdefs.h> 371556Srgrimes__FBSDID("$FreeBSD$"); 3899110Sobrien 3999110Sobrien#include <ctype.h> 401556Srgrimes#include <stdio.h> 41109627Stjr#include <stdlib.h> 421556Srgrimes#include <string.h> 43109627Stjr#include <unistd.h> 4417987Speter 4559437Scracauer#ifdef YP 4617987Speter/* 471556Srgrimes * Notes: 481556Srgrimes * We want to be able to use NIS netgroups properly while retaining 491556Srgrimes * the ability to use a local /etc/netgroup file. Unfortunately, you 501556Srgrimes * can't really do both at the same time - at least, not efficiently. 5117987Speter * NetBSD deals with this problem by creating a netgroup database 521556Srgrimes * using Berkeley DB (just like the password database) that allows 531556Srgrimes * for lookups using netgroup, netgroup.byuser or netgroup.byhost 541556Srgrimes * searches. This is a neat idea, but I don't have time to implement 55213811Sobrien * something like that now. (I think ultimately it would be nice 56213811Sobrien * if we DB-fied the group and netgroup stuff all in one shot, but 57213811Sobrien * for now I'm satisfied just to have something that works well 58213811Sobrien * without requiring massive code changes.) 59213811Sobrien * 601556Srgrimes * Therefore, to still permit the use of the local file and maintain 611556Srgrimes * optimum NIS performance, we allow for the following conditions: 6217987Speter * 6390111Simp * - If /etc/netgroup does not exist and NIS is turned on, we use 6417987Speter * NIS netgroups only. 651556Srgrimes * 661556Srgrimes * - If /etc/netgroup exists but is empty, we use NIS netgroups 671556Srgrimes * only. 681556Srgrimes * 691556Srgrimes * - If /etc/netgroup exists and contains _only_ a '+', we use 70213811Sobrien * NIS netgroups only. 7190111Simp * 7217987Speter * - If /etc/netgroup exists, contains locally defined netgroups 731556Srgrimes * and a '+', we use a mixture of NIS and the local entries. 741556Srgrimes * This method should return the same NIS data as just using 751556Srgrimes * NIS alone, but it will be slower if the NIS netgroup database 7617987Speter * is large (innetgr() in particular will suffer since extra 7717987Speter * processing has to be done in order to determine memberships 7817987Speter * using just the raw netgroup data). 791556Srgrimes * 801556Srgrimes * - If /etc/netgroup exists and contains only locally defined 811556Srgrimes * netgroup entries, we use just those local entries and ignore 821556Srgrimes * NIS (this is the original, pre-NIS behavior). 831556Srgrimes */ 841556Srgrimes 851556Srgrimes#include <rpc/rpc.h> 861556Srgrimes#include <rpcsvc/yp_prot.h> 871556Srgrimes#include <rpcsvc/ypclnt.h> 881556Srgrimes#include <sys/types.h> 891556Srgrimes#include <sys/stat.h> 901556Srgrimes#include <sys/param.h> 911556Srgrimes#include <sys/errno.h> 921556Srgrimesstatic char *_netgr_yp_domain; 931556Srgrimesint _use_only_yp; 941556Srgrimesstatic int _netgr_yp_enabled; 951556Srgrimesstatic int _yp_innetgr; 961556Srgrimes#endif 971556Srgrimes 981556Srgrimes#ifndef _PATH_NETGROUP 991556Srgrimes#define _PATH_NETGROUP "/etc/netgroup" 1001556Srgrimes#endif 1011556Srgrimes 1021556Srgrimes/* 1031556Srgrimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 1041556Srgrimes * endnetgrent(). 1051556Srgrimes * There are two linked lists: 1061556Srgrimes * - linelist is just used by setnetgrent() to parse the net group file via. 1071556Srgrimes * parse_netgrp() 1081556Srgrimes * - netgrp is the list of entries for the current netgroup 1091556Srgrimes */ 1101556Srgrimesstruct linelist { 1111556Srgrimes struct linelist *l_next; /* Chain ptr. */ 1121556Srgrimes int l_parsed; /* Flag for cycles */ 1131556Srgrimes char *l_groupname; /* Name of netgroup */ 1141556Srgrimes char *l_line; /* Netgroup entrie(s) to be parsed */ 1151556Srgrimes}; 1161556Srgrimes 1171556Srgrimesstruct netgrp { 1181556Srgrimes struct netgrp *ng_next; /* Chain ptr */ 1191556Srgrimes char *ng_str[3]; /* Field pointers, see below */ 1201556Srgrimes}; 121213811Sobrien#define NG_HOST 0 /* Host name */ 12290111Simp#define NG_USER 1 /* User name */ 12317987Speter#define NG_DOM 2 /* and Domain name */ 1241556Srgrimes 1251556Srgrimesstatic struct linelist *linehead = (struct linelist *)0; 1261556Srgrimesstatic struct netgrp *nextgrp = (struct netgrp *)0; 1271556Srgrimesstatic struct { 1281556Srgrimes struct netgrp *gr; 1291556Srgrimes char *grname; 1301556Srgrimes} grouphead = { 1311556Srgrimes (struct netgrp *)0, 1321556Srgrimes (char *)0, 1331556Srgrimes}; 1341556Srgrimesstatic FILE *netf = (FILE *)0; 1351556Srgrimes 1361556Srgrimesstatic int parse_netgrp(const char *); 1371556Srgrimesstatic struct linelist *read_for_group(const char *); 1381556Srgrimesvoid setnetgrent(const char *); 1391556Srgrimesvoid endnetgrent(void); 1401556Srgrimesint getnetgrent(char **, char **, char **); 1411556Srgrimesint innetgr(const char *, const char *, const char *, const char *); 1421556Srgrimes 14396922Stjr#define LINSIZ 1024 /* Length of netgroup file line */ 1441556Srgrimes 14566612Sbrian/* 1461556Srgrimes * setnetgrent() 147157750Sschweikh * Parse the netgroup file looking for the netgroup and build the list 148157750Sschweikh * of netgrp structures. Let parse_netgrp() and read_for_group() do 14917987Speter * most of the work. 1501556Srgrimes */ 1511556Srgrimesvoid 1521556Srgrimessetnetgrent(const char *group) 1531556Srgrimes{ 1541556Srgrimes#ifdef YP 15599634Stjr struct stat _yp_statp; 15699634Stjr char _yp_plus; 15799634Stjr#endif 15899634Stjr 159157750Sschweikh /* Sanity check */ 160157750Sschweikh 161157750Sschweikh if (group == NULL || !strlen(group)) 162157750Sschweikh return; 1631556Srgrimes 1641556Srgrimes if (grouphead.gr == NULL || strcmp(group, grouphead.grname)) { 1651556Srgrimes endnetgrent(); 1661556Srgrimes#ifdef YP 1671556Srgrimes /* Presumed guilty until proven innocent. */ 1681556Srgrimes _use_only_yp = 0; 1691556Srgrimes /* 1701556Srgrimes * If /etc/netgroup doesn't exist or is empty, 1711556Srgrimes * use NIS exclusively. 172213811Sobrien */ 17390111Simp if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 17490111Simp errno == ENOENT) || _yp_statp.st_size == 0) 1751556Srgrimes _use_only_yp = _netgr_yp_enabled = 1; 1761556Srgrimes if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){ 1771556Srgrimes /* 1781556Srgrimes * Icky: grab the first character of the netgroup file 1791556Srgrimes * and turn on NIS if it's a '+'. rewind the stream 1801556Srgrimes * afterwards so we don't goof up read_for_group() later. 1811556Srgrimes */ 1821556Srgrimes if (netf) { 1831556Srgrimes fscanf(netf, "%c", &_yp_plus); 1841556Srgrimes rewind(netf); 1851556Srgrimes if (_yp_plus == '+') 1861556Srgrimes _use_only_yp = _netgr_yp_enabled = 1; 1871556Srgrimes } 1881556Srgrimes /* 1891556Srgrimes * If we were called specifically for an innetgr() 1901556Srgrimes * lookup and we're in NIS-only mode, short-circuit 1911556Srgrimes * parse_netgroup() and cut directly to the chase. 1921556Srgrimes */ 1931556Srgrimes if (_use_only_yp && _yp_innetgr) { 19417987Speter /* dohw! */ 19517987Speter if (netf != NULL) 19617987Speter fclose(netf); 1971556Srgrimes return; 1981556Srgrimes } 19917987Speter#else 2001556Srgrimes if ((netf = fopen(_PATH_NETGROUP, "re"))) { 2011556Srgrimes#endif 20217987Speter if (parse_netgrp(group)) 2031556Srgrimes endnetgrent(); 2041556Srgrimes else { 2051556Srgrimes grouphead.grname = strdup(group); 2061556Srgrimes } 2071556Srgrimes if (netf) 2081556Srgrimes fclose(netf); 2091556Srgrimes } 2101556Srgrimes } 2111556Srgrimes nextgrp = grouphead.gr; 2121556Srgrimes} 2131556Srgrimes 2141556Srgrimes/* 2151556Srgrimes * Get the next netgroup off the list. 2161556Srgrimes */ 2171556Srgrimesint 2181556Srgrimesgetnetgrent(char **hostp, char **userp, char **domp) 21917987Speter{ 22017987Speter#ifdef YP 22117987Speter _yp_innetgr = 0; 22217987Speter#endif 22317987Speter 22417987Speter if (nextgrp) { 22517987Speter *hostp = nextgrp->ng_str[NG_HOST]; 22617987Speter *userp = nextgrp->ng_str[NG_USER]; 22717987Speter *domp = nextgrp->ng_str[NG_DOM]; 22817987Speter nextgrp = nextgrp->ng_next; 22917987Speter return (1); 23017987Speter } 23117987Speter return (0); 23217987Speter} 23317987Speter 23417987Speter/* 2351556Srgrimes * endnetgrent() - cleanup 2361556Srgrimes */ 2371556Srgrimesvoid 2381556Srgrimesendnetgrent(void) 2391556Srgrimes{ 2401556Srgrimes struct linelist *lp, *olp; 2411556Srgrimes struct netgrp *gp, *ogp; 2421556Srgrimes 2431556Srgrimes lp = linehead; 2441556Srgrimes while (lp) { 2451556Srgrimes olp = lp; 2461556Srgrimes lp = lp->l_next; 2471556Srgrimes free(olp->l_groupname); 2481556Srgrimes free(olp->l_line); 2491556Srgrimes free(olp); 2501556Srgrimes } 2511556Srgrimes linehead = NULL; 2521556Srgrimes if (grouphead.grname) { 2531556Srgrimes free(grouphead.grname); 2541556Srgrimes grouphead.grname = NULL; 2551556Srgrimes } 2561556Srgrimes gp = grouphead.gr; 257213811Sobrien while (gp) { 25890111Simp ogp = gp; 25917987Speter gp = gp->ng_next; 2601556Srgrimes free(ogp->ng_str[NG_HOST]); 2611556Srgrimes free(ogp->ng_str[NG_USER]); 2621556Srgrimes free(ogp->ng_str[NG_DOM]); 2631556Srgrimes free(ogp); 2641556Srgrimes } 2651556Srgrimes grouphead.gr = NULL; 2661556Srgrimes nextgrp = NULL; 2671556Srgrimes#ifdef YP 2681556Srgrimes _netgr_yp_enabled = 0; 2691556Srgrimes#endif 2701556Srgrimes} 2711556Srgrimes 2721556Srgrimes#ifdef YP 2731556Srgrimesstatic int 2741556Srgrimes_listmatch(const char *list, const char *group, int len) 2751556Srgrimes{ 2761556Srgrimes const char *ptr = list; 277213744Sobrien const char *cptr; 2781556Srgrimes int glen = strlen(group); 2791556Srgrimes 2801556Srgrimes /* skip possible leading whitespace */ 2811556Srgrimes while (isspace((unsigned char)*ptr)) 2821556Srgrimes ptr++; 2831556Srgrimes 28417987Speter while (ptr < list + len) { 28590111Simp cptr = ptr; 28617987Speter while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr)) 2871556Srgrimes ptr++; 2881556Srgrimes if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 2891556Srgrimes return (1); 2901556Srgrimes while (*ptr == ',' || isspace((unsigned char)*ptr)) 2911556Srgrimes ptr++; 2921556Srgrimes } 2931556Srgrimes 29420425Ssteve return (0); 29517987Speter} 29659438Scracauer 29717987Speterstatic int 29817987Speter_revnetgr_lookup(char* lookupdom, char* map, const char* str, 29917987Speter const char* dom, const char* group) 30017987Speter{ 30117987Speter int y, rv, rot; 30217987Speter char key[MAXHOSTNAMELEN]; 30317987Speter char *result; 30417987Speter int resultlen; 30517987Speter 3061556Srgrimes for (rot = 0; ; rot++) { 3071556Srgrimes switch (rot) { 3081556Srgrimes case 0: 30917987Speter snprintf(key, MAXHOSTNAMELEN, "%s.%s", str, 310200956Sjilles dom ? dom : lookupdom); 31117987Speter break; 3121556Srgrimes case 1: 3131556Srgrimes snprintf(key, MAXHOSTNAMELEN, "%s.*", str); 3141556Srgrimes break; 3151556Srgrimes case 2: 3161556Srgrimes snprintf(key, MAXHOSTNAMELEN, "*.%s", 3171556Srgrimes dom ? dom : lookupdom); 3181556Srgrimes break; 3191556Srgrimes case 3: 320213811Sobrien snprintf(key, MAXHOSTNAMELEN, "*.*"); 32190111Simp break; 32217987Speter default: 32325222Ssteve return (0); 3241556Srgrimes } 3251556Srgrimes y = yp_match(lookupdom, map, key, strlen(key), &result, 3261556Srgrimes &resultlen); 3271556Srgrimes if (y == 0) { 3281556Srgrimes rv = _listmatch(result, group, resultlen); 3291556Srgrimes free(result); 3301556Srgrimes if (rv) 3311556Srgrimes return (1); 3321556Srgrimes } else if (y != YPERR_KEY) { 3331556Srgrimes /* 3341556Srgrimes * If we get an error other than 'no 3351556Srgrimes * such key in map' then something is 3361556Srgrimes * wrong and we should stop the search. 3371556Srgrimes */ 3381556Srgrimes return (-1); 3391556Srgrimes } 3401556Srgrimes } 3411556Srgrimes} 3421556Srgrimes#endif 3431556Srgrimes 3441556Srgrimes/* 3451556Srgrimes * Search for a match in a netgroup. 3461556Srgrimes */ 3471556Srgrimesint 3481556Srgrimesinnetgr(const char *group, const char *host, const char *user, const char *dom) 3491556Srgrimes{ 3501556Srgrimes char *hst, *usr, *dm; 3511556Srgrimes /* Sanity check */ 3521556Srgrimes 3531556Srgrimes if (group == NULL || !strlen(group)) 3541556Srgrimes return (0); 3551556Srgrimes 3561556Srgrimes#ifdef YP 35718018Speter _yp_innetgr = 1; 3581556Srgrimes#endif 3591556Srgrimes setnetgrent(group); 36017987Speter#ifdef YP 36190111Simp _yp_innetgr = 0; 36217987Speter /* 3631556Srgrimes * If we're in NIS-only mode, do the search using 3641556Srgrimes * NIS 'reverse netgroup' lookups. 3651556Srgrimes * 3661556Srgrimes * What happens with 'reverse netgroup' lookups: 3671556Srgrimes * 3681556Srgrimes * 1) try 'reverse netgroup' lookup 3691556Srgrimes * 1.a) if host is specified and user is null: 3701556Srgrimes * look in netgroup.byhost 3711556Srgrimes * (try host.domain, host.*, *.domain or *.*) 3721556Srgrimes * if found, return yes 3731556Srgrimes * 1.b) if user is specified and host is null: 3741556Srgrimes * look in netgroup.byuser 3751556Srgrimes * (try host.domain, host.*, *.domain or *.*) 37617987Speter * if found, return yes 37790111Simp * 1.c) if both host and user are specified, 37890111Simp * don't do 'reverse netgroup' lookup. It won't work. 3791556Srgrimes * 1.d) if neither host ane user are specified (why?!?) 3801556Srgrimes * don't do 'reverse netgroup' lookup either. 3811556Srgrimes * 2) if domain is specified and 'reverse lookup' is done: 3821556Srgrimes * 'reverse lookup' was authoritative. bye bye. 3831556Srgrimes * 3) otherwise, too bad, try it the slow way. 3841556Srgrimes */ 38517987Speter if (_use_only_yp && (host == NULL) != (user == NULL)) { 38617987Speter int ret; 38717987Speter if(yp_get_default_domain(&_netgr_yp_domain)) 38817987Speter return (0); 38917987Speter ret = _revnetgr_lookup(_netgr_yp_domain, 39017987Speter host?"netgroup.byhost":"netgroup.byuser", 39117987Speter host?host:user, dom, group); 39217987Speter if (ret == 1) 393262951Sjmmv return (1); 39417987Speter else if (ret == 0 && dom != NULL) 3951556Srgrimes return (0); 3961556Srgrimes } 397262951Sjmmv 3981556Srgrimes setnetgrent(group); 3991556Srgrimes#endif /* YP */ 40053891Scracauer 4011556Srgrimes while (getnetgrent(&hst, &usr, &dm)) 4021556Srgrimes if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 4031556Srgrimes (user == NULL || usr == NULL || !strcmp(user, usr)) && 4041556Srgrimes ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 4051556Srgrimes endnetgrent(); 4061556Srgrimes return (1); 40720425Ssteve } 4081556Srgrimes endnetgrent(); 409 return (0); 410} 411 412/* 413 * Parse the netgroup file setting up the linked lists. 414 */ 415static int 416parse_netgrp(const char *group) 417{ 418 struct netgrp *grp; 419 struct linelist *lp = linehead; 420 char **ng; 421 char *epos, *gpos, *pos, *spos; 422 int freepos, len, strpos; 423#ifdef DEBUG 424 int fields; 425#endif 426 427 /* 428 * First, see if the line has already been read in. 429 */ 430 while (lp) { 431 if (!strcmp(group, lp->l_groupname)) 432 break; 433 lp = lp->l_next; 434 } 435 if (lp == NULL && (lp = read_for_group(group)) == NULL) 436 return (1); 437 if (lp->l_parsed) { 438#ifdef DEBUG 439 /* 440 * This error message is largely superflous since the 441 * code handles the error condition sucessfully, and 442 * spewing it out from inside libc can actually hose 443 * certain programs. 444 */ 445 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 446#endif 447 return (1); 448 } else 449 lp->l_parsed = 1; 450 pos = lp->l_line; 451 /* Watch for null pointer dereferences, dammit! */ 452 while (pos != NULL && *pos != '\0') { 453 if (*pos == '(') { 454 grp = malloc(sizeof(*grp)); 455 if (grp == NULL) 456 return (1); 457 ng = grp->ng_str; 458 bzero(grp, sizeof(*grp)); 459 pos++; 460 gpos = strsep(&pos, ")"); 461#ifdef DEBUG 462 fields = 0; 463#endif 464 for (strpos = 0; strpos < 3; strpos++) { 465 if ((spos = strsep(&gpos, ",")) == NULL) { 466 /* 467 * All other systems I've tested 468 * return NULL for empty netgroup 469 * fields. It's up to user programs 470 * to handle the NULLs appropriately. 471 */ 472 ng[strpos] = NULL; 473 continue; 474 } 475#ifdef DEBUG 476 fields++; 477#endif 478 while (*spos == ' ' || *spos == '\t') 479 spos++; 480 if ((epos = strpbrk(spos, " \t"))) { 481 *epos = '\0'; 482 len = epos - spos; 483 } else 484 len = strlen(spos); 485 if (len <= 0) 486 continue; 487 ng[strpos] = malloc(len + 1); 488 if (ng[strpos] == NULL) { 489 for (freepos = 0; freepos < strpos; 490 freepos++) 491 free(ng[freepos]); 492 free(grp); 493 return (1); 494 } 495 bcopy(spos, ng[strpos], len + 1); 496 } 497 grp->ng_next = grouphead.gr; 498 grouphead.gr = grp; 499#ifdef DEBUG 500 /* 501 * Note: on other platforms, malformed netgroup 502 * entries are not normally flagged. While we 503 * can catch bad entries and report them, we should 504 * stay silent by default for compatibility's sake. 505 */ 506 if (fields < 3) { 507 fprintf(stderr, 508 "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 509 ng[NG_HOST] == NULL ? "" : ng[NG_HOST], 510 ng[NG_USER] == NULL ? "" : ",", 511 ng[NG_USER] == NULL ? "" : ng[NG_USER], 512 ng[NG_DOM] == NULL ? "" : ",", 513 ng[NG_DOM] == NULL ? "" : ng[NG_DOM], 514 lp->l_groupname); 515 } 516#endif 517 } else { 518 spos = strsep(&pos, ", \t"); 519 if (parse_netgrp(spos)) 520 continue; 521 } 522 if (pos == NULL) 523 break; 524 while (*pos == ' ' || *pos == ',' || *pos == '\t') 525 pos++; 526 } 527 return (0); 528} 529 530/* 531 * Read the netgroup file and save lines until the line for the netgroup 532 * is found. Return 1 if eof is encountered. 533 */ 534static struct linelist * 535read_for_group(const char *group) 536{ 537 char *linep, *olinep, *pos, *spos; 538 int len, olen; 539 int cont; 540 struct linelist *lp; 541 char line[LINSIZ + 2]; 542#ifdef YP 543 char *result; 544 int resultlen; 545 linep = NULL; 546 547 while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 548 if (_netgr_yp_enabled) { 549 if(!_netgr_yp_domain) 550 if(yp_get_default_domain(&_netgr_yp_domain)) 551 continue; 552 if (yp_match(_netgr_yp_domain, "netgroup", group, 553 strlen(group), &result, &resultlen)) { 554 free(result); 555 if (_use_only_yp) 556 return ((struct linelist *)0); 557 else { 558 _netgr_yp_enabled = 0; 559 continue; 560 } 561 } 562 if (strlen(result) == 0) { 563 free(result); 564 return (NULL); 565 } 566 snprintf(line, LINSIZ, "%s %s", group, result); 567 free(result); 568 } 569#else 570 linep = NULL; 571 while (fgets(line, LINSIZ, netf) != NULL) { 572#endif 573 pos = (char *)&line; 574#ifdef YP 575 if (*pos == '+') { 576 _netgr_yp_enabled = 1; 577 continue; 578 } 579#endif 580 if (*pos == '#') 581 continue; 582 while (*pos == ' ' || *pos == '\t') 583 pos++; 584 spos = pos; 585 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 586 *pos != '\0') 587 pos++; 588 len = pos - spos; 589 while (*pos == ' ' || *pos == '\t') 590 pos++; 591 if (*pos != '\n' && *pos != '\0') { 592 lp = (struct linelist *)malloc(sizeof (*lp)); 593 if (lp == NULL) 594 return (NULL); 595 lp->l_parsed = 0; 596 lp->l_groupname = (char *)malloc(len + 1); 597 if (lp->l_groupname == NULL) { 598 free(lp); 599 return (NULL); 600 } 601 bcopy(spos, lp->l_groupname, len); 602 *(lp->l_groupname + len) = '\0'; 603 len = strlen(pos); 604 olen = 0; 605 606 /* 607 * Loop around handling line continuations. 608 */ 609 do { 610 if (*(pos + len - 1) == '\n') 611 len--; 612 if (*(pos + len - 1) == '\\') { 613 len--; 614 cont = 1; 615 } else 616 cont = 0; 617 if (len > 0) { 618 linep = malloc(olen + len + 1); 619 if (linep == NULL) { 620 free(lp->l_groupname); 621 free(lp); 622 if (olen > 0) 623 free(olinep); 624 return (NULL); 625 } 626 if (olen > 0) { 627 bcopy(olinep, linep, olen); 628 free(olinep); 629 } 630 bcopy(pos, linep + olen, len); 631 olen += len; 632 *(linep + olen) = '\0'; 633 olinep = linep; 634 } 635 if (cont) { 636 if (fgets(line, LINSIZ, netf)) { 637 pos = line; 638 len = strlen(pos); 639 } else 640 cont = 0; 641 } 642 } while (cont); 643 lp->l_line = linep; 644 lp->l_next = linehead; 645 linehead = lp; 646 647 /* 648 * If this is the one we wanted, we are done. 649 */ 650 if (!strcmp(lp->l_groupname, group)) 651 return (lp); 652 } 653 } 654#ifdef YP 655 /* 656 * Yucky. The recursive nature of this whole mess might require 657 * us to make more than one pass through the netgroup file. 658 * This might be best left outside the #ifdef YP, but YP is 659 * defined by default anyway, so I'll leave it like this 660 * until I know better. 661 */ 662 rewind(netf); 663#endif 664 return (NULL); 665} 666