nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

qmail-qread.c (3830B)


      1 #include <sys/types.h>
      2 #include <sys/stat.h>
      3 #include "stralloc.h"
      4 #include "substdio.h"
      5 #include "subfd.h"
      6 #include "fmt.h"
      7 #include "str.h"
      8 #include "getln.h"
      9 #include "fmtqfn.h"
     10 #include "readsubdir.h"
     11 #include "auto_qmail.h"
     12 #include "open.h"
     13 #include "datetime.h"
     14 #include "date822fmt.h"
     15 #include "noreturn.h"
     16 #include "readwrite.h"
     17 #include "error.h"
     18 #include "exit.h"
     19 
     20 readsubdir rs;
     21 
     22 void _noreturn_ die(n) int n; { substdio_flush(subfdout); _exit(n); }
     23 
     24 void warn(s1,s2) char *s1; char *s2;
     25 {
     26  char *x;
     27  x = error_str(errno);
     28  substdio_puts(subfdout,s1);
     29  substdio_puts(subfdout,s2);
     30  substdio_puts(subfdout,": ");
     31  substdio_puts(subfdout,x);
     32  substdio_puts(subfdout,"\n");
     33 }
     34 
     35 void _noreturn_ die_nomem() { substdio_puts(subfdout,"fatal: out of memory\n"); die(111); }
     36 void _noreturn_ die_chdir() { warn("fatal: unable to chdir",""); die(111); }
     37 void _noreturn_ die_opendir(char *fn) { warn("fatal: unable to opendir ",fn); die(111); }
     38 
     39 void err(id) unsigned long id;
     40 {
     41  char foo[FMT_ULONG];
     42  foo[fmt_ulong(foo,id)] = 0;
     43  warn("warning: trouble with #",foo);
     44 }
     45 
     46 char fnmess[FMTQFN];
     47 char fninfo[FMTQFN];
     48 char fnlocal[FMTQFN];
     49 char fnremote[FMTQFN];
     50 char fnbounce[FMTQFN];
     51 
     52 char inbuf[1024];
     53 stralloc sender = {0};
     54 
     55 unsigned long id;
     56 datetime_sec qtime;
     57 int flagbounce;
     58 unsigned long size;
     59 
     60 unsigned int fmtstats(s)
     61 char *s;
     62 {
     63  struct datetime dt;
     64  unsigned int len;
     65  unsigned int i;
     66 
     67  len = 0;
     68  datetime_tai(&dt,qtime);
     69  i = date822fmt(s,&dt) - 7/*XXX*/; len += i; if (s) s += i;
     70  i = fmt_str(s," GMT  #"); len += i; if (s) s += i;
     71  i = fmt_ulong(s,id); len += i; if (s) s += i;
     72  i = fmt_str(s,"  "); len += i; if (s) s += i;
     73  i = fmt_ulong(s,size); len += i; if (s) s += i;
     74  i = fmt_str(s,"  <"); len += i; if (s) s += i;
     75  i = fmt_str(s,sender.s + 1); len += i; if (s) s += i;
     76  i = fmt_str(s,"> "); len += i; if (s) s += i;
     77  if (flagbounce)
     78   {
     79    i = fmt_str(s," bouncing"); len += i; if (s) s += i;
     80   }
     81 
     82  return len;
     83 }
     84 
     85 stralloc stats = {0};
     86 
     87 void out(s,n) char *s; unsigned int n;
     88 {
     89  while (n > 0)
     90   {
     91    substdio_put(subfdout,((*s >= 32) && (*s <= 126)) ? s : "_",1);
     92    --n;
     93    ++s;
     94   }
     95 }
     96 void outs(s) char *s; { out(s,str_len(s)); }
     97 void outok(s) char *s; { substdio_puts(subfdout,s); }
     98 
     99 void putstats()
    100 {
    101  if (!stralloc_ready(&stats,fmtstats(FMT_LEN))) die_nomem();
    102  stats.len = fmtstats(stats.s);
    103  out(stats.s,stats.len);
    104  outok("\n");
    105 }
    106 
    107 stralloc line = {0};
    108 
    109 int main(void)
    110 {
    111  int channel;
    112  int match;
    113  struct stat st;
    114  int fd;
    115  substdio ss;
    116  int x;
    117 
    118  if (chdir(auto_qmail) == -1) die_chdir();
    119  if (chdir("queue") == -1) die_chdir();
    120  readsubdir_init(&rs,"info",die_opendir);
    121 
    122  while ((x = readsubdir_next(&rs,&id)))
    123    if (x > 0)
    124     {
    125      fmtqfn(fnmess,"mess/",id,1);
    126      fmtqfn(fninfo,"info/",id,1);
    127      fmtqfn(fnlocal,"local/",id,1);
    128      fmtqfn(fnremote,"remote/",id,1);
    129      fmtqfn(fnbounce,"bounce/",id,0);
    130 
    131      if (stat(fnmess,&st) == -1) { err(id); continue; }
    132      size = st.st_size;
    133      flagbounce = !stat(fnbounce,&st);
    134 
    135      fd = open_read(fninfo);
    136      if (fd == -1) { err(id); continue; }
    137      substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
    138      if (getln(&ss,&sender,&match,0) == -1) die_nomem();
    139      if (fstat(fd,&st) == -1) { close(fd); err(id); continue; }
    140      close(fd);
    141      qtime = st.st_mtime;
    142 
    143      putstats();
    144 
    145      for (channel = 0;channel < 2;++channel)
    146       {
    147        fd = open_read(channel ? fnremote : fnlocal);
    148        if (fd == -1)
    149 	{
    150 	 if (errno != error_noent)
    151 	   err(id);
    152 	}
    153        else
    154         {
    155          for (;;)
    156 	  {
    157 	   if (getln(&ss,&line,&match,0) == -1) die_nomem();
    158 	   if (!match) break;
    159 	   switch(line.s[0])
    160 	    {
    161 	     case 'D':
    162 	       outok("  done");
    163 	     case 'T':
    164 	       outok(channel ? "\tremote\t" : "\tlocal\t");
    165 	       outs(line.s + 1);
    166 	       outok("\n");
    167 	       break;
    168 	    }
    169 	  }
    170          close(fd);
    171         }
    172       }
    173     }
    174 
    175  die(0);
    176 }