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