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