V10/ipc/mgrs/ns/oparsefiles.c

Compare this file to the similar file:
Show the results in this format:

#include <fio.h>
#include <libc.h>
#include <string.h>
#include <sysent.h>
#include <sys/types.h>
#include <sys/stat.h>
extern "C" int stat (const char*, struct stat*);	/* added by pg so that
							 * this could compile
							 */
#include "dbtypes.h"

#define MINLINE 256

/*
 * predeclared
 */
int parseuusys(Ordered *, int, Tuple *);
int parseinhost(Ordered *, int, Tuple *);
int parseinnet(Ordered *, int, Tuple *);
int parsedb(Ordered *, int, Tuple *);
void parsefile(Ordered *, int (*)(Ordered *, int, Tuple *), char *, Tuple *,
		 char *);
int checkfiles();

/*
 *  command table
 */
struct cmdtbl {
	int (*p)(Ordered *, int, Tuple *);
	char *k;
} cmds[] = {
	{ parseuusys,	"uusys"		},
	{ parseinhost,	"inhost"	},
	{ parseinnet,	"innet"		},
	{ parsedb,	"include"	},
	{ 0,		(char *)0	},
};

/*
 *  list of all constant tuples and all data base tuples
 */
static Tuple *dblist;
static Tuple *constlist;

/*
 *  list of parsed files and their update times (up to 32 files)
 */
#define NF 32
struct File {
	File *next;
	char *name;
	long time;
};
File *flist;

/*
 *  Start parsing with the root of the parse files.  Return an
 *  ordered list of the entries.
 */
Ordered *
parsefiles(char *root, Ordered *o)
{
	File *fp, *next;

	/*
	 *  First see if any files have changed.
	 */
	if(checkfiles()==0)
		return o;

	/*
	 *  forget about old files
	 */
	for(fp = flist; fp; fp = next){
		free(fp->name);
		next = fp->next;
		delete fp;
	}
	flist = 0;

	/*
	 *  free old tuples
	 */
	freetuplelist(&dblist);
	freetuplelist(&constlist);

	/*
	 *  create a new ordered set
	 */
	if(o)
		delete o;
	o = new Ordered(12);

	parsefile(o, parsedb, root, (Tuple *)0, (char *)0);
	logevent("db parsed\n");
	return o;
}

/*
 *  see if any db files have changed.  return non-zero if they have.
 */
checkfiles()
{
	struct stat s;
	File *fp;

	if(flist==0)
		return 1;
	for(fp = flist; fp; fp = fp->next){
		if(stat(fp->name, &s)<0){
			if(fp->time) {
				logevent("%s disappeared\n", fp->name);
				return 1;
			}
		} else if(fp->time != s.st_mtime) {
			if(fp->time)
				logevent("%s changed\n", fp->name);
			else
				logevent("%s appeared\n", fp->name);
			return 1;
		}
	}
	return 0;
}

/*
 *  relative paths
 */
char *
path(char *cp, char *dp)
{
	static char path[MAXPATH];

	if(*cp=='/'){
		return cp;
	} else {
		strcpy(path, dp);
		strcat(path, "/");
		strcat(path, cp);
		return path;
	}
}

/*
 *  parse a file.  `parser' is the routine used to do the parsing.
 *  `consttuple' is a tuple of atributes to add to each tuple in the
 *  file.  `conststring' is a string of attributes to add to each
 *  tuple in the file.
 */
void
parsefile(
	Ordered *o,
	int (*parser)(Ordered *, int, Tuple *),
	char *file,
	Tuple *consttuple,
	char *conststring
)
{
	int fd;
	Tuple *ctp;
	char filebuf[sizeof(Fbuffer)];
	struct stat s;
	File *fp;
	char *pp;

	if(conststring){
		ctp = new Tuple(conststring, &constlist);
		ctp->cat(consttuple);
	} else
		ctp = consttuple;

	/*
	 *  remember the file as one of the db files
	 */
	pp = path(file, "/usr/ipc/lib/");
	for(fp = flist; fp; fp = fp->next)
		if(strcmp(fp->name, pp)==0)
			break;
	if(fp==0){
		fp = new File;
		fp->name = strdup(pp);
		fp->next = flist;
		flist = fp;
	}

	/*
	 *  open file and remember it's update time
	 */
	fd = open(pp, 0);
	if(fd<0) {
		fp->time = 0;
		logevent("can't open %s\n", file);
		return;
	}
	fstat(fd, &s);
	fp->time = s.st_mtime;

	/*
	 *  run the file through a parser
	 */
	Finit(fd, filebuf);
	if((*parser)(o, fd, ctp)<0) {
		logevent("error parsing %s\n", file);
		return;
	}
	close(fd);
}

/*
 *  Parse a data base file.  Anything not starting with a # is a tuple. # lines
 *  are of the formats:
 *	# xyz			- a comment
 *	#uusys file attributes	- a request to parse a uucp systems file.
 *				  the attributes are added to each line.
 *	#inhost file attributes	- a request to parse an internet hosts file.
 *				  the attributes are added to each line.
 *	#innet file attributes	- a request to parse an internet networks file.
 *				  the attributes are added to each line.
 *	#include file attributes	- a request to parse a file like this one.
 *				  the attributes are added to each line.
 */
parsedb(Ordered *o, int fd, Tuple *consttuple)
{
	char *cp;
	char *fields[4];
	struct cmdtbl *ctp;
	Tuple *t;

	while((cp = Frdline(fd))!=(char *)0){
		while(*cp==' ' || *cp=='\t')
			cp++;
		switch(*cp){
		case '\0':
			/*
			 *  a blank line is a comment
			 */
			break;
		case '#':
			/*
			 *  less than two fields after a # is a comment
			 */
			setfields("\t ");
			if(getmfields(cp+1, fields, 3)<2)
				break;

			/*
			 *  look for includes
			 */
			for(ctp=cmds; ctp->k; ctp++){
				if(strcmp(fields[0], ctp->k)==0){
					parsefile(o, ctp->p, fields[1],
						consttuple, fields[2]);
					break;
				}
			}

			/*
			 *  anything else is a comment
			 */
			break;
		default:
			t = new Tuple(cp, o, &dblist);
			t->cat(consttuple);
			break;
		}
	}
	return 0;
}

/*
 *  parse a hosts file
 */
parseinhost(Ordered *o, int fd, Tuple *consttuple)
{
	char *line;
	char *fields[16];
	int n, i;
	char attributes[MINLINE];
	Tuple *t;

	while((line=Frdline(fd))!=(char *)0){
		setfields(" \t");
		n = getmfields(line, fields, 16);
		if(n < 2 || *fields[0] == '#')
			continue;
		strcpy(attributes, fields[0]);
		strcat(attributes, ",in ");
		for(i=1; i<n; i++){
			strcat(attributes, fields[i]);
			if(strchr(fields[i], '.')!=(char *)0)
				strcat(attributes, ".,dom ");
			else
				strcat(attributes, " ");
		}
		t = new Tuple(attributes, o, &dblist);
		t->cat(consttuple);
	}
	return 0;
}

/*
 *  parse a networks file
 */
parseinnet(Ordered *o, int fd, Tuple *consttuple)
{
	char *line;
	char *fields[16];
	int n, i;
	char attributes[MINLINE];
	Tuple *t;

	while((line=Frdline(fd))!=(char *)0){
		setfields(" \t");
		n = getmfields(line, fields, 16);
		if(n < 2 || *fields[0] == '#')
			continue;
		strcpy(attributes, fields[1]);
		strcat(attributes, ",in ");
		strcat(attributes, fields[0]);
		strcat(attributes, " ");
		for(i=2; i<n; i++){
			strcat(attributes, fields[i]);
			strcat(attributes, " ");
		}
		t = new Tuple(attributes, o, &dblist);
		t->cat(consttuple);
	}
	return 0;
}

/*
 *  parse the systems file
 */
parseuusys(Ordered *o, int fd, Tuple *consttuple)
{
	char attributes[MINLINE];
	char *line, *cp, *type;
	char *fields[16];
	int n;
	Tuple *t, *ctp;

	static char lastn[32];
	static char lasta[32];
	static char *lastt;

	strcpy(attributes, "uucp,svc");
	ctp = new Tuple(attributes, &constlist);
	ctp->cat(consttuple);
	while((line=Frdline(fd))!=(char *)0){
		/*
		 *  parse a single line
		 */
		setfields(" \t");
		n = getmfields(line, fields, 16);
		if(n < 2 || *fields[0] == '#')
			continue;
		type = (char *)0;
		if(n>=5) {
			if(strncmp(fields[2], "DK", 2)==0){
				cp = strchr(fields[4], '.');
				if(cp!=(char *)0)
					*cp = '\0';
				type = ",dk";
			} else if(strncmp(fields[2], "ACU", 3)==0){
				type = ",tel";
			}
		}
		if(type==lastt && fstrcmp(lastn, fields[0])==0
		&& fstrcmp(lasta, fields[4])==0)
				continue;
		strcpy(attributes, fields[0]);
		if(type){
			strcat(attributes, " ");
			strcat(attributes, fields[4]);
			strcat(attributes, type);
		}
		lastt = type;
		strcpy(lastn, fields[0]);
		if(n>=5 && fields[4])
			strcpy(lasta, fields[4]);
		else
			lasta[0] = '\0';
		t = new Tuple(attributes, o, &dblist);
		t->cat(ctp);
	}
	return 0;
}