1 # include <stdio.h> 2 # include <pwd.h> 3 # include <signal.h> 4 # include <ctype.h> 5 # include <errno.h> 6 # include "sendmail.h" 7 # ifdef LOG 8 # include <syslog.h> 9 # endif LOG 10 11 static char SccsId[] = "@(#)deliver.c 3.22 08/18/81"; 12 13 /* 14 ** DELIVER -- Deliver a message to a particular address. 15 ** 16 ** Parameters: 17 ** to -- the address to deliver the message to. 18 ** editfcn -- if non-NULL, we want to call this function 19 ** to output the letter (instead of just out- 20 ** putting it raw). 21 ** 22 ** Returns: 23 ** zero -- successfully delivered. 24 ** else -- some failure, see ExitStat for more info. 25 ** 26 ** Side Effects: 27 ** The standard input is passed off to someone. 28 */ 29 30 deliver(to, editfcn) 31 ADDRESS *to; 32 int (*editfcn)(); 33 { 34 char *host; 35 char *user; 36 char **pvp; 37 register char **mvp; 38 register char *p; 39 register struct mailer *m; 40 register int i; 41 extern putmessage(); 42 extern bool checkcompat(); 43 char *pv[MAXPV+1]; 44 char tobuf[MAXLINE]; 45 char buf[MAXNAME]; 46 bool firstone; 47 48 if (bitset(QDONTSEND, to->q_flags)) 49 return (0); 50 51 # ifdef DEBUG 52 if (Debug) 53 printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 54 to->q_mailer, to->q_host, to->q_user); 55 # endif DEBUG 56 57 /* 58 ** Do initial argv setup. 59 ** Insert the mailer name. Notice that $x expansion is 60 ** NOT done on the mailer name. Then, if the mailer has 61 ** a picky -f flag, we insert it as appropriate. This 62 ** code does not check for 'pv' overflow; this places a 63 ** manifest lower limit of 4 for MAXPV. 64 */ 65 66 m = Mailer[to->q_mailer]; 67 host = to->q_host; 68 define('g', m->m_from); /* translated from address */ 69 define('h', host); /* to host */ 70 Errors = 0; 71 errno = 0; 72 pvp = pv; 73 *pvp++ = m->m_argv[0]; 74 75 /* insert -f or -r flag as appropriate */ 76 if (bitset(M_FOPT|M_ROPT, m->m_flags) && FromFlag) 77 { 78 if (bitset(M_FOPT, m->m_flags)) 79 *pvp++ = "-f"; 80 else 81 *pvp++ = "-r"; 82 (void) expand("$g", buf, &buf[sizeof buf - 1]); 83 *pvp++ = newstr(buf); 84 } 85 86 /* 87 ** Append the other fixed parts of the argv. These run 88 ** up to the first entry containing "$u". There can only 89 ** be one of these, and there are only a few more slots 90 ** in the pv after it. 91 */ 92 93 for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 94 { 95 while ((p = index(p, '$')) != NULL) 96 if (*++p == 'u') 97 break; 98 if (p != NULL) 99 break; 100 101 /* this entry is safe -- go ahead and process it */ 102 (void) expand(*mvp, buf, &buf[sizeof buf - 1]); 103 *pvp++ = newstr(buf); 104 if (pvp >= &pv[MAXPV - 3]) 105 { 106 syserr("Too many parameters to %s before $u", pv[0]); 107 return (-1); 108 } 109 } 110 if (*mvp == NULL) 111 syserr("No $u in mailer argv for %s", pv[0]); 112 113 /* 114 ** At this point *mvp points to the argument with $u. We 115 ** run through our address list and append all the addresses 116 ** we can. If we run out of space, do not fret! We can 117 ** always send another copy later. 118 */ 119 120 tobuf[0] = '\0'; 121 firstone = TRUE; 122 To = tobuf; 123 for (; to != NULL; to = to->q_next) 124 { 125 /* avoid sending multiple recipients to dumb mailers */ 126 if (!firstone && !bitset(M_MUSER, m->m_flags)) 127 break; 128 129 /* if already sent or not for this host, don't send */ 130 if (bitset(QDONTSEND, to->q_flags) || strcmp(to->q_host, host) != 0) 131 continue; 132 user = to->q_user; 133 To = to->q_paddr; 134 to->q_flags |= QDONTSEND; 135 firstone = FALSE; 136 137 # ifdef DEBUG 138 if (Debug) 139 printf(" send to `%s'\n", user); 140 # endif DEBUG 141 142 /* 143 ** Check to see that these people are allowed to 144 ** talk to each other. 145 */ 146 147 if (!checkcompat(to)) 148 { 149 giveresponse(EX_UNAVAILABLE, TRUE, m); 150 continue; 151 } 152 153 /* 154 ** Strip quote bits from names if the mailer is dumb 155 ** about them. 156 */ 157 158 if (bitset(M_STRIPQ, m->m_flags)) 159 { 160 stripquotes(user, TRUE); 161 stripquotes(host, TRUE); 162 } 163 else 164 { 165 stripquotes(user, FALSE); 166 stripquotes(host, FALSE); 167 } 168 169 /* 170 ** If an error message has already been given, don't 171 ** bother to send to this address. 172 ** 173 ** >>>>>>>>>> This clause assumes that the local mailer 174 ** >> NOTE >> cannot do any further aliasing; that 175 ** >>>>>>>>>> function is subsumed by sendmail. 176 */ 177 178 if (bitset(QBADADDR, to->q_flags)) 179 continue; 180 181 /* 182 ** See if this user name is "special". 183 ** If the user name has a slash in it, assume that this 184 ** is a file -- send it off without further ado. 185 ** Note that this means that editfcn's will not 186 ** be applied to the message. Also note that 187 ** this type of addresses is not processed along 188 ** with the others, so we fudge on the To person. 189 */ 190 191 if (m == Mailer[M_LOCAL]) 192 { 193 if (index(user, '/') != NULL) 194 { 195 i = mailfile(user); 196 giveresponse(i, TRUE, m); 197 continue; 198 } 199 } 200 201 /* create list of users for error messages */ 202 if (tobuf[0] != '\0') 203 (void) strcat(tobuf, ","); 204 (void) strcat(tobuf, to->q_paddr); 205 define('u', user); /* to user */ 206 define('z', to->q_home); /* user's home */ 207 208 /* expand out this user */ 209 (void) expand(user, buf, &buf[sizeof buf - 1]); 210 *pvp++ = newstr(buf); 211 if (pvp >= &pv[MAXPV - 2]) 212 { 213 /* allow some space for trailing parms */ 214 break; 215 } 216 } 217 218 /* see if any addresses still exist */ 219 if (tobuf[0] == '\0') 220 return (0); 221 222 /* print out messages as full list */ 223 To = tobuf; 224 225 /* 226 ** Fill out any parameters after the $u parameter. 227 */ 228 229 while (*++mvp != NULL) 230 { 231 (void) expand(*mvp, buf, &buf[sizeof buf - 1]); 232 *pvp++ = newstr(buf); 233 if (pvp >= &pv[MAXPV]) 234 syserr("deliver: pv overflow after $u for %s", pv[0]); 235 } 236 *pvp++ = NULL; 237 238 /* 239 ** Call the mailer. 240 ** The argument vector gets built, pipes 241 ** are created as necessary, and we fork & exec as 242 ** appropriate. 243 ** 244 ** Notice the tacky hack to handle private mailers. 245 */ 246 247 if (editfcn == NULL) 248 editfcn = putmessage; 249 i = sendoff(m, pv, editfcn); 250 251 return (i); 252 } 253 /* 254 ** SENDOFF -- send off call to mailer & collect response. 255 ** 256 ** Parameters: 257 ** m -- mailer descriptor. 258 ** pvp -- parameter vector to send to it. 259 ** editfcn -- function to pipe it through. 260 ** 261 ** Returns: 262 ** exit status of mailer. 263 ** 264 ** Side Effects: 265 ** none. 266 */ 267 268 #define NFORKTRIES 5 269 270 sendoff(m, pvp, editfcn) 271 struct mailer *m; 272 char **pvp; 273 int (*editfcn)(); 274 { 275 auto int st; 276 register int i; 277 int pid; 278 int pvect[2]; 279 FILE *mfile; 280 extern putmessage(); 281 extern FILE *fdopen(); 282 283 # ifdef DEBUG 284 if (Debug) 285 { 286 printf("Sendoff:\n"); 287 printav(pvp); 288 } 289 # endif DEBUG 290 291 /* create a pipe to shove the mail through */ 292 if (pipe(pvect) < 0) 293 { 294 syserr("pipe"); 295 return (-1); 296 } 297 for (i = NFORKTRIES; i-- > 0; ) 298 { 299 # ifdef VFORK 300 pid = vfork(); 301 # else 302 pid = fork(); 303 # endif 304 if (pid >= 0) 305 break; 306 sleep((unsigned) NFORKTRIES - i); 307 } 308 if (pid < 0) 309 { 310 syserr("Cannot fork"); 311 (void) close(pvect[0]); 312 (void) close(pvect[1]); 313 return (-1); 314 } 315 else if (pid == 0) 316 { 317 /* child -- set up input & exec mailer */ 318 /* make diagnostic output be standard output */ 319 (void) close(2); 320 (void) dup(1); 321 (void) signal(SIGINT, SIG_IGN); 322 (void) close(0); 323 if (dup(pvect[0]) < 0) 324 { 325 syserr("Cannot dup to zero!"); 326 _exit(EX_OSERR); 327 } 328 (void) close(pvect[0]); 329 (void) close(pvect[1]); 330 if (!bitset(M_RESTR, m->m_flags)) 331 (void) setuid(getuid()); 332 # ifndef VFORK 333 /* 334 ** We have to be careful with vfork - we can't mung up the 335 ** memory but we don't want the mailer to inherit any extra 336 ** open files. Chances are the mailer won't 337 ** care about an extra file, but then again you never know. 338 ** Actually, we would like to close(fileno(pwf)), but it's 339 ** declared static so we can't. But if we fclose(pwf), which 340 ** is what endpwent does, it closes it in the parent too and 341 ** the next getpwnam will be slower. If you have a weird 342 ** mailer that chokes on the extra file you should do the 343 ** endpwent(). 344 ** 345 ** Similar comments apply to log. However, openlog is 346 ** clever enough to set the FIOCLEX mode on the file, 347 ** so it will be closed automatically on the exec. 348 */ 349 350 endpwent(); 351 # ifdef LOG 352 closelog(); 353 # endif LOG 354 # endif VFORK 355 execv(m->m_mailer, pvp); 356 /* syserr fails because log is closed */ 357 /* syserr("Cannot exec %s", m->m_mailer); */ 358 printf("Cannot exec %s\n", m->m_mailer); 359 (void) fflush(stdout); 360 _exit(EX_UNAVAILABLE); 361 } 362 363 /* write out message to mailer */ 364 (void) close(pvect[0]); 365 (void) signal(SIGPIPE, SIG_IGN); 366 mfile = fdopen(pvect[1], "w"); 367 if (editfcn == NULL) 368 editfcn = putmessage; 369 (*editfcn)(mfile, m); 370 (void) fclose(mfile); 371 372 /* 373 ** Wait for child to die and report status. 374 ** We should never get fatal errors (e.g., segmentation 375 ** violation), so we report those specially. For other 376 ** errors, we choose a status message (into statmsg), 377 ** and if it represents an error, we print it. 378 */ 379 380 while ((i = wait(&st)) > 0 && i != pid) 381 continue; 382 if (i < 0) 383 { 384 syserr("wait"); 385 return (-1); 386 } 387 if ((st & 0377) != 0) 388 { 389 syserr("%s: stat %o", pvp[0], st); 390 ExitStat = EX_UNAVAILABLE; 391 return (-1); 392 } 393 i = (st >> 8) & 0377; 394 giveresponse(i, TRUE, m); 395 return (i); 396 } 397 /* 398 ** GIVERESPONSE -- Interpret an error response from a mailer 399 ** 400 ** Parameters: 401 ** stat -- the status code from the mailer (high byte 402 ** only; core dumps must have been taken care of 403 ** already). 404 ** force -- if set, force an error message output, even 405 ** if the mailer seems to like to print its own 406 ** messages. 407 ** m -- the mailer descriptor for this mailer. 408 ** 409 ** Returns: 410 ** none. 411 ** 412 ** Side Effects: 413 ** Errors may be incremented. 414 ** ExitStat may be set. 415 ** 416 ** Called By: 417 ** deliver 418 */ 419 420 giveresponse(stat, force, m) 421 int stat; 422 int force; 423 register struct mailer *m; 424 { 425 register char *statmsg; 426 extern char *SysExMsg[]; 427 register int i; 428 extern int N_SysEx; 429 extern long MsgSize; 430 char buf[30]; 431 432 i = stat - EX__BASE; 433 if (i < 0 || i > N_SysEx) 434 statmsg = NULL; 435 else 436 statmsg = SysExMsg[i]; 437 if (stat == 0) 438 { 439 if (bitset(M_FINAL, m->m_flags)) 440 statmsg = "delivered"; 441 else 442 statmsg = "queued"; 443 if (Verbose) 444 message("050", statmsg); 445 } 446 else 447 { 448 Errors++; 449 if (statmsg == NULL && m->m_badstat != 0) 450 { 451 stat = m->m_badstat; 452 i = stat - EX__BASE; 453 # ifdef DEBUG 454 if (i < 0 || i >= N_SysEx) 455 syserr("Bad m_badstat %d", stat); 456 else 457 # endif DEBUG 458 statmsg = SysExMsg[i]; 459 } 460 if (statmsg == NULL) 461 usrerr("unknown mailer response %d", stat); 462 else if (force || !bitset(M_QUIET, m->m_flags) || Verbose) 463 usrerr("%s", statmsg); 464 } 465 466 /* 467 ** Final cleanup. 468 ** Log a record of the transaction. Compute the new 469 ** ExitStat -- if we already had an error, stick with 470 ** that. 471 */ 472 473 if (statmsg == NULL) 474 { 475 (void) sprintf(buf, "error %d", stat); 476 statmsg = buf; 477 } 478 479 # ifdef LOG 480 syslog(LOG_INFO, "%s->%s: %ld: %s", From.q_paddr, To, MsgSize, statmsg); 481 # endif LOG 482 setstat(stat); 483 } 484 /* 485 ** PUTMESSAGE -- output a message to the final mailer. 486 ** 487 ** This routine takes care of recreating the header from the 488 ** in-core copy, etc. 489 ** 490 ** Parameters: 491 ** fp -- file to output onto. 492 ** m -- a mailer descriptor. 493 ** 494 ** Returns: 495 ** none. 496 ** 497 ** Side Effects: 498 ** The message is written onto fp. 499 */ 500 501 putmessage(fp, m) 502 FILE *fp; 503 struct mailer *m; 504 { 505 char buf[BUFSIZ]; 506 register int i; 507 HDR *h; 508 register char *p; 509 extern char *arpadate(); 510 bool anyheader = FALSE; 511 extern char *capitalize(); 512 513 /* output "From" line unless supressed */ 514 if (!bitset(M_NHDR, m->m_flags)) 515 fprintf(fp, "%s\n", FromLine); 516 517 /* output all header lines */ 518 for (h = Header; h != NULL; h = h->h_link) 519 { 520 if (bitset(H_DELETE, h->h_flags)) 521 continue; 522 if (bitset(H_CHECK|H_ACHECK, h->h_flags) && !bitset(h->h_mflags, m->m_flags)) 523 continue; 524 if (bitset(H_DEFAULT, h->h_flags)) 525 { 526 (void) expand(h->h_value, buf, &buf[sizeof buf]); 527 p = buf; 528 } 529 else 530 p = h->h_value; 531 if (*p == '\0') 532 continue; 533 fprintf(fp, "%s: %s\n", capitalize(h->h_field), p); 534 h->h_flags |= H_USED; 535 anyheader = TRUE; 536 } 537 538 if (anyheader) 539 fprintf(fp, "\n"); 540 541 /* output the body of the message */ 542 rewind(stdin); 543 while (!ferror(fp) && (i = fread(buf, 1, BUFSIZ, stdin)) > 0) 544 (void) fwrite(buf, 1, i, fp); 545 546 if (ferror(fp) && errno != EPIPE) 547 { 548 syserr("putmessage: write error"); 549 setstat(EX_IOERR); 550 } 551 errno = 0; 552 } 553 /* 554 ** SENDTO -- Designate a send list. 555 ** 556 ** The parameter is a comma-separated list of people to send to. 557 ** This routine arranges to send to all of them. 558 ** 559 ** Parameters: 560 ** list -- the send list. 561 ** copyf -- the copy flag; passed to parse. 562 ** 563 ** Returns: 564 ** none 565 ** 566 ** Side Effects: 567 ** none. 568 */ 569 570 # define MAXRCRSN 10 571 572 sendto(list, copyf) 573 char *list; 574 int copyf; 575 { 576 register char *p; 577 register char *q; 578 register char c; 579 ADDRESS *a; 580 bool more; 581 582 /* more keeps track of what the previous delimiter was */ 583 more = TRUE; 584 for (p = list; more; ) 585 { 586 /* find the end of this address */ 587 while (*p == ' ' || *p == '\t') 588 p++; 589 q = p; 590 while ((c = *p++) != '\0' && c != ',' && c != '\n') 591 continue; 592 more = c != '\0'; 593 *--p = '\0'; 594 if (more) 595 p++; 596 597 /* parse the address */ 598 if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 599 continue; 600 601 /* arrange to send to this person */ 602 recipient(a); 603 } 604 To = NULL; 605 } 606 /* 607 ** RECIPIENT -- Designate a message recipient 608 ** 609 ** Saves the named person for future mailing. 610 ** 611 ** Parameters: 612 ** a -- the (preparsed) address header for the recipient. 613 ** 614 ** Returns: 615 ** none. 616 ** 617 ** Side Effects: 618 ** none. 619 */ 620 621 recipient(a) 622 register ADDRESS *a; 623 { 624 register ADDRESS *q; 625 register struct mailer *m; 626 char buf[MAXNAME]; 627 628 To = a->q_paddr; 629 m = Mailer[a->q_mailer]; 630 errno = 0; 631 # ifdef DEBUG 632 if (Debug) 633 printf("recipient(%s)\n", To); 634 # endif DEBUG 635 636 /* break aliasing loops */ 637 if (AliasLevel > MAXRCRSN) 638 { 639 usrerr("aliasing/forwarding loop broken"); 640 return; 641 } 642 643 /* 644 ** Do sickly crude mapping for program mailing, etc. 645 */ 646 647 if (a->q_mailer == M_LOCAL) 648 { 649 if (a->q_user[0] == '|') 650 { 651 a->q_mailer = M_PROG; 652 m = Mailer[M_PROG]; 653 a->q_user++; 654 } 655 } 656 657 /* 658 ** Look up this person in the recipient list. If they 659 ** are there already, return, otherwise continue. 660 ** If the list is empty, just add it. 661 */ 662 663 if (m->m_sendq == NULL) 664 { 665 m->m_sendq = a; 666 } 667 else 668 { 669 ADDRESS *pq; 670 671 for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next) 672 { 673 if (!ForceMail && sameaddr(q, a, FALSE)) 674 { 675 # ifdef DEBUG 676 if (Debug) 677 printf("(%s in sendq)\n", a->q_paddr); 678 # endif DEBUG 679 if (Verbose && !bitset(QDONTSEND, a->q_flags)) 680 message("050", "duplicate supressed"); 681 return; 682 } 683 } 684 685 /* add address on list */ 686 q = pq; 687 q->q_next = a; 688 } 689 a->q_next = NULL; 690 691 /* 692 ** Alias the name and handle :include: specs. 693 */ 694 695 if (a->q_mailer == M_LOCAL) 696 { 697 if (strncmp(a->q_user, ":include:", 9) == 0) 698 { 699 a->q_flags |= QDONTSEND; 700 include(&a->q_user[9]); 701 } 702 else 703 alias(a); 704 } 705 706 /* 707 ** If the user is local and still being sent, verify that 708 ** the address is good. If it is, try to forward. 709 ** If the address is already good, we have a forwarding 710 ** loop. This can be broken by just sending directly to 711 ** the user (which is probably correct anyway). 712 */ 713 714 if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL) 715 { 716 char buf[MAXNAME]; 717 718 strcpy(buf, a->q_user); 719 stripquotes(buf, TRUE); 720 721 /* see if this is to a file */ 722 if (index(buf, '/') != NULL) 723 { 724 if (access(buf, 2) < 0) 725 { 726 a->q_flags |= QBADADDR; 727 giveresponse(EX_CANTCREAT, TRUE, m); 728 } 729 } 730 else 731 { 732 register struct passwd *pw; 733 extern struct passwd *getpwnam(); 734 pw = getpwnam(buf); 735 if (pw == NULL) 736 { 737 a->q_flags |= QBADADDR; 738 giveresponse(EX_NOUSER, TRUE, m); 739 } 740 else 741 { 742 a->q_home = newstr(pw->pw_dir); 743 if (strcmp(buf, a->q_user) == 0) 744 forward(a); 745 } 746 } 747 } 748 } 749 /* 750 ** INCLUDE -- handle :include: specification. 751 ** 752 ** Parameters: 753 ** fname -- filename to include. 754 ** 755 ** Returns: 756 ** none. 757 ** 758 ** Side Effects: 759 ** reads the :include: file and sends to everyone 760 ** listed in that file. 761 */ 762 763 include(fname) 764 char *fname; 765 { 766 char buf[MAXLINE]; 767 register FILE *fp; 768 769 if (Verbose) 770 message("050", "Including file %s", fname); 771 fp = fopen(fname, "r"); 772 if (fp == NULL) 773 { 774 usrerr("Cannot open %s", fname); 775 return; 776 } 777 778 /* read the file -- each line is a comma-separated list. */ 779 while (fgets(buf, sizeof buf, fp) != NULL) 780 { 781 register char *p = index(buf, '\n'); 782 783 if (p != NULL) 784 *p = '\0'; 785 if (buf[0] == '\0') 786 continue; 787 To = fname; 788 if (Verbose) 789 message("050", " >> %s", buf); 790 sendto(buf, 1); 791 } 792 793 fclose(fp); 794 } 795 /* 796 ** MAILFILE -- Send a message to a file. 797 ** 798 ** Parameters: 799 ** filename -- the name of the file to send to. 800 ** 801 ** Returns: 802 ** The exit code associated with the operation. 803 ** 804 ** Side Effects: 805 ** none. 806 ** 807 ** Called By: 808 ** deliver 809 */ 810 811 mailfile(filename) 812 char *filename; 813 { 814 register FILE *f; 815 816 f = fopen(filename, "a"); 817 if (f == NULL) 818 return (EX_CANTCREAT); 819 820 putmessage(f, Mailer[1]); 821 fputs("\n", f); 822 (void) fclose(f); 823 return (EX_OK); 824 } 825