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.44 2001/02/22 00:55:35 ca Exp $ (with queueing)"; 20 # else /* QUEUE */ 21 static char id[] = "@(#)$Id: queue.c,v 8.343.4.44 2001/02/22 00:55:35 ca 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 clrcontrol(); 797 proc_list_clear(); 798 799 /* Add parent process as first child item */ 800 proc_list_add(getpid(), "Queue runner child process", 801 PROC_QUEUE_CHILD); 802 (void) releasesignal(SIGCHLD); 803 (void) setsignal(SIGCHLD, SIG_DFL); 804 (void) setsignal(SIGHUP, intsig); 805 806 } 807 808 sm_setproctitle(TRUE, CurEnv, "running queue: %s", 809 qid_printqueue(queuedir)); 810 811 if (LogLevel > 69 || tTd(63, 99)) 812 sm_syslog(LOG_DEBUG, NOQID, 813 "runqueue %s, pid=%d, forkflag=%d", 814 qid_printqueue(queuedir), getpid(), forkflag); 815 816 /* 817 ** Release any resources used by the daemon code. 818 */ 819 820 # if DAEMON 821 clrdaemon(); 822 # endif /* DAEMON */ 823 824 /* force it to run expensive jobs */ 825 NoConnect = FALSE; 826 827 /* drop privileges */ 828 if (geteuid() == (uid_t) 0) 829 (void) drop_privileges(FALSE); 830 831 /* 832 ** Create ourselves an envelope 833 */ 834 835 CurEnv = &QueueEnvelope; 836 e = newenvelope(&QueueEnvelope, CurEnv); 837 e->e_flags = BlankEnvelope.e_flags; 838 e->e_parent = NULL; 839 840 /* make sure we have disconnected from parent */ 841 if (forkflag) 842 { 843 disconnect(1, e); 844 QuickAbort = FALSE; 845 } 846 847 /* 848 ** If we are running part of the queue, always ignore stored 849 ** host status. 850 */ 851 852 if (QueueLimitId != NULL || QueueLimitSender != NULL || 853 QueueLimitRecipient != NULL) 854 { 855 IgnoreHostStatus = TRUE; 856 MinQueueAge = 0; 857 } 858 859 /* 860 ** Start making passes through the queue. 861 ** First, read and sort the entire queue. 862 ** Then, process the work in that order. 863 ** But if you take too long, start over. 864 */ 865 866 /* order the existing work requests */ 867 njobs = orderq(queuedir, FALSE); 868 869 870 /* process them once at a time */ 871 while (WorkQ != NULL) 872 { 873 WORK *w = WorkQ; 874 875 WorkQ = WorkQ->w_next; 876 e->e_to = NULL; 877 878 /* 879 ** Ignore jobs that are too expensive for the moment. 880 ** 881 ** Get new load average every 30 seconds. 882 */ 883 884 now = curtime(); 885 if (current_la_time < now - 30) 886 { 887 CurrentLA = sm_getla(e); 888 current_la_time = now; 889 } 890 if (shouldqueue(WkRecipFact, current_la_time)) 891 { 892 char *msg = "Aborting queue run: load average too high"; 893 894 if (Verbose) 895 message("%s", msg); 896 if (LogLevel > 8) 897 sm_syslog(LOG_INFO, NOQID, 898 "runqueue: %s", 899 msg); 900 break; 901 } 902 sequenceno++; 903 if (shouldqueue(w->w_pri, w->w_ctime)) 904 { 905 if (Verbose) 906 message(""); 907 if (QueueSortOrder == QSO_BYPRIORITY) 908 { 909 if (Verbose) 910 message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue", 911 qid_printqueue(queuedir), 912 w->w_name + 2, 913 sequenceno, 914 njobs); 915 if (LogLevel > 8) 916 sm_syslog(LOG_INFO, NOQID, 917 "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)", 918 qid_printqueue(queuedir), 919 w->w_name + 2, 920 w->w_pri, 921 CurrentLA, 922 sequenceno, 923 njobs); 924 break; 925 } 926 else if (Verbose) 927 message("Skipping %s/%s (sequence %d of %d)", 928 qid_printqueue(queuedir), 929 w->w_name + 2, 930 sequenceno, njobs); 931 } 932 else 933 { 934 pid_t pid; 935 936 if (Verbose) 937 { 938 message(""); 939 message("Running %s/%s (sequence %d of %d)", 940 qid_printqueue(queuedir), 941 w->w_name + 2, 942 sequenceno, njobs); 943 } 944 if (tTd(63, 100)) 945 sm_syslog(LOG_DEBUG, NOQID, 946 "runqueue %s dowork(%s)", 947 qid_printqueue(queuedir), 948 w->w_name + 2); 949 950 pid = dowork(queuedir, w->w_name + 2, 951 ForkQueueRuns, FALSE, e); 952 errno = 0; 953 if (pid != 0) 954 (void) waitfor(pid); 955 } 956 free(w->w_name); 957 if (w->w_host) 958 free(w->w_host); 959 free((char *) w); 960 } 961 962 /* exit without the usual cleanup */ 963 e->e_id = NULL; 964 if (forkflag) 965 finis(TRUE, ExitStat); 966 /* NOTREACHED */ 967 return TRUE; 968 } 969 970 /* 971 ** RUNQUEUEEVENT -- stub for use in setevent 972 */ 973 974 static void 975 runqueueevent() 976 { 977 DoQueueRun = TRUE; 978 } 979 /* 980 ** ORDERQ -- order the work queue. 981 ** 982 ** Parameters: 983 ** queuedir -- the index of the queue directory. 984 ** doall -- if set, include everything in the queue (even 985 ** the jobs that cannot be run because the load 986 ** average is too high). Otherwise, exclude those 987 ** jobs. 988 ** 989 ** Returns: 990 ** The number of request in the queue (not necessarily 991 ** the number of requests in WorkQ however). 992 ** 993 ** Side Effects: 994 ** Sets WorkQ to the queue of available work, in order. 995 */ 996 997 # define NEED_P 001 998 # define NEED_T 002 999 # define NEED_R 004 1000 # define NEED_S 010 1001 # define NEED_H 020 1002 1003 static WORK *WorkList = NULL; 1004 static int WorkListSize = 0; 1005 1006 static int 1007 orderq(queuedir, doall) 1008 int queuedir; 1009 bool doall; 1010 { 1011 register struct dirent *d; 1012 register WORK *w; 1013 register char *p; 1014 DIR *f; 1015 register int i; 1016 int wn = -1; 1017 int wc; 1018 QUEUE_CHAR *check; 1019 char qd[MAXPATHLEN]; 1020 char qf[MAXPATHLEN]; 1021 1022 if (queuedir == NOQDIR) 1023 (void) strlcpy(qd, ".", sizeof qd); 1024 else 1025 (void) snprintf(qd, sizeof qd, "%s%s", 1026 QPaths[queuedir].qp_name, 1027 (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); 1028 1029 if (tTd(41, 1)) 1030 { 1031 dprintf("orderq:\n"); 1032 1033 check = QueueLimitId; 1034 while (check != NULL) 1035 { 1036 dprintf("\tQueueLimitId = %s\n", 1037 check->queue_match); 1038 check = check->queue_next; 1039 } 1040 1041 check = QueueLimitSender; 1042 while (check != NULL) 1043 { 1044 dprintf("\tQueueLimitSender = %s\n", 1045 check->queue_match); 1046 check = check->queue_next; 1047 } 1048 1049 check = QueueLimitRecipient; 1050 while (check != NULL) 1051 { 1052 dprintf("\tQueueLimitRecipient = %s\n", 1053 check->queue_match); 1054 check = check->queue_next; 1055 } 1056 } 1057 1058 /* clear out old WorkQ */ 1059 for (w = WorkQ; w != NULL; ) 1060 { 1061 register WORK *nw = w->w_next; 1062 1063 WorkQ = nw; 1064 free(w->w_name); 1065 if (w->w_host != NULL) 1066 free(w->w_host); 1067 free((char *) w); 1068 w = nw; 1069 } 1070 1071 /* open the queue directory */ 1072 f = opendir(qd); 1073 if (f == NULL) 1074 { 1075 syserr("orderq: cannot open \"%s\"", qid_printqueue(queuedir)); 1076 return 0; 1077 } 1078 1079 /* 1080 ** Read the work directory. 1081 */ 1082 1083 while ((d = readdir(f)) != NULL) 1084 { 1085 FILE *cf; 1086 int qfver = 0; 1087 char lbuf[MAXNAME + 1]; 1088 struct stat sbuf; 1089 1090 if (tTd(41, 50)) 1091 dprintf("orderq: checking %s\n", d->d_name); 1092 1093 /* is this an interesting entry? */ 1094 if (d->d_name[0] != 'q' || d->d_name[1] != 'f') 1095 continue; 1096 1097 if (strlen(d->d_name) >= MAXQFNAME) 1098 { 1099 if (Verbose) 1100 printf("orderq: %s too long, %d max characters\n", 1101 d->d_name, MAXQFNAME); 1102 if (LogLevel > 0) 1103 sm_syslog(LOG_ALERT, NOQID, 1104 "orderq: %s too long, %d max characters", 1105 d->d_name, MAXQFNAME); 1106 continue; 1107 } 1108 1109 check = QueueLimitId; 1110 while (check != NULL) 1111 { 1112 if (strcontainedin(check->queue_match, d->d_name)) 1113 break; 1114 else 1115 check = check->queue_next; 1116 } 1117 if (QueueLimitId != NULL && check == NULL) 1118 continue; 1119 1120 /* grow work list if necessary */ 1121 if (++wn >= MaxQueueRun && MaxQueueRun > 0) 1122 { 1123 if (wn == MaxQueueRun && LogLevel > 0) 1124 sm_syslog(LOG_WARNING, NOQID, 1125 "WorkList for %s maxed out at %d", 1126 qid_printqueue(queuedir), 1127 MaxQueueRun); 1128 continue; 1129 } 1130 if (wn >= WorkListSize) 1131 { 1132 grow_wlist(queuedir); 1133 if (wn >= WorkListSize) 1134 continue; 1135 } 1136 w = &WorkList[wn]; 1137 1138 (void) snprintf(qf, sizeof qf, "%s/%s", qd, d->d_name); 1139 if (stat(qf, &sbuf) < 0) 1140 { 1141 if (errno != ENOENT) 1142 sm_syslog(LOG_INFO, NOQID, 1143 "orderq: can't stat %s/%s", 1144 qid_printqueue(queuedir), d->d_name); 1145 wn--; 1146 continue; 1147 } 1148 if (!bitset(S_IFREG, sbuf.st_mode)) 1149 { 1150 /* Yikes! Skip it or we will hang on open! */ 1151 syserr("orderq: %s/%s is not a regular file", 1152 qid_printqueue(queuedir), d->d_name); 1153 wn--; 1154 continue; 1155 } 1156 1157 /* avoid work if possible */ 1158 if (QueueSortOrder == QSO_BYFILENAME && 1159 QueueLimitSender == NULL && 1160 QueueLimitRecipient == NULL) 1161 { 1162 w->w_name = newstr(d->d_name); 1163 w->w_host = NULL; 1164 w->w_lock = w->w_tooyoung = FALSE; 1165 w->w_pri = 0; 1166 w->w_ctime = 0; 1167 continue; 1168 } 1169 1170 /* open control file */ 1171 cf = fopen(qf, "r"); 1172 1173 if (cf == NULL) 1174 { 1175 /* this may be some random person sending hir msgs */ 1176 /* syserr("orderq: cannot open %s", cbuf); */ 1177 if (tTd(41, 2)) 1178 dprintf("orderq: cannot open %s: %s\n", 1179 d->d_name, errstring(errno)); 1180 errno = 0; 1181 wn--; 1182 continue; 1183 } 1184 w->w_name = newstr(d->d_name); 1185 w->w_host = NULL; 1186 w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB); 1187 w->w_tooyoung = FALSE; 1188 1189 /* make sure jobs in creation don't clog queue */ 1190 w->w_pri = 0x7fffffff; 1191 w->w_ctime = 0; 1192 1193 /* extract useful information */ 1194 i = NEED_P | NEED_T; 1195 if (QueueSortOrder == QSO_BYHOST) 1196 { 1197 /* need w_host set for host sort order */ 1198 i |= NEED_H; 1199 } 1200 if (QueueLimitSender != NULL) 1201 i |= NEED_S; 1202 if (QueueLimitRecipient != NULL) 1203 i |= NEED_R; 1204 while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) 1205 { 1206 int c; 1207 time_t age; 1208 1209 p = strchr(lbuf, '\n'); 1210 if (p != NULL) 1211 *p = '\0'; 1212 else 1213 { 1214 /* flush rest of overly long line */ 1215 while ((c = getc(cf)) != EOF && c != '\n') 1216 continue; 1217 } 1218 1219 switch (lbuf[0]) 1220 { 1221 case 'V': 1222 qfver = atoi(&lbuf[1]); 1223 break; 1224 1225 case 'P': 1226 w->w_pri = atol(&lbuf[1]); 1227 i &= ~NEED_P; 1228 break; 1229 1230 case 'T': 1231 w->w_ctime = atol(&lbuf[1]); 1232 i &= ~NEED_T; 1233 break; 1234 1235 case 'R': 1236 if (w->w_host == NULL && 1237 (p = strrchr(&lbuf[1], '@')) != NULL) 1238 { 1239 w->w_host = strrev(&p[1]); 1240 makelower(w->w_host); 1241 i &= ~NEED_H; 1242 } 1243 if (QueueLimitRecipient == NULL) 1244 { 1245 i &= ~NEED_R; 1246 break; 1247 } 1248 if (qfver > 0) 1249 { 1250 p = strchr(&lbuf[1], ':'); 1251 if (p == NULL) 1252 p = &lbuf[1]; 1253 } 1254 else 1255 p = &lbuf[1]; 1256 check = QueueLimitRecipient; 1257 while (check != NULL) 1258 { 1259 if (strcontainedin(check->queue_match, 1260 p)) 1261 break; 1262 else 1263 check = check->queue_next; 1264 } 1265 if (check != NULL) 1266 i &= ~NEED_R; 1267 break; 1268 1269 case 'S': 1270 check = QueueLimitSender; 1271 while (check != NULL) 1272 { 1273 if (strcontainedin(check->queue_match, 1274 &lbuf[1])) 1275 break; 1276 else 1277 check = check->queue_next; 1278 } 1279 if (check != NULL) 1280 i &= ~NEED_S; 1281 break; 1282 1283 case 'K': 1284 age = curtime() - (time_t) atol(&lbuf[1]); 1285 if (age >= 0 && MinQueueAge > 0 && 1286 age < MinQueueAge) 1287 w->w_tooyoung = TRUE; 1288 break; 1289 1290 case 'N': 1291 if (atol(&lbuf[1]) == 0) 1292 w->w_tooyoung = FALSE; 1293 break; 1294 1295 # if _FFR_QUEUEDELAY 1296 /* 1297 case 'G': 1298 queuealg = atoi(lbuf[1]); 1299 break; 1300 case 'Y': 1301 queuedelay = (time_t) atol(&lbuf[1]); 1302 break; 1303 */ 1304 # endif /* _FFR_QUEUEDELAY */ 1305 } 1306 } 1307 (void) fclose(cf); 1308 1309 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 1310 bitset(NEED_R|NEED_S, i)) 1311 { 1312 /* don't even bother sorting this job in */ 1313 if (tTd(41, 49)) 1314 dprintf("skipping %s (%x)\n", w->w_name, i); 1315 free(w->w_name); 1316 if (w->w_host) 1317 free(w->w_host); 1318 wn--; 1319 } 1320 } 1321 (void) closedir(f); 1322 wn++; 1323 1324 WorkQ = NULL; 1325 if (WorkList == NULL) 1326 return 0; 1327 wc = min(wn, WorkListSize); 1328 if (wc > MaxQueueRun && MaxQueueRun > 0) 1329 wc = MaxQueueRun; 1330 1331 if (QueueSortOrder == QSO_BYHOST) 1332 { 1333 /* 1334 ** Sort the work directory for the first time, 1335 ** based on host name, lock status, and priority. 1336 */ 1337 1338 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1); 1339 1340 /* 1341 ** If one message to host is locked, "lock" all messages 1342 ** to that host. 1343 */ 1344 1345 i = 0; 1346 while (i < wc) 1347 { 1348 if (!WorkList[i].w_lock) 1349 { 1350 i++; 1351 continue; 1352 } 1353 w = &WorkList[i]; 1354 while (++i < wc) 1355 { 1356 if (WorkList[i].w_host == NULL && 1357 w->w_host == NULL) 1358 WorkList[i].w_lock = TRUE; 1359 else if (WorkList[i].w_host != NULL && 1360 w->w_host != NULL && 1361 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0) 1362 WorkList[i].w_lock = TRUE; 1363 else 1364 break; 1365 } 1366 } 1367 1368 /* 1369 ** Sort the work directory for the second time, 1370 ** based on lock status, host name, and priority. 1371 */ 1372 1373 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2); 1374 } 1375 else if (QueueSortOrder == QSO_BYTIME) 1376 { 1377 /* 1378 ** Simple sort based on submission time only. 1379 */ 1380 1381 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); 1382 } 1383 else if (QueueSortOrder == QSO_BYFILENAME) 1384 { 1385 /* 1386 ** Sort based on qf filename. 1387 */ 1388 1389 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4); 1390 } 1391 else 1392 { 1393 /* 1394 ** Simple sort based on queue priority only. 1395 */ 1396 1397 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0); 1398 } 1399 1400 /* 1401 ** Convert the work list into canonical form. 1402 ** Should be turning it into a list of envelopes here perhaps. 1403 */ 1404 1405 for (i = wc; --i >= 0; ) 1406 { 1407 w = (WORK *) xalloc(sizeof *w); 1408 w->w_name = WorkList[i].w_name; 1409 w->w_host = WorkList[i].w_host; 1410 w->w_lock = WorkList[i].w_lock; 1411 w->w_tooyoung = WorkList[i].w_tooyoung; 1412 w->w_pri = WorkList[i].w_pri; 1413 w->w_ctime = WorkList[i].w_ctime; 1414 w->w_next = WorkQ; 1415 WorkQ = w; 1416 } 1417 if (WorkList != NULL) 1418 free(WorkList); 1419 WorkList = NULL; 1420 WorkListSize = 0; 1421 1422 if (tTd(40, 1)) 1423 { 1424 for (w = WorkQ; w != NULL; w = w->w_next) 1425 { 1426 if (w->w_host != NULL) 1427 dprintf("%22s: pri=%ld %s\n", 1428 w->w_name, w->w_pri, w->w_host); 1429 else 1430 dprintf("%32s: pri=%ld\n", 1431 w->w_name, w->w_pri); 1432 } 1433 } 1434 1435 return wn; 1436 } 1437 /* 1438 ** GROW_WLIST -- make the work list larger 1439 ** 1440 ** Parameters: 1441 ** queuedir -- the index for the queue directory. 1442 ** 1443 ** Returns: 1444 ** none. 1445 ** 1446 ** Side Effects: 1447 ** Adds another QUEUESEGSIZE entries to WorkList if possible. 1448 ** It can fail if there isn't enough memory, so WorkListSize 1449 ** should be checked again upon return. 1450 */ 1451 1452 static void 1453 grow_wlist(queuedir) 1454 int queuedir; 1455 { 1456 if (tTd(41, 1)) 1457 dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize); 1458 if (WorkList == NULL) 1459 { 1460 WorkList = (WORK *) xalloc((sizeof *WorkList) * 1461 (QUEUESEGSIZE + 1)); 1462 WorkListSize = QUEUESEGSIZE; 1463 } 1464 else 1465 { 1466 int newsize = WorkListSize + QUEUESEGSIZE; 1467 WORK *newlist = (WORK *) realloc((char *)WorkList, 1468 (unsigned)sizeof(WORK) * (newsize + 1)); 1469 1470 if (newlist != NULL) 1471 { 1472 WorkListSize = newsize; 1473 WorkList = newlist; 1474 if (LogLevel > 1) 1475 { 1476 sm_syslog(LOG_INFO, NOQID, 1477 "grew WorkList for %s to %d", 1478 qid_printqueue(queuedir), 1479 WorkListSize); 1480 } 1481 } 1482 else if (LogLevel > 0) 1483 { 1484 sm_syslog(LOG_ALERT, NOQID, 1485 "FAILED to grow WorkList for %s to %d", 1486 qid_printqueue(queuedir), newsize); 1487 } 1488 } 1489 if (tTd(41, 1)) 1490 dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize); 1491 } 1492 /* 1493 ** WORKCMPF0 -- simple priority-only compare function. 1494 ** 1495 ** Parameters: 1496 ** a -- the first argument. 1497 ** b -- the second argument. 1498 ** 1499 ** Returns: 1500 ** -1 if a < b 1501 ** 0 if a == b 1502 ** +1 if a > b 1503 ** 1504 ** Side Effects: 1505 ** none. 1506 */ 1507 1508 static int 1509 workcmpf0(a, b) 1510 register WORK *a; 1511 register WORK *b; 1512 { 1513 long pa = a->w_pri; 1514 long pb = b->w_pri; 1515 1516 if (pa == pb) 1517 return 0; 1518 else if (pa > pb) 1519 return 1; 1520 else 1521 return -1; 1522 } 1523 /* 1524 ** WORKCMPF1 -- first compare function for ordering work based on host name. 1525 ** 1526 ** Sorts on host name, lock status, and priority in that order. 1527 ** 1528 ** Parameters: 1529 ** a -- the first argument. 1530 ** b -- the second argument. 1531 ** 1532 ** Returns: 1533 ** <0 if a < b 1534 ** 0 if a == b 1535 ** >0 if a > b 1536 ** 1537 ** Side Effects: 1538 ** none. 1539 */ 1540 1541 static int 1542 workcmpf1(a, b) 1543 register WORK *a; 1544 register WORK *b; 1545 { 1546 int i; 1547 1548 /* host name */ 1549 if (a->w_host != NULL && b->w_host == NULL) 1550 return 1; 1551 else if (a->w_host == NULL && b->w_host != NULL) 1552 return -1; 1553 if (a->w_host != NULL && b->w_host != NULL && 1554 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1555 return i; 1556 1557 /* lock status */ 1558 if (a->w_lock != b->w_lock) 1559 return b->w_lock - a->w_lock; 1560 1561 /* job priority */ 1562 return workcmpf0(a, b); 1563 } 1564 /* 1565 ** WORKCMPF2 -- second compare function for ordering work based on host name. 1566 ** 1567 ** Sorts on lock status, host name, and priority in that order. 1568 ** 1569 ** Parameters: 1570 ** a -- the first argument. 1571 ** b -- the second argument. 1572 ** 1573 ** Returns: 1574 ** <0 if a < b 1575 ** 0 if a == b 1576 ** >0 if a > b 1577 ** 1578 ** Side Effects: 1579 ** none. 1580 */ 1581 1582 static int 1583 workcmpf2(a, b) 1584 register WORK *a; 1585 register WORK *b; 1586 { 1587 int i; 1588 1589 /* lock status */ 1590 if (a->w_lock != b->w_lock) 1591 return a->w_lock - b->w_lock; 1592 1593 /* host name */ 1594 if (a->w_host != NULL && b->w_host == NULL) 1595 return 1; 1596 else if (a->w_host == NULL && b->w_host != NULL) 1597 return -1; 1598 if (a->w_host != NULL && b->w_host != NULL && 1599 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 1600 return i; 1601 1602 /* job priority */ 1603 return workcmpf0(a, b); 1604 } 1605 /* 1606 ** WORKCMPF3 -- simple submission-time-only compare function. 1607 ** 1608 ** Parameters: 1609 ** a -- the first argument. 1610 ** b -- the second argument. 1611 ** 1612 ** Returns: 1613 ** -1 if a < b 1614 ** 0 if a == b 1615 ** +1 if a > b 1616 ** 1617 ** Side Effects: 1618 ** none. 1619 */ 1620 1621 static int 1622 workcmpf3(a, b) 1623 register WORK *a; 1624 register WORK *b; 1625 { 1626 if (a->w_ctime > b->w_ctime) 1627 return 1; 1628 else if (a->w_ctime < b->w_ctime) 1629 return -1; 1630 else 1631 return 0; 1632 } 1633 /* 1634 ** WORKCMPF4 -- compare based on file name 1635 ** 1636 ** Parameters: 1637 ** a -- the first argument. 1638 ** b -- the second argument. 1639 ** 1640 ** Returns: 1641 ** -1 if a < b 1642 ** 0 if a == b 1643 ** +1 if a > b 1644 ** 1645 ** Side Effects: 1646 ** none. 1647 */ 1648 1649 static int 1650 workcmpf4(a, b) 1651 register WORK *a; 1652 register WORK *b; 1653 { 1654 return strcmp(a->w_name, b->w_name); 1655 } 1656 /* 1657 ** STRREV -- reverse string 1658 ** 1659 ** Returns a pointer to a new string that is the reverse of 1660 ** the string pointed to by fwd. The space for the new 1661 ** string is obtained using xalloc(). 1662 ** 1663 ** Parameters: 1664 ** fwd -- the string to reverse. 1665 ** 1666 ** Returns: 1667 ** the reversed string. 1668 */ 1669 1670 static char * 1671 strrev(fwd) 1672 char *fwd; 1673 { 1674 char *rev = NULL; 1675 int len, cnt; 1676 1677 len = strlen(fwd); 1678 rev = xalloc(len + 1); 1679 for (cnt = 0; cnt < len; ++cnt) 1680 rev[cnt] = fwd[len - cnt - 1]; 1681 rev[len] = '\0'; 1682 return rev; 1683 } 1684 /* 1685 ** DOWORK -- do a work request. 1686 ** 1687 ** Parameters: 1688 ** queuedir -- the index of the queue directory for the job. 1689 ** id -- the ID of the job to run. 1690 ** forkflag -- if set, run this in background. 1691 ** requeueflag -- if set, reinstantiate the queue quickly. 1692 ** This is used when expanding aliases in the queue. 1693 ** If forkflag is also set, it doesn't wait for the 1694 ** child. 1695 ** e - the envelope in which to run it. 1696 ** 1697 ** Returns: 1698 ** process id of process that is running the queue job. 1699 ** 1700 ** Side Effects: 1701 ** The work request is satisfied if possible. 1702 */ 1703 1704 pid_t 1705 dowork(queuedir, id, forkflag, requeueflag, e) 1706 int queuedir; 1707 char *id; 1708 bool forkflag; 1709 bool requeueflag; 1710 register ENVELOPE *e; 1711 { 1712 register pid_t pid; 1713 1714 if (tTd(40, 1)) 1715 dprintf("dowork(%s/%s)\n", qid_printqueue(queuedir), id); 1716 1717 /* 1718 ** Fork for work. 1719 */ 1720 1721 if (forkflag) 1722 { 1723 /* 1724 ** Since the delivery may happen in a child and the 1725 ** parent does not wait, the parent may close the 1726 ** maps thereby removing any shared memory used by 1727 ** the map. Therefore, close the maps now so the 1728 ** child will dynamically open them if necessary. 1729 */ 1730 1731 closemaps(); 1732 1733 pid = fork(); 1734 if (pid < 0) 1735 { 1736 syserr("dowork: cannot fork"); 1737 return 0; 1738 } 1739 else if (pid > 0) 1740 { 1741 /* parent -- clean out connection cache */ 1742 mci_flush(FALSE, NULL); 1743 } 1744 else 1745 { 1746 /* child -- error messages to the transcript */ 1747 QuickAbort = OnlyOneError = FALSE; 1748 } 1749 } 1750 else 1751 { 1752 pid = 0; 1753 } 1754 1755 if (pid == 0) 1756 { 1757 /* 1758 ** CHILD 1759 ** Lock the control file to avoid duplicate deliveries. 1760 ** Then run the file as though we had just read it. 1761 ** We save an idea of the temporary name so we 1762 ** can recover on interrupt. 1763 */ 1764 1765 /* set basic modes, etc. */ 1766 (void) alarm(0); 1767 clearstats(); 1768 clearenvelope(e, FALSE); 1769 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 1770 set_delivery_mode(SM_DELIVER, e); 1771 e->e_errormode = EM_MAIL; 1772 e->e_id = id; 1773 e->e_queuedir = queuedir; 1774 GrabTo = UseErrorsTo = FALSE; 1775 ExitStat = EX_OK; 1776 if (forkflag) 1777 { 1778 disconnect(1, e); 1779 OpMode = MD_QUEUERUN; 1780 } 1781 sm_setproctitle(TRUE, e, "%s: from queue", qid_printname(e)); 1782 if (LogLevel > 76) 1783 sm_syslog(LOG_DEBUG, e->e_id, 1784 "dowork, pid=%d", 1785 getpid()); 1786 1787 /* don't use the headers from sendmail.cf... */ 1788 e->e_header = NULL; 1789 1790 /* read the queue control file -- return if locked */ 1791 if (!readqf(e)) 1792 { 1793 if (tTd(40, 4) && e->e_id != NULL) 1794 dprintf("readqf(%s) failed\n", 1795 qid_printname(e)); 1796 e->e_id = NULL; 1797 if (forkflag) 1798 finis(FALSE, EX_OK); 1799 else 1800 return 0; 1801 } 1802 1803 e->e_flags |= EF_INQUEUE; 1804 eatheader(e, requeueflag); 1805 1806 if (requeueflag) 1807 queueup(e, FALSE); 1808 1809 /* do the delivery */ 1810 sendall(e, SM_DELIVER); 1811 1812 /* finish up and exit */ 1813 if (forkflag) 1814 finis(TRUE, ExitStat); 1815 else 1816 dropenvelope(e, TRUE); 1817 } 1818 e->e_id = NULL; 1819 return pid; 1820 } 1821 /* 1822 ** READQF -- read queue file and set up environment. 1823 ** 1824 ** Parameters: 1825 ** e -- the envelope of the job to run. 1826 ** 1827 ** Returns: 1828 ** TRUE if it successfully read the queue file. 1829 ** FALSE otherwise. 1830 ** 1831 ** Side Effects: 1832 ** The queue file is returned locked. 1833 */ 1834 1835 static bool 1836 readqf(e) 1837 register ENVELOPE *e; 1838 { 1839 register FILE *qfp; 1840 ADDRESS *ctladdr; 1841 struct stat st; 1842 char *bp; 1843 int qfver = 0; 1844 long hdrsize = 0; 1845 register char *p; 1846 char *orcpt = NULL; 1847 bool nomore = FALSE; 1848 MODE_T qsafe; 1849 char qf[MAXPATHLEN]; 1850 char buf[MAXLINE]; 1851 1852 /* 1853 ** Read and process the file. 1854 */ 1855 1856 (void) strlcpy(qf, queuename(e, 'q'), sizeof qf); 1857 qfp = fopen(qf, "r+"); 1858 if (qfp == NULL) 1859 { 1860 int save_errno = errno; 1861 1862 if (tTd(40, 8)) 1863 dprintf("readqf(%s): fopen failure (%s)\n", 1864 qf, errstring(errno)); 1865 errno = save_errno; 1866 if (errno != ENOENT 1867 ) 1868 syserr("readqf: no control file %s", qf); 1869 return FALSE; 1870 } 1871 1872 if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB)) 1873 { 1874 /* being processed by another queuer */ 1875 if (Verbose) 1876 printf("%s: locked\n", e->e_id); 1877 if (tTd(40, 8)) 1878 dprintf("%s: locked\n", e->e_id); 1879 if (LogLevel > 19) 1880 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 1881 (void) fclose(qfp); 1882 return FALSE; 1883 } 1884 1885 /* 1886 ** Check the queue file for plausibility to avoid attacks. 1887 */ 1888 1889 if (fstat(fileno(qfp), &st) < 0) 1890 { 1891 /* must have been being processed by someone else */ 1892 if (tTd(40, 8)) 1893 dprintf("readqf(%s): fstat failure (%s)\n", 1894 qf, errstring(errno)); 1895 (void) fclose(qfp); 1896 return FALSE; 1897 } 1898 1899 qsafe = S_IWOTH|S_IWGRP; 1900 #if _FFR_QUEUE_FILE_MODE 1901 if (bitset(S_IWGRP, QueueFileMode)) 1902 qsafe &= ~S_IWGRP; 1903 #endif /* _FFR_QUEUE_FILE_MODE */ 1904 1905 if ((st.st_uid != geteuid() && 1906 st.st_uid != TrustedUid && 1907 geteuid() != RealUid) || 1908 bitset(qsafe, st.st_mode)) 1909 { 1910 if (LogLevel > 0) 1911 { 1912 sm_syslog(LOG_ALERT, e->e_id, 1913 "bogus queue file, uid=%d, mode=%o", 1914 st.st_uid, st.st_mode); 1915 } 1916 if (tTd(40, 8)) 1917 dprintf("readqf(%s): bogus file\n", qf); 1918 loseqfile(e, "bogus file uid in mqueue"); 1919 (void) fclose(qfp); 1920 return FALSE; 1921 } 1922 1923 if (st.st_size == 0) 1924 { 1925 /* must be a bogus file -- if also old, just remove it */ 1926 if (st.st_ctime + 10 * 60 < curtime()) 1927 { 1928 (void) xunlink(queuename(e, 'd')); 1929 (void) xunlink(queuename(e, 'q')); 1930 } 1931 (void) fclose(qfp); 1932 return FALSE; 1933 } 1934 1935 if (st.st_nlink == 0) 1936 { 1937 /* 1938 ** Race condition -- we got a file just as it was being 1939 ** unlinked. Just assume it is zero length. 1940 */ 1941 1942 (void) fclose(qfp); 1943 return FALSE; 1944 } 1945 1946 /* good file -- save this lock */ 1947 e->e_lockfp = qfp; 1948 1949 /* do basic system initialization */ 1950 initsys(e); 1951 define('i', e->e_id, e); 1952 1953 LineNumber = 0; 1954 e->e_flags |= EF_GLOBALERRS; 1955 OpMode = MD_QUEUERUN; 1956 ctladdr = NULL; 1957 e->e_dfino = -1; 1958 e->e_msgsize = -1; 1959 # if _FFR_QUEUEDELAY 1960 e->e_queuealg = QD_LINEAR; 1961 e->e_queuedelay = (time_t) 0; 1962 # endif /* _FFR_QUEUEDELAY */ 1963 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 1964 { 1965 u_long qflags; 1966 ADDRESS *q; 1967 int mid; 1968 time_t now; 1969 auto char *ep; 1970 1971 if (tTd(40, 4)) 1972 dprintf("+++++ %s\n", bp); 1973 if (nomore) 1974 { 1975 /* hack attack */ 1976 syserr("SECURITY ALERT: extra data in qf: %s", bp); 1977 (void) fclose(qfp); 1978 loseqfile(e, "bogus queue line"); 1979 return FALSE; 1980 } 1981 switch (bp[0]) 1982 { 1983 case 'V': /* queue file version number */ 1984 qfver = atoi(&bp[1]); 1985 if (qfver <= QF_VERSION) 1986 break; 1987 syserr("Version number in qf (%d) greater than max (%d)", 1988 qfver, QF_VERSION); 1989 (void) fclose(qfp); 1990 loseqfile(e, "unsupported qf file version"); 1991 return FALSE; 1992 1993 case 'C': /* specify controlling user */ 1994 ctladdr = setctluser(&bp[1], qfver); 1995 break; 1996 1997 case 'Q': /* original recipient */ 1998 orcpt = newstr(&bp[1]); 1999 break; 2000 2001 case 'R': /* specify recipient */ 2002 p = bp; 2003 qflags = 0; 2004 if (qfver >= 1) 2005 { 2006 /* get flag bits */ 2007 while (*++p != '\0' && *p != ':') 2008 { 2009 switch (*p) 2010 { 2011 case 'N': 2012 qflags |= QHASNOTIFY; 2013 break; 2014 2015 case 'S': 2016 qflags |= QPINGONSUCCESS; 2017 break; 2018 2019 case 'F': 2020 qflags |= QPINGONFAILURE; 2021 break; 2022 2023 case 'D': 2024 qflags |= QPINGONDELAY; 2025 break; 2026 2027 case 'P': 2028 qflags |= QPRIMARY; 2029 break; 2030 2031 case 'A': 2032 if (ctladdr != NULL) 2033 ctladdr->q_flags |= QALIAS; 2034 break; 2035 } 2036 } 2037 } 2038 else 2039 qflags |= QPRIMARY; 2040 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); 2041 if (q != NULL) 2042 { 2043 q->q_alias = ctladdr; 2044 if (qfver >= 1) 2045 q->q_flags &= ~Q_PINGFLAGS; 2046 q->q_flags |= qflags; 2047 q->q_orcpt = orcpt; 2048 (void) recipient(q, &e->e_sendqueue, 0, e); 2049 } 2050 orcpt = NULL; 2051 break; 2052 2053 case 'E': /* specify error recipient */ 2054 /* no longer used */ 2055 break; 2056 2057 case 'H': /* header */ 2058 (void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e); 2059 hdrsize += strlen(&bp[1]); 2060 break; 2061 2062 case 'L': /* Solaris Content-Length: */ 2063 case 'M': /* message */ 2064 /* ignore this; we want a new message next time */ 2065 break; 2066 2067 case 'S': /* sender */ 2068 setsender(newstr(&bp[1]), e, NULL, '\0', TRUE); 2069 break; 2070 2071 case 'B': /* body type */ 2072 e->e_bodytype = newstr(&bp[1]); 2073 break; 2074 2075 # if _FFR_SAVE_CHARSET 2076 case 'X': /* character set */ 2077 e->e_charset = newstr(&bp[1]); 2078 break; 2079 # endif /* _FFR_SAVE_CHARSET */ 2080 2081 case 'D': /* data file name */ 2082 /* obsolete -- ignore */ 2083 break; 2084 2085 case 'T': /* init time */ 2086 e->e_ctime = atol(&bp[1]); 2087 break; 2088 2089 case 'I': /* data file's inode number */ 2090 /* regenerated below */ 2091 break; 2092 2093 case 'K': /* time of last delivery attempt */ 2094 e->e_dtime = atol(&buf[1]); 2095 break; 2096 2097 # if _FFR_QUEUEDELAY 2098 case 'G': /* queue delay algorithm */ 2099 e->e_queuealg = atoi(&buf[1]); 2100 break; 2101 case 'Y': /* current delay */ 2102 e->e_queuedelay = (time_t) atol(&buf[1]); 2103 break; 2104 # endif /* _FFR_QUEUEDELAY */ 2105 2106 case 'N': /* number of delivery attempts */ 2107 e->e_ntries = atoi(&buf[1]); 2108 2109 /* if this has been tried recently, let it be */ 2110 now = curtime(); 2111 if (e->e_ntries > 0 && e->e_dtime <= now && 2112 now < e->e_dtime + queuedelay(e)) 2113 { 2114 char *howlong; 2115 2116 howlong = pintvl(now - e->e_dtime, TRUE); 2117 if (Verbose) 2118 printf("%s: too young (%s)\n", 2119 e->e_id, howlong); 2120 if (tTd(40, 8)) 2121 dprintf("%s: too young (%s)\n", 2122 e->e_id, howlong); 2123 if (LogLevel > 19) 2124 sm_syslog(LOG_DEBUG, e->e_id, 2125 "too young (%s)", 2126 howlong); 2127 e->e_id = NULL; 2128 unlockqueue(e); 2129 return FALSE; 2130 } 2131 define(macid("{ntries}", NULL), newstr(&buf[1]), e); 2132 2133 # if NAMED_BIND 2134 /* adjust BIND parameters immediately */ 2135 if (e->e_ntries == 0) 2136 { 2137 _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 2138 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 2139 } 2140 else 2141 { 2142 _res.retry = TimeOuts.res_retry[RES_TO_NORMAL]; 2143 _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL]; 2144 } 2145 # endif /* NAMED_BIND */ 2146 break; 2147 2148 case 'P': /* message priority */ 2149 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 2150 break; 2151 2152 case 'F': /* flag bits */ 2153 if (strncmp(bp, "From ", 5) == 0) 2154 { 2155 /* we are being spoofed! */ 2156 syserr("SECURITY ALERT: bogus qf line %s", bp); 2157 (void) fclose(qfp); 2158 loseqfile(e, "bogus queue line"); 2159 return FALSE; 2160 } 2161 for (p = &bp[1]; *p != '\0'; p++) 2162 { 2163 switch (*p) 2164 { 2165 case 'w': /* warning sent */ 2166 e->e_flags |= EF_WARNING; 2167 break; 2168 2169 case 'r': /* response */ 2170 e->e_flags |= EF_RESPONSE; 2171 break; 2172 2173 case '8': /* has 8 bit data */ 2174 e->e_flags |= EF_HAS8BIT; 2175 break; 2176 2177 case 'b': /* delete Bcc: header */ 2178 e->e_flags |= EF_DELETE_BCC; 2179 break; 2180 2181 case 'd': /* envelope has DSN RET= */ 2182 e->e_flags |= EF_RET_PARAM; 2183 break; 2184 2185 case 'n': /* don't return body */ 2186 e->e_flags |= EF_NO_BODY_RETN; 2187 break; 2188 } 2189 } 2190 break; 2191 2192 case 'Z': /* original envelope id from ESMTP */ 2193 e->e_envid = newstr(&bp[1]); 2194 define(macid("{dsn_envid}", NULL), newstr(&bp[1]), e); 2195 break; 2196 2197 case 'A': /* AUTH= parameter */ 2198 e->e_auth_param = newstr(&bp[1]); 2199 break; 2200 2201 case '$': /* define macro */ 2202 { 2203 char *p; 2204 2205 mid = macid(&bp[1], &ep); 2206 if (mid == 0) 2207 break; 2208 2209 p = newstr(ep); 2210 define(mid, p, e); 2211 2212 /* 2213 ** HACK ALERT: Unfortunately, 8.10 and 2214 ** 8.11 reused the ${if_addr} and 2215 ** ${if_family} macros for both the incoming 2216 ** interface address/family (getrequests()) 2217 ** and the outgoing interface address/family 2218 ** (makeconnection()). In order for D_BINDIF 2219 ** to work properly, have to preserve the 2220 ** incoming information in the queue file for 2221 ** later delivery attempts. The original 2222 ** information is stored in the envelope 2223 ** in readqf() so it can be stored in 2224 ** queueup_macros(). This should be fixed 2225 ** in 8.12. 2226 */ 2227 2228 if (strcmp(macname(mid), "if_addr") == 0) 2229 e->e_if_macros[EIF_ADDR] = p; 2230 } 2231 break; 2232 2233 case '.': /* terminate file */ 2234 nomore = TRUE; 2235 break; 2236 2237 default: 2238 syserr("readqf: %s: line %d: bad line \"%s\"", 2239 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 2240 (void) fclose(qfp); 2241 loseqfile(e, "unrecognized line"); 2242 return FALSE; 2243 } 2244 2245 if (bp != buf) 2246 free(bp); 2247 } 2248 2249 /* 2250 ** If we haven't read any lines, this queue file is empty. 2251 ** Arrange to remove it without referencing any null pointers. 2252 */ 2253 2254 if (LineNumber == 0) 2255 { 2256 errno = 0; 2257 e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE; 2258 return TRUE; 2259 } 2260 2261 /* possibly set ${dsn_ret} macro */ 2262 if (bitset(EF_RET_PARAM, e->e_flags)) 2263 { 2264 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 2265 define(macid("{dsn_ret}", NULL), "hdrs", e); 2266 else 2267 define(macid("{dsn_ret}", NULL), "full", e); 2268 } 2269 2270 /* 2271 ** Arrange to read the data file. 2272 */ 2273 2274 p = queuename(e, 'd'); 2275 e->e_dfp = fopen(p, "r"); 2276 if (e->e_dfp == NULL) 2277 { 2278 syserr("readqf: cannot open %s", p); 2279 } 2280 else 2281 { 2282 e->e_flags |= EF_HAS_DF; 2283 if (fstat(fileno(e->e_dfp), &st) >= 0) 2284 { 2285 e->e_msgsize = st.st_size + hdrsize; 2286 e->e_dfdev = st.st_dev; 2287 e->e_dfino = st.st_ino; 2288 } 2289 } 2290 2291 return TRUE; 2292 } 2293 /* 2294 ** PRTSTR -- print a string, "unprintable" characters are shown as \oct 2295 ** 2296 ** Parameters: 2297 ** s -- string to print 2298 ** ml -- maximum length of output 2299 ** 2300 ** Returns: 2301 ** none. 2302 ** 2303 ** Side Effects: 2304 ** Prints a string on stdout. 2305 */ 2306 2307 static void 2308 prtstr(s, ml) 2309 char *s; 2310 int ml; 2311 { 2312 char c; 2313 2314 if (s == NULL) 2315 return; 2316 while (ml-- > 0 && ((c = *s++) != '\0')) 2317 { 2318 if (c == '\\') 2319 { 2320 if (ml-- > 0) 2321 { 2322 putchar(c); 2323 putchar(c); 2324 } 2325 } 2326 else if (isascii(c) && isprint(c)) 2327 putchar(c); 2328 else 2329 { 2330 if ((ml -= 3) > 0) 2331 printf("\\%03o", c); 2332 } 2333 } 2334 } 2335 /* 2336 ** PRINTQUEUE -- print out a representation of the mail queue 2337 ** 2338 ** Parameters: 2339 ** none. 2340 ** 2341 ** Returns: 2342 ** none. 2343 ** 2344 ** Side Effects: 2345 ** Prints a listing of the mail queue on the standard output. 2346 */ 2347 2348 void 2349 printqueue() 2350 { 2351 int i, nrequests = 0; 2352 2353 for (i = 0; i < NumQueues; i++) 2354 nrequests += print_single_queue(i); 2355 if (NumQueues > 1) 2356 printf("\t\tTotal Requests: %d\n", nrequests); 2357 } 2358 /* 2359 ** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue 2360 ** 2361 ** Parameters: 2362 ** queuedir -- queue directory 2363 ** 2364 ** Returns: 2365 ** number of entries 2366 ** 2367 ** Side Effects: 2368 ** Prints a listing of the mail queue on the standard output. 2369 */ 2370 2371 static int 2372 print_single_queue(queuedir) 2373 int queuedir; 2374 { 2375 register WORK *w; 2376 FILE *f; 2377 int nrequests; 2378 char qd[MAXPATHLEN]; 2379 char qddf[MAXPATHLEN]; 2380 char buf[MAXLINE]; 2381 2382 if (queuedir == NOQDIR) 2383 { 2384 (void) strlcpy(qd, ".", sizeof qd); 2385 (void) strlcpy(qddf, ".", sizeof qddf); 2386 } 2387 else 2388 { 2389 (void) snprintf(qd, sizeof qd, "%s%s", 2390 QPaths[queuedir].qp_name, 2391 (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); 2392 (void) snprintf(qddf, sizeof qddf, "%s%s", 2393 QPaths[queuedir].qp_name, 2394 (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); 2395 } 2396 2397 /* 2398 ** Check for permission to print the queue 2399 */ 2400 2401 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 2402 { 2403 struct stat st; 2404 # ifdef NGROUPS_MAX 2405 int n; 2406 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 2407 # endif /* NGROUPS_MAX */ 2408 2409 if (stat(qd, &st) < 0) 2410 { 2411 syserr("Cannot stat %s", qid_printqueue(queuedir)); 2412 return 0; 2413 } 2414 # ifdef NGROUPS_MAX 2415 n = NGROUPS_MAX; 2416 while (--n >= 0) 2417 { 2418 if (InitialGidSet[n] == st.st_gid) 2419 break; 2420 } 2421 if (n < 0 && RealGid != st.st_gid) 2422 # else /* NGROUPS_MAX */ 2423 if (RealGid != st.st_gid) 2424 # endif /* NGROUPS_MAX */ 2425 { 2426 usrerr("510 You are not permitted to see the queue"); 2427 setstat(EX_NOPERM); 2428 return 0; 2429 } 2430 } 2431 2432 /* 2433 ** Read and order the queue. 2434 */ 2435 2436 nrequests = orderq(queuedir, TRUE); 2437 2438 /* 2439 ** Print the work list that we have read. 2440 */ 2441 2442 /* first see if there is anything */ 2443 if (nrequests <= 0) 2444 { 2445 printf("%s is empty\n", qid_printqueue(queuedir)); 2446 return 0; 2447 } 2448 2449 CurrentLA = sm_getla(NULL); /* get load average */ 2450 2451 printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests, 2452 nrequests == 1 ? "" : "s"); 2453 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 2454 printf(", only %d printed", MaxQueueRun); 2455 if (Verbose) 2456 printf(")\n----Q-ID---- --Size-- -Priority- ---Q-Time--- ---------Sender/Recipient--------\n"); 2457 else 2458 printf(")\n----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n"); 2459 for (w = WorkQ; w != NULL; w = w->w_next) 2460 { 2461 struct stat st; 2462 auto time_t submittime = 0; 2463 long dfsize; 2464 int flags = 0; 2465 int qfver; 2466 char statmsg[MAXLINE]; 2467 char bodytype[MAXNAME + 1]; 2468 char qf[MAXPATHLEN]; 2469 2470 printf("%12s", w->w_name + 2); 2471 (void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name); 2472 f = fopen(qf, "r"); 2473 if (f == NULL) 2474 { 2475 printf(" (job completed)\n"); 2476 errno = 0; 2477 continue; 2478 } 2479 w->w_name[0] = 'd'; 2480 (void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name); 2481 if (stat(qf, &st) >= 0) 2482 dfsize = st.st_size; 2483 else 2484 dfsize = -1; 2485 if (w->w_lock) 2486 printf("*"); 2487 else if (w->w_tooyoung) 2488 printf("-"); 2489 else if (shouldqueue(w->w_pri, w->w_ctime)) 2490 printf("X"); 2491 else 2492 printf(" "); 2493 errno = 0; 2494 2495 statmsg[0] = bodytype[0] = '\0'; 2496 qfver = 0; 2497 while (fgets(buf, sizeof buf, f) != NULL) 2498 { 2499 register int i; 2500 register char *p; 2501 2502 fixcrlf(buf, TRUE); 2503 switch (buf[0]) 2504 { 2505 case 'V': /* queue file version */ 2506 qfver = atoi(&buf[1]); 2507 break; 2508 2509 case 'M': /* error message */ 2510 if ((i = strlen(&buf[1])) >= sizeof statmsg) 2511 i = sizeof statmsg - 1; 2512 memmove(statmsg, &buf[1], i); 2513 statmsg[i] = '\0'; 2514 break; 2515 2516 case 'B': /* body type */ 2517 if ((i = strlen(&buf[1])) >= sizeof bodytype) 2518 i = sizeof bodytype - 1; 2519 memmove(bodytype, &buf[1], i); 2520 bodytype[i] = '\0'; 2521 break; 2522 2523 case 'S': /* sender name */ 2524 if (Verbose) 2525 { 2526 printf("%8ld %10ld%c%.12s ", 2527 dfsize, 2528 w->w_pri, 2529 bitset(EF_WARNING, flags) ? '+' : ' ', 2530 ctime(&submittime) + 4); 2531 prtstr(&buf[1], 78); 2532 } 2533 else 2534 { 2535 printf("%8ld %.16s ", dfsize, 2536 ctime(&submittime)); 2537 prtstr(&buf[1], 40); 2538 } 2539 if (statmsg[0] != '\0' || bodytype[0] != '\0') 2540 { 2541 printf("\n %10.10s", bodytype); 2542 if (statmsg[0] != '\0') 2543 printf(" (%.*s)", 2544 Verbose ? 100 : 60, 2545 statmsg); 2546 } 2547 break; 2548 2549 case 'C': /* controlling user */ 2550 if (Verbose) 2551 printf("\n\t\t\t\t (---%.74s---)", 2552 &buf[1]); 2553 break; 2554 2555 case 'R': /* recipient name */ 2556 p = &buf[1]; 2557 if (qfver >= 1) 2558 { 2559 p = strchr(p, ':'); 2560 if (p == NULL) 2561 break; 2562 p++; 2563 } 2564 if (Verbose) 2565 { 2566 printf("\n\t\t\t\t\t "); 2567 prtstr(p, 73); 2568 } 2569 else 2570 { 2571 printf("\n\t\t\t\t "); 2572 prtstr(p, 40); 2573 } 2574 break; 2575 2576 case 'T': /* creation time */ 2577 submittime = atol(&buf[1]); 2578 break; 2579 2580 case 'F': /* flag bits */ 2581 for (p = &buf[1]; *p != '\0'; p++) 2582 { 2583 switch (*p) 2584 { 2585 case 'w': 2586 flags |= EF_WARNING; 2587 break; 2588 } 2589 } 2590 } 2591 } 2592 if (submittime == (time_t) 0) 2593 printf(" (no control file)"); 2594 printf("\n"); 2595 (void) fclose(f); 2596 } 2597 return nrequests; 2598 } 2599 /* 2600 ** QUEUENAME -- build a file name in the queue directory for this envelope. 2601 ** 2602 ** Parameters: 2603 ** e -- envelope to build it in/from. 2604 ** type -- the file type, used as the first character 2605 ** of the file name. 2606 ** 2607 ** Returns: 2608 ** a pointer to the queue name (in a static buffer). 2609 ** 2610 ** Side Effects: 2611 ** If no id code is already assigned, queuename() will 2612 ** assign an id code with assign_queueid(). If no queue 2613 ** directory is assigned, one will be set with setnewqueue(). 2614 */ 2615 2616 char * 2617 queuename(e, type) 2618 register ENVELOPE *e; 2619 int type; 2620 { 2621 char *sub = ""; 2622 static char buf[MAXPATHLEN]; 2623 2624 /* Assign an ID if needed */ 2625 if (e->e_id == NULL) 2626 assign_queueid(e); 2627 2628 /* Assign a queue directory if needed */ 2629 if (e->e_queuedir == NOQDIR) 2630 setnewqueue(e); 2631 2632 if (e->e_queuedir == NOQDIR) 2633 (void) snprintf(buf, sizeof buf, "%cf%s", 2634 type, e->e_id); 2635 else 2636 { 2637 switch (type) 2638 { 2639 case 'd': 2640 if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs)) 2641 sub = "/df"; 2642 break; 2643 2644 case TEMPQF_LETTER: 2645 case 't': 2646 case LOSEQF_LETTER: 2647 case 'q': 2648 if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs)) 2649 sub = "/qf"; 2650 break; 2651 2652 case 'x': 2653 if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs)) 2654 sub = "/xf"; 2655 break; 2656 } 2657 2658 (void) snprintf(buf, sizeof buf, "%s%s/%cf%s", 2659 QPaths[e->e_queuedir].qp_name, 2660 sub, type, e->e_id); 2661 } 2662 2663 if (tTd(7, 2)) 2664 dprintf("queuename: %s\n", buf); 2665 return buf; 2666 } 2667 /* 2668 ** ASSIGN_QUEUEID -- assign a queue ID for this envelope. 2669 ** 2670 ** Assigns an id code if one does not already exist. 2671 ** This code assumes that nothing will remain in the queue for 2672 ** longer than 60 years. It is critical that files with the given 2673 ** name not already exist in the queue. 2674 ** Also initializes e_queuedir to NOQDIR. 2675 ** 2676 ** Parameters: 2677 ** e -- envelope to set it in. 2678 ** 2679 ** Returns: 2680 ** none. 2681 */ 2682 2683 static char Base60Code[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"; 2684 2685 void 2686 assign_queueid(e) 2687 register ENVELOPE *e; 2688 { 2689 pid_t pid = getpid(); 2690 static char cX = 0; 2691 static long random_offset; 2692 struct tm *tm; 2693 char idbuf[MAXQFNAME - 2]; 2694 2695 if (e->e_id != NULL) 2696 return; 2697 2698 /* see if we need to get a new base time/pid */ 2699 if (cX >= 60 || LastQueueTime == 0 || LastQueuePid != pid) 2700 { 2701 time_t then = LastQueueTime; 2702 2703 /* if the first time through, pick a random offset */ 2704 if (LastQueueTime == 0) 2705 random_offset = get_random(); 2706 2707 while ((LastQueueTime = curtime()) == then && 2708 LastQueuePid == pid) 2709 { 2710 (void) sleep(1); 2711 } 2712 LastQueuePid = getpid(); 2713 cX = 0; 2714 } 2715 if (tTd(7, 50)) 2716 dprintf("assign_queueid: random_offset = %ld (%d)\n", 2717 random_offset, (int)(cX + random_offset) % 60); 2718 2719 tm = gmtime(&LastQueueTime); 2720 idbuf[0] = Base60Code[tm->tm_year % 60]; 2721 idbuf[1] = Base60Code[tm->tm_mon]; 2722 idbuf[2] = Base60Code[tm->tm_mday]; 2723 idbuf[3] = Base60Code[tm->tm_hour]; 2724 idbuf[4] = Base60Code[tm->tm_min]; 2725 idbuf[5] = Base60Code[tm->tm_sec]; 2726 idbuf[6] = Base60Code[((int)cX++ + random_offset) % 60]; 2727 (void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d", 2728 (int) LastQueuePid); 2729 e->e_id = newstr(idbuf); 2730 define('i', e->e_id, e); 2731 e->e_queuedir = NOQDIR; 2732 if (tTd(7, 1)) 2733 dprintf("assign_queueid: assigned id %s, e=%lx\n", 2734 e->e_id, (u_long) e); 2735 if (LogLevel > 93) 2736 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 2737 } 2738 /* 2739 ** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second 2740 ** 2741 ** Make sure one PID can't be used by two processes in any one second. 2742 ** 2743 ** If the system rotates PIDs fast enough, may get the 2744 ** same pid in the same second for two distinct processes. 2745 ** This will interfere with the queue file naming system. 2746 ** 2747 ** Parameters: 2748 ** none 2749 ** 2750 ** Returns: 2751 ** none 2752 */ 2753 void 2754 sync_queue_time() 2755 { 2756 # if FAST_PID_RECYCLE 2757 if (OpMode != MD_TEST && 2758 OpMode != MD_VERIFY && 2759 LastQueueTime > 0 && 2760 LastQueuePid == getpid() && 2761 curtime() == LastQueueTime) 2762 (void) sleep(1); 2763 # endif /* FAST_PID_RECYCLE */ 2764 } 2765 /* 2766 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 2767 ** 2768 ** Parameters: 2769 ** e -- the envelope to unlock. 2770 ** 2771 ** Returns: 2772 ** none 2773 ** 2774 ** Side Effects: 2775 ** unlocks the queue for `e'. 2776 */ 2777 2778 void 2779 unlockqueue(e) 2780 ENVELOPE *e; 2781 { 2782 if (tTd(51, 4)) 2783 dprintf("unlockqueue(%s)\n", 2784 e->e_id == NULL ? "NOQUEUE" : e->e_id); 2785 2786 2787 /* if there is a lock file in the envelope, close it */ 2788 if (e->e_lockfp != NULL) 2789 (void) fclose(e->e_lockfp); 2790 e->e_lockfp = NULL; 2791 2792 /* don't create a queue id if we don't already have one */ 2793 if (e->e_id == NULL) 2794 return; 2795 2796 /* remove the transcript */ 2797 if (LogLevel > 87) 2798 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 2799 if (!tTd(51, 104)) 2800 xunlink(queuename(e, 'x')); 2801 2802 } 2803 /* 2804 ** SETCTLUSER -- create a controlling address 2805 ** 2806 ** Create a fake "address" given only a local login name; this is 2807 ** used as a "controlling user" for future recipient addresses. 2808 ** 2809 ** Parameters: 2810 ** user -- the user name of the controlling user. 2811 ** qfver -- the version stamp of this qf file. 2812 ** 2813 ** Returns: 2814 ** An address descriptor for the controlling user. 2815 ** 2816 ** Side Effects: 2817 ** none. 2818 */ 2819 2820 static ADDRESS * 2821 setctluser(user, qfver) 2822 char *user; 2823 int qfver; 2824 { 2825 register ADDRESS *a; 2826 struct passwd *pw; 2827 char *p; 2828 2829 /* 2830 ** See if this clears our concept of controlling user. 2831 */ 2832 2833 if (user == NULL || *user == '\0') 2834 return NULL; 2835 2836 /* 2837 ** Set up addr fields for controlling user. 2838 */ 2839 2840 a = (ADDRESS *) xalloc(sizeof *a); 2841 memset((char *) a, '\0', sizeof *a); 2842 2843 if (*user == '\0') 2844 { 2845 p = NULL; 2846 a->q_user = newstr(DefUser); 2847 } 2848 else if (*user == ':') 2849 { 2850 p = &user[1]; 2851 a->q_user = newstr(p); 2852 } 2853 else 2854 { 2855 p = strtok(user, ":"); 2856 a->q_user = newstr(user); 2857 if (qfver >= 2) 2858 { 2859 if ((p = strtok(NULL, ":")) != NULL) 2860 a->q_uid = atoi(p); 2861 if ((p = strtok(NULL, ":")) != NULL) 2862 a->q_gid = atoi(p); 2863 if ((p = strtok(NULL, ":")) != NULL) 2864 a->q_flags |= QGOODUID; 2865 } 2866 else if ((pw = sm_getpwnam(user)) != NULL) 2867 { 2868 if (*pw->pw_dir == '\0') 2869 a->q_home = NULL; 2870 else if (strcmp(pw->pw_dir, "/") == 0) 2871 a->q_home = ""; 2872 else 2873 a->q_home = newstr(pw->pw_dir); 2874 a->q_uid = pw->pw_uid; 2875 a->q_gid = pw->pw_gid; 2876 a->q_flags |= QGOODUID; 2877 } 2878 } 2879 2880 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 2881 a->q_mailer = LocalMailer; 2882 if (p == NULL) 2883 a->q_paddr = newstr(a->q_user); 2884 else 2885 a->q_paddr = newstr(p); 2886 return a; 2887 } 2888 /* 2889 ** LOSEQFILE -- save the qf as Qf and try to let someone know 2890 ** 2891 ** Parameters: 2892 ** e -- the envelope (e->e_id will be used). 2893 ** why -- reported to whomever can hear. 2894 ** 2895 ** Returns: 2896 ** none. 2897 */ 2898 2899 void 2900 loseqfile(e, why) 2901 register ENVELOPE *e; 2902 char *why; 2903 { 2904 char *p; 2905 char buf[MAXPATHLEN]; 2906 2907 if (e == NULL || e->e_id == NULL) 2908 return; 2909 p = queuename(e, 'q'); 2910 if (strlen(p) >= (SIZE_T) sizeof buf) 2911 return; 2912 (void) strlcpy(buf, p, sizeof buf); 2913 p = queuename(e, LOSEQF_LETTER); 2914 if (rename(buf, p) < 0) 2915 syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); 2916 else if (LogLevel > 0) 2917 sm_syslog(LOG_ALERT, e->e_id, 2918 "Losing %s: %s", buf, why); 2919 } 2920 /* 2921 ** QID_PRINTNAME -- create externally printable version of queue id 2922 ** 2923 ** Parameters: 2924 ** e -- the envelope. 2925 ** 2926 ** Returns: 2927 ** a printable version 2928 */ 2929 2930 char * 2931 qid_printname(e) 2932 ENVELOPE *e; 2933 { 2934 char *id; 2935 static char idbuf[MAXQFNAME + 34]; 2936 2937 if (e == NULL) 2938 return ""; 2939 2940 if (e->e_id == NULL) 2941 id = ""; 2942 else 2943 id = e->e_id; 2944 2945 if (e->e_queuedir == NOQDIR) 2946 return id; 2947 2948 (void) snprintf(idbuf, sizeof idbuf, "%.32s/%s", 2949 QPaths[e->e_queuedir].qp_name, id); 2950 return idbuf; 2951 } 2952 /* 2953 ** QID_PRINTQUEUE -- create full version of queue directory for df files 2954 ** 2955 ** Parameters: 2956 ** queuedir -- the short version of the queue directory 2957 ** 2958 ** Returns: 2959 ** the full pathname to the queue (static) 2960 */ 2961 2962 char * 2963 qid_printqueue(queuedir) 2964 int queuedir; 2965 { 2966 char *subdir; 2967 static char dir[MAXPATHLEN]; 2968 2969 if (queuedir == NOQDIR) 2970 return QueueDir; 2971 2972 if (strcmp(QPaths[queuedir].qp_name, ".") == 0) 2973 subdir = NULL; 2974 else 2975 subdir = QPaths[queuedir].qp_name; 2976 2977 (void) snprintf(dir, sizeof dir, "%s%s%s%s", QueueDir, 2978 subdir == NULL ? "" : "/", 2979 subdir == NULL ? "" : subdir, 2980 (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); 2981 return dir; 2982 } 2983 /* 2984 ** SETNEWQUEUE -- Sets a new queue directory 2985 ** 2986 ** Assign a queue directory to an envelope and store the directory 2987 ** in e->e_queuedir. The queue is chosen at random. 2988 ** 2989 ** This routine may be improved in the future to allow for more 2990 ** elaborate queueing schemes. Suggestions and code contributions 2991 ** are welcome. 2992 ** 2993 ** Parameters: 2994 ** e -- envelope to assign a queue for. 2995 ** 2996 ** Returns: 2997 ** none. 2998 */ 2999 3000 void 3001 setnewqueue(e) 3002 ENVELOPE *e; 3003 { 3004 int idx; 3005 3006 if (tTd(41, 20)) 3007 dprintf("setnewqueue: called\n"); 3008 3009 if (e->e_queuedir != NOQDIR) 3010 { 3011 if (tTd(41, 20)) 3012 dprintf("setnewqueue: e_queuedir already assigned (%s)\n", 3013 qid_printqueue(e->e_queuedir)); 3014 return; 3015 } 3016 3017 if (NumQueues == 1) 3018 idx = 0; 3019 else 3020 { 3021 #if RANDOMSHIFT 3022 /* lower bits are not random "enough", select others */ 3023 idx = (get_random() >> RANDOMSHIFT) % NumQueues; 3024 #else /* RANDOMSHIFT */ 3025 idx = get_random() % NumQueues; 3026 #endif /* RANDOMSHIFT */ 3027 if (tTd(41, 15)) 3028 dprintf("setnewqueue: get_random() %% %d = %d\n", 3029 NumQueues, idx); 3030 } 3031 3032 e->e_queuedir = idx; 3033 if (tTd(41, 3)) 3034 dprintf("setnewqueue: Assigned queue directory %s\n", 3035 qid_printqueue(e->e_queuedir)); 3036 } 3037 3038 /* 3039 ** CHKQDIR -- check a queue directory 3040 ** 3041 ** Parameters: 3042 ** name -- name of queue directory 3043 ** sff -- flags for safefile() 3044 ** 3045 ** Returns: 3046 ** is it a queue directory? 3047 */ 3048 3049 static bool 3050 chkqdir(name, sff) 3051 char *name; 3052 long sff; 3053 { 3054 struct stat statb; 3055 int i; 3056 3057 /* skip over . and .. directories */ 3058 if (name[0] == '.' && 3059 (name[1] == '\0' || (name[2] == '.' && name[3] == '\0'))) 3060 return FALSE; 3061 # if HASLSTAT 3062 if (lstat(name, &statb) < 0) 3063 # else /* HASLSTAT */ 3064 if (stat(name, &statb) < 0) 3065 # endif /* HASLSTAT */ 3066 { 3067 if (tTd(41, 2)) 3068 dprintf("multiqueue_cache: stat(\"%s\"): %s\n", 3069 name, errstring(errno)); 3070 return FALSE; 3071 } 3072 # if HASLSTAT 3073 if (S_ISLNK(statb.st_mode)) 3074 { 3075 /* 3076 ** For a symlink we need to make sure the 3077 ** target is a directory 3078 */ 3079 if (stat(name, &statb) < 0) 3080 { 3081 if (tTd(41, 2)) 3082 dprintf("multiqueue_cache: stat(\"%s\"): %s\n", 3083 name, errstring(errno)); 3084 return FALSE; 3085 } 3086 } 3087 # endif /* HASLSTAT */ 3088 3089 if (!S_ISDIR(statb.st_mode)) 3090 { 3091 if (tTd(41, 2)) 3092 dprintf("multiqueue_cache: \"%s\": Not a directory\n", 3093 name); 3094 return FALSE; 3095 } 3096 3097 /* Print a warning if unsafe (but still use it) */ 3098 i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0); 3099 if (i != 0 && tTd(41, 2)) 3100 dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 3101 name, errstring(i)); 3102 return TRUE; 3103 } 3104 3105 /* 3106 ** MULTIQUEUE_CACHE -- cache a list of paths to queues. 3107 ** 3108 ** Each potential queue is checked as the cache is built. 3109 ** Thereafter, each is blindly trusted. 3110 ** Note that we can be called again after a timeout to rebuild 3111 ** (although code for that is not ready yet). 3112 ** 3113 ** Parameters: 3114 ** none 3115 ** 3116 ** Returns: 3117 ** none 3118 */ 3119 3120 void 3121 multiqueue_cache() 3122 { 3123 register DIR *dp; 3124 register struct dirent *d; 3125 char *cp; 3126 int i, len; 3127 int slotsleft = 0; 3128 long sff = SFF_ANYFILE; 3129 char qpath[MAXPATHLEN]; 3130 char subdir[MAXPATHLEN]; 3131 3132 if (tTd(41, 20)) 3133 dprintf("multiqueue_cache: called\n"); 3134 3135 if (NumQueues != 0 && QPaths != NULL) 3136 { 3137 for (i = 0; i < NumQueues; i++) 3138 { 3139 if (QPaths[i].qp_name != NULL) 3140 (void) free(QPaths[i].qp_name); 3141 } 3142 (void) free((char *)QPaths); 3143 QPaths = NULL; 3144 NumQueues = 0; 3145 } 3146 3147 /* If running as root, allow safedirpath() checks to use privs */ 3148 if (RunAsUid == 0) 3149 sff |= SFF_ROOTOK; 3150 3151 (void) snprintf(qpath, sizeof qpath, "%s", QueueDir); 3152 len = strlen(qpath) - 1; 3153 cp = &qpath[len]; 3154 if (*cp == '*') 3155 { 3156 *cp = '\0'; 3157 if ((cp = strrchr(qpath, '/')) == NULL) 3158 { 3159 syserr("QueueDirectory: can not wildcard relative path"); 3160 if (tTd(41, 2)) 3161 dprintf("multiqueue_cache: \"%s\": Can not wildcard relative path.\n", 3162 qpath); 3163 ExitStat = EX_CONFIG; 3164 return; 3165 } 3166 if (cp == qpath) 3167 { 3168 /* 3169 ** Special case of top level wildcard, like /foo* 3170 */ 3171 3172 (void) snprintf(qpath + 1, sizeof qpath - 1, 3173 "%s", qpath); 3174 ++cp; 3175 } 3176 *(cp++) = '\0'; 3177 len = strlen(cp); 3178 3179 if (tTd(41, 2)) 3180 dprintf("multiqueue_cache: prefix=\"%s\"\n", cp); 3181 3182 QueueDir = newstr(qpath); 3183 3184 /* 3185 ** XXX Should probably wrap this whole loop in a timeout 3186 ** in case some wag decides to NFS mount the queues. 3187 */ 3188 3189 /* test path to get warning messages */ 3190 i= safedirpath(QueueDir, RunAsUid, RunAsGid, NULL, sff, 0, 0); 3191 if (i != 0 && tTd(41, 2)) 3192 dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 3193 QueueDir, errstring(i)); 3194 3195 if (chdir(QueueDir) < 0) 3196 { 3197 syserr("can not chdir(%s)", QueueDir); 3198 if (tTd(41, 2)) 3199 dprintf("multiqueue_cache: \"%s\": %s\n", 3200 qpath, errstring(errno)); 3201 ExitStat = EX_CONFIG; 3202 return; 3203 } 3204 3205 if ((dp = opendir(".")) == NULL) 3206 { 3207 syserr("can not opendir(%s)", QueueDir); 3208 if (tTd(41, 2)) 3209 dprintf("multiqueue_cache: opendir(\"%s\"): %s\n", 3210 QueueDir, errstring(errno)); 3211 ExitStat = EX_CONFIG; 3212 return; 3213 } 3214 while ((d = readdir(dp)) != NULL) 3215 { 3216 if (strncmp(d->d_name, cp, len) != 0) 3217 { 3218 if (tTd(41, 5)) 3219 dprintf("multiqueue_cache: \"%s\", skipped\n", 3220 d->d_name); 3221 continue; 3222 } 3223 if (!chkqdir(d->d_name, sff)) 3224 continue; 3225 3226 if (QPaths == NULL) 3227 { 3228 slotsleft = 20; 3229 QPaths = (QPATHS *)xalloc((sizeof *QPaths) * 3230 slotsleft); 3231 NumQueues = 0; 3232 } 3233 else if (slotsleft < 1) 3234 { 3235 QPaths = (QPATHS *)realloc((char *)QPaths, 3236 (sizeof *QPaths) * 3237 (NumQueues + 10)); 3238 if (QPaths == NULL) 3239 { 3240 (void) closedir(dp); 3241 return; 3242 } 3243 slotsleft += 10; 3244 } 3245 3246 /* check subdirs */ 3247 QPaths[NumQueues].qp_subdirs = QP_NOSUB; 3248 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3249 qpath, d->d_name, "qf"); 3250 if (chkqdir(subdir, sff)) 3251 QPaths[NumQueues].qp_subdirs |= QP_SUBQF; 3252 3253 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3254 qpath, d->d_name, "df"); 3255 if (chkqdir(subdir, sff)) 3256 QPaths[NumQueues].qp_subdirs |= QP_SUBDF; 3257 3258 (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", 3259 qpath, d->d_name, "xf"); 3260 if (chkqdir(subdir, sff)) 3261 QPaths[NumQueues].qp_subdirs |= QP_SUBXF; 3262 3263 /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */ 3264 /* maybe even - 17 (subdirs) */ 3265 QPaths[NumQueues].qp_name = newstr(d->d_name); 3266 if (tTd(41, 2)) 3267 dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n", 3268 NumQueues, d->d_name, 3269 QPaths[NumQueues].qp_subdirs); 3270 NumQueues++; 3271 slotsleft--; 3272 } 3273 (void) closedir(dp); 3274 } 3275 if (NumQueues == 0) 3276 { 3277 if (*cp != '*' && tTd(41, 2)) 3278 dprintf("multiqueue_cache: \"%s\": No wildcard suffix character\n", 3279 QueueDir); 3280 QPaths = (QPATHS *)xalloc(sizeof *QPaths); 3281 QPaths[0].qp_name = newstr("."); 3282 QPaths[0].qp_subdirs = QP_NOSUB; 3283 NumQueues = 1; 3284 3285 /* test path to get warning messages */ 3286 (void) safedirpath(QueueDir, RunAsUid, RunAsGid, 3287 NULL, sff, 0, 0); 3288 if (chdir(QueueDir) < 0) 3289 { 3290 syserr("can not chdir(%s)", QueueDir); 3291 if (tTd(41, 2)) 3292 dprintf("multiqueue_cache: \"%s\": %s\n", 3293 QueueDir, errstring(errno)); 3294 ExitStat = EX_CONFIG; 3295 } 3296 3297 /* check subdirs */ 3298 (void) snprintf(subdir, sizeof subdir, "%s/qf", QueueDir); 3299 if (chkqdir(subdir, sff)) 3300 QPaths[0].qp_subdirs |= QP_SUBQF; 3301 3302 (void) snprintf(subdir, sizeof subdir, "%s/df", QueueDir); 3303 if (chkqdir(subdir, sff)) 3304 QPaths[0].qp_subdirs |= QP_SUBDF; 3305 3306 (void) snprintf(subdir, sizeof subdir, "%s/xf", QueueDir); 3307 if (chkqdir(subdir, sff)) 3308 QPaths[0].qp_subdirs |= QP_SUBXF; 3309 } 3310 } 3311 3312 # if 0 3313 /* 3314 ** HASHFQN -- calculate a hash value for a fully qualified host name 3315 ** 3316 ** Arguments: 3317 ** fqn -- an all lower-case host.domain string 3318 ** buckets -- the number of buckets (queue directories) 3319 ** 3320 ** Returns: 3321 ** a bucket number (signed integer) 3322 ** -1 on error 3323 ** 3324 ** Contributed by Exactis.com, Inc. 3325 */ 3326 3327 int 3328 hashfqn(fqn, buckets) 3329 register char *fqn; 3330 int buckets; 3331 { 3332 register char *p; 3333 register int h = 0, hash, cnt; 3334 # define WATERINC (1000) 3335 3336 if (fqn == NULL) 3337 return -1; 3338 3339 /* 3340 ** A variation on the gdb hash 3341 ** This is the best as of Feb 19, 1996 --bcx 3342 */ 3343 3344 p = fqn; 3345 h = 0x238F13AF * strlen(p); 3346 for (cnt = 0; *p != 0; ++p, cnt++) 3347 { 3348 h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF; 3349 } 3350 h = (1103515243 * h + 12345) & 0x7FFFFFFF; 3351 if (buckets < 2) 3352 hash = 0; 3353 else 3354 hash = (h % buckets); 3355 3356 return hash; 3357 } 3358 # endif /* 0 */ 3359 3360 # if _FFR_QUEUEDELAY 3361 /* 3362 ** QUEUEDELAY -- compute queue delay time 3363 ** 3364 ** Parameters: 3365 ** e -- the envelope to queue up. 3366 ** 3367 ** Returns: 3368 ** queue delay time 3369 ** 3370 ** Side Effects: 3371 ** may change e_queuedelay 3372 */ 3373 3374 static time_t 3375 queuedelay(e) 3376 ENVELOPE *e; 3377 { 3378 time_t qd; 3379 3380 if (e->e_queuealg == QD_EXP) 3381 { 3382 if (e->e_queuedelay == 0) 3383 e->e_queuedelay = QueueInitDelay; 3384 else 3385 { 3386 e->e_queuedelay *= 2; 3387 if (e->e_queuedelay > QueueMaxDelay) 3388 e->e_queuedelay = QueueMaxDelay; 3389 } 3390 qd = e->e_queuedelay; 3391 } 3392 else 3393 qd = MinQueueAge; 3394 return qd; 3395 } 3396 # endif /* _FFR_QUEUEDELAY */ 3397 #endif /* QUEUE */ 3398