queue.c revision 38032
1/* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 */ 12 13# include "sendmail.h" 14 15#ifndef lint 16#if QUEUE 17static char sccsid[] = "@(#)queue.c 8.202 (Berkeley) 6/15/98 (with queueing)"; 18#else 19static char sccsid[] = "@(#)queue.c 8.202 (Berkeley) 6/15/98 (without queueing)"; 20#endif 21#endif /* not lint */ 22 23# include <errno.h> 24# include <dirent.h> 25 26# if QUEUE 27 28/* 29** Work queue. 30*/ 31 32struct work 33{ 34 char *w_name; /* name of control file */ 35 char *w_host; /* name of recipient host */ 36 bool w_lock; /* is message locked? */ 37 bool w_tooyoung; /* is it too young to run? */ 38 long w_pri; /* priority of message, see below */ 39 time_t w_ctime; /* creation time of message */ 40 struct work *w_next; /* next in queue */ 41}; 42 43typedef struct work WORK; 44 45WORK *WorkQ; /* queue of things to be done */ 46 47#define QF_VERSION 2 /* version number of this queue format */ 48 49extern int orderq __P((bool)); 50/* 51** QUEUEUP -- queue a message up for future transmission. 52** 53** Parameters: 54** e -- the envelope to queue up. 55** announce -- if TRUE, tell when you are queueing up. 56** 57** Returns: 58** none. 59** 60** Side Effects: 61** The current request are saved in a control file. 62** The queue file is left locked. 63*/ 64 65void 66queueup(e, announce) 67 register ENVELOPE *e; 68 bool announce; 69{ 70 char *qf; 71 register FILE *tfp; 72 register HDR *h; 73 register ADDRESS *q; 74 int fd; 75 int i; 76 bool newid; 77 register char *p; 78 MAILER nullmailer; 79 MCI mcibuf; 80 char tf[MAXQFNAME]; 81 char buf[MAXLINE]; 82 extern void printctladdr __P((ADDRESS *, FILE *)); 83 84 /* 85 ** Create control file. 86 */ 87 88 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 89 90 /* if newid, queuename will create a locked qf file in e->lockfp */ 91 strcpy(tf, queuename(e, 't')); 92 tfp = e->e_lockfp; 93 if (tfp == NULL) 94 newid = FALSE; 95 96 /* if newid, just write the qf file directly (instead of tf file) */ 97 if (!newid) 98 { 99 /* get a locked tf file */ 100 for (i = 0; i < 128; i++) 101 { 102 fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode); 103 if (fd < 0) 104 { 105 if (errno != EEXIST) 106 break; 107 if (LogLevel > 0 && (i % 32) == 0) 108 sm_syslog(LOG_ALERT, e->e_id, 109 "queueup: cannot create %s, uid=%d: %s", 110 tf, geteuid(), errstring(errno)); 111 } 112 else 113 { 114 if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB)) 115 break; 116 else if (LogLevel > 0 && (i % 32) == 0) 117 sm_syslog(LOG_ALERT, e->e_id, 118 "queueup: cannot lock %s: %s", 119 tf, errstring(errno)); 120 close(fd); 121 } 122 123 if ((i % 32) == 31) 124 { 125 /* save the old temp file away */ 126 (void) rename(tf, queuename(e, 'T')); 127 } 128 else 129 sleep(i % 32); 130 } 131 if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL) 132 { 133 printopenfds(TRUE); 134 syserr("!queueup: cannot create queue temp file %s, uid=%d", 135 tf, geteuid()); 136 } 137 } 138 139 if (tTd(40, 1)) 140 printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id, 141 newid ? " (new id)" : ""); 142 if (tTd(40, 3)) 143 { 144 extern void printenvflags __P((ENVELOPE *)); 145 146 printf(" e_flags="); 147 printenvflags(e); 148 } 149 if (tTd(40, 32)) 150 { 151 printf(" sendq="); 152 printaddr(e->e_sendqueue, TRUE); 153 } 154 if (tTd(40, 9)) 155 { 156 printf(" tfp="); 157 dumpfd(fileno(tfp), TRUE, FALSE); 158 printf(" lockfp="); 159 if (e->e_lockfp == NULL) 160 printf("NULL\n"); 161 else 162 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 163 } 164 165 /* 166 ** If there is no data file yet, create one. 167 */ 168 169 if (!bitset(EF_HAS_DF, e->e_flags)) 170 { 171 register FILE *dfp = NULL; 172 char dfname[MAXQFNAME]; 173 struct stat stbuf; 174 175 strcpy(dfname, queuename(e, 'd')); 176 fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode); 177 if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL) 178 syserr("!queueup: cannot create data temp file %s, uid=%d", 179 dfname, geteuid()); 180 if (fstat(fd, &stbuf) < 0) 181 e->e_dfino = -1; 182 else 183 { 184 e->e_dfdev = stbuf.st_dev; 185 e->e_dfino = stbuf.st_ino; 186 } 187 e->e_flags |= EF_HAS_DF; 188 bzero(&mcibuf, sizeof mcibuf); 189 mcibuf.mci_out = dfp; 190 mcibuf.mci_mailer = FileMailer; 191 (*e->e_putbody)(&mcibuf, e, NULL); 192 (void) xfclose(dfp, "queueup dfp", e->e_id); 193 e->e_putbody = putbody; 194 } 195 196 /* 197 ** Output future work requests. 198 ** Priority and creation time should be first, since 199 ** they are required by orderq. 200 */ 201 202 /* output queue version number (must be first!) */ 203 fprintf(tfp, "V%d\n", QF_VERSION); 204 205 /* output creation time */ 206 fprintf(tfp, "T%ld\n", (long) e->e_ctime); 207 208 /* output last delivery time */ 209 fprintf(tfp, "K%ld\n", (long) e->e_dtime); 210 211 /* output number of delivery attempts */ 212 fprintf(tfp, "N%d\n", e->e_ntries); 213 214 /* output message priority */ 215 fprintf(tfp, "P%ld\n", e->e_msgpriority); 216 217 /* output inode number of data file */ 218 /* XXX should probably include device major/minor too */ 219 if (e->e_dfino != -1) 220 { 221 if (sizeof e->e_dfino > sizeof(long)) 222 fprintf(tfp, "I%d/%d/%s\n", 223 major(e->e_dfdev), minor(e->e_dfdev), 224 quad_to_string(e->e_dfino)); 225 else 226 fprintf(tfp, "I%d/%d/%lu\n", 227 major(e->e_dfdev), minor(e->e_dfdev), 228 (unsigned long) e->e_dfino); 229 } 230 231 /* output body type */ 232 if (e->e_bodytype != NULL) 233 fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE)); 234 235#if _FFR_SAVE_CHARSET 236 if (e->e_charset != NULL) 237 fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE)); 238#endif 239 240 /* message from envelope, if it exists */ 241 if (e->e_message != NULL) 242 fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE)); 243 244 /* send various flag bits through */ 245 p = buf; 246 if (bitset(EF_WARNING, e->e_flags)) 247 *p++ = 'w'; 248 if (bitset(EF_RESPONSE, e->e_flags)) 249 *p++ = 'r'; 250 if (bitset(EF_HAS8BIT, e->e_flags)) 251 *p++ = '8'; 252 if (bitset(EF_DELETE_BCC, e->e_flags)) 253 *p++ = 'b'; 254 if (bitset(EF_RET_PARAM, e->e_flags)) 255 *p++ = 'd'; 256 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 257 *p++ = 'n'; 258 *p++ = '\0'; 259 if (buf[0] != '\0') 260 fprintf(tfp, "F%s\n", buf); 261 262 /* $r and $s and $_ macro values */ 263 if ((p = macvalue('r', e)) != NULL) 264 fprintf(tfp, "$r%s\n", denlstring(p, TRUE, FALSE)); 265 if ((p = macvalue('s', e)) != NULL) 266 fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE)); 267 if ((p = macvalue('_', e)) != NULL) 268 fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE)); 269 270 /* output name of sender */ 271 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) 272 p = e->e_sender; 273 else 274 p = e->e_from.q_paddr; 275 fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE)); 276 277 /* output ESMTP-supplied "original" information */ 278 if (e->e_envid != NULL) 279 fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE)); 280 281 /* output list of recipient addresses */ 282 printctladdr(NULL, NULL); 283 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 284 { 285 if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags)) 286 { 287#if XDEBUG 288 if (bitset(QQUEUEUP, q->q_flags)) 289 sm_syslog(LOG_DEBUG, e->e_id, 290 "dropenvelope: q_flags = %x, paddr = %s", 291 q->q_flags, q->q_paddr); 292#endif 293 continue; 294 } 295 printctladdr(q, tfp); 296 if (q->q_orcpt != NULL) 297 fprintf(tfp, "Q%s\n", 298 denlstring(q->q_orcpt, TRUE, FALSE)); 299 putc('R', tfp); 300 if (bitset(QPRIMARY, q->q_flags)) 301 putc('P', tfp); 302 if (bitset(QHASNOTIFY, q->q_flags)) 303 putc('N', tfp); 304 if (bitset(QPINGONSUCCESS, q->q_flags)) 305 putc('S', tfp); 306 if (bitset(QPINGONFAILURE, q->q_flags)) 307 putc('F', tfp); 308 if (bitset(QPINGONDELAY, q->q_flags)) 309 putc('D', tfp); 310 putc(':', tfp); 311 fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE)); 312 if (announce) 313 { 314 e->e_to = q->q_paddr; 315 message("queued"); 316 if (LogLevel > 8) 317 logdelivery(q->q_mailer, NULL, "queued", 318 NULL, (time_t) 0, e); 319 e->e_to = NULL; 320 } 321 if (tTd(40, 1)) 322 { 323 printf("queueing "); 324 printaddr(q, FALSE); 325 } 326 } 327 328 /* 329 ** Output headers for this message. 330 ** Expand macros completely here. Queue run will deal with 331 ** everything as absolute headers. 332 ** All headers that must be relative to the recipient 333 ** can be cracked later. 334 ** We set up a "null mailer" -- i.e., a mailer that will have 335 ** no effect on the addresses as they are output. 336 */ 337 338 bzero((char *) &nullmailer, sizeof nullmailer); 339 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 340 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; 341 nullmailer.m_eol = "\n"; 342 bzero(&mcibuf, sizeof mcibuf); 343 mcibuf.mci_mailer = &nullmailer; 344 mcibuf.mci_out = tfp; 345 346 define('g', "\201f", e); 347 for (h = e->e_header; h != NULL; h = h->h_link) 348 { 349 extern bool bitzerop __P((BITMAP)); 350 351 /* don't output null headers */ 352 if (h->h_value == NULL || h->h_value[0] == '\0') 353 continue; 354 355 /* don't output resent headers on non-resent messages */ 356 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 357 continue; 358 359 /* expand macros; if null, don't output header at all */ 360 if (bitset(H_DEFAULT, h->h_flags)) 361 { 362 (void) expand(h->h_value, buf, sizeof buf, e); 363 if (buf[0] == '\0') 364 continue; 365 } 366 367 /* output this header */ 368 fprintf(tfp, "H"); 369 370 /* if conditional, output the set of conditions */ 371 if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags)) 372 { 373 int j; 374 375 (void) putc('?', tfp); 376 for (j = '\0'; j <= '\177'; j++) 377 if (bitnset(j, h->h_mflags)) 378 (void) putc(j, tfp); 379 (void) putc('?', tfp); 380 } 381 382 /* output the header: expand macros, convert addresses */ 383 if (bitset(H_DEFAULT, h->h_flags)) 384 { 385 fprintf(tfp, "%s: %s\n", 386 h->h_field, 387 denlstring(buf, FALSE, TRUE)); 388 } 389 else if (bitset(H_FROM|H_RCPT, h->h_flags)) 390 { 391 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 392 FILE *savetrace = TrafficLogFile; 393 394 TrafficLogFile = NULL; 395 396 if (bitset(H_FROM, h->h_flags)) 397 oldstyle = FALSE; 398 399 commaize(h, h->h_value, oldstyle, &mcibuf, e); 400 401 TrafficLogFile = savetrace; 402 } 403 else 404 { 405 fprintf(tfp, "%s: %s\n", 406 h->h_field, 407 denlstring(h->h_value, FALSE, TRUE)); 408 } 409 } 410 411 /* 412 ** Clean up. 413 ** 414 ** Write a terminator record -- this is to prevent 415 ** scurrilous crackers from appending any data. 416 */ 417 418 fprintf(tfp, ".\n"); 419 420 if (fflush(tfp) < 0 || 421 (SuperSafe && fsync(fileno(tfp)) < 0) || 422 ferror(tfp)) 423 { 424 if (newid) 425 syserr("!552 Error writing control file %s", tf); 426 else 427 syserr("!452 Error writing control file %s", tf); 428 } 429 430 if (!newid) 431 { 432 /* rename (locked) tf to be (locked) qf */ 433 qf = queuename(e, 'q'); 434 if (rename(tf, qf) < 0) 435 syserr("cannot rename(%s, %s), uid=%d", 436 tf, qf, geteuid()); 437 438 /* close and unlock old (locked) qf */ 439 if (e->e_lockfp != NULL) 440 (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id); 441 e->e_lockfp = tfp; 442 } 443 else 444 qf = tf; 445 errno = 0; 446 e->e_flags |= EF_INQUEUE; 447 448 /* save log info */ 449 if (LogLevel > 79) 450 sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf); 451 452 if (tTd(40, 1)) 453 printf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 454 return; 455} 456 457void 458printctladdr(a, tfp) 459 register ADDRESS *a; 460 FILE *tfp; 461{ 462 char *uname; 463 register ADDRESS *q; 464 uid_t uid; 465 gid_t gid; 466 static ADDRESS *lastctladdr = NULL; 467 static uid_t lastuid; 468 469 /* initialization */ 470 if (a == NULL || a->q_alias == NULL || tfp == NULL) 471 { 472 if (lastctladdr != NULL && tfp != NULL) 473 fprintf(tfp, "C\n"); 474 lastctladdr = NULL; 475 lastuid = 0; 476 return; 477 } 478 479 /* find the active uid */ 480 q = getctladdr(a); 481 if (q == NULL) 482 { 483 uname = NULL; 484 uid = 0; 485 gid = 0; 486 } 487 else 488 { 489 uname = q->q_ruser != NULL ? q->q_ruser : q->q_user; 490 uid = q->q_uid; 491 gid = q->q_gid; 492 } 493 a = a->q_alias; 494 495 /* check to see if this is the same as last time */ 496 if (lastctladdr != NULL && uid == lastuid && 497 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 498 return; 499 lastuid = uid; 500 lastctladdr = a; 501 502 if (uid == 0 || uname == NULL || uname[0] == '\0') 503 fprintf(tfp, "C"); 504 else 505 fprintf(tfp, "C%s:%ld:%ld", 506 denlstring(uname, TRUE, FALSE), (long) uid, (long) gid); 507 fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE)); 508} 509/* 510** RUNQUEUE -- run the jobs in the queue. 511** 512** Gets the stuff out of the queue in some presumably logical 513** order and processes them. 514** 515** Parameters: 516** forkflag -- TRUE if the queue scanning should be done in 517** a child process. We double-fork so it is not our 518** child and we don't have to clean up after it. 519** verbose -- if TRUE, print out status information. 520** 521** Returns: 522** TRUE if the queue run successfully began. 523** 524** Side Effects: 525** runs things in the mail queue. 526*/ 527 528ENVELOPE QueueEnvelope; /* the queue run envelope */ 529extern int get_num_procs_online __P((void)); 530 531bool 532runqueue(forkflag, verbose) 533 bool forkflag; 534 bool verbose; 535{ 536 register ENVELOPE *e; 537 int njobs; 538 int sequenceno = 0; 539 time_t current_la_time; 540 extern ENVELOPE BlankEnvelope; 541 extern void clrdaemon __P((void)); 542 extern void runqueueevent __P((void)); 543 544 DoQueueRun = FALSE; 545 546 /* 547 ** If no work will ever be selected, don't even bother reading 548 ** the queue. 549 */ 550 551 CurrentLA = getla(); /* get load average */ 552 current_la_time = curtime(); 553 554 if (shouldqueue(WkRecipFact, current_la_time)) 555 { 556 char *msg = "Skipping queue run -- load average too high"; 557 558 if (verbose) 559 message("458 %s\n", msg); 560 if (LogLevel > 8) 561 sm_syslog(LOG_INFO, NOQID, 562 "runqueue: %s", 563 msg); 564 if (forkflag && QueueIntvl != 0) 565 (void) setevent(QueueIntvl, runqueueevent, 0); 566 return FALSE; 567 } 568 569 /* 570 ** See if we already have too many children. 571 */ 572 573 if (forkflag && QueueIntvl != 0 && 574 MaxChildren > 0 && CurChildren >= MaxChildren) 575 { 576 (void) setevent(QueueIntvl, runqueueevent, 0); 577 return FALSE; 578 } 579 580 /* 581 ** See if we want to go off and do other useful work. 582 */ 583 584 if (forkflag) 585 { 586 pid_t pid; 587 extern SIGFUNC_DECL intsig __P((int)); 588 extern SIGFUNC_DECL reapchild __P((int)); 589 590 blocksignal(SIGCHLD); 591 (void) setsignal(SIGCHLD, reapchild); 592 593 pid = dofork(); 594 if (pid == -1) 595 { 596 const char *msg = "Skipping queue run -- fork() failed"; 597 const char *err = errstring(errno); 598 599 if (verbose) 600 message("458 %s: %s\n", msg, err); 601 if (LogLevel > 8) 602 sm_syslog(LOG_INFO, NOQID, 603 "runqueue: %s: %s", 604 msg, err); 605 if (QueueIntvl != 0) 606 (void) setevent(QueueIntvl, runqueueevent, 0); 607 (void) releasesignal(SIGCHLD); 608 return FALSE; 609 } 610 if (pid != 0) 611 { 612 /* parent -- pick up intermediate zombie */ 613 (void) blocksignal(SIGALRM); 614 proc_list_add(pid); 615 (void) releasesignal(SIGALRM); 616 releasesignal(SIGCHLD); 617 if (QueueIntvl != 0) 618 (void) setevent(QueueIntvl, runqueueevent, 0); 619 return TRUE; 620 } 621 /* child -- double fork and clean up signals */ 622 proc_list_clear(); 623 releasesignal(SIGCHLD); 624 (void) setsignal(SIGCHLD, SIG_DFL); 625 (void) setsignal(SIGHUP, intsig); 626 } 627 628 setproctitle("running queue: %s", QueueDir); 629 630 if (LogLevel > 69) 631 sm_syslog(LOG_DEBUG, NOQID, 632 "runqueue %s, pid=%d, forkflag=%d", 633 QueueDir, getpid(), forkflag); 634 635 /* 636 ** Release any resources used by the daemon code. 637 */ 638 639# if DAEMON 640 clrdaemon(); 641# endif /* DAEMON */ 642 643 /* force it to run expensive jobs */ 644 NoConnect = FALSE; 645 646 /* drop privileges */ 647 if (geteuid() == (uid_t) 0) 648 (void) drop_privileges(FALSE); 649 650 /* 651 ** Create ourselves an envelope 652 */ 653 654 CurEnv = &QueueEnvelope; 655 e = newenvelope(&QueueEnvelope, CurEnv); 656 e->e_flags = BlankEnvelope.e_flags; 657 658 /* make sure we have disconnected from parent */ 659 if (forkflag) 660 { 661 disconnect(1, e); 662 QuickAbort = FALSE; 663 } 664 665 /* 666 ** Make sure the alias database is open. 667 */ 668 669 initmaps(FALSE, e); 670 671 /* 672 ** If we are running part of the queue, always ignore stored 673 ** host status. 674 */ 675 676 if (QueueLimitId != NULL || QueueLimitSender != NULL || 677 QueueLimitRecipient != NULL) 678 { 679 IgnoreHostStatus = TRUE; 680 MinQueueAge = 0; 681 } 682 683 /* 684 ** Start making passes through the queue. 685 ** First, read and sort the entire queue. 686 ** Then, process the work in that order. 687 ** But if you take too long, start over. 688 */ 689 690 /* order the existing work requests */ 691 njobs = orderq(FALSE); 692 693 /* process them once at a time */ 694 while (WorkQ != NULL) 695 { 696 WORK *w = WorkQ; 697 698 WorkQ = WorkQ->w_next; 699 e->e_to = NULL; 700 701 /* 702 ** Ignore jobs that are too expensive for the moment. 703 ** 704 ** Get new load average every 30 seconds. 705 */ 706 707 if (current_la_time < curtime() - 30) 708 { 709 CurrentLA = getla(); 710 current_la_time = curtime(); 711 } 712 if (shouldqueue(WkRecipFact, current_la_time)) 713 { 714 char *msg = "Aborting queue run: load average too high"; 715 716 if (Verbose) 717 message("%s", msg); 718 if (LogLevel > 8) 719 sm_syslog(LOG_INFO, NOQID, 720 "runqueue: %s", 721 msg); 722 break; 723 } 724 sequenceno++; 725 if (shouldqueue(w->w_pri, w->w_ctime)) 726 { 727 if (Verbose) 728 message(""); 729 if (QueueSortOrder == QS_BYPRIORITY) 730 { 731 if (Verbose) 732 message("Skipping %s (sequence %d of %d) and flushing rest of queue", 733 w->w_name + 2, 734 sequenceno, 735 njobs); 736 if (LogLevel > 8) 737 sm_syslog(LOG_INFO, NOQID, 738 "runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)", 739 w->w_name + 2, 740 w->w_pri, 741 CurrentLA, 742 sequenceno, 743 njobs); 744 break; 745 } 746 else if (Verbose) 747 message("Skipping %s (sequence %d of %d)", 748 w->w_name + 2, sequenceno, njobs); 749 } 750 else 751 { 752 pid_t pid; 753 extern pid_t dowork __P((char *, bool, bool, ENVELOPE *)); 754 755 if (Verbose) 756 { 757 message(""); 758 message("Running %s (sequence %d of %d)", 759 w->w_name + 2, sequenceno, njobs); 760 } 761 pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e); 762 errno = 0; 763 if (pid != 0) 764 (void) waitfor(pid); 765 } 766 free(w->w_name); 767 if (w->w_host) 768 free(w->w_host); 769 free((char *) w); 770 } 771 772 /* exit without the usual cleanup */ 773 e->e_id = NULL; 774 finis(); 775 /*NOTREACHED*/ 776 return TRUE; 777} 778 779 780/* 781** RUNQUEUEEVENT -- stub for use in setevent 782*/ 783 784void 785runqueueevent() 786{ 787 DoQueueRun = TRUE; 788} 789/* 790** ORDERQ -- order the work queue. 791** 792** Parameters: 793** doall -- if set, include everything in the queue (even 794** the jobs that cannot be run because the load 795** average is too high). Otherwise, exclude those 796** jobs. 797** 798** Returns: 799** The number of request in the queue (not necessarily 800** the number of requests in WorkQ however). 801** 802** Side Effects: 803** Sets WorkQ to the queue of available work, in order. 804*/ 805 806# define NEED_P 001 807# define NEED_T 002 808# define NEED_R 004 809# define NEED_S 010 810 811static WORK *WorkList = NULL; 812static int WorkListSize = 0; 813 814int 815orderq(doall) 816 bool doall; 817{ 818 register struct dirent *d; 819 register WORK *w; 820 register char *p; 821 DIR *f; 822 register int i; 823 int wn = -1; 824 int wc; 825 QUEUE_CHAR *check; 826 827 if (tTd(41, 1)) 828 { 829 printf("orderq:\n"); 830 831 check = QueueLimitId; 832 while (check != NULL) 833 { 834 printf("\tQueueLimitId = %s\n", 835 check->queue_match); 836 check = check->queue_next; 837 } 838 839 check = QueueLimitSender; 840 while (check != NULL) 841 { 842 printf("\tQueueLimitSender = %s\n", 843 check->queue_match); 844 check = check->queue_next; 845 } 846 847 check = QueueLimitRecipient; 848 while (check != NULL) 849 { 850 printf("\tQueueLimitRecipient = %s\n", 851 check->queue_match); 852 check = check->queue_next; 853 } 854 } 855 856 /* clear out old WorkQ */ 857 for (w = WorkQ; w != NULL; ) 858 { 859 register WORK *nw = w->w_next; 860 861 WorkQ = nw; 862 free(w->w_name); 863 if (w->w_host) 864 free(w->w_host); 865 free((char *) w); 866 w = nw; 867 } 868 869 /* open the queue directory */ 870 f = opendir("."); 871 if (f == NULL) 872 { 873 syserr("orderq: cannot open \"%s\" as \".\"", QueueDir); 874 return (0); 875 } 876 877 /* 878 ** Read the work directory. 879 */ 880 881 while ((d = readdir(f)) != NULL) 882 { 883 FILE *cf; 884 int qfver = 0; 885 char lbuf[MAXNAME + 1]; 886 extern bool strcontainedin __P((char *, char *)); 887 888 if (tTd(41, 50)) 889 printf("orderq: checking %s\n", d->d_name); 890 891 /* is this an interesting entry? */ 892 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 893 continue; 894 895 if (strlen(d->d_name) > MAXQFNAME) 896 continue; 897 898 check = QueueLimitId; 899 while (check != NULL) 900 { 901 if (strcontainedin(check->queue_match, d->d_name)) 902 break; 903 else 904 check = check->queue_next; 905 } 906 if (QueueLimitId != NULL && check == NULL) 907 continue; 908 909#ifdef PICKY_QF_NAME_CHECK 910 /* 911 ** Check queue name for plausibility. This handles 912 ** both old and new type ids. 913 */ 914 915 p = d->d_name + 2; 916 if (isupper(p[0]) && isupper(p[2])) 917 p += 3; 918 else if (isupper(p[1])) 919 p += 2; 920 else 921 p = d->d_name; 922 for (i = 0; isdigit(*p); p++) 923 i++; 924 if (i < 5 || *p != '\0') 925 { 926 if (Verbose) 927 printf("orderq: bogus qf name %s\n", d->d_name); 928 if (LogLevel > 0) 929 sm_syslog(LOG_ALERT, NOQID, 930 "orderq: bogus qf name %s", 931 d->d_name); 932 if (strlen(d->d_name) > (SIZE_T) MAXNAME) 933 d->d_name[MAXNAME] = '\0'; 934 strcpy(lbuf, d->d_name); 935 lbuf[0] = 'Q'; 936 (void) rename(d->d_name, lbuf); 937 continue; 938 } 939#endif 940 941 /* open control file (if not too many files) */ 942 if (++wn >= MaxQueueRun && MaxQueueRun > 0) 943 { 944 if (wn == MaxQueueRun && LogLevel > 0) 945 sm_syslog(LOG_ALERT, NOQID, 946 "WorkList for %s maxed out at %d", 947 QueueDir, MaxQueueRun); 948 continue; 949 } 950 if (wn >= WorkListSize) 951 { 952 extern void grow_wlist __P((void)); 953 954 grow_wlist(); 955 if (wn >= WorkListSize) 956 continue; 957 } 958 959 cf = fopen(d->d_name, "r"); 960 if (cf == NULL) 961 { 962 /* this may be some random person sending hir msgs */ 963 /* syserr("orderq: cannot open %s", cbuf); */ 964 if (tTd(41, 2)) 965 printf("orderq: cannot open %s: %s\n", 966 d->d_name, errstring(errno)); 967 errno = 0; 968 wn--; 969 continue; 970 } 971 w = &WorkList[wn]; 972 w->w_name = newstr(d->d_name); 973 w->w_host = NULL; 974 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 975 w->w_tooyoung = FALSE; 976 977 /* make sure jobs in creation don't clog queue */ 978 w->w_pri = 0x7fffffff; 979 w->w_ctime = 0; 980 981 /* extract useful information */ 982 i = NEED_P | NEED_T; 983 if (QueueLimitSender != NULL) 984 i |= NEED_S; 985 if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL) 986 i |= NEED_R; 987 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 988 { 989 int c; 990 time_t age; 991 extern bool strcontainedin __P((char *, char *)); 992 993 p = strchr(lbuf, '\n'); 994 if (p != NULL) 995 *p = '\0'; 996 else 997 { 998 /* flush rest of overly long line */ 999 while ((c = getc(cf)) != EOF && c != '\n') 1000 continue; 1001 } 1002 1003 switch (lbuf[0]) 1004 { 1005 case 'V': 1006 qfver = atoi(&lbuf[1]); 1007 break; 1008 1009 case 'P': 1010 w->w_pri = atol(&lbuf[1]); 1011 i &= ~NEED_P; 1012 break; 1013 1014 case 'T': 1015 w->w_ctime = atol(&lbuf[1]); 1016 i &= ~NEED_T; 1017 break; 1018 1019 case 'R': 1020 if (w->w_host == NULL && 1021 (p = strrchr(&lbuf[1], '@')) != NULL) 1022 w->w_host = newstr(&p[1]); 1023 if (QueueLimitRecipient == NULL) 1024 { 1025 i &= ~NEED_R; 1026 break; 1027 } 1028 if (qfver > 0) 1029 { 1030 p = strchr(&lbuf[1], ':'); 1031 if (p == NULL) 1032 p = &lbuf[1]; 1033 } 1034 else 1035 p = &lbuf[1]; 1036 check = QueueLimitRecipient; 1037 while (check != NULL) 1038 { 1039 if (strcontainedin(check->queue_match, 1040 p)) 1041 break; 1042 else 1043 check = check->queue_next; 1044 } 1045 if (check != NULL) 1046 i &= ~NEED_R; 1047 break; 1048 1049 case 'S': 1050 check = QueueLimitSender; 1051 while (check != NULL) 1052 { 1053 if (strcontainedin(check->queue_match, 1054 &lbuf[1])) 1055 break; 1056 else 1057 check = check->queue_next; 1058 } 1059 if (check != NULL) 1060 i &= ~NEED_S; 1061 break; 1062 1063 case 'K': 1064 age = curtime() - (time_t) atol(&lbuf[1]); 1065 if (age >= 0 && MinQueueAge > 0 && 1066 age < MinQueueAge) 1067 w->w_tooyoung = TRUE; 1068 break; 1069 1070 case 'N': 1071 if (atol(&lbuf[1]) == 0) 1072 w->w_tooyoung = FALSE; 1073 break; 1074 } 1075 } 1076 (void) fclose(cf); 1077 1078 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 1079 bitset(NEED_R|NEED_S, i)) 1080 { 1081 /* don't even bother sorting this job in */ 1082 if (tTd(41, 49)) 1083 printf("skipping %s (%x)\n", w->w_name, i); 1084 free(w->w_name); 1085 if (w->w_host) 1086 free(w->w_host); 1087 wn--; 1088 } 1089 } 1090 (void) closedir(f); 1091 wn++; 1092 1093 wc = min(wn, WorkListSize); 1094 if (wc > MaxQueueRun && MaxQueueRun > 0) 1095 wc = MaxQueueRun; 1096 1097 if (QueueSortOrder == QS_BYHOST) 1098 { 1099 extern int workcmpf1(); 1100 extern int workcmpf2(); 1101 1102 /* 1103 ** Sort the work directory for the first time, 1104 ** based on host name, lock status, and priority. 1105 */ 1106 1107 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1); 1108 1109 /* 1110 ** If one message to host is locked, "lock" all messages 1111 ** to that host. 1112 */ 1113 1114 i = 0; 1115 while (i < wc) 1116 { 1117 if (!WorkList[i].w_lock) 1118 { 1119 i++; 1120 continue; 1121 } 1122 w = &WorkList[i]; 1123 while (++i < wc) 1124 { 1125 extern int sm_strcasecmp __P((char *, char *)); 1126 1127 if (WorkList[i].w_host == NULL && 1128 w->w_host == NULL) 1129 WorkList[i].w_lock = TRUE; 1130 else if (WorkList[i].w_host != NULL && 1131 w->w_host != NULL && 1132 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0) 1133 WorkList[i].w_lock = TRUE; 1134 else 1135 break; 1136 } 1137 } 1138 1139 /* 1140 ** Sort the work directory for the second time, 1141 ** based on lock status, host name, and priority. 1142 */ 1143 1144 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2); 1145 } 1146 else if (QueueSortOrder == QS_BYTIME) 1147 { 1148 extern int workcmpf3(); 1149 1150 /* 1151 ** Simple sort based on submission time only. 1152 */ 1153 1154 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); 1155 } 1156 else 1157 { 1158 extern int workcmpf0(); 1159 1160 /* 1161 ** Simple sort based on queue priority only. 1162 */ 1163 1164 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0); 1165 } 1166 1167 /* 1168 ** Convert the work list into canonical form. 1169 ** Should be turning it into a list of envelopes here perhaps. 1170 */ 1171 1172 WorkQ = NULL; 1173 for (i = wc; --i >= 0; ) 1174 { 1175 w = (WORK *) xalloc(sizeof *w); 1176 w->w_name = WorkList[i].w_name; 1177 w->w_host = WorkList[i].w_host; 1178 w->w_lock = WorkList[i].w_lock; 1179 w->w_tooyoung = WorkList[i].w_tooyoung; 1180 w->w_pri = WorkList[i].w_pri; 1181 w->w_ctime = WorkList[i].w_ctime; 1182 w->w_next = WorkQ; 1183 WorkQ = w; 1184 } 1185 if (WorkList != NULL) 1186 free(WorkList); 1187 WorkList = NULL; 1188 WorkListSize = 0; 1189 1190 if (tTd(40, 1)) 1191 { 1192 for (w = WorkQ; w != NULL; w = w->w_next) 1193 printf("%32s: pri=%ld\n", w->w_name, w->w_pri); 1194 } 1195 1196 return (wn); 1197} 1198/* 1199** GROW_WLIST -- make the work list larger 1200** 1201** Parameters: 1202** none. 1203** 1204** Returns: 1205** none. 1206** 1207** Side Effects: 1208** Adds another QUEUESEGSIZE entries to WorkList if possible. 1209** It can fail if there isn't enough memory, so WorkListSize 1210** should be checked again upon return. 1211*/ 1212 1213void 1214grow_wlist() 1215{ 1216 if (tTd(41, 1)) 1217 printf("grow_wlist: WorkListSize=%d\n", WorkListSize); 1218 if (WorkList == NULL) 1219 { 1220 WorkList = (WORK *) xalloc(sizeof(WORK) * (QUEUESEGSIZE + 1)); 1221 WorkListSize = QUEUESEGSIZE; 1222 } 1223 else 1224 { 1225 int newsize = WorkListSize + QUEUESEGSIZE; 1226 WORK *newlist = (WORK *) realloc((char *)WorkList, 1227 (unsigned)sizeof(WORK) * (newsize + 1)); 1228 1229 if (newlist != NULL) 1230 { 1231 WorkListSize = newsize; 1232 WorkList = newlist; 1233 if (LogLevel > 1) 1234 { 1235 sm_syslog(LOG_NOTICE, NOQID, 1236 "grew WorkList for %s to %d", 1237 QueueDir, WorkListSize); 1238 } 1239 } 1240 else if (LogLevel > 0) 1241 { 1242 sm_syslog(LOG_ALERT, NOQID, 1243 "FAILED to grow WorkList for %s to %d", 1244 QueueDir, newsize); 1245 } 1246 } 1247 if (tTd(41, 1)) 1248 printf("grow_wlist: WorkListSize now %d\n", WorkListSize); 1249} 1250/* 1251** WORKCMPF0 -- simple priority-only compare function. 1252** 1253** Parameters: 1254** a -- the first argument. 1255** b -- the second argument. 1256** 1257** Returns: 1258** -1 if a < b 1259** 0 if a == b 1260** +1 if a > b 1261** 1262** Side Effects: 1263** none. 1264*/ 1265 1266int 1267workcmpf0(a, b) 1268 register WORK *a; 1269 register WORK *b; 1270{ 1271 long pa = a->w_pri; 1272 long pb = b->w_pri; 1273 1274 if (pa == pb) 1275 return 0; 1276 else if (pa > pb) 1277 return 1; 1278 else 1279 return -1; 1280} 1281/* 1282** WORKCMPF1 -- first compare function for ordering work based on host name. 1283** 1284** Sorts on host name, lock status, and priority in that order. 1285** 1286** Parameters: 1287** a -- the first argument. 1288** b -- the second argument. 1289** 1290** Returns: 1291** <0 if a < b 1292** 0 if a == b 1293** >0 if a > b 1294** 1295** Side Effects: 1296** none. 1297*/ 1298 1299int 1300workcmpf1(a, b) 1301 register WORK *a; 1302 register WORK *b; 1303{ 1304 int i; 1305 extern int sm_strcasecmp __P((char *, char *)); 1306 1307 /* host name */ 1308 if (a->w_host != NULL && b->w_host == NULL) 1309 return 1; 1310 else if (a->w_host == NULL && b->w_host != NULL) 1311 return -1; 1312 if (a->w_host != NULL && b->w_host != NULL && 1313 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1314 return i; 1315 1316 /* lock status */ 1317 if (a->w_lock != b->w_lock) 1318 return b->w_lock - a->w_lock; 1319 1320 /* job priority */ 1321 return a->w_pri - b->w_pri; 1322} 1323/* 1324** WORKCMPF2 -- second compare function for ordering work based on host name. 1325** 1326** Sorts on lock status, host name, and priority in that order. 1327** 1328** Parameters: 1329** a -- the first argument. 1330** b -- the second argument. 1331** 1332** Returns: 1333** <0 if a < b 1334** 0 if a == b 1335** >0 if a > b 1336** 1337** Side Effects: 1338** none. 1339*/ 1340 1341int 1342workcmpf2(a, b) 1343 register WORK *a; 1344 register WORK *b; 1345{ 1346 int i; 1347 extern int sm_strcasecmp __P((char *, char *)); 1348 1349 /* lock status */ 1350 if (a->w_lock != b->w_lock) 1351 return a->w_lock - b->w_lock; 1352 1353 /* host name */ 1354 if (a->w_host != NULL && b->w_host == NULL) 1355 return 1; 1356 else if (a->w_host == NULL && b->w_host != NULL) 1357 return -1; 1358 if (a->w_host != NULL && b->w_host != NULL && 1359 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1360 return i; 1361 1362 /* job priority */ 1363 return a->w_pri - b->w_pri; 1364} 1365/* 1366** WORKCMPF3 -- simple submission-time-only compare function. 1367** 1368** Parameters: 1369** a -- the first argument. 1370** b -- the second argument. 1371** 1372** Returns: 1373** -1 if a < b 1374** 0 if a == b 1375** +1 if a > b 1376** 1377** Side Effects: 1378** none. 1379*/ 1380 1381int 1382workcmpf3(a, b) 1383 register WORK *a; 1384 register WORK *b; 1385{ 1386 if (a->w_ctime > b->w_ctime) 1387 return 1; 1388 else if (a->w_ctime < b->w_ctime) 1389 return -1; 1390 else 1391 return 0; 1392} 1393/* 1394** DOWORK -- do a work request. 1395** 1396** Parameters: 1397** id -- the ID of the job to run. 1398** forkflag -- if set, run this in background. 1399** requeueflag -- if set, reinstantiate the queue quickly. 1400** This is used when expanding aliases in the queue. 1401** If forkflag is also set, it doesn't wait for the 1402** child. 1403** e - the envelope in which to run it. 1404** 1405** Returns: 1406** process id of process that is running the queue job. 1407** 1408** Side Effects: 1409** The work request is satisfied if possible. 1410*/ 1411 1412pid_t 1413dowork(id, forkflag, requeueflag, e) 1414 char *id; 1415 bool forkflag; 1416 bool requeueflag; 1417 register ENVELOPE *e; 1418{ 1419 register pid_t pid; 1420 extern bool readqf __P((ENVELOPE *)); 1421 1422 if (tTd(40, 1)) 1423 printf("dowork(%s)\n", id); 1424 1425 /* 1426 ** Fork for work. 1427 */ 1428 1429 if (forkflag) 1430 { 1431 pid = fork(); 1432 if (pid < 0) 1433 { 1434 syserr("dowork: cannot fork"); 1435 return 0; 1436 } 1437 else if (pid > 0) 1438 { 1439 /* parent -- clean out connection cache */ 1440 mci_flush(FALSE, NULL); 1441 } 1442 else 1443 { 1444 /* child -- error messages to the transcript */ 1445 QuickAbort = OnlyOneError = FALSE; 1446 } 1447 } 1448 else 1449 { 1450 pid = 0; 1451 } 1452 1453 if (pid == 0) 1454 { 1455 /* 1456 ** CHILD 1457 ** Lock the control file to avoid duplicate deliveries. 1458 ** Then run the file as though we had just read it. 1459 ** We save an idea of the temporary name so we 1460 ** can recover on interrupt. 1461 */ 1462 1463 /* set basic modes, etc. */ 1464 (void) alarm(0); 1465 clearenvelope(e, FALSE); 1466 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1467 e->e_sendmode = SM_DELIVER; 1468 e->e_errormode = EM_MAIL; 1469 e->e_id = id; 1470 GrabTo = UseErrorsTo = FALSE; 1471 ExitStat = EX_OK; 1472 if (forkflag) 1473 { 1474 disconnect(1, e); 1475 OpMode = MD_DELIVER; 1476 } 1477 setproctitle("%s: from queue", id); 1478 if (LogLevel > 76) 1479 sm_syslog(LOG_DEBUG, e->e_id, 1480 "dowork, pid=%d", 1481 getpid()); 1482 1483 /* don't use the headers from sendmail.cf... */ 1484 e->e_header = NULL; 1485 1486 /* read the queue control file -- return if locked */ 1487 if (!readqf(e)) 1488 { 1489 if (tTd(40, 4) && e->e_id != NULL) 1490 printf("readqf(%s) failed\n", e->e_id); 1491 e->e_id = NULL; 1492 if (forkflag) 1493 exit(EX_OK); 1494 else 1495 return 0; 1496 } 1497 1498 e->e_flags |= EF_INQUEUE; 1499 eatheader(e, requeueflag); 1500 1501 if (requeueflag) 1502 queueup(e, FALSE); 1503 1504 /* do the delivery */ 1505 sendall(e, SM_DELIVER); 1506 1507 /* finish up and exit */ 1508 if (forkflag) 1509 finis(); 1510 else 1511 dropenvelope(e, TRUE); 1512 } 1513 e->e_id = NULL; 1514 return pid; 1515} 1516/* 1517** READQF -- read queue file and set up environment. 1518** 1519** Parameters: 1520** e -- the envelope of the job to run. 1521** 1522** Returns: 1523** TRUE if it successfully read the queue file. 1524** FALSE otherwise. 1525** 1526** Side Effects: 1527** The queue file is returned locked. 1528*/ 1529 1530bool 1531readqf(e) 1532 register ENVELOPE *e; 1533{ 1534 register FILE *qfp; 1535 ADDRESS *ctladdr; 1536 struct stat st; 1537 char *bp; 1538 int qfver = 0; 1539 long hdrsize = 0; 1540 register char *p; 1541 char *orcpt = NULL; 1542 bool nomore = FALSE; 1543 char qf[MAXQFNAME]; 1544 char buf[MAXLINE]; 1545 extern ADDRESS *setctluser __P((char *, int)); 1546 1547 /* 1548 ** Read and process the file. 1549 */ 1550 1551 strcpy(qf, queuename(e, 'q')); 1552 qfp = fopen(qf, "r+"); 1553 if (qfp == NULL) 1554 { 1555 if (tTd(40, 8)) 1556 printf("readqf(%s): fopen failure (%s)\n", 1557 qf, errstring(errno)); 1558 if (errno != ENOENT) 1559 syserr("readqf: no control file %s", qf); 1560 return FALSE; 1561 } 1562 1563 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1564 { 1565 /* being processed by another queuer */ 1566 if (Verbose || tTd(40, 8)) 1567 printf("%s: locked\n", e->e_id); 1568 if (LogLevel > 19) 1569 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 1570 (void) fclose(qfp); 1571 return FALSE; 1572 } 1573 1574 /* 1575 ** Check the queue file for plausibility to avoid attacks. 1576 */ 1577 1578 if (fstat(fileno(qfp), &st) < 0) 1579 { 1580 /* must have been being processed by someone else */ 1581 if (tTd(40, 8)) 1582 printf("readqf(%s): fstat failure (%s)\n", 1583 qf, errstring(errno)); 1584 fclose(qfp); 1585 return FALSE; 1586 } 1587 1588 if ((st.st_uid != geteuid() && geteuid() != RealUid) || 1589 bitset(S_IWOTH|S_IWGRP, st.st_mode)) 1590 { 1591 if (LogLevel > 0) 1592 { 1593 sm_syslog(LOG_ALERT, e->e_id, 1594 "bogus queue file, uid=%d, mode=%o", 1595 st.st_uid, st.st_mode); 1596 } 1597 if (tTd(40, 8)) 1598 printf("readqf(%s): bogus file\n", qf); 1599 loseqfile(e, "bogus file uid in mqueue"); 1600 fclose(qfp); 1601 return FALSE; 1602 } 1603 1604 if (st.st_size == 0) 1605 { 1606 /* must be a bogus file -- if also old, just remove it */ 1607 if (st.st_ctime + 10 * 60 < curtime()) 1608 { 1609 qf[0] = 'd'; 1610 (void) unlink(qf); 1611 qf[0] = 'q'; 1612 (void) unlink(qf); 1613 } 1614 fclose(qfp); 1615 return FALSE; 1616 } 1617 1618 if (st.st_nlink == 0) 1619 { 1620 /* 1621 ** Race condition -- we got a file just as it was being 1622 ** unlinked. Just assume it is zero length. 1623 */ 1624 1625 fclose(qfp); 1626 return FALSE; 1627 } 1628 1629 /* good file -- save this lock */ 1630 e->e_lockfp = qfp; 1631 1632 /* do basic system initialization */ 1633 initsys(e); 1634 define('i', e->e_id, e); 1635 1636 LineNumber = 0; 1637 e->e_flags |= EF_GLOBALERRS; 1638 OpMode = MD_DELIVER; 1639 ctladdr = NULL; 1640 e->e_dfino = -1; 1641 e->e_msgsize = -1; 1642 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1643 { 1644 register char *p; 1645 u_long qflags; 1646 ADDRESS *q; 1647 int mid; 1648 auto char *ep; 1649 1650 if (tTd(40, 4)) 1651 printf("+++++ %s\n", bp); 1652 if (nomore) 1653 { 1654 /* hack attack */ 1655 syserr("SECURITY ALERT: extra data in qf: %s", bp); 1656 fclose(qfp); 1657 loseqfile(e, "bogus queue line"); 1658 return FALSE; 1659 } 1660 switch (bp[0]) 1661 { 1662 case 'V': /* queue file version number */ 1663 qfver = atoi(&bp[1]); 1664 if (qfver <= QF_VERSION) 1665 break; 1666 syserr("Version number in qf (%d) greater than max (%d)", 1667 qfver, QF_VERSION); 1668 fclose(qfp); 1669 loseqfile(e, "unsupported qf file version"); 1670 return FALSE; 1671 1672 case 'C': /* specify controlling user */ 1673 ctladdr = setctluser(&bp[1], qfver); 1674 break; 1675 1676 case 'Q': /* original recipient */ 1677 orcpt = newstr(&bp[1]); 1678 break; 1679 1680 case 'R': /* specify recipient */ 1681 p = bp; 1682 qflags = 0; 1683 if (qfver >= 1) 1684 { 1685 /* get flag bits */ 1686 while (*++p != '\0' && *p != ':') 1687 { 1688 switch (*p) 1689 { 1690 case 'N': 1691 qflags |= QHASNOTIFY; 1692 break; 1693 1694 case 'S': 1695 qflags |= QPINGONSUCCESS; 1696 break; 1697 1698 case 'F': 1699 qflags |= QPINGONFAILURE; 1700 break; 1701 1702 case 'D': 1703 qflags |= QPINGONDELAY; 1704 break; 1705 1706 case 'P': 1707 qflags |= QPRIMARY; 1708 break; 1709 } 1710 } 1711 } 1712 else 1713 qflags |= QPRIMARY; 1714 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 1715 if (q != NULL) 1716 { 1717 q->q_alias = ctladdr; 1718 if (qfver >= 1) 1719 q->q_flags &= ~Q_PINGFLAGS; 1720 q->q_flags |= qflags; 1721 q->q_orcpt = orcpt; 1722 (void) recipient(q, &e->e_sendqueue, 0, e); 1723 } 1724 orcpt = NULL; 1725 break; 1726 1727 case 'E': /* specify error recipient */ 1728 /* no longer used */ 1729 break; 1730 1731 case 'H': /* header */ 1732 (void) chompheader(&bp[1], FALSE, NULL, e); 1733 hdrsize += strlen(&bp[1]); 1734 break; 1735 1736 case 'L': /* Solaris Content-Length: */ 1737 case 'M': /* message */ 1738 /* ignore this; we want a new message next time */ 1739 break; 1740 1741 case 'S': /* sender */ 1742 setsender(newstr(&bp[1]), e, NULL, '\0', TRUE); 1743 break; 1744 1745 case 'B': /* body type */ 1746 e->e_bodytype = newstr(&bp[1]); 1747 break; 1748 1749#if _FFR_SAVE_CHARSET 1750 case 'X': /* character set */ 1751 e->e_charset = newstr(&bp[1]); 1752 break; 1753#endif 1754 1755 case 'D': /* data file name */ 1756 /* obsolete -- ignore */ 1757 break; 1758 1759 case 'T': /* init time */ 1760 e->e_ctime = atol(&bp[1]); 1761 break; 1762 1763 case 'I': /* data file's inode number */ 1764 /* regenerated below */ 1765 break; 1766 1767 case 'K': /* time of last deliver attempt */ 1768 e->e_dtime = atol(&buf[1]); 1769 break; 1770 1771 case 'N': /* number of delivery attempts */ 1772 e->e_ntries = atoi(&buf[1]); 1773 1774 /* if this has been tried recently, let it be */ 1775 if (e->e_ntries > 0 && 1776 MinQueueAge > 0 && e->e_dtime <= curtime() && 1777 curtime() < e->e_dtime + MinQueueAge) 1778 { 1779 char *howlong = pintvl(curtime() - e->e_dtime, TRUE); 1780 extern void unlockqueue __P((ENVELOPE *)); 1781 1782 if (Verbose || tTd(40, 8)) 1783 printf("%s: too young (%s)\n", 1784 e->e_id, howlong); 1785 if (LogLevel > 19) 1786 sm_syslog(LOG_DEBUG, e->e_id, 1787 "too young (%s)", 1788 howlong); 1789 e->e_id = NULL; 1790 unlockqueue(e); 1791 return FALSE; 1792 } 1793 break; 1794 1795 case 'P': /* message priority */ 1796 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 1797 break; 1798 1799 case 'F': /* flag bits */ 1800 if (strncmp(bp, "From ", 5) == 0) 1801 { 1802 /* we are being spoofed! */ 1803 syserr("SECURITY ALERT: bogus qf line %s", bp); 1804 fclose(qfp); 1805 loseqfile(e, "bogus queue line"); 1806 return FALSE; 1807 } 1808 for (p = &bp[1]; *p != '\0'; p++) 1809 { 1810 switch (*p) 1811 { 1812 case 'w': /* warning sent */ 1813 e->e_flags |= EF_WARNING; 1814 break; 1815 1816 case 'r': /* response */ 1817 e->e_flags |= EF_RESPONSE; 1818 break; 1819 1820 case '8': /* has 8 bit data */ 1821 e->e_flags |= EF_HAS8BIT; 1822 break; 1823 1824 case 'b': /* delete Bcc: header */ 1825 e->e_flags |= EF_DELETE_BCC; 1826 break; 1827 1828 case 'd': /* envelope has DSN RET= */ 1829 e->e_flags |= EF_RET_PARAM; 1830 break; 1831 1832 case 'n': /* don't return body */ 1833 e->e_flags |= EF_NO_BODY_RETN; 1834 break; 1835 } 1836 } 1837 break; 1838 1839 case 'Z': /* original envelope id from ESMTP */ 1840 e->e_envid = newstr(&bp[1]); 1841 break; 1842 1843 case '$': /* define macro */ 1844 mid = macid(&bp[1], &ep); 1845 define(mid, newstr(ep), e); 1846 break; 1847 1848 case '.': /* terminate file */ 1849 nomore = TRUE; 1850 break; 1851 1852 default: 1853 syserr("readqf: %s: line %d: bad line \"%s\"", 1854 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 1855 fclose(qfp); 1856 loseqfile(e, "unrecognized line"); 1857 return FALSE; 1858 } 1859 1860 if (bp != buf) 1861 free(bp); 1862 } 1863 1864 /* 1865 ** If we haven't read any lines, this queue file is empty. 1866 ** Arrange to remove it without referencing any null pointers. 1867 */ 1868 1869 if (LineNumber == 0) 1870 { 1871 errno = 0; 1872 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 1873 return TRUE; 1874 } 1875 1876 /* 1877 ** Arrange to read the data file. 1878 */ 1879 1880 p = queuename(e, 'd'); 1881 e->e_dfp = fopen(p, "r"); 1882 if (e->e_dfp == NULL) 1883 { 1884 syserr("readqf: cannot open %s", p); 1885 } 1886 else 1887 { 1888 e->e_flags |= EF_HAS_DF; 1889 if (fstat(fileno(e->e_dfp), &st) >= 0) 1890 { 1891 e->e_msgsize = st.st_size + hdrsize; 1892 e->e_dfdev = st.st_dev; 1893 e->e_dfino = st.st_ino; 1894 } 1895 } 1896 1897 return TRUE; 1898} 1899/* 1900** PRINTQUEUE -- print out a representation of the mail queue 1901** 1902** Parameters: 1903** none. 1904** 1905** Returns: 1906** none. 1907** 1908** Side Effects: 1909** Prints a listing of the mail queue on the standard output. 1910*/ 1911 1912void 1913printqueue() 1914{ 1915 register WORK *w; 1916 FILE *f; 1917 int nrequests; 1918 char buf[MAXLINE]; 1919 1920 /* 1921 ** Check for permission to print the queue 1922 */ 1923 1924 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 1925 { 1926 struct stat st; 1927# ifdef NGROUPS_MAX 1928 int n; 1929 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 1930# endif 1931 1932 if (stat(QueueDir, &st) < 0) 1933 { 1934 syserr("Cannot stat %s", QueueDir); 1935 return; 1936 } 1937# ifdef NGROUPS_MAX 1938 n = NGROUPS_MAX; 1939 while (--n >= 0) 1940 { 1941 if (InitialGidSet[n] == st.st_gid) 1942 break; 1943 } 1944 if (n < 0 && RealGid != st.st_gid) 1945# else 1946 if (RealGid != st.st_gid) 1947# endif 1948 { 1949 usrerr("510 You are not permitted to see the queue"); 1950 setstat(EX_NOPERM); 1951 return; 1952 } 1953 } 1954 1955 /* 1956 ** Read and order the queue. 1957 */ 1958 1959 nrequests = orderq(TRUE); 1960 1961 /* 1962 ** Print the work list that we have read. 1963 */ 1964 1965 /* first see if there is anything */ 1966 if (nrequests <= 0) 1967 { 1968 printf("Mail queue is empty\n"); 1969 return; 1970 } 1971 1972 CurrentLA = getla(); /* get load average */ 1973 1974 printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s"); 1975 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 1976 printf(", only %d printed", MaxQueueRun); 1977 if (Verbose) 1978 printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n"); 1979 else 1980 printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 1981 for (w = WorkQ; w != NULL; w = w->w_next) 1982 { 1983 struct stat st; 1984 auto time_t submittime = 0; 1985 long dfsize; 1986 int flags = 0; 1987 int qfver; 1988 char statmsg[MAXLINE]; 1989 char bodytype[MAXNAME + 1]; 1990 1991 printf("%8s", w->w_name + 2); 1992 f = fopen(w->w_name, "r"); 1993 if (f == NULL) 1994 { 1995 printf(" (job completed)\n"); 1996 errno = 0; 1997 continue; 1998 } 1999 w->w_name[0] = 'd'; 2000 if (stat(w->w_name, &st) >= 0) 2001 dfsize = st.st_size; 2002 else 2003 dfsize = -1; 2004 if (w->w_lock) 2005 printf("*"); 2006 else if (w->w_tooyoung) 2007 printf("-"); 2008 else if (shouldqueue(w->w_pri, w->w_ctime)) 2009 printf("X"); 2010 else 2011 printf(" "); 2012 errno = 0; 2013 2014 statmsg[0] = bodytype[0] = '\0'; 2015 qfver = 0; 2016 while (fgets(buf, sizeof buf, f) != NULL) 2017 { 2018 register int i; 2019 register char *p; 2020 2021 fixcrlf(buf, TRUE); 2022 switch (buf[0]) 2023 { 2024 case 'V': /* queue file version */ 2025 qfver = atoi(&buf[1]); 2026 break; 2027 2028 case 'M': /* error message */ 2029 if ((i = strlen(&buf[1])) >= sizeof statmsg) 2030 i = sizeof statmsg - 1; 2031 bcopy(&buf[1], statmsg, i); 2032 statmsg[i] = '\0'; 2033 break; 2034 2035 case 'B': /* body type */ 2036 if ((i = strlen(&buf[1])) >= sizeof bodytype) 2037 i = sizeof bodytype - 1; 2038 bcopy(&buf[1], bodytype, i); 2039 bodytype[i] = '\0'; 2040 break; 2041 2042 case 'S': /* sender name */ 2043 if (Verbose) 2044 printf("%8ld %10ld%c%.12s %.78s", 2045 dfsize, 2046 w->w_pri, 2047 bitset(EF_WARNING, flags) ? '+' : ' ', 2048 ctime(&submittime) + 4, 2049 &buf[1]); 2050 else 2051 printf("%8ld %.16s %.45s", dfsize, 2052 ctime(&submittime), &buf[1]); 2053 if (statmsg[0] != '\0' || bodytype[0] != '\0') 2054 { 2055 printf("\n %10.10s", bodytype); 2056 if (statmsg[0] != '\0') 2057 printf(" (%.*s)", 2058 Verbose ? 100 : 60, 2059 statmsg); 2060 } 2061 break; 2062 2063 case 'C': /* controlling user */ 2064 if (Verbose) 2065 printf("\n\t\t\t\t (---%.74s---)", 2066 &buf[1]); 2067 break; 2068 2069 case 'R': /* recipient name */ 2070 p = &buf[1]; 2071 if (qfver >= 1) 2072 { 2073 p = strchr(p, ':'); 2074 if (p == NULL) 2075 break; 2076 p++; 2077 } 2078 if (Verbose) 2079 printf("\n\t\t\t\t\t %.78s", p); 2080 else 2081 printf("\n\t\t\t\t %.45s", p); 2082 break; 2083 2084 case 'T': /* creation time */ 2085 submittime = atol(&buf[1]); 2086 break; 2087 2088 case 'F': /* flag bits */ 2089 for (p = &buf[1]; *p != '\0'; p++) 2090 { 2091 switch (*p) 2092 { 2093 case 'w': 2094 flags |= EF_WARNING; 2095 break; 2096 } 2097 } 2098 } 2099 } 2100 if (submittime == (time_t) 0) 2101 printf(" (no control file)"); 2102 printf("\n"); 2103 (void) fclose(f); 2104 } 2105} 2106 2107# endif /* QUEUE */ 2108/* 2109** QUEUENAME -- build a file name in the queue directory for this envelope. 2110** 2111** Assigns an id code if one does not already exist. 2112** This code is very careful to avoid trashing existing files 2113** under any circumstances. 2114** 2115** Parameters: 2116** e -- envelope to build it in/from. 2117** type -- the file type, used as the first character 2118** of the file name. 2119** 2120** Returns: 2121** a pointer to the new file name (in a static buffer). 2122** 2123** Side Effects: 2124** If no id code is already assigned, queuename will 2125** assign an id code, create a qf file, and leave a 2126** locked, open-for-write file pointer in the envelope. 2127*/ 2128 2129#ifndef ENOLCK 2130# define ENOLCK -1 2131#endif 2132#ifndef ENOSPC 2133# define ENOSPC -1 2134#endif 2135 2136char * 2137queuename(e, type) 2138 register ENVELOPE *e; 2139 int type; 2140{ 2141 static pid_t pid = -1; 2142 static char c0; 2143 static char c1; 2144 static char c2; 2145 time_t now; 2146 struct tm *tm; 2147 static char buf[MAXNAME + 1]; 2148 2149 if (e->e_id == NULL) 2150 { 2151 char qf[MAXQFNAME]; 2152 2153 /* find a unique id */ 2154 if (pid != getpid()) 2155 { 2156 /* new process -- start back at "AA" */ 2157 pid = getpid(); 2158 now = curtime(); 2159 tm = localtime(&now); 2160 c0 = 'A' + tm->tm_hour; 2161 c1 = 'A'; 2162 c2 = 'A' - 1; 2163 } 2164 (void) snprintf(qf, sizeof qf, "qf%cAA%05d", c0, pid); 2165 2166 while (c1 < '~' || c2 < 'Z') 2167 { 2168 int i; 2169 int attempts = 0; 2170 2171 if (c2 >= 'Z') 2172 { 2173 c1++; 2174 c2 = 'A' - 1; 2175 } 2176 qf[3] = c1; 2177 qf[4] = ++c2; 2178 if (tTd(7, 20)) 2179 printf("queuename: trying \"%s\"\n", qf); 2180 2181 i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode); 2182 if (i < 0) 2183 { 2184 if (errno == EEXIST) 2185 continue; 2186 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 2187 qf, QueueDir, geteuid()); 2188 exit(EX_UNAVAILABLE); 2189 } 2190 do 2191 { 2192 if (attempts > 0) 2193 sleep(attempts); 2194 e->e_lockfp = 0; 2195 if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB)) 2196 { 2197 e->e_lockfp = fdopen(i, "w"); 2198 break; 2199 } 2200 } while ((errno == ENOLCK || errno == ENOSPC) && 2201 attempts++ < 4); 2202 2203 /* Successful lock */ 2204 if (e->e_lockfp != 0) 2205 break; 2206 2207#if !HASFLOCK 2208 if (errno != EAGAIN && errno != EACCES) 2209#else 2210 if (errno != EWOULDBLOCK) 2211#endif 2212 { 2213 syserr("queuename: Cannot lock \"%s\" in \"%s\" (euid=%d)", 2214 qf, QueueDir, geteuid()); 2215 exit(EX_OSERR); 2216 } 2217 2218 /* a reader got the file; abandon it and try again */ 2219 (void) close(i); 2220 } 2221 if (c1 >= '~' && c2 >= 'Z') 2222 { 2223 syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)", 2224 qf, QueueDir, geteuid()); 2225 exit(EX_OSERR); 2226 } 2227 e->e_id = newstr(&qf[2]); 2228 define('i', e->e_id, e); 2229 if (tTd(7, 1)) 2230 printf("queuename: assigned id %s, env=%lx\n", 2231 e->e_id, (u_long) e); 2232 if (tTd(7, 9)) 2233 { 2234 printf(" lockfd="); 2235 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 2236 } 2237 if (LogLevel > 93) 2238 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 2239 } 2240 2241 if (type == '\0') 2242 return (NULL); 2243 (void) snprintf(buf, sizeof buf, "%cf%s", type, e->e_id); 2244 if (tTd(7, 2)) 2245 printf("queuename: %s\n", buf); 2246 return (buf); 2247} 2248/* 2249** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 2250** 2251** Parameters: 2252** e -- the envelope to unlock. 2253** 2254** Returns: 2255** none 2256** 2257** Side Effects: 2258** unlocks the queue for `e'. 2259*/ 2260 2261void 2262unlockqueue(e) 2263 ENVELOPE *e; 2264{ 2265 if (tTd(51, 4)) 2266 printf("unlockqueue(%s)\n", 2267 e->e_id == NULL ? "NOQUEUE" : e->e_id); 2268 2269 /* if there is a lock file in the envelope, close it */ 2270 if (e->e_lockfp != NULL) 2271 xfclose(e->e_lockfp, "unlockqueue", e->e_id); 2272 e->e_lockfp = NULL; 2273 2274 /* don't create a queue id if we don't already have one */ 2275 if (e->e_id == NULL) 2276 return; 2277 2278 /* remove the transcript */ 2279 if (LogLevel > 87) 2280 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 2281 if (!tTd(51, 104)) 2282 xunlink(queuename(e, 'x')); 2283 2284} 2285/* 2286** SETCTLUSER -- create a controlling address 2287** 2288** Create a fake "address" given only a local login name; this is 2289** used as a "controlling user" for future recipient addresses. 2290** 2291** Parameters: 2292** user -- the user name of the controlling user. 2293** qfver -- the version stamp of this qf file. 2294** 2295** Returns: 2296** An address descriptor for the controlling user. 2297** 2298** Side Effects: 2299** none. 2300*/ 2301 2302ADDRESS * 2303setctluser(user, qfver) 2304 char *user; 2305 int qfver; 2306{ 2307 register ADDRESS *a; 2308 struct passwd *pw; 2309 char *p; 2310 2311 /* 2312 ** See if this clears our concept of controlling user. 2313 */ 2314 2315 if (user == NULL || *user == '\0') 2316 return NULL; 2317 2318 /* 2319 ** Set up addr fields for controlling user. 2320 */ 2321 2322 a = (ADDRESS *) xalloc(sizeof *a); 2323 bzero((char *) a, sizeof *a); 2324 2325 if (*user == '\0') 2326 { 2327 p = NULL; 2328 a->q_user = newstr(DefUser); 2329 } 2330 else if (*user == ':') 2331 { 2332 p = &user[1]; 2333 a->q_user = newstr(p); 2334 } 2335 else 2336 { 2337 p = strtok(user, ":"); 2338 a->q_user = newstr(user); 2339 if (qfver >= 2) 2340 { 2341 if ((p = strtok(NULL, ":")) != NULL) 2342 a->q_uid = atoi(p); 2343 if ((p = strtok(NULL, ":")) != NULL) 2344 a->q_gid = atoi(p); 2345 if ((p = strtok(NULL, ":")) != NULL) 2346 a->q_flags |= QGOODUID; 2347 } 2348 else if ((pw = sm_getpwnam(user)) != NULL) 2349 { 2350 if (strcmp(pw->pw_dir, "/") == 0) 2351 a->q_home = ""; 2352 else 2353 a->q_home = newstr(pw->pw_dir); 2354 a->q_uid = pw->pw_uid; 2355 a->q_gid = pw->pw_gid; 2356 a->q_flags |= QGOODUID; 2357 } 2358 } 2359 2360 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 2361 a->q_mailer = LocalMailer; 2362 if (p == NULL) 2363 a->q_paddr = a->q_user; 2364 else 2365 a->q_paddr = newstr(p); 2366 return a; 2367} 2368/* 2369** LOSEQFILE -- save the qf as Qf and try to let someone know 2370** 2371** Parameters: 2372** e -- the envelope (e->e_id will be used). 2373** why -- reported to whomever can hear. 2374** 2375** Returns: 2376** none. 2377*/ 2378 2379void 2380loseqfile(e, why) 2381 register ENVELOPE *e; 2382 char *why; 2383{ 2384 char *p; 2385 char buf[MAXQFNAME + 1]; 2386 2387 if (e == NULL || e->e_id == NULL) 2388 return; 2389 p = queuename(e, 'q'); 2390 if (strlen(p) > MAXQFNAME) 2391 { 2392 syserr("loseqfile: queuename (%s) too long", p); 2393 return; 2394 } 2395 strcpy(buf, p); 2396 p = queuename(e, 'Q'); 2397 if (rename(buf, p) < 0) 2398 syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); 2399 else if (LogLevel > 0) 2400 sm_syslog(LOG_ALERT, e->e_id, 2401 "Losing %s: %s", buf, why); 2402} 2403