20 stralloc filenames
= {0};
26 stralloc ufline
= {0};
28 char inbuf
[SUBSTDIO_INSIZE
];
29 char outbuf
[SUBSTDIO_OUTSIZE
];
31 #define FATAL "maildir2mbox: fatal: "
32 #define WARNING "maildir2mbox: warning: "
34 void die_nomem() { strerr_die2x(111,FATAL
,"out of memory"); }
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");
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
);
60 if (!prioq_min(&pq
,&pe
)) _exit(0); /* nothing new */
62 fdlock
= open_append(mbox
);
64 strerr_die4sys(111,FATAL
,"unable to lock ",mbox
,": ");
65 if (lock_ex(fdlock
) == -1)
66 strerr_die4sys(111,FATAL
,"unable to lock ",mbox
,": ");
68 fdoldmbox
= open_read(mbox
);
70 strerr_die4sys(111,FATAL
,"unable to read ",mbox
,": ");
72 fdnewmbox
= open_trunc(mboxtmp
);
74 strerr_die4sys(111,FATAL
,"unable to create ",mboxtmp
,": ");
76 substdio_fdbuf(&ssin
,read
,fdoldmbox
,inbuf
,sizeof(inbuf
));
77 substdio_fdbuf(&ssout
,write
,fdnewmbox
,outbuf
,sizeof(outbuf
));
79 switch(substdio_copy(&ssout
,&ssin
))
81 case -2: strerr_die4sys(111,FATAL
,"unable to read ",mbox
,": ");
82 case -3: strerr_die4sys(111,FATAL
,"unable to write to ",mboxtmp
,": ");
85 while (prioq_min(&pq
,&pe
))
88 if (!prioq_insert(&pq2
,&pe
)) die_nomem();
90 fd
= open_read(filenames
.s
+ pe
.id
);
92 strerr_die4sys(111,FATAL
,"unable to read $MAILDIR/",filenames
.s
+ pe
.id
,": ");
93 substdio_fdbuf(&ssin
,read
,fd
,inbuf
,sizeof(inbuf
));
95 if (getln(&ssin
,&line
,&match
,'\n') != 0)
96 strerr_die4sys(111,FATAL
,"unable to read $MAILDIR/",filenames
.s
+ pe
.id
,": ");
98 if (!stralloc_copys(&ufline
,"From XXX ")) die_nomem();
100 if (stralloc_starts(&line
,"Return-Path: <"))
102 if (line
.s
[14] == '>')
104 if (!stralloc_copys(&ufline
,"From MAILER-DAEMON ")) die_nomem();
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
++] = '-';
115 ufline
.s
[ufline
.len
++] = line
.s
[i
];
116 if (!stralloc_cats(&ufline
," ")) die_nomem();
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
,": ");
123 while (match
&& line
.len
)
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
,": ");
132 if (substdio_puts(&ssout
,"\n") == -1)
133 strerr_die4sys(111,FATAL
,"unable to write to ",mboxtmp
,": ");
136 if (getln(&ssin
,&line
,&match
,'\n') != 0)
137 strerr_die4sys(111,FATAL
,"unable to read $MAILDIR/",filenames
.s
+ pe
.id
,": ");
139 if (substdio_puts(&ssout
,"\n"))
140 strerr_die4sys(111,FATAL
,"unable to write to ",mboxtmp
,": ");
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
);
154 while (prioq_min(&pq2
,&pe
))
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
);