#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "hash.h"
#ifndef lint
static const char rcsid[] = "$OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $";
#endif
struct linelist {
struct linelist *l_next;
int l_parsed;
char *l_groupname;
char *l_line;
};
struct netgrp {
struct netgrp *ng_next;
char *ng_str[3];
};
#define NG_HOST 0
#define NG_USER 1
#define NG_DOM 2
static struct linelist *linehead = (struct linelist *)0;
static struct netgrp *nextgrp = (struct netgrp *)0;
static struct {
struct netgrp *gr;
char *grname;
} grouphead = {
(struct netgrp *)0,
(char *)0,
};
static int parse_netgrp();
static struct linelist *read_for_group();
void __setnetgrent(), __endnetgrent();
int __getnetgrent();
extern struct group_entry *gtable[];
void
__setnetgrent(group)
char *group;
{
if (group == NULL || !strlen(group))
return;
if (grouphead.gr == (struct netgrp *)0 ||
strcmp(group, grouphead.grname)) {
__endnetgrent();
if (parse_netgrp(group))
__endnetgrent();
else {
grouphead.grname = (char *)
malloc(strlen(group) + 1);
strcpy(grouphead.grname, group);
}
}
nextgrp = grouphead.gr;
}
int
__getnetgrent(hostp, userp, domp)
char **hostp, **userp, **domp;
{
if (nextgrp) {
*hostp = nextgrp->ng_str[NG_HOST];
*userp = nextgrp->ng_str[NG_USER];
*domp = nextgrp->ng_str[NG_DOM];
nextgrp = nextgrp->ng_next;
return (1);
}
return (0);
}
void
__endnetgrent()
{
register struct linelist *lp, *olp;
register struct netgrp *gp, *ogp;
lp = linehead;
while (lp) {
olp = lp;
lp = lp->l_next;
free(olp->l_groupname);
free(olp->l_line);
free((char *)olp);
}
linehead = (struct linelist *)0;
if (grouphead.grname) {
free(grouphead.grname);
grouphead.grname = (char *)0;
}
gp = 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);
}
grouphead.gr = (struct netgrp *)0;
}
static int
parse_netgrp(group)
char *group;
{
register char *spos, *epos;
register int len, strpos;
#ifdef DEBUG
register int fields;
#endif
char *pos, *gpos;
struct netgrp *grp;
struct linelist *lp = linehead;
while (lp) {
if (!strcmp(group, lp->l_groupname))
break;
lp = lp->l_next;
}
if (lp == (struct linelist *)0 &&
(lp = read_for_group(group)) == (struct linelist *)0)
return (1);
if (lp->l_parsed) {
#ifdef DEBUG
fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
#endif
return (1);
} else
lp->l_parsed = 1;
pos = lp->l_line;
while (pos != NULL && *pos != '\0') {
if (*pos == '(') {
grp = (struct netgrp *)malloc(sizeof (struct netgrp));
bzero((char *)grp, sizeof (struct netgrp));
grp->ng_next = grouphead.gr;
grouphead.gr = grp;
pos++;
gpos = strsep(&pos, ")");
#ifdef DEBUG
fields = 0;
#endif
for (strpos = 0; strpos < 3; strpos++) {
if ((spos = strsep(&gpos, ","))) {
#ifdef DEBUG
fields++;
#endif
while (*spos == ' ' || *spos == '\t')
spos++;
if ((epos = strpbrk(spos, " \t"))) {
*epos = '\0';
len = epos - spos;
} else
len = strlen(spos);
if (len > 0) {
grp->ng_str[strpos] = (char *)
malloc(len + 1);
bcopy(spos, grp->ng_str[strpos],
len + 1);
}
} else {
grp->ng_str[strpos] = NULL;
}
}
#ifdef DEBUG
if (fields < 3)
fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n",
grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
grp->ng_str[NG_USER] == NULL ? "" : ",",
grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
grp->ng_str[NG_DOM] == NULL ? "" : ",",
grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
lp->l_groupname);
#endif
} else {
spos = strsep(&pos, ", \t");
if (parse_netgrp(spos))
continue;
}
if (pos != NULL)
while (*pos == ' ' || *pos == ',' || *pos == '\t')
pos++;
}
return (0);
}
static struct linelist *
read_for_group(group)
char *group;
{
register char *pos, *spos, *linep = NULL, *olinep = NULL;
register int len, olen;
int cont;
struct linelist *lp;
char line[LINSIZ + 1];
char *data = NULL;
data = lookup (gtable, group);
sprintf(line, "%s %s", group, data);
pos = (char *)&line;
#ifdef CANT_HAPPEN
if (*pos == '#')
continue;
#endif
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') {
lp = (struct linelist *)malloc(sizeof (*lp));
lp->l_parsed = 0;
lp->l_groupname = (char *)malloc(len + 1);
bcopy(spos, lp->l_groupname, len);
*(lp->l_groupname + len) = '\0';
len = strlen(pos);
olen = 0;
do {
if (*(pos + len - 1) == '\n')
len--;
if (*(pos + len - 1) == '\\') {
len--;
cont = 1;
} else
cont = 0;
if (len > 0) {
linep = (char *)malloc(olen + len + 1);
if (olen > 0) {
bcopy(olinep, linep, olen);
free(olinep);
}
bcopy(pos, linep + olen, len);
olen += len;
*(linep + olen) = '\0';
olinep = linep;
}
#ifdef CANT_HAPPEN
if (cont) {
if (fgets(line, LINSIZ, netf)) {
pos = line;
len = strlen(pos);
} else
cont = 0;
}
#endif
} while (cont);
lp->l_line = linep;
lp->l_next = linehead;
linehead = lp;
#ifdef CANT_HAPPEN
if (!strcmp(lp->l_groupname, group))
#endif
return (lp);
}
return ((struct linelist *)0);
}