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