Commit | Line | Data |
---|---|---|
f8beb284 MW |
1 | /*$Id: ezmlm-return.c,v 1.26 1999/08/07 20:50:52 lindberg Exp $*/ |
2 | /*$Name: ezmlm-idx-040 $*/ | |
3 | #include <sys/types.h> | |
4 | #include "direntry.h" | |
5b62e993 MW |
5 | #include "stralloc.h" |
6 | #include "str.h" | |
7 | #include "env.h" | |
8 | #include "sig.h" | |
9 | #include "slurp.h" | |
10 | #include "getconf.h" | |
11 | #include "strerr.h" | |
12 | #include "byte.h" | |
13 | #include "case.h" | |
14 | #include "getln.h" | |
15 | #include "substdio.h" | |
16 | #include "error.h" | |
17 | #include "quote.h" | |
18 | #include "readwrite.h" | |
19 | #include "fmt.h" | |
20 | #include "now.h" | |
21 | #include "cookie.h" | |
22 | #include "subscribe.h" | |
f8beb284 MW |
23 | #include "errtxt.h" |
24 | #include "idx.h" | |
5b62e993 MW |
25 | |
26 | #define FATAL "ezmlm-return: fatal: " | |
f8beb284 MW |
27 | #define INFO "ezmlm-return: info: " |
28 | void die_usage() | |
29 | { strerr_die1x(100,"ezmlm-return: usage: ezmlm-return [-dD] dir"); } | |
30 | void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); } | |
5b62e993 MW |
31 | void die_badaddr() |
32 | { | |
f8beb284 | 33 | strerr_die2x(100,FATAL,ERR_BAD_RETURN_ADDRESS); |
5b62e993 MW |
34 | } |
35 | void die_trash() | |
36 | { | |
f8beb284 | 37 | strerr_die2x(99,INFO,"trash address"); |
5b62e993 MW |
38 | } |
39 | ||
40 | char outbuf[1024]; | |
41 | substdio ssout; | |
42 | char inbuf[1024]; | |
43 | substdio ssin; | |
44 | ||
45 | char strnum[FMT_ULONG]; | |
46 | char hash[COOKIE]; | |
47 | char hashcopy[COOKIE]; | |
f8beb284 | 48 | char *hashp = (char *) 0; |
5b62e993 | 49 | unsigned long cookiedate; |
f8beb284 MW |
50 | unsigned long addrno = 0L; |
51 | unsigned long addrno1 = 0L; | |
52 | stralloc fndir = {0}; | |
5b62e993 MW |
53 | stralloc fndate = {0}; |
54 | stralloc fndatenew = {0}; | |
55 | stralloc fnhash = {0}; | |
56 | stralloc fnhashnew = {0}; | |
f8beb284 | 57 | void *psql = (void *) 0; |
5b62e993 MW |
58 | |
59 | stralloc quoted = {0}; | |
f8beb284 | 60 | stralloc ddir = {0}; |
5b62e993 | 61 | char *sender; |
f8beb284 MW |
62 | char *dir; |
63 | char *workdir; | |
5b62e993 MW |
64 | |
65 | void die_hashnew() | |
f8beb284 | 66 | { strerr_die4sys(111,FATAL,ERR_WRITE,fnhashnew.s,": "); } |
5b62e993 | 67 | void die_datenew() |
f8beb284 | 68 | { strerr_die4sys(111,FATAL,ERR_WRITE,fndatenew.s,": "); } |
5b62e993 | 69 | void die_msgin() |
f8beb284 MW |
70 | { strerr_die2sys(111,FATAL,ERR_READ_INPUT); } |
71 | ||
72 | void makedir(s) | |
73 | char *s; | |
74 | { | |
75 | if (mkdir(s,0755) == -1) | |
76 | if (errno != error_exist) | |
77 | strerr_die4x(111,FATAL,ERR_CREATE,s,": "); | |
78 | } | |
5b62e993 MW |
79 | |
80 | void dowit(addr,when,bounce) | |
81 | char *addr; | |
82 | unsigned long when; | |
83 | stralloc *bounce; | |
84 | { | |
85 | int fd; | |
f8beb284 MW |
86 | unsigned int wpos; |
87 | unsigned long wdir,wfile; | |
5b62e993 | 88 | |
f8beb284 | 89 | if (!issub(workdir,addr,(char *) 0,FATAL)) return; |
5b62e993 | 90 | |
f8beb284 MW |
91 | if (!stralloc_copys(&fndate,workdir)) die_nomem(); |
92 | if (!stralloc_cats(&fndate,"/bounce/d")) die_nomem(); | |
93 | if (!stralloc_0(&fndate)) die_nomem(); | |
94 | fndate.s[fndate.len - 1] = '/'; /* replace '\0' */ | |
95 | wpos = fndate.len - 1; | |
96 | wdir = when / 10000; | |
97 | wfile = when - 10000 * wdir; | |
98 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,wdir))) die_nomem(); | |
99 | if (!stralloc_0(&fndate)) die_nomem(); | |
100 | makedir(fndate.s); | |
101 | --fndate.len; /* remove terminal '\0' */ | |
102 | if (!stralloc_cats(&fndate,"/w")) die_nomem(); | |
103 | wpos = fndate.len - 1; | |
104 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,wfile))) die_nomem(); | |
5b62e993 | 105 | if (!stralloc_cats(&fndate,".")) die_nomem(); |
f8beb284 MW |
106 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,(unsigned long) getpid()))) |
107 | die_nomem(); | |
5b62e993 MW |
108 | if (!stralloc_0(&fndate)) die_nomem(); |
109 | if (!stralloc_copy(&fndatenew,&fndate)) die_nomem(); | |
f8beb284 | 110 | fndatenew.s[wpos] = 'W'; |
5b62e993 MW |
111 | |
112 | fd = open_trunc(fndatenew.s); | |
113 | if (fd == -1) die_datenew(); | |
114 | substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); | |
115 | if (substdio_puts(&ssout,addr) == -1) die_datenew(); | |
116 | if (substdio_put(&ssout,"",1) == -1) die_datenew(); | |
117 | if (substdio_puts(&ssout,"Return-Path: <") == -1) die_datenew(); | |
118 | if (!quote2("ed,sender)) die_nomem(); | |
119 | if (substdio_put(&ssout,quoted.s,quoted.len) == -1) die_datenew(); | |
120 | if (substdio_puts(&ssout,">\n") == -1) die_datenew(); | |
121 | if (substdio_put(&ssout,bounce->s,bounce->len) == -1) die_datenew(); | |
122 | if (substdio_flush(&ssout) == -1) die_datenew(); | |
123 | if (fsync(fd) == -1) die_datenew(); | |
124 | if (close(fd) == -1) die_datenew(); /* NFS stupidity */ | |
125 | ||
126 | if (rename(fndatenew.s,fndate.s) == -1) | |
f8beb284 | 127 | strerr_die6sys(111,FATAL,ERR_MOVE,fndatenew.s," to ",fndate.s,": "); |
5b62e993 MW |
128 | } |
129 | ||
130 | void doit(addr,msgnum,when,bounce) | |
131 | char *addr; | |
132 | unsigned long msgnum; | |
133 | unsigned long when; | |
134 | stralloc *bounce; | |
135 | { | |
136 | int fd; | |
137 | int fdnew; | |
f8beb284 MW |
138 | unsigned int pos; |
139 | unsigned long ddir,dfile; | |
5b62e993 | 140 | |
f8beb284 | 141 | if (!issub(workdir,addr,(char *) 0,FATAL)) return; |
5b62e993 | 142 | |
f8beb284 MW |
143 | if (!stralloc_copys(&fndate,workdir)) die_nomem(); |
144 | if (!stralloc_cats(&fndate,"/bounce/d")) die_nomem(); | |
145 | if (!stralloc_0(&fndate)) die_nomem(); | |
146 | makedir(fndate.s); | |
147 | fndate.s[fndate.len-1] = '/'; /* replace terminal '\0' */ | |
148 | ddir = when / 10000; | |
149 | dfile = when - 10000 * ddir; | |
150 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,ddir))) die_nomem(); | |
151 | if (!stralloc_copy(&fndir,&fndate)) die_nomem(); | |
152 | if (!stralloc_0(&fndir)) die_nomem(); /* make later if necessary (new addr)*/ | |
153 | if (!stralloc_cats(&fndate,"/d")) die_nomem(); | |
154 | pos = fndate.len - 2; | |
155 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,dfile))) die_nomem(); | |
5b62e993 | 156 | if (!stralloc_cats(&fndate,".")) die_nomem(); |
f8beb284 MW |
157 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,(unsigned long) getpid()))) |
158 | die_nomem(); | |
159 | if (addrno) { /* so that pre-VERP bounces make a d... file per address */ | |
160 | /* for the first one we use the std-style fname */ | |
161 | if (!stralloc_cats(&fndate,".")) die_nomem(); | |
162 | if (!stralloc_catb(&fndate,strnum,fmt_ulong(strnum,addrno))) die_nomem(); | |
163 | } | |
164 | addrno++; /* get ready for next */ | |
5b62e993 MW |
165 | if (!stralloc_0(&fndate)) die_nomem(); |
166 | if (!stralloc_copy(&fndatenew,&fndate)) die_nomem(); | |
f8beb284 MW |
167 | fndatenew.s[pos] = '_'; /* fndate = bounce/d/nnnn/dmmmmmm */ |
168 | /* fndatenew = bounce/d/nnnn_dmmmmmm */ | |
5b62e993 MW |
169 | |
170 | fd = open_trunc(fndatenew.s); | |
171 | if (fd == -1) die_datenew(); | |
172 | substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); | |
173 | if (substdio_puts(&ssout,addr) == -1) die_datenew(); | |
174 | if (substdio_put(&ssout,"",1) == -1) die_datenew(); | |
175 | if (substdio_puts(&ssout,"Return-Path: <") == -1) die_datenew(); | |
176 | if (!quote2("ed,sender)) die_nomem(); | |
177 | if (substdio_put(&ssout,quoted.s,quoted.len) == -1) die_datenew(); | |
178 | if (substdio_puts(&ssout,">\n") == -1) die_datenew(); | |
179 | if (substdio_put(&ssout,bounce->s,bounce->len) == -1) die_datenew(); | |
180 | if (substdio_flush(&ssout) == -1) die_datenew(); | |
181 | if (fsync(fd) == -1) die_datenew(); | |
182 | if (close(fd) == -1) die_datenew(); /* NFS stupidity */ | |
183 | ||
184 | cookie(hash,"",0,"",addr,""); | |
f8beb284 MW |
185 | if (!stralloc_copys(&fnhash,workdir)) die_nomem(); |
186 | if (!stralloc_cats(&fnhash,"/bounce/h")) die_nomem(); | |
187 | if (!stralloc_0(&fnhash)) die_nomem(); | |
188 | makedir(fnhash.s); | |
189 | fnhash.s[fnhash.len - 1] = '/'; /* replace terminal '\0' */ | |
190 | if (!stralloc_catb(&fnhash,hash,1)) die_nomem(); | |
191 | if (!stralloc_0(&fnhash)) die_nomem(); | |
192 | makedir(fnhash.s); | |
193 | --fnhash.len; /* remove terminal '\0' */ | |
194 | if (!stralloc_cats(&fnhash,"/h")) die_nomem(); | |
195 | pos = fnhash.len - 1; | |
196 | if (!stralloc_catb(&fnhash,hash+1,COOKIE-1)) die_nomem(); | |
5b62e993 MW |
197 | if (!stralloc_0(&fnhash)) die_nomem(); |
198 | if (!stralloc_copy(&fnhashnew,&fnhash)) die_nomem(); | |
f8beb284 | 199 | fnhashnew.s[pos] = 'H'; |
5b62e993 MW |
200 | |
201 | fdnew = open_trunc(fnhashnew.s); | |
202 | if (fdnew == -1) die_hashnew(); | |
203 | substdio_fdbuf(&ssout,write,fdnew,outbuf,sizeof(outbuf)); | |
204 | ||
205 | fd = open_read(fnhash.s); | |
206 | if (fd == -1) { | |
207 | if (errno != error_noent) | |
f8beb284 MW |
208 | strerr_die4sys(111,FATAL,ERR_READ,fnhash.s,": "); |
209 | makedir(fndir.s); | |
5b62e993 | 210 | if (rename(fndatenew.s,fndate.s) == -1) |
f8beb284 | 211 | strerr_die6sys(111,FATAL,ERR_MOVE,fndatenew.s," to ",fndate.s,": "); |
5b62e993 MW |
212 | } |
213 | else { | |
214 | substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); | |
215 | switch(substdio_copy(&ssout,&ssin)) { | |
216 | case -2: die_msgin(); | |
217 | case -3: die_hashnew(); | |
218 | } | |
219 | close(fd); | |
220 | if (unlink(fndatenew.s) == -1) | |
f8beb284 | 221 | strerr_die4sys(111,FATAL,ERR_DELETE,fndatenew.s,": "); |
5b62e993 MW |
222 | } |
223 | if (substdio_puts(&ssout," ") == -1) die_hashnew(); | |
224 | if (substdio_put(&ssout,strnum,fmt_ulong(strnum,msgnum)) == -1) die_hashnew(); | |
225 | if (substdio_puts(&ssout,"\n") == -1) die_hashnew(); | |
226 | if (substdio_flush(&ssout) == -1) die_hashnew(); | |
227 | if (fsync(fdnew) == -1) die_hashnew(); | |
228 | if (close(fdnew) == -1) die_hashnew(); /* NFS stupidity */ | |
229 | ||
230 | if (rename(fnhashnew.s,fnhash.s) == -1) | |
f8beb284 | 231 | strerr_die6sys(111,FATAL,ERR_MOVE,fnhashnew.s," to ",fnhash.s,": "); |
5b62e993 MW |
232 | } |
233 | ||
234 | stralloc bounce = {0}; | |
235 | stralloc line = {0}; | |
236 | stralloc header = {0}; | |
237 | stralloc intro = {0}; | |
238 | stralloc failure = {0}; | |
239 | stralloc paragraph = {0}; | |
f8beb284 | 240 | int flagmasterbounce = 0; |
5b62e993 MW |
241 | int flaghaveheader; |
242 | int flaghaveintro; | |
243 | ||
244 | stralloc key = {0}; | |
5b62e993 MW |
245 | |
246 | char msginbuf[1024]; | |
247 | substdio ssmsgin; | |
248 | ||
249 | void main(argc,argv) | |
250 | int argc; | |
251 | char **argv; | |
252 | { | |
5b62e993 MW |
253 | char *local; |
254 | char *action; | |
f8beb284 MW |
255 | char *def; |
256 | char *ret; | |
257 | char *cp; | |
5b62e993 MW |
258 | unsigned long msgnum; |
259 | unsigned long cookiedate; | |
260 | unsigned long when; | |
f8beb284 | 261 | unsigned long listno = 0L; |
5b62e993 | 262 | int match; |
f8beb284 MW |
263 | unsigned int i; |
264 | int flagdig = 0; | |
265 | int flagmaster = 0; | |
266 | int flagreceipt = 0; | |
5b62e993 | 267 | int fdlock; |
f8beb284 | 268 | register char ch; |
5b62e993 MW |
269 | |
270 | umask(022); | |
271 | sig_pipeignore(); | |
272 | when = (unsigned long) now(); | |
273 | ||
274 | dir = argv[1]; | |
275 | if (!dir) die_usage(); | |
f8beb284 MW |
276 | if (*dir == '-') { /* for normal use */ |
277 | if (dir[1] == 'd') { | |
278 | flagdig = 1; | |
279 | } else if (dir[1] == 'D') { | |
280 | flagdig = 0; | |
281 | } else | |
282 | die_usage(); | |
283 | dir = argv[2]; | |
284 | if (!dir) die_usage(); | |
285 | } | |
5b62e993 MW |
286 | |
287 | sender = env_get("SENDER"); | |
f8beb284 | 288 | if (!sender) strerr_die2x(100,FATAL,ERR_NOSENDER); |
5b62e993 | 289 | local = env_get("LOCAL"); |
f8beb284 MW |
290 | if (!local) strerr_die2x(100,FATAL,ERR_NOLOCAL); |
291 | def = env_get("DEFAULT"); /* qmail-1.02 */ | |
5b62e993 MW |
292 | |
293 | if (chdir(dir) == -1) | |
f8beb284 | 294 | strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": "); |
5b62e993 MW |
295 | |
296 | switch(slurp("key",&key,32)) { | |
297 | case -1: | |
f8beb284 | 298 | strerr_die4sys(111,FATAL,ERR_READ,dir,"/key: "); |
5b62e993 | 299 | case 0: |
f8beb284 | 300 | strerr_die4x(100,FATAL,dir,"/key",ERR_NOEXIST); |
5b62e993 | 301 | } |
f8beb284 MW |
302 | workdir = dir; |
303 | action = def; | |
5b62e993 | 304 | |
f8beb284 MW |
305 | if (str_start(action,"receipt-")) { |
306 | flagreceipt = 1; | |
307 | action += 8; | |
308 | } | |
309 | ch = *action; /* -d -digest, -m -master, -g -getmaster */ | |
310 | if (ch && action[1] == '-') { | |
311 | switch (ch) { | |
312 | case 'g': flagmaster = 1; flagdig = 1; action += 2; break; | |
313 | case 'm': flagmaster = 1; action += 2; break; | |
314 | default: break; | |
315 | } | |
316 | } | |
317 | if (flagdig) { | |
318 | if (!stralloc_copys(&ddir,dir)) die_nomem(); | |
319 | if (!stralloc_cats(&ddir,"/digest")) die_nomem(); | |
320 | if (!stralloc_0(&ddir)) die_nomem(); | |
321 | workdir = ddir.s; | |
322 | } | |
5b62e993 MW |
323 | |
324 | if (!*action) die_trash(); | |
325 | ||
f8beb284 MW |
326 | if (flagreceipt || flagmaster) /* check cookie */ |
327 | if (str_chr(action,'-') == COOKIE) { | |
328 | action[COOKIE] = '\0'; | |
329 | hashp = action; | |
330 | action += COOKIE + 1; | |
5b62e993 MW |
331 | } |
332 | ||
f8beb284 MW |
333 | if (!flagreceipt) { |
334 | if (!flagmaster && str_start(action,"probe-")) { | |
335 | action += 6; | |
336 | action += scan_ulong(action,&cookiedate); | |
337 | if (now() - cookiedate > 3000000) die_trash(); | |
338 | if (*action++ != '.') die_trash(); | |
339 | i = str_chr(action,'-'); | |
340 | if (i != COOKIE) die_trash(); | |
341 | byte_copy(hashcopy,COOKIE,action); | |
342 | action += COOKIE; | |
343 | if (*action++ != '-') die_trash(); | |
344 | i = str_rchr(action,'='); | |
345 | if (!stralloc_copyb(&line,action,i)) die_nomem(); | |
346 | if (action[i]) { | |
347 | if (!stralloc_cats(&line,"@")) die_nomem(); | |
348 | if (!stralloc_cats(&line,action + i + 1)) die_nomem(); | |
349 | } | |
350 | if (!stralloc_0(&line)) die_nomem(); | |
351 | strnum[fmt_ulong(strnum,cookiedate)] = 0; | |
352 | cookie(hash,key.s,key.len,strnum,line.s,"P"); | |
353 | if (byte_diff(hash,COOKIE,hashcopy)) die_trash(); | |
354 | ||
355 | (void) subscribe(workdir,line.s,0,"","-probe",1,-1,(char *) 0,FATAL); | |
356 | _exit(99); | |
5b62e993 | 357 | } |
f8beb284 MW |
358 | |
359 | if (!stralloc_copys(&line,workdir)) die_nomem(); | |
360 | if (!stralloc_cats(&line,"/lockbounce")) die_nomem(); | |
5b62e993 | 361 | if (!stralloc_0(&line)) die_nomem(); |
5b62e993 | 362 | |
f8beb284 MW |
363 | fdlock = open_append(line.s); |
364 | if (fdlock == -1) | |
365 | strerr_die4sys(111,FATAL,ERR_OPEN,line.s,": "); | |
366 | if (lock_ex(fdlock) == -1) | |
367 | strerr_die4sys(111,FATAL,ERR_OBTAIN,line.s,": "); | |
368 | ||
369 | if (!flagmaster && str_start(action,"warn-")) { | |
370 | action += 5; | |
371 | action += scan_ulong(action,&cookiedate); | |
372 | if (now() - cookiedate > 3000000) die_trash(); | |
373 | if (*action++ != '.') die_trash(); | |
374 | i = str_chr(action,'-'); | |
375 | if (i != COOKIE) die_trash(); | |
376 | byte_copy(hashcopy,COOKIE,action); | |
377 | action += COOKIE; | |
378 | if (*action++ != '-') die_trash(); | |
379 | i = str_rchr(action,'='); | |
380 | if (!stralloc_copyb(&line,action,i)) die_nomem(); | |
381 | if (action[i]) { | |
382 | if (!stralloc_cats(&line,"@")) die_nomem(); | |
383 | if (!stralloc_cats(&line,action + i + 1)) die_nomem(); | |
384 | } | |
385 | if (!stralloc_0(&line)) die_nomem(); | |
386 | strnum[fmt_ulong(strnum,cookiedate)] = 0; | |
387 | cookie(hash,key.s,key.len,strnum,line.s,"W"); | |
388 | if (byte_diff(hash,COOKIE,hashcopy)) die_trash(); | |
389 | ||
390 | if (slurpclose(0,&bounce,1024) == -1) die_msgin(); | |
391 | dowit(line.s,when,&bounce); | |
392 | _exit(99); | |
393 | } | |
5b62e993 | 394 | } |
5b62e993 | 395 | action += scan_ulong(action,&msgnum); |
f8beb284 MW |
396 | if (*action++ != '-') die_badaddr(); |
397 | cp = action; | |
398 | if (*action >= '0' && *action <= '9') { /* listno */ | |
399 | action += scan_ulong(action,&listno); | |
400 | listno++; /* logging is 1-53, not 0-52 */ | |
401 | } | |
5b62e993 | 402 | |
f8beb284 MW |
403 | if (hashp) { /* scrap bad cookies */ |
404 | if ((ret = checktag(workdir,msgnum,0L,"x",(char *) 0,hashp))) { | |
405 | if (*ret) | |
406 | strerr_die2x(111,FATAL,*ret); | |
407 | else | |
408 | die_trash(); | |
409 | } else if (flagreceipt) { | |
410 | if (!(ret = logmsg(dir,msgnum,listno,0L,5))) { | |
411 | closesql(); | |
412 | strerr_die6x(99,INFO,"receipt:",cp," [",hashp,"]"); | |
413 | } | |
414 | if (*ret) strerr_die2x(111,FATAL,ret); | |
415 | else strerr_die2x(0,INFO,ERR_DONE); | |
416 | } else if (*action) { /* post VERP master bounce */ | |
417 | if ((ret = logmsg(dir,msgnum,listno,0L,-1))) { | |
418 | closesql(); | |
419 | strerr_die4x(0,INFO,"bounce [",hashp,"]"); | |
420 | } | |
421 | if (*ret) strerr_die2x(111,FATAL,ret); | |
422 | else strerr_die2x(99,INFO,ERR_DONE); | |
423 | } | |
424 | } else if (flagreceipt || flagmaster) | |
425 | die_badaddr(); | |
5b62e993 | 426 | |
f8beb284 | 427 | if (*action) { |
5b62e993 MW |
428 | i = str_rchr(action,'='); |
429 | if (!stralloc_copyb(&line,action,i)) die_nomem(); | |
430 | if (action[i]) { | |
431 | if (!stralloc_cats(&line,"@")) die_nomem(); | |
432 | if (!stralloc_cats(&line,action + i + 1)) die_nomem(); | |
433 | } | |
434 | if (!stralloc_0(&line)) die_nomem(); | |
f8beb284 | 435 | if (slurpclose(0,&bounce,1024) == -1) die_msgin(); |
5b62e993 | 436 | doit(line.s,msgnum,when,&bounce); |
f8beb284 | 437 | _exit(99); |
5b62e993 MW |
438 | } |
439 | ||
f8beb284 | 440 | /* pre-VERP bounce, in QSBMF format. Receipts are never pre-VERP */ |
5b62e993 MW |
441 | |
442 | substdio_fdbuf(&ssmsgin,read,0,msginbuf,sizeof(msginbuf)); | |
443 | ||
444 | flaghaveheader = 0; | |
445 | flaghaveintro = 0; | |
446 | ||
447 | for (;;) { | |
448 | if (!stralloc_copys(¶graph,"")) die_nomem(); | |
449 | for (;;) { | |
450 | if (getln(&ssmsgin,&line,&match,'\n') == -1) die_msgin(); | |
451 | if (!match) die_trash(); | |
452 | if (!stralloc_cat(¶graph,&line)) die_nomem(); | |
453 | if (line.len <= 1) break; | |
454 | } | |
455 | ||
456 | if (!flaghaveheader) { | |
457 | if (!stralloc_copy(&header,¶graph)) die_nomem(); | |
458 | flaghaveheader = 1; | |
459 | continue; | |
460 | } | |
461 | ||
462 | if (!flaghaveintro) { | |
f8beb284 MW |
463 | if (paragraph.s[0] == '-' && paragraph.s[1] == '-') |
464 | continue; /* skip MIME boundary if it exists */ | |
5b62e993 MW |
465 | if (paragraph.len < 15) die_trash(); |
466 | if (str_diffn(paragraph.s,"Hi. This is the",15)) die_trash(); | |
467 | if (!stralloc_copy(&intro,¶graph)) die_nomem(); | |
468 | flaghaveintro = 1; | |
469 | continue; | |
470 | } | |
471 | ||
472 | if (paragraph.s[0] == '-') | |
473 | break; | |
474 | ||
475 | if (paragraph.s[0] == '<') { | |
476 | if (!stralloc_copy(&failure,¶graph)) die_nomem(); | |
477 | ||
478 | if (!stralloc_copy(&bounce,&header)) die_nomem(); | |
479 | if (!stralloc_cat(&bounce,&intro)) die_nomem(); | |
480 | if (!stralloc_cat(&bounce,&failure)) die_nomem(); | |
481 | ||
482 | i = byte_chr(failure.s,failure.len,'\n'); | |
483 | if (i < 3) die_trash(); | |
484 | ||
485 | if (!stralloc_copyb(&line,failure.s + 1,i - 3)) die_nomem(); | |
486 | if (byte_chr(line.s,line.len,'\0') == line.len) { | |
487 | if (!stralloc_0(&line)) die_nomem(); | |
f8beb284 MW |
488 | if (flagmaster) { /* bounced msg slave! */ |
489 | if ((i = str_rchr(line.s,'@')) >= 5) { /* 00_52@host */ | |
490 | line.s[i] = '\0'; /* 00_52 */ | |
491 | (void) scan_ulong(line.s + i - 5,&listno); | |
492 | if ((ret = logmsg(dir,msgnum,listno + 1,0L,-1)) && *ret) | |
493 | strerr_die2x(111,FATAL,ret); | |
494 | strerr_warn3(INFO,"bounce ",line.s + i - 5,(struct strerr *) 0); | |
495 | flagmasterbounce = 1; | |
496 | } | |
497 | } else | |
498 | doit(line.s,msgnum,when,&bounce); | |
5b62e993 MW |
499 | } |
500 | } | |
501 | } | |
f8beb284 MW |
502 | closesql(); |
503 | if (flagmasterbounce) | |
504 | strerr_die3x(0,"[",hashp,"]"); | |
505 | else | |
506 | _exit(99); | |
5b62e993 | 507 | } |