#include #include "genalloc.h" #include "alloc.h" #include "stralloc.h" #include "logmsg.h" #include "getln.h" #include "buffer.h" #include "readwrite.h" #include "exit.h" #include "str.h" #include "fmt.h" #include "scan.h" #include "case.h" #define WHO "matchup" void nomem() { logmsg(WHO,111,FATAL,"out of memory"); } void die_read() { logmsg(WHO,110,ERROR,"unable to read input: "); } void die_write() { logmsg(WHO,110,ERROR,"unable to write output: "); } void die_write5() { logmsg(WHO,111,FATAL,"unable to write fd 5: "); } void out(char *buf,int len) { if (buffer_put(buffer_1,buf,len) == -1) die_write(); } void outs(char *buf) { if (buffer_puts(buffer_1,buf) == -1) die_write(); } char buf5[512]; buffer bo5 = BUFFER_INIT(write,5,buf5,sizeof(buf5)); void out5(char *buf,int len) { if (buffer_put(&bo5,buf,len) == -1) die_write5(); } void outs5(char *buf) { if (buffer_puts(&bo5,buf) == -1) die_write5(); } GEN_ALLOC_typedef(ulongalloc,unsigned long,u,len,a) GEN_ALLOC_ready(ulongalloc,unsigned long,u,len,a,i,n,x,30,ulongalloc_ready) GEN_ALLOC_readyplus(ulongalloc,unsigned long,u,len,a,i,n,x,30,ulongalloc_readyplus) char strnum[FMT_ULONG]; stralloc pool = {0}; unsigned int poolbytes = 0; int nummsg = 0; ulongalloc msg = {0}; ulongalloc bytes = {0}; ulongalloc qp = {0}; ulongalloc uid = {0}; ulongalloc numk = {0}; ulongalloc numd = {0}; ulongalloc numz = {0}; ulongalloc sender = {0}; ulongalloc birth = {0}; int msg_find(unsigned long m) { int i; for (i = 0; i < nummsg; ++i) if (msg.u[i] == m) return i; return -1; } int msg_add(unsigned long m) { int i; for (i = 0; i < nummsg; ++i) if (msg.u[i] == m) return i; i = nummsg++; if (!ulongalloc_ready(&msg,nummsg)) nomem(); if (!ulongalloc_ready(&bytes,nummsg)) nomem(); if (!ulongalloc_ready(&qp,nummsg)) nomem(); if (!ulongalloc_ready(&uid,nummsg)) nomem(); if (!ulongalloc_ready(&numk,nummsg)) nomem(); if (!ulongalloc_ready(&numd,nummsg)) nomem(); if (!ulongalloc_ready(&numz,nummsg)) nomem(); if (!ulongalloc_ready(&sender,nummsg)) nomem(); if (!ulongalloc_ready(&birth,nummsg)) nomem(); msg.u[i] = m; return i; } void msg_kill(int i) { poolbytes -= str_len(pool.s + sender.u[i]) + 1; poolbytes -= str_len(pool.s + birth.u[i]) + 1; --nummsg; msg.u[i] = msg.u[nummsg]; bytes.u[i] = bytes.u[nummsg]; qp.u[i] = qp.u[nummsg]; uid.u[i] = uid.u[nummsg]; numk.u[i] = numk.u[nummsg]; numd.u[i] = numd.u[nummsg]; numz.u[i] = numz.u[nummsg]; sender.u[i] = sender.u[nummsg]; birth.u[i] = birth.u[nummsg]; } int numdel = 0; ulongalloc del = {0}; ulongalloc dmsg = {0}; ulongalloc dchan = {0}; ulongalloc drecip = {0}; ulongalloc dstart = {0}; int del_find(unsigned long d) { int i; for (i = 0; i < numdel; ++i) if (del.u[i] == d) return i; return -1; } int del_add(unsigned long d) { int i; for (i = 0; i < numdel; ++i) if (del.u[i] == d) return i; i = numdel++; if (!ulongalloc_ready(&del,numdel)) nomem(); if (!ulongalloc_ready(&dmsg,numdel)) nomem(); if (!ulongalloc_ready(&dchan,numdel)) nomem(); if (!ulongalloc_ready(&drecip,numdel)) nomem(); if (!ulongalloc_ready(&dstart,numdel)) nomem(); del.u[i] = d; return i; } void del_kill(int i) { poolbytes -= str_len(pool.s + dchan.u[i]) + 1; poolbytes -= str_len(pool.s + drecip.u[i]) + 1; poolbytes -= str_len(pool.s + dstart.u[i]) + 1; --numdel; del.u[i] = del.u[numdel]; dmsg.u[i] = dmsg.u[numdel]; dchan.u[i] = dchan.u[numdel]; drecip.u[i] = drecip.u[numdel]; dstart.u[i] = dstart.u[numdel]; } stralloc pool2 = {0}; void garbage() { int i; char *x; if (pool.len - poolbytes < poolbytes + 4096) return; if (!stralloc_copys(&pool2,"")) nomem(); for (i = 0; i < nummsg; ++i) { x = pool.s + birth.u[i]; birth.u[i] = pool2.len; if (!stralloc_cats(&pool2,x)) nomem(); if (!stralloc_0(&pool2)) nomem(); x = pool.s + sender.u[i]; sender.u[i] = pool2.len; if (!stralloc_cats(&pool2,x)) nomem(); if (!stralloc_0(&pool2)) nomem(); } for (i = 0; i < numdel; ++i) { x = pool.s + dstart.u[i]; dstart.u[i] = pool2.len; if (!stralloc_cats(&pool2,x)) nomem(); if (!stralloc_0(&pool2)) nomem(); x = pool.s + dchan.u[i]; dchan.u[i] = pool2.len; if (!stralloc_cats(&pool2,x)) nomem(); if (!stralloc_0(&pool2)) nomem(); x = pool.s + drecip.u[i]; drecip.u[i] = pool2.len; if (!stralloc_cats(&pool2,x)) nomem(); if (!stralloc_0(&pool2)) nomem(); } if (!stralloc_copy(&pool,&pool2)) nomem(); poolbytes = pool.len; /* redundant, but doesn't hurt */ } stralloc line = {0}; int match; #define FIELDS 20 int field[FIELDS]; void clear() { while (numdel > 0) del_kill(0); garbage(); } void starting() { unsigned long d; unsigned long m; int dpos; scan_ulong(line.s + field[3],&d); scan_ulong(line.s + field[5],&m); dpos = del_add(d); dmsg.u[dpos] = m; dstart.u[dpos] = pool.len; if (!stralloc_cats(&pool,line.s + field[0])) nomem(); if (!stralloc_0(&pool)) nomem(); dchan.u[dpos] = pool.len; if (!stralloc_cats(&pool,line.s + field[7])) nomem(); if (!stralloc_0(&pool)) nomem(); drecip.u[dpos] = pool.len; if (!stralloc_cats(&pool,line.s + field[8])) nomem(); if (!stralloc_0(&pool)) nomem(); case_lowers(pool.s + drecip.u[dpos]); poolbytes += pool.len - dstart.u[dpos]; } void delivery() { unsigned long d; unsigned long m; int dpos; int mpos; char *result = "?"; char *reason = ""; scan_ulong(line.s + field[2],&d); dpos = del_find(d); if (dpos == -1) return; m = dmsg.u[dpos]; mpos = msg_find(m); if (str_start(line.s + field[3],"succ")) { if (mpos != -1) ++numk.u[mpos]; result = "d k "; reason = line.s + field[4]; } else if (str_start(line.s + field[3],"fail")) { if (mpos != -1) ++numd.u[mpos]; result = "d d "; reason = line.s + field[4]; } else if (str_start(line.s + field[3],"defer")) { if (mpos != -1) ++numz.u[mpos]; result = "d z "; reason = line.s + field[4]; } else if (str_start(line.s + field[3],"report")) { if (mpos != -1) ++numz.u[mpos]; result = "d z "; reason = "report_mangled"; } outs(result); if (mpos != -1) { outs(pool.s + birth.u[mpos]); outs(" "); outs(pool.s + dstart.u[dpos]); outs(" "); outs(line.s + field[0]); outs(" "); out(strnum,fmt_ulong(strnum,bytes.u[mpos])); outs(" "); outs(pool.s + sender.u[mpos]); outs(" "); outs(pool.s + dchan.u[dpos]); outs("."); outs(pool.s + drecip.u[dpos]); outs(" "); out(strnum,fmt_ulong(strnum,qp.u[mpos])); outs(" "); out(strnum,fmt_ulong(strnum,uid.u[mpos])); outs(" "); outs(reason); } else { outs(pool.s + dstart.u[dpos]); outs(" "); outs(pool.s + dstart.u[dpos]); outs(" "); outs(line.s + field[0]); outs(" 0 ? "); outs(pool.s + dchan.u[dpos]); outs("."); outs(pool.s + drecip.u[dpos]); outs(" ? ? "); outs(reason); } outs("\n"); del_kill(dpos); garbage(); } void newmsg() { unsigned long m; int mpos; scan_ulong(line.s + field[3],&m); mpos = msg_find(m); if (mpos == -1) return; msg_kill(mpos); garbage(); } void endmsg() { unsigned long m; int mpos; scan_ulong(line.s + field[3],&m); mpos = msg_find(m); if (mpos == -1) return; outs("m "); outs(pool.s + birth.u[mpos]); outs(" "); outs(line.s + field[0]); outs(" "); out(strnum,fmt_ulong(strnum,bytes.u[mpos])); outs(" "); out(strnum,fmt_ulong(strnum,numk.u[mpos])); outs(" "); out(strnum,fmt_ulong(strnum,numd.u[mpos])); outs(" "); out(strnum,fmt_ulong(strnum,numz.u[mpos])); outs(" "); outs(pool.s + sender.u[mpos]); outs(" "); out(strnum,fmt_ulong(strnum,qp.u[mpos])); outs(" "); out(strnum,fmt_ulong(strnum,uid.u[mpos])); outs("\n"); msg_kill(mpos); garbage(); } void info() { unsigned long m; int mpos; scan_ulong(line.s + field[3],&m); mpos = msg_add(m); scan_ulong(line.s + field[5],&bytes.u[mpos]); scan_ulong(line.s + field[9],&qp.u[mpos]); scan_ulong(line.s + field[11],&uid.u[mpos]); numk.u[mpos] = 0; numd.u[mpos] = 0; numz.u[mpos] = 0; birth.u[mpos] = pool.len; if (!stralloc_cats(&pool,line.s + field[0])) nomem(); if (!stralloc_0(&pool)) nomem(); sender.u[mpos] = pool.len; if (!stralloc_cats(&pool,line.s + field[7])) nomem(); if (!stralloc_0(&pool)) nomem(); case_lowers(pool.s + sender.u[mpos]); poolbytes += pool.len - birth.u[mpos]; } void extra() { unsigned long m; int mpos; scan_ulong(line.s + field[2],&m); mpos = msg_find(m); if (mpos == -1) return; scan_ulong(line.s + field[3],&numk.u[mpos]); scan_ulong(line.s + field[4],&numz.u[mpos]); scan_ulong(line.s + field[5],&numd.u[mpos]); } void pending() { int i; for (i = 0; i < nummsg; ++i) { outs5(pool.s + birth.u[i]); outs5(" info msg "); out5(strnum,fmt_ulong(strnum,msg.u[i])); outs5(": bytes "); out5(strnum,fmt_ulong(strnum,bytes.u[i])); outs5(" from "); outs5(pool.s + sender.u[i]); outs5(" qp "); out5(strnum,fmt_ulong(strnum,qp.u[i])); outs5(" uid "); out5(strnum,fmt_ulong(strnum,uid.u[i])); outs5("\n"); outs5(pool.s + birth.u[i]); outs5(" extra "); out5(strnum,fmt_ulong(strnum,msg.u[i])); outs5(" "); out5(strnum,fmt_ulong(strnum,numk.u[i])); outs5(" "); out5(strnum,fmt_ulong(strnum,numz.u[i])); outs5(" "); out5(strnum,fmt_ulong(strnum,numd.u[i])); outs5("\n"); } for (i = 0; i < numdel; ++i) { outs5(pool.s + dstart.u[i]); outs5(" starting delivery "); out5(strnum,fmt_ulong(strnum,del.u[i])); outs5(": msg "); out5(strnum,fmt_ulong(strnum,dmsg.u[i])); outs5(" to "); outs5(pool.s + dchan.u[i]); outs5(" "); outs5(pool.s + drecip.u[i]); outs5("\n"); } out5(line.s,line.len); if (buffer_flush(&bo5) == -1) die_write5(); } stralloc outline = {0}; int main() { int i; int j; char ch; if (!stralloc_copys(&pool,"")) nomem(); if (!ulongalloc_ready(&msg,1)) nomem(); if (!ulongalloc_ready(&bytes,1)) nomem(); if (!ulongalloc_ready(&qp,1)) nomem(); if (!ulongalloc_ready(&uid,1)) nomem(); if (!ulongalloc_ready(&numk,1)) nomem(); if (!ulongalloc_ready(&numd,1)) nomem(); if (!ulongalloc_ready(&numz,1)) nomem(); if (!ulongalloc_ready(&del,1)) nomem(); if (!ulongalloc_ready(&dmsg,1)) nomem(); for (;;) { if (getln(buffer_0,&line,&match,'\n') == -1) die_read(); if (!match) break; if (!stralloc_copy(&outline,&line)) nomem(); for (i = 0; i < line.len; ++i) { ch = line.s[i]; if ((ch == '\n') || (ch == ' ') || (ch == '\t')) line.s[i] = 0; } j = 0; for (i = 0; i < FIELDS; ++i) { while (j < line.len) if (line.s[j]) break; else ++j; field[i] = j; while (j < line.len) if (!line.s[j]) break; else ++j; } if (!stralloc_0(&line)) nomem(); if (str_equal(line.s + field[1],"status:")) ; else if (str_equal(line.s + field[1],"starting")) starting(); else if (str_equal(line.s + field[1],"delivery")) delivery(); else if (str_equal(line.s + field[1],"new")) newmsg(); else if (str_equal(line.s + field[1],"end")) endmsg(); else if (str_equal(line.s + field[1],"info")) info(); else if (str_equal(line.s + field[1],"extra")) extra(); else if (str_equal(line.s + field[1],"running")) clear(); else if (str_equal(line.s + field[1],"exiting")) clear(); else if (str_equal(line.s + field[1],"number")) ; else if (str_equal(line.s + field[1],"local")) ; else if (str_equal(line.s + field[1],"remote")) ; else if (str_equal(line.s + field[1],"warning:")) out(outline.s,outline.len); else if (str_equal(line.s + field[1],"alert:")) out(outline.s,outline.len); else { outs("? "); out(outline.s,outline.len); } } if (buffer_flush(buffer_1) == -1) die_write(); pending(); _exit(0); }