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