diff options
author | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-03 15:48:04 +0200 |
---|---|---|
committer | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-03 15:48:04 +0200 |
commit | 89b7b67a13ebb7965cc7f13ad0595e2194a2d34c (patch) | |
tree | 25efd77a90ae87236e6730d8ea3846bbe0fd126f /src/matchup.c |
add sqmail-4.2.29asqmail-4.2
Diffstat (limited to 'src/matchup.c')
-rw-r--r-- | src/matchup.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/src/matchup.c b/src/matchup.c new file mode 100644 index 0000000..047ea65 --- /dev/null +++ b/src/matchup.c @@ -0,0 +1,489 @@ +#include <unistd.h> +#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); +} |