V10/ipc/mgrs/ns/oparsefiles.c
#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;
}