|
|
1.1 root 1: #include <fio.h>
2: #include <libc.h>
3: #include <string.h>
4: #include <sysent.h>
5: #include <sys/types.h>
6: #include <sys/stat.h>
7: extern "C" int stat (const char*, struct stat*); /* added by pg so that
8: * this could compile
9: */
10: extern "C" char *memset(char*, int, int);
11: extern "C" long time(long *);
12: extern "C" long in_aton(char *);
13: extern "C" char *in_ntoa(long);
14:
15: #include "dbtypes.h"
16:
17: #define MINLINE 256
18:
19: /*
20: * list of information about each open database (up to NDB of them)
21: * the system database is always at index 0
22: */
23:
24: #define NDB 64
25: #define SYSDB 0
26:
27: Db *db[NDB];
28:
29: /*
30: * predeclared
31: */
32: int parseuusys(Db *, int, Tuple *);
33: int parseinhost(Db *, int, Tuple *);
34: int parseinnet(Db *, int, Tuple *);
35: int parsedb(Db *, int, Tuple *);
36: void parsefile(Db *, int (*)(Db *, int, Tuple *), char *, Tuple *, char *);
37: void clearDb(Db *);
38: void releaseDb(Db *);
39: int checkfiles(Db *);
40:
41: /*
42: * command table
43: */
44: struct cmdtbl {
45: int (*p)(Db *, int, Tuple *);
46: char *k;
47: } cmds[] = {
48: { parseuusys, "uusys" },
49: { parseinhost, "inhost" },
50: { parseinnet, "innet" },
51: { parsedb, "include" },
52: { 0, (char *)0 },
53: };
54:
55: /*
56: * Return a pointer to a loaded database for *uid. If (uid == 0), return a
57: * pointer to the system database. If the database is not loaded, return
58: * (Db *)0. *Hint provides the array location of the last user database,
59: * and is updated for each user database created/found.
60: */
61: Db *
62: finddb(int *uid, int *hint)
63: {
64: int uidval;
65: int dbindex;
66: int hintval = *hint;
67: Db *d = 0;
68:
69: if (uid) {
70: uidval = *uid;
71: /*
72: * See if it's the same db as last time
73: */
74: if ((hintval > SYSDB) && (hintval < NDB) && (db[hintval]) &&
75: (db[hintval]->uid == uidval))
76: d = db[hintval];
77: else
78: /*
79: * Look for user db
80: */
81: for (dbindex = SYSDB + 1; dbindex < NDB; dbindex++) {
82: if (db[dbindex]) {
83: if (uidval == db[dbindex]->uid) {
84: *hint = dbindex;
85: d = db[dbindex];
86: break;
87: }
88: }
89: }
90: } else
91: d = db[SYSDB];
92:
93: if (d)
94: d->lasttime = time ((long *) 0);
95: return d;
96: }
97:
98: /*
99: * Load the database in rootdir/filename. If uid == 0, load the database
100: * as the system database; otherwise, load the database for user with *uid.
101: * Return a pointer to the database loaded. If the database is a user
102: * database, update *hint with the array index of the database.
103: */
104: Db *
105: newdb(int *uid, char *rootdir, char *filename, char *dbname, int *hint)
106: {
107: int oldindex;
108: int dbindex;
109: long oldtime;
110: int uidval = 0;
111: Db *d;
112:
113: if (uid) {
114: /*
115: * Find the first free slot or the oldest slot
116: */
117: uidval = *uid;
118: oldindex = SYSDB + 1;
119: if (db[oldindex]) {
120: oldtime = db[oldindex]->lasttime;
121: for (dbindex = oldindex; dbindex < NDB; dbindex++) {
122: if (!db[dbindex])
123: break;
124: if (db[dbindex]->lasttime < oldtime) {
125: oldindex = dbindex;
126: oldtime = db[dbindex]->lasttime;
127: }
128: }
129: }
130: if (db[oldindex])
131: releaseDb(db[oldindex]);
132: dbindex = oldindex;
133: *hint = dbindex;
134: } else
135: dbindex = SYSDB;
136:
137: if (!(d = db[dbindex])) {
138: db[dbindex] = d = new Db;
139: memset((char *)d, 0, sizeof(Db));
140: }
141:
142: d->uid = uidval;
143: d->rootdir = strdup(rootdir);
144: d->filename = strdup(filename);
145: d->dbname = strdup(dbname);
146: d->lasttime = time((long *)0);
147: return d;
148: }
149:
150: /*
151: * Start parsing with the root of the parse files. Return an
152: * ordered list of the entries.
153: */
154: void
155: parsefiles(Db *d)
156: {
157: char dbattr[MAXDBNAME+4];
158:
159: clearDb(d);
160: d->o = new Ordered(12);
161: strcpy(dbattr,d->dbname);
162: strcat(dbattr,",db");
163: parsefile(d, parsedb, d->filename, (Tuple *)0, dbattr);
164: d->origin = lookup("local,origin", d->o);
165: logevent("db %s: parsed from %s/%s\n",d->dbname,d->rootdir,d->filename);
166: }
167:
168: /*
169: * Release all databases. System database is cleared, so it will be
170: * reparsed by main loop.
171: */
172: void
173: releasedbs()
174: {
175: int dbindex;
176:
177: clearDb(db[SYSDB]);
178: for (dbindex = SYSDB+1; dbindex < NDB; dbindex++) {
179: if (db[dbindex]) {
180: releaseDb(db[dbindex]);
181: delete db[dbindex];
182: db[dbindex] = 0;
183: }
184: }
185: }
186:
187: /*
188: * Completely release all space occupied by a database
189: */
190: void
191: releaseDb(Db *db)
192: {
193: if (db->rootdir)
194: free(db->rootdir);
195: if (db->filename)
196: free(db->filename);
197: if (db->dbname)
198: free(db->dbname);
199: db->rootdir = db->filename = db->dbname = (char *) 0;
200: clearDb(db);
201: }
202:
203: /*
204: * Clear database data structures to prepare for reparsing the database
205: * from the same root db file
206: */
207: void
208: clearDb(Db *db)
209: {
210: File *fp, *next;
211:
212: /*
213: * forget about old files
214: */
215: for(fp = db->flist; fp; fp = next){
216: if (fp->name) free(fp->name);
217: next = fp->next;
218: delete fp;
219: }
220: db->flist = 0;
221:
222: /*
223: * free old tuples
224: */
225: freetuplelist(&db->dblist);
226: freetuplelist(&db->constlist);
227:
228: /*
229: * Delete the old set
230: */
231: if(db->o)
232: delete db->o;
233: db->o = (Ordered *)0;
234:
235: /*
236: * Delete the origin
237: */
238: if (db->origin)
239: delete db->origin;
240: db->origin = (Set *)0;
241: }
242:
243: /*
244: * see if any db files have changed. return non-zero if they have.
245: */
246: int
247: checkfiles(Db *d)
248: {
249: struct stat s;
250: File *fp;
251:
252: if(d->flist==0)
253: return 1;
254: for(fp = d->flist; fp; fp = fp->next){
255: if(stat(fp->name, &s)<0){
256: if(fp->time) {
257: logevent("db %s: %s disappeared\n", d->dbname,
258: fp->name);
259: return 1;
260: }
261: } else if(fp->time != s.st_mtime) {
262: if(fp->time)
263: logevent("db %s: %s changed\n", d->dbname,
264: fp->name);
265: else
266: logevent("db %s: %s appeared\n", d->dbname,
267: fp->name);
268: return 1;
269: }
270: }
271: return 0;
272: }
273:
274: /*
275: * relative paths
276: */
277: char *
278: path(char *cp, char *dp)
279: {
280: static char path[MAXPATH];
281:
282: if(*cp=='/'){
283: return cp;
284: } else {
285: strcpy(path, dp);
286: strcat(path, "/");
287: strcat(path, cp);
288: return path;
289: }
290: }
291:
292: /*
293: * parse a file. `parser' is the routine used to do the parsing.
294: * `consttuple' is a tuple of atributes to add to each tuple in the
295: * file. `conststring' is a string of attributes to add to each
296: * tuple in the file.
297: */
298: void
299: parsefile(
300: Db *d,
301: int (*parser)(Db *, int, Tuple *),
302: char *file,
303: Tuple *consttuple,
304: char *conststring
305: )
306: {
307: int fd;
308: Tuple *ctp;
309: char filebuf[sizeof(Fbuffer)];
310: struct stat s;
311: File *fp;
312: char *pp;
313:
314: if(conststring){
315: ctp = new Tuple(conststring, &d->constlist);
316: ctp->cat(consttuple);
317: } else
318: ctp = consttuple;
319:
320: /*
321: * remember the file as one of the db files
322: */
323: pp = path(file, d->rootdir);
324: for(fp = d->flist; fp; fp = fp->next)
325: if(strcmp(fp->name, pp)==0)
326: break;
327: if(fp==0){
328: fp = new File;
329: fp->name = strdup(pp);
330: fp->next = d->flist;
331: d->flist = fp;
332: }
333:
334: /*
335: * open file and remember it's update time
336: */
337: fd = open(pp, 0);
338: if(fd<0) {
339: fp->time = 0;
340: logevent("db %s: can't open %s\n", d->dbname, pp);
341: return;
342: }
343: fstat(fd, &s);
344: fp->time = s.st_mtime;
345:
346: /*
347: * run the file through a parser
348: */
349: logevent("db %s:parsing %s\n", d->dbname, file);
350: Finit(fd, filebuf);
351: if((*parser)(d, fd, ctp)<0) {
352: logevent("db %s:error parsing %s\n", d->dbname, file);
353: return;
354: }
355: close(fd);
356: }
357:
358: /*
359: * Parse a data base file. Anything not starting with a # is a tuple. # lines
360: * are of the formats:
361: * # xyz - a comment
362: * #uusys file attributes - a request to parse a uucp systems file.
363: * the attributes are added to each line.
364: * #inhost file attributes - a request to parse an internet hosts file.
365: * the attributes are added to each line.
366: * #innet file attributes - a request to parse an internet networks file.
367: * the attributes are added to each line.
368: * #include file attributes - a request to parse a file like this one.
369: * the attributes are added to each line.
370: */
371: parsedb(Db *d, int fd, Tuple *consttuple)
372: {
373: char *cp;
374: char *fields[4];
375: struct cmdtbl *ctp;
376: Tuple *t;
377:
378: while((cp = Frdline(fd))!=(char *)0){
379: while(*cp==' ' || *cp=='\t')
380: cp++;
381: switch(*cp){
382: case '\0':
383: /*
384: * a blank line is a comment
385: */
386: break;
387: case '#':
388: /*
389: * less than two fields after a # is a comment
390: */
391: setfields("\t ");
392: if(getmfields(cp+1, fields, 3)<2)
393: break;
394:
395: /*
396: * look for includes
397: */
398: for(ctp=cmds; ctp->k; ctp++){
399: if(strcmp(fields[0], ctp->k)==0){
400: parsefile(d, ctp->p, fields[1],
401: consttuple, fields[2]);
402: break;
403: }
404: }
405:
406: /*
407: * anything else is a comment
408: */
409: break;
410: default:
411: t = new Tuple(cp, d->o, &d->dblist);
412: t->cat(consttuple);
413: break;
414: }
415: }
416: return 0;
417: }
418:
419: /*
420: * parse a hosts file
421: */
422: parseinhost(Db *d, int fd, Tuple *consttuple)
423: {
424: char *line;
425: char *fields[16];
426: int n, i, len;
427: char attributes[MINLINE];
428: Tuple *t;
429:
430: while((line=Frdline(fd))!=(char *)0){
431: setfields(" \t");
432: n = getmfields(line, fields, 16);
433: if(n < 2 || *fields[0] == '#')
434: continue;
435: strcpy(attributes, fields[0]);
436: strcat(attributes, ",in ");
437: len = strlen(attributes);
438: for(i=1; i<n; i++){
439: len += strlen(fields[i]) + 6;
440: if(len >= MINLINE)
441: break;
442: strcat(attributes, fields[i]);
443: if(strchr(fields[i], '.')!=(char *)0)
444: strcat(attributes, ".,dom ");
445: else
446: strcat(attributes, " ");
447: }
448: t = new Tuple(attributes, d->o, &d->dblist);
449: t->cat(consttuple);
450: }
451: return 0;
452: }
453:
454: /*
455: * parse a networks file
456: */
457: parseinnet(Db *d, int fd, Tuple *consttuple)
458: {
459: char *line;
460: char *fields[16];
461: int n, i, len;
462: char attributes[MINLINE];
463: Tuple *t;
464:
465: while((line=Frdline(fd))!=(char *)0){
466: setfields(" \t");
467: n = getmfields(line, fields, 16);
468: if(n < 2 || *fields[0] == '#')
469: continue;
470: strcpy(attributes, fields[1]);
471: strcat(attributes, ",in ");
472: strcat(attributes, fields[0]);
473: strcat(attributes, " ");
474: len = strlen(attributes);
475: for(i=2; i<n; i++){
476: len += strlen(fields[i]) + 1;
477: if(len >= MINLINE)
478: break;
479: strcat(attributes, fields[i]);
480: strcat(attributes, " ");
481: }
482: t = new Tuple(attributes, d->o, &d->dblist);
483: t->cat(consttuple);
484: }
485: return 0;
486: }
487:
488: /*
489: * parse the systems file
490: */
491: parseuusys(Db *d, int fd, Tuple *consttuple)
492: {
493: char attributes[MINLINE];
494: char *line, *cp, *type;
495: char *fields[16];
496: int n;
497: Tuple *t, *ctp;
498:
499: static char lastn[32];
500: static char lasta[32];
501: static char *lastt;
502:
503: strcpy(attributes, "uucp,svc");
504: ctp = new Tuple(attributes, &d->constlist);
505: ctp->cat(consttuple);
506: while((line=Frdline(fd))!=(char *)0){
507: /*
508: * parse a single line
509: */
510: setfields(" \t");
511: n = getmfields(line, fields, 16);
512: if(n < 2 || *fields[0] == '#')
513: continue;
514: type = (char *)0;
515: if(n>=5) {
516: if(strncmp(fields[2], "DK", 2)==0){
517: cp = strchr(fields[4], '.');
518: if(cp!=(char *)0)
519: *cp = '\0';
520: type = ",dk";
521: } else if(strncmp(fields[2], "ACU", 3)==0){
522: type = ",tel";
523: }
524: }
525: if(type==lastt && fstrcmp(lastn, fields[0])==0
526: && fstrcmp(lasta, fields[4])==0)
527: continue;
528: strcpy(attributes, fields[0]);
529: if(type){
530: strcat(attributes, " ");
531: strcat(attributes, fields[4]);
532: strcat(attributes, type);
533: }
534: lastt = type;
535: strcpy(lastn, fields[0]);
536: if(n>=5 && fields[4])
537: strcpy(lasta, fields[4]);
538: else
539: lasta[0] = '\0';
540: t = new Tuple(attributes, d->o, &d->dblist);
541: t->cat(ctp);
542: }
543: return 0;
544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.