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