31409766d562f233c2984b55dffb3319c6b1a3e5
17 #include "date822fmt.h"
22 #define FATAL "ezmlm-warn: fatal: "
23 void die_usage() { strerr_die1x(100,"ezmlm-warn: usage: ezmlm-warn dir"); }
24 void die_nomem() { strerr_die2x(111,FATAL
,"out of memory"); }
27 stralloc outhost
= {0};
28 stralloc outlocal
= {0};
29 stralloc mailinglist
= {0};
36 void die_read() { strerr_die6sys(111,FATAL
,"unable to read ",dir
,"/",fn
.s
,": "); }
44 char strnum
[FMT_ULONG
];
46 stralloc fnhash
= {0};
47 stralloc quoted
= {0};
51 int qqwrite(fd
,buf
,len
) int fd
; char *buf
; unsigned int len
;
53 qmail_put(&qq
,buf
,len
);
57 substdio ssqq
= SUBSTDIO_FDBUF(qqwrite
,-1,qqbuf
,sizeof(qqbuf
));
59 char date
[DATE822FMT
];
69 strerr_die4sys(111,FATAL
,"unable to open ",fn
,": ");
71 substdio_fdbuf(&sstext
,read
,fd
,textbuf
,sizeof(textbuf
));
73 if (getln(&sstext
,&line
,&match
,'\n') == -1)
74 strerr_die4sys(111,FATAL
,"unable to read ",fn
,": ");
77 qmail_put(&qq
,line
.s
,line
.len
);
93 if (fd
== -1) die_read();
94 substdio_fdbuf(&ssin
,read
,fd
,inbuf
,sizeof(inbuf
));
96 if (getln(&ssin
,&addr
,&match
,'\0') == -1) die_read();
97 if (!match
) { close(fd
); return; }
99 if (!issub(addr
.s
)) { close(fd
); /*XXX*/unlink(fn
.s
); return; }
101 cookie(hash
,"",0,"",addr
.s
,"");
102 if (!stralloc_copys(&fnhash
,"bounce/h")) die_nomem();
103 if (!stralloc_catb(&fnhash
,hash
,COOKIE
)) die_nomem();
104 if (!stralloc_0(&fnhash
)) die_nomem();
106 if (qmail_open(&qq
) == -1)
107 strerr_die2sys(111,FATAL
,"unable to run qmail-queue: ");
110 qmail_puts(&qq
,"Mailing-List: ");
111 qmail_put(&qq
,mailinglist
.s
,mailinglist
.len
);
112 qmail_puts(&qq
,"\nDate: ");
113 datetime_tai(&dt
,msgwhen
);
114 qmail_put(&qq
,date
,date822fmt(date
,&dt
));
115 qmail_puts(&qq
,"Message-ID: <");
116 qmail_put(&qq
,strnum
,fmt_ulong(strnum
,(unsigned long) msgwhen
));
118 qmail_put(&qq
,strnum
,fmt_ulong(strnum
,(unsigned long) getpid()));
119 qmail_puts(&qq
,".ezmlm-warn@");
120 qmail_put(&qq
,outhost
.s
,outhost
.len
);
121 qmail_puts(&qq
,">\nFrom: ");
122 if (!quote("ed
,&outlocal
)) die_nomem();
123 qmail_put(&qq
,quoted
.s
,quoted
.len
);
124 qmail_puts(&qq
,"-help@");
125 qmail_put(&qq
,outhost
.s
,outhost
.len
);
126 qmail_puts(&qq
,"\nTo: ");
127 if (!quote2("ed
,addr
.s
)) die_nomem();
128 qmail_put(&qq
,quoted
.s
,quoted
.len
);
129 qmail_puts(&qq
,flagw ?
"\nSubject: ezmlm probe\n\n" : "\nSubject: ezmlm warning\n\n");
132 copy(flagw ?
"text/bounce-probe" : "text/bounce-warn");
135 fdhash
= open_read(fnhash
.s
);
137 if (errno
!= error_noent
)
138 strerr_die6sys(111,FATAL
,"unable to open ",dir
,"/",fnhash
.s
,": ");
141 copy("text/bounce-num");
142 substdio_fdbuf(&sstext
,read
,fdhash
,textbuf
,sizeof(textbuf
));
143 if (substdio_copy(&ssqq
,&sstext
) < 0)
144 strerr_die6sys(111,FATAL
,"unable to read ",dir
,"/",fnhash
.s
,": ");
149 copy("text/bounce-bottom");
150 if (substdio_copy(&ssqq
,&ssin
) < 0) die_read();
153 strnum
[fmt_ulong(strnum
,when
)] = 0;
154 cookie(hash
,key
.s
,key
.len
,strnum
,addr
.s
,flagw ?
"P" : "W");
155 if (!stralloc_copy(&line
,&outlocal
)) die_nomem();
156 if (!stralloc_cats(&line
,flagw ?
"-return-probe-" : "-return-warn-")) die_nomem();
157 if (!stralloc_cats(&line
,strnum
)) die_nomem();
158 if (!stralloc_cats(&line
,".")) die_nomem();
159 if (!stralloc_catb(&line
,hash
,COOKIE
)) die_nomem();
160 if (!stralloc_cats(&line
,"-")) die_nomem();
161 i
= str_chr(addr
.s
,'@');
162 if (!stralloc_catb(&line
,addr
.s
,i
)) die_nomem();
164 if (!stralloc_cats(&line
,"=")) die_nomem();
165 if (!stralloc_cats(&line
,addr
.s
+ i
+ 1)) die_nomem();
167 if (!stralloc_cats(&line
,"@")) die_nomem();
168 if (!stralloc_cat(&line
,&outhost
)) die_nomem();
169 if (!stralloc_0(&line
)) die_nomem();
170 qmail_from(&qq
,line
.s
);
172 qmail_to(&qq
,addr
.s
);
173 if (qmail_close(&qq
) != 0)
174 strerr_die2x(111,FATAL
,"temporary qmail-queue error");
176 strnum
[fmt_ulong(strnum
,qmail_qp(&qq
))] = 0;
177 strerr_warn2("ezmlm-warn: info: qp ",strnum
,0);
180 if (unlink(fnhash
.s
) == -1)
181 if (errno
!= error_noent
)
182 strerr_die6sys(111,FATAL
,"unable to remove ",dir
,"/",fnhash
.s
,": ");
184 if (unlink(fn
.s
) == -1)
185 strerr_die6sys(111,FATAL
,"unable to remove ",dir
,"/",fn
.s
,": ");
194 unsigned long bouncedate
;
199 when
= (unsigned long) now();
202 if (!dir
) die_usage();
204 if (chdir(dir
) == -1)
205 strerr_die4sys(111,FATAL
,"unable to switch to ",dir
,": ");
207 switch(slurp("key",&key
,32)) {
209 strerr_die4sys(111,FATAL
,"unable to read ",dir
,"/key: ");
211 strerr_die3x(100,FATAL
,dir
,"/key does not exist");
213 getconf_line(&outhost
,"outhost",1,FATAL
,dir
);
214 getconf_line(&outlocal
,"outlocal",1,FATAL
,dir
);
215 getconf_line(&mailinglist
,"mailinglist",1,FATAL
,dir
);
217 fdlock
= open_append("lockbounce");
219 strerr_die4sys(111,FATAL
,"unable to open ",dir
,"/lockbounce: ");
220 if (lock_ex(fdlock
) == -1)
221 strerr_die4sys(111,FATAL
,"unable to lock ",dir
,"/lockbounce: ");
223 bouncedir
= opendir("bounce");
225 strerr_die4sys(111,FATAL
,"unable to open ",dir
,"/bounce: ");
227 while (d
= readdir(bouncedir
)) {
228 if (str_equal(d
->d_name
,".")) continue;
229 if (str_equal(d
->d_name
,"..")) continue;
231 if (!stralloc_copys(&fn
,"bounce/")) die_nomem();
232 if (!stralloc_cats(&fn
,d
->d_name
)) die_nomem();
233 if (!stralloc_0(&fn
)) die_nomem();
235 if (stat(fn
.s
,&st
) == -1) {
236 if (errno
== error_noent
) continue;
237 strerr_die6sys(111,FATAL
,"unable to stat ",dir
,"/",fn
.s
,": ");
240 if (when
> st
.st_mtime
+ 3000000)
241 if (unlink(fn
.s
) == -1)
242 strerr_die6sys(111,FATAL
,"unable to remove ",dir
,"/",fn
.s
,": ");
244 if ((d
->d_name
[0] == 'd') || (d
->d_name
[0] == 'w')) {
245 scan_ulong(d
->d_name
+ 1,&bouncedate
);
246 if (when
> bouncedate
+ 1000000)
247 doit(d
->d_name
[0] == 'w');