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