1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 # include "sendmail.h" 10 11 #ifndef lint 12 #ifdef QUEUE 13 static char sccsid[] = "@(#)queue.c 8.29 (Berkeley) 11/20/93 (with queueing)"; 14 #else 15 static char sccsid[] = "@(#)queue.c 8.29 (Berkeley) 11/20/93 (without queueing)"; 16 #endif 17 #endif /* not lint */ 18 19 # include <errno.h> 20 # include <pwd.h> 21 # include <dirent.h> 22 23 # ifdef QUEUE 24 25 /* 26 ** Work queue. 27 */ 28 29 struct work 30 { 31 char *w_name; /* name of control file */ 32 long w_pri; /* priority of message, see below */ 33 time_t w_ctime; /* creation time of message */ 34 struct work *w_next; /* next in queue */ 35 }; 36 37 typedef struct work WORK; 38 39 WORK *WorkQ; /* queue of things to be done */ 40 /* 41 ** QUEUEUP -- queue a message up for future transmission. 42 ** 43 ** Parameters: 44 ** e -- the envelope to queue up. 45 ** queueall -- if TRUE, queue all addresses, rather than 46 ** just those with the QQUEUEUP flag set. 47 ** announce -- if TRUE, tell when you are queueing up. 48 ** 49 ** Returns: 50 ** none. 51 ** 52 ** Side Effects: 53 ** The current request are saved in a control file. 54 ** The queue file is left locked. 55 */ 56 57 queueup(e, queueall, announce) 58 register ENVELOPE *e; 59 bool queueall; 60 bool announce; 61 { 62 char *qf; 63 register FILE *tfp; 64 register HDR *h; 65 register ADDRESS *q; 66 int fd; 67 int i; 68 bool newid; 69 register char *p; 70 MAILER nullmailer; 71 char buf[MAXLINE], tf[MAXLINE]; 72 73 /* 74 ** Create control file. 75 */ 76 77 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 78 79 /* if newid, queuename will create a locked qf file in e->lockfp */ 80 strcpy(tf, queuename(e, 't')); 81 tfp = e->e_lockfp; 82 if (tfp == NULL) 83 newid = FALSE; 84 85 /* if newid, just write the qf file directly (instead of tf file) */ 86 if (!newid) 87 { 88 /* get a locked tf file */ 89 for (i = 0; i < 128; i++) 90 { 91 fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode); 92 if (fd < 0) 93 { 94 if (errno != EEXIST) 95 break; 96 #ifdef LOG 97 if (LogLevel > 0 && (i % 32) == 0) 98 syslog(LOG_ALERT, "queueup: cannot create %s: %s", 99 tf, errstring(errno)); 100 #endif 101 continue; 102 } 103 104 if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB)) 105 break; 106 #ifdef LOG 107 else if (LogLevel > 0 && (i % 32) == 0) 108 syslog(LOG_ALERT, "queueup: cannot lock %s: %s", 109 tf, errstring(errno)); 110 #endif 111 112 close(fd); 113 114 if ((i % 32) == 31) 115 { 116 /* save the old temp file away */ 117 (void) rename(tf, queuename(e, 'T')); 118 } 119 else 120 sleep(i % 32); 121 } 122 if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL) 123 { 124 printopenfds(TRUE); 125 syserr("!queueup: cannot create queue temp file %s", tf); 126 } 127 } 128 129 if (tTd(40, 1)) 130 printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id, 131 newid ? " (new id)" : ""); 132 if (tTd(40, 9)) 133 { 134 printf(" tfp="); 135 dumpfd(fileno(tfp), TRUE, FALSE); 136 printf(" lockfp="); 137 if (e->e_lockfp == NULL) 138 printf("NULL\n"); 139 else 140 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 141 } 142 143 /* 144 ** If there is no data file yet, create one. 145 */ 146 147 if (e->e_df == NULL) 148 { 149 register FILE *dfp; 150 extern putbody(); 151 152 e->e_df = queuename(e, 'd'); 153 e->e_df = newstr(e->e_df); 154 fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode); 155 if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL) 156 syserr("!queueup: cannot create data temp file %s", 157 e->e_df); 158 (*e->e_putbody)(dfp, FileMailer, e, NULL); 159 (void) xfclose(dfp, "queueup dfp", e->e_id); 160 e->e_putbody = putbody; 161 } 162 163 /* 164 ** Output future work requests. 165 ** Priority and creation time should be first, since 166 ** they are required by orderq. 167 */ 168 169 /* output message priority */ 170 fprintf(tfp, "P%ld\n", e->e_msgpriority); 171 172 /* output creation time */ 173 fprintf(tfp, "T%ld\n", e->e_ctime); 174 175 /* output type and name of data file */ 176 if (e->e_bodytype != NULL) 177 fprintf(tfp, "B%s\n", e->e_bodytype); 178 fprintf(tfp, "D%s\n", e->e_df); 179 180 /* message from envelope, if it exists */ 181 if (e->e_message != NULL) 182 fprintf(tfp, "M%s\n", e->e_message); 183 184 /* send various flag bits through */ 185 p = buf; 186 if (bitset(EF_WARNING, e->e_flags)) 187 *p++ = 'w'; 188 if (bitset(EF_RESPONSE, e->e_flags)) 189 *p++ = 'r'; 190 *p++ = '\0'; 191 if (buf[0] != '\0') 192 fprintf(tfp, "F%s\n", buf); 193 194 /* $r and $s and $_ macro values */ 195 if ((p = macvalue('r', e)) != NULL) 196 fprintf(tfp, "$r%s\n", p); 197 if ((p = macvalue('s', e)) != NULL) 198 fprintf(tfp, "$s%s\n", p); 199 if ((p = macvalue('_', e)) != NULL) 200 fprintf(tfp, "$_%s\n", p); 201 202 /* output name of sender */ 203 fprintf(tfp, "S%s\n", e->e_from.q_paddr); 204 205 /* output list of error recipients */ 206 printctladdr(NULL, NULL); 207 for (q = e->e_errorqueue; q != NULL; q = q->q_next) 208 { 209 if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 210 { 211 printctladdr(q, tfp); 212 fprintf(tfp, "E%s\n", q->q_paddr); 213 } 214 } 215 216 /* output list of recipient addresses */ 217 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 218 { 219 if (bitset(QQUEUEUP, q->q_flags) || 220 (queueall && !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))) 221 { 222 printctladdr(q, tfp); 223 fprintf(tfp, "R%s\n", q->q_paddr); 224 if (announce) 225 { 226 e->e_to = q->q_paddr; 227 message("queued"); 228 if (LogLevel > 8) 229 logdelivery(NULL, NULL, "queued", NULL, e); 230 e->e_to = NULL; 231 } 232 if (tTd(40, 1)) 233 { 234 printf("queueing "); 235 printaddr(q, FALSE); 236 } 237 } 238 } 239 240 /* 241 ** Output headers for this message. 242 ** Expand macros completely here. Queue run will deal with 243 ** everything as absolute headers. 244 ** All headers that must be relative to the recipient 245 ** can be cracked later. 246 ** We set up a "null mailer" -- i.e., a mailer that will have 247 ** no effect on the addresses as they are output. 248 */ 249 250 bzero((char *) &nullmailer, sizeof nullmailer); 251 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 252 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = 0; 253 nullmailer.m_eol = "\n"; 254 255 define('g', "\201f", e); 256 for (h = e->e_header; h != NULL; h = h->h_link) 257 { 258 extern bool bitzerop(); 259 260 /* don't output null headers */ 261 if (h->h_value == NULL || h->h_value[0] == '\0') 262 continue; 263 264 /* don't output resent headers on non-resent messages */ 265 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 266 continue; 267 268 /* output this header */ 269 fprintf(tfp, "H"); 270 271 /* if conditional, output the set of conditions */ 272 if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags)) 273 { 274 int j; 275 276 (void) putc('?', tfp); 277 for (j = '\0'; j <= '\177'; j++) 278 if (bitnset(j, h->h_mflags)) 279 (void) putc(j, tfp); 280 (void) putc('?', tfp); 281 } 282 283 /* output the header: expand macros, convert addresses */ 284 if (bitset(H_DEFAULT, h->h_flags)) 285 { 286 (void) expand(h->h_value, buf, &buf[sizeof buf], e); 287 fprintf(tfp, "%s: %s\n", h->h_field, buf); 288 } 289 else if (bitset(H_FROM|H_RCPT, h->h_flags)) 290 { 291 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 292 FILE *savetrace = TrafficLogFile; 293 294 TrafficLogFile = NULL; 295 296 if (bitset(H_FROM, h->h_flags)) 297 oldstyle = FALSE; 298 299 commaize(h, h->h_value, tfp, oldstyle, 300 &nullmailer, e); 301 302 TrafficLogFile = savetrace; 303 } 304 else 305 fprintf(tfp, "%s: %s\n", h->h_field, h->h_value); 306 } 307 308 /* 309 ** Clean up. 310 */ 311 312 if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp)) 313 { 314 if (newid) 315 syserr("!552 Error writing control file %s", tf); 316 else 317 syserr("!452 Error writing control file %s", tf); 318 } 319 320 if (!newid) 321 { 322 /* rename (locked) tf to be (locked) qf */ 323 qf = queuename(e, 'q'); 324 if (rename(tf, qf) < 0) 325 syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df); 326 327 /* close and unlock old (locked) qf */ 328 if (e->e_lockfp != NULL) 329 (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id); 330 e->e_lockfp = tfp; 331 } 332 else 333 qf = tf; 334 errno = 0; 335 e->e_flags |= EF_INQUEUE; 336 337 # ifdef LOG 338 /* save log info */ 339 if (LogLevel > 79) 340 syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df); 341 # endif /* LOG */ 342 343 if (tTd(40, 1)) 344 printf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 345 return; 346 } 347 348 printctladdr(a, tfp) 349 register ADDRESS *a; 350 FILE *tfp; 351 { 352 char *uname; 353 register struct passwd *pw; 354 register ADDRESS *q; 355 uid_t uid; 356 static ADDRESS *lastctladdr; 357 static uid_t lastuid; 358 359 /* initialization */ 360 if (a == NULL || a->q_alias == NULL || tfp == NULL) 361 { 362 if (lastctladdr != NULL && tfp != NULL) 363 fprintf(tfp, "C\n"); 364 lastctladdr = NULL; 365 lastuid = 0; 366 return; 367 } 368 369 /* find the active uid */ 370 q = getctladdr(a); 371 if (q == NULL) 372 uid = 0; 373 else 374 uid = q->q_uid; 375 a = a->q_alias; 376 377 /* check to see if this is the same as last time */ 378 if (lastctladdr != NULL && uid == lastuid && 379 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 380 return; 381 lastuid = uid; 382 lastctladdr = a; 383 384 if (uid == 0 || (pw = getpwuid(uid)) == NULL) 385 uname = ""; 386 else 387 uname = pw->pw_name; 388 389 fprintf(tfp, "C%s:%s\n", uname, a->q_paddr); 390 } 391 392 /* 393 ** RUNQUEUE -- run the jobs in the queue. 394 ** 395 ** Gets the stuff out of the queue in some presumably logical 396 ** order and processes them. 397 ** 398 ** Parameters: 399 ** forkflag -- TRUE if the queue scanning should be done in 400 ** a child process. We double-fork so it is not our 401 ** child and we don't have to clean up after it. 402 ** 403 ** Returns: 404 ** none. 405 ** 406 ** Side Effects: 407 ** runs things in the mail queue. 408 */ 409 410 ENVELOPE QueueEnvelope; /* the queue run envelope */ 411 412 runqueue(forkflag) 413 bool forkflag; 414 { 415 register ENVELOPE *e; 416 extern ENVELOPE BlankEnvelope; 417 418 /* 419 ** If no work will ever be selected, don't even bother reading 420 ** the queue. 421 */ 422 423 CurrentLA = getla(); /* get load average */ 424 425 if (shouldqueue(0L, curtime())) 426 { 427 if (Verbose) 428 printf("Skipping queue run -- load average too high\n"); 429 if (forkflag && QueueIntvl != 0) 430 (void) setevent(QueueIntvl, runqueue, TRUE); 431 return; 432 } 433 434 /* 435 ** See if we want to go off and do other useful work. 436 */ 437 438 if (forkflag) 439 { 440 int pid; 441 442 pid = dofork(); 443 if (pid != 0) 444 { 445 extern void reapchild(); 446 447 /* parent -- pick up intermediate zombie */ 448 #ifndef SIGCHLD 449 (void) waitfor(pid); 450 #else /* SIGCHLD */ 451 (void) setsignal(SIGCHLD, reapchild); 452 #endif /* SIGCHLD */ 453 if (QueueIntvl != 0) 454 (void) setevent(QueueIntvl, runqueue, TRUE); 455 return; 456 } 457 /* child -- double fork */ 458 #ifndef SIGCHLD 459 if (fork() != 0) 460 exit(EX_OK); 461 #else /* SIGCHLD */ 462 (void) setsignal(SIGCHLD, SIG_DFL); 463 #endif /* SIGCHLD */ 464 } 465 466 setproctitle("running queue: %s", QueueDir); 467 468 # ifdef LOG 469 if (LogLevel > 69) 470 syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d", 471 QueueDir, getpid(), forkflag); 472 # endif /* LOG */ 473 474 /* 475 ** Release any resources used by the daemon code. 476 */ 477 478 # ifdef DAEMON 479 clrdaemon(); 480 # endif /* DAEMON */ 481 482 /* force it to run expensive jobs */ 483 NoConnect = FALSE; 484 485 /* 486 ** Create ourselves an envelope 487 */ 488 489 CurEnv = &QueueEnvelope; 490 e = newenvelope(&QueueEnvelope, CurEnv); 491 e->e_flags = BlankEnvelope.e_flags; 492 493 /* 494 ** Make sure the alias database is open. 495 */ 496 497 initmaps(FALSE, e); 498 499 /* 500 ** Start making passes through the queue. 501 ** First, read and sort the entire queue. 502 ** Then, process the work in that order. 503 ** But if you take too long, start over. 504 */ 505 506 /* order the existing work requests */ 507 (void) orderq(FALSE); 508 509 /* process them once at a time */ 510 while (WorkQ != NULL) 511 { 512 WORK *w = WorkQ; 513 514 WorkQ = WorkQ->w_next; 515 516 /* 517 ** Ignore jobs that are too expensive for the moment. 518 */ 519 520 if (shouldqueue(w->w_pri, w->w_ctime)) 521 { 522 if (Verbose) 523 printf("\nSkipping %s\n", w->w_name + 2); 524 } 525 else 526 { 527 pid_t pid; 528 extern pid_t dowork(); 529 530 pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e); 531 errno = 0; 532 (void) waitfor(pid); 533 } 534 free(w->w_name); 535 free((char *) w); 536 } 537 538 /* exit without the usual cleanup */ 539 e->e_id = NULL; 540 finis(); 541 } 542 /* 543 ** ORDERQ -- order the work queue. 544 ** 545 ** Parameters: 546 ** doall -- if set, include everything in the queue (even 547 ** the jobs that cannot be run because the load 548 ** average is too high). Otherwise, exclude those 549 ** jobs. 550 ** 551 ** Returns: 552 ** The number of request in the queue (not necessarily 553 ** the number of requests in WorkQ however). 554 ** 555 ** Side Effects: 556 ** Sets WorkQ to the queue of available work, in order. 557 */ 558 559 # define NEED_P 001 560 # define NEED_T 002 561 # define NEED_R 004 562 # define NEED_S 010 563 564 orderq(doall) 565 bool doall; 566 { 567 register struct dirent *d; 568 register WORK *w; 569 DIR *f; 570 register int i; 571 WORK wlist[QUEUESIZE+1]; 572 int wn = -1; 573 extern workcmpf(); 574 575 if (tTd(41, 1)) 576 { 577 printf("orderq:\n"); 578 if (QueueLimitId != NULL) 579 printf("\tQueueLimitId = %s\n", QueueLimitId); 580 if (QueueLimitSender != NULL) 581 printf("\tQueueLimitSender = %s\n", QueueLimitSender); 582 if (QueueLimitRecipient != NULL) 583 printf("\tQueueLimitRecipient = %s\n", QueueLimitRecipient); 584 } 585 586 /* clear out old WorkQ */ 587 for (w = WorkQ; w != NULL; ) 588 { 589 register WORK *nw = w->w_next; 590 591 WorkQ = nw; 592 free(w->w_name); 593 free((char *) w); 594 w = nw; 595 } 596 597 /* open the queue directory */ 598 f = opendir("."); 599 if (f == NULL) 600 { 601 syserr("orderq: cannot open \"%s\" as \".\"", QueueDir); 602 return (0); 603 } 604 605 /* 606 ** Read the work directory. 607 */ 608 609 while ((d = readdir(f)) != NULL) 610 { 611 FILE *cf; 612 register char *p; 613 char lbuf[MAXNAME]; 614 extern bool strcontainedin(); 615 616 /* is this an interesting entry? */ 617 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 618 continue; 619 620 if (QueueLimitId != NULL && 621 !strcontainedin(QueueLimitId, d->d_name)) 622 continue; 623 624 /* 625 ** Check queue name for plausibility. This handles 626 ** both old and new type ids. 627 */ 628 629 p = d->d_name + 2; 630 if (isupper(p[0]) && isupper(p[2])) 631 p += 3; 632 else if (isupper(p[1])) 633 p += 2; 634 else 635 p = d->d_name; 636 for (i = 0; isdigit(*p); p++) 637 i++; 638 if (i < 5 || *p != '\0') 639 { 640 if (Verbose) 641 printf("orderq: bogus qf name %s\n", d->d_name); 642 #ifdef LOG 643 if (LogLevel > 3) 644 syslog(LOG_CRIT, "orderq: bogus qf name %s", 645 d->d_name); 646 #endif 647 if (strlen(d->d_name) >= MAXNAME) 648 d->d_name[MAXNAME - 1] = '\0'; 649 strcpy(lbuf, d->d_name); 650 lbuf[0] = 'Q'; 651 (void) rename(d->d_name, lbuf); 652 continue; 653 } 654 655 /* yes -- open control file (if not too many files) */ 656 if (++wn >= QUEUESIZE) 657 continue; 658 659 cf = fopen(d->d_name, "r"); 660 if (cf == NULL) 661 { 662 /* this may be some random person sending hir msgs */ 663 /* syserr("orderq: cannot open %s", cbuf); */ 664 if (tTd(41, 2)) 665 printf("orderq: cannot open %s (%d)\n", 666 d->d_name, errno); 667 errno = 0; 668 wn--; 669 continue; 670 } 671 w = &wlist[wn]; 672 w->w_name = newstr(d->d_name); 673 674 /* make sure jobs in creation don't clog queue */ 675 w->w_pri = 0x7fffffff; 676 w->w_ctime = 0; 677 678 /* extract useful information */ 679 i = NEED_P | NEED_T; 680 if (QueueLimitSender != NULL) 681 i |= NEED_S; 682 if (QueueLimitRecipient != NULL) 683 i |= NEED_R; 684 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 685 { 686 extern long atol(); 687 extern bool strcontainedin(); 688 689 switch (lbuf[0]) 690 { 691 case 'P': 692 w->w_pri = atol(&lbuf[1]); 693 i &= ~NEED_P; 694 break; 695 696 case 'T': 697 w->w_ctime = atol(&lbuf[1]); 698 i &= ~NEED_T; 699 break; 700 701 case 'R': 702 if (QueueLimitRecipient != NULL && 703 strcontainedin(QueueLimitRecipient, &lbuf[1])) 704 i &= ~NEED_R; 705 break; 706 707 case 'S': 708 if (QueueLimitSender != NULL && 709 strcontainedin(QueueLimitSender, &lbuf[1])) 710 i &= ~NEED_S; 711 break; 712 } 713 } 714 (void) fclose(cf); 715 716 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 717 bitset(NEED_R|NEED_S, i)) 718 { 719 /* don't even bother sorting this job in */ 720 wn--; 721 } 722 } 723 (void) closedir(f); 724 wn++; 725 726 /* 727 ** Sort the work directory. 728 */ 729 730 qsort((char *) wlist, min(wn, QUEUESIZE), sizeof *wlist, workcmpf); 731 732 /* 733 ** Convert the work list into canonical form. 734 ** Should be turning it into a list of envelopes here perhaps. 735 */ 736 737 WorkQ = NULL; 738 for (i = min(wn, QUEUESIZE); --i >= 0; ) 739 { 740 w = (WORK *) xalloc(sizeof *w); 741 w->w_name = wlist[i].w_name; 742 w->w_pri = wlist[i].w_pri; 743 w->w_ctime = wlist[i].w_ctime; 744 w->w_next = WorkQ; 745 WorkQ = w; 746 } 747 748 if (tTd(40, 1)) 749 { 750 for (w = WorkQ; w != NULL; w = w->w_next) 751 printf("%32s: pri=%ld\n", w->w_name, w->w_pri); 752 } 753 754 return (wn); 755 } 756 /* 757 ** WORKCMPF -- compare function for ordering work. 758 ** 759 ** Parameters: 760 ** a -- the first argument. 761 ** b -- the second argument. 762 ** 763 ** Returns: 764 ** -1 if a < b 765 ** 0 if a == b 766 ** +1 if a > b 767 ** 768 ** Side Effects: 769 ** none. 770 */ 771 772 workcmpf(a, b) 773 register WORK *a; 774 register WORK *b; 775 { 776 long pa = a->w_pri; 777 long pb = b->w_pri; 778 779 if (pa == pb) 780 return (0); 781 else if (pa > pb) 782 return (1); 783 else 784 return (-1); 785 } 786 /* 787 ** DOWORK -- do a work request. 788 ** 789 ** Parameters: 790 ** id -- the ID of the job to run. 791 ** forkflag -- if set, run this in background. 792 ** requeueflag -- if set, reinstantiate the queue quickly. 793 ** This is used when expanding aliases in the queue. 794 ** If forkflag is also set, it doesn't wait for the 795 ** child. 796 ** e - the envelope in which to run it. 797 ** 798 ** Returns: 799 ** process id of process that is running the queue job. 800 ** 801 ** Side Effects: 802 ** The work request is satisfied if possible. 803 */ 804 805 pid_t 806 dowork(id, forkflag, requeueflag, e) 807 char *id; 808 bool forkflag; 809 bool requeueflag; 810 register ENVELOPE *e; 811 { 812 register pid_t pid; 813 extern bool readqf(); 814 815 if (tTd(40, 1)) 816 printf("dowork(%s)\n", id); 817 818 /* 819 ** Fork for work. 820 */ 821 822 if (forkflag) 823 { 824 pid = fork(); 825 if (pid < 0) 826 { 827 syserr("dowork: cannot fork"); 828 return 0; 829 } 830 else if (pid > 0) 831 { 832 /* parent -- clean out connection cache */ 833 mci_flush(FALSE, NULL); 834 } 835 } 836 else 837 { 838 pid = 0; 839 } 840 841 if (pid == 0) 842 { 843 /* 844 ** CHILD 845 ** Lock the control file to avoid duplicate deliveries. 846 ** Then run the file as though we had just read it. 847 ** We save an idea of the temporary name so we 848 ** can recover on interrupt. 849 */ 850 851 /* set basic modes, etc. */ 852 (void) alarm(0); 853 clearenvelope(e, FALSE); 854 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 855 e->e_errormode = EM_MAIL; 856 e->e_id = id; 857 GrabTo = UseErrorsTo = FALSE; 858 if (forkflag) 859 { 860 disconnect(1, e); 861 OpMode = MD_DELIVER; 862 } 863 # ifdef LOG 864 if (LogLevel > 76) 865 syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id, 866 getpid()); 867 # endif /* LOG */ 868 869 /* don't use the headers from sendmail.cf... */ 870 e->e_header = NULL; 871 872 /* read the queue control file -- return if locked */ 873 if (!readqf(e, !requeueflag)) 874 { 875 if (tTd(40, 4)) 876 printf("readqf(%s) failed\n", e->e_id); 877 if (forkflag) 878 exit(EX_OK); 879 else 880 return; 881 } 882 883 e->e_flags |= EF_INQUEUE; 884 eatheader(e, requeueflag); 885 886 if (requeueflag) 887 queueup(e, TRUE, FALSE); 888 889 /* do the delivery */ 890 sendall(e, SM_DELIVER); 891 892 /* finish up and exit */ 893 if (forkflag) 894 finis(); 895 else 896 dropenvelope(e); 897 } 898 e->e_id = NULL; 899 return pid; 900 } 901 /* 902 ** READQF -- read queue file and set up environment. 903 ** 904 ** Parameters: 905 ** e -- the envelope of the job to run. 906 ** announcefile -- if set, announce the name of the queue 907 ** file in error messages. 908 ** 909 ** Returns: 910 ** TRUE if it successfully read the queue file. 911 ** FALSE otherwise. 912 ** 913 ** Side Effects: 914 ** The queue file is returned locked. 915 */ 916 917 bool 918 readqf(e, announcefile) 919 register ENVELOPE *e; 920 bool announcefile; 921 { 922 register FILE *qfp; 923 ADDRESS *ctladdr; 924 struct stat st; 925 char *bp; 926 char qf[20]; 927 char buf[MAXLINE]; 928 extern long atol(); 929 extern ADDRESS *setctluser(); 930 931 /* 932 ** Read and process the file. 933 */ 934 935 strcpy(qf, queuename(e, 'q')); 936 qfp = fopen(qf, "r+"); 937 if (qfp == NULL) 938 { 939 if (tTd(40, 8)) 940 printf("readqf(%s): fopen failure (%s)\n", 941 qf, errstring(errno)); 942 if (errno != ENOENT) 943 syserr("readqf: no control file %s", qf); 944 return FALSE; 945 } 946 947 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 948 { 949 /* being processed by another queuer */ 950 if (tTd(40, 8)) 951 printf("readqf(%s): locked\n", qf); 952 if (Verbose) 953 printf("%s: locked\n", e->e_id); 954 # ifdef LOG 955 if (LogLevel > 19) 956 syslog(LOG_DEBUG, "%s: locked", e->e_id); 957 # endif /* LOG */ 958 (void) fclose(qfp); 959 return FALSE; 960 } 961 962 /* 963 ** Check the queue file for plausibility to avoid attacks. 964 */ 965 966 if (fstat(fileno(qfp), &st) < 0) 967 { 968 /* must have been being processed by someone else */ 969 if (tTd(40, 8)) 970 printf("readqf(%s): fstat failure (%s)\n", 971 qf, errstring(errno)); 972 fclose(qfp); 973 return FALSE; 974 } 975 976 if (st.st_uid != geteuid()) 977 { 978 # ifdef LOG 979 if (LogLevel > 0) 980 { 981 syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o", 982 e->e_id, st.st_uid, st.st_mode); 983 } 984 # endif /* LOG */ 985 if (tTd(40, 8)) 986 printf("readqf(%s): bogus file\n", qf); 987 rename(qf, queuename(e, 'Q')); 988 fclose(qfp); 989 return FALSE; 990 } 991 992 if (st.st_size == 0) 993 { 994 /* must be a bogus file -- just remove it */ 995 (void) unlink(qf); 996 fclose(qfp); 997 return FALSE; 998 } 999 1000 if (st.st_nlink == 0) 1001 { 1002 /* 1003 ** Race condition -- we got a file just as it was being 1004 ** unlinked. Just assume it is zero length. 1005 */ 1006 1007 fclose(qfp); 1008 return FALSE; 1009 } 1010 1011 /* good file -- save this lock */ 1012 e->e_lockfp = qfp; 1013 1014 /* do basic system initialization */ 1015 initsys(e); 1016 1017 if (announcefile) 1018 FileName = qf; 1019 LineNumber = 0; 1020 e->e_flags |= EF_GLOBALERRS; 1021 OpMode = MD_DELIVER; 1022 if (Verbose) 1023 printf("\nRunning %s\n", e->e_id); 1024 ctladdr = NULL; 1025 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1026 { 1027 register char *p; 1028 struct stat st; 1029 1030 if (tTd(40, 4)) 1031 printf("+++++ %s\n", bp); 1032 switch (bp[0]) 1033 { 1034 case 'C': /* specify controlling user */ 1035 ctladdr = setctluser(&bp[1]); 1036 break; 1037 1038 case 'R': /* specify recipient */ 1039 (void) sendtolist(&bp[1], ctladdr, &e->e_sendqueue, e); 1040 break; 1041 1042 case 'E': /* specify error recipient */ 1043 (void) sendtolist(&bp[1], ctladdr, &e->e_errorqueue, e); 1044 break; 1045 1046 case 'H': /* header */ 1047 (void) chompheader(&bp[1], FALSE, e); 1048 break; 1049 1050 case 'M': /* message */ 1051 /* ignore this; we want a new message next time */ 1052 break; 1053 1054 case 'S': /* sender */ 1055 setsender(newstr(&bp[1]), e, NULL, TRUE); 1056 break; 1057 1058 case 'B': /* body type */ 1059 e->e_bodytype = newstr(&bp[1]); 1060 break; 1061 1062 case 'D': /* data file name */ 1063 e->e_df = newstr(&bp[1]); 1064 e->e_dfp = fopen(e->e_df, "r"); 1065 if (e->e_dfp == NULL) 1066 { 1067 syserr("readqf: cannot open %s", e->e_df); 1068 e->e_msgsize = -1; 1069 } 1070 else if (fstat(fileno(e->e_dfp), &st) >= 0) 1071 e->e_msgsize = st.st_size; 1072 break; 1073 1074 case 'T': /* init time */ 1075 e->e_ctime = atol(&bp[1]); 1076 break; 1077 1078 case 'P': /* message priority */ 1079 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 1080 break; 1081 1082 case 'F': /* flag bits */ 1083 for (p = &bp[1]; *p != '\0'; p++) 1084 { 1085 switch (*p) 1086 { 1087 case 'w': /* warning sent */ 1088 e->e_flags |= EF_WARNING; 1089 break; 1090 1091 case 'r': /* response */ 1092 e->e_flags |= EF_RESPONSE; 1093 break; 1094 } 1095 } 1096 break; 1097 1098 case '$': /* define macro */ 1099 define(bp[1], newstr(&bp[2]), e); 1100 break; 1101 1102 case '\0': /* blank line; ignore */ 1103 break; 1104 1105 default: 1106 syserr("readqf: bad line \"%s\"", e->e_id, 1107 LineNumber, bp); 1108 fclose(qfp); 1109 rename(qf, queuename(e, 'Q')); 1110 return FALSE; 1111 } 1112 1113 if (bp != buf) 1114 free(bp); 1115 } 1116 1117 FileName = NULL; 1118 1119 /* 1120 ** If we haven't read any lines, this queue file is empty. 1121 ** Arrange to remove it without referencing any null pointers. 1122 */ 1123 1124 if (LineNumber == 0) 1125 { 1126 errno = 0; 1127 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 1128 } 1129 return TRUE; 1130 } 1131 /* 1132 ** PRINTQUEUE -- print out a representation of the mail queue 1133 ** 1134 ** Parameters: 1135 ** none. 1136 ** 1137 ** Returns: 1138 ** none. 1139 ** 1140 ** Side Effects: 1141 ** Prints a listing of the mail queue on the standard output. 1142 */ 1143 1144 printqueue() 1145 { 1146 register WORK *w; 1147 FILE *f; 1148 int nrequests; 1149 char buf[MAXLINE]; 1150 1151 /* 1152 ** Check for permission to print the queue 1153 */ 1154 1155 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 1156 { 1157 struct stat st; 1158 # ifdef NGROUPS 1159 int n; 1160 GIDSET_T gidset[NGROUPS]; 1161 # endif 1162 1163 if (stat(QueueDir, &st) < 0) 1164 { 1165 syserr("Cannot stat %s", QueueDir); 1166 return; 1167 } 1168 # ifdef NGROUPS 1169 n = getgroups(NGROUPS, gidset); 1170 while (--n >= 0) 1171 { 1172 if (gidset[n] == st.st_gid) 1173 break; 1174 } 1175 if (n < 0) 1176 # else 1177 if (RealGid != st.st_gid) 1178 # endif 1179 { 1180 usrerr("510 You are not permitted to see the queue"); 1181 setstat(EX_NOPERM); 1182 return; 1183 } 1184 } 1185 1186 /* 1187 ** Read and order the queue. 1188 */ 1189 1190 nrequests = orderq(TRUE); 1191 1192 /* 1193 ** Print the work list that we have read. 1194 */ 1195 1196 /* first see if there is anything */ 1197 if (nrequests <= 0) 1198 { 1199 printf("Mail queue is empty\n"); 1200 return; 1201 } 1202 1203 CurrentLA = getla(); /* get load average */ 1204 1205 printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); 1206 if (nrequests > QUEUESIZE) 1207 printf(", only %d printed", QUEUESIZE); 1208 if (Verbose) 1209 printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); 1210 else 1211 printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 1212 for (w = WorkQ; w != NULL; w = w->w_next) 1213 { 1214 struct stat st; 1215 auto time_t submittime = 0; 1216 long dfsize = -1; 1217 int flags = 0; 1218 char message[MAXLINE]; 1219 char bodytype[MAXNAME]; 1220 1221 printf("%8s", w->w_name + 2); 1222 f = fopen(w->w_name, "r"); 1223 if (f == NULL) 1224 { 1225 printf(" (job completed)\n"); 1226 errno = 0; 1227 continue; 1228 } 1229 if (!lockfile(fileno(f), w->w_name, NULL, LOCK_SH|LOCK_NB)) 1230 printf("*"); 1231 else if (shouldqueue(w->w_pri, w->w_ctime)) 1232 printf("X"); 1233 else 1234 printf(" "); 1235 errno = 0; 1236 1237 message[0] = bodytype[0] = '\0'; 1238 while (fgets(buf, sizeof buf, f) != NULL) 1239 { 1240 register int i; 1241 register char *p; 1242 1243 fixcrlf(buf, TRUE); 1244 switch (buf[0]) 1245 { 1246 case 'M': /* error message */ 1247 if ((i = strlen(&buf[1])) >= sizeof message) 1248 i = sizeof message - 1; 1249 bcopy(&buf[1], message, i); 1250 message[i] = '\0'; 1251 break; 1252 1253 case 'B': /* body type */ 1254 if ((i = strlen(&buf[1])) >= sizeof bodytype) 1255 i = sizeof bodytype - 1; 1256 bcopy(&buf[1], bodytype, i); 1257 bodytype[i] = '\0'; 1258 break; 1259 1260 case 'S': /* sender name */ 1261 if (Verbose) 1262 printf("%8ld %10ld%c%.12s %.38s", 1263 dfsize, 1264 w->w_pri, 1265 bitset(EF_WARNING, flags) ? '+' : ' ', 1266 ctime(&submittime) + 4, 1267 &buf[1]); 1268 else 1269 printf("%8ld %.16s %.45s", dfsize, 1270 ctime(&submittime), &buf[1]); 1271 if (message[0] != '\0' || bodytype[0] != '\0') 1272 { 1273 printf("\n %10.10s", bodytype); 1274 if (message[0] != '\0') 1275 printf(" (%.60s)", message); 1276 } 1277 break; 1278 1279 case 'C': /* controlling user */ 1280 if (Verbose) 1281 printf("\n\t\t\t\t (---%.34s---)", 1282 &buf[1]); 1283 break; 1284 1285 case 'R': /* recipient name */ 1286 if (Verbose) 1287 printf("\n\t\t\t\t\t %.38s", &buf[1]); 1288 else 1289 printf("\n\t\t\t\t %.45s", &buf[1]); 1290 break; 1291 1292 case 'T': /* creation time */ 1293 submittime = atol(&buf[1]); 1294 break; 1295 1296 case 'D': /* data file name */ 1297 if (stat(&buf[1], &st) >= 0) 1298 dfsize = st.st_size; 1299 break; 1300 1301 case 'F': /* flag bits */ 1302 for (p = &buf[1]; *p != '\0'; p++) 1303 { 1304 switch (*p) 1305 { 1306 case 'w': 1307 flags |= EF_WARNING; 1308 break; 1309 } 1310 } 1311 } 1312 } 1313 if (submittime == (time_t) 0) 1314 printf(" (no control file)"); 1315 printf("\n"); 1316 (void) fclose(f); 1317 } 1318 } 1319 1320 # endif /* QUEUE */ 1321 /* 1322 ** QUEUENAME -- build a file name in the queue directory for this envelope. 1323 ** 1324 ** Assigns an id code if one does not already exist. 1325 ** This code is very careful to avoid trashing existing files 1326 ** under any circumstances. 1327 ** 1328 ** Parameters: 1329 ** e -- envelope to build it in/from. 1330 ** type -- the file type, used as the first character 1331 ** of the file name. 1332 ** 1333 ** Returns: 1334 ** a pointer to the new file name (in a static buffer). 1335 ** 1336 ** Side Effects: 1337 ** If no id code is already assigned, queuename will 1338 ** assign an id code, create a qf file, and leave a 1339 ** locked, open-for-write file pointer in the envelope. 1340 */ 1341 1342 char * 1343 queuename(e, type) 1344 register ENVELOPE *e; 1345 int type; 1346 { 1347 static int pid = -1; 1348 static char c0; 1349 static char c1; 1350 static char c2; 1351 time_t now; 1352 struct tm *tm; 1353 static char buf[MAXNAME]; 1354 1355 if (e->e_id == NULL) 1356 { 1357 char qf[20]; 1358 1359 /* find a unique id */ 1360 if (pid != getpid()) 1361 { 1362 /* new process -- start back at "AA" */ 1363 pid = getpid(); 1364 now = curtime(); 1365 tm = localtime(&now); 1366 c0 = 'A' + tm->tm_hour; 1367 c1 = 'A'; 1368 c2 = 'A' - 1; 1369 } 1370 (void) sprintf(qf, "qf%cAA%05d", c0, pid); 1371 1372 while (c1 < '~' || c2 < 'Z') 1373 { 1374 int i; 1375 1376 if (c2 >= 'Z') 1377 { 1378 c1++; 1379 c2 = 'A' - 1; 1380 } 1381 qf[3] = c1; 1382 qf[4] = ++c2; 1383 if (tTd(7, 20)) 1384 printf("queuename: trying \"%s\"\n", qf); 1385 1386 i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); 1387 if (i < 0) 1388 { 1389 if (errno == EEXIST) 1390 continue; 1391 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1392 qf, QueueDir, geteuid()); 1393 exit(EX_UNAVAILABLE); 1394 } 1395 if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) 1396 { 1397 e->e_lockfp = fdopen(i, "w"); 1398 break; 1399 } 1400 1401 /* a reader got the file; abandon it and try again */ 1402 (void) close(i); 1403 } 1404 if (c1 >= '~' && c2 >= 'Z') 1405 { 1406 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 1407 qf, QueueDir, geteuid()); 1408 exit(EX_OSERR); 1409 } 1410 e->e_id = newstr(&qf[2]); 1411 define('i', e->e_id, e); 1412 if (tTd(7, 1)) 1413 printf("queuename: assigned id %s, env=%x\n", e->e_id, e); 1414 if (tTd(7, 9)) 1415 { 1416 printf(" lockfd="); 1417 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 1418 } 1419 # ifdef LOG 1420 if (LogLevel > 93) 1421 syslog(LOG_DEBUG, "%s: assigned id", e->e_id); 1422 # endif /* LOG */ 1423 } 1424 1425 if (type == '\0') 1426 return (NULL); 1427 (void) sprintf(buf, "%cf%s", type, e->e_id); 1428 if (tTd(7, 2)) 1429 printf("queuename: %s\n", buf); 1430 return (buf); 1431 } 1432 /* 1433 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 1434 ** 1435 ** Parameters: 1436 ** e -- the envelope to unlock. 1437 ** 1438 ** Returns: 1439 ** none 1440 ** 1441 ** Side Effects: 1442 ** unlocks the queue for `e'. 1443 */ 1444 1445 unlockqueue(e) 1446 ENVELOPE *e; 1447 { 1448 if (tTd(51, 4)) 1449 printf("unlockqueue(%s)\n", e->e_id); 1450 1451 /* if there is a lock file in the envelope, close it */ 1452 if (e->e_lockfp != NULL) 1453 xfclose(e->e_lockfp, "unlockqueue", e->e_id); 1454 e->e_lockfp = NULL; 1455 1456 /* don't create a queue id if we don't already have one */ 1457 if (e->e_id == NULL) 1458 return; 1459 1460 /* remove the transcript */ 1461 # ifdef LOG 1462 if (LogLevel > 87) 1463 syslog(LOG_DEBUG, "%s: unlock", e->e_id); 1464 # endif /* LOG */ 1465 if (!tTd(51, 104)) 1466 xunlink(queuename(e, 'x')); 1467 1468 } 1469 /* 1470 ** SETCTLUSER -- create a controlling address 1471 ** 1472 ** Create a fake "address" given only a local login name; this is 1473 ** used as a "controlling user" for future recipient addresses. 1474 ** 1475 ** Parameters: 1476 ** user -- the user name of the controlling user. 1477 ** 1478 ** Returns: 1479 ** An address descriptor for the controlling user. 1480 ** 1481 ** Side Effects: 1482 ** none. 1483 */ 1484 1485 ADDRESS * 1486 setctluser(user) 1487 char *user; 1488 { 1489 register ADDRESS *a; 1490 struct passwd *pw; 1491 char *p; 1492 1493 /* 1494 ** See if this clears our concept of controlling user. 1495 */ 1496 1497 if (user == NULL || *user == '\0') 1498 return NULL; 1499 1500 /* 1501 ** Set up addr fields for controlling user. 1502 */ 1503 1504 a = (ADDRESS *) xalloc(sizeof *a); 1505 bzero((char *) a, sizeof *a); 1506 1507 p = strchr(user, ':'); 1508 if (p != NULL) 1509 *p++ = '\0'; 1510 if (*user != '\0' && (pw = getpwnam(user)) != NULL) 1511 { 1512 a->q_home = newstr(pw->pw_dir); 1513 a->q_uid = pw->pw_uid; 1514 a->q_gid = pw->pw_gid; 1515 a->q_user = newstr(user); 1516 a->q_flags |= QGOODUID; 1517 } 1518 else 1519 { 1520 a->q_user = newstr(DefUser); 1521 } 1522 1523 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 1524 a->q_mailer = LocalMailer; 1525 if (p == NULL) 1526 a->q_paddr = a->q_user; 1527 else 1528 a->q_paddr = newstr(p); 1529 return a; 1530 } 1531