15 #include "readwrite.h"
21 #define FATAL "ezmlm-send: fatal: "
25 strerr_die1x(100,"ezmlm-send: usage: ezmlm-send dir");
29 strerr_die2x(111,FATAL
,"out of memory");
32 char strnum
[FMT_ULONG
];
34 stralloc fnadir
= {0};
42 char archivebuf
[1024];
45 stralloc sublist
= {0};
46 stralloc mailinglist
= {0};
47 stralloc outlocal
= {0};
48 stralloc outhost
= {0};
49 stralloc headerremove
= {0};
50 struct constmap headerremovemap
;
51 stralloc headeradd
= {0};
59 int mywrite(fd
,buf
,len
)
64 qmail_put(&qq
,buf
,len
);
70 strerr_die4sys(111,FATAL
,"unable to write to ",fnaf
.s
,": ");
74 strerr_die2sys(111,FATAL
,"unable to create numnew: ");
77 void put(buf
,len
) char *buf
; int len
;
79 qmail_put(&qq
,buf
,len
);
81 if (substdio_put(&ssarchive
,buf
,len
) == -1) die_archive();
84 void puts(buf
) char *buf
;
88 if (substdio_puts(&ssarchive
,buf
) == -1) die_archive();
91 int sublistmatch(sender
)
98 if (j
< sublist
.len
) return 0;
100 i
= byte_rchr(sublist
.s
,sublist
.len
,'@');
101 if (i
== sublist
.len
) return 1;
103 if (byte_diff(sublist
.s
,i
,sender
)) return 0;
104 if (case_diffb(sublist
.s
+ i
,sublist
.len
- i
,sender
+ j
- (sublist
.len
- i
)))
112 unsigned long msgnum
;
116 substdio ss0
= SUBSTDIO_FDBUF(read
,0,buf0
,sizeof(buf0
));
122 fd
= open_trunc("numnew");
123 if (fd
== -1) die_numnew();
124 substdio_fdbuf(&ssnumnew
,write
,fd
,numnewbuf
,sizeof(numnewbuf
));
125 if (substdio_put(&ssnumnew
,strnum
,fmt_ulong(strnum
,msgnum
)) == -1)
127 if (substdio_puts(&ssnumnew
,"\n") == -1) die_numnew();
128 if (substdio_flush(&ssnumnew
) == -1) die_numnew();
129 if (fsync(fd
) == -1) die_numnew();
130 if (close(fd
) == -1) die_numnew(); /* NFS stupidity */
131 if (rename("numnew","num") == -1)
132 strerr_die2sys(111,FATAL
,"unable to move numnew to num: ");
135 stralloc mydtline
= {0};
156 if (!dir
) die_usage();
158 sender
= env_get("SENDER");
160 if (chdir(dir
) == -1)
161 strerr_die4sys(111,FATAL
,"unable to switch to ",dir
,": ");
163 fdlock
= open_append("lock");
165 strerr_die4sys(111,FATAL
,"unable to open ",dir
,"/lock: ");
166 if (lock_ex(fdlock
) == -1)
167 strerr_die4sys(111,FATAL
,"unable to obtain ",dir
,"/lock: ");
169 if (qmail_open(&qq
) == -1)
170 strerr_die2sys(111,FATAL
,"unable to run qmail-queue: ");
172 flagarchived
= getconf_line(&line
,"archived",0,FATAL
,dir
);
174 getconf_line(&num
,"num",1,FATAL
,dir
);
175 if (!stralloc_0(&num
)) die_nomem();
176 scan_ulong(num
.s
,&msgnum
);
179 getconf_line(&outhost
,"outhost",1,FATAL
,dir
);
180 getconf_line(&outlocal
,"outlocal",1,FATAL
,dir
);
181 getconf_line(&mailinglist
,"mailinglist",1,FATAL
,dir
);
182 flagsublist
= getconf_line(&sublist
,"sublist",0,FATAL
,dir
);
184 getconf(&headerremove
,"headerremove",1,FATAL
,dir
);
185 constmap_init(&headerremovemap
,headerremove
.s
,headerremove
.len
,0);
187 getconf(&headeradd
,"headeradd",1,FATAL
,dir
);
188 for (i
= 0;i
< headeradd
.len
;++i
)
190 headeradd
.s
[i
] = '\n';
192 if (!stralloc_copys(&mydtline
,"Delivered-To: mailing list ")) die_nomem();
193 if (!stralloc_catb(&mydtline
,outlocal
.s
,outlocal
.len
)) die_nomem();
194 if (!stralloc_cats(&mydtline
,"@")) die_nomem();
195 if (!stralloc_catb(&mydtline
,outhost
.s
,outhost
.len
)) die_nomem();
196 if (!stralloc_cats(&mydtline
,"\n")) die_nomem();
200 strerr_die2x(100,FATAL
,"I don't distribute bounce messages (#5.7.2)");
201 if (str_equal(sender
,"#@[]"))
202 strerr_die2x(100,FATAL
,"I don't distribute bounce messages (#5.7.2)");
204 if (!sublistmatch(sender
))
205 strerr_die2x(100,FATAL
,"this message is not from my parent list (#5.7.2)");
209 if (!stralloc_copys(&fnadir
,"archive/")) die_nomem();
210 if (!stralloc_catb(&fnadir
,strnum
,fmt_ulong(strnum
,msgnum
/ 100))) die_nomem();
211 if (!stralloc_copy(&fnaf
,&fnadir
)) die_nomem();
212 if (!stralloc_cats(&fnaf
,"/")) die_nomem();
213 if (!stralloc_catb(&fnaf
,strnum
,fmt_uint0(strnum
,(unsigned int) (msgnum
% 100),2))) die_nomem();
214 if (!stralloc_0(&fnadir
)) die_nomem();
215 if (!stralloc_0(&fnaf
)) die_nomem();
217 if (mkdir(fnadir
.s
,0755) == -1)
218 if (errno
!= error_exist
)
219 strerr_die4sys(111,FATAL
,"unable to create ",fnadir
.s
,": ");
220 fdarchive
= open_trunc(fnaf
.s
);
222 strerr_die4sys(111,FATAL
,"unable to write ",fnaf
.s
,": ");
224 substdio_fdbuf(&ssarchive
,write
,fdarchive
,archivebuf
,sizeof(archivebuf
));
228 puts("Mailing-List: ");
229 put(mailinglist
.s
,mailinglist
.len
);
232 put(headeradd
.s
,headeradd
.len
);
233 put(mydtline
.s
,mydtline
.len
);
240 if (getln(&ss0
,&line
,&match
,'\n') == -1)
241 strerr_die2sys(111,FATAL
,"unable to read input: ");
243 if (flaginheader
&& match
) {
246 if ((line
.s
[0] != ' ') && (line
.s
[0] != '\t')) {
248 if (constmap(&headerremovemap
,line
.s
,byte_chr(line
.s
,line
.len
,':')))
250 if (case_startb(line
.s
,line
.len
,"mailing-list:"))
252 if (line
.len
== mydtline
.len
)
253 if (!byte_diff(line
.s
,line
.len
,mydtline
.s
))
254 strerr_die2x(100,FATAL
,"this message is looping: it already has my Delivered-To line (#5.4.6)");
258 if (!(flaginheader
&& flagbadfield
))
259 put(line
.s
,line
.len
);
267 strerr_die2x(100,FATAL
,"sublist messages must have Mailing-List (#5.7.2)");
270 strerr_die2x(100,FATAL
,"message already has Mailing-List (#5.7.2)");
273 if (substdio_flush(&ssarchive
) == -1) die_archive();
274 if (fsync(fdarchive
) == -1) die_archive();
275 if (fchmod(fdarchive
,0744) == -1) die_archive();
276 if (close(fdarchive
) == -1) die_archive(); /* NFS stupidity */
281 if (!stralloc_copy(&line
,&outlocal
)) die_nomem();
282 if (!stralloc_cats(&line
,"-return-")) die_nomem();
283 if (!stralloc_catb(&line
,strnum
,fmt_ulong(strnum
,msgnum
))) die_nomem();
284 if (!stralloc_cats(&line
,"-@")) die_nomem();
285 if (!stralloc_cat(&line
,&outhost
)) die_nomem();
286 if (!stralloc_cats(&line
,"-@[]")) die_nomem();
287 if (!stralloc_0(&line
)) die_nomem();
289 qmail_from(&qq
,line
.s
);
291 for (i
= 0;i
< 53;++i
) {
293 if (!stralloc_copys(&fnsub
,"subscribers/")) die_nomem();
294 if (!stralloc_catb(&fnsub
,&ch
,1)) strerr_die2x(111,FATAL
,"out of memory");
295 if (!stralloc_0(&fnsub
)) strerr_die2x(111,FATAL
,"out of memory");
296 fd
= open_read(fnsub
.s
);
298 if (errno
!= error_noent
)
299 strerr_die4sys(111,FATAL
,"unable to read ",fnsub
.s
,": ");
302 substdio_fdbuf(&ssin
,read
,fd
,inbuf
,sizeof(inbuf
));
303 substdio_fdbuf(&ssout
,mywrite
,-1,outbuf
,sizeof(outbuf
));
304 if (substdio_copy(&ssout
,&ssin
) != 0)
305 strerr_die4sys(111,FATAL
,"unable to read ",fnsub
.s
,": ");
310 switch(qmail_close(&qq
)) {
312 strnum
[fmt_ulong(strnum
,qmail_qp(&qq
))] = 0;
313 strerr_die2x(0,"ezmlm-send: info: qp ",strnum
);
317 strerr_die2x(111,FATAL
,"temporary qmail-queue error");