#include "strerr.h" #include "stralloc.h" #include "substdio.h" #include "getln.h" #include "error.h" #include "exit.h" #include "readwrite.h" #include "open.h" #include "auto_qmail.h" #include "cdbmss.h" #include "fmt.h" #include "scan.h" #include "byte.h" #define FATAL "qmail-mfrules: fatal: " stralloc address = {0}; stralloc data = {0}; stralloc key = {0}; stralloc line = {0}; char inbuf[1024]; substdio ssin; int fd; int fdtemp; int match = 1; struct cdbmss cdbmss; void die_nomem(void) { strerr_die2x(112,FATAL,"out of memory"); } void die_parse(void) { if (!stralloc_0(&line)) die_nomem(); strerr_die3x(100,FATAL,"unable to parse this line: ",line.s); } void die_read() { strerr_die2sys(111,FATAL,"unable to read control/mailfromrules: "); } void die_write() { strerr_die2sys(111,FATAL,"unable to write to control/mailfromrules.tmp: "); } char strnum[FMT_ULONG]; stralloc sanum = {0}; void getnum(char *buf,int len,unsigned long *u) { if (!stralloc_copyb(&sanum,buf,len)) die_nomem(); if (!stralloc_0(&sanum)) die_nomem(); if (sanum.s[scan_ulong(sanum.s,u)]) die_parse(); } void doaddressdata(void) { int i; int left; int right; unsigned long bot; unsigned long top; if (byte_chr(address.s,address.len,'=') == address.len) if (byte_chr(address.s,address.len,'@') == address.len) { i = byte_chr(address.s,address.len,'-'); if (i < address.len) { left = byte_rchr(address.s,i,'.'); if (left == i) left = 0; else ++left; ++i; right = i + byte_chr(address.s + i,address.len - i,'.'); getnum(address.s + left,i - 1 - left,&bot); getnum(address.s + i,right - i,&top); if (top > 255) top = 255; while (bot <= top) { if (!stralloc_copyb(&key,address.s,left)) die_nomem(); if (!stralloc_catb(&key,strnum,fmt_ulong(strnum,bot))) die_nomem(); if (!stralloc_catb(&key,address.s + right,address.len - right)) die_nomem(); case_lowerb(key.s,key.len); if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_write(); ++bot; } return; } } case_lowerb(address.s,address.len); case_lowerb(data.s,data.len); if (cdbmss_add(&cdbmss,address.s,address.len,data.s,data.len) == -1) die_write(); } void main() { int colon; int dot; int i; int len; char *x; char ch; umask(033); if (chdir(auto_qmail) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); fd = open_read("control/mailfromrules"); if (fd == -1) die_read(); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); fdtemp = open_trunc("control/mailfromrules.tmp"); if (fdtemp == -1) die_write(); if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write(); while (match) { if (getln(&ssin,&line,&match,'\n') != 0) die_read(); x = line.s; len = line.len; if (!len) break; if (x[0] == '#') continue; if (x[0] == '\n') continue; while (len) { ch = x[len - 1]; if (ch != '\n') if (ch != ' ') if (ch != '\t') break; --len; } line.len = len; /* for die_parse() */ colon = byte_chr(x,len,':'); if (!colon) die_parse(); if (colon) if (colon == len || colon < 2) die_parse(); dot = byte_chr(x,len,'.'); if (!dot) die_parse(); if (dot) if (dot == len) die_parse(); if (!stralloc_copyb(&address,x,colon)) die_nomem(); if (!stralloc_copys(&data,"")) die_nomem(); x = line.s + colon + 1; len = line.len - colon - 1; while (len) { if (len < 3) die_parse(); /* input checks */ if ( *x == ',' || *x == ' ' || *x == '\t') die_parse(); i = byte_chr(x,len,','); if (i > 0 && i < len) { if (!stralloc_catb(&data,"+",1)) die_nomem(); if (!stralloc_catb(&data,x,i)) die_nomem(); x += i + 1; len -= i + 1; } else { if (!stralloc_catb(&data,"+",1)) die_nomem(); if (!stralloc_catb(&data,x,len)) die_nomem(); len = 0; } } doaddressdata(); } if (cdbmss_finish(&cdbmss) == -1) die_write(); if (fsync(fdtemp) == -1) die_write(); if (close(fdtemp) == -1) die_write(); /* NFS stupidity */ if (rename("control/mailfromrules.tmp","control/mailfromrules.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move control/mailfromrules.tmp to control/mailfromrules.cdb"); _exit(0); }