#if !defined(LINT) && !defined(CODECENTER)
static const char rcsid[] = "$Id: lcl_ng.c,v 1.1.1.1 2003/01/10 00:48:14 bbraun Exp $";
#endif
#include "port_before.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <irs.h>
#include <isc/memcluster.h>
#include "port_after.h"
#include "irs_p.h"
#include "lcl_p.h"
#define NG_HOST 0
#define NG_USER 1
#define NG_DOM 2
#define LINSIZ 1024
struct linelist {
struct linelist *l_next;
int l_parsed;
char * l_groupname;
char * l_line;
};
struct ng_old_struct {
struct ng_old_struct *ng_next;
char * ng_str[3];
};
struct pvt {
FILE *fp;
struct linelist *linehead;
struct ng_old_struct *nextgrp;
struct {
struct ng_old_struct *gr;
char *grname;
} grouphead;
};
static void ng_rewind(struct irs_ng *, const char*);
static void ng_close(struct irs_ng *);
static int ng_next(struct irs_ng *, const char **,
const char **, const char **);
static int ng_test(struct irs_ng *, const char *,
const char *, const char *,
const char *);
static void ng_minimize(struct irs_ng *);
static int parse_netgrp(struct irs_ng *, const char*);
static struct linelist *read_for_group(struct irs_ng *, const char *);
static void freelists(struct irs_ng *);
struct irs_ng *
irs_lcl_ng(struct irs_acc *this) {
struct irs_ng *ng;
struct pvt *pvt;
UNUSED(this);
if (!(ng = memget(sizeof *ng))) {
errno = ENOMEM;
return (NULL);
}
memset(ng, 0x5e, sizeof *ng);
if (!(pvt = memget(sizeof *pvt))) {
memput(ng, sizeof *ng);
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
ng->private = pvt;
ng->close = ng_close;
ng->next = ng_next;
ng->test = ng_test;
ng->rewind = ng_rewind;
ng->minimize = ng_minimize;
return (ng);
}
static void
ng_close(struct irs_ng *this) {
struct pvt *pvt = (struct pvt *)this->private;
if (pvt->fp != NULL)
fclose(pvt->fp);
freelists(this);
memput(pvt, sizeof *pvt);
memput(this, sizeof *this);
}
static void
ng_rewind(struct irs_ng *this, const char *group) {
struct pvt *pvt = (struct pvt *)this->private;
if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) {
fclose(pvt->fp);
pvt->fp = NULL;
}
if (pvt->fp == NULL || pvt->grouphead.gr == NULL ||
strcmp(group, pvt->grouphead.grname)) {
freelists(this);
if (pvt->fp != NULL)
fclose(pvt->fp);
pvt->fp = fopen(_PATH_NETGROUP, "r");
if (pvt->fp != NULL) {
if (parse_netgrp(this, group))
freelists(this);
if (!(pvt->grouphead.grname = strdup(group)))
freelists(this);
fclose(pvt->fp);
pvt->fp = NULL;
}
}
pvt->nextgrp = pvt->grouphead.gr;
}
static int
ng_next(struct irs_ng *this, const char **host, const char **user,
const char **domain)
{
struct pvt *pvt = (struct pvt *)this->private;
if (pvt->nextgrp) {
*host = pvt->nextgrp->ng_str[NG_HOST];
*user = pvt->nextgrp->ng_str[NG_USER];
*domain = pvt->nextgrp->ng_str[NG_DOM];
pvt->nextgrp = pvt->nextgrp->ng_next;
return (1);
}
return (0);
}
static int
ng_test(struct irs_ng *this, const char *name,
const char *host, const char *user, const char *domain)
{
const char *ng_host, *ng_user, *ng_domain;
ng_rewind(this, name);
while (ng_next(this, &ng_host, &ng_user, &ng_domain))
if ((host == NULL || ng_host == NULL ||
!strcmp(host, ng_host)) &&
(user == NULL || ng_user == NULL ||
!strcmp(user, ng_user)) &&
(domain == NULL || ng_domain == NULL ||
!strcmp(domain, ng_domain))) {
freelists(this);
return (1);
}
freelists(this);
return (0);
}
static void
ng_minimize(struct irs_ng *this) {
struct pvt *pvt = (struct pvt *)this->private;
if (pvt->fp != NULL) {
(void)fclose(pvt->fp);
pvt->fp = NULL;
}
}
static void
freelists(struct irs_ng *this) {
struct pvt *pvt = (struct pvt *)this->private;
struct linelist *lp, *olp;
struct ng_old_struct *gp, *ogp;
lp = pvt->linehead;
while (lp) {
olp = lp;
lp = lp->l_next;
free(olp->l_groupname);
free(olp->l_line);
free((char *)olp);
}
pvt->linehead = NULL;
if (pvt->grouphead.grname) {
free(pvt->grouphead.grname);
pvt->grouphead.grname = NULL;
}
gp = pvt->grouphead.gr;
while (gp) {
ogp = gp;
gp = gp->ng_next;
if (ogp->ng_str[NG_HOST])
free(ogp->ng_str[NG_HOST]);
if (ogp->ng_str[NG_USER])
free(ogp->ng_str[NG_USER]);
if (ogp->ng_str[NG_DOM])
free(ogp->ng_str[NG_DOM]);
free((char *)ogp);
}
pvt->grouphead.gr = NULL;
}
static int
parse_netgrp(struct irs_ng *this, const char *group) {
struct pvt *pvt = (struct pvt *)this->private;
char *spos, *epos;
int len, strpos;
char *pos, *gpos;
struct ng_old_struct *grp;
struct linelist *lp = pvt->linehead;
while (lp) {
if (!strcmp(group, lp->l_groupname))
break;
lp = lp->l_next;
}
if (lp == NULL &&
(lp = read_for_group(this, group)) == NULL)
return (1);
if (lp->l_parsed) {
return (1);
} else
lp->l_parsed = 1;
pos = lp->l_line;
while (*pos != '\0') {
if (*pos == '(') {
if (!(grp = malloc(sizeof (struct ng_old_struct)))) {
freelists(this);
errno = ENOMEM;
return (1);
}
memset(grp, 0, sizeof (struct ng_old_struct));
grp->ng_next = pvt->grouphead.gr;
pvt->grouphead.gr = grp;
pos++;
gpos = strsep(&pos, ")");
for (strpos = 0; strpos < 3; strpos++) {
if ((spos = strsep(&gpos, ","))) {
while (*spos == ' ' || *spos == '\t')
spos++;
if ((epos = strpbrk(spos, " \t"))) {
*epos = '\0';
len = epos - spos;
} else
len = strlen(spos);
if (len > 0) {
if(!(grp->ng_str[strpos]
= (char *)
malloc(len + 1))) {
freelists(this);
return (1);
}
memcpy(grp->ng_str[strpos],
spos,
len + 1);
}
} else
goto errout;
}
} else {
spos = strsep(&pos, ", \t");
if (spos != NULL && parse_netgrp(this, spos)) {
freelists(this);
return (1);
}
}
if (pos == NULL)
break;
while (*pos == ' ' || *pos == ',' || *pos == '\t')
pos++;
}
return (0);
errout:
return (1);
}
static struct linelist *
read_for_group(struct irs_ng *this, const char *group) {
struct pvt *pvt = (struct pvt *)this->private;
char *pos, *spos, *linep = NULL, *olinep;
int len, olen, cont;
struct linelist *lp;
char line[LINSIZ + 1];
while (fgets(line, LINSIZ, pvt->fp) != NULL) {
pos = line;
if (*pos == '#')
continue;
while (*pos == ' ' || *pos == '\t')
pos++;
spos = pos;
while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
*pos != '\0')
pos++;
len = pos - spos;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos != '\n' && *pos != '\0') {
if (!(lp = malloc(sizeof (*lp)))) {
freelists(this);
return (NULL);
}
lp->l_parsed = 0;
if (!(lp->l_groupname = malloc(len + 1))) {
free(lp);
freelists(this);
return (NULL);
}
memcpy(lp->l_groupname, spos, len);
*(lp->l_groupname + len) = '\0';
len = strlen(pos);
olen = 0;
olinep = NULL;
do {
if (*(pos + len - 1) == '\n')
len--;
if (*(pos + len - 1) == '\\') {
len--;
cont = 1;
} else
cont = 0;
if (len > 0) {
if (!(linep = malloc(olen + len + 1))){
if (olen > 0)
free(olinep);
free(lp->l_groupname);
free(lp);
freelists(this);
errno = ENOMEM;
return (NULL);
}
if (olen > 0) {
memcpy(linep, olinep, olen);
free(olinep);
}
memcpy(linep + olen, pos, len);
olen += len;
*(linep + olen) = '\0';
olinep = linep;
}
if (cont) {
if (fgets(line, LINSIZ, pvt->fp)) {
pos = line;
len = strlen(pos);
} else
cont = 0;
}
} while (cont);
lp->l_line = linep;
lp->l_next = pvt->linehead;
pvt->linehead = lp;
if (!strcmp(lp->l_groupname, group))
return (lp);
}
}
return (NULL);
}