ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
ezmlm-request.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include "stralloc.h"
5#include "error.h"
6#include "qmail.h"
7#include "env.h"
8#include "sig.h"
9#include "open.h"
10#include "getln.h"
11#include "case.h"
12#include "str.h"
13#include "datetime.h"
14#include "now.h"
15#include "quote.h"
16#include "readwrite.h"
17#include "exit.h"
18#include "buffer.h"
19#include "getconf.h"
20#include "constmap.h"
21#include "fmt.h"
22#include "getoptb.h"
23#include "byte.h"
24#include "seek.h"
25#include "errtxt.h"
26#include "ezcopy.h"
27#include "cookie.h"
28#include "subscribe.h"
29#include "mime.h"
30#include "hdr.h"
31#include "idx.h"
32#include "auto_version.h"
33#include "logmsg.h"
34#include "ezmlm.h"
35
36#define WHO "ezmlm-request"
37
43
44
45static void die_usage() { logmsg(WHO,100,USAGE,"ezmlm-request [-f lists.cfg] dir"); }
46static void die_nomem() { logmsg(WHO,111,FATAL,ERR_NOMEM); }
47
48char strnum[FMT_ULONG];
49
50char *userlocal = (char *) 0;
51char *userhost = (char *) 0;
52char *listlocal = (char *) 0;
53char *listhost = (char *) 0;
54const char *cfname = (char *) 0;
55char *command = (char*)"help";
56
57stralloc outhost = {0};
58stralloc outlocal = {0};
59
60stralloc line = {0};
61stralloc qline = {0};
62stralloc usr = {0};
63stralloc lhost = {0};
64stralloc subject = {0};
65stralloc listname = {0};
66stralloc hostname = {0};
67stralloc headerremove = {0};
68stralloc mailinglist = {0};
69stralloc cmds = {0};
70stralloc from = {0};
71stralloc to = {0};
72stralloc charset = {0};
73stralloc quoted = {0};
74char hboundary[COOKIE] = "zxcaeedrqcrtrvthbdty"; /* cheap "rnd" MIME boundary */
75char flagcd = '\0'; /* no encoding by default */
76
77struct constmap headerremovemap;
78struct constmap commandmap;
79int flaggotsub = 0; /* Found a subject */
80 /* cmdstring has all commands seperated by '\'. cmdxlate maps each */
81 /* command alias to the basic command, which is used to construct */
82 /* the command address (positive numbers) or handled by this */
83 /* program (negative numbers). Note: Any command not matched is */
84 /* used to make a command address, so ezmlm request can handle */
85 /* ("transmit") user-added commands. */
86const char *cmdstring =
87 "system\\help\\" /* 1,2 */
88 "subscribe\\unsubscribe\\index\\" /* 3,4,5 */
89 "info\\list\\query\\" /* 6,7,8 */
90 "sub\\unsub\\remove\\signoff\\" /* 9,10,11,12 */
91 "lists\\which\\" /* 13,14 */
92 "ind\\rev\\review\\recipients\\" /* 15,16,17,18 */
93 "who\\showdist\\" /* 19,20 */
94 "put\\set"; /* 21,22 */
95
96 /* map aliases. -> 0 not recognized. -> 1 recognized will be made */
97 /* help and arguments scrapped. < 0 handled locally. HELP without */
98 /* args also handled locally */
99
100
101 /* the last are not supported -> help */
102
103const int cmdxlate[] = { 0,1,2,3,4,5,6,7,8,3,4,4,4,-13,-14,5,7,7,7,7,7,1,1 };
104
105 /* If there are no arguments (listlocal = 0) then commands are mapped*/
106 /* through this. This way, help, list, query, ... can mean something */
107 /* here even though they have local funcions at the lists if used */
108 /* with arguments. (Made same lengh as cmdxlate in case of bugs.) */
109 /* Note: This is used ONLY for the global interface */
110
111const int noargsxlate[] = { 0,1,-2,3,4,5,-2,-13,-14,9,10,11,12,13,14,15,16,17,
112 18,19,20,21,22 };
113
114 /* these need to be defined as the index of the corresponding */
115 /* commands. They are handled by ezmlm-request. NOTE: Help is >0! */
116
117#define EZREQ_LISTS 13
118#define EZREQ_WHICH 14
119#define EZREQ_HELP 2
120#define EZREQ_BAD 1
121
122buffer bt;
123char textbuf[1024];
124
125struct qmail qq;
126
127ssize_t qqwrite(int fd,char *buf,unsigned int len)
128{
130 return len;
131}
132
133char qqbuf[1];
134buffer bq = BUFFER_INIT(qqwrite,-1,qqbuf,(int) sizeof(qqbuf));
135
136char inbuf[1024];
137buffer bi = BUFFER_INIT(read,0,inbuf,(int) sizeof(inbuf));
138buffer bj = BUFFER_INIT(read,0,inbuf,(int) sizeof(inbuf));
139
140buffer bo;
141char outbuf[1];
142
143stralloc mydtline = {0};
144
145int code_qput(char *s,unsigned int n)
146{
147 if (!flagcd)
148 qmail_put(&qq,s,n);
149 else {
150 if (flagcd == 'B')
151 encode_b64(s,n,&qline,0);
152 else
153 encode_qp(s,n,&qline);
154 qmail_put(&qq,qline.s,qline.len);
155 }
156 return 0; /* always succeeds */
157}
158
165
166void checkarg(char *s)
167{
168 char *cp;
169 char ch;
170 cp = s;
171 if (!cp) return; /* undef is ok */
172
173 while ((ch = *cp++)) {
174 if (ch >= 'a' && ch <= 'z')
175 continue; /* lc letters */
176 if (ch >= '0' && ch <='9') /* digits */
177 continue;
178 if (ch == '.' || ch == '-' || ch == '_' || ch == '+')
179 continue; /* ok chars */
180 if (ch >= 'A' && ch <= 'Z') continue; /* UC LETTERS */
181 logmsg(WHO,100,FATAL,B(ERR_NOT_CLEAN,"\\",s,"\\"));
182 }
183 return;
184}
185
210
211void parseline(char *cp)
212{
213 char *cp1;
214 char *cp2;
215 char *cp3;
216
217 cp1 = cp;
218 while (*cp1) { /* make tabs into spaces */
219 if (*cp1 == '\t') *cp1 = ' ';
220 ++cp1;
221 }
222 /* NOTE: outlocal has '\0' added! */
223 if (outlocal.len < str_len(cp) && cp[outlocal.len -1] == '-' &&
224 case_starts(cp,outlocal.s)) { /* normal ezmlm cmd */
225 command = cp + outlocal.len; /* after the '-' */
226 listlocal = outlocal.s;
227 listhost = outhost.s;
228 cp1 = command;
229 while (*cp1 && *cp1 != '-') /* find next '-' */
230 ++cp1;
231
232 if (*cp1) {
233 *cp1 = '\0';
234 userlocal = ++cp1; /* after '-' */
235 cp1 = cp1 + str_rchr(cp1,'@'); /* @ _or_ end */
236 *cp1 = '\0'; /* last '=' in userlocal */
237 cp1 = userlocal + str_rchr(userlocal,'=');
238 if (*cp1) { /* found '=' */
239 *cp1 = '\0'; /* zap */
240 userhost = cp1 + 1; /* char after '=' */
241 }
242 }
243 } else { /* '@' before ' ' means complete cmd */
244 if (str_chr(cp,'@') < str_chr(cp,' ')) /* addr where local failed */
245 logmsg(WHO,100,FATAL,ERR_REQ_LOCAL);
246 /* to match */
247 command = cp;
248 cp1 = cp + str_chr(cp,' ');
249 if (*cp1) {
250 *cp1++ = '\0';
251 while (*cp1 && *cp1 == ' ') /* skip spaces */
252 ++cp1;
253 }
254 cp2 = 0;
255 if (*cp1) { /* argument */
256 cp2 = cp1 + str_chr(cp1,' ');
257 cp3 = cp2;
258 while (*cp2 && *cp2 == ' ') /* skip spaces */
259 ++cp2;
260 *cp3 = '\0';
261
262 if (!*cp2)
263 cp2 = 0;
264 else {
265 cp3 = cp2 + str_chr(cp2,' ');
266 *cp3 = '\0';
267 }
268 } else
269 cp1 = 0;
270
271 if (!cfname && !cp2) { /* the single arg is user if we serve a */
272 cp2 = cp1; /* list. It's list if we serve "domo@" */
273 cp1 = 0;
274 }
275 if (cp2) {
276 userlocal = cp2;
277 cp2 += str_chr(cp2,'@');
278 if (*cp2) {
279 *cp2++ = '\0';
280 userhost = cp2;
281 }
282 }
283 if (cp1) {
284 listlocal = cp1;
285 cp1 += str_chr(cp1,'@');
286 if (*cp1) {
287 *cp1++ = '\0';
288 listhost = cp1;
289 }
290 }
291 }
292 checkarg(command); /* better safe than sorry */
295}
296
297int main(int argc,char **argv)
298{
299 char *dir;
300 char *local;
301 char *action;
302 char *def;
303 char *sender;
304 char *psz;
305 const char *err;
306 int cmdidx;
307 int flagsub;
308 int flagok;
309 int flagnosubject;
310 int match;
311 int flaginheader;
312 int flagbadfield;
313 int flagmultipart = 0;
314 int fd;
315 int opt;
316 unsigned int pos,pos1,len,last;
317
318 umask(022);
319 sig_pipeignore();
320
321 while ((opt = getoptb(argc,argv,"f:F:vV")) != opteof)
322 switch(opt) {
323 case 'F':
324 case 'f': if (optarg) cfname = optarg; break;
325 case 'v':
326 case 'V': logmsg(WHO,0,VERSION,auto_version); break;
327 default: die_usage();
328 }
329
330 dir = argv[optind];
331 if (!dir) die_usage();
332
333 if (chdir(dir) == -1)
334 logmsg(WHO,111,FATAL,B(ERR_SWITCH,dir));
335
336 /* do minimum to identify request for this program in case */
337 /* it's invoked in line with e.g. ezmlm-manage */
338
339 def = env_get("DEFAULT");
340 if (def) {
341 action = def;
342 } else if (cfname) { /* just list-mdomo */
343 local = env_get("LOCAL");
344 if (!local) logmsg(WHO,100,FATAL,ERR_NOLOCAL);
345 len = str_len(local);
346 if (len >= 8 && !case_diffb(local + len - 8,8,"-return-")) {
347 action = (char*)"return-"; /* our bounce with qmail<1.02 */
348 } else
349 action = (char*)""; /* list-mdomo-xxx won't work for older lists */
350 } else
351 logmsg(WHO,100,FATAL,B(ERR_NODEFAULT," and -f not used"));
352 /* at this point action = "request" or "request-..." for std use; */
353 /* "" for majordomo@ */
354 if (!cfname) { /* expect request */
355 if (case_starts(action,ACTION_REQUEST))
356 action += str_len(ACTION_REQUEST);
357 else if (case_starts(action,ALT_REQUEST))
358 action += str_len(ALT_REQUEST);
359 else
360 _exit(0); /* not for us */
361 }
362 getconf_line(&outlocal,"outlocal",1,dir);
363 getconf_line(&outhost,"outhost",1,dir);
364
365 if (!stralloc_copy(&listname,&outlocal)) die_nomem();
366 if (!stralloc_copy(&hostname,&outhost)) die_nomem();
367 if (!stralloc_0(&outlocal)) die_nomem();
368 if (!stralloc_0(&outhost)) die_nomem();
369
370 sender = env_get("SENDER");
371 if (!sender) logmsg(WHO,99,ERROR,ERR_NOSENDER);
372 if (!*sender)
373 logmsg(WHO,99,ERROR,ERR_BOUNCE);
374 if (!sender[str_chr(sender,'@')])
375 logmsg(WHO,99,INFO,ERR_ANONYMOUS);
376 if (str_equal(sender,"#@[]"))
377 logmsg(WHO,99,INFO,ERR_BOUNCE);
378
379 getconf(&headerremove,"headerremove",1,dir);
380 constmap_init(&headerremovemap,headerremove.s,headerremove.len,0);
381
382 if (!stralloc_copys(&mydtline,
383 "Delivered-To: request processor for ")) die_nomem();
384 if (!stralloc_cats(&mydtline,outlocal.s)) die_nomem();
385 if (!stralloc_cats(&mydtline,"@")) die_nomem();
386 if (!stralloc_cats(&mydtline,outhost.s)) die_nomem();
387 if (!stralloc_cats(&mydtline,"\n")) die_nomem();
388
389 flagnosubject = 1;
390 if (action[0]) { /* mainly to allow ezmlm-lists or ezmlm-which with */
391 flagnosubject = 0; /* a command address rather than a complete msg */
392 command = action;
393 if (str_start(action,"return")) /* kill bounces */
394 logmsg(WHO,0,INFO,ERR_BOUNCE);
395 pos = 1 + str_chr(action + 1,'-');
396 if (action[pos]) { /* start of target */
397 action[pos] = '\0';
398 userlocal = action + pos + 1;
399 pos = str_rchr(userlocal,'='); /* the "pseudo-@" */
400 if (userlocal[pos]) {
401 userlocal[pos] = '\0';
402 userhost = userlocal + pos + 1;
403 }
404 }
405 } else {
406 for (flagsub;;) { /* Get Subject: */
407 if (getln(&bi,&line,&match,'\n') == -1)
408 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
409 if (line.len <= 1)
410 break;
411 if ((line.s[0] != ' ') && (line.s[0] != '\t')) {
412 flagsub = 0;
413
414 if (case_startb(line.s,line.len,"mailing-list:")) {
415 logmsg(WHO,100,FATAL,ERR_MAILING_LIST);
416 } else if (case_startb(line.s,line.len,"Subject:")) {
417 flagsub = flaggotsub = 1;
418 pos = 8;
419 last = line.len - 2; /* skip terminal '\n' */
420 while (line.s[last] == ' ' || line.s[last] == '\t') --last;
421 while (pos <= last && (line.s[pos] == ' ' || line.s[pos] == '\t'))
422 ++pos;
423 if (!stralloc_copyb(&subject,line.s+pos,last-pos+1)) die_nomem();
424 } else if (case_startb(line.s,line.len,"content-type:")) {
425 pos = 13; last = line.len - 2; /* not cont-line - ok */
426 while (pos <= last && (line.s[pos] == ' ' || line.s[pos] == '\t'))
427 ++pos;
428 if (case_startb(line.s+pos,line.len - pos,"multipart/"))
429 flagmultipart = 1;
430 } else if (line.len == mydtline.len)
431 if (!byte_diff(line.s,line.len,mydtline.s))
432 logmsg(WHO,100,FATAL,ERR_LOOPING);
433 } else if (flagsub) { /* Continuation line */
434 pos = 1;
435 len = line.len - 2; /* skip terminal '\n' */
436 while (line.s[len] == ' ' || line.s[len] == '\t')
437 --len;
438 while (pos < len && (line.s[pos] == ' ' || line.s[pos] == '\t'))
439 ++pos;
440 if (!stralloc_append(&subject," ")) die_nomem();
441 if (!stralloc_catb(&subject,line.s+pos,len-pos+1)) die_nomem();
442 }
443 if (!match)
444 break;
445 }
446 if (!cfname) { /* listserv@/majordomo@ ignore */
447 char ch;
448 if (!stralloc_0(&subject)) die_nomem();
449 ch = *subject.s; /* valid commands/list names start w letter */
450 if ((ch <= 'z' && ch >= 'a') || (ch <= 'Z' && ch >= 'A')) {
452 flagnosubject = 0;
453 }
454 }
455 if (cfname || flagnosubject) {
456 for (;;) { /* parse body */
457 if (getln(&bi,&line,&match,'\n') == -1)
458 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
459 if (!match) break;
460 if (line.len == 1 && flagmultipart != 2) continue;
461 /* lazy MIME cludge assumes first '--...' is start border */
462 /* which is virtually always true */
463 if (flagmultipart == 1) { /* skip to first border */
464 if (*line.s != '-' || line.s[1] != '-') continue;
465 flagmultipart = 2;
466 continue;
467 } else if (flagmultipart == 2) { /* skip content info */
468 if (line.len != 1) continue;
469 flagmultipart = 3; /* may be part within part */
470 continue; /* and blank line */
471 } else if (flagmultipart == 3) {
472 if (*line.s == '-' && line.s[1] == '-') {
473 flagmultipart = 2; /* part within part */
474 continue;
475 }
476 }
477 /* Sheltered */
478 {
479 char ch;
480 ch = *line.s;
481 if (line.len == 1 || !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
482 continue; /* skip if not letter pos 1 */
483 }
484 /* Here we have a body line with something */
485 if (!stralloc_copy(&subject,&line)) die_nomem(); /* save it */
486 subject.s[subject.len-1] = '\0';
488 break;
489 }
490 }
491 }
492 /* Do command substitution */
493 if (!stralloc_copys(&cmds,cmdstring)) die_nomem();
494 if (!stralloc_0(&cmds)) die_nomem();
495 psz = cmds.s;
496 while (*psz) {
497 if (*psz == '\\') *psz = '\0';
498 ++psz;
499 }
500 if (!constmap_init(&commandmap,cmds.s,cmds.len,0)) die_nomem();
501 cmdidx = cmdxlate[constmap_index(&commandmap,command,str_len(command))];
502 if (cmdidx == EZREQ_BAD) { /* recognized, but not supported -> help */
503 listlocal = 0; /* needed 'cause arguments are who-knows-what */
504 listhost = 0;
505 userlocal = 0;
506 userhost = 0;
507 cmdidx = EZREQ_HELP;
508 }
509 if (cfname && !listlocal && !userlocal && cmdidx > 0)
510 cmdidx = noargsxlate[cmdidx]; /* some done differently if no args */
511
512 /* =0 not found. This is treated as a list command! */
513 if (cmdidx < 0 && !cfname) {
514 cmdidx = EZREQ_HELP;
515 }
516 if (qmail_open(&qq,(stralloc *) 0) == -1)
517 logmsg(WHO,111,FATAL,ERR_QMAIL_QUEUE);
518
519 if (cmdidx >= 0) {
520 /* Things handled elsewhere. We do want to handle a simple HELP */
521 /* without arguments for e.g. majordomo@ from our own help file */
522
523 if (!stralloc_copys(&from,sender)) die_nomem();
524 if (!stralloc_0(&from)) die_nomem();
525 if (!listlocal) {
526 if (cfname)
527 logmsg(WHO,100,FATAL,ERR_REQ_LISTNAME);
528 else
529 listlocal = outlocal.s; /* This is at the -request address */
530 }
531 /* if !cfname listhost is made outhost. If cfname, listhost=outhost */
532 /* is ok. listhost=0 => first match in config. Other listhost is ok */
533 /* only if match is found. Otherwise it's set to outhost. */
534
535 if (!cfname || (listhost && !case_diffs(listhost,outhost.s)))
536 listhost = outhost.s;
537 else { /* Check listhost against config file */
538 pos = str_len(listlocal);
539 fd = open_read(cfname);
540 if (fd == -1)
541 logmsg(WHO,111,FATAL,B(ERR_OPEN,cfname));
542 buffer_init(&bt,buffer_unixread,fd,textbuf,sizeof(textbuf));
543 flagok = 0; /* got listhost match */
544 for (;;) {
545 if (getln(&bt,&line,&match,'\n') == -1)
546 logmsg(WHO,111,FATAL,B(ERR_READ,cfname));
547 if (!match)
548 break;
549 if (line.len <= 1 || line.s[0] == '#')
550 continue;
551 if ((pos < line.len) && (line.s[pos] == '@') && !byte_diff(line.s,pos,listlocal)) {
552 last = byte_chr(line.s,line.len,':');
553 if (!stralloc_copyb(&lhost,line.s + pos + 1,last - pos - 1)) die_nomem();
554 if (!stralloc_0(&lhost)) die_nomem();
555 if (listhost) {
556 if (!case_diffs(listhost,lhost.s)) {
557 flagok = 1;
558 break; /* host did match */
559 } else
560 continue; /* host didn't match */
561 } else { /* none given - grab first */
562 listhost = lhost.s;
563 flagok = 1;
564 break;
565 }
566 }
567 }
568 if (!flagok)
569 listhost = outhost.s;
570 close(fd);
571 }
572 if (!listhost)
573 listhost = outhost.s;
574 if (!userlocal) {
575 if (!stralloc_copys(&usr,sender)) die_nomem();
576 if (!stralloc_0(&usr)) die_nomem();
577 userlocal = usr.s;
578 userhost = usr.s + byte_rchr(usr.s,usr.len-1,'@');
579 if (!*userhost)
580 userhost = 0;
581 else {
582 *userhost = '\0';
583 ++userhost;
584 }
585 }
586
587 if (!stralloc_copys(&to,listlocal)) die_nomem();
588 if (!stralloc_cats(&to,"-")) die_nomem();
589 if (cmdidx) { /* recognized - substitute */
590 if (!stralloc_cats(&to,constmap_get(&commandmap,cmdidx)))
591 die_nomem();
592 } else /* not recognized - use as is */
593 if (!stralloc_cats(&to,command)) die_nomem();
594
595 if (!stralloc_cats(&to,"-")) die_nomem();
596 if (!stralloc_cats(&to,userlocal)) die_nomem();
597 if (userhost) { /* doesn't exist for e.g. -get */
598 if (!stralloc_cats(&to,"=")) die_nomem();
599 if (!stralloc_cats(&to,userhost)) die_nomem();
600 }
601 if (!stralloc_cats(&to,"@")) die_nomem();
602 if (!stralloc_cats(&to,listhost)) die_nomem();
603 if (!stralloc_0(&to)) die_nomem();
604
606
607 flaginheader = 1;
608 flagbadfield = 0;
609
610 if (seek_begin(0) == -1)
611 logmsg(WHO,111,FATAL,ERR_SEEK_INPUT);
612 buffer_init(&bi,buffer_unixread,0,inbuf,sizeof(inbuf));
613
614 for (;;) {
615 if (getln(&bi,&line,&match,'\n') == -1)
616 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
617
618 if (flaginheader && match) {
619 if (line.len == 1)
620 flaginheader = 0;
621 if ((line.s[0] != ' ') && (line.s[0] != '\t')) {
622 flagbadfield = 0;
623 if (constmap(&headerremovemap,line.s,byte_chr(line.s,line.len,':')))
624 flagbadfield = 1;
625 }
626 }
627 if (!(flaginheader && flagbadfield))
628 qmail_put(&qq,line.s,line.len);
629 if (!match)
630 break;
631 }
632 } else { /* commands we deal with */
633 cmdidx = - cmdidx; /* now positive */
634 if (cmdidx == EZREQ_WHICH) { /* arg is user, not list */
637 }
638 if (!stralloc_copys(&from,outlocal.s)) die_nomem();
639 if (!stralloc_cats(&from,"-return-@")) die_nomem();
640 if (!stralloc_cats(&from,outhost.s)) die_nomem();
641 if (!stralloc_0(&from)) die_nomem();
642
643 if (userlocal) {
644 if (!stralloc_copys(&to,userlocal)) die_nomem();
645 if (!stralloc_cats(&to,"@")) die_nomem();
646 if (userhost) {
647 if (!stralloc_cats(&to,userhost)) die_nomem();
648 } else {
649 if (!stralloc_cats(&to,outhost.s)) die_nomem();
650 }
651 } else
652 if (!stralloc_copys(&to,sender)) die_nomem();
653 if (!stralloc_0(&to)) die_nomem();
654
655 /* now we need to look for charset and set flagcd appropriately */
656
657 if (getconf_line(&charset,"charset",0,dir)) {
658 if (charset.len >= 2 && charset.s[charset.len - 2] == ':') {
659 if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') {
660 flagcd = charset.s[charset.len - 1];
661 charset.s[charset.len - 2] = '\0';
662 }
663 }
664 } else
665 if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem();
666 if (!stralloc_0(&charset)) die_nomem();
667
668 set_cpoutlocal(&listname); /* necessary in case there are <#l#> */
669 set_cpouthost(&hostname); /* necessary in case there are <#h#> */
670 /* we don't want to be send to a list*/
671 hdr_adds("Mailing-List: ezmlm-request");
672 if (getconf_line(&line,"listid",0,dir))
673 hdr_add2("List-ID: ",line.s,line.len);
675 hdr_from((cmdidx == EZREQ_HELP) ? "-return-" : "-help");
677 if (!quote2(&line,to.s)) die_nomem();
678 hdr_add2("To: ",line.s,line.len);
680 qmail_puts(&qq,"Subject: ");
681 if (!quote2(&line,outlocal.s)) die_nomem();
682 qmail_put(&qq,line.s,line.len);
685 ezcopy(&qq,"text/top",flagcd);
686 if (cmdidx == EZREQ_LISTS || cmdidx == EZREQ_WHICH) {
687 switch (cmdidx) {
688 case EZREQ_LISTS: code_qput("LISTS:",6);
689 break;
690 case EZREQ_WHICH: code_qput("WHICH (",7);
691 code_qput(to.s,to.len - 1);
692 code_qput("):\n\n",4);
693 break;
694 default: break;
695 }
696 fd = open_read(cfname);
697 if (fd == -1)
698 logmsg(WHO,111,FATAL,B(ERR_OPEN,cfname));
699 buffer_init(&bt,buffer_unixread,fd,textbuf,sizeof(textbuf));
700
701 for (;;) {
702 if (getln(&bt,&line,&match,'\n') == -1)
703 logmsg(WHO,111,FATAL,B(ERR_READ,cfname));
704 if (!match)
705 break;
706 if (line.len <= 1 || line.s[0] == '#')
707 continue;
708 if (!stralloc_0(&line)) die_nomem();
709 pos = str_chr(line.s,':');
710 if (!line.s[pos])
711 break;
712 line.s[pos] = '\0';
713 ++pos;
714 pos1 = pos + str_chr(line.s + pos,':');
715 if (line.s[pos1]) {
716 line.s[pos1] = '\0';
717 ++pos1;
718 } else
719 pos1 = 0;
720
721 switch (cmdidx) {
722 case EZREQ_LISTS: code_qput("\n\n\t",3);
723 code_qput(line.s,pos-1);
724 code_qput("\n",1);
725 if (pos1) code_qput(line.s + pos1,line.len - 2 - pos1);
726 break;
727 case EZREQ_WHICH: if (issub(line.s + pos,0,(char *) 0)) {
728 code_qput(line.s,pos-1);
729 code_qput("\n",1);
730 }
731 closesql(); /* likely different dbs for different lists */
732 break;
733 }
734 }
735 code_qput("\n",1);
736 close(fd);
737 } else
738 ezcopy(&qq,"text/help",flagcd);
739
740 ezcopy(&qq,"text/bottom",flagcd);
741 if (flagcd) {
742 if (flagcd == 'B') {
743 encode_b64("",0,&line,2); /* flush */
744 qmail_put(&qq,line.s,line.len);
745 }
746 hdr_boundary(0);
748 hdr_adds("Content-Disposition: inline; filename=request.msg");
749 qmail_puts(&qq,"\n");
750 }
751 qmail_puts(&qq,"Return-Path: <");
752 if (!quote2(&line,sender)) die_nomem();
753 qmail_put(&qq,line.s,line.len);
754 qmail_puts(&qq,">\n");
755 if (seek_begin(0) == -1)
756 logmsg(WHO,111,FATAL,ERR_SEEK_INPUT);
757 if (buffer_copy(&bq,&bj) != 0)
758 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
759 if (flagcd)
760 hdr_boundary(1);
761 }
762 qmail_from(&qq,from.s);
763 qmail_to(&qq,to.s);
764 if (*(err = qmail_close(&qq)) != '\0')
765 logmsg(WHO,111,FATAL,B(ERR_TMP_QMAIL_QUEUE,err + 1));
766
767 strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
768 logmsg(WHO,99,ERROR,B("qp ",strnum));
769
770 return 0;
771}
datetime_sec now(void)
Definition now.c:5
#define COOKIE
Definition cookie.h:4
#define TXT_DEF_CHARSET
Definition idx.h:93
#define ALT_REQUEST
Definition idx.h:53
#define TXT_RESULTS
Definition idx.h:137
#define ACTION_REQUEST
Definition idx.h:191
int issub()
Returns (char *) to match if userhost is in the subscriber database dbname, 0 otherwise....
int quote2(stralloc *sa, const char *s)
Definition quote.c:65
const char auto_version[]
@ CTYPE_TEXT
Definition hdr.h:13
@ CTYPE_MULTIPART
Definition hdr.h:14
@ CTYPE_MESSAGE
Definition hdr.h:16
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_OPEN
Definition errtxt.h:30
#define ERR_NOLOCAL
Definition errtxt.h:34
#define ERR_ANONYMOUS
Definition errtxt.h:44
#define ERR_READ_INPUT
Definition errtxt.h:26
#define ERR_REQ_LOCAL
Definition errtxt.h:73
#define ERR_MAILING_LIST
Definition errtxt.h:57
#define ERR_READ
Definition errtxt.h:18
#define ERR_LOOPING
Definition errtxt.h:58
#define ERR_QMAIL_QUEUE
Definition errtxt.h:53
#define ERR_NODEFAULT
Definition errtxt.h:35
#define ERR_SWITCH
Definition errtxt.h:42
#define ERR_SEEK_INPUT
Definition errtxt.h:27
#define ERR_NOSENDER
Definition errtxt.h:37
#define ERR_TMP_QMAIL_QUEUE
Definition errtxt.h:54
#define ERR_BOUNCE
Definition errtxt.h:38
#define ERR_REQ_LISTNAME
Definition errtxt.h:72
#define ERR_NOT_CLEAN
Definition errtxt.h:130
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 closesql(void)
close connection to SQL server, if open
Definition opensql.c:21
void die_nomem()
Definition getconf.c:17
int getconf(stralloc *sa, const char *fn, int flagrequired, const char *dir)
Definition getconf.c:21
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
buffer bj
Definition ezmlm-get.c:154
int flagsub
Definition ezmlm-get.c:54
void hdr_from(const char *append)
Definition hdr_from.c:23
char inbuf[1024]
char outbuf[1024]
char * dir
buffer bi
buffer bo
stralloc from
int main()
Definition ezmlm-weed.c:69
void hdr_boundary(int last)
const int noargsxlate[]
void parseline(char *cp)
struct constmap commandmap
stralloc headerremove
#define EZREQ_LISTS
stralloc lhost
char * listhost
char * userhost
ssize_t qqwrite(int fd, char *buf, unsigned int len)
const char * cmdstring
#define EZREQ_WHICH
#define EZREQ_BAD
struct constmap headerremovemap
stralloc hostname
void checkarg(char *s)
#define EZREQ_HELP
char * userlocal
stralloc usr
char * command
int flaggotsub
const char * cfname
const int cmdxlate[]
char * listlocal
int code_qput(char *s, unsigned int n)
void hdr_datemsgid(unsigned long when)
int opt
Definition ezmlm-cron.c:53
const char * cp
Definition ezmlm-cron.c:76
unsigned int len
Definition ezmlm-cron.c:68
stralloc cmds
Definition ezmlm-gate.c:36
char buf[256]
Definition install.c:113
char * local
Definition ezmlm-cgi.c:106
int fd
Definition ezmlm-cgi.c:141
stralloc listname
Definition ezmlm-cgi.c:132
const char * charset
Definition ezmlm-cgi.c:110
int match
Definition ezmlm-cgi.c:140
stralloc subject
Definition ezmlm-cgi.c:119
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
char flagcd
Definition ezmlm-clean.c:59
stralloc to
Definition ezmlm-clean.c:97
struct qmail qq
Definition ezmlm-clean.c:73
void hdr_add2(const char *start, const char *value, unsigned int len)
Definition hdr_add.c:25
void hdr_adds(const char *line)
Definition hdr_add.c:19
void hdr_ctboundary(void)
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
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