Return-Path: bind-request@uunet.uu.net Received: by cognition.pa.dec.com; id AA20768; Thu, 6 May 93 22:31:27 -0700 Received: by inet-gw-2.pa.dec.com; id AA08078; Thu, 6 May 93 22:30:39 -0700 Received: by rodan.UU.NET (5.61/UUNET-mail-drop) id AA10465; Fri, 7 May 93 01:22:48 -0400 Received: from relay1.UU.NET by rodan.UU.NET with SMTP (5.61/UUNET-mail-drop) id AA10461; Fri, 7 May 93 01:22:41 -0400 Received: from inet-gw-1.pa.dec.com by relay1.UU.NET with SMTP (5.61/UUNET-internet-primary) id AA26744; Fri, 7 May 93 01:22:16 -0400 Received: by inet-gw-1.pa.dec.com; id AA23315; Thu, 6 May 93 22:19:41 -0700 Received: from ucsd.edu (ucsd.edu [128.54.16.1]) by vangogh.CS.Berkeley.EDU (ALPHA-6.55/6.25) id WAA29603; Thu, 6 May 1993 22:17:58 -0700 Received: by ucsd.edu; id AA23528 sendmail 5.67/UCSD-2.2-sun Thu, 6 May 93 22:18:06 -0700 for bind@vangogh.CS.Berkeley.EDU Date: Thu, 6 May 93 22:18:06 -0700 From: brian@UCSD.EDU (Brian Kantor) Message-Id: <9305070518.AA23528@ucsd.edu> To: bind@vangogh.CS.Berkeley.EDU, sra@epilogue.com Subject: Re: wish list The AMPR.ORG domain is maintained by a mail robot which updates the zone files through a simple unique-key database. Maintenance of the entries is split among more than 150 "coordinators" in more than 140 regions of the world (more than 50 countries), with more than 15,000 entries in the zone file. It's simple stupid code, and people futz it up occasionally, but it works. Sure, I have to go through the database every few weeks and clean out the stupidities, but without the robot, I'd never have the time to maintain it by hand! These tools are included below primarily as inspiration; I'd hate to inflict this Joe-code (I hacked it up in one weekend) on anyone who would run it as is. - Brian :::::::::::::: /usr/ham/Makefile :::::::::::::: all: ham.org hamhosts hamaddr ham.serial ham.data: ham.pag dbtofile dbtofile ham | sort -u > ham.data chmod 664 ham.data /usr/etc/chown nobody.ham ham.data ham.org: ham.head ham.rev.head ham.data ham.serial cat ham.head ham.data > ham.org cat ham.rev.head > ham.org.rev fgrep '44.' ham.data | awk -f rev.awk >> ham.org.rev cp ham.org /usr/spool/ftp/hamradio/ham.org cp ham.org.rev /usr/spool/ftp/hamradio/ham.org.rev chmod 444 /usr/spool/ftp/hamradio/ham.org chmod 444 /usr/spool/ftp/hamradio/ham.org.rev /usr/etc/chown nobody.ham /usr/spool/ftp/hamradio/ham.org /usr/etc/chown nobody.ham /usr/spool/ftp/hamradio/ham.org.rev hamhosts: ham.data awk -f hosts.awk < ham.data > hamhosts sort -nt. +1 -2 +2 -3 +3 -4 hamhosts -o hamhosts cp hamhosts /usr/spool/ftp/hamradio/hamhosts chmod 644 /usr/spool/ftp/hamradio/hamhosts /usr/etc/chown nobody.ham /usr/spool/ftp/hamradio/hamhosts ham.serial: ham.data serial newserial serial > ham.serial newserial serial: serial.c cc serial.c -O -o serial :::::::::::::: /usr/ham/hosts.awk :::::::::::::: /^#/ {print ""; print $0; h = "AaBbCc";next} /IN A/ {h = $1; printf("\n%s\t%s",$4,$1) next} $3 == "CNAME" && $4 == h {printf " %s",$1} END {printf "\n"} :::::::::::::: /usr/ham/rev.awk :::::::::::::: /IN A 44/ { split($1, h, " "); split($4, a, "."); if (a[1] == "" || a[2] == "" || a[3] == "") next; if ( last4 != $4 ) { printf "%s.%s.%s\tIN\tPTR\t%s.ampr.org.\n", a[4],a[3],a[2],h[1] last4 = $4 } } :::::::::::::: /usr/ham/hamaddr.c :::::::::::::: #include <stdio.h> #include <ndbm.h> #include <strings.h> #include <ctype.h> #include <sys/file.h> char buf[BUFSIZ]; char dat[6][128]; char from[BUFSIZ]; char keybuf[256]; char valbuf[256]; FILE *mailer; #define sendmail "/usr/lib/sendmail -oi -t" #define DB "/usr/ham/ham" DBM *db; datum key, val; main() { int nf; int lc = 0; int i; char *c; int hdr = 0; mailer = popen(sendmail, "w"); if (mailer == NULL) { perror(sendmail); exit(-1); } db = dbm_open(DB, O_RDWR, 0666); if (db == NULL) { perror(DB); exit(1); } while(fgets(buf, sizeof buf, stdin)) { if ( (c = index(buf,'\n')) != NULL) *c = 0; if (strlen(buf) < 1) { hdr++; continue; } if (hdr == 0 && !strncmp(buf, "From:", 5)) { fprintf(mailer, "From: ham-request@ucsd.edu\n"); fprintf(mailer, "To: %s\n", &buf[5]); printf("------->To: %s\n", &buf[6]); fprintf(mailer, "Subject: address update rec'd\n"); fprintf(mailer,"\n\n--- begin ---\n"); continue; } if (hdr == 0) continue; fprintf(mailer,"> %s\n", buf); if ( (c = index(buf,'#')) != NULL) *c = 0; if ( (c = index(buf,';')) != NULL) *c = 0; if ( (c = index(buf,'\r')) != NULL) *c = 0; c = buf; while (*c) { if (isupper(*c)) *c = tolower(*c); c++; } nf = sscanf(buf, "%s %s %s %s %s", dat[1], dat[2], dat[3], dat[4], dat[5]); if (nf < 2) { fprintf(mailer,"---> ignored\n"); continue; } if (dat[1][strlen(dat[1])-1] == '.') { fprintf(mailer,"---> error: trailing period in field 1\n"); continue; } if (dat[2][strlen(dat[2])-1] == '.') { fprintf(mailer,"---> error: trailing period in field 2\n"); continue; } if (!strncmp(dat[1],"44.",3)) /* must be host table fmt */ { lc++; fprintf(mailer,"%d ---> ADD/CHANGE: %s\tIN\tA\t%s\n", lc, dat[2], dat[1]); sprintf(keybuf,"A-%s", dat[2]); key.dptr = keybuf; key.dsize = strlen(key.dptr) + 1; sprintf(valbuf, "%s\tIN\tA\t%s\n", dat[2], dat[1]); val.dptr = valbuf; val.dsize = strlen(val.dptr) + 1; dbm_store(db, key, val, DBM_REPLACE); continue; } if (nf == 4 && !strcmp(dat[2],"in") && !strcmp(dat[3],"a")) { lc++; sprintf(keybuf,"A-%s", dat[1]); key.dptr = keybuf; key.dsize = strlen(key.dptr) + 1; sprintf(valbuf, "%s\tIN\tA\t%s\n", dat[1], dat[4]); val.dptr = valbuf; val.dsize = strlen(val.dptr) + 1; if (strcmp(dat[4], "delete")) { dbm_store(db, key, val, DBM_REPLACE); fprintf(mailer,"%d ---> ADD/CHANGE: %s\tIN\tA\t%s\n", lc, dat[1], dat[4]); } else { dbm_delete(db,key); fprintf(mailer,"%d ---> DELETED: %s\tIN\tA\t%s\n", lc, dat[1], dat[4]); } continue; } if (nf == 4 && !strcmp(dat[2],"in") && !strcmp(dat[3],"cname")) { lc++; fprintf(mailer,"%d:\t%s\tIN\tCNAME\t%s\n", lc, dat[1], dat[4]); sprintf(keybuf,"C-%s", dat[1]); key.dptr = keybuf; key.dsize = strlen(key.dptr) + 1; sprintf(valbuf, "%s\tIN\tCNAME\t%s\n", dat[1], dat[4]); val.dptr = valbuf; val.dsize = strlen(val.dptr) + 1; if (strcmp(dat[4], "delete")) { dbm_store(db, key, val, DBM_REPLACE); fprintf(mailer,"%d ---> ADD/CHANGE: %s\tIN\tA\t%s\n", lc, dat[1], dat[4]); } else { dbm_delete(db,key); fprintf(mailer,"%d ---> DELETED: %s\tIN\tA\t%s\n", lc, dat[1], dat[4]); } continue; } if (nf == 5 && !strcmp(dat[2],"in") && !strcmp(dat[3],"mx") && isdigit(dat[4][0])) { lc++; fprintf(mailer,"%d:\t%s\tIN\tMX %s\t%s\n", lc, dat[1], dat[4], dat[5]); sprintf(keybuf,"M%s-%s", dat[4], dat[1]); key.dptr = keybuf; key.dsize = strlen(key.dptr) + 1; sprintf(valbuf, "%s\tIN\tMX %s\t%s\n", dat[1], dat[4], dat[5]); val.dptr = valbuf; val.dsize = strlen(val.dptr) + 1; if (strcmp(dat[5], "delete")) { dbm_store(db, key, val, DBM_REPLACE); fprintf(mailer,"%d ---> ADD/CHANGE: %s\tIN\tMX %s\t%s\n", lc, dat[1], dat[4], dat[5]); } else { dbm_delete(db,key); fprintf(mailer,"%d ---> DELETED: %s\tIN\tMX %s\t%s\n", lc, dat[1], dat[4], dat[5]); } continue; } fprintf(mailer,"---> skipped: record format error\n"); } fprintf(mailer,"--- end ---\n"); fflush(mailer); pclose(mailer); dbm_close(db); exit(0); } :::::::::::::: /usr/ham/dbtofile.c :::::::::::::: /* * dumps DBM database contents to stdout */ #include <stdio.h> #include <ndbm.h> #include <sys/file.h> char buf[BUFSIZ]; DBM *db; datum key, val; main(argc,argv) int argc; char **argv; { if (argc != 2) { fprintf(stderr,"Usage: dbtofile db \n"); exit(1); } if ((db = dbm_open(argv[1], O_RDONLY, 0)) < 0) { perror(argv[1]); exit(1); } for (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db)) { val = dbm_fetch(db, key); puts(val.dptr); } } :::::::::::::: /usr/ham/serial.c :::::::::::::: #include <stdio.h> #include <sys/time.h> main() { struct tm *tm; struct timeval tv; struct timezone tz; gettimeofday(&tv,&tz); tm = gmtime(&tv.tv_sec); printf("\t\t\t\t%02d%02d%02d%02d\t; Serial\n", tm->tm_year, (tm->tm_mon + 1), tm->tm_mday, tm->tm_hour); exit(0); } :::::::::::::: /usr/ham/newserial :::::::::::::: #!/bin/sh for f in \ ham.head \ ham.rev.head \ ; do ex $f << EOF > /dev/null /Serial/ d - r ham.serial w q EOF echo $f 'updated' ; done ; exit 0