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