nightmaremail

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

maildir2mbox.c (4606B)


      1 #include <sys/stat.h>
      2 #include "readwrite.h"
      3 #include "prioq.h"
      4 #include "env.h"
      5 #include "stralloc.h"
      6 #include "subfd.h"
      7 #include "substdio.h"
      8 #include "getln.h"
      9 #include "error.h"
     10 #include "open.h"
     11 #include "lock.h"
     12 #include "gfrom.h"
     13 #include "str.h"
     14 #include "myctime.h"
     15 #include "maildir.h"
     16 
     17 extern int rename(const char *, const char *);
     18 
     19 char *mbox;
     20 char *mboxtmp;
     21 
     22 stralloc filenames = {0};
     23 prioq pq = {0};
     24 prioq pq2 = {0};
     25 
     26 stralloc line = {0};
     27 
     28 stralloc ufline = {0};
     29 
     30 char inbuf[SUBSTDIO_INSIZE];
     31 char outbuf[SUBSTDIO_OUTSIZE];
     32 
     33 #define FATAL "maildir2mbox: fatal: "
     34 #define WARNING "maildir2mbox: warning: "
     35 
     36 void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); }
     37 
     38 int main(void)
     39 {
     40  substdio ssin;
     41  substdio ssout;
     42  struct prioq_elt pe;
     43  int fdoldmbox;
     44  int fdnewmbox;
     45  int fd;
     46  int match;
     47  int fdlock;
     48 
     49  umask(077);
     50 
     51  mbox = env_get("MAIL");
     52  if (!mbox) strerr_die2x(111,FATAL,"MAIL not set");
     53  mboxtmp = env_get("MAILTMP");
     54  if (!mboxtmp) strerr_die2x(111,FATAL,"MAILTMP not set");
     55 
     56  if (maildir_chdir() == -1)
     57    strerr_die1(111,FATAL,&maildir_chdir_err);
     58  maildir_clean(&filenames);
     59  if (maildir_scan(&pq,&filenames,1,1) == -1)
     60    strerr_die1(111,FATAL,&maildir_scan_err);
     61 
     62  if (!prioq_min(&pq,&pe)) return 0; /* nothing new */
     63 
     64  fdlock = open_append(mbox);
     65  if (fdlock == -1)
     66    strerr_die4sys(111,FATAL,"unable to lock ",mbox,": ");
     67  if (lock_ex(fdlock) == -1)
     68    strerr_die4sys(111,FATAL,"unable to lock ",mbox,": ");
     69 
     70  fdoldmbox = open_read(mbox);
     71  if (fdoldmbox == -1)
     72    strerr_die4sys(111,FATAL,"unable to read ",mbox,": ");
     73 
     74  fdnewmbox = open_trunc(mboxtmp);
     75  if (fdnewmbox == -1)
     76    strerr_die4sys(111,FATAL,"unable to create ",mboxtmp,": ");
     77 
     78  substdio_fdbuf(&ssin,read,fdoldmbox,inbuf,sizeof(inbuf));
     79  substdio_fdbuf(&ssout,write,fdnewmbox,outbuf,sizeof(outbuf));
     80 
     81  switch(substdio_copy(&ssout,&ssin))
     82   {
     83    case -2: strerr_die4sys(111,FATAL,"unable to read ",mbox,": ");
     84    case -3: strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
     85   }
     86 
     87  while (prioq_min(&pq,&pe))
     88   {
     89    prioq_delmin(&pq);
     90    if (!prioq_insert(&pq2,&pe)) die_nomem();
     91 
     92    fd = open_read(filenames.s + pe.id);
     93    if (fd == -1)
     94      strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": ");
     95    substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
     96 
     97    if (getln(&ssin,&line,&match,'\n') != 0)
     98      strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": ");
     99    
    100    if (!stralloc_copys(&ufline,"From XXX ")) die_nomem();
    101    if (match)
    102      if (stralloc_starts(&line,"Return-Path: <"))
    103       {
    104        if (line.s[14] == '>')
    105 	{
    106          if (!stralloc_copys(&ufline,"From MAILER-DAEMON ")) die_nomem();
    107 	}
    108        else
    109 	{
    110 	 int i;
    111          if (!stralloc_ready(&ufline,line.len)) die_nomem();
    112          if (!stralloc_copys(&ufline,"From ")) die_nomem();
    113 	 for (i = 14;i < line.len - 2;++i)
    114 	   if ((line.s[i] == ' ') || (line.s[i] == '\t'))
    115 	     ufline.s[ufline.len++] = '-';
    116 	   else
    117 	     ufline.s[ufline.len++] = line.s[i];
    118          if (!stralloc_cats(&ufline," ")) die_nomem();
    119 	}
    120       }
    121    if (!stralloc_cats(&ufline,myctime(pe.dt))) die_nomem();
    122    if (substdio_put(&ssout,ufline.s,ufline.len) == -1)
    123      strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    124 
    125    while (match && line.len)
    126     {
    127      if (gfrom(line.s,line.len))
    128        if (substdio_puts(&ssout,">") == -1)
    129          strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    130      if (substdio_put(&ssout,line.s,line.len) == -1)
    131        strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    132      if (!match)
    133       {
    134        if (substdio_puts(&ssout,"\n") == -1)
    135          strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    136        break;
    137       }
    138      if (getln(&ssin,&line,&match,'\n') != 0)
    139        strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": ");
    140     }
    141    if (substdio_puts(&ssout,"\n"))
    142      strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    143 
    144    close(fd);
    145   }
    146 
    147  if (substdio_flush(&ssout) == -1)
    148    strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    149  if (fsync(fdnewmbox) == -1)
    150    strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    151  if (close(fdnewmbox) == -1) /* NFS dorks */
    152    strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": ");
    153  if (rename(mboxtmp,mbox) == -1)
    154    strerr_die6(111,FATAL,"unable to move ",mboxtmp," to ",mbox,": ",&strerr_sys);
    155  
    156  while (prioq_min(&pq2,&pe))
    157   {
    158    prioq_delmin(&pq2);
    159    if (unlink(filenames.s + pe.id) == -1)
    160      strerr_warn4(WARNING,"$MAILDIR/",filenames.s + pe.id," will be delivered twice; unable to unlink: ",&strerr_sys);
    161   }
    162 
    163  return 0;
    164 }