debian/rules: Use `git' potty wrapper.
[qmail] / qmail-inject.c
CommitLineData
2117e02e
MW
1#include "sig.h"
2#include "substdio.h"
3#include "stralloc.h"
4#include "subfd.h"
5#include "sgetopt.h"
6#include "getln.h"
7#include "alloc.h"
8#include "str.h"
9#include "fmt.h"
10#include "hfield.h"
11#include "token822.h"
12#include "control.h"
13#include "env.h"
14#include "gen_alloc.h"
15#include "gen_allocdefs.h"
16#include "error.h"
17#include "qmail.h"
18#include "now.h"
19#include "exit.h"
20#include "quote.h"
21#include "headerbody.h"
22#include "auto_qmail.h"
23#include "newfield.h"
212b6f5d 24#include "constmap.h"
2117e02e
MW
25
26#define LINELEN 80
27
28datetime_sec starttime;
29
30char *qmopts;
31int flagdeletesender = 0;
32int flagdeletefrom = 0;
33int flagdeletemessid = 0;
34int flagnamecomment = 0;
35int flaghackmess = 0;
36int flaghackrecip = 0;
37char *mailhost;
38char *mailuser;
39int mailusertokentype;
40char *mailrhost;
41char *mailruser;
42
43stralloc control_idhost = {0};
44stralloc control_defaultdomain = {0};
45stralloc control_defaulthost = {0};
46stralloc control_plusdomain = {0};
47
48stralloc sender = {0};
49stralloc envsbuf = {0};
50token822_alloc envs = {0};
51int flagrh;
52
53int flagqueue;
54struct qmail qqt;
55
56void put(s,len) char *s; int len;
57{ if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); }
58void puts(s) char *s; { put(s,str_len(s)); }
59
60void perm() { _exit(100); }
61void temp() { _exit(111); }
62void die_nomem() {
63 substdio_putsflush(subfderr,"qmail-inject: fatal: out of memory\n"); temp(); }
64void die_invalid(sa) stralloc *sa; {
65 substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: ");
66 substdio_putflush(subfderr,sa->s,sa->len); perm(); }
2117e02e
MW
67void die_qqt() {
68 substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); }
69void die_chdir() {
70 substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); }
2117e02e
MW
71void die_read() {
72 if (errno == error_nomem) die_nomem();
73 substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); }
74void doordie(sa,r) stralloc *sa; int r; {
75 if (r == 1) return; if (r == -1) die_nomem();
76 substdio_putsflush(subfderr,"qmail-inject: fatal: unable to parse this line:\n");
77 substdio_putflush(subfderr,sa->s,sa->len); perm(); }
78
2117e02e
MW
79GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
80GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
81
82static stralloc sauninit = {0};
83
84saa savedh = {0};
85saa hrlist = {0};
212b6f5d 86saa tocclist = {0};
2117e02e
MW
87saa hrrlist = {0};
88saa reciplist = {0};
89int flagresent;
90
91void exitnicely()
92{
212b6f5d
MW
93 char *qqx;
94
2117e02e
MW
95 if (!flagqueue) substdio_flush(subfdout);
96
97 if (flagqueue)
98 {
99 int i;
100
101 if (!stralloc_0(&sender)) die_nomem();
102 qmail_from(&qqt,sender.s);
103
104 for (i = 0;i < reciplist.len;++i)
105 {
106 if (!stralloc_0(&reciplist.sa[i])) die_nomem();
107 qmail_to(&qqt,reciplist.sa[i].s);
108 }
109 if (flagrh)
110 if (flagresent)
111 for (i = 0;i < hrrlist.len;++i)
112 {
113 if (!stralloc_0(&hrrlist.sa[i])) die_nomem();
114 qmail_to(&qqt,hrrlist.sa[i].s);
115 }
116 else
117 for (i = 0;i < hrlist.len;++i)
118 {
119 if (!stralloc_0(&hrlist.sa[i])) die_nomem();
120 qmail_to(&qqt,hrlist.sa[i].s);
121 }
122
212b6f5d
MW
123 qqx = qmail_close(&qqt);
124 if (*qqx)
125 if (*qqx == 'D') {
126 substdio_puts(subfderr,"qmail-inject: fatal: ");
127 substdio_puts(subfderr,qqx + 1);
128 substdio_puts(subfderr,"\n");
129 substdio_flush(subfderr);
130 perm();
131 }
132 else {
133 substdio_puts(subfderr,"qmail-inject: fatal: ");
134 substdio_puts(subfderr,qqx + 1);
135 substdio_puts(subfderr,"\n");
136 substdio_flush(subfderr);
137 temp();
138 }
2117e02e
MW
139 }
140
141 _exit(0);
142}
143
144void savedh_append(h)
145stralloc *h;
146{
147 if (!saa_readyplus(&savedh,1)) die_nomem();
148 savedh.sa[savedh.len] = sauninit;
149 if (!stralloc_copy(savedh.sa + savedh.len,h)) die_nomem();
150 ++savedh.len;
151}
152
153void savedh_print()
154{
155 int i;
156
157 for (i = 0;i < savedh.len;++i)
158 put(savedh.sa[i].s,savedh.sa[i].len);
159}
160
161stralloc defaultdomainbuf = {0};
162token822_alloc defaultdomain = {0};
163stralloc defaulthostbuf = {0};
164token822_alloc defaulthost = {0};
165stralloc plusdomainbuf = {0};
166token822_alloc plusdomain = {0};
167
168void rwroute(addr)
169token822_alloc *addr;
170{
171 if (addr->t[addr->len - 1].type == TOKEN822_AT)
172 while (addr->len)
173 if (addr->t[--addr->len].type == TOKEN822_COLON)
174 return;
175}
176
177void rwextraat(addr)
178token822_alloc *addr;
179{
180 int i;
181 if (addr->t[0].type == TOKEN822_AT)
182 {
183 --addr->len;
184 for (i = 0;i < addr->len;++i)
185 addr->t[i] = addr->t[i + 1];
186 }
187}
188
189void rwextradot(addr)
190token822_alloc *addr;
191{
192 int i;
193 if (addr->t[0].type == TOKEN822_DOT)
194 {
195 --addr->len;
196 for (i = 0;i < addr->len;++i)
197 addr->t[i] = addr->t[i + 1];
198 }
199}
200
201void rwnoat(addr)
202token822_alloc *addr;
203{
204 int i;
205 int shift;
206
207 for (i = 0;i < addr->len;++i)
208 if (addr->t[i].type == TOKEN822_AT)
209 return;
210 shift = defaulthost.len;
211 if (!token822_readyplus(addr,shift)) die_nomem();
212 for (i = addr->len - 1;i >= 0;--i)
213 addr->t[i + shift] = addr->t[i];
214 addr->len += shift;
215 for (i = 0;i < shift;++i)
216 addr->t[i] = defaulthost.t[shift - 1 - i];
217}
218
219void rwnodot(addr)
220token822_alloc *addr;
221{
222 int i;
223 int shift;
224 for (i = 0;i < addr->len;++i)
225 {
226 if (addr->t[i].type == TOKEN822_DOT)
227 return;
228 if (addr->t[i].type == TOKEN822_AT)
229 break;
230 }
231 for (i = 0;i < addr->len;++i)
232 {
233 if (addr->t[i].type == TOKEN822_LITERAL)
234 return;
235 if (addr->t[i].type == TOKEN822_AT)
236 break;
237 }
238 shift = defaultdomain.len;
239 if (!token822_readyplus(addr,shift)) die_nomem();
240 for (i = addr->len - 1;i >= 0;--i)
241 addr->t[i + shift] = addr->t[i];
242 addr->len += shift;
243 for (i = 0;i < shift;++i)
244 addr->t[i] = defaultdomain.t[shift - 1 - i];
245}
246
247void rwplus(addr)
248token822_alloc *addr;
249{
250 int i;
251 int shift;
252
253 if (addr->t[0].type != TOKEN822_ATOM) return;
254 if (!addr->t[0].slen) return;
255 if (addr->t[0].s[addr->t[0].slen - 1] != '+') return;
256
257 --addr->t[0].slen; /* remove + */
258
259 shift = plusdomain.len;
260 if (!token822_readyplus(addr,shift)) die_nomem();
261 for (i = addr->len - 1;i >= 0;--i)
262 addr->t[i + shift] = addr->t[i];
263 addr->len += shift;
264 for (i = 0;i < shift;++i)
265 addr->t[i] = plusdomain.t[shift - 1 - i];
266}
267
268void rwgeneric(addr)
269token822_alloc *addr;
270{
271 if (!addr->len) return; /* don't rewrite <> */
272 if (addr->len >= 2)
273 if (addr->t[1].type == TOKEN822_AT)
274 if (addr->t[0].type == TOKEN822_LITERAL)
275 if (!addr->t[0].slen) /* don't rewrite <foo@[]> */
276 return;
277 rwroute(addr);
278 if (!addr->len) return; /* <@foo:> -> <> */
279 rwextradot(addr);
280 if (!addr->len) return; /* <.> -> <> */
281 rwextraat(addr);
282 if (!addr->len) return; /* <@> -> <> */
283 rwnoat(addr);
284 rwplus(addr);
285 rwnodot(addr);
286}
287
288int setreturn(addr)
289token822_alloc *addr;
290{
291 if (!sender.s)
292 {
293 token822_reverse(addr);
294 if (token822_unquote(&sender,addr) != 1) die_nomem();
295 if (flaghackrecip)
296 if (!stralloc_cats(&sender,"-@[]")) die_nomem();
297 token822_reverse(addr);
298 }
299 return 1;
300}
301
302int rwreturn(addr)
303token822_alloc *addr;
304{
305 rwgeneric(addr);
306 setreturn(addr);
307 return 1;
308}
309
310int rwsender(addr)
311token822_alloc *addr;
312{
313 rwgeneric(addr);
314 return 1;
315}
316
212b6f5d 317void rwappend(addr,xl)
2117e02e
MW
318token822_alloc *addr;
319saa *xl;
320{
2117e02e
MW
321 token822_reverse(addr);
322 if (!saa_readyplus(xl,1)) die_nomem();
323 xl->sa[xl->len] = sauninit;
324 if (token822_unquote(&xl->sa[xl->len],addr) != 1) die_nomem();
325 ++xl->len;
326 token822_reverse(addr);
327}
328
329int rwhrr(addr) token822_alloc *addr;
212b6f5d 330{ rwgeneric(addr); rwappend(addr,&hrrlist); return 1; }
2117e02e 331int rwhr(addr) token822_alloc *addr;
212b6f5d
MW
332{ rwgeneric(addr); rwappend(addr,&hrlist); return 1; }
333int rwtocc(addr) token822_alloc *addr;
334{ rwgeneric(addr); rwappend(addr,&hrlist); rwappend(addr,&tocclist); return 1; }
2117e02e
MW
335
336int htypeseen[H_NUM];
337stralloc hfbuf = {0};
338token822_alloc hfin = {0};
339token822_alloc hfrewrite = {0};
340token822_alloc hfaddr = {0};
341
342void doheaderfield(h)
343stralloc *h;
344{
212b6f5d
MW
345 int htype;
346 int (*rw)() = 0;
347
348 htype = hfield_known(h->s,h->len);
349 if (flagdeletefrom) if (htype == H_FROM) return;
350 if (flagdeletemessid) if (htype == H_MESSAGEID) return;
351 if (flagdeletesender) if (htype == H_RETURNPATH) return;
352
353 if (htype)
354 htypeseen[htype] = 1;
355 else
356 if (!hfield_valid(h->s,h->len))
357 die_invalid(h);
358
359 switch(htype) {
360 case H_TO: case H_CC:
361 rw = rwtocc; break;
362 case H_BCC: case H_APPARENTLYTO:
363 rw = rwhr; break;
364 case H_R_TO: case H_R_CC: case H_R_BCC:
365 rw = rwhrr; break;
366 case H_RETURNPATH:
367 rw = rwreturn; break;
368 case H_SENDER: case H_FROM: case H_REPLYTO:
369 case H_RETURNRECEIPTTO: case H_ERRORSTO:
370 case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO:
371 rw = rwsender; break;
2117e02e
MW
372 }
373
212b6f5d
MW
374 if (rw) {
375 doordie(h,token822_parse(&hfin,h,&hfbuf));
376 doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rw));
377 if (token822_unparse(h,&hfrewrite,LINELEN) != 1)
378 die_nomem();
2117e02e 379 }
212b6f5d
MW
380
381 if (htype == H_BCC) return;
382 if (htype == H_R_BCC) return;
383 if (htype == H_RETURNPATH) return;
384 if (htype == H_CONTENTLENGTH) return; /* some things are just too stupid */
385 savedh_append(h);
2117e02e
MW
386}
387
388void dobody(h)
389stralloc *h;
390{
391 put(h->s,h->len);
392}
393
394stralloc torecip = {0};
395token822_alloc tr = {0};
396
397void dorecip(s)
398char *s;
399{
400 if (!quote2(&torecip,s)) die_nomem();
401 switch(token822_parse(&tr,&torecip,&hfbuf))
402 {
403 case -1: die_nomem();
404 case 0:
405 substdio_puts(subfderr,"qmail-inject: fatal: unable to parse address: ");
406 substdio_puts(subfderr,s);
407 substdio_putsflush(subfderr,"\n");
408 perm();
409 }
410 token822_reverse(&tr);
212b6f5d
MW
411 rwgeneric(&tr);
412 rwappend(&tr,&reciplist);
2117e02e
MW
413}
414
415stralloc defaultfrom = {0};
416token822_alloc df = {0};
417
418void defaultfrommake()
419{
420 char *fullname;
421 fullname = env_get("QMAILNAME");
422 if (!fullname) fullname = env_get("MAILNAME");
423 if (!fullname) fullname = env_get("NAME");
424 if (!token822_ready(&df,20)) die_nomem();
425 df.len = 0;
426 df.t[df.len].type = TOKEN822_ATOM;
427 df.t[df.len].s = "From";
428 df.t[df.len].slen = 4;
429 ++df.len;
430 df.t[df.len].type = TOKEN822_COLON;
431 ++df.len;
432 if (fullname && !flagnamecomment)
433 {
434 df.t[df.len].type = TOKEN822_QUOTE;
435 df.t[df.len].s = fullname;
436 df.t[df.len].slen = str_len(fullname);
437 ++df.len;
438 df.t[df.len].type = TOKEN822_LEFT;
439 ++df.len;
440 }
441 df.t[df.len].type = mailusertokentype;
442 df.t[df.len].s = mailuser;
443 df.t[df.len].slen = str_len(mailuser);
444 ++df.len;
445 if (mailhost)
446 {
447 df.t[df.len].type = TOKEN822_AT;
448 ++df.len;
449 df.t[df.len].type = TOKEN822_ATOM;
450 df.t[df.len].s = mailhost;
451 df.t[df.len].slen = str_len(mailhost);
452 ++df.len;
453 }
454 if (fullname && !flagnamecomment)
455 {
456 df.t[df.len].type = TOKEN822_RIGHT;
457 ++df.len;
458 }
459 if (fullname && flagnamecomment)
460 {
461 df.t[df.len].type = TOKEN822_COMMENT;
462 df.t[df.len].s = fullname;
463 df.t[df.len].slen = str_len(fullname);
464 ++df.len;
465 }
466 if (token822_unparse(&defaultfrom,&df,LINELEN) != 1) die_nomem();
467 doordie(&defaultfrom,token822_parse(&df,&defaultfrom,&hfbuf));
468 doordie(&defaultfrom,token822_addrlist(&hfrewrite,&hfaddr,&df,rwsender));
469 if (token822_unparse(&defaultfrom,&hfrewrite,LINELEN) != 1) die_nomem();
470}
471
472stralloc defaultreturnpath = {0};
473token822_alloc drp = {0};
474stralloc hackedruser = {0};
475char strnum[FMT_ULONG];
476
477void dodefaultreturnpath()
478{
479 if (!stralloc_copys(&hackedruser,mailruser)) die_nomem();
480 if (flaghackmess)
481 {
482 if (!stralloc_cats(&hackedruser,"-")) die_nomem();
483 if (!stralloc_catb(&hackedruser,strnum,fmt_ulong(strnum,(unsigned long) starttime))) die_nomem();
484 if (!stralloc_cats(&hackedruser,".")) die_nomem();
485 if (!stralloc_catb(&hackedruser,strnum,fmt_ulong(strnum,(unsigned long) getpid()))) die_nomem();
486 }
487 if (flaghackrecip)
488 if (!stralloc_cats(&hackedruser,"-")) die_nomem();
489 if (!token822_ready(&drp,10)) die_nomem();
490 drp.len = 0;
491 drp.t[drp.len].type = TOKEN822_ATOM;
492 drp.t[drp.len].s = "Return-Path";
493 drp.t[drp.len].slen = 11;
494 ++drp.len;
495 drp.t[drp.len].type = TOKEN822_COLON;
496 ++drp.len;
497 drp.t[drp.len].type = TOKEN822_QUOTE;
498 drp.t[drp.len].s = hackedruser.s;
499 drp.t[drp.len].slen = hackedruser.len;
500 ++drp.len;
501 if (mailrhost)
502 {
503 drp.t[drp.len].type = TOKEN822_AT;
504 ++drp.len;
505 drp.t[drp.len].type = TOKEN822_ATOM;
506 drp.t[drp.len].s = mailrhost;
507 drp.t[drp.len].slen = str_len(mailrhost);
508 ++drp.len;
509 }
510 if (token822_unparse(&defaultreturnpath,&drp,LINELEN) != 1) die_nomem();
511 doordie(&defaultreturnpath,token822_parse(&drp,&defaultreturnpath,&hfbuf));
512 doordie(&defaultreturnpath
513 ,token822_addrlist(&hfrewrite,&hfaddr,&drp,rwreturn));
514 if (token822_unparse(&defaultreturnpath,&hfrewrite,LINELEN) != 1) die_nomem();
515}
516
212b6f5d
MW
517int flagmft = 0;
518stralloc mft = {0};
519struct constmap mapmft;
520
521void mft_init()
522{
523 char *x;
524 int r;
525
526 x = env_get("QMAILMFTFILE");
527 if (!x) return;
528
529 r = control_readfile(&mft,x,0);
530 if (r == -1) die_read(); /*XXX*/
531 if (!r) return;
532
533 if (!constmap_init(&mapmft,mft.s,mft.len,0)) die_nomem();
534 flagmft = 1;
535}
536
537void finishmft()
538{
539 int i;
540 static stralloc sa = {0};
541 static stralloc sa2 = {0};
542
543 if (!flagmft) return;
544 if (htypeseen[H_MAILFOLLOWUPTO]) return;
545
546 for (i = 0;i < tocclist.len;++i)
547 if (constmap(&mapmft,tocclist.sa[i].s,tocclist.sa[i].len))
548 break;
549
550 if (i == tocclist.len) return;
551
552 puts("Mail-Followup-To: ");
553 i = tocclist.len;
554 while (i--) {
555 if (!stralloc_copy(&sa,&tocclist.sa[i])) die_nomem();
556 if (!stralloc_0(&sa)) die_nomem();
557 if (!quote2(&sa2,sa.s)) die_nomem();
558 put(sa2.s,sa2.len);
559 if (i) puts(",\n ");
560 }
561 puts("\n");
562}
563
2117e02e
MW
564void finishheader()
565{
566 flagresent =
567 htypeseen[H_R_SENDER] || htypeseen[H_R_FROM] || htypeseen[H_R_REPLYTO]
568 || htypeseen[H_R_TO] || htypeseen[H_R_CC] || htypeseen[H_R_BCC]
569 || htypeseen[H_R_DATE] || htypeseen[H_R_MESSAGEID];
570
571 if (!sender.s)
572 dodefaultreturnpath();
573
574 if (!flagqueue)
575 {
576 static stralloc sa = {0};
577 static stralloc sa2 = {0};
578
579 if (!stralloc_copy(&sa,&sender)) die_nomem();
580 if (!stralloc_0(&sa)) die_nomem();
581 if (!quote2(&sa2,sa.s)) die_nomem();
582
583 puts("Return-Path: <");
584 put(sa2.s,sa2.len);
585 puts(">\n");
586 }
587
588 /* could check at this point whether there are any recipients */
589 if (flagqueue)
590 if (qmail_open(&qqt) == -1) die_qqt();
591
592 if (flagresent)
593 {
594 if (!htypeseen[H_R_DATE])
595 {
596 if (!newfield_datemake(starttime)) die_nomem();
597 puts("Resent-");
598 put(newfield_date.s,newfield_date.len);
599 }
600 if (!htypeseen[H_R_MESSAGEID])
601 {
602 if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem();
603 puts("Resent-");
604 put(newfield_msgid.s,newfield_msgid.len);
605 }
606 if (!htypeseen[H_R_FROM])
607 {
608 defaultfrommake();
609 puts("Resent-");
610 put(defaultfrom.s,defaultfrom.len);
611 }
612 if (!htypeseen[H_R_TO] && !htypeseen[H_R_CC])
613 puts("Resent-Cc: recipient list not shown: ;\n");
614 }
615 else
616 {
617 if (!htypeseen[H_DATE])
618 {
619 if (!newfield_datemake(starttime)) die_nomem();
620 put(newfield_date.s,newfield_date.len);
621 }
622 if (!htypeseen[H_MESSAGEID])
623 {
624 if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem();
625 put(newfield_msgid.s,newfield_msgid.len);
626 }
627 if (!htypeseen[H_FROM])
628 {
629 defaultfrommake();
630 put(defaultfrom.s,defaultfrom.len);
631 }
632 if (!htypeseen[H_TO] && !htypeseen[H_CC])
633 puts("Cc: recipient list not shown: ;\n");
212b6f5d 634 finishmft();
2117e02e
MW
635 }
636
637 savedh_print();
638}
639
640void getcontrols()
641{
642 static stralloc sa = {0};
643 char *x;
644
212b6f5d
MW
645 mft_init();
646
647 if (chdir(auto_qmail) == -1) die_chdir();
2117e02e
MW
648 if (control_init() == -1) die_read();
649
650 if (control_rldef(&control_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1)
651 die_read();
652 x = env_get("QMAILDEFAULTDOMAIN");
653 if (x) if (!stralloc_copys(&control_defaultdomain,x)) die_nomem();
654 if (!stralloc_copys(&sa,".")) die_nomem();
655 if (!stralloc_cat(&sa,&control_defaultdomain)) die_nomem();
656 doordie(&sa,token822_parse(&defaultdomain,&sa,&defaultdomainbuf));
657
658 if (control_rldef(&control_defaulthost,"control/defaulthost",1,"defaulthost") != 1)
659 die_read();
660 x = env_get("QMAILDEFAULTHOST");
661 if (x) if (!stralloc_copys(&control_defaulthost,x)) die_nomem();
662 if (!stralloc_copys(&sa,"@")) die_nomem();
663 if (!stralloc_cat(&sa,&control_defaulthost)) die_nomem();
664 doordie(&sa,token822_parse(&defaulthost,&sa,&defaulthostbuf));
665
666 if (control_rldef(&control_plusdomain,"control/plusdomain",1,"plusdomain") != 1)
667 die_read();
668 x = env_get("QMAILPLUSDOMAIN");
669 if (x) if (!stralloc_copys(&control_plusdomain,x)) die_nomem();
670 if (!stralloc_copys(&sa,".")) die_nomem();
671 if (!stralloc_cat(&sa,&control_plusdomain)) die_nomem();
672 doordie(&sa,token822_parse(&plusdomain,&sa,&plusdomainbuf));
673
674 if (control_rldef(&control_idhost,"control/idhost",1,"idhost") != 1)
675 die_read();
676 x = env_get("QMAILIDHOST");
677 if (x) if (!stralloc_copys(&control_idhost,x)) die_nomem();
678}
679
680#define RECIP_DEFAULT 1
681#define RECIP_ARGS 2
682#define RECIP_HEADER 3
683#define RECIP_AH 4
684
685void main(argc,argv)
686int argc;
687char **argv;
688{
689 int i;
690 int opt;
691 int recipstrategy;
692
693 sig_pipeignore();
694
695 starttime = now();
696
697 qmopts = env_get("QMAILINJECT");
698 if (qmopts)
699 while (*qmopts)
700 switch(*qmopts++)
701 {
702 case 'c': flagnamecomment = 1; break;
703 case 's': flagdeletesender = 1; break;
704 case 'f': flagdeletefrom = 1; break;
705 case 'i': flagdeletemessid = 1; break;
706 case 'r': flaghackrecip = 1; break;
707 case 'm': flaghackmess = 1; break;
708 }
709
710 mailhost = env_get("QMAILHOST");
711 if (!mailhost) mailhost = env_get("MAILHOST");
712 mailrhost = env_get("QMAILSHOST");
713 if (!mailrhost) mailrhost = mailhost;
714
715 mailuser = env_get("QMAILUSER");
716 if (!mailuser) mailuser = env_get("MAILUSER");
717 if (!mailuser) mailuser = env_get("USER");
718 if (!mailuser) mailuser = env_get("LOGNAME");
719 if (!mailuser) mailuser = "anonymous";
720 mailusertokentype = TOKEN822_ATOM;
721 if (quote_need(mailuser,str_len(mailuser))) mailusertokentype = TOKEN822_QUOTE;
722 mailruser = env_get("QMAILSUSER");
723 if (!mailruser) mailruser = mailuser;
724
725 for (i = 0;i < H_NUM;++i) htypeseen[i] = 0;
726
727 recipstrategy = RECIP_DEFAULT;
728 flagqueue = 1;
729
2117e02e
MW
730 getcontrols();
731
732 if (!saa_readyplus(&hrlist,1)) die_nomem();
212b6f5d 733 if (!saa_readyplus(&tocclist,1)) die_nomem();
2117e02e
MW
734 if (!saa_readyplus(&hrrlist,1)) die_nomem();
735 if (!saa_readyplus(&reciplist,1)) die_nomem();
736
737 while ((opt = getopt(argc,argv,"aAhHnNf:")) != opteof)
738 switch(opt)
739 {
740 case 'a': recipstrategy = RECIP_ARGS; break;
741 case 'A': recipstrategy = RECIP_DEFAULT; break;
742 case 'h': recipstrategy = RECIP_HEADER; break;
743 case 'H': recipstrategy = RECIP_AH; break;
744 case 'n': flagqueue = 0; break;
745 case 'N': flagqueue = 1; break;
746 case 'f':
747 if (!quote2(&sender,optarg)) die_nomem();
748 doordie(&sender,token822_parse(&envs,&sender,&envsbuf));
749 token822_reverse(&envs);
750 rwgeneric(&envs);
751 token822_reverse(&envs);
752 if (token822_unquote(&sender,&envs) != 1) die_nomem();
753 break;
754 case '?':
755 default:
756 perm();
757 }
758 argc -= optind;
759 argv += optind;
760
761 if (recipstrategy == RECIP_DEFAULT)
762 recipstrategy = (*argv ? RECIP_ARGS : RECIP_HEADER);
763
764 if (recipstrategy != RECIP_HEADER)
765 while (*argv)
766 dorecip(*argv++);
767
768 flagrh = (recipstrategy != RECIP_ARGS);
769
770 if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1)
771 die_read();
772 exitnicely();
773}