Commit | Line | Data |
---|---|---|
f8beb284 MW |
1 | /*$Id: ezmlm-store.c,v 1.52 1999/10/09 16:49:56 lindberg Exp $*/ |
2 | /*$Name: ezmlm-idx-040 $*/ | |
3 | ||
4 | #include <sys/types.h> | |
5 | #include <sys/stat.h> | |
6 | #include "stralloc.h" | |
7 | #include "subfd.h" | |
8 | #include "strerr.h" | |
9 | #include "error.h" | |
10 | #include "qmail.h" | |
11 | #include "env.h" | |
12 | #include "lock.h" | |
13 | #include "sig.h" | |
14 | #include "open.h" | |
15 | #include "getln.h" | |
16 | #include "str.h" | |
17 | #include "fmt.h" | |
18 | #include "readwrite.h" | |
19 | #include "auto_bin.h" | |
20 | #include "fork.h" | |
21 | #include "wait.h" | |
22 | #include "exit.h" | |
23 | #include "substdio.h" | |
24 | #include "getconf.h" | |
25 | #include "datetime.h" | |
26 | #include "now.h" | |
27 | #include "date822fmt.h" | |
28 | #include "cookie.h" | |
29 | #include "sgetopt.h" | |
30 | #include "errtxt.h" | |
31 | #include "idx.h" | |
32 | #include "copy.h" | |
33 | #include "subscribe.h" | |
34 | #include "mime.h" | |
35 | ||
36 | int flagmime = MOD_MIME; /* default is message as attachment */ | |
37 | int flagpublic = 1; /* default anyone can post */ | |
38 | /* =0 for only moderators can */ | |
39 | int flagself = 0; /* `modpost` mods approve own posts */ | |
40 | /* but mod/ is used for moderators */ | |
41 | /* of other posts. Def=no=0 */ | |
42 | char flagcd = '\0'; /* default: don't use quoted-printable */ | |
43 | int flagbody = 1; /* body of message enclosed with mod request */ | |
44 | /* 0 => headers only */ | |
45 | ||
46 | #define FATAL "ezmlm-store: fatal: " | |
47 | ||
48 | void die_usage() | |
49 | { | |
50 | strerr_die1x(100,"ezmlm-store: usage: ezmlm-store [-cCmMpPrRsSvV] dir"); | |
51 | } | |
52 | void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); } | |
53 | ||
54 | stralloc fnmsg = {0}; | |
55 | ||
56 | void die_msg() { strerr_die4sys(111,FATAL,ERR_WRITE,fnmsg.s,": "); } | |
57 | ||
58 | int fdmsg; | |
59 | int fdmod; | |
60 | int pid; | |
61 | int match; | |
62 | ||
63 | char strnum[FMT_ULONG]; | |
64 | char date[DATE822FMT]; | |
65 | char hash[COOKIE]; | |
66 | char boundary[COOKIE]; | |
67 | datetime_sec when; | |
68 | struct datetime dt; | |
69 | struct stat st; | |
70 | ||
71 | void *psql = (void *) 0; | |
72 | ||
73 | stralloc fnbase = {0}; | |
74 | stralloc line = {0}; | |
75 | stralloc mailinglist = {0}; | |
76 | stralloc outlocal = {0}; | |
77 | stralloc outhost = {0}; | |
78 | stralloc mydtline = {0}; | |
79 | stralloc returnpath = {0}; | |
80 | stralloc accept = {0}; | |
81 | stralloc action = {0}; | |
82 | stralloc reject = {0}; | |
83 | stralloc quoted = {0}; | |
84 | stralloc key = {0}; | |
85 | stralloc subject = {0}; | |
86 | stralloc moderators = {0}; | |
87 | stralloc charset = {0}; | |
88 | stralloc sendopt = {0}; | |
89 | ||
90 | struct qmail qq; | |
91 | int qqwrite(fd,buf,len) int fd; char *buf; unsigned int len; | |
92 | { | |
93 | qmail_put(&qq,buf,len); | |
94 | return len; | |
95 | } | |
96 | ||
97 | int subto(s,l) | |
98 | char *s; | |
99 | unsigned int l; | |
100 | { | |
101 | qmail_put(&qq,"T",1); | |
102 | qmail_put(&qq,s,l); | |
103 | qmail_put(&qq,"",1); | |
104 | return (int) l; | |
105 | } | |
106 | ||
107 | char qqbuf[1]; | |
108 | substdio ssqq = SUBSTDIO_FDBUF(qqwrite,-1,qqbuf,sizeof(qqbuf)); | |
109 | ||
110 | substdio ssin; | |
111 | char inbuf[1024]; | |
112 | ||
113 | substdio ssmsg; | |
114 | char msgbuf[1024]; | |
115 | ||
116 | substdio sstext; | |
117 | char textbuf[512]; | |
118 | ||
119 | substdio sssub; | |
120 | char subbuf[512]; | |
121 | ||
122 | void transferenc() | |
123 | { | |
124 | if (flagcd) { | |
125 | qmail_puts(&qq,"\nContent-Transfer-Encoding: "); | |
126 | if (flagcd == 'Q') | |
127 | qmail_puts(&qq,"Quoted-Printable\n\n"); | |
128 | else | |
129 | qmail_puts(&qq,"base64\n\n"); | |
130 | } else | |
131 | qmail_puts(&qq,"\n\n"); | |
132 | } | |
133 | ||
134 | void makehash(act) | |
135 | stralloc *act; /* has to be 0-terminated */ | |
136 | /* act is expected to be -reject-ddddd.ttttt or -accept-ddddd.ttttt */ | |
137 | /* The routine will add .hash@outhost to act. act will NOT be 0-terminated */ | |
138 | { | |
139 | int d; | |
140 | ||
141 | d = 2 + str_chr(act->s + 1,'-'); | |
142 | cookie(hash,key.s,key.len,act->s + d,"","a"); | |
143 | *(act->s + act->len - 1) = '.'; /* we put a '.' Bad, but works */ | |
144 | if (!stralloc_catb(act,hash,COOKIE)) die_nomem(); | |
145 | if (!stralloc_cats(act,"@")) die_nomem(); | |
146 | if (!stralloc_cat(act,&outhost)) die_nomem(); | |
147 | } | |
148 | ||
149 | void main(argc,argv) | |
150 | int argc; | |
151 | char **argv; | |
152 | { | |
153 | char *dir; | |
154 | int fdlock; | |
155 | char *sender; | |
156 | int match; | |
157 | int flaginheader; | |
158 | int flagmodpost; | |
159 | int flagremote; | |
160 | char *pmod; | |
161 | char *err; | |
162 | int opt; | |
163 | unsigned int i; | |
164 | char szchar[2] = "-"; | |
165 | char *sendargs[4]; | |
166 | int child,wstat; | |
167 | ||
168 | (void) umask(022); | |
169 | sig_pipeignore(); | |
170 | ||
171 | if (!stralloc_copys(&sendopt," -")) die_nomem(); | |
172 | while ((opt = getopt(argc,argv,"bBcCmMpPrRsSvV")) != opteof) | |
173 | switch(opt) { | |
174 | case 'b': flagbody = 1; break; | |
175 | case 'B': flagbody = 0; break; | |
176 | case 'm': flagmime = 1; break; | |
177 | case 'M': flagmime = 0; break; | |
178 | case 'p': flagpublic = 1; break; /* anyone can post (still moderated)*/ | |
179 | case 'P': flagpublic = 0; break; /* only moderators can post */ | |
180 | case 's': flagself = 1; break; /* modpost and DIR/mod diff fxns */ | |
181 | case 'S': flagself = 0; break; /* same fxn */ | |
182 | case 'c': /* ezmlm-send flags */ | |
183 | case 'C': | |
184 | case 'r': | |
185 | case 'R': | |
186 | szchar[0] = (char) opt & 0xff; | |
187 | if (!stralloc_append(&sendopt,szchar)) die_nomem(); | |
188 | break; | |
189 | case 'v': | |
190 | case 'V': strerr_die2x(0,"ezmlm-store version: ",EZIDX_VERSION); | |
191 | default: | |
192 | die_usage(); | |
193 | } | |
194 | ||
195 | sender = env_get("SENDER"); | |
196 | ||
197 | if (sender) { | |
198 | if (!*sender || str_equal(sender,"#@[]")) | |
199 | strerr_die2x(100,FATAL,ERR_BOUNCE); | |
200 | } | |
201 | ||
202 | dir = argv[optind]; | |
203 | if (!dir) die_usage(); | |
204 | ||
205 | if (chdir(dir) == -1) | |
206 | strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": "); | |
207 | ||
208 | flagmodpost = getconf_line(&moderators,"modpost",0,FATAL,dir); | |
209 | flagremote = getconf_line(&line,"remote",0,FATAL,dir); | |
210 | if (!flagmodpost) { /* not msg-mod. Pipe to ezmlm-send */ | |
211 | sendargs[0] = "/bin/sh"; | |
212 | sendargs[1] = "-c"; | |
213 | if (!stralloc_copys(&line,auto_bin)) die_nomem(); | |
214 | if (!stralloc_cats(&line,"/ezmlm-send")) die_nomem(); | |
215 | if (sendopt.len > 2) | |
216 | if (!stralloc_cat(&line,&sendopt)) die_nomem(); | |
217 | if (!stralloc_cats(&line," '")) die_nomem(); | |
218 | if (!stralloc_cats(&line,dir)) die_nomem(); | |
219 | if (!stralloc_cats(&line,"'")) die_nomem(); | |
220 | if (!stralloc_0(&line)) die_nomem(); | |
221 | sendargs[2] = line.s; | |
222 | sendargs[3] = 0; | |
223 | switch(child = fork()) { | |
224 | case -1: | |
225 | strerr_die2sys(111,FATAL,ERR_FORK); | |
226 | case 0: | |
227 | execvp(*sendargs,sendargs); | |
228 | if (errno == error_txtbsy || errno == error_nomem || | |
229 | errno == error_io) | |
230 | strerr_die5sys(111,FATAL,ERR_EXECUTE,"/bin/sh -c ",sendargs[2],": "); | |
231 | else | |
232 | strerr_die5sys(100,FATAL,ERR_EXECUTE,"/bin/sh -c ",sendargs[2],": "); | |
233 | } | |
234 | /* parent */ | |
235 | wait_pid(&wstat,child); | |
236 | if (wait_crashed(wstat)) | |
237 | strerr_die2x(111,FATAL,ERR_CHILD_CRASHED); | |
238 | switch(wait_exitcode(wstat)) { | |
239 | case 100: | |
240 | strerr_die2x(100,FATAL,"Fatal error from child"); | |
241 | case 111: | |
242 | strerr_die2x(111,FATAL,"Temporary error from child"); | |
243 | case 0: | |
244 | _exit(0); | |
245 | default: | |
246 | strerr_die2x(111,FATAL,"Unknown temporary error from child"); | |
247 | } | |
248 | } | |
249 | ||
250 | if (!moderators.len || !(moderators.s[0] == '/')) { | |
251 | if (!stralloc_copys(&moderators,dir)) die_nomem(); | |
252 | if (!stralloc_cats(&moderators,"/mod")) die_nomem(); | |
253 | } | |
254 | if (!stralloc_0(&moderators)) die_nomem(); | |
255 | ||
256 | if (sender) { | |
257 | pmod = issub(moderators.s,sender,(char *) 0,FATAL); | |
258 | closesql(); | |
259 | /* sender = moderator? */ | |
260 | } else | |
261 | pmod = 0; | |
262 | ||
263 | if (!pmod && !flagpublic) | |
264 | strerr_die2x(100,FATAL,ERR_NO_POST); | |
265 | ||
266 | switch(slurp("key",&key,32)) { | |
267 | case -1: | |
268 | strerr_die4sys(111,FATAL,ERR_READ,dir,"/key: "); | |
269 | case 0: | |
270 | strerr_die4x(100,FATAL,dir,"/key",ERR_NOEXIST); | |
271 | } | |
272 | ||
273 | getconf_line(&outhost,"outhost",1,FATAL,dir); | |
274 | getconf_line(&outlocal,"outlocal",1,FATAL,dir); | |
275 | getconf_line(&mailinglist,"mailinglist",1,FATAL,dir); | |
276 | ||
277 | fdlock = open_append("mod/lock"); | |
278 | if (fdlock == -1) | |
279 | strerr_die4sys(111,FATAL,ERR_OPEN,dir,"/mod/lock: "); | |
280 | if (lock_ex(fdlock) == -1) | |
281 | strerr_die4sys(111,FATAL,ERR_OBTAIN,dir,"/mod/lock: "); | |
282 | ||
283 | if (!stralloc_copys(&mydtline,"Delivered-To: moderator for ")) die_nomem(); | |
284 | if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem(); | |
285 | if (!stralloc_append(&mydtline,"@")) die_nomem(); | |
286 | if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem(); | |
287 | if (!stralloc_cats(&mydtline,"\n")) die_nomem(); | |
288 | ||
289 | if (!stralloc_copys(&returnpath,"Return-Path: <")) die_nomem(); | |
290 | if (sender) { | |
291 | if (!stralloc_cats(&returnpath,sender)) die_nomem(); | |
292 | for (i = 14; i < returnpath.len;++i) | |
293 | if (returnpath.s[i] == '\n' || !returnpath.s[i] ) | |
294 | returnpath.s[i] = '_'; | |
295 | /* NUL and '\n' are bad, but we don't quote since this is */ | |
296 | /* only for ezmlm-moderate, NOT for SMTP */ | |
297 | } | |
298 | if (!stralloc_cats(&returnpath,">\n")) die_nomem(); | |
299 | ||
300 | pid = getpid(); /* unique file name */ | |
301 | for (i = 0;;++i) /* got lock - nobody else can add files */ | |
302 | { | |
303 | when = now(); /* when is also used later for date! */ | |
304 | if (!stralloc_copys(&fnmsg,"mod/pending/")) die_nomem(); | |
305 | if (!stralloc_copyb(&fnbase,strnum,fmt_ulong(strnum,when))) die_nomem(); | |
306 | if (!stralloc_append(&fnbase,".")) die_nomem(); | |
307 | if (!stralloc_catb(&fnbase,strnum,fmt_ulong(strnum,pid))) die_nomem(); | |
308 | if (!stralloc_cat(&fnmsg,&fnbase)) die_nomem(); | |
309 | if (!stralloc_0(&fnmsg)) die_nomem(); | |
310 | if (stat(fnmsg.s,&st) == -1) if (errno == error_noent) break; | |
311 | /* really should never get to this point */ | |
312 | if (i == 2) | |
313 | strerr_die2x(111,FATAL,ERR_UNIQUE); | |
314 | sleep(2); | |
315 | } | |
316 | ||
317 | if (!stralloc_copys(&action,"-")) die_nomem(); | |
318 | if (!stralloc_cats(&action,ACTION_REJECT)) die_nomem(); | |
319 | if (!stralloc_cat(&action,&fnbase)) die_nomem(); | |
320 | if (!stralloc_0(&action)) die_nomem(); | |
321 | makehash(&action); | |
322 | if (!quote("ed,&outlocal)) die_nomem(); | |
323 | if (!stralloc_copy(&reject,"ed)) die_nomem(); | |
324 | if (!stralloc_cat(&reject,&action)) die_nomem(); | |
325 | if (!stralloc_0(&reject)) die_nomem(); | |
326 | ||
327 | if (!stralloc_copys(&action,"-")) die_nomem(); | |
328 | if (!stralloc_cats(&action,ACTION_ACCEPT)) die_nomem(); | |
329 | if (!stralloc_cat(&action,&fnbase)) die_nomem(); | |
330 | if (!stralloc_0(&action)) die_nomem(); | |
331 | makehash(&action); | |
332 | if (!stralloc_copy(&accept,"ed)) die_nomem(); | |
333 | if (!stralloc_cat(&accept,&action)) die_nomem(); | |
334 | if (!stralloc_0(&accept)) die_nomem(); | |
335 | ||
336 | set_cpoutlocal(&outlocal); | |
337 | set_cpouthost(&outhost); | |
338 | set_cptarget(accept.s); /* for copy () */ | |
339 | set_cpconfirm(reject.s); | |
340 | ||
341 | fdmsg = open_trunc(fnmsg.s); | |
342 | if (fdmsg == -1) | |
343 | strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnmsg.s,": "); | |
344 | substdio_fdbuf(&ssmsg,write,fdmsg,msgbuf,sizeof(msgbuf)); | |
345 | ||
346 | if (qmail_open(&qq, (stralloc *) 0) == -1) /* Open mailer */ | |
347 | strerr_die2sys(111,FATAL,ERR_QMAIL_QUEUE); | |
348 | ||
349 | qmail_puts(&qq,"Mailing-List: "); | |
350 | qmail_put(&qq,mailinglist.s,mailinglist.len); | |
351 | if (getconf_line(&line,"listid",0,FATAL,dir)) { | |
352 | qmail_puts(&qq,"List-ID: "); | |
353 | qmail_put(&qq,line.s,line.len); | |
354 | } | |
355 | qmail_puts(&qq,"\nDate: "); | |
356 | datetime_tai(&dt,when); | |
357 | qmail_put(&qq,date,date822fmt(date,&dt)); | |
358 | qmail_puts(&qq,"Message-ID: <"); | |
359 | if (!stralloc_copyb(&line,strnum,fmt_ulong(strnum,(unsigned long) when))) | |
360 | die_nomem(); | |
361 | if (!stralloc_append(&line,".")) die_nomem(); | |
362 | if (!stralloc_catb(&line,strnum, | |
363 | fmt_ulong(strnum,(unsigned long) getpid()))) die_nomem(); | |
364 | if (!stralloc_cats(&line,".ezmlm@")) die_nomem(); | |
365 | if (!stralloc_cat(&line,&outhost)) die_nomem(); | |
366 | if (!stralloc_0(&line)) die_nomem(); | |
367 | qmail_puts(&qq,line.s); | |
368 | /* "unique" MIME boundary as hash of messageid */ | |
369 | cookie(boundary,"",0,"",line.s,""); | |
370 | qmail_puts(&qq,">\nFrom: "); | |
371 | qmail_puts(&qq,reject.s); | |
372 | qmail_puts(&qq,"\nReply-To: "); | |
373 | qmail_puts(&qq,accept.s); | |
374 | if (!pmod && flagremote) { /* if remote admin add -allow- address */ | |
375 | qmail_puts(&qq,"\nCc: "); /* for ezmlm-gate users */ | |
376 | strnum[fmt_ulong(strnum,(unsigned long) when)] = 0; | |
377 | cookie(hash,key.s,key.len-FLD_ALLOW,strnum,sender,"t"); | |
378 | if (!stralloc_copy(&line,&outlocal)) die_nomem(); | |
379 | if (!stralloc_cats(&line,"-allow-tc.")) die_nomem(); | |
380 | if (!stralloc_cats(&line,strnum)) die_nomem(); | |
381 | if (!stralloc_append(&line,".")) die_nomem(); | |
382 | if (!stralloc_catb(&line,hash,COOKIE)) die_nomem(); | |
383 | if (!stralloc_append(&line,"-")) die_nomem(); | |
384 | i = str_rchr(sender,'@'); | |
385 | if (!stralloc_catb(&line,sender,i)) die_nomem(); | |
386 | if (sender[i]) { | |
387 | if (!stralloc_append(&line,"=")) die_nomem(); | |
388 | if (!stralloc_cats(&line,sender + i + 1)) die_nomem(); | |
389 | } | |
390 | qmail_put(&qq,line.s,line.len); | |
391 | qmail_puts(&qq,"@"); | |
392 | qmail_put(&qq,outhost.s,outhost.len); | |
393 | } | |
394 | qmail_puts(&qq,"\nTo: Recipient list not shown: ;"); | |
395 | if (!stralloc_copys(&subject,"\nSubject: ")) die_nomem(); | |
396 | if (!stralloc_cats(&subject,TXT_MODERATE)) die_nomem(); | |
397 | if (!quote("ed,&outlocal)) die_nomem(); | |
398 | if (!stralloc_cat(&subject,"ed)) die_nomem(); | |
399 | if (!stralloc_append(&subject,"@")) die_nomem(); | |
400 | if (!stralloc_cat(&subject,&outhost)) die_nomem(); | |
401 | if (flagmime) { | |
402 | if (getconf_line(&charset,"charset",0,FATAL,dir)) { | |
403 | if (charset.len >= 2 && charset.s[charset.len - 2] == ':') { | |
404 | if (charset.s[charset.len - 1] == 'B' || | |
405 | charset.s[charset.len - 1] == 'Q') { | |
406 | flagcd = charset.s[charset.len - 1]; | |
407 | charset.s[charset.len - 2] = '\0'; | |
408 | } | |
409 | } | |
410 | } else | |
411 | if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem(); | |
412 | if (!stralloc_0(&charset)) die_nomem(); | |
413 | qmail_puts(&qq,"\nMIME-Version: 1.0\n"); | |
414 | qmail_puts(&qq,"Content-Type: multipart/mixed;\n\tboundary="); | |
415 | qmail_put(&qq,boundary,COOKIE); | |
416 | qmail_put(&qq,subject.s,subject.len); | |
417 | qmail_puts(&qq,"\n\n--"); | |
418 | qmail_put(&qq,boundary,COOKIE); | |
419 | qmail_puts(&qq,"\nContent-Type: text/plain; charset="); | |
420 | qmail_puts(&qq,charset.s); | |
421 | transferenc(); | |
422 | } else { | |
423 | qmail_put(&qq,subject.s,subject.len); | |
424 | qmail_puts(&qq,"\n\n"); | |
425 | } | |
426 | copy(&qq,"text/mod-request",flagcd,FATAL); | |
427 | if (flagcd == 'B') { | |
428 | encodeB("",0,&line,2,FATAL); | |
429 | qmail_put(&qq,line.s,line.len); | |
430 | } | |
431 | if (substdio_put(&ssmsg,returnpath.s,returnpath.len) == -1) die_msg(); | |
432 | if (substdio_put(&ssmsg,mydtline.s,mydtline.len) == -1) die_msg(); | |
433 | substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); | |
434 | ||
435 | if (flagmime) { | |
436 | qmail_puts(&qq,"\n--"); | |
437 | qmail_put(&qq,boundary,COOKIE); | |
438 | qmail_puts(&qq,"\nContent-Type: message/rfc822\n\n"); | |
439 | } | |
440 | ||
441 | qmail_put(&qq,returnpath.s,returnpath.len); | |
442 | qmail_put(&qq,mydtline.s,mydtline.len); | |
443 | flaginheader = 1; | |
444 | for (;;) { | |
445 | if (getln(&ssin,&line,&match,'\n') == -1) | |
446 | strerr_die2sys(111,FATAL,ERR_READ_INPUT); | |
447 | if (!match) break; | |
448 | if (line.len == 1) flaginheader = 0; | |
449 | if (flaginheader) { | |
450 | if ((line.len == mydtline.len) && | |
451 | !byte_diff(line.s,line.len,mydtline.s)) { | |
452 | close(fdmsg); /* be nice - clean up */ | |
453 | unlink(fnmsg.s); | |
454 | strerr_die2x(100,FATAL,ERR_LOOPING); | |
455 | } | |
456 | if (case_startb(line.s,line.len,"mailing-list:")) { | |
457 | close(fdmsg); /* be nice - clean up */ | |
458 | unlink(fnmsg.s); | |
459 | strerr_die2x(100,FATAL,ERR_MAILING_LIST); | |
460 | } | |
461 | } | |
462 | ||
463 | if (flagbody || flaginheader) /* skip body if !flagbody */ | |
464 | qmail_put(&qq,line.s,line.len); | |
465 | if (substdio_put(&ssmsg,line.s,line.len) == -1) die_msg(); | |
466 | } | |
467 | ||
468 | if (flagmime) { | |
469 | qmail_puts(&qq,"\n--"); | |
470 | qmail_put(&qq,boundary,COOKIE); | |
471 | qmail_puts(&qq,"--\n"); | |
472 | } | |
473 | ||
474 | /* close archive before qmail. Loss of qmail will result in re-run, and */ | |
475 | /* worst case this results in a duplicate msg sitting orphaned until it's */ | |
476 | /* cleaned out. */ | |
477 | ||
478 | if (substdio_flush(&ssmsg) == -1) die_msg(); | |
479 | if (fsync(fdmsg) == -1) die_msg(); | |
480 | if (fchmod(fdmsg,MODE_MOD_MSG | 0700) == -1) die_msg(); | |
481 | if (close(fdmsg) == -1) die_msg(); /* NFS stupidity */ | |
482 | ||
483 | close(fdlock); | |
484 | ||
485 | if (!stralloc_copy(&line,&outlocal)) die_nomem(); | |
486 | if (!stralloc_cats(&line,"-return-@")) die_nomem(); | |
487 | if (!stralloc_cat(&line,&outhost)) die_nomem(); | |
488 | if (!stralloc_0(&line)) die_nomem(); | |
489 | qmail_from(&qq,line.s); /* envelope sender */ | |
490 | if (pmod) /* to moderator only */ | |
491 | qmail_to(&qq,pmod); | |
492 | else { | |
493 | if (flagself) { /* to all moderators */ | |
494 | if (!stralloc_copys(&moderators,dir)) die_nomem(); | |
495 | if (!stralloc_cats(&moderators,"/mod")) die_nomem(); | |
496 | if (!stralloc_0(&moderators)) die_nomem(); | |
497 | } | |
498 | putsubs(moderators.s,0,52,subto,1,FATAL); | |
499 | } | |
500 | ||
501 | if (*(err = qmail_close(&qq)) == '\0') { | |
502 | strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; | |
503 | strerr_die2x(0,"ezmlm-store: info: qp ",strnum); | |
504 | } else | |
505 | strerr_die3x(111,FATAL,ERR_TMP_QMAIL_QUEUE,err+1); | |
506 | } |