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