summaryrefslogtreecommitdiff
path: root/src/qmail-qread.c
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-03 15:48:04 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-03 15:48:04 +0200
commit89b7b67a13ebb7965cc7f13ad0595e2194a2d34c (patch)
tree25efd77a90ae87236e6730d8ea3846bbe0fd126f /src/qmail-qread.c
add sqmail-4.2.29asqmail-4.2
Diffstat (limited to 'src/qmail-qread.c')
-rw-r--r--src/qmail-qread.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/qmail-qread.c b/src/qmail-qread.c
new file mode 100644
index 0000000..888c14a
--- /dev/null
+++ b/src/qmail-qread.c
@@ -0,0 +1,162 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "stralloc.h"
+#include "fmt.h"
+#include "str.h"
+#include "getln.h"
+#include "fmtqfn.h"
+#include "readsubdir.h"
+#include "auto_qmail.h"
+#include "open.h"
+#include "datetime.h"
+#include "date822fmt.h"
+#include "error.h"
+#include "exit.h"
+
+readsubdir rs;
+
+void die(int n) { buffer_flush(buffer_1); _exit(n); }
+
+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");
+}
+
+void die_nomem() { buffer_puts(buffer_1,"fatal: out of memory\n"); die(111); }
+void die_chdir() { warn("fatal: unable to chdir",""); die(110); }
+void die_opendir(fn) char *fn; { warn("fatal: unable to opendir ",fn); die(110); }
+
+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;
+
+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};
+
+void out(char *s,unsigned int n)
+{
+ while (n > 0) {
+ buffer_put(buffer_1,((*s >= 32) && (*s <= 126)) ? s : "_",1);
+ --n;
+ ++s;
+ }
+}
+void outs(char *s) { out(s,str_len(s)); }
+void outok(char *s) { buffer_puts(buffer_1,s); }
+
+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);
+}