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