|
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 } |