s/qmail 4.2.29a
Next generation secure email transport
Loading...
Searching...
No Matches
maildir2mbox.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/stat.h>
3#include "env.h"
4#include "genalloc.h"
5#include "stralloc.h"
6#include "buffer.h"
7#include "getln.h"
8#include "logmsg.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#include "prioq.h"
17
18char *mbox;
19char *mboxtmp;
20
21int rename(const char *,const char *); // stdio.h
22
23stralloc filenames = {0};
24prioq pq = {0};
25prioq pq2 = {0};
26
27stralloc line = {0};
28
29stralloc ufline = {0};
30
31char inbuf[BUFFER_INSIZE];
32char outbuf[BUFFER_OUTSIZE];
33
34#define WHO "maildir2mbox"
35
36void die_nomem() { logmsg(WHO,111,FATAL,"out of memory"); }
37
38int main()
39{
40 buffer bi;
41 buffer bo;
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) logmsg(WHO,111,FATAL,"MAIL not set");
53 mboxtmp = env_get("MAILTMP");
54 if (!mboxtmp) logmsg(WHO,111,FATAL,"MAILTMP not set");
55
56 if (maildir_chdir() == -1)
57 logmsg(WHO,110,FATAL,"Can't changet maildir");
59 if (maildir_scan(&pq,&filenames,1,1) == -1)
60 logmsg(WHO,112,FATAL,"Can't read maidir");
61
62 if (!prioq_min(&pq,&pe)) _exit(0); /* nothing new */
63
64 fdlock = open_append(mbox);
65 if (fdlock == -1)
66 logmsg(WHO,111,FATAL,B("unable to lock: ",mbox));
67 if (lock_ex(fdlock) == -1)
68 logmsg(WHO,111,FATAL,B("unable to lock: ",mbox));
69
70 fdoldmbox = open_read(mbox);
71 if (fdoldmbox == -1)
72 logmsg(WHO,112,FATAL,B("unable to read: ",mbox));
73
74 fdnewmbox = open_trunc(mboxtmp);
75 if (fdnewmbox == -1)
76 logmsg(WHO,112,FATAL,B("unable to create: ",mboxtmp));
77
78 buffer_init(&bi,read,fdoldmbox,inbuf,sizeof(inbuf));
79 buffer_init(&bo,write,fdnewmbox,outbuf,sizeof(outbuf));
80
81 switch (buffer_copy(&bo,&bi)) {
82 case -2: logmsg(WHO,112,FATAL,B("unable to read: ",mbox));
83 case -3: logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
84 }
85
86 while (prioq_min(&pq,&pe)) {
88 if (!prioq_insert(&pq2,&pe)) die_nomem();
89
90 fd = open_read(filenames.s + pe.id);
91 if (fd == -1)
92 logmsg(WHO,112,FATAL,B("unable to read: $MAILDIR/",filenames.s + pe.id));
93 buffer_init(&bi,read,fd,inbuf,sizeof(inbuf));
94
95 if (getln(&bi,&line,&match,'\n') != 0)
96 logmsg(WHO,112,FATAL,B("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 if (line.s[14] == '>') {
102 if (!stralloc_copys(&ufline,"From MAILER-DAEMON ")) die_nomem();
103 } else {
104 int i;
105 if (!stralloc_ready(&ufline,line.len)) die_nomem();
106 if (!stralloc_copys(&ufline,"From ")) die_nomem();
107
108 for (i = 14;i < line.len - 2;++i)
109 if ((line.s[i] == ' ') || (line.s[i] == '\t'))
110 ufline.s[ufline.len++] = '-';
111 else
112 ufline.s[ufline.len++] = line.s[i];
113 if (!stralloc_cats(&ufline," ")) die_nomem();
114 }
115 }
116 if (!stralloc_cats(&ufline,myctime(pe.dt))) die_nomem();
117 if (buffer_put(&bo,ufline.s,ufline.len) == -1)
118 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
119
120 while (match && line.len) {
121 if (gfrom(line.s,line.len))
122 if (buffer_puts(&bo,">") == -1)
123 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
124 if (buffer_put(&bo,line.s,line.len) == -1)
125 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
126 if (!match) {
127 if (buffer_puts(&bo,"\n") == -1)
128 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
129 break;
130 }
131 if (getln(&bi,&line,&match,'\n') != 0)
132 logmsg(WHO,112,FATAL,B("unable to read: $MAILDIR/",filenames.s + pe.id));
133 }
134 if (buffer_puts(&bo,"\n"))
135 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
136
137 close(fd);
138 }
139
140 if (buffer_flush(&bo) == -1)
141 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
142 if (fsync(fdnewmbox) == -1)
143 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
144 if (close(fdnewmbox) == -1) /* NFS dorks */
145 logmsg(WHO,112,FATAL,B("unable to write to: ",mboxtmp));
146 if (rename(mboxtmp,mbox) == -1)
147 logmsg(WHO,112,FATAL,B("unable to move ",mboxtmp," to: ",mbox));
148
149 while (prioq_min(&pq2,&pe)) {
151 if (unlink(filenames.s + pe.id) == -1)
152 logmsg(WHO,0,WARN,B("$MAILDIR/",filenames.s + pe.id," will be delivered twice; unable to unlink"));
153 }
154
155 _exit(0);
156}
buffer bo
Definition: columnt.c:14
buffer bi
Definition: condredirect.c:23
int stralloc_copys(stralloc *, char const *)
void _exit()
int gfrom(char *s, int len)
Definition: gfrom.c:4
stralloc filenames
Definition: maildir2mbox.c:23
void die_nomem()
Definition: maildir2mbox.c:36
char inbuf[BUFFER_INSIZE]
Definition: maildir2mbox.c:31
char * mbox
Definition: maildir2mbox.c:18
int rename(const char *, const char *)
prioq pq2
Definition: maildir2mbox.c:25
char * mboxtmp
Definition: maildir2mbox.c:19
prioq pq
Definition: maildir2mbox.c:24
stralloc ufline
Definition: maildir2mbox.c:29
stralloc line
Definition: maildir2mbox.c:27
char outbuf[BUFFER_OUTSIZE]
Definition: maildir2mbox.c:32
#define WHO
Definition: maildir2mbox.c:34
int main()
Definition: maildir2mbox.c:38
int maildir_chdir(void)
Definition: maildir.c:16
int maildir_scan(prioq *, stralloc *, int, int)
Definition: maildir.c:83
void maildir_clean(stralloc *)
Definition: maildir.c:27
int match
Definition: matchup.c:195
char * myctime(datetime_sec)
Definition: myctime.c:14
void prioq_delmin()
int prioq_min()
int fd
Definition: prioq.h:7
datetime_sec dt
Definition: prioq.h:7
unsigned long id
Definition: prioq.h:7
void write()