debian/rules: Use `git' potty wrapper.
[qmail] / qmail-inject.c
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"
24 #include "constmap.h"
25
26 #define LINELEN 80
27
28 datetime_sec starttime;
29
30 char *qmopts;
31 int flagdeletesender = 0;
32 int flagdeletefrom = 0;
33 int flagdeletemessid = 0;
34 int flagnamecomment = 0;
35 int flaghackmess = 0;
36 int flaghackrecip = 0;
37 char *mailhost;
38 char *mailuser;
39 int mailusertokentype;
40 char *mailrhost;
41 char *mailruser;
42
43 stralloc control_idhost = {0};
44 stralloc control_defaultdomain = {0};
45 stralloc control_defaulthost = {0};
46 stralloc control_plusdomain = {0};
47
48 stralloc sender = {0};
49 stralloc envsbuf = {0};
50 token822_alloc envs = {0};
51 int flagrh;
52
53 int flagqueue;
54 struct qmail qqt;
55
56 void put(s,len) char *s; int len;
57 { if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); }
58 void puts(s) char *s; { put(s,str_len(s)); }
59
60 void perm() { _exit(100); }
61 void temp() { _exit(111); }
62 void die_nomem() {
63 substdio_putsflush(subfderr,"qmail-inject: fatal: out of memory\n"); temp(); }
64 void die_invalid(sa) stralloc *sa; {
65 substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: ");
66 substdio_putflush(subfderr,sa->s,sa->len); perm(); }
67 void die_qqt() {
68 substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); }
69 void die_chdir() {
70 substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); }
71 void die_read() {
72 if (errno == error_nomem) die_nomem();
73 substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); }
74 void 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
79 GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
80 GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
81
82 static stralloc sauninit = {0};
83
84 saa savedh = {0};
85 saa hrlist = {0};
86 saa tocclist = {0};
87 saa hrrlist = {0};
88 saa reciplist = {0};
89 int flagresent;
90
91 void exitnicely()
92 {
93 char *qqx;
94
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
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 }
139 }
140
141 _exit(0);
142 }
143
144 void savedh_append(h)
145 stralloc *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
153 void 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
161 stralloc defaultdomainbuf = {0};
162 token822_alloc defaultdomain = {0};
163 stralloc defaulthostbuf = {0};
164 token822_alloc defaulthost = {0};
165 stralloc plusdomainbuf = {0};
166 token822_alloc plusdomain = {0};
167
168 void rwroute(addr)
169 token822_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
177 void rwextraat(addr)
178 token822_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
189 void rwextradot(addr)
190 token822_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
201 void rwnoat(addr)
202 token822_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
219 void rwnodot(addr)
220 token822_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
247 void rwplus(addr)
248 token822_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
268 void rwgeneric(addr)
269 token822_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
288 int setreturn(addr)
289 token822_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
302 int rwreturn(addr)
303 token822_alloc *addr;
304 {
305 rwgeneric(addr);
306 setreturn(addr);
307 return 1;
308 }
309
310 int rwsender(addr)
311 token822_alloc *addr;
312 {
313 rwgeneric(addr);
314 return 1;
315 }
316
317 void rwappend(addr,xl)
318 token822_alloc *addr;
319 saa *xl;
320 {
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
329 int rwhrr(addr) token822_alloc *addr;
330 { rwgeneric(addr); rwappend(addr,&hrrlist); return 1; }
331 int rwhr(addr) token822_alloc *addr;
332 { rwgeneric(addr); rwappend(addr,&hrlist); return 1; }
333 int rwtocc(addr) token822_alloc *addr;
334 { rwgeneric(addr); rwappend(addr,&hrlist); rwappend(addr,&tocclist); return 1; }
335
336 int htypeseen[H_NUM];
337 stralloc hfbuf = {0};
338 token822_alloc hfin = {0};
339 token822_alloc hfrewrite = {0};
340 token822_alloc hfaddr = {0};
341
342 void doheaderfield(h)
343 stralloc *h;
344 {
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;
372 }
373
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();
379 }
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);
386 }
387
388 void dobody(h)
389 stralloc *h;
390 {
391 put(h->s,h->len);
392 }
393
394 stralloc torecip = {0};
395 token822_alloc tr = {0};
396
397 void dorecip(s)
398 char *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);
411 rwgeneric(&tr);
412 rwappend(&tr,&reciplist);
413 }
414
415 stralloc defaultfrom = {0};
416 token822_alloc df = {0};
417
418 void 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
472 stralloc defaultreturnpath = {0};
473 token822_alloc drp = {0};
474 stralloc hackedruser = {0};
475 char strnum[FMT_ULONG];
476
477 void 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
517 int flagmft = 0;
518 stralloc mft = {0};
519 struct constmap mapmft;
520
521 void 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
537 void 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
564 void 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");
634 finishmft();
635 }
636
637 savedh_print();
638 }
639
640 void getcontrols()
641 {
642 static stralloc sa = {0};
643 char *x;
644
645 mft_init();
646
647 if (chdir(auto_qmail) == -1) die_chdir();
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
685 void main(argc,argv)
686 int argc;
687 char **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
730 getcontrols();
731
732 if (!saa_readyplus(&hrlist,1)) die_nomem();
733 if (!saa_readyplus(&tocclist,1)) die_nomem();
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 }