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