#include #include "buffer.h" #include "case.h" #include "exit.h" #include "fmt.h" #include "genalloc.h" #include "getln.h" #include "logmsg.h" #include "scan.h" #include "str.h" #include "stralloc.h" #define WHO "matchup" static void nomem() { logmsg(WHO, 111, FATAL, "out of memory"); } static void die_read() { logmsg(WHO, 110, ERROR, "unable to read input: "); } static void die_write() { logmsg(WHO, 110, ERROR, "unable to write output: "); } static void die_write5() { logmsg(WHO, 111, FATAL, "unable to write fd 5: "); } static void out(char *buf, int len) { if (buffer_put(buffer_1, buf, len) == -1) die_write(); } static 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)); static void out5(char *buf, int len) { if (buffer_put(&bo5, buf, len) == -1) die_write5(); } static 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}; static int msg_find(unsigned long m) { int i; for (i = 0; i < nummsg; ++i) if (msg.u[i] == m) return i; return -1; } static 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; } static 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}; static int del_find(unsigned long d) { int i; for (i = 0; i < numdel; ++i) if (del.u[i] == d) return i; return -1; } static 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; } static 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}; static 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]; static void clear() { while (numdel > 0) del_kill(0); garbage(); } static 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]; } static 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(); } static 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(); } static 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(); } static 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]; } static 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]); } static 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); }