1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1996-1999 by Internet Software Consortium. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 10*0Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 11*0Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14*0Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16*0Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17*0Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18*0Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19*0Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*0Sstevel@tonic-gate * SOFTWARE. 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER) 26*0Sstevel@tonic-gate static const char rcsid[] = "$Id: lcl_ng.c,v 1.17 2001/05/29 05:49:05 marka Exp $"; 27*0Sstevel@tonic-gate #endif 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* Imports */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include "port_before.h" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <netinet/in.h> 35*0Sstevel@tonic-gate #include <arpa/nameser.h> 36*0Sstevel@tonic-gate #include <resolv.h> 37*0Sstevel@tonic-gate #include <errno.h> 38*0Sstevel@tonic-gate #include <stdio.h> 39*0Sstevel@tonic-gate #include <stdlib.h> 40*0Sstevel@tonic-gate #include <string.h> 41*0Sstevel@tonic-gate #include <unistd.h> 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include <irs.h> 44*0Sstevel@tonic-gate #include <isc/memcluster.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include "port_after.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include "irs_p.h" 49*0Sstevel@tonic-gate #include "lcl_p.h" 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate /* Definitions */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #define NG_HOST 0 /* Host name */ 54*0Sstevel@tonic-gate #define NG_USER 1 /* User name */ 55*0Sstevel@tonic-gate #define NG_DOM 2 /* and Domain name */ 56*0Sstevel@tonic-gate #define LINSIZ 1024 /* Length of netgroup file line */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * XXX Warning XXX 60*0Sstevel@tonic-gate * This code is a hack-and-slash special. It realy needs to be 61*0Sstevel@tonic-gate * rewritten with things like strdup, and realloc in mind. 62*0Sstevel@tonic-gate * More reasonable data structures would not be a bad thing. 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* 66*0Sstevel@tonic-gate * Static Variables and functions used by setnetgrent(), getnetgrent() and 67*0Sstevel@tonic-gate * endnetgrent(). 68*0Sstevel@tonic-gate * There are two linked lists: 69*0Sstevel@tonic-gate * - linelist is just used by setnetgrent() to parse the net group file via. 70*0Sstevel@tonic-gate * parse_netgrp() 71*0Sstevel@tonic-gate * - netgrp is the list of entries for the current netgroup 72*0Sstevel@tonic-gate */ 73*0Sstevel@tonic-gate struct linelist { 74*0Sstevel@tonic-gate struct linelist *l_next; /* Chain ptr. */ 75*0Sstevel@tonic-gate int l_parsed; /* Flag for cycles */ 76*0Sstevel@tonic-gate char * l_groupname; /* Name of netgroup */ 77*0Sstevel@tonic-gate char * l_line; /* Netgroup entrie(s) to be parsed */ 78*0Sstevel@tonic-gate }; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate struct ng_old_struct { 81*0Sstevel@tonic-gate struct ng_old_struct *ng_next; /* Chain ptr */ 82*0Sstevel@tonic-gate char * ng_str[3]; /* Field pointers, see below */ 83*0Sstevel@tonic-gate }; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate struct pvt { 86*0Sstevel@tonic-gate FILE *fp; 87*0Sstevel@tonic-gate struct linelist *linehead; 88*0Sstevel@tonic-gate struct ng_old_struct *nextgrp; 89*0Sstevel@tonic-gate struct { 90*0Sstevel@tonic-gate struct ng_old_struct *gr; 91*0Sstevel@tonic-gate char *grname; 92*0Sstevel@tonic-gate } grouphead; 93*0Sstevel@tonic-gate }; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* Forward */ 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate static void ng_rewind(struct irs_ng *, const char*); 98*0Sstevel@tonic-gate static void ng_close(struct irs_ng *); 99*0Sstevel@tonic-gate static int ng_next(struct irs_ng *, const char **, 100*0Sstevel@tonic-gate const char **, const char **); 101*0Sstevel@tonic-gate static int ng_test(struct irs_ng *, const char *, 102*0Sstevel@tonic-gate const char *, const char *, 103*0Sstevel@tonic-gate const char *); 104*0Sstevel@tonic-gate static void ng_minimize(struct irs_ng *); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate static int parse_netgrp(struct irs_ng *, const char*); 107*0Sstevel@tonic-gate static struct linelist *read_for_group(struct irs_ng *, const char *); 108*0Sstevel@tonic-gate static void freelists(struct irs_ng *); 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* Public */ 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate struct irs_ng * 113*0Sstevel@tonic-gate irs_lcl_ng(struct irs_acc *this) { 114*0Sstevel@tonic-gate struct irs_ng *ng; 115*0Sstevel@tonic-gate struct pvt *pvt; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate UNUSED(this); 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate if (!(ng = memget(sizeof *ng))) { 120*0Sstevel@tonic-gate errno = ENOMEM; 121*0Sstevel@tonic-gate return (NULL); 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate memset(ng, 0x5e, sizeof *ng); 124*0Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 125*0Sstevel@tonic-gate memput(ng, sizeof *ng); 126*0Sstevel@tonic-gate errno = ENOMEM; 127*0Sstevel@tonic-gate return (NULL); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 130*0Sstevel@tonic-gate ng->private = pvt; 131*0Sstevel@tonic-gate ng->close = ng_close; 132*0Sstevel@tonic-gate ng->next = ng_next; 133*0Sstevel@tonic-gate ng->test = ng_test; 134*0Sstevel@tonic-gate ng->rewind = ng_rewind; 135*0Sstevel@tonic-gate ng->minimize = ng_minimize; 136*0Sstevel@tonic-gate return (ng); 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate /* Methods */ 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate static void 142*0Sstevel@tonic-gate ng_close(struct irs_ng *this) { 143*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if (pvt->fp != NULL) 146*0Sstevel@tonic-gate fclose(pvt->fp); 147*0Sstevel@tonic-gate freelists(this); 148*0Sstevel@tonic-gate memput(pvt, sizeof *pvt); 149*0Sstevel@tonic-gate memput(this, sizeof *this); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate /* 153*0Sstevel@tonic-gate * Parse the netgroup file looking for the netgroup and build the list 154*0Sstevel@tonic-gate * of netgrp structures. Let parse_netgrp() and read_for_group() do 155*0Sstevel@tonic-gate * most of the work. 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate static void 158*0Sstevel@tonic-gate ng_rewind(struct irs_ng *this, const char *group) { 159*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { 162*0Sstevel@tonic-gate fclose(pvt->fp); 163*0Sstevel@tonic-gate pvt->fp = NULL; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate if (pvt->fp == NULL || pvt->grouphead.gr == NULL || 167*0Sstevel@tonic-gate strcmp(group, pvt->grouphead.grname)) { 168*0Sstevel@tonic-gate freelists(this); 169*0Sstevel@tonic-gate if (pvt->fp != NULL) 170*0Sstevel@tonic-gate fclose(pvt->fp); 171*0Sstevel@tonic-gate pvt->fp = fopen(_PATH_NETGROUP, "r"); 172*0Sstevel@tonic-gate if (pvt->fp != NULL) { 173*0Sstevel@tonic-gate if (parse_netgrp(this, group)) 174*0Sstevel@tonic-gate freelists(this); 175*0Sstevel@tonic-gate if (!(pvt->grouphead.grname = strdup(group))) 176*0Sstevel@tonic-gate freelists(this); 177*0Sstevel@tonic-gate fclose(pvt->fp); 178*0Sstevel@tonic-gate pvt->fp = NULL; 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate pvt->nextgrp = pvt->grouphead.gr; 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* 185*0Sstevel@tonic-gate * Get the next netgroup off the list. 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate static int 188*0Sstevel@tonic-gate ng_next(struct irs_ng *this, const char **host, const char **user, 189*0Sstevel@tonic-gate const char **domain) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (pvt->nextgrp) { 194*0Sstevel@tonic-gate *host = pvt->nextgrp->ng_str[NG_HOST]; 195*0Sstevel@tonic-gate *user = pvt->nextgrp->ng_str[NG_USER]; 196*0Sstevel@tonic-gate *domain = pvt->nextgrp->ng_str[NG_DOM]; 197*0Sstevel@tonic-gate pvt->nextgrp = pvt->nextgrp->ng_next; 198*0Sstevel@tonic-gate return (1); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate return (0); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate /* 204*0Sstevel@tonic-gate * Search for a match in a netgroup. 205*0Sstevel@tonic-gate */ 206*0Sstevel@tonic-gate static int 207*0Sstevel@tonic-gate ng_test(struct irs_ng *this, const char *name, 208*0Sstevel@tonic-gate const char *host, const char *user, const char *domain) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate const char *ng_host, *ng_user, *ng_domain; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate ng_rewind(this, name); 213*0Sstevel@tonic-gate while (ng_next(this, &ng_host, &ng_user, &ng_domain)) 214*0Sstevel@tonic-gate if ((host == NULL || ng_host == NULL || 215*0Sstevel@tonic-gate !strcmp(host, ng_host)) && 216*0Sstevel@tonic-gate (user == NULL || ng_user == NULL || 217*0Sstevel@tonic-gate !strcmp(user, ng_user)) && 218*0Sstevel@tonic-gate (domain == NULL || ng_domain == NULL || 219*0Sstevel@tonic-gate !strcmp(domain, ng_domain))) { 220*0Sstevel@tonic-gate freelists(this); 221*0Sstevel@tonic-gate return (1); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate freelists(this); 224*0Sstevel@tonic-gate return (0); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate static void 228*0Sstevel@tonic-gate ng_minimize(struct irs_ng *this) { 229*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (pvt->fp != NULL) { 232*0Sstevel@tonic-gate (void)fclose(pvt->fp); 233*0Sstevel@tonic-gate pvt->fp = NULL; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* Private */ 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * endnetgrent() - cleanup 241*0Sstevel@tonic-gate */ 242*0Sstevel@tonic-gate static void 243*0Sstevel@tonic-gate freelists(struct irs_ng *this) { 244*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 245*0Sstevel@tonic-gate struct linelist *lp, *olp; 246*0Sstevel@tonic-gate struct ng_old_struct *gp, *ogp; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate lp = pvt->linehead; 249*0Sstevel@tonic-gate while (lp) { 250*0Sstevel@tonic-gate olp = lp; 251*0Sstevel@tonic-gate lp = lp->l_next; 252*0Sstevel@tonic-gate free(olp->l_groupname); 253*0Sstevel@tonic-gate free(olp->l_line); 254*0Sstevel@tonic-gate free((char *)olp); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate pvt->linehead = NULL; 257*0Sstevel@tonic-gate if (pvt->grouphead.grname) { 258*0Sstevel@tonic-gate free(pvt->grouphead.grname); 259*0Sstevel@tonic-gate pvt->grouphead.grname = NULL; 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate gp = pvt->grouphead.gr; 262*0Sstevel@tonic-gate while (gp) { 263*0Sstevel@tonic-gate ogp = gp; 264*0Sstevel@tonic-gate gp = gp->ng_next; 265*0Sstevel@tonic-gate if (ogp->ng_str[NG_HOST]) 266*0Sstevel@tonic-gate free(ogp->ng_str[NG_HOST]); 267*0Sstevel@tonic-gate if (ogp->ng_str[NG_USER]) 268*0Sstevel@tonic-gate free(ogp->ng_str[NG_USER]); 269*0Sstevel@tonic-gate if (ogp->ng_str[NG_DOM]) 270*0Sstevel@tonic-gate free(ogp->ng_str[NG_DOM]); 271*0Sstevel@tonic-gate free((char *)ogp); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate pvt->grouphead.gr = NULL; 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate /* 277*0Sstevel@tonic-gate * Parse the netgroup file setting up the linked lists. 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate static int 280*0Sstevel@tonic-gate parse_netgrp(struct irs_ng *this, const char *group) { 281*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 282*0Sstevel@tonic-gate char *spos, *epos; 283*0Sstevel@tonic-gate int len, strpos; 284*0Sstevel@tonic-gate char *pos, *gpos; 285*0Sstevel@tonic-gate struct ng_old_struct *grp; 286*0Sstevel@tonic-gate struct linelist *lp = pvt->linehead; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* 289*0Sstevel@tonic-gate * First, see if the line has already been read in. 290*0Sstevel@tonic-gate */ 291*0Sstevel@tonic-gate while (lp) { 292*0Sstevel@tonic-gate if (!strcmp(group, lp->l_groupname)) 293*0Sstevel@tonic-gate break; 294*0Sstevel@tonic-gate lp = lp->l_next; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate if (lp == NULL && 297*0Sstevel@tonic-gate (lp = read_for_group(this, group)) == NULL) 298*0Sstevel@tonic-gate return (1); 299*0Sstevel@tonic-gate if (lp->l_parsed) { 300*0Sstevel@tonic-gate /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ 301*0Sstevel@tonic-gate return (1); 302*0Sstevel@tonic-gate } else 303*0Sstevel@tonic-gate lp->l_parsed = 1; 304*0Sstevel@tonic-gate pos = lp->l_line; 305*0Sstevel@tonic-gate while (*pos != '\0') { 306*0Sstevel@tonic-gate if (*pos == '(') { 307*0Sstevel@tonic-gate if (!(grp = malloc(sizeof (struct ng_old_struct)))) { 308*0Sstevel@tonic-gate freelists(this); 309*0Sstevel@tonic-gate errno = ENOMEM; 310*0Sstevel@tonic-gate return (1); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate memset(grp, 0, sizeof (struct ng_old_struct)); 313*0Sstevel@tonic-gate grp->ng_next = pvt->grouphead.gr; 314*0Sstevel@tonic-gate pvt->grouphead.gr = grp; 315*0Sstevel@tonic-gate pos++; 316*0Sstevel@tonic-gate gpos = strsep(&pos, ")"); 317*0Sstevel@tonic-gate for (strpos = 0; strpos < 3; strpos++) { 318*0Sstevel@tonic-gate if ((spos = strsep(&gpos, ","))) { 319*0Sstevel@tonic-gate while (*spos == ' ' || *spos == '\t') 320*0Sstevel@tonic-gate spos++; 321*0Sstevel@tonic-gate if ((epos = strpbrk(spos, " \t"))) { 322*0Sstevel@tonic-gate *epos = '\0'; 323*0Sstevel@tonic-gate len = epos - spos; 324*0Sstevel@tonic-gate } else 325*0Sstevel@tonic-gate len = strlen(spos); 326*0Sstevel@tonic-gate if (len > 0) { 327*0Sstevel@tonic-gate if(!(grp->ng_str[strpos] 328*0Sstevel@tonic-gate = (char *) 329*0Sstevel@tonic-gate malloc(len + 1))) { 330*0Sstevel@tonic-gate freelists(this); 331*0Sstevel@tonic-gate return (1); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate memcpy(grp->ng_str[strpos], 334*0Sstevel@tonic-gate spos, 335*0Sstevel@tonic-gate len + 1); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate } else 338*0Sstevel@tonic-gate goto errout; 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate } else { 341*0Sstevel@tonic-gate spos = strsep(&pos, ", \t"); 342*0Sstevel@tonic-gate if (spos != NULL && parse_netgrp(this, spos)) { 343*0Sstevel@tonic-gate freelists(this); 344*0Sstevel@tonic-gate return (1); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate if (pos == NULL) 348*0Sstevel@tonic-gate break; 349*0Sstevel@tonic-gate while (*pos == ' ' || *pos == ',' || *pos == '\t') 350*0Sstevel@tonic-gate pos++; 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate return (0); 353*0Sstevel@tonic-gate errout: 354*0Sstevel@tonic-gate /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 355*0Sstevel@tonic-gate spos);*/ 356*0Sstevel@tonic-gate return (1); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate /* 360*0Sstevel@tonic-gate * Read the netgroup file and save lines until the line for the netgroup 361*0Sstevel@tonic-gate * is found. Return 1 if eof is encountered. 362*0Sstevel@tonic-gate */ 363*0Sstevel@tonic-gate static struct linelist * 364*0Sstevel@tonic-gate read_for_group(struct irs_ng *this, const char *group) { 365*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 366*0Sstevel@tonic-gate char *pos, *spos, *linep = NULL, *olinep; 367*0Sstevel@tonic-gate int len, olen, cont; 368*0Sstevel@tonic-gate struct linelist *lp; 369*0Sstevel@tonic-gate char line[LINSIZ + 1]; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate while (fgets(line, LINSIZ, pvt->fp) != NULL) { 372*0Sstevel@tonic-gate pos = line; 373*0Sstevel@tonic-gate if (*pos == '#') 374*0Sstevel@tonic-gate continue; 375*0Sstevel@tonic-gate while (*pos == ' ' || *pos == '\t') 376*0Sstevel@tonic-gate pos++; 377*0Sstevel@tonic-gate spos = pos; 378*0Sstevel@tonic-gate while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 379*0Sstevel@tonic-gate *pos != '\0') 380*0Sstevel@tonic-gate pos++; 381*0Sstevel@tonic-gate len = pos - spos; 382*0Sstevel@tonic-gate while (*pos == ' ' || *pos == '\t') 383*0Sstevel@tonic-gate pos++; 384*0Sstevel@tonic-gate if (*pos != '\n' && *pos != '\0') { 385*0Sstevel@tonic-gate if (!(lp = malloc(sizeof (*lp)))) { 386*0Sstevel@tonic-gate freelists(this); 387*0Sstevel@tonic-gate return (NULL); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate lp->l_parsed = 0; 390*0Sstevel@tonic-gate if (!(lp->l_groupname = malloc(len + 1))) { 391*0Sstevel@tonic-gate free(lp); 392*0Sstevel@tonic-gate freelists(this); 393*0Sstevel@tonic-gate return (NULL); 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate memcpy(lp->l_groupname, spos, len); 396*0Sstevel@tonic-gate *(lp->l_groupname + len) = '\0'; 397*0Sstevel@tonic-gate len = strlen(pos); 398*0Sstevel@tonic-gate olen = 0; 399*0Sstevel@tonic-gate olinep = NULL; 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate /* 402*0Sstevel@tonic-gate * Loop around handling line continuations. 403*0Sstevel@tonic-gate */ 404*0Sstevel@tonic-gate do { 405*0Sstevel@tonic-gate if (*(pos + len - 1) == '\n') 406*0Sstevel@tonic-gate len--; 407*0Sstevel@tonic-gate if (*(pos + len - 1) == '\\') { 408*0Sstevel@tonic-gate len--; 409*0Sstevel@tonic-gate cont = 1; 410*0Sstevel@tonic-gate } else 411*0Sstevel@tonic-gate cont = 0; 412*0Sstevel@tonic-gate if (len > 0) { 413*0Sstevel@tonic-gate if (!(linep = malloc(olen + len + 1))){ 414*0Sstevel@tonic-gate if (olen > 0) 415*0Sstevel@tonic-gate free(olinep); 416*0Sstevel@tonic-gate free(lp->l_groupname); 417*0Sstevel@tonic-gate free(lp); 418*0Sstevel@tonic-gate freelists(this); 419*0Sstevel@tonic-gate errno = ENOMEM; 420*0Sstevel@tonic-gate return (NULL); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate if (olen > 0) { 423*0Sstevel@tonic-gate memcpy(linep, olinep, olen); 424*0Sstevel@tonic-gate free(olinep); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate memcpy(linep + olen, pos, len); 427*0Sstevel@tonic-gate olen += len; 428*0Sstevel@tonic-gate *(linep + olen) = '\0'; 429*0Sstevel@tonic-gate olinep = linep; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate if (cont) { 432*0Sstevel@tonic-gate if (fgets(line, LINSIZ, pvt->fp)) { 433*0Sstevel@tonic-gate pos = line; 434*0Sstevel@tonic-gate len = strlen(pos); 435*0Sstevel@tonic-gate } else 436*0Sstevel@tonic-gate cont = 0; 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate } while (cont); 439*0Sstevel@tonic-gate lp->l_line = linep; 440*0Sstevel@tonic-gate lp->l_next = pvt->linehead; 441*0Sstevel@tonic-gate pvt->linehead = lp; 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate /* 444*0Sstevel@tonic-gate * If this is the one we wanted, we are done. 445*0Sstevel@tonic-gate */ 446*0Sstevel@tonic-gate if (!strcmp(lp->l_groupname, group)) 447*0Sstevel@tonic-gate return (lp); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate return (NULL); 451*0Sstevel@tonic-gate } 452