#include #include #include #include "error.h" #include "exit.h" #include "fmt.h" #include "getln.h" #include "open.h" #include "str.h" #include "stralloc.h" #include "date822fmt.h" #include "datetime.h" #include "fmtqfn.h" #include "readsubdir.h" #ifdef USE_CONFIG #include "fehsqm-config.h" #else #include "auto_qmail.h" #endif readsubdir rs; static void die(int n) { buffer_flush(buffer_1); _exit(n); } static void warn(char *s1, char *s2) { char *x; x = error_str(errno); buffer_puts(buffer_1, s1); buffer_puts(buffer_1, s2); buffer_puts(buffer_1, ": "); buffer_puts(buffer_1, x); buffer_puts(buffer_1, "\n"); } static void die_nomem() { buffer_puts(buffer_1, "fatal: out of memory\n"); die(111); } static void die_chdir() { warn("fatal: unable to chdir", ""); die(110); } static void die_opendir(char *fn) { warn("fatal: unable to opendir ", fn); die(110); } static void err(unsigned long id) { char foo[FMT_ULONG]; foo[fmt_ulong(foo, id)] = 0; warn("warning: trouble with #", foo); } char fnmess[FMTQFN]; char fninfo[FMTQFN]; char fnlocal[FMTQFN]; char fnremote[FMTQFN]; char fnbounce[FMTQFN]; char inbuf[1024]; stralloc sender = {0}; unsigned long id; datetime_sec qtime; int flagbounce; unsigned long size; static unsigned int fmtstats(char *s) { struct datetime dt; unsigned int len; unsigned int i; len = 0; datetime_tai(&dt, qtime); i = date822fmt(s, &dt) - 7 /*XXX*/; len += i; if (s) s += i; i = fmt_str(s, " GMT #"); len += i; if (s) s += i; i = fmt_ulong(s, id); len += i; if (s) s += i; i = fmt_str(s, " "); len += i; if (s) s += i; i = fmt_ulong(s, size); len += i; if (s) s += i; i = fmt_str(s, " <"); len += i; if (s) s += i; i = fmt_str(s, sender.s + 1); len += i; if (s) s += i; i = fmt_str(s, "> "); len += i; if (s) s += i; if (flagbounce) { i = fmt_str(s, " bouncing"); len += i; if (s) s += i; } return len; } stralloc stats = {0}; static void out(char *s, unsigned int n) { while (n > 0) { buffer_put(buffer_1, ((*s >= 32) && (*s <= 126)) ? s : "_", 1); --n; ++s; } } static void outs(char *s) { out(s, str_len(s)); } static void outok(char *s) { buffer_puts(buffer_1, s); } static void putstats() { if (!stralloc_ready(&stats, fmtstats(FMT_LEN))) die_nomem(); stats.len = fmtstats(stats.s); out(stats.s, stats.len); outok("\n"); } stralloc line = {0}; int main() { int channel; int match; struct stat st; int fd; buffer b; int x; if (chdir(auto_qmail) == -1) die_chdir(); if (chdir("queue") == -1) die_chdir(); readsubdir_init(&rs, "info", die_opendir); while ((x = readsubdir_next(&rs, &id))) { if (x > 0) { fmtqfn(fnmess, "mess/", id, 1); fmtqfn(fninfo, "info/", id, 1); fmtqfn(fnlocal, "local/", id, 1); fmtqfn(fnremote, "remote/", id, 1); fmtqfn(fnbounce, "bounce/", id, 0); if (stat(fnmess, &st) == -1) { err(id); continue; } size = st.st_size; flagbounce = !stat(fnbounce, &st); fd = open_read(fninfo); if (fd == -1) { err(id); continue; } buffer_init(&b, read, fd, inbuf, sizeof(inbuf)); if (getln(&b, &sender, &match, 0) == -1) die_nomem(); if (fstat(fd, &st) == -1) { close(fd); err(id); continue; } close(fd); qtime = st.st_mtime; putstats(); for (channel = 0; channel < 2; ++channel) { fd = open_read(channel ? fnremote : fnlocal); if (fd == -1) { if (errno != ENOENT) err(id); } else { for (;;) { if (getln(&b, &line, &match, 0) == -1) die_nomem(); if (!match) break; switch (line.s[0]) { case 'D': outok(" done"); case 'T': outok(channel ? "\tremote\t" : "\tlocal\t"); outs(line.s + 1); outok("\n"); break; } } close(fd); } } } } die(0); }