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