ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
ezmlm-moderate.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include "error.h"
5#include "case.h"
6#include "stralloc.h"
7#include "str.h"
8#include "env.h"
9#include "error.h"
10#include "sig.h"
11#include "wait.h"
12#include "readclose.h"
13#include "getconf.h"
14#include "logmsg.h"
15#include "byte.h"
16#include "getln.h"
17#include "qmail.h"
18#include "buffer.h"
19#include "readwrite.h"
20#include "seek.h"
21#include "quote.h"
22#include "datetime.h"
23#include "now.h"
24#include "fmt.h"
25#include "getoptb.h"
26#include "cookie.h"
27#include "errtxt.h"
28#include "ezcopy.h"
29#include "hdr.h"
30#include "mime.h"
31#include "open.h"
32#include "lock.h"
33#include "idx.h"
34#include "wrap.h"
35#include "auto_version.h"
36#include "lockfile.h"
37#include "ezmlm.h"
38
39#define WHO "ezmlm-moderate"
40
46
47int flagmime = MOD_MIME; /* default is message as attachment */
48char flagcd = '\0'; /* default: do not use transfer encoding */
49
50static void die_usage() { logmsg(WHO,100,USAGE,"ezmlm-moderate [-cCmMrRvV] [-t replyto] " "dir [/path/ezmlm-send]"); }
51static void die_nomem() { logmsg(WHO,111,FATAL,ERR_NOMEM); }
52static void die_badformat() { logmsg(WHO,100,FATAL,ERR_BAD_REQUEST); }
53
54stralloc outhost = {0};
55stralloc outlocal = {0};
56
57stralloc key = {0};
58stralloc mydtline = {0};
59stralloc mailinglist = {0};
60stralloc accept = {0};
61stralloc reject = {0};
62stralloc to = {0};
63stralloc send = {0};
64stralloc sendopt = {0};
65stralloc comment = {0};
66stralloc charset = {0};
68
69char strnum[FMT_ULONG];
70char hash[COOKIE];
72
73stralloc line = {0};
74stralloc qline = {0};
75stralloc text = {0};
76stralloc quoted = {0};
77stralloc fnbase = {0};
78stralloc fnmsg = {0};
79stralloc fnnew = {0};
80stralloc fnsub = {0};
81char subbuf[256];
82buffer bs;
83
84char *dir;
85
86struct stat st;
87struct qmail qq;
88
89void code_qput(char *s,unsigned int n)
90{
91 if (!flagcd)
92 qmail_put(&qq,s,n);
93 else {
94 if (flagcd == 'B')
95 encode_b64(s,n,&qline,0);
96 else
97 encode_qp(s,n,&qline);
98 qmail_put(&qq,qline.s,qline.len);
99 }
100}
101
114
115int checkfile( char *fn)
116{
117 if (!stralloc_copys(&fnmsg,"mod/pending/")) die_nomem();
118 if (!stralloc_cats(&fnmsg,fn)) die_nomem();
119 if (!stralloc_0(&fnmsg)) die_nomem();
120 if (stat(fnmsg.s,&st) == -1) {
121 if (errno != ENOENT)
122 logmsg(WHO,111,FATAL,B(ERR_STAT,dir,"/",fnmsg.s));
123 } else
124 return 1;
125
126 if (!stralloc_copys(&fnmsg,"mod/accepted/")) die_nomem();
127 if (!stralloc_cats(&fnmsg,fn)) die_nomem();
128 if (!stralloc_0(&fnmsg)) die_nomem();
129 if (stat(fnmsg.s,&st) == -1) {
130 if (errno != ENOENT)
131 logmsg(WHO,111,FATAL,B(ERR_STAT,dir,"/",fnmsg.s));
132 } else
133 return -1;
134
135 if (!stralloc_copys(&fnmsg,"mod/rejected/")) die_nomem();
136 if (!stralloc_cats(&fnmsg,fn)) die_nomem();
137 if (!stralloc_0(&fnmsg)) die_nomem();
138 if (stat(fnmsg.s,&st) == -1) {
139 if (errno != ENOENT)
140 logmsg(WHO,111,FATAL,B(ERR_STAT,dir,"/",fnmsg.s));
141 } else
142 return -2;
143 return 0;
144}
145
146ssize_t qqwrite(int fd,char *buf,unsigned int len)
147{
149 return len;
150}
151char qqbuf[1];
152buffer bq = BUFFER_INIT(qqwrite,-1,qqbuf,sizeof(qqbuf));
153
154buffer bt;
155char textbuf[1024];
156
165
166void maketo()
167{
168 unsigned int x, y;
169
170 if (case_startb(line.s,line.len,"return-path:")) {
171 x = 12 + byte_chr(line.s + 12,line.len-12,'<');
172 if (x != line.len) {
173 y = byte_rchr(line.s + x,line.len-x,'>');
174 if (y + x != line.len) {
175 if (!stralloc_copyb(&to,line.s+x+1,y-1)) die_nomem();
176 if (!stralloc_0(&to)) die_nomem();
177 } /* no return path-> no addressee. A NUL in the sender */
178 } /* is no worse than a faked sender, so no problem */
179 }
180}
181
182int main(int argc,char **argv)
183{
184 char *sender;
185 char *def;
186 char *local;
187 char *action;
188 int flaginheader;
189 int flagcomment;
190 int flaggoodfield;
191 int flagdone;
192 int fd, fdlock;
193 int match;
194 const char *err;
195 char encin = '\0';
196 char szchar[2] = "-";
197 const char *replyto = (char *) 0;
198 unsigned int start,confnum;
199 unsigned int pos,i;
200 int child;
201 int opt;
202 char *cp, *cpnext, *cpfirst, *cplast, *cpafter;
203
204 umask(022);
205 sig_pipeignore();
206 when = now();
207
208 if (!stralloc_copys(&sendopt,"-")) die_nomem();
209
210 while ((opt = getoptb(argc,argv,"cCmMrRt:T:vV")) != opteof)
211 switch(opt) { /* pass on ezmlm-send options */
212 case 'c': /* ezmlm-send flags */
213 case 'C':
214 case 'r':
215 case 'R': szchar[0] = (char) opt & 0xff;
216 if (!stralloc_append(&sendopt,szchar)) die_nomem();
217 break;
218 case 'm': flagmime = 1; break;
219 case 'M': flagmime = 0; break;
220 case 't':
221 case 'T': if (optarg) replyto = optarg; break;
222 case 'v':
223 case 'V': logmsg(WHO,0,VERSION,auto_version);
224 default: die_usage();
225 }
226
227 dir = argv[optind++];
228 if (!dir) die_usage();
229
230 sender = env_get("SENDER");
231 if (!sender) logmsg(WHO,100,FATAL,ERR_NOSENDER);
232 local = env_get("LOCAL");
233 if (!local) logmsg(WHO,100,FATAL,ERR_NOLOCAL);
234 def = env_get("DEFAULT");
235 if (!def) logmsg(WHO,100,FATAL,ERR_NODEFAULT);
236
237 if (!*sender)
238 logmsg(WHO,100,FATAL,ERR_BOUNCE);
239 if (!sender[str_chr(sender,'@')])
240 logmsg(WHO,100,FATAL,ERR_ANONYMOUS);
241 if (str_equal(sender,"#@[]"))
242 logmsg(WHO,100,FATAL,ERR_BOUNCE);
243
244 if (chdir(dir) == -1)
245 logmsg(WHO,111,FATAL,B(ERR_SWITCH,dir));
246
247 switch (openreadclose("key",&key,32)) {
248 case -1: logmsg(WHO,111,FATAL,B(ERR_READ,"/key",dir));
249 case 0: logmsg(WHO,100,FATAL,B("/key",dir,ERR_NOEXIST));
250 }
251 getconf_line(&mailinglist,"mailinglist",1,dir);
252 getconf_line(&outhost,"outhost",1,dir);
253 getconf_line(&outlocal,"outlocal",1,dir);
254 set_cpoutlocal(&outlocal); /* for ezcopy() */
255 set_cpouthost(&outhost); /* for ezcopy() */
256
257 /* local should be >= def, but who knows ... */
258
259 cp = local + str_len(local) - str_len(def) - 2;
260 if (cp < local) die_badformat();
261 action = local + byte_rchr(local,cp - local,'-');
262 if (action == cp) die_badformat();
263 action++;
264
265 if (!action[0]) die_badformat();
266 if (!str_start(action,ACTION_ACCEPT) && !str_start(action,ACTION_REJECT))
268 start = str_chr(action,'-');
269 if (!action[start]) die_badformat();
270 confnum = 1 + start + str_chr(action + start + 1,'.');
271 if (!action[confnum]) die_badformat();
272 confnum += 1 + str_chr(action + confnum + 1,'.');
273 if (!action[confnum]) die_badformat();
274 if (!stralloc_copyb(&fnbase,action+start+1,confnum-start-1)) die_nomem();
275 if (!stralloc_0(&fnbase)) die_nomem();
276 cookie(hash,key.s,key.len,fnbase.s,"","a");
277 if (byte_diff(hash,COOKIE,action+confnum+1))
279
280 fdlock = lockfile("mod/lock");
281
282 switch (checkfile(fnbase.s)) {
283 case 0: logmsg(WHO,100,FATAL,ERR_MOD_TIMEOUT);
284 /* only error if new request != action taken */
285 case -1: if (str_start(action,ACTION_ACCEPT))
287 else
288 logmsg(WHO,100,FATAL,ERR_MOD_ACCEPTED);
289 case -2: if (str_start(action,ACTION_REJECT))
291 else
292 logmsg(WHO,100,FATAL,ERR_MOD_REJECTED);
293 default: break;
294 }
295
296/* Here, we have an existing filename in fnbase with the complete path */
297/* from the current dir in fnmsg. */
298
299 // Lets go for the long 'if' ACTION: REJECT case
300
301 if (str_start(action,ACTION_REJECT)) {
302 if (qmail_open(&qq,(stralloc *) 0) == -1)
303 logmsg(WHO,111,FATAL,ERR_QMAIL_QUEUE);
304
305 /* Build recipient from msg return-path */
306
307 fd = open_read(fnmsg.s);
308 if (fd == -1) {
309 if (errno != ENOENT)
310 logmsg(WHO,111,FATAL,B(ERR_OPEN,fnmsg.s));
311 else
312 logmsg(WHO,100,FATAL,ERR_MOD_TIMEOUT);
313 }
314 buffer_init(&bt,buffer_unixread,fd,textbuf,sizeof(textbuf));
315
316 if (getln(&bt,&line,&match,'\n') == -1 || !match)
317 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
318
319 maketo(); /* extract SENDER from return-path; Build message */
320
321 hdr_add2("Mailing-List: ",mailinglist.s,mailinglist.len);
322 if (getconf_line(&line,"listid",0,dir))
323 hdr_add2("List-ID: ",line.s,line.len);
325 hdr_from("-owner");
326 if (replyto)
327 hdr_add2s("Reply-To: ",replyto);
328 hdr_add2s("To: ",to.s);
330
331 if (flagmime) {
332 if (getconf_line(&charset,"charset",0,dir)) {
333 if (charset.len >= 2 && charset.s[charset.len - 2] == ':') {
334 if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') {
335 flagcd = charset.s[charset.len - 1];
336 charset.s[charset.len - 2] = '\0';
337 }
338 }
339 } else
340 if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem();
341 if (!stralloc_0(&charset)) die_nomem();
343 hdr_boundary(0);
346 }
347 ezcopy(&qq,"text/top",flagcd);
348 ezcopy(&qq,"text/mod-reject",flagcd);
349
350 flagcomment = 0;
351 flaginheader = 1;
352 if (!stralloc_copys(&text,"")) die_nomem();
353 if (!stralloc_ready(&text,1024)) die_nomem();
354
355 /* copy moderator's rejection comment */
356
357 for (;;) {
358 if (getln(buffer_0,&line,&match,'\n') == -1)
359 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
360 if (!match) break;
361 if (flaginheader) {
362 if (case_startb(line.s,line.len,"Content-Transfer-Encoding:")) {
363 pos = 26;
364 while (line.s[pos] == ' ' || line.s[pos] == '\t')
365 ++pos;
366 if (case_startb(line.s+pos,line.len-pos,"base64"))
367 encin = 'B';
368 else if (case_startb(line.s+pos,line.len-pos,"quoted-printable"))
369 encin = 'Q';
370 }
371 if (line.len == 1)
372 flaginheader = 0;
373 } else
374 if (!stralloc_cat(&text,&line)) die_nomem();
375 } /* got body */
376
377 if (encin) {
378 if (encin == 'B')
379 decode_b64(text.s,text.len,&line);
380 else
381 decode_qp(text.s,text.len,&line);
382 if (!stralloc_copy(&text,&line)) die_nomem();
383 }
384 cp = text.s;
385 cpafter = text.s + text.len;
386 if (!stralloc_copys(&line,"\n>>>>> -------------------- >>>>>\n"))
387 die_nomem();
388
389 flaggoodfield = 0;
390 flagdone = 0;
391
392 while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) {
393 i = byte_chr(cp,cpnext-cp,'%');
394 if (i <= 5 && cpnext-cp >= 8) { /* max 5 "quote characters" and space for %%% */
395 if (cp[i+1] == '%' && cp[i+2] == '%') {
396 if (!flaggoodfield) { /* Start tag */
397 if (!stralloc_copyb(&quoted,cp,i)) die_nomem(); /* quote chars*/
398 flaggoodfield = 1;
399 cp = cpnext + 1;
400 cpfirst = cp;
401 continue;
402 } else { /* end tag */
403 if (flagdone) /* 0 no comment lines, 1 comment line */
404 flagdone = 2; /* 2 at least 1 comment line & end tag */
405 break;
406 }
407 }
408 }
409 if (flaggoodfield) {
410 cplast = cpnext - 1;
411 if (*cplast == '\r') /* CRLF -> '\n' for base64 encoding */
412 *cplast = '\n';
413 else
414 ++cplast;
415
416 /* NUL is now ok, so the test for it was removed */
417
418 flagdone = 1;
419 i = cplast - cp + 1;
420 if (quoted.len && quoted.len <= i &&
421 !str_diffn(cp,quoted.s,quoted.len)) { /* quote chars */
422 if (!stralloc_catb(&line,cp+quoted.len,i-quoted.len)) die_nomem();
423 } else
424 if (!stralloc_catb(&line,cp,i)) die_nomem(); /* no quote chars */
425 }
426 cp = cpnext + 1;
427 } // while done
428
429 if (flagdone == 2) {
430 if (!stralloc_cats(&line,"<<<<< -------------------- <<<<<\n")) die_nomem();
431 code_qput(line.s,line.len);
432 }
433 if (flagcd == 'B') {
434 encode_b64("",0,&line,2);
435 qmail_put(&qq,line.s,line.len);
436 }
437 if (flagmime) {
438 hdr_boundary(0);
440 }
441 qmail_puts(&qq,"\n");
442 if (seek_begin(fd) == -1)
443 logmsg(WHO,111,FATAL,B(ERR_SEEK,fnmsg.s));
444
445 buffer_init(&bt,buffer_unixread,fd,textbuf,sizeof(textbuf));
446 if (buffer_copy(&bq,&bt) != 0)
447 logmsg(WHO,111,FATAL,B(ERR_READ,fnmsg.s));
448 close(fd);
449
450 if (flagmime) hdr_boundary(1);
451
452 if (!stralloc_copy(&line,&outlocal)) die_nomem();
453 if (!stralloc_cats(&line,"-return-@")) die_nomem();
454 if (!stralloc_cat(&line,&outhost)) die_nomem();
455 if (!stralloc_0(&line)) die_nomem();
456 qmail_from(&qq,line.s);
457 if (to.len) qmail_to(&qq,to.s);
458
459 if (!stralloc_copys(&fnnew,"mod/rejected/")) die_nomem();
460 if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
461 if (!stralloc_0(&fnnew)) die_nomem();
462
463/* this is strictly to track what happended to a message to give informative */
464/* messages to the 2nd-nth moderator that acts on the same message. Since */
465/* this isn't vital we ignore errors. Also, it is no big ideal if unlinking */
466/* the old file fails. In the worst case it gets acted on again. If we issue */
467/* a temp error the reject will be redone, which is slightly worse. */
468
469 if (*(err = qmail_close(&qq)) == '\0') {
470 fd = open_trunc(fnnew.s);
471 if (fd != -1)
472 close(fd);
473 unlink(fnmsg.s);
474 strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
475 logmsg(WHO,0,ERROR,B("qp ",strnum));
476 } else
477 logmsg(WHO,111,FATAL,B(ERR_TMP_QMAIL_QUEUE,err + 1));
478
479 } // ACTION: REJECT end -- go for ACCEPT (easier)
480
481 if (str_start(action,ACTION_ACCEPT)) {
482 fd = open_read(fnmsg.s);
483 if (fd == -1)
484 if (errno !=ENOENT)
485 logmsg(WHO,111,FATAL,B(ERR_OPEN,fnmsg.s));
486 else /* shouldn't happen since we've got lock */
487 logmsg(WHO,100,FATAL,B(fnmsg.s,ERR_MOD_TIMEOUT));
488
489 buffer_init(&bt,buffer_unixread,fd,textbuf,sizeof(textbuf));
490
491 if (getln(&bt,&line,&match,'\n') == -1 || !match) /* read "Return-Path:" line */
492 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
493
494 maketo(); /* extract SENDER to "to" */
495 env_put2("SENDER",to.s); /* set SENDER */
496 if (seek_begin(fd) == -1) /* rewind, since we read an entire buffer */
497 logmsg(WHO,111,FATAL,B(ERR_SEEK,fnmsg.s));
498
499 if ((child = wrap_fork()) == 0) {
500 close(0);
501 dup(fd); /* make fnmsg.s stdin */
502 if (argc > optind)
503 wrap_execsh(argv[optind]);
504 else
505 wrap_execbin("/ezmlm-send", &sendopt, dir);
506 }
507
508 /* parent */
509
510 close(fd);
512 if (!stralloc_copys(&fnnew,"mod/accepted/")) die_nomem();
513
514 if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
515 if (!stralloc_0(&fnnew)) die_nomem();
516
517 fd = open_trunc(fnnew.s); /* ignore errors */
518 if (fd != -1)
519 close(fd);
520 unlink(fnmsg.s);
521 _exit(0);
522 }
523
524// return 0;
525}
datetime_sec now(void)
Definition now.c:5
#define COOKIE
Definition cookie.h:4
#define ACTION_REJECT
Definition idx.h:195
#define TXT_DEF_CHARSET
Definition idx.h:93
#define ACTION_ACCEPT
Definition idx.h:194
#define MOD_MIME
Definition idx.h:173
#define TXT_RETURNED_POST
Definition idx.h:109
const char auto_version[]
#define hdr_listsubject1(a)
Definition hdr.h:27
@ CTYPE_TEXT
Definition hdr.h:13
@ CTYPE_MULTIPART
Definition hdr.h:14
@ CTYPE_MESSAGE
Definition hdr.h:16
void wrap_execsh(const char *command)
Definition wrap_execsh.c:9
void wrap_exitcode(int pid)
int wrap_fork(void)
Definition wrap_fork.c:15
void wrap_execbin(const char *program, struct stralloc *opts, const char *dir)
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_MOD_ACCEPTED
Definition errtxt.h:100
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_OPEN
Definition errtxt.h:30
#define ERR_NOLOCAL
Definition errtxt.h:34
#define ERR_BAD_REQUEST
Definition errtxt.h:52
#define ERR_NOEXIST
Definition errtxt.h:40
#define ERR_ANONYMOUS
Definition errtxt.h:44
#define ERR_READ_INPUT
Definition errtxt.h:26
#define ERR_SEEK
Definition errtxt.h:21
#define ERR_MOD_REJECTED
Definition errtxt.h:101
#define ERR_READ
Definition errtxt.h:18
#define ERR_QMAIL_QUEUE
Definition errtxt.h:53
#define ERR_NODEFAULT
Definition errtxt.h:35
#define ERR_MOD_TIMEOUT
Definition errtxt.h:99
#define ERR_SWITCH
Definition errtxt.h:42
#define ERR_STAT
Definition errtxt.h:24
#define ERR_NOSENDER
Definition errtxt.h:37
#define ERR_TMP_QMAIL_QUEUE
Definition errtxt.h:54
#define ERR_BOUNCE
Definition errtxt.h:38
int lockfile(const char *)
Definition lockfile.c:15
long datetime_sec
Definition datetime.h:15
const char * qmail_close(struct qmail *)
Definition qmail.c:120
void qmail_puts(struct qmail *, const char *)
Definition qmail.c:94
void qmail_put(struct qmail *, const char *, int)
Definition qmail.c:87
void qmail_from(struct qmail *, const char *)
Definition qmail.c:103
void qmail_to(struct qmail *, const char *)
Definition qmail.c:113
unsigned long qmail_qp(struct qmail *)
Definition qmail.c:77
int qmail_open(struct qmail *, const stralloc *)
Definition qmail.c:25
charset, outhost, outlocal and flagcd are shared
void die_nomem()
Definition getconf.c:17
int getconf_line(stralloc *sa, const char *fn, int flagrequired, const char *dir)
Definition getconf.c:53
void ezcopy(struct qmail *qqp, const char *fn, char q)
Definition ezcopy.c:128
void set_cpoutlocal(const stralloc *ln)
Definition ezcopy.c:67
void set_cpouthost(const stralloc *ln)
Definition ezcopy.c:73
#define WHO
Definition author.c:1
void encode_qp(const char *indata, unsigned int n, stralloc *outdata)
Definition encode_qp.c:21
stralloc mydtline
Definition ezmlm-get.c:72
void hdr_from(const char *append)
Definition hdr_from.c:23
stralloc fn
char * dir
stralloc text
char encin
int main()
Definition ezmlm-weed.c:69
void decode_b64(const char *cpfrom, unsigned int n, stralloc *outdata)
Definition decode_b64.c:33
void hdr_boundary(int last)
void hdr_datemsgid(unsigned long when)
void cookie(char *hash, const char *key, unsigned int keylen, const char *date, const char *addr, const char *action)
Definition cookie.c:14
int opt
Definition ezmlm-cron.c:53
const char * cp
Definition ezmlm-cron.c:76
unsigned int len
Definition ezmlm-cron.c:68
int fdlock
Definition ezmlm-cron.c:71
char szchar[2]
Definition ezmlm-gate.c:40
char buf[256]
Definition install.c:113
char * local
Definition ezmlm-cgi.c:106
int child
Definition ezmlm-cgi.c:143
int fd
Definition ezmlm-cgi.c:141
datetime_sec when
Definition ezmlm-cgi.c:173
const char * charset
Definition ezmlm-cgi.c:110
int match
Definition ezmlm-cgi.c:140
unsigned int flagmime
Definition ezmlm-cgi.c:145
void die_badformat()
stralloc quoted
Definition ezmlm-clean.c:90
buffer bq
Definition ezmlm-clean.c:81
stralloc mailinglist
Definition ezmlm-clean.c:93
ssize_t qqwrite(int fd, char *buf, unsigned int len)
Definition ezmlm-clean.c:75
char hboundary[HASHLEN]
Definition ezmlm-clean.c:86
stralloc fnmsg
Definition ezmlm-clean.c:60
char flagcd
Definition ezmlm-clean.c:59
stralloc to
Definition ezmlm-clean.c:97
struct qmail qq
Definition ezmlm-clean.c:73
void hdr_transferenc(void)
buffer bs
int checkfile(char *fn)
stralloc reject
stralloc fnsub
stralloc comment
char subbuf[256]
stralloc fnnew
stralloc send
ssize_t qqwrite(int fd, char *buf, unsigned int len)
void maketo()
expects line to be a return-path line. If it is and the format is valid to is set to to the sender....
stralloc accept
void code_qput(char *s, unsigned int n)
void hdr_add2(const char *start, const char *value, unsigned int len)
Definition hdr_add.c:25
void hdr_add2s(const char *start, const char *value)
Definition hdr_add.c:32
void encode_b64(const unsigned char *indata, unsigned int n, stralloc *outdata, int control)
Definition encode_b64.c:75
void hdr_ctype(enum ctype ctype)
Definition hdr_mime.c:24
void hdr_mime(enum ctype ctype)
Definition hdr_mime.c:43
stralloc action
Definition ezmlm-store.c:84
void decode_qp(const char *cpfrom, unsigned int n, stralloc *outdata)
Definition decode_qp.c:35
Definition qmail.h:10
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32