1 /* 2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 15 #include <sendmail.h> 16 17 #ifndef lint 18 # if QUEUE 19 static char id[] = "@(#)$Id: queue.c,v 8.343.4.62 2001/07/20 00:53:01 gshapiro Exp $ (with queueing)"; 20 # else /* QUEUE */ 21 static char id[] = "@(#)$Id: queue.c,v 8.343.4.62 2001/07/20 00:53:01 gshapiro Exp $ (without queueing)"; 22 # endif /* QUEUE */ 23 #endif /* ! lint */ 24 25 # include <dirent.h> 26 27 #if QUEUE 28 29 # if _FFR_QUEUEDELAY 30 # define QF_VERSION 5 /* version number of this queue format */ 31 static time_t queuedelay __P((ENVELOPE *)); 32 # else /* _FFR_QUEUEDELAY */ 33 # define QF_VERSION 4 /* version number of this queue format */ 34 # define queuedelay(e) MinQueueAge 35 # endif /* _FFR_QUEUEDELAY */ 36 37 /* 38 ** Work queue. 39 */ 40 41 struct work 42 { 43 char *w_name; /* name of control file */ 44 char *w_host; /* name of recipient host */ 45 bool w_lock; /* is message locked? */ 46 bool w_tooyoung; /* is it too young to run? */ 47 long w_pri; /* priority of message, see below */ 48 time_t w_ctime; /* creation time of message */ 49 struct work *w_next; /* next in queue */ 50 }; 51 52 typedef struct work WORK; 53 54 static WORK *WorkQ; /* queue of things to be done */ 55 56 static void grow_wlist __P((int)); 57 static int orderq __P((int, bool)); 58 static void printctladdr __P((ADDRESS *, FILE *)); 59 static int print_single_queue __P((int)); 60 static bool readqf __P((ENVELOPE *)); 61 static void runqueueevent __P((void)); 62 static int run_single_queue __P((int, bool, bool)); 63 static char *strrev __P((char *)); 64 static ADDRESS *setctluser __P((char *, int)); 65 static int workcmpf0(); 66 static int workcmpf1(); 67 static int workcmpf2(); 68 static int workcmpf3(); 69 static int workcmpf4(); 70 71 /* 72 ** Current qf file field assignments: 73 ** 74 ** A AUTH= parameter 75 ** B body type 76 ** C controlling user 77 ** D data file name 78 ** E error recipient 79 ** F flag bits 80 ** G queue delay algorithm 81 ** H header 82 ** I data file's inode number 83 ** K time of last delivery attempt 84 ** L Solaris Content-Length: header (obsolete) 85 ** M message (obsolete) 86 ** N number of delivery attempts 87 ** P message priority 88 ** Q original recipient (ORCPT=) 89 ** R recipient 90 ** S sender 91 ** T init time 92 ** V queue file version 93 ** X character set (_FFR_SAVE_CHARSET) 94 ** Y current delay 95 ** Z original envelope id from ESMTP 96 ** $ define macro 97 ** . terminate file 98 */ 99 100 /* 101 ** QUEUEUP -- queue a message up for future transmission. 102 ** 103 ** Parameters: 104 ** e -- the envelope to queue up. 105 ** announce -- if TRUE, tell when you are queueing up. 106 ** 107 ** Returns: 108 ** none. 109 ** 110 ** Side Effects: 111 ** The current request are saved in a control file. 112 ** The queue file is left locked. 113 */ 114 115 # define TEMPQF_LETTER 'T' 116 # define LOSEQF_LETTER 'Q' 117 118 void 119 queueup(e, announce) 120 register ENVELOPE *e; 121 bool announce; 122 { 123 char *qf; 124 register FILE *tfp; 125 register HDR *h; 126 register ADDRESS *q; 127 int tfd = -1; 128 int i; 129 bool newid; 130 register char *p; 131 MAILER nullmailer; 132 MCI mcibuf; 133 char tf[MAXPATHLEN]; 134 char buf[MAXLINE]; 135 136 /* 137 ** Create control file. 138 */ 139 140 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 141 142 /* if newid, queuename will create a locked qf file in e->lockfp */ 143 (void) strlcpy(tf, queuename(e, 't'), sizeof tf); 144 tfp = e->e_lockfp; 145 if (tfp == NULL) 146 newid = FALSE; 147 148 /* if newid, just write the qf file directly (instead of tf file) */ 149 if (!newid) 150 { 151 int flags; 152 153 flags = O_CREAT|O_WRONLY|O_EXCL; 154 155 /* get a locked tf file */ 156 for (i = 0; i < 128; i++) 157 { 158 if (tfd < 0) 159 { 160 #if _FFR_QUEUE_FILE_MODE 161 MODE_T oldumask; 162 163 if (bitset(S_IWGRP, QueueFileMode)) 164 oldumask = umask(002); 165 tfd = open(tf, flags, QueueFileMode); 166 if (bitset(S_IWGRP, QueueFileMode)) 167 (void) umask(oldumask); 168 #else /* _FFR_QUEUE_FILE_MODE */ 169 tfd = open(tf, flags, FileMode); 170 #endif /* _FFR_QUEUE_FILE_MODE */ 171 172 if (tfd < 0) 173 { 174 if (errno != EEXIST) 175 break; 176 if (LogLevel > 0 && (i % 32) == 0) 177 sm_syslog(LOG_ALERT, e->e_id, 178 "queueup: cannot create %s, uid=%d: %s", 179 tf, geteuid(), errstring(errno)); 180 } 181 } 182 if (tfd >= 0) 183 { 184 if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB)) 185 break; 186 else if (LogLevel > 0 && (i % 32) == 0) 187 sm_syslog(LOG_ALERT, e->e_id, 188 "queueup: cannot lock %s: %s", 189 tf, errstring(errno)); 190 if ((i % 32) == 31) 191 { 192 (void) close(tfd); 193 tfd = -1; 194 } 195 } 196 197 if ((i % 32) == 31) 198 { 199 /* save the old temp file away */ 200 (void) rename(tf, queuename(e, TEMPQF_LETTER)); 201 } 202 else 203 (void) sleep(i % 32); 204 } 205 if (tfd < 0 || (tfp = fdopen(tfd, "w")) == NULL) 206 { 207 int save_errno = errno; 208 209 printopenfds(TRUE); 210 errno = save_errno; 211 syserr("!queueup: cannot create queue temp file %s, uid=%d", 212 tf, geteuid()); 213 } 214 } 215 216 if (tTd(40, 1)) 217 dprintf("\n>>>>> queueing %s/qf%s%s >>>>>\n", 218 qid_printqueue(e->e_queuedir), e->e_id, 219 newid ? " (new id)" : ""); 220 if (tTd(40, 3)) 221 { 222 dprintf(" e_flags="); 223 printenvflags(e); 224 } 225 if (tTd(40, 32)) 226 { 227 dprintf(" sendq="); 228 printaddr(e->e_sendqueue, TRUE); 229 } 230 if (tTd(40, 9)) 231 { 232 dprintf(" tfp="); 233 dumpfd(fileno(tfp), TRUE, FALSE); 234 dprintf(" lockfp="); 235 if (e->e_lockfp == NULL) 236 dprintf("NULL\n"); 237 else 238 dumpfd(fileno(e->e_lockfp), TRUE, FALSE); 239 } 240 241 /* 242 ** If there is no data file yet, create one. 243 */ 244 245 if (bitset(EF_HAS_DF, e->e_flags)) 246 { 247 if (e->e_dfp != NULL && bfcommit(e->e_dfp) < 0) 248 syserr("!queueup: cannot commit data file %s, uid=%d", 249 queuename(e, 'd'), geteuid()); 250 } 251 else 252 { 253 int dfd; 254 register FILE *dfp = NULL; 255 char dfname[MAXPATHLEN]; 256 struct stat stbuf; 257 258 if (e->e_dfp != NULL && bftest(e->e_dfp)) 259 syserr("committing over bf file"); 260 261 (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); 262 #if _FFR_QUEUE_FILE_MODE 263 { 264 MODE_T oldumask; 265 266 if (bitset(S_IWGRP, QueueFileMode)) 267 oldumask = umask(002); 268 dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, 269 QueueFileMode); 270 if (bitset(S_IWGRP, QueueFileMode)) 271 (void) umask(oldumask); 272 } 273 #else /* _FFR_QUEUE_FILE_MODE */ 274 dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode); 275 #endif /* _FFR_QUEUE_FILE_MODE */ 276 if (dfd < 0 || (dfp = fdopen(dfd, "w")) == NULL) 277 syserr("!queueup: cannot create data temp file %s, uid=%d", 278 dfname, geteuid()); 279 if (fstat(dfd, &stbuf) < 0) 280 e->e_dfino = -1; 281 else 282 { 283 e->e_dfdev = stbuf.st_dev; 284 e->e_dfino = stbuf.st_ino; 285 } 286 e->e_flags |= EF_HAS_DF; 287 memset(&mcibuf, '\0', sizeof mcibuf); 288 mcibuf.mci_out = dfp; 289 mcibuf.mci_mailer = FileMailer; 290 (*e->e_putbody)(&mcibuf, e, NULL); 291 if (fclose(dfp) < 0) 292 syserr("!queueup: cannot save data temp file %s, uid=%d", 293 dfname, geteuid()); 294 e->e_putbody = putbody; 295 } 296 297 /* 298 ** Output future work requests. 299 ** Priority and creation time should be first, since 300 ** they are required by orderq. 301 */ 302 303 /* output queue version number (must be first!) */ 304 fprintf(tfp, "V%d\n", QF_VERSION); 305 306 /* output creation time */ 307 fprintf(tfp, "T%ld\n", (long) e->e_ctime); 308 309 /* output last delivery time */ 310 # if _FFR_QUEUEDELAY 311 fprintf(tfp, "K%ld\n", (long) e->e_dtime); 312 fprintf(tfp, "G%d\n", e->e_queuealg); 313 fprintf(tfp, "Y%ld\n", (long) e->e_queuedelay); 314 if (tTd(40, 64)) 315 sm_syslog(LOG_INFO, e->e_id, 316 "queue alg: %d delay %ld next: %ld (now: %ld)\n", 317 e->e_queuealg, e->e_queuedelay, e->e_dtime, curtime()); 318 # else /* _FFR_QUEUEDELAY */ 319 fprintf(tfp, "K%ld\n", (long) e->e_dtime); 320 # endif /* _FFR_QUEUEDELAY */ 321 322 /* output number of delivery attempts */ 323 fprintf(tfp, "N%d\n", e->e_ntries); 324 325 /* output message priority */ 326 fprintf(tfp, "P%ld\n", e->e_msgpriority); 327 328 /* output inode number of data file */ 329 /* XXX should probably include device major/minor too */ 330 if (e->e_dfino != -1) 331 { 332 /*CONSTCOND*/ 333 if (sizeof e->e_dfino > sizeof(long)) 334 fprintf(tfp, "I%ld/%ld/%s\n", 335 (long) major(e->e_dfdev), 336 (long) minor(e->e_dfdev), 337 quad_to_string(e->e_dfino)); 338 else 339 fprintf(tfp, "I%ld/%ld/%lu\n", 340 (long) major(e->e_dfdev), 341 (long) minor(e->e_dfdev), 342 (unsigned long) e->e_dfino); 343 } 344 345 /* output body type */ 346 if (e->e_bodytype != NULL) 347 fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE)); 348 349 # if _FFR_SAVE_CHARSET 350 if (e->e_charset != NULL) 351 fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE)); 352 # endif /* _FFR_SAVE_CHARSET */ 353 354 /* message from envelope, if it exists */ 355 if (e->e_message != NULL) 356 fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE)); 357 358 /* send various flag bits through */ 359 p = buf; 360 if (bitset(EF_WARNING, e->e_flags)) 361 *p++ = 'w'; 362 if (bitset(EF_RESPONSE, e->e_flags)) 363 *p++ = 'r'; 364 if (bitset(EF_HAS8BIT, e->e_flags)) 365 *p++ = '8'; 366 if (bitset(EF_DELETE_BCC, e->e_flags)) 367 *p++ = 'b'; 368 if (bitset(EF_RET_PARAM, e->e_flags)) 369 *p++ = 'd'; 370 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 371 *p++ = 'n'; 372 *p++ = '\0'; 373 if (buf[0] != '\0') 374 fprintf(tfp, "F%s\n", buf); 375 376 /* save $={persistentMacros} macro values */ 377 queueup_macros(macid("{persistentMacros}", NULL), tfp, e); 378 379 /* output name of sender */ 380 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) 381 p = e->e_sender; 382 else 383 p = e->e_from.q_paddr; 384 fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE)); 385 386 /* output ESMTP-supplied "original" information */ 387 if (e->e_envid != NULL) 388 fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE)); 389 390 /* output AUTH= parameter */ 391 if (e->e_auth_param != NULL) 392 fprintf(tfp, "A%s\n", denlstring(e->e_auth_param, 393 TRUE, FALSE)); 394 395 /* output list of recipient addresses */ 396 printctladdr(NULL, NULL); 397 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 398 { 399 if (!QS_IS_UNDELIVERED(q->q_state)) 400 continue; 401 402 printctladdr(q, tfp); 403 if (q->q_orcpt != NULL) 404 fprintf(tfp, "Q%s\n", 405 denlstring(q->q_orcpt, TRUE, FALSE)); 406 407 (void) putc('R', tfp); 408 if (bitset(QPRIMARY, q->q_flags)) 409 (void) putc('P', tfp); 410 if (bitset(QHASNOTIFY, q->q_flags)) 411 (void) putc('N', tfp); 412 if (bitset(QPINGONSUCCESS, q->q_flags)) 413 (void) putc('S', tfp); 414 if (bitset(QPINGONFAILURE, q->q_flags)) 415 (void) putc('F', tfp); 416 if (bitset(QPINGONDELAY, q->q_flags)) 417 (void) putc('D', tfp); 418 if (q->q_alias != NULL && 419 bitset(QALIAS, q->q_alias->q_flags)) 420 (void) putc('A', tfp); 421 (void) putc(':', tfp); 422 (void) fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE)); 423 if (announce) 424 { 425 e->e_to = q->q_paddr; 426 message("queued"); 427 if (LogLevel > 8) 428 logdelivery(q->q_mailer, NULL, q->q_status, 429 "queued", NULL, (time_t) 0, e); 430 e->e_to = NULL; 431 } 432 if (tTd(40, 1)) 433 { 434 dprintf("queueing "); 435 printaddr(q, FALSE); 436 } 437 } 438 439 /* 440 ** Output headers for this message. 441 ** Expand macros completely here. Queue run will deal with 442 ** everything as absolute headers. 443 ** All headers that must be relative to the recipient 444 ** can be cracked later. 445 ** We set up a "null mailer" -- i.e., a mailer that will have 446 ** no effect on the addresses as they are output. 447 */ 448 449 memset((char *) &nullmailer, '\0', sizeof nullmailer); 450 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 451 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; 452 nullmailer.m_eol = "\n"; 453 memset(&mcibuf, '\0', sizeof mcibuf); 454 mcibuf.mci_mailer = &nullmailer; 455 mcibuf.mci_out = tfp; 456 457 define('g', "\201f", e); 458 for (h = e->e_header; h != NULL; h = h->h_link) 459 { 460 if (h->h_value == NULL) 461 continue; 462 463 /* don't output resent headers on non-resent messages */ 464 if (bitset(H_RESENT, h->h_flags) && 465 !bitset(EF_RESENT, e->e_flags)) 466 continue; 467 468 /* expand macros; if null, don't output header at all */ 469 if (bitset(H_DEFAULT, h->h_flags)) 470 { 471 (void) expand(h->h_value, buf, sizeof buf, e); 472 if (buf[0] == '\0') 473 continue; 474 } 475 476 /* output this header */ 477 fprintf(tfp, "H?"); 478 479 /* output conditional macro if present */ 480 if (h->h_macro != '\0') 481 { 482 if (bitset(0200, h->h_macro)) 483 fprintf(tfp, "${%s}", 484 macname(bitidx(h->h_macro))); 485 else 486 fprintf(tfp, "$%c", h->h_macro); 487 } 488 else if (!bitzerop(h->h_mflags) && 489 bitset(H_CHECK|H_ACHECK, h->h_flags)) 490 { 491 int j; 492 493 /* if conditional, output the set of conditions */ 494 for (j = '\0'; j <= '\177'; j++) 495 if (bitnset(j, h->h_mflags)) 496 (void) putc(j, tfp); 497 } 498 (void) putc('?', tfp); 499 500 /* output the header: expand macros, convert addresses */ 501 if (bitset(H_DEFAULT, h->h_flags) && 502 !bitset(H_BINDLATE, h->h_flags)) 503 { 504 fprintf(tfp, "%s: %s\n", 505 h->h_field, 506 denlstring(buf, FALSE, TRUE)); 507 } 508 else if (bitset(H_FROM|H_RCPT, h->h_flags) && 509 !bitset(H_BINDLATE, h->h_flags)) 510 { 511 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 512 FILE *savetrace = TrafficLogFile; 513 514 TrafficLogFile = NULL; 515 516 if (bitset(H_FROM, h->h_flags)) 517 oldstyle = FALSE; 518 519 commaize(h, h->h_value, oldstyle, &mcibuf, e); 520 521 TrafficLogFile = savetrace; 522 } 523 else 524 { 525 fprintf(tfp, "%s: %s\n", 526 h->h_field, 527 denlstring(h->h_value, FALSE, TRUE)); 528 } 529 } 530 531 /* 532 ** Clean up. 533 ** 534 ** Write a terminator record -- this is to prevent 535 ** scurrilous crackers from appending any data. 536 */ 537 538 fprintf(tfp, ".\n"); 539 540 if (fflush(tfp) != 0 || 541 (SuperSafe && fsync(fileno(tfp)) < 0) || 542 ferror(tfp)) 543 { 544 if (newid) 545 syserr("!552 Error writing control file %s", tf); 546 else 547 syserr("!452 Error writing control file %s", tf); 548 } 549 550 if (!newid) 551 { 552 /* rename (locked) tf to be (locked) qf */ 553 qf = queuename(e, 'q'); 554 if (rename(tf, qf) < 0) 555 syserr("cannot rename(%s, %s), uid=%d", 556 tf, qf, geteuid()); 557 /* 558 ** fsync() after renaming to make sure 559 ** metadata is written to disk on 560 ** filesystems in which renames are 561 ** not guaranteed such as softupdates. 562 */ 563 564 if (tfd >= 0 && SuperSafe && fsync(tfd) < 0) 565 syserr("!queueup: cannot fsync queue temp file %s", tf); 566 567 /* close and unlock old (locked) qf */ 568 if (e->e_lockfp != NULL) 569 (void) fclose(e->e_lockfp); 570 e->e_lockfp = tfp; 571 } 572 else 573 qf = tf; 574 errno = 0; 575 e->e_flags |= EF_INQUEUE; 576 577 /* save log info */ 578 if (LogLevel > 79) 579 sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf); 580 581 if (tTd(40, 1)) 582 dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 583 return; 584 } 585 586 static void 587 printctladdr(a, tfp) 588 register ADDRESS *a; 589 FILE *tfp; 590 { 591 char *user; 592 register ADDRESS *q; 593 uid_t uid; 594 gid_t gid; 595 static ADDRESS *lastctladdr = NULL; 596 static uid_t lastuid; 597 598 /* initialization */ 599 if (a == NULL || a->q_alias == NULL || tfp == NULL) 600 { 601 if (lastctladdr != NULL && tfp != NULL) 602 fprintf(tfp, "C\n"); 603 lastctladdr = NULL; 604 lastuid = 0; 605 return; 606 } 607 608 /* find the active uid */ 609 q = getctladdr(a); 610 if (q == NULL) 611 { 612 user = NULL; 613 uid = 0; 614 gid = 0; 615 } 616 else 617 { 618 user = q->q_ruser != NULL ? q->q_ruser : q->q_user; 619 uid = q->q_uid; 620 gid = q->q_gid; 621 } 622 a = a->q_alias; 623 624 /* check to see if this is the same as last time */ 625 if (lastctladdr != NULL && uid == lastuid && 626 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 627 return; 628 lastuid = uid; 629 lastctladdr = a; 630 631 if (uid == 0 || user == NULL || user[0] == '\0') 632 fprintf(tfp, "C"); 633 else 634 fprintf(tfp, "C%s:%ld:%ld", 635 denlstring(user, TRUE, FALSE), (long) uid, (long) gid); 636 fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE)); 637 } 638 /* 639 ** RUNQUEUE -- run the jobs in the queue. 640 ** 641 ** Gets the stuff out of the queue in some presumably logical 642 ** order and processes them. 643 ** 644 ** Parameters: 645 ** forkflag -- TRUE if the queue scanning should be done in 646 ** a child process. We double-fork so it is not our 647 ** child and we don't have to clean up after it. 648 ** FALSE can be ignored if we have multiple queues. 649 ** verbose -- if TRUE, print out status information. 650 ** 651 ** Returns: 652 ** TRUE if the queue run successfully began. 653 ** 654 ** Side Effects: 655 ** runs things in the mail queue. 656 */ 657 658 static ENVELOPE QueueEnvelope; /* the queue run envelope */ 659 int NumQueues = 0; /* number of queues */ 660 static time_t LastQueueTime = 0; /* last time a queue ID assigned */ 661 static pid_t LastQueuePid = -1; /* last PID which had a queue ID */ 662 663 struct qpaths_s 664 { 665 char *qp_name; /* name of queue dir */ 666 short qp_subdirs; /* use subdirs? */ 667 }; 668 669 typedef struct qpaths_s QPATHS; 670 671 /* values for qp_supdirs */ 672 #define QP_NOSUB 0x0000 /* No subdirectories */ 673 #define QP_SUBDF 0x0001 /* "df" subdirectory */ 674 #define QP_SUBQF 0x0002 /* "qf" subdirectory */ 675 #define QP_SUBXF 0x0004 /* "xf" subdirectory */ 676 677 static QPATHS *QPaths = NULL; /* list of queue directories */ 678 679 bool 680 runqueue(forkflag, verbose) 681 bool forkflag; 682 bool verbose; 683 { 684 int i; 685 bool ret = TRUE; 686 static int curnum = 0; 687 688 DoQueueRun = FALSE; 689 690 691 if (!forkflag && NumQueues > 1 && !verbose) 692 forkflag = TRUE; 693 694 for (i = 0; i < NumQueues; i++) 695 { 696 /* 697 ** Pick up where we left off, in case we 698 ** used up all the children last time 699 ** without finishing. 700 */ 701 702 ret = run_single_queue(curnum, forkflag, verbose); 703 704 /* 705 ** Failure means a message was printed for ETRN 706 ** and subsequent queues are likely to fail as well. 707 */ 708 709 if (!ret) 710 break; 711 712 if (++curnum >= NumQueues) 713 curnum = 0; 714 } 715 if (QueueIntvl != 0) 716 (void) setevent(QueueIntvl, runqueueevent, 0); 717 return ret; 718 } 719 /* 720 ** RUN_SINGLE_QUEUE -- run the jobs in a single queue. 721 ** 722 ** Gets the stuff out of the queue in some presumably logical 723 ** order and processes them. 724 ** 725 ** Parameters: 726 ** queuedir -- queue to process 727 ** forkflag -- TRUE if the queue scanning should be done in 728 ** a child process. We double-fork so it is not our 729 ** child and we don't have to clean up after it. 730 ** verbose -- if TRUE, print out status information. 731 ** 732 ** Returns: 733 ** TRUE if the queue run successfully began. 734 ** 735 ** Side Effects: 736 ** runs things in the mail queue. 737 */ 738 739 static bool 740 run_single_queue(queuedir, forkflag, verbose) 741 int queuedir; 742 bool forkflag; 743 bool verbose; 744 { 745 register ENVELOPE *e; 746 int njobs; 747 int sequenceno = 0; 748 time_t current_la_time, now; 749 extern ENVELOPE BlankEnvelope; 750 751 /* 752 ** If no work will ever be selected, don't even bother reading 753 ** the queue. 754 */ 755 756 CurrentLA = sm_getla(NULL); /* get load average */ 757 current_la_time = curtime(); 758 759 if (shouldqueue(WkRecipFact, current_la_time)) 760 { 761 char *msg = "Skipping queue run -- load average too high"; 762 763 if (verbose) 764 message("458 %s\n", msg); 765 if (LogLevel > 8) 766 sm_syslog(LOG_INFO, NOQID, 767 "runqueue: %s", 768 msg); 769 return FALSE; 770 } 771 772 /* 773 ** See if we already have too many children. 774 */ 775 776 if (forkflag && QueueIntvl != 0 && 777 MaxChildren > 0 && CurChildren >= MaxChildren) 778 { 779 char *msg = "Skipping queue run -- too many children"; 780 781 if (verbose) 782 message("458 %s (%d)\n", msg, CurChildren); 783 if (LogLevel > 8) 784 sm_syslog(LOG_INFO, NOQID, 785 "runqueue: %s (%d)", 786 msg, CurChildren); 787 return FALSE; 788 } 789 790 /* 791 ** See if we want to go off and do other useful work. 792 */ 793 794 if (forkflag) 795 { 796 pid_t pid; 797 798 (void) blocksignal(SIGCHLD); 799 (void) setsignal(SIGCHLD, reapchild); 800 801 pid = dofork(); 802 if (pid == -1) 803 { 804 const char *msg = "Skipping queue run -- fork() failed"; 805 const char *err = errstring(errno); 806 807 if (verbose) 808 message("458 %s: %s\n", msg, err); 809 if (LogLevel > 8) 810 sm_syslog(LOG_INFO, NOQID, 811 "runqueue: %s: %s", 812 msg, err); 813 (void) releasesignal(SIGCHLD); 814 return FALSE; 815 } 816 if (pid != 0) 817 { 818 /* parent -- pick up intermediate zombie */ 819 (void) blocksignal(SIGALRM); 820 proc_list_add(pid, "Queue runner", PROC_QUEUE); 821 (void) releasesignal(SIGALRM); 822 (void) releasesignal(SIGCHLD); 823 return TRUE; 824 } 825 /* child -- clean up signals */ 826 827 /* Reset global flags */ 828 RestartRequest = NULL; 829 ShutdownRequest = NULL; 830 PendingSignal = 0; 831 832 clrcontrol(); 833 proc_list_clear(); 834 835 /* Add parent process as first child item */ 836 proc_list_add(getpid(), "Queue runner child process", 837 PROC_QUEUE_CHILD); 838 (void) releasesignal(SIGCHLD); 839 (void) setsignal(SIGCHLD, SIG_DFL); 840 (void) setsignal(SIGHUP, SIG_DFL); 841 (void) setsignal(SIGTERM, intsig); 842 } 843 844 sm_setproctitle(TRUE, CurEnv, "running queue: %s", 845 qid_printqueue(queuedir)); 846 847 if (LogLevel > 69 || tTd(63, 99)) 848 sm_syslog(LOG_DEBUG, NOQID, 849 "runqueue %s, pid=%d, forkflag=%d", 850 qid_printqueue(queuedir), (int) getpid(), forkflag); 851 852 /* 853 ** Release any resources used by the daemon code. 854 */ 855 856 # if DAEMON 857 clrdaemon(); 858 # endif /* DAEMON */ 859 860 /* force it to run expensive jobs */ 861 NoConnect = FALSE; 862 863 /* drop privileges */ 864 if (geteuid() == (uid_t) 0) 865 (void) drop_privileges(FALSE); 866 867 /* 868 ** Create ourselves an envelope 869 */ 870 871 CurEnv = &QueueEnvelope; 872 e = newenvelope(&QueueEnvelope, CurEnv); 873 e->e_flags = BlankEnvelope.e_flags; 874 e->e_parent = NULL; 875 876 /* make sure we have disconnected from parent */ 877 if (forkflag) 878 { 879 disconnect(1, e); 880 QuickAbort = FALSE; 881 } 882 883 /* 884 ** If we are running part of the queue, always ignore stored 885 ** host status. 886 */ 887 888 if (QueueLimitId != NULL || QueueLimitSender != NULL || 889 QueueLimitRecipient != NULL) 890 { 891 IgnoreHostStatus = TRUE; 892 MinQueueAge = 0; 893 } 894 895 /* 896 ** Start making passes through the queue. 897 ** First, read and sort the entire queue. 898 ** Then, process the work in that order. 899 ** But if you take too long, start over. 900 */ 901 902 /* order the existing work requests */ 903 njobs = orderq(queuedir, FALSE); 904 905 906 /* process them once at a time */ 907 while (WorkQ != NULL) 908 { 909 WORK *w = WorkQ; 910 911 WorkQ = WorkQ->w_next; 912 e->e_to = NULL; 913 914 /* 915 ** Ignore jobs that are too expensive for the moment. 916 ** 917 ** Get new load average every 30 seconds. 918 */ 919 920 now = curtime(); 921 if (current_la_time < now - 30) 922 { 923 CurrentLA = sm_getla(e); 924 current_la_time = now; 925 } 926 if (shouldqueue(WkRecipFact, current_la_time)) 927 { 928 char *msg = "Aborting queue run: load average too high"; 929 930 if (Verbose) 931 message("%s", msg); 932 if (LogLevel > 8) 933 sm_syslog(LOG_INFO, NOQID, 934 "runqueue: %s", 935 msg); 936 break; 937 } 938 sequenceno++; 939 if (shouldqueue(w->w_pri, w->w_ctime)) 940 { 941 if (Verbose) 942 message(""); 943 if (QueueSortOrder == QSO_BYPRIORITY) 944 { 945 if (Verbose) 946 message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue", 947 qid_printqueue(queuedir), 948 w->w_name + 2, 949 sequenceno, 950 njobs); 951 if (LogLevel > 8) 952 sm_syslog(LOG_INFO, NOQID, 953 "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)", 954 qid_printqueue(queuedir), 955 w->w_name + 2, 956 w->w_pri, 957 CurrentLA, 958 sequenceno, 959 njobs); 960 break; 961 } 962 else if (Verbose) 963 message("Skipping %s/%s (sequence %d of %d)", 964 qid_printqueue(queuedir), 965 w->w_name + 2, 966 sequenceno, njobs); 967 } 968 else 969 { 970 pid_t pid; 971 972 if (Verbose) 973 { 974 message(""); 975 message("Running %s/%s (sequence %d of %d)", 976 qid_printqueue(queuedir), 977 w->w_name + 2, 978 sequenceno, njobs); 979 } 980 if (tTd(63, 100)) 981 sm_syslog(LOG_DEBUG, NOQID, 982 "runqueue %s dowork(%s)", 983 qid_printqueue(queuedir), 984 w->w_name + 2); 985 986 pid = dowork(queuedir, w->w_name + 2, 987 ForkQueueRuns, FALSE, e); 988 errno = 0; 989 if (pid != 0) 990 (void) waitfor(pid); 991 } 992 sm_free(w->w_name); 993 if (w->w_host) 994 sm_free(w->w_host); 995 sm_free((char *) w); 996 } 997 998 /* exit without the usual cleanup */ 999 e->e_id = NULL; 1000 if (forkflag) 1001 finis(TRUE, ExitStat); 1002 /* NOTREACHED */ 1003 return TRUE; 1004 } 1005 1006 /* 1007 ** RUNQUEUEEVENT -- stub for use in setevent 1008 ** 1009 ** Parameters: 1010 ** none. 1011 ** 1012 ** Returns: 1013 ** none. 1014 ** 1015 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1016 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1017 ** DOING. 1018 */ 1019 1020 static void 1021 runqueueevent() 1022 { 1023 DoQueueRun = TRUE; 1024 } 1025 /* 1026 ** ORDERQ -- order the work queue. 1027 ** 1028 ** Parameters: 1029 ** queuedir -- the index of the queue directory. 1030 ** doall -- if set, include everything in the queue (even 1031 ** the jobs that cannot be run because the load 1032 ** average is too high). Otherwise, exclude those 1033 ** jobs. 1034 ** 1035 ** Returns: 1036 ** The number of request in the queue (not necessarily 1037 ** the number of requests in WorkQ however). 1038 ** 1039 ** Side Effects: 1040 ** Sets WorkQ to the queue of available work, in order. 1041 */ 1042 1043 # define NEED_P 001 1044 # define NEED_T 002 1045 # define NEED_R 004 1046 # define NEED_S 010 1047 # define NEED_H 020 1048 1049 static WORK *WorkList = NULL; 1050 static int WorkListSize = 0; 1051 1052 static int 1053 orderq(queuedir, doall) 1054 int queuedir; 1055 bool doall; 1056 { 1057 register struct dirent *d; 1058 register WORK *w; 1059 register char *p; 1060 DIR *f; 1061 register int i; 1062 int wn = -1; 1063 int wc; 1064 QUEUE_CHAR *check; 1065 char qd[MAXPATHLEN]; 1066 char qf[MAXPATHLEN]; 1067 1068 if (queuedir == NOQDIR) 1069 (void) strlcpy(qd, ".", sizeof qd); 1070 else 1071 (void) snprintf(qd, sizeof qd, "%s%s", 1072 QPaths[queuedir].qp_name, 1073 (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); 1074 1075 if (tTd(41, 1)) 1076 { 1077 dprintf("orderq:\n"); 1078 1079 check = QueueLimitId; 1080 while (check != NULL) 1081 { 1082 dprintf("\tQueueLimitId = %s\n", 1083 check->queue_match); 1084 check = check->queue_next; 1085 } 1086 1087 check = QueueLimitSender; 1088 while (check != NULL) 1089 { 1090 dprintf("\tQueueLimitSender = %s\n", 1091 check->queue_match); 1092 check = check->queue_next; 1093 } 1094 1095 check = QueueLimitRecipient; 1096 while (check != NULL) 1097 { 1098 dprintf("\tQueueLimitRecipient = %s\n", 1099 check->queue_match); 1100 check = check->queue_next; 1101 } 1102 } 1103 1104 /* clear out old WorkQ */ 1105 for (w = WorkQ; w != NULL; ) 1106 { 1107 register WORK *nw = w->w_next; 1108 1109 WorkQ = nw; 1110 sm_free(w->w_name); 1111 if (w->w_host != NULL) 1112 sm_free(w->w_host); 1113 sm_free((char *) w); 1114 w = nw; 1115 } 1116 1117 /* open the queue directory */ 1118 f = opendir(qd); 1119 if (f == NULL) 1120 { 1121 syserr("orderq: cannot open \"%s\"", qid_printqueue(queuedir)); 1122 return 0; 1123 } 1124 1125 /* 1126 ** Read the work directory. 1127 */ 1128 1129 while ((d = readdir(f)) != NULL) 1130 { 1131 FILE *cf; 1132 int qfver = 0; 1133 char lbuf[MAXNAME + 1]; 1134 struct stat sbuf; 1135 1136 if (tTd(41, 50)) 1137 dprintf("orderq: checking %s\n", d->d_name); 1138 1139 /* is this an interesting entry? */ 1140 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 1141 continue; 1142 1143 if (strlen(d->d_name) >= MAXQFNAME) 1144 { 1145 if (Verbose) 1146 printf("orderq: %s too long, %d max characters\n", 1147 d->d_name, MAXQFNAME); 1148 if (LogLevel > 0) 1149 sm_syslog(LOG_ALERT, NOQID, 1150 "orderq: %s too long, %d max characters", 1151 d->d_name, MAXQFNAME); 1152 continue; 1153 } 1154 1155 check = QueueLimitId; 1156 while (check != NULL) 1157 { 1158 if (strcontainedin(check->queue_match, d->d_name)) 1159 break; 1160 else 1161 check = check->queue_next; 1162 } 1163 if (QueueLimitId != NULL && check == NULL) 1164 continue; 1165 1166 /* grow work list if necessary */ 1167 if (++wn >= MaxQueueRun && MaxQueueRun > 0) 1168 { 1169 if (wn == MaxQueueRun && LogLevel > 0) 1170 sm_syslog(LOG_WARNING, NOQID, 1171 "WorkList for %s maxed out at %d", 1172 qid_printqueue(queuedir), 1173 MaxQueueRun); 1174 continue; 1175 } 1176 if (wn >= WorkListSize) 1177 { 1178 grow_wlist(queuedir); 1179 if (wn >= WorkListSize) 1180 continue; 1181 } 1182 w = &WorkList[wn]; 1183 1184 (void) snprintf(qf, sizeof qf, "%s/%s", qd, d->d_name); 1185 if (stat(qf, &sbuf) < 0) 1186 { 1187 if (errno != ENOENT) 1188 sm_syslog(LOG_INFO, NOQID, 1189 "orderq: can't stat %s/%s", 1190 qid_printqueue(queuedir), d->d_name); 1191 wn--; 1192 continue; 1193 } 1194 if (!bitset(S_IFREG, sbuf.st_mode)) 1195 { 1196 /* Yikes! Skip it or we will hang on open! */ 1197 syserr("orderq: %s/%s is not a regular file", 1198 qid_printqueue(queuedir), d->d_name); 1199 wn--; 1200 continue; 1201 } 1202 1203 /* avoid work if possible */ 1204 if (QueueSortOrder == QSO_BYFILENAME && 1205 QueueLimitSender == NULL && 1206 QueueLimitRecipient == NULL) 1207 { 1208 w->w_name = newstr(d->d_name); 1209 w->w_host = NULL; 1210 w->w_lock = w->w_tooyoung = FALSE; 1211 w->w_pri = 0; 1212 w->w_ctime = 0; 1213 continue; 1214 } 1215 1216 /* open control file */ 1217 cf = fopen(qf, "r"); 1218 1219 if (cf == NULL) 1220 { 1221 /* this may be some random person sending hir msgs */ 1222 /* syserr("orderq: cannot open %s", cbuf); */ 1223 if (tTd(41, 2)) 1224 dprintf("orderq: cannot open %s: %s\n", 1225 d->d_name, errstring(errno)); 1226 errno = 0; 1227 wn--; 1228 continue; 1229 } 1230 w->w_name = newstr(d->d_name); 1231 w->w_host = NULL; 1232 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 1233 w->w_tooyoung = FALSE; 1234 1235 /* make sure jobs in creation don't clog queue */ 1236 w->w_pri = 0x7fffffff; 1237 w->w_ctime = 0; 1238 1239 /* extract useful information */ 1240 i = NEED_P | NEED_T; 1241 if (QueueSortOrder == QSO_BYHOST) 1242 { 1243 /* need w_host set for host sort order */ 1244 i |= NEED_H; 1245 } 1246 if (QueueLimitSender != NULL) 1247 i |= NEED_S; 1248 if (QueueLimitRecipient != NULL) 1249 i |= NEED_R; 1250 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 1251 { 1252 int c; 1253 time_t age; 1254 1255 p = strchr(lbuf, '\n'); 1256 if (p != NULL) 1257 *p = '\0'; 1258 else 1259 { 1260 /* flush rest of overly long line */ 1261 while ((c = getc(cf)) != EOF && c != '\n') 1262 continue; 1263 } 1264 1265 switch (lbuf[0]) 1266 { 1267 case 'V': 1268 qfver = atoi(&lbuf[1]); 1269 break; 1270 1271 case 'P': 1272 w->w_pri = atol(&lbuf[1]); 1273 i &= ~NEED_P; 1274 break; 1275 1276 case 'T': 1277 w->w_ctime = atol(&lbuf[1]); 1278 i &= ~NEED_T; 1279 break; 1280 1281 case 'R': 1282 if (w->w_host == NULL && 1283 (p = strrchr(&lbuf[1], '@')) != NULL) 1284 { 1285 w->w_host = strrev(&p[1]); 1286 makelower(w->w_host); 1287 i &= ~NEED_H; 1288 } 1289 if (QueueLimitRecipient == NULL) 1290 { 1291 i &= ~NEED_R; 1292 break; 1293 } 1294 if (qfver > 0) 1295 { 1296 p = strchr(&lbuf[1], ':'); 1297 if (p == NULL) 1298 p = &lbuf[1]; 1299 } 1300 else 1301 p = &lbuf[1]; 1302 check = QueueLimitRecipient; 1303 while (check != NULL) 1304 { 1305 if (strcontainedin(check->queue_match, 1306 p)) 1307 break; 1308 else 1309 check = check->queue_next; 1310 } 1311 if (check != NULL) 1312 i &= ~NEED_R; 1313 break; 1314 1315 case 'S': 1316 check = QueueLimitSender; 1317 while (check != NULL) 1318 { 1319 if (strcontainedin(check->queue_match, 1320 &lbuf[1])) 1321 break; 1322 else 1323 check = check->queue_next; 1324 } 1325 if (check != NULL) 1326 i &= ~NEED_S; 1327 break; 1328 1329 case 'K': 1330 age = curtime() - (time_t) atol(&lbuf[1]); 1331 if (age >= 0 && MinQueueAge > 0 && 1332 age < MinQueueAge) 1333 w->w_tooyoung = TRUE; 1334 break; 1335 1336 case 'N': 1337 if (atol(&lbuf[1]) == 0) 1338 w->w_tooyoung = FALSE; 1339 break; 1340 1341 # if _FFR_QUEUEDELAY 1342 /* 1343 case 'G': 1344 queuealg = atoi(lbuf[1]); 1345 break; 1346 case 'Y': 1347 queuedelay = (time_t) atol(&lbuf[1]); 1348 break; 1349 */ 1350 # endif /* _FFR_QUEUEDELAY */ 1351 } 1352 } 1353 (void) fclose(cf); 1354 1355 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 1356 bitset(NEED_R|NEED_S, i)) 1357 { 1358 /* don't even bother sorting this job in */ 1359 if (tTd(41, 49)) 1360 dprintf("skipping %s (%x)\n", w->w_name, i); 1361 sm_free(w->w_name); 1362 if (w->w_host) 1363 sm_free(w->w_host); 1364 wn--; 1365 } 1366 } 1367 (void) closedir(f); 1368 wn++; 1369 1370 WorkQ = NULL; 1371 if (WorkList == NULL) 1372 return 0; 1373 wc = min(wn, WorkListSize); 1374 if (wc > MaxQueueRun && MaxQueueRun > 0) 1375 wc = MaxQueueRun; 1376 1377 if (QueueSortOrder == QSO_BYHOST) 1378 { 1379 /* 1380 ** Sort the work directory for the first time, 1381 ** based on host name, lock status, and priority. 1382 */ 1383 1384 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1); 1385 1386 /* 1387 ** If one message to host is locked, "lock" all messages 1388 ** to that host. 1389 */ 1390 1391 i = 0; 1392 while (i < wc) 1393 { 1394 if (!WorkList[i].w_lock) 1395 { 1396 i++; 1397 continue; 1398 } 1399 w = &WorkList[i]; 1400 while (++i < wc) 1401 { 1402 if (WorkList[i].w_host == NULL && 1403 w->w_host == NULL) 1404 WorkList[i].w_lock = TRUE; 1405 else if (WorkList[i].w_host != NULL && 1406 w->w_host != NULL && 1407 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0) 1408 WorkList[i].w_lock = TRUE; 1409 else 1410 break; 1411 } 1412 } 1413 1414 /* 1415 ** Sort the work directory for the second time, 1416 ** based on lock status, host name, and priority. 1417 */ 1418 1419 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2); 1420 } 1421 else if (QueueSortOrder == QSO_BYTIME) 1422 { 1423 /* 1424 ** Simple sort based on submission time only. 1425 */ 1426 1427 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); 1428 } 1429 else if (QueueSortOrder == QSO_BYFILENAME) 1430 { 1431 /* 1432 ** Sort based on qf filename. 1433 */ 1434 1435 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4); 1436 } 1437 else 1438 { 1439 /* 1440 ** Simple sort based on queue priority only. 1441 */ 1442 1443 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0); 1444 } 1445 1446 /* 1447 ** Convert the work list into canonical form. 1448 ** Should be turning it into a list of envelopes here perhaps. 1449 */ 1450 1451 for (i = wc; --i >= 0; ) 1452 { 1453 w = (WORK *) xalloc(sizeof *w); 1454 w->w_name = WorkList[i].w_name; 1455 w->w_host = WorkList[i].w_host; 1456 w->w_lock = WorkList[i].w_lock; 1457 w->w_tooyoung = WorkList[i].w_tooyoung; 1458 w->w_pri = WorkList[i].w_pri; 1459 w->w_ctime = WorkList[i].w_ctime; 1460 w->w_next = WorkQ; 1461 WorkQ = w; 1462 } 1463 if (WorkList != NULL) 1464 sm_free(WorkList); 1465 WorkList = NULL; 1466 WorkListSize = 0; 1467 1468 if (tTd(40, 1)) 1469 { 1470 for (w = WorkQ; w != NULL; w = w->w_next) 1471 { 1472 if (w->w_host != NULL) 1473 dprintf("%22s: pri=%ld %s\n", 1474 w->w_name, w->w_pri, w->w_host); 1475 else 1476 dprintf("%32s: pri=%ld\n", 1477 w->w_name, w->w_pri); 1478 } 1479 } 1480 1481 return wn; 1482 } 1483 /* 1484 ** GROW_WLIST -- make the work list larger 1485 ** 1486 ** Parameters: 1487 ** queuedir -- the index for the queue directory. 1488 ** 1489 ** Returns: 1490 ** none. 1491 ** 1492 ** Side Effects: 1493 ** Adds another QUEUESEGSIZE entries to WorkList if possible. 1494 ** It can fail if there isn't enough memory, so WorkListSize 1495 ** should be checked again upon return. 1496 */ 1497 1498 static void 1499 grow_wlist(queuedir) 1500 int queuedir; 1501 { 1502 if (tTd(41, 1)) 1503 dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize); 1504 if (WorkList == NULL) 1505 { 1506 WorkList = (WORK *) xalloc((sizeof *WorkList) * 1507 (QUEUESEGSIZE + 1)); 1508 WorkListSize = QUEUESEGSIZE; 1509 } 1510 else 1511 { 1512 int newsize = WorkListSize + QUEUESEGSIZE; 1513 WORK *newlist = (WORK *) xrealloc((char *)WorkList, 1514 (unsigned)sizeof(WORK) * (newsize + 1)); 1515 1516 if (newlist != NULL) 1517 { 1518 WorkListSize = newsize; 1519 WorkList = newlist; 1520 if (LogLevel > 1) 1521 { 1522 sm_syslog(LOG_INFO, NOQID, 1523 "grew WorkList for %s to %d", 1524 qid_printqueue(queuedir), 1525 WorkListSize); 1526 } 1527 } 1528 else if (LogLevel > 0) 1529 { 1530 sm_syslog(LOG_ALERT, NOQID, 1531 "FAILED to grow WorkList for %s to %d", 1532 qid_printqueue(queuedir), newsize); 1533 } 1534 } 1535 if (tTd(41, 1)) 1536 dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize); 1537 } 1538 /* 1539 ** WORKCMPF0 -- simple priority-only compare function. 1540 ** 1541 ** Parameters: 1542 ** a -- the first argument. 1543 ** b -- the second argument. 1544 ** 1545 ** Returns: 1546 ** -1 if a < b 1547 ** 0 if a == b 1548 ** +1 if a > b 1549 ** 1550 ** Side Effects: 1551 ** none. 1552 */ 1553 1554 static int 1555 workcmpf0(a, b) 1556 register WORK *a; 1557 register WORK *b; 1558 { 1559 long pa = a->w_pri; 1560 long pb = b->w_pri; 1561 1562 if (pa == pb) 1563 return 0; 1564 else if (pa > pb) 1565 return 1; 1566 else 1567 return -1; 1568 } 1569 /* 1570 ** WORKCMPF1 -- first compare function for ordering work based on host name. 1571 ** 1572 ** Sorts on host name, lock status, and priority in that order. 1573 ** 1574 ** Parameters: 1575 ** a -- the first argument. 1576 ** b -- the second argument. 1577 ** 1578 ** Returns: 1579 ** <0 if a < b 1580 ** 0 if a == b 1581 ** >0 if a > b 1582 ** 1583 ** Side Effects: 1584 ** none. 1585 */ 1586 1587 static int 1588 workcmpf1(a, b) 1589 register WORK *a; 1590 register WORK *b; 1591 { 1592 int i; 1593 1594 /* host name */ 1595 if (a->w_host != NULL && b->w_host == NULL) 1596 return 1; 1597 else if (a->w_host == NULL && b->w_host != NULL) 1598 return -1; 1599 if (a->w_host != NULL && b->w_host != NULL && 1600 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1601 return i; 1602 1603 /* lock status */ 1604 if (a->w_lock != b->w_lock) 1605 return b->w_lock - a->w_lock; 1606 1607 /* job priority */ 1608 return workcmpf0(a, b); 1609 } 1610 /* 1611 ** WORKCMPF2 -- second compare function for ordering work based on host name. 1612 ** 1613 ** Sorts on lock status, host name, and priority in that order. 1614 ** 1615 ** Parameters: 1616 ** a -- the first argument. 1617 ** b -- the second argument. 1618 ** 1619 ** Returns: 1620 ** <0 if a < b 1621 ** 0 if a == b 1622 ** >0 if a > b 1623 ** 1624 ** Side Effects: 1625 ** none. 1626 */ 1627 1628 static int 1629 workcmpf2(a, b) 1630 register WORK *a; 1631 register WORK *b; 1632 { 1633 int i; 1634 1635 /* lock status */ 1636 if (a->w_lock != b->w_lock) 1637 return a->w_lock - b->w_lock; 1638 1639 /* host name */ 1640 if (a->w_host != NULL && b->w_host == NULL) 1641 return 1; 1642 else if (a->w_host == NULL && b->w_host != NULL) 1643 return -1; 1644 if (a->w_host != NULL && b->w_host != NULL && 1645 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1646 return i; 1647 1648 /* job priority */ 1649 return workcmpf0(a, b); 1650 } 1651 /* 1652 ** WORKCMPF3 -- simple submission-time-only compare function. 1653 ** 1654 ** Parameters: 1655 ** a -- the first argument. 1656 ** b -- the second argument. 1657 ** 1658 ** Returns: 1659 ** -1 if a < b 1660 ** 0 if a == b 1661 ** +1 if a > b 1662 ** 1663 ** Side Effects: 1664 ** none. 1665 */ 1666 1667 static int 1668 workcmpf3(a, b) 1669 register WORK *a; 1670 register WORK *b; 1671 { 1672 if (a->w_ctime > b->w_ctime) 1673 return 1; 1674 else if (a->w_ctime < b->w_ctime) 1675 return -1; 1676 else 1677 return 0; 1678 } 1679 /* 1680 ** WORKCMPF4 -- compare based on file name 1681 ** 1682 ** Parameters: 1683 ** a -- the first argument. 1684 ** b -- the second argument. 1685 ** 1686 ** Returns: 1687 ** -1 if a < b 1688 ** 0 if a == b 1689 ** +1 if a > b 1690 ** 1691 ** Side Effects: 1692 ** none. 1693 */ 1694 1695 static int 1696 workcmpf4(a, b) 1697 register WORK *a; 1698 register WORK *b; 1699 { 1700 return strcmp(a->w_name, b->w_name); 1701 } 1702 /* 1703 ** STRREV -- reverse string 1704 ** 1705 ** Returns a pointer to a new string that is the reverse of 1706 ** the string pointed to by fwd. The space for the new 1707 ** string is obtained using xalloc(). 1708 ** 1709 ** Parameters: 1710 ** fwd -- the string to reverse. 1711 ** 1712 ** Returns: 1713 ** the reversed string. 1714 */ 1715 1716 static char * 1717 strrev(fwd) 1718 char *fwd; 1719 { 1720 char *rev = NULL; 1721 int len, cnt; 1722 1723 len = strlen(fwd); 1724 rev = xalloc(len + 1); 1725 for (cnt = 0; cnt < len; ++cnt) 1726 rev[cnt] = fwd[len - cnt - 1]; 1727 rev[len] = '\0'; 1728 return rev; 1729 } 1730 /* 1731 ** DOWORK -- do a work request. 1732 ** 1733 ** Parameters: 1734 ** queuedir -- the index of the queue directory for the job. 1735 ** id -- the ID of the job to run. 1736 ** forkflag -- if set, run this in background. 1737 ** requeueflag -- if set, reinstantiate the queue quickly. 1738 ** This is used when expanding aliases in the queue. 1739 ** If forkflag is also set, it doesn't wait for the 1740 ** child. 1741 ** e - the envelope in which to run it. 1742 ** 1743 ** Returns: 1744 ** process id of process that is running the queue job. 1745 ** 1746 ** Side Effects: 1747 ** The work request is satisfied if possible. 1748 */ 1749 1750 pid_t 1751 dowork(queuedir, id, forkflag, requeueflag, e) 1752 int queuedir; 1753 char *id; 1754 bool forkflag; 1755 bool requeueflag; 1756 register ENVELOPE *e; 1757 { 1758 register pid_t pid; 1759 1760 if (tTd(40, 1)) 1761 dprintf("dowork(%s/%s)\n", qid_printqueue(queuedir), id); 1762 1763 /* 1764 ** Fork for work. 1765 */ 1766 1767 if (forkflag) 1768 { 1769 /* 1770 ** Since the delivery may happen in a child and the 1771 ** parent does not wait, the parent may close the 1772 ** maps thereby removing any shared memory used by 1773 ** the map. Therefore, close the maps now so the 1774 ** child will dynamically open them if necessary. 1775 */ 1776 1777 closemaps(); 1778 1779 pid = fork(); 1780 if (pid < 0) 1781 { 1782 syserr("dowork: cannot fork"); 1783 return 0; 1784 } 1785 else if (pid > 0) 1786 { 1787 /* parent -- clean out connection cache */ 1788 mci_flush(FALSE, NULL); 1789 } 1790 else 1791 { 1792 /* child -- error messages to the transcript */ 1793 QuickAbort = OnlyOneError = FALSE; 1794 } 1795 } 1796 else 1797 { 1798 pid = 0; 1799 } 1800 1801 if (pid == 0) 1802 { 1803 /* 1804 ** CHILD 1805 ** Lock the control file to avoid duplicate deliveries. 1806 ** Then run the file as though we had just read it. 1807 ** We save an idea of the temporary name so we 1808 ** can recover on interrupt. 1809 */ 1810 1811 /* Reset global flags */ 1812 RestartRequest = NULL; 1813 ShutdownRequest = NULL; 1814 PendingSignal = 0; 1815 1816 /* set basic modes, etc. */ 1817 (void) alarm(0); 1818 clearstats(); 1819 clearenvelope(e, FALSE); 1820 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1821 set_delivery_mode(SM_DELIVER, e); 1822 e->e_errormode = EM_MAIL; 1823 e->e_id = id; 1824 e->e_queuedir = queuedir; 1825 GrabTo = UseErrorsTo = FALSE; 1826 ExitStat = EX_OK; 1827 if (forkflag) 1828 { 1829 disconnect(1, e); 1830 OpMode = MD_QUEUERUN; 1831 } 1832 sm_setproctitle(TRUE, e, "%s: from queue", qid_printname(e)); 1833 if (LogLevel > 76) 1834 sm_syslog(LOG_DEBUG, e->e_id, 1835 "dowork, pid=%d", 1836 (int) getpid()); 1837 1838 /* don't use the headers from sendmail.cf... */ 1839 e->e_header = NULL; 1840 1841 /* read the queue control file -- return if locked */ 1842 if (!readqf(e)) 1843 { 1844 if (tTd(40, 4) && e->e_id != NULL) 1845 dprintf("readqf(%s) failed\n", 1846 qid_printname(e)); 1847 e->e_id = NULL; 1848 if (forkflag) 1849 finis(FALSE, EX_OK); 1850 else 1851 return 0; 1852 } 1853 1854 e->e_flags |= EF_INQUEUE; 1855 eatheader(e, requeueflag); 1856 1857 if (requeueflag) 1858 queueup(e, FALSE); 1859 1860 /* do the delivery */ 1861 sendall(e, SM_DELIVER); 1862 1863 /* finish up and exit */ 1864 if (forkflag) 1865 finis(TRUE, ExitStat); 1866 else 1867 dropenvelope(e, TRUE); 1868 } 1869 e->e_id = NULL; 1870 return pid; 1871 } 1872 /* 1873 ** READQF -- read queue file and set up environment. 1874 ** 1875 ** Parameters: 1876 ** e -- the envelope of the job to run. 1877 ** 1878 ** Returns: 1879 ** TRUE if it successfully read the queue file. 1880 ** FALSE otherwise. 1881 ** 1882 ** Side Effects: 1883 ** The queue file is returned locked. 1884 */ 1885 1886 static bool 1887 readqf(e) 1888 register ENVELOPE *e; 1889 { 1890 register FILE *qfp; 1891 ADDRESS *ctladdr; 1892 struct stat st, stf; 1893 char *bp; 1894 int qfver = 0; 1895 long hdrsize = 0; 1896 register char *p; 1897 char *orcpt = NULL; 1898 bool nomore = FALSE; 1899 MODE_T qsafe; 1900 char qf[MAXPATHLEN]; 1901 char buf[MAXLINE]; 1902 1903 /* 1904 ** Read and process the file. 1905 */ 1906 1907 (void) strlcpy(qf, queuename(e, 'q'), sizeof qf); 1908 qfp = fopen(qf, "r+"); 1909 if (qfp == NULL) 1910 { 1911 int save_errno = errno; 1912 1913 if (tTd(40, 8)) 1914 dprintf("readqf(%s): fopen failure (%s)\n", 1915 qf, errstring(errno)); 1916 errno = save_errno; 1917 if (errno != ENOENT 1918 ) 1919 syserr("readqf: no control file %s", qf); 1920 return FALSE; 1921 } 1922 1923 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1924 { 1925 /* being processed by another queuer */ 1926 if (Verbose) 1927 printf("%s: locked\n", e->e_id); 1928 if (tTd(40, 8)) 1929 dprintf("%s: locked\n", e->e_id); 1930 if (LogLevel > 19) 1931 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 1932 (void) fclose(qfp); 1933 return FALSE; 1934 } 1935 1936 /* 1937 ** Prevent locking race condition. 1938 ** 1939 ** Process A: readqf(): qfp = fopen(qffile) 1940 ** Process B: queueup(): rename(tf, qf) 1941 ** Process B: unlocks(tf) 1942 ** Process A: lockfile(qf); 1943 ** 1944 ** Process A (us) has the old qf file (before the rename deleted 1945 ** the directory entry) and will be delivering based on old data. 1946 ** This can lead to multiple deliveries of the same recipients. 1947 ** 1948 ** Catch this by checking if the underlying qf file has changed 1949 ** *after* acquiring our lock and if so, act as though the file 1950 ** was still locked (i.e., just return like the lockfile() case 1951 ** above. 1952 */ 1953 1954 if (stat(qf, &stf) < 0 || 1955 fstat(fileno(qfp), &st) < 0) 1956 { 1957 /* must have been being processed by someone else */ 1958 if (tTd(40, 8)) 1959 dprintf("readqf(%s): [f]stat failure (%s)\n", 1960 qf, errstring(errno)); 1961 (void) fclose(qfp); 1962 return FALSE; 1963 } 1964 1965 if (st.st_nlink != stf.st_nlink || 1966 st.st_dev != stf.st_dev || 1967 st.st_ino != stf.st_ino || 1968 # if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ 1969 st.st_gen != stf.st_gen || 1970 # endif /* HAS_ST_GEN && 0 */ 1971 st.st_uid != stf.st_uid || 1972 st.st_gid != stf.st_gid || 1973 st.st_size != stf.st_size) 1974 { 1975 /* changed after opened */ 1976 if (Verbose) 1977 printf("%s: changed\n", e->e_id); 1978 if (tTd(40, 8)) 1979 dprintf("%s: changed\n", e->e_id); 1980 if (LogLevel > 19) 1981 sm_syslog(LOG_DEBUG, e->e_id, "changed"); 1982 (void) fclose(qfp); 1983 return FALSE; 1984 } 1985 1986 /* 1987 ** Check the queue file for plausibility to avoid attacks. 1988 */ 1989 1990 qsafe = S_IWOTH|S_IWGRP; 1991 #if _FFR_QUEUE_FILE_MODE 1992 if (bitset(S_IWGRP, QueueFileMode)) 1993 qsafe &= ~S_IWGRP; 1994 #endif /* _FFR_QUEUE_FILE_MODE */ 1995 1996 if ((st.st_uid != geteuid() && 1997 st.st_uid != TrustedUid && 1998 geteuid() != RealUid) || 1999 bitset(qsafe, st.st_mode)) 2000 { 2001 if (LogLevel > 0) 2002 { 2003 sm_syslog(LOG_ALERT, e->e_id, 2004 "bogus queue file, uid=%d, mode=%o", 2005 st.st_uid, st.st_mode); 2006 } 2007 if (tTd(40, 8)) 2008 dprintf("readqf(%s): bogus file\n", qf); 2009 loseqfile(e, "bogus file uid in mqueue"); 2010 (void) fclose(qfp); 2011 return FALSE; 2012 } 2013 2014 if (st.st_size == 0) 2015 { 2016 /* must be a bogus file -- if also old, just remove it */ 2017 if (st.st_ctime + 10 * 60 < curtime()) 2018 { 2019 (void) xunlink(queuename(e, 'd')); 2020 (void) xunlink(queuename(e, 'q')); 2021 } 2022 (void) fclose(qfp); 2023 return FALSE; 2024 } 2025 2026 if (st.st_nlink == 0) 2027 { 2028 /* 2029 ** Race condition -- we got a file just as it was being 2030 ** unlinked. Just assume it is zero length. 2031 */ 2032 2033 (void) fclose(qfp); 2034 return FALSE; 2035 } 2036 2037 /* good file -- save this lock */ 2038 e->e_lockfp = qfp; 2039 2040 /* do basic system initialization */ 2041 initsys(e); 2042 define('i', e->e_id, e); 2043 2044 LineNumber = 0; 2045 e->e_flags |= EF_GLOBALERRS; 2046 OpMode = MD_QUEUERUN; 2047 ctladdr = NULL; 2048 e->e_dfino = -1; 2049 e->e_msgsize = -1; 2050 # if _FFR_QUEUEDELAY 2051 e->e_queuealg = QD_LINEAR; 2052 e->e_queuedelay = (time_t) 0; 2053 # endif /* _FFR_QUEUEDELAY */ 2054 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 2055 { 2056 u_long qflags; 2057 ADDRESS *q; 2058 int mid; 2059 time_t now; 2060 auto char *ep; 2061 2062 if (tTd(40, 4)) 2063 dprintf("+++++ %s\n", bp); 2064 if (nomore) 2065 { 2066 /* hack attack */ 2067 syserr("SECURITY ALERT: extra data in qf: %s", bp); 2068 (void) fclose(qfp); 2069 loseqfile(e, "bogus queue line"); 2070 return FALSE; 2071 } 2072 switch (bp[0]) 2073 { 2074 case 'V': /* queue file version number */ 2075 qfver = atoi(&bp[1]); 2076 if (qfver <= QF_VERSION) 2077 break; 2078 syserr("Version number in qf (%d) greater than max (%d)", 2079 qfver, QF_VERSION); 2080 (void) fclose(qfp); 2081 loseqfile(e, "unsupported qf file version"); 2082 return FALSE; 2083 2084 case 'C': /* specify controlling user */ 2085 ctladdr = setctluser(&bp[1], qfver); 2086 break; 2087 2088 case 'Q': /* original recipient */ 2089 orcpt = newstr(&bp[1]); 2090 break; 2091 2092 case 'R': /* specify recipient */ 2093 p = bp; 2094 qflags = 0; 2095 if (qfver >= 1) 2096 { 2097 /* get flag bits */ 2098 while (*++p != '\0' && *p != ':') 2099 { 2100 switch (*p) 2101 { 2102 case 'N': 2103 qflags |= QHASNOTIFY; 2104 break; 2105 2106 case 'S': 2107 qflags |= QPINGONSUCCESS; 2108 break; 2109 2110 case 'F': 2111 qflags |= QPINGONFAILURE; 2112 break; 2113 2114 case 'D': 2115 qflags |= QPINGONDELAY; 2116 break; 2117 2118 case 'P': 2119 qflags |= QPRIMARY; 2120 break; 2121 2122 case 'A': 2123 if (ctladdr != NULL) 2124 ctladdr->q_flags |= QALIAS; 2125 break; 2126 } 2127 } 2128 } 2129 else 2130 qflags |= QPRIMARY; 2131 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 2132 if (q != NULL) 2133 { 2134 q->q_alias = ctladdr; 2135 if (qfver >= 1) 2136 q->q_flags &= ~Q_PINGFLAGS; 2137 q->q_flags |= qflags; 2138 q->q_orcpt = orcpt; 2139 (void) recipient(q, &e->e_sendqueue, 0, e); 2140 } 2141 orcpt = NULL; 2142 break; 2143 2144 case 'E': /* specify error recipient */ 2145 /* no longer used */ 2146 break; 2147 2148 case 'H': /* header */ 2149 (void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e); 2150 hdrsize += strlen(&bp[1]); 2151 break; 2152 2153 case 'L': /* Solaris Content-Length: */ 2154 case 'M': /* message */ 2155 /* ignore this; we want a new message next time */ 2156 break; 2157 2158 case 'S': /* sender */ 2159 setsender(newstr(&bp[1]), e, NULL, '\0', TRUE); 2160 break; 2161 2162 case 'B': /* body type */ 2163 e->e_bodytype = newstr(&bp[1]); 2164 break; 2165 2166 # if _FFR_SAVE_CHARSET 2167 case 'X': /* character set */ 2168 e->e_charset = newstr(&bp[1]); 2169 break; 2170 # endif /* _FFR_SAVE_CHARSET */ 2171 2172 case 'D': /* data file name */ 2173 /* obsolete -- ignore */ 2174 break; 2175 2176 case 'T': /* init time */ 2177 e->e_ctime = atol(&bp[1]); 2178 break; 2179 2180 case 'I': /* data file's inode number */ 2181 /* regenerated below */ 2182 break; 2183 2184 case 'K': /* time of last delivery attempt */ 2185 e->e_dtime = atol(&buf[1]); 2186 break; 2187 2188 # if _FFR_QUEUEDELAY 2189 case 'G': /* queue delay algorithm */ 2190 e->e_queuealg = atoi(&buf[1]); 2191 break; 2192 case 'Y': /* current delay */ 2193 e->e_queuedelay = (time_t) atol(&buf[1]); 2194 break; 2195 # endif /* _FFR_QUEUEDELAY */ 2196 2197 case 'N': /* number of delivery attempts */ 2198 e->e_ntries = atoi(&buf[1]); 2199 2200 /* if this has been tried recently, let it be */ 2201 now = curtime(); 2202 if (e->e_ntries > 0 && e->e_dtime <= now && 2203 now < e->e_dtime + queuedelay(e)) 2204 { 2205 char *howlong; 2206 2207 howlong = pintvl(now - e->e_dtime, TRUE); 2208 if (Verbose) 2209 printf("%s: too young (%s)\n", 2210 e->e_id, howlong); 2211 if (tTd(40, 8)) 2212 dprintf("%s: too young (%s)\n", 2213 e->e_id, howlong); 2214 if (LogLevel > 19) 2215 sm_syslog(LOG_DEBUG, e->e_id, 2216 "too young (%s)", 2217 howlong); 2218 e->e_id = NULL; 2219 unlockqueue(e); 2220 return FALSE; 2221 } 2222 define(macid("{ntries}", NULL), newstr(&buf[1]), e); 2223 2224 # if NAMED_BIND 2225 /* adjust BIND parameters immediately */ 2226 if (e->e_ntries == 0) 2227 { 2228 _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 2229 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 2230 } 2231 else 2232 { 2233 _res.retry = TimeOuts.res_retry[RES_TO_NORMAL]; 2234 _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL]; 2235 } 2236 # endif /* NAMED_BIND */ 2237 break; 2238 2239 case 'P': /* message priority */ 2240 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 2241 break; 2242 2243 case 'F': /* flag bits */ 2244 if (strncmp(bp, "From ", 5) == 0) 2245 { 2246 /* we are being spoofed! */ 2247 syserr("SECURITY ALERT: bogus qf line %s", bp); 2248 (void) fclose(qfp); 2249 loseqfile(e, "bogus queue line"); 2250 return FALSE; 2251 } 2252 for (p = &bp[1]; *p != '\0'; p++) 2253 { 2254 switch (*p) 2255 { 2256 case 'w': /* warning sent */ 2257 e->e_flags |= EF_WARNING; 2258 break; 2259 2260 case 'r': /* response */ 2261 e->e_flags |= EF_RESPONSE; 2262 break; 2263 2264 case '8': /* has 8 bit data */ 2265 e->e_flags |= EF_HAS8BIT; 2266 break; 2267 2268 case 'b': /* delete Bcc: header */ 2269 e->e_flags |= EF_DELETE_BCC; 2270 break; 2271 2272 case 'd': /* envelope has DSN RET= */ 2273 e->e_flags |= EF_RET_PARAM; 2274 break; 2275 2276 case 'n': /* don't return body */ 2277 e->e_flags |= EF_NO_BODY_RETN; 2278 break; 2279 } 2280 } 2281 break; 2282 2283 case 'Z': /* original envelope id from ESMTP */ 2284 e->e_envid = newstr(&bp[1]); 2285 define(macid("{dsn_envid}", NULL), newstr(&bp[1]), e); 2286 break; 2287 2288 case 'A': /* AUTH= parameter */ 2289 e->e_auth_param = newstr(&bp[1]); 2290 break; 2291 2292 case '$': /* define macro */ 2293 { 2294 char *p; 2295 2296 mid = macid(&bp[1], &ep); 2297 if (mid == 0) 2298 break; 2299 2300 p = newstr(ep); 2301 define(mid, p, e); 2302 2303 /* 2304 ** HACK ALERT: Unfortunately, 8.10 and 2305 ** 8.11 reused the ${if_addr} and 2306 ** ${if_family} macros for both the incoming 2307 ** interface address/family (getrequests()) 2308 ** and the outgoing interface address/family 2309 ** (makeconnection()). In order for D_BINDIF 2310 ** to work properly, have to preserve the 2311 ** incoming information in the queue file for 2312 ** later delivery attempts. The original 2313 ** information is stored in the envelope 2314 ** in readqf() so it can be stored in 2315 ** queueup_macros(). This should be fixed 2316 ** in 8.12. 2317 */ 2318 2319 if (strcmp(macname(mid), "if_addr") == 0) 2320 e->e_if_macros[EIF_ADDR] = p; 2321 } 2322 break; 2323 2324 case '.': /* terminate file */ 2325 nomore = TRUE; 2326 break; 2327 2328 default: 2329 syserr("readqf: %s: line %d: bad line \"%s\"", 2330 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 2331 (void) fclose(qfp); 2332 loseqfile(e, "unrecognized line"); 2333 return FALSE; 2334 } 2335 2336 if (bp != buf) 2337 sm_free(bp); 2338 } 2339 2340 /* 2341 ** If we haven't read any lines, this queue file is empty. 2342 ** Arrange to remove it without referencing any null pointers. 2343 */ 2344 2345 if (LineNumber == 0) 2346 { 2347 errno = 0; 2348 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 2349 return TRUE; 2350 } 2351 2352 /* possibly set ${dsn_ret} macro */ 2353 if (bitset(EF_RET_PARAM, e->e_flags)) 2354 { 2355 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 2356 define(macid("{dsn_ret}", NULL), "hdrs", e); 2357 else 2358 define(macid("{dsn_ret}", NULL), "full", e); 2359 } 2360 2361 /* 2362 ** Arrange to read the data file. 2363 */ 2364 2365 p = queuename(e, 'd'); 2366 e->e_dfp = fopen(p, "r"); 2367 if (e->e_dfp == NULL) 2368 { 2369 syserr("readqf: cannot open %s", p); 2370 } 2371 else 2372 { 2373 e->e_flags |= EF_HAS_DF; 2374 if (fstat(fileno(e->e_dfp), &st) >= 0) 2375 { 2376 e->e_msgsize = st.st_size + hdrsize; 2377 e->e_dfdev = st.st_dev; 2378 e->e_dfino = st.st_ino; 2379 } 2380 } 2381 2382 return TRUE; 2383 } 2384 /* 2385 ** PRTSTR -- print a string, "unprintable" characters are shown as \oct 2386 ** 2387 ** Parameters: 2388 ** s -- string to print 2389 ** ml -- maximum length of output 2390 ** 2391 ** Returns: 2392 ** none. 2393 ** 2394 ** Side Effects: 2395 ** Prints a string on stdout. 2396 */ 2397 2398 static void 2399 prtstr(s, ml) 2400 char *s; 2401 int ml; 2402 { 2403 char c; 2404 2405 if (s == NULL) 2406 return; 2407 while (ml-- > 0 && ((c = *s++) != '\0')) 2408 { 2409 if (c == '\\') 2410 { 2411 if (ml-- > 0) 2412 { 2413 putchar(c); 2414 putchar(c); 2415 } 2416 } 2417 else if (isascii(c) && isprint(c)) 2418 putchar(c); 2419 else 2420 { 2421 if ((ml -= 3) > 0) 2422 printf("\\%03o", c); 2423 } 2424 } 2425 } 2426 /* 2427 ** PRINTQUEUE -- print out a representation of the mail queue 2428 ** 2429 ** Parameters: 2430 ** none. 2431 ** 2432 ** Returns: 2433 ** none. 2434 ** 2435 ** Side Effects: 2436 ** Prints a listing of the mail queue on the standard output. 2437 */ 2438 2439 void 2440 printqueue() 2441 { 2442 int i, nrequests = 0; 2443 2444 for (i = 0; i < NumQueues; i++) 2445 { 2446 if (StopRequest) 2447 stop_sendmail(); 2448 nrequests += print_single_queue(i); 2449 } 2450 if (NumQueues > 1) 2451 printf("\t\tTotal Requests: %d\n", nrequests); 2452 } 2453 /* 2454 ** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue 2455 ** 2456 ** Parameters: 2457 ** queuedir -- queue directory 2458 ** 2459 ** Returns: 2460 ** number of entries 2461 ** 2462 ** Side Effects: 2463 ** Prints a listing of the mail queue on the standard output. 2464 */ 2465 2466 static int 2467 print_single_queue(queuedir) 2468 int queuedir; 2469 { 2470 register WORK *w; 2471 FILE *f; 2472 int nrequests; 2473 char qd[MAXPATHLEN]; 2474 char qddf[MAXPATHLEN]; 2475 char buf[MAXLINE]; 2476 2477 if (queuedir == NOQDIR) 2478 { 2479 (void) strlcpy(qd, ".", sizeof qd); 2480 (void) strlcpy(qddf, ".", sizeof qddf); 2481 } 2482 else 2483 { 2484 (void) snprintf(qd, sizeof qd, "%s%s", 2485 QPaths[queuedir].qp_name, 2486 (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); 2487 (void) snprintf(qddf, sizeof qddf, "%s%s", 2488 QPaths[queuedir].qp_name, 2489 (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); 2490 } 2491 2492 /* 2493 ** Check for permission to print the queue 2494 */ 2495 2496 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 2497 { 2498 struct stat st; 2499 # ifdef NGROUPS_MAX 2500 int n; 2501 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 2502 # endif /* NGROUPS_MAX */ 2503 2504 if (stat(qd, &st) < 0) 2505 { 2506 syserr("Cannot stat %s", qid_printqueue(queuedir)); 2507 return 0; 2508 } 2509 # ifdef NGROUPS_MAX 2510 n = NGROUPS_MAX; 2511 while (--n >= 0) 2512 { 2513 if (InitialGidSet[n] == st.st_gid) 2514 break; 2515 } 2516 if (n < 0 && RealGid != st.st_gid) 2517 # else /* NGROUPS_MAX */ 2518 if (RealGid != st.st_gid) 2519 # endif /* NGROUPS_MAX */ 2520 { 2521 usrerr("510 You are not permitted to see the queue"); 2522 setstat(EX_NOPERM); 2523 return 0; 2524 } 2525 } 2526 2527 /* 2528 ** Read and order the queue. 2529 */ 2530 2531 nrequests = orderq(queuedir, TRUE); 2532 2533 /* 2534 ** Print the work list that we have read. 2535 */ 2536 2537 /* first see if there is anything */ 2538 if (nrequests <= 0) 2539 { 2540 printf("%s is empty\n", qid_printqueue(queuedir)); 2541 return 0; 2542 } 2543 2544 CurrentLA = sm_getla(NULL); /* get load average */ 2545 2546 printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests, 2547 nrequests == 1 ? "" : "s"); 2548 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 2549 printf(", only %d printed", MaxQueueRun); 2550 if (Verbose) 2551 printf(")\n----Q-ID---- --Size-- -Priority- ---Q-Time--- ---------Sender/Recipient--------\n"); 2552 else 2553 printf(")\n----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 2554 for (w = WorkQ; w != NULL; w = w->w_next) 2555 { 2556 struct stat st; 2557 auto time_t submittime = 0; 2558 long dfsize; 2559 int flags = 0; 2560 int qfver; 2561 char statmsg[MAXLINE]; 2562 char bodytype[MAXNAME + 1]; 2563 char qf[MAXPATHLEN]; 2564 2565 if (StopRequest) 2566 stop_sendmail(); 2567 2568 printf("%12s", w->w_name + 2); 2569 (void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name); 2570 f = fopen(qf, "r"); 2571 if (f == NULL) 2572 { 2573 printf(" (job completed)\n"); 2574 errno = 0; 2575 continue; 2576 } 2577 w->w_name[0] = 'd'; 2578 (void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name); 2579 if (stat(qf, &st) >= 0) 2580 dfsize = st.st_size; 2581 else 2582 dfsize = -1; 2583 if (w->w_lock) 2584 printf("*"); 2585 else if (w->w_tooyoung) 2586 printf("-"); 2587 else if (shouldqueue(w->w_pri, w->w_ctime)) 2588 printf("X"); 2589 else 2590 printf(" "); 2591 errno = 0; 2592 2593 statmsg[0] = bodytype[0] = '\0'; 2594 qfver = 0; 2595 while (fgets(buf, sizeof buf, f) != NULL) 2596 { 2597 register int i; 2598 register char *p; 2599 2600 if (StopRequest) 2601 stop_sendmail(); 2602 2603 fixcrlf(buf, TRUE); 2604 switch (buf[0]) 2605 { 2606 case 'V': /* queue file version */ 2607 qfver = atoi(&buf[1]); 2608 break; 2609 2610 case 'M': /* error message */ 2611 if ((i = strlen(&buf[1])) >= sizeof statmsg) 2612 i = sizeof statmsg - 1; 2613 memmove(statmsg, &buf[1], i); 2614 statmsg[i] = '\0'; 2615 break; 2616 2617 case 'B': /* body type */ 2618 if ((i = strlen(&buf[1])) >= sizeof bodytype) 2619 i = sizeof bodytype - 1; 2620 memmove(bodytype, &buf[1], i); 2621 bodytype[i] = '\0'; 2622 break; 2623 2624 case 'S': /* sender name */ 2625 if (Verbose) 2626 { 2627 printf("%8ld %10ld%c%.12s ", 2628 dfsize, 2629 w->w_pri, 2630 bitset(EF_WARNING, flags) ? '+' : ' ', 2631 ctime(&submittime) + 4); 2632 prtstr(&buf[1], 78); 2633 } 2634 else 2635 { 2636 printf("%8ld %.16s ", dfsize, 2637 ctime(&submittime)); 2638 prtstr(&buf[1], 40); 2639 } 2640 if (statmsg[0] != '\0' || bodytype[0] != '\0') 2641 { 2642 printf("\n %10.10s", bodytype); 2643 if (statmsg[0] != '\0') 2644 printf(" (%.*s)", 2645 Verbose ? 100 : 60, 2646 statmsg); 2647 } 2648 break; 2649 2650 case 'C': /* controlling user */ 2651 if (Verbose) 2652 printf("\n\t\t\t\t (---%.74s---)", 2653 &buf[1]); 2654 break; 2655 2656 case 'R': /* recipient name */ 2657 p = &buf[1]; 2658 if (qfver >= 1) 2659 { 2660 p = strchr(p, ':'); 2661 if (p == NULL) 2662 break; 2663 p++; 2664 } 2665 if (Verbose) 2666 { 2667 printf("\n\t\t\t\t\t "); 2668 prtstr(p, 73); 2669 } 2670 else 2671 { 2672 printf("\n\t\t\t\t "); 2673 prtstr(p, 40); 2674 } 2675 break; 2676 2677 case 'T': /* creation time */ 2678 submittime = atol(&buf[1]); 2679 break; 2680 2681 case 'F': /* flag bits */ 2682 for (p = &buf[1]; *p != '\0'; p++) 2683 { 2684 switch (*p) 2685 { 2686 case 'w': 2687 flags |= EF_WARNING; 2688 break; 2689 } 2690 } 2691 } 2692 } 2693 if (submittime == (time_t) 0) 2694 printf(" (no control file)"); 2695 printf("\n"); 2696 (void) fclose(f); 2697 } 2698 return nrequests; 2699 } 2700 /* 2701 ** QUEUENAME -- build a file name in the queue directory for this envelope. 2702 ** 2703 ** Parameters: 2704 ** e -- envelope to build it in/from. 2705 ** type -- the file type, used as the first character 2706 ** of the file name. 2707 ** 2708 ** Returns: 2709 ** a pointer to the queue name (in a static buffer). 2710 ** 2711 ** Side Effects: 2712 ** If no id code is already assigned, queuename() will 2713 ** assign an id code with assign_queueid(). If no queue 2714 ** directory is assigned, one will be set with setnewqueue(). 2715 */ 2716 2717 char * 2718 queuename(e, type) 2719 register ENVELOPE *e; 2720 int type; 2721 { 2722 char *sub = ""; 2723 static char buf[MAXPATHLEN]; 2724 2725 /* Assign an ID if needed */ 2726 if (e->e_id == NULL) 2727 assign_queueid(e); 2728 2729 /* Assign a queue directory if needed */ 2730 if (e->e_queuedir == NOQDIR) 2731 setnewqueue(e); 2732 2733 if (e->e_queuedir == NOQDIR) 2734 (void) snprintf(buf, sizeof buf, "%cf%s", 2735 type, e->e_id); 2736 else 2737 { 2738 switch (type) 2739 { 2740 case 'd': 2741 if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs)) 2742 sub = "/df"; 2743 break; 2744 2745 case TEMPQF_LETTER: 2746 case 't': 2747 case LOSEQF_LETTER: 2748 case 'q': 2749 if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs)) 2750 sub = "/qf"; 2751 break; 2752 2753 case 'x': 2754 if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs)) 2755 sub = "/xf"; 2756 break; 2757 } 2758 2759 (void) snprintf(buf, sizeof buf, "%s%s/%cf%s", 2760 QPaths[e->e_queuedir].qp_name, 2761 sub, type, e->e_id); 2762 } 2763 2764 if (tTd(7, 2)) 2765 dprintf("queuename: %s\n", buf); 2766 return buf; 2767 } 2768 /* 2769 ** ASSIGN_QUEUEID -- assign a queue ID for this envelope. 2770 ** 2771 ** Assigns an id code if one does not already exist. 2772 ** This code assumes that nothing will remain in the queue for 2773 ** longer than 60 years. It is critical that files with the given 2774 ** name not already exist in the queue. 2775 ** Also initializes e_queuedir to NOQDIR. 2776 ** 2777 ** Parameters: 2778 ** e -- envelope to set it in. 2779 ** 2780 ** Returns: 2781 ** none. 2782 */ 2783 2784 static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"; 2785 # define QIC_LEN 60 2786 2787 void 2788 assign_queueid(e) 2789 register ENVELOPE *e; 2790 { 2791 pid_t pid = getpid(); 2792 static char cX = 0; 2793 static long random_offset; 2794 struct tm *tm; 2795 char idbuf[MAXQFNAME - 2]; 2796 2797 if (e->e_id != NULL) 2798 return; 2799 2800 /* see if we need to get a new base time/pid */ 2801 if (cX >= QIC_LEN || LastQueueTime == 0 || LastQueuePid != pid) 2802 { 2803 time_t then = LastQueueTime; 2804 2805 /* if the first time through, pick a random offset */ 2806 if (LastQueueTime == 0) 2807 random_offset = get_random(); 2808 2809 while ((LastQueueTime = curtime()) == then && 2810 LastQueuePid == pid) 2811 { 2812 (void) sleep(1); 2813 } 2814 LastQueuePid = getpid(); 2815 cX = 0; 2816 } 2817 if (tTd(7, 50)) 2818 dprintf("assign_queueid: random_offset = %ld (%d)\n", 2819 random_offset, (int)(cX + random_offset) % QIC_LEN); 2820 2821 tm = gmtime(&LastQueueTime); 2822 idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN]; 2823 idbuf[1] = QueueIdChars[tm->tm_mon]; 2824 idbuf[2] = QueueIdChars[tm->tm_mday]; 2825 idbuf[3] = QueueIdChars[tm->tm_hour]; 2826 idbuf[4] = QueueIdChars[tm->tm_min]; 2827 idbuf[5] = QueueIdChars[tm->tm_sec]; 2828 idbuf[6] = QueueIdChars[((int)cX++ + random_offset) % QIC_LEN]; 2829 (void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d", 2830 (int) LastQueuePid); 2831 e->e_id = newstr(idbuf); 2832 define('i', e->e_id, e); 2833 e->e_queuedir = NOQDIR; 2834 if (tTd(7, 1)) 2835 dprintf("assign_queueid: assigned id %s, e=%lx\n", 2836 e->e_id, (u_long) e); 2837 if (LogLevel > 93) 2838 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 2839 } 2840 /* 2841 ** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second 2842 ** 2843 ** Make sure one PID can't be used by two processes in any one second. 2844 ** 2845 ** If the system rotates PIDs fast enough, may get the 2846 ** same pid in the same second for two distinct processes. 2847 ** This will interfere with the queue file naming system. 2848 ** 2849 ** Parameters: 2850 ** none 2851 ** 2852 ** Returns: 2853 ** none 2854 */ 2855 void 2856 sync_queue_time() 2857 { 2858 # if FAST_PID_RECYCLE 2859 if (OpMode != MD_TEST && 2860 OpMode != MD_VERIFY && 2861 LastQueueTime > 0 && 2862 LastQueuePid == getpid() && 2863 curtime() == LastQueueTime) 2864 (void) sleep(1); 2865 # endif /* FAST_PID_RECYCLE */ 2866 } 2867 /* 2868 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 2869 ** 2870 ** Parameters: 2871 ** e -- the envelope to unlock. 2872 ** 2873 ** Returns: 2874 ** none 2875 ** 2876 ** Side Effects: 2877 ** unlocks the queue for `e'. 2878 */ 2879 2880 void 2881 unlockqueue(e) 2882 ENVELOPE *e; 2883 { 2884 if (tTd(51, 4)) 2885 dprintf("unlockqueue(%s)\n", 2886 e->e_id == NULL ? "NOQUEUE" : e->e_id); 2887 2888 2889 /* if there is a lock file in the envelope, close it */ 2890 if (e->e_lockfp != NULL) 2891 (void) fclose(e->e_lockfp); 2892 e->e_lockfp = NULL; 2893 2894 /* don't create a queue id if we don't already have one */ 2895 if (e->e_id == NULL) 2896 return; 2897 2898 /* remove the transcript */ 2899 if (LogLevel > 87) 2900 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 2901 if (!tTd(51, 104)) 2902 xunlink(queuename(e, 'x')); 2903 2904 } 2905 /* 2906 ** SETCTLUSER -- create a controlling address 2907 ** 2908 ** Create a fake "address" given only a local login name; this is 2909 ** used as a "controlling user" for future recipient addresses. 2910 ** 2911 ** Parameters: 2912 ** user -- the user name of the controlling user. 2913 ** qfver -- the version stamp of this qf file. 2914 ** 2915 ** Returns: 2916 ** An address descriptor for the controlling user. 2917 ** 2918 ** Side Effects: 2919 ** none. 2920 */ 2921 2922 static ADDRESS * 2923 setctluser(user, qfver) 2924 char *user; 2925 int qfver; 2926 { 2927 register ADDRESS *a; 2928 struct passwd *pw; 2929 char *p; 2930 2931 /* 2932 ** See if this clears our concept of controlling user. 2933 */ 2934 2935 if (user == NULL || *user == '\0') 2936 return NULL; 2937 2938 /* 2939 ** Set up addr fields for controlling user. 2940 */ 2941 2942 a = (ADDRESS *) xalloc(sizeof *a); 2943 memset((char *) a, '\0', sizeof *a); 2944 2945 if (*user == '\0') 2946 { 2947 p = NULL; 2948 a->q_user = newstr(DefUser); 2949 } 2950 else if (*user == ':') 2951 { 2952 p = &user[1]; 2953 a->q_user = newstr(p); 2954 } 2955 else 2956 { 2957 p = strtok(user, ":"); 2958 a->q_user = newstr(user); 2959 if (qfver >= 2) 2960 { 2961 if ((p = strtok(NULL, ":")) != NULL) 2962 a->q_uid = atoi(p); 2963 if ((p = strtok(NULL, ":")) != NULL) 2964 a->q_gid = atoi(p); 2965 if ((p = strtok(NULL, ":")) != NULL) 2966 { 2967 char *o; 2968 2969 a->q_flags |= QGOODUID; 2970 2971 /* if there is another ':': restore it */ 2972 if ((o = strtok(NULL, ":")) != NULL && o > p) 2973 o[-1] = ':'; 2974 } 2975 } 2976 else if ((pw = sm_getpwnam(user)) != NULL) 2977 { 2978 if (*pw->pw_dir == '\0') 2979 a->q_home = NULL; 2980 else if (strcmp(pw->pw_dir, "/") == 0) 2981 a->q_home = ""; 2982 else 2983 a->q_home = newstr(pw->pw_dir); 2984 a->q_uid = pw->pw_uid; 2985 a->q_gid = pw->pw_gid; 2986 a->q_flags |= QGOODUID; 2987 } 2988 } 2989 2990 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 2991 a->q_mailer = LocalMailer; 2992 if (p == NULL) 2993 a->q_paddr = newstr(a->q_user); 2994 else 2995 a->q_paddr = newstr(p); 2996 return a; 2997 } 2998 /* 2999 ** LOSEQFILE -- save the qf as Qf and try to let someone know 3000 ** 3001 ** Parameters: 3002 ** e -- the envelope (e->e_id will be used). 3003 ** why -- reported to whomever can hear. 3004 ** 3005 ** Returns: 3006 ** none. 3007 */ 3008 3009 void 3010 loseqfile(e, why) 3011 register ENVELOPE *e; 3012 char *why; 3013 { 3014 char *p; 3015 char buf[MAXPATHLEN]; 3016 3017 if (e == NULL || e->e_id == NULL) 3018 return; 3019 p = queuename(e, 'q'); 3020 if (strlen(p) >= (SIZE_T) sizeof buf) 3021 return; 3022 (void) strlcpy(buf, p, sizeof buf); 3023 p = queuename(e, LOSEQF_LETTER); 3024 if (rename(buf, p) < 0) 3025 syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); 3026 else if (LogLevel > 0) 3027 sm_syslog(LOG_ALERT, e->e_id, 3028 "Losing %s: %s", buf, why); 3029 } 3030 /* 3031 ** QID_PRINTNAME -- create externally printable version of queue id 3032 ** 3033 ** Parameters: 3034 ** e -- the envelope. 3035 ** 3036 ** Returns: 3037 ** a printable version 3038 */ 3039 3040 char * 3041 qid_printname(e) 3042 ENVELOPE *e; 3043 { 3044 char *id; 3045 static char idbuf[MAXQFNAME + 34]; 3046 3047 if (e == NULL) 3048 return ""; 3049 3050 if (e->e_id == NULL) 3051 id = ""; 3052 else 3053 id = e->e_id; 3054 3055 if (e->e_queuedir == NOQDIR) 3056 return id; 3057 3058 (void) snprintf(idbuf, sizeof idbuf, "%.32s/%s", 3059 QPaths[e->e_queuedir].qp_name, id); 3060 return idbuf; 3061 } 3062 /* 3063 ** QID_PRINTQUEUE -- create full version of queue directory for df files 3064 ** 3065 ** Parameters: 3066 ** queuedir -- the short version of the queue directory 3067 ** 3068 ** Returns: 3069 ** the full pathname to the queue (static) 3070 */ 3071 3072 char * 3073 qid_printqueue(queuedir) 3074 int queuedir; 3075 { 3076 char *subdir; 3077 static char dir[MAXPATHLEN]; 3078 3079 if (queuedir == NOQDIR) 3080 return QueueDir; 3081 3082 if (strcmp(QPaths[queuedir].qp_name, ".") == 0) 3083 subdir = NULL; 3084 else 3085 subdir = QPaths[queuedir].qp_name; 3086 3087 (void) snprintf(dir, sizeof dir, "%s%s%s%s", QueueDir, 3088 subdir == NULL ? "" : "/", 3089 subdir == NULL ? "" : subdir, 3090 (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); 3091 return dir; 3092 } 3093 /* 3094 ** SETNEWQUEUE -- Sets a new queue directory 3095 ** 3096 ** Assign a queue directory to an envelope and store the directory 3097 ** in e->e_queuedir. The queue is chosen at random. 3098 ** 3099 ** This routine may be improved in the future to allow for more 3100 ** elaborate queueing schemes. Suggestions and code contributions 3101 ** are welcome. 3102 ** 3103 ** Parameters: 3104 ** e -- envelope to assign a queue for. 3105 ** 3106 ** Returns: 3107 ** none. 3108 */ 3109 3110 void 3111 setnewqueue(e) 3112 ENVELOPE *e; 3113 { 3114 int idx; 3115 3116 if (tTd(41, 20)) 3117 dprintf("setnewqueue: called\n"); 3118 3119 if (e->e_queuedir != NOQDIR) 3120 { 3121 if (tTd(41, 20)) 3122 dprintf("setnewqueue: e_queuedir already assigned (%s)\n", 3123 qid_printqueue(e->e_queuedir)); 3124 return; 3125 } 3126 3127 if (NumQueues <= 1) 3128 idx = 0; 3129 else 3130 { 3131 #if RANDOMSHIFT 3132 /* lower bits are not random "enough", select others */ 3133 idx = (get_random() >> RANDOMSHIFT) % NumQueues; 3134 #else /* RANDOMSHIFT */ 3135 idx = get_random() % NumQueues; 3136 #endif /* RANDOMSHIFT */ 3137 if (tTd(41, 15)) 3138 dprintf("setnewqueue: get_random() %% %d = %d\n", 3139 NumQueues, idx); 3140 } 3141 3142 e->e_queuedir = idx; 3143 if (tTd(41, 3)) 3144 dprintf("setnewqueue: Assigned queue directory %s\n", 3145 qid_printqueue(e->e_queuedir)); 3146 } 3147 3148 /* 3149 ** CHKQDIR -- check a queue directory 3150 ** 3151 ** Parameters: 3152 ** name -- name of queue directory 3153 ** sff -- flags for safefile() 3154 ** 3155 ** Returns: 3156 ** is it a queue directory? 3157 */ 3158 3159 static bool 3160 chkqdir(name, sff) 3161 char *name; 3162 long sff; 3163 { 3164 struct stat statb; 3165 int i; 3166 3167 /* skip over . and .. directories */ 3168 if (name[0] == '.' && 3169 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) 3170 return FALSE; 3171 # if HASLSTAT 3172 if (lstat(name, &statb) < 0) 3173 # else /* HASLSTAT */ 3174 if (stat(name, &statb) < 0) 3175 # endif /* HASLSTAT */ 3176 { 3177 if (tTd(41, 2)) 3178 dprintf("multiqueue_cache: stat(\"%s\"): %s\n", 3179 name, errstring(errno)); 3180 return FALSE; 3181 } 3182 # if HASLSTAT 3183 if (S_ISLNK(statb.st_mode)) 3184 { 3185 /* 3186 ** For a symlink we need to make sure the 3187 ** target is a directory 3188 */ 3189 if (stat(name, &statb) < 0) 3190 { 3191 if (tTd(41, 2)) 3192 dprintf("multiqueue_cache: stat(\"%s\"): %s\n", 3193 name, errstring(errno)); 3194 return FALSE; 3195 } 3196 } 3197 # endif /* HASLSTAT */ 3198 3199 if (!S_ISDIR(statb.st_mode)) 3200 { 3201 if (tTd(41, 2)) 3202 dprintf("multiqueue_cache: \"%s\": Not a directory\n", 3203 name); 3204 return FALSE; 3205 } 3206 3207 /* Print a warning if unsafe (but still use it) */ 3208 i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0); 3209 if (i != 0 && tTd(41, 2)) 3210 dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 3211 name, errstring(i)); 3212 return TRUE; 3213 } 3214 3215 /* 3216 ** MULTIQUEUE_CACHE -- cache a list of paths to queues. 3217 ** 3218 ** Each potential queue is checked as the cache is built. 3219 ** Thereafter, each is blindly trusted. 3220 ** Note that we can be called again after a timeout to rebuild 3221 ** (although code for that is not ready yet). 3222 ** 3223 ** Parameters: 3224 ** none 3225 ** 3226 ** Returns: 3227 ** none 3228 */ 3229 3230 void 3231 multiqueue_cache() 3232 { 3233 register DIR *dp; 3234 register struct dirent *d; 3235 char *cp; 3236 int i, len; 3237 int slotsleft = 0; 3238 long sff = SFF_ANYFILE; 3239 char qpath[MAXPATHLEN]; 3240 char subdir[MAXPATHLEN]; 3241 3242 if (tTd(41, 20)) 3243 dprintf("multiqueue_cache: called\n"); 3244 3245 if (NumQueues != 0 && QPaths != NULL) 3246 { 3247 for (i = 0; i < NumQueues; i++) 3248 { 3249 if (QPaths[i].qp_name != NULL) 3250 sm_free(QPaths[i].qp_name); 3251 } 3252 sm_free((char *)QPaths); 3253 QPaths = NULL; 3254 NumQueues = 0; 3255 } 3256 3257 /* If running as root, allow safedirpath() checks to use privs */ 3258 if (RunAsUid == 0) 3259 sff |= SFF_ROOTOK; 3260 3261 (void) snprintf(qpath, sizeof qpath, "%s", QueueDir); 3262 len = strlen(qpath) - 1; 3263 cp = &qpath[len]; 3264 if (*cp == '*') 3265 { 3266 *cp = '\0'; 3267 if ((cp = strrchr(qpath, '/')) == NULL) 3268 { 3269 syserr("QueueDirectory: can not wildcard relative path"); 3270 if (tTd(41, 2)) 3271 dprintf("multiqueue_cache: \"%s\": Can not wildcard relative path.\n", 3272 qpath); 3273 ExitStat = EX_CONFIG; 3274 return; 3275 } 3276 if (cp == qpath) 3277 { 3278 /* 3279 ** Special case of top level wildcard, like /foo* 3280 */ 3281 3282 (void) snprintf(qpath + 1, sizeof qpath - 1, 3283 "%s", qpath); 3284 ++cp; 3285 } 3286 *(cp++) = '\0'; 3287 len = strlen(cp); 3288 3289 if (tTd(41, 2)) 3290 dprintf("multiqueue_cache: prefix=\"%s\"\n", cp); 3291 3292 QueueDir = newstr(qpath); 3293 3294 /* 3295 ** XXX Should probably wrap this whole loop in a timeout 3296 ** in case some wag decides to NFS mount the queues. 3297 */ 3298 3299 /* test path to get warning messages */ 3300 i= safedirpath(QueueDir, RunAsUid, RunAsGid, NULL, sff, 0, 0); 3301 if (i != 0 && tTd(41, 2)) 3302 dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 3303 QueueDir, errstring(i)); 3304 3305 if (chdir(QueueDir) < 0) 3306 { 3307 syserr("can not chdir(%s)", QueueDir); 3308 if (tTd(41, 2)) 3309 dprintf("multiqueue_cache: \"%s\": %s\n", 3310 qpath, errstring(errno)); 3311 ExitStat = EX_CONFIG; 3312 return; 3313 } 3314 3315 if ((dp = opendir(".")) == NULL) 3316 { 3317 syserr("can not opendir(%s)", QueueDir); 3318 if (tTd(41, 2)) 3319 dprintf("multiqueue_cache: opendir(\"%s\"): %s\n", 3320 QueueDir, errstring(errno)); 3321 ExitStat = EX_CONFIG; 3322 return; 3323 } 3324 while ((d = readdir(dp)) != NULL) 3325 { 3326 if (strncmp(d->d_name, cp, len) != 0) 3327 { 3328 if (tTd(41, 5)) 3329 dprintf("multiqueue_cache: \"%s\", skipped\n", 3330 d->d_name); 3331 continue; 3332 } 3333 if (!chkqdir(d->d_name, sff)) 3334 continue; 3335 3336 if (QPaths == NULL) 3337 { 3338 slotsleft = 20; 3339 QPaths = (QPATHS *)xalloc((sizeof *QPaths) * 3340 slotsleft); 3341 NumQueues = 0; 3342 } 3343 else if (slotsleft < 1) 3344 { 3345 QPaths = (QPATHS *)xrealloc((char *)QPaths, 3346 (sizeof *QPaths) * 3347 (NumQueues + 10)); 3348 if (QPaths == NULL) 3349 { 3350 (void) closedir(dp); 3351 return; 3352 } 3353 slotsleft += 10; 3354 } 3355 3356 /* check subdirs */ 3357 QPaths[NumQueues].qp_subdirs = QP_NOSUB; 3358 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3359 qpath, d->d_name, "qf"); 3360 if (chkqdir(subdir, sff)) 3361 QPaths[NumQueues].qp_subdirs |= QP_SUBQF; 3362 3363 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3364 qpath, d->d_name, "df"); 3365 if (chkqdir(subdir, sff)) 3366 QPaths[NumQueues].qp_subdirs |= QP_SUBDF; 3367 3368 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3369 qpath, d->d_name, "xf"); 3370 if (chkqdir(subdir, sff)) 3371 QPaths[NumQueues].qp_subdirs |= QP_SUBXF; 3372 3373 /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */ 3374 /* maybe even - 17 (subdirs) */ 3375 QPaths[NumQueues].qp_name = newstr(d->d_name); 3376 if (tTd(41, 2)) 3377 dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n", 3378 NumQueues, d->d_name, 3379 QPaths[NumQueues].qp_subdirs); 3380 NumQueues++; 3381 slotsleft--; 3382 } 3383 (void) closedir(dp); 3384 } 3385 if (NumQueues == 0) 3386 { 3387 if (*cp != '*' && tTd(41, 2)) 3388 dprintf("multiqueue_cache: \"%s\": No wildcard suffix character\n", 3389 QueueDir); 3390 QPaths = (QPATHS *)xalloc(sizeof *QPaths); 3391 QPaths[0].qp_name = newstr("."); 3392 QPaths[0].qp_subdirs = QP_NOSUB; 3393 NumQueues = 1; 3394 3395 /* test path to get warning messages */ 3396 (void) safedirpath(QueueDir, RunAsUid, RunAsGid, 3397 NULL, sff, 0, 0); 3398 if (chdir(QueueDir) < 0) 3399 { 3400 syserr("can not chdir(%s)", QueueDir); 3401 if (tTd(41, 2)) 3402 dprintf("multiqueue_cache: \"%s\": %s\n", 3403 QueueDir, errstring(errno)); 3404 ExitStat = EX_CONFIG; 3405 } 3406 3407 /* check subdirs */ 3408 (void) snprintf(subdir, sizeof subdir, "%s/qf", QueueDir); 3409 if (chkqdir(subdir, sff)) 3410 QPaths[0].qp_subdirs |= QP_SUBQF; 3411 3412 (void) snprintf(subdir, sizeof subdir, "%s/df", QueueDir); 3413 if (chkqdir(subdir, sff)) 3414 QPaths[0].qp_subdirs |= QP_SUBDF; 3415 3416 (void) snprintf(subdir, sizeof subdir, "%s/xf", QueueDir); 3417 if (chkqdir(subdir, sff)) 3418 QPaths[0].qp_subdirs |= QP_SUBXF; 3419 } 3420 } 3421 3422 # if 0 3423 /* 3424 ** HASHFQN -- calculate a hash value for a fully qualified host name 3425 ** 3426 ** Arguments: 3427 ** fqn -- an all lower-case host.domain string 3428 ** buckets -- the number of buckets (queue directories) 3429 ** 3430 ** Returns: 3431 ** a bucket number (signed integer) 3432 ** -1 on error 3433 ** 3434 ** Contributed by Exactis.com, Inc. 3435 */ 3436 3437 int 3438 hashfqn(fqn, buckets) 3439 register char *fqn; 3440 int buckets; 3441 { 3442 register char *p; 3443 register int h = 0, hash, cnt; 3444 # define WATERINC (1000) 3445 3446 if (fqn == NULL) 3447 return -1; 3448 3449 /* 3450 ** A variation on the gdb hash 3451 ** This is the best as of Feb 19, 1996 --bcx 3452 */ 3453 3454 p = fqn; 3455 h = 0x238F13AF * strlen(p); 3456 for (cnt = 0; *p != 0; ++p, cnt++) 3457 { 3458 h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF; 3459 } 3460 h = (1103515243 * h + 12345) & 0x7FFFFFFF; 3461 if (buckets < 2) 3462 hash = 0; 3463 else 3464 hash = (h % buckets); 3465 3466 return hash; 3467 } 3468 # endif /* 0 */ 3469 3470 # if _FFR_QUEUEDELAY 3471 /* 3472 ** QUEUEDELAY -- compute queue delay time 3473 ** 3474 ** Parameters: 3475 ** e -- the envelope to queue up. 3476 ** 3477 ** Returns: 3478 ** queue delay time 3479 ** 3480 ** Side Effects: 3481 ** may change e_queuedelay 3482 */ 3483 3484 static time_t 3485 queuedelay(e) 3486 ENVELOPE *e; 3487 { 3488 time_t qd; 3489 3490 if (e->e_queuealg == QD_EXP) 3491 { 3492 if (e->e_queuedelay == 0) 3493 e->e_queuedelay = QueueInitDelay; 3494 else 3495 { 3496 e->e_queuedelay *= 2; 3497 if (e->e_queuedelay > QueueMaxDelay) 3498 e->e_queuedelay = QueueMaxDelay; 3499 } 3500 qd = e->e_queuedelay; 3501 } 3502 else 3503 qd = MinQueueAge; 3504 return qd; 3505 } 3506 # endif /* _FFR_QUEUEDELAY */ 3507 #endif /* QUEUE */ 3508