queue.c revision 141858
1/* 2 * Copyright (c) 1998-2004 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#include <sendmail.h> 15 16SM_RCSID("@(#)$Id: queue.c,v 8.939 2004/08/03 19:57:23 ca Exp $") 17 18#include <dirent.h> 19 20# define RELEASE_QUEUE (void) 0 21# define ST_INODE(st) (st).st_ino 22 23# define sm_file_exists(errno) ((errno) == EEXIST) 24 25# if HASFLOCK && defined(O_EXLOCK) 26# define SM_OPEN_EXLOCK 1 27# define TF_OPEN_FLAGS (O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK) 28# else /* HASFLOCK && defined(O_EXLOCK) */ 29# define TF_OPEN_FLAGS (O_CREAT|O_WRONLY|O_EXCL) 30# endif /* HASFLOCK && defined(O_EXLOCK) */ 31 32#ifndef SM_OPEN_EXLOCK 33# define SM_OPEN_EXLOCK 0 34#endif /* ! SM_OPEN_EXLOCK */ 35 36/* 37** Historical notes: 38** QF_VERSION == 4 was sendmail 8.10/8.11 without _FFR_QUEUEDELAY 39** QF_VERSION == 5 was sendmail 8.10/8.11 with _FFR_QUEUEDELAY 40** QF_VERSION == 6 was sendmail 8.12 without _FFR_QUEUEDELAY 41** QF_VERSION == 7 was sendmail 8.12 with _FFR_QUEUEDELAY 42** QF_VERSION == 8 is sendmail 8.13 43*/ 44 45#define QF_VERSION 8 /* version number of this queue format */ 46 47static char queue_letter __P((ENVELOPE *, int)); 48static bool quarantine_queue_item __P((int, int, ENVELOPE *, char *)); 49 50/* Naming convention: qgrp: index of queue group, qg: QUEUEGROUP */ 51 52/* 53** Work queue. 54*/ 55 56struct work 57{ 58 char *w_name; /* name of control file */ 59 char *w_host; /* name of recipient host */ 60 bool w_lock; /* is message locked? */ 61 bool w_tooyoung; /* is it too young to run? */ 62 long w_pri; /* priority of message, see below */ 63 time_t w_ctime; /* creation time */ 64 time_t w_mtime; /* modification time */ 65 int w_qgrp; /* queue group located in */ 66 int w_qdir; /* queue directory located in */ 67 struct work *w_next; /* next in queue */ 68}; 69 70typedef struct work WORK; 71 72static WORK *WorkQ; /* queue of things to be done */ 73static int NumWorkGroups; /* number of work groups */ 74static time_t Current_LA_time = 0; 75 76/* Get new load average every 30 seconds. */ 77#define GET_NEW_LA_TIME 30 78 79#define SM_GET_LA(now) \ 80 do \ 81 { \ 82 now = curtime(); \ 83 if (Current_LA_time < now - GET_NEW_LA_TIME) \ 84 { \ 85 sm_getla(); \ 86 Current_LA_time = now; \ 87 } \ 88 } while (0) 89 90/* 91** DoQueueRun indicates that a queue run is needed. 92** Notice: DoQueueRun is modified in a signal handler! 93*/ 94 95static bool volatile DoQueueRun; /* non-interrupt time queue run needed */ 96 97/* 98** Work group definition structure. 99** Each work group contains one or more queue groups. This is done 100** to manage the number of queue group runners active at the same time 101** to be within the constraints of MaxQueueChildren (if it is set). 102** The number of queue groups that can be run on the next work run 103** is kept track of. The queue groups are run in a round robin. 104*/ 105 106struct workgrp 107{ 108 int wg_numqgrp; /* number of queue groups in work grp */ 109 int wg_runners; /* total runners */ 110 int wg_curqgrp; /* current queue group */ 111 QUEUEGRP **wg_qgs; /* array of queue groups */ 112 int wg_maxact; /* max # of active runners */ 113 time_t wg_lowqintvl; /* lowest queue interval */ 114 int wg_restart; /* needs restarting? */ 115 int wg_restartcnt; /* count of times restarted */ 116}; 117 118typedef struct workgrp WORKGRP; 119 120static WORKGRP volatile WorkGrp[MAXWORKGROUPS + 1]; /* work groups */ 121 122#if SM_HEAP_CHECK 123static SM_DEBUG_T DebugLeakQ = SM_DEBUG_INITIALIZER("leak_q", 124 "@(#)$Debug: leak_q - trace memory leaks during queue processing $"); 125#endif /* SM_HEAP_CHECK */ 126 127/* 128** We use EmptyString instead of "" to avoid 129** 'zero-length format string' warnings from gcc 130*/ 131 132static const char EmptyString[] = ""; 133 134static void grow_wlist __P((int, int)); 135static int multiqueue_cache __P((char *, int, QUEUEGRP *, int, unsigned int *)); 136static int gatherq __P((int, int, bool, bool *, bool *)); 137static int sortq __P((int)); 138static void printctladdr __P((ADDRESS *, SM_FILE_T *)); 139static bool readqf __P((ENVELOPE *, bool)); 140static void restart_work_group __P((int)); 141static void runner_work __P((ENVELOPE *, int, bool, int, int)); 142static void schedule_queue_runs __P((bool, int, bool)); 143static char *strrev __P((char *)); 144static ADDRESS *setctluser __P((char *, int, ENVELOPE *)); 145#if _FFR_RHS 146static int sm_strshufflecmp __P((char *, char *)); 147static void init_shuffle_alphabet __P(()); 148#endif /* _FFR_RHS */ 149static int workcmpf0(); 150static int workcmpf1(); 151static int workcmpf2(); 152static int workcmpf3(); 153static int workcmpf4(); 154static int randi = 3; /* index for workcmpf5() */ 155static int workcmpf5(); 156static int workcmpf6(); 157#if _FFR_RHS 158static int workcmpf7(); 159#endif /* _FFR_RHS */ 160 161#if RANDOMSHIFT 162# define get_rand_mod(m) ((get_random() >> RANDOMSHIFT) % (m)) 163#else /* RANDOMSHIFT */ 164# define get_rand_mod(m) (get_random() % (m)) 165#endif /* RANDOMSHIFT */ 166 167/* 168** File system definition. 169** Used to keep track of how much free space is available 170** on a file system in which one or more queue directories reside. 171*/ 172 173typedef struct filesys_shared FILESYS; 174 175struct filesys_shared 176{ 177 dev_t fs_dev; /* unique device id */ 178 long fs_avail; /* number of free blocks available */ 179 long fs_blksize; /* block size, in bytes */ 180}; 181 182/* probably kept in shared memory */ 183static FILESYS FileSys[MAXFILESYS]; /* queue file systems */ 184static char *FSPath[MAXFILESYS]; /* pathnames for file systems */ 185 186#if SM_CONF_SHM 187 188/* 189** Shared memory data 190** 191** Current layout: 192** size -- size of shared memory segment 193** pid -- pid of owner, should be a unique id to avoid misinterpretations 194** by other processes. 195** tag -- should be a unique id to avoid misinterpretations by others. 196** idea: hash over configuration data that will be stored here. 197** NumFileSys -- number of file systems. 198** FileSys -- (arrary of) structure for used file systems. 199** RSATmpCnt -- counter for number of uses of ephemeral RSA key. 200** QShm -- (array of) structure for information about queue directories. 201*/ 202 203/* 204** Queue data in shared memory 205*/ 206 207typedef struct queue_shared QUEUE_SHM_T; 208 209struct queue_shared 210{ 211 int qs_entries; /* number of entries */ 212 /* XXX more to follow? */ 213}; 214 215static void *Pshm; /* pointer to shared memory */ 216static FILESYS *PtrFileSys; /* pointer to queue file system array */ 217int ShmId = SM_SHM_NO_ID; /* shared memory id */ 218static QUEUE_SHM_T *QShm; /* pointer to shared queue data */ 219static size_t shms; 220 221# define SHM_OFF_PID(p) (((char *) (p)) + sizeof(int)) 222# define SHM_OFF_TAG(p) (((char *) (p)) + sizeof(pid_t) + sizeof(int)) 223# define SHM_OFF_HEAD (sizeof(pid_t) + sizeof(int) * 2) 224 225/* how to access FileSys */ 226# define FILE_SYS(i) (PtrFileSys[i]) 227 228/* first entry is a tag, for now just the size */ 229# define OFF_FILE_SYS(p) (((char *) (p)) + SHM_OFF_HEAD) 230 231/* offset for PNumFileSys */ 232# define OFF_NUM_FILE_SYS(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys)) 233 234/* offset for PRSATmpCnt */ 235# define OFF_RSA_TMP_CNT(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int)) 236int *PRSATmpCnt; 237 238/* offset for queue_shm */ 239# define OFF_QUEUE_SHM(p) (((char *) (p)) + SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2) 240 241# define QSHM_ENTRIES(i) QShm[i].qs_entries 242 243/* basic size of shared memory segment */ 244# define SM_T_SIZE (SHM_OFF_HEAD + sizeof(FileSys) + sizeof(int) * 2) 245 246static unsigned int hash_q __P((char *, unsigned int)); 247 248/* 249** HASH_Q -- simple hash function 250** 251** Parameters: 252** p -- string to hash. 253** h -- hash start value (from previous run). 254** 255** Returns: 256** hash value. 257*/ 258 259static unsigned int 260hash_q(p, h) 261 char *p; 262 unsigned int h; 263{ 264 int c, d; 265 266 while (*p != '\0') 267 { 268 d = *p++; 269 c = d; 270 c ^= c<<6; 271 h += (c<<11) ^ (c>>1); 272 h ^= (d<<14) + (d<<7) + (d<<4) + d; 273 } 274 return h; 275} 276 277 278#else /* SM_CONF_SHM */ 279# define FILE_SYS(i) FileSys[i] 280#endif /* SM_CONF_SHM */ 281 282/* access to the various components of file system data */ 283#define FILE_SYS_NAME(i) FSPath[i] 284#define FILE_SYS_AVAIL(i) FILE_SYS(i).fs_avail 285#define FILE_SYS_BLKSIZE(i) FILE_SYS(i).fs_blksize 286#define FILE_SYS_DEV(i) FILE_SYS(i).fs_dev 287 288 289/* 290** Current qf file field assignments: 291** 292** A AUTH= parameter 293** B body type 294** C controlling user 295** D data file name 296** d data file directory name (added in 8.12) 297** E error recipient 298** F flag bits 299** G free (was: queue delay algorithm if _FFR_QUEUEDELAY) 300** H header 301** I data file's inode number 302** K time of last delivery attempt 303** L Solaris Content-Length: header (obsolete) 304** M message 305** N number of delivery attempts 306** P message priority 307** q quarantine reason 308** Q original recipient (ORCPT=) 309** r final recipient (Final-Recipient: DSN field) 310** R recipient 311** S sender 312** T init time 313** V queue file version 314** X free (was: character set if _FFR_SAVE_CHARSET) 315** Y free (was: current delay if _FFR_QUEUEDELAY) 316** Z original envelope id from ESMTP 317** ! deliver by (added in 8.12) 318** $ define macro 319** . terminate file 320*/ 321 322/* 323** QUEUEUP -- queue a message up for future transmission. 324** 325** Parameters: 326** e -- the envelope to queue up. 327** announce -- if true, tell when you are queueing up. 328** msync -- if true, then fsync() if SuperSafe interactive mode. 329** 330** Returns: 331** none. 332** 333** Side Effects: 334** The current request is saved in a control file. 335** The queue file is left locked. 336*/ 337 338void 339queueup(e, announce, msync) 340 register ENVELOPE *e; 341 bool announce; 342 bool msync; 343{ 344 register SM_FILE_T *tfp; 345 register HDR *h; 346 register ADDRESS *q; 347 int tfd = -1; 348 int i; 349 bool newid; 350 register char *p; 351 MAILER nullmailer; 352 MCI mcibuf; 353 char qf[MAXPATHLEN]; 354 char tf[MAXPATHLEN]; 355 char df[MAXPATHLEN]; 356 char buf[MAXLINE]; 357 358 /* 359 ** Create control file. 360 */ 361 362#define OPEN_TF do \ 363 { \ 364 MODE_T oldumask = 0; \ 365 \ 366 if (bitset(S_IWGRP, QueueFileMode)) \ 367 oldumask = umask(002); \ 368 tfd = open(tf, TF_OPEN_FLAGS, QueueFileMode); \ 369 if (bitset(S_IWGRP, QueueFileMode)) \ 370 (void) umask(oldumask); \ 371 } while (0) 372 373 374 newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags); 375 (void) sm_strlcpy(tf, queuename(e, NEWQFL_LETTER), sizeof tf); 376 tfp = e->e_lockfp; 377 if (tfp == NULL && newid) 378 { 379 /* 380 ** open qf file directly: this will give an error if the file 381 ** already exists and hence prevent problems if a queue-id 382 ** is reused (e.g., because the clock is set back). 383 */ 384 385 (void) sm_strlcpy(tf, queuename(e, ANYQFL_LETTER), sizeof tf); 386 OPEN_TF; 387 if (tfd < 0 || 388#if !SM_OPEN_EXLOCK 389 !lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB) || 390#endif /* !SM_OPEN_EXLOCK */ 391 (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 392 (void *) &tfd, SM_IO_WRONLY, 393 NULL)) == NULL) 394 { 395 int save_errno = errno; 396 397 printopenfds(true); 398 errno = save_errno; 399 syserr("!queueup: cannot create queue file %s, euid=%d, fd=%d, fp=%p", 400 tf, (int) geteuid(), tfd, tfp); 401 /* NOTREACHED */ 402 } 403 e->e_lockfp = tfp; 404 } 405 406 /* if newid, write the queue file directly (instead of temp file) */ 407 if (!newid) 408 { 409 /* get a locked tf file */ 410 for (i = 0; i < 128; i++) 411 { 412 if (tfd < 0) 413 { 414 OPEN_TF; 415 if (tfd < 0) 416 { 417 if (errno != EEXIST) 418 break; 419 if (LogLevel > 0 && (i % 32) == 0) 420 sm_syslog(LOG_ALERT, e->e_id, 421 "queueup: cannot create %s, uid=%d: %s", 422 tf, (int) geteuid(), 423 sm_errstring(errno)); 424 } 425#if SM_OPEN_EXLOCK 426 else 427 break; 428#endif /* SM_OPEN_EXLOCK */ 429 } 430 if (tfd >= 0) 431 { 432#if SM_OPEN_EXLOCK 433 /* file is locked by open() */ 434 break; 435#else /* SM_OPEN_EXLOCK */ 436 if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB)) 437 break; 438 else 439#endif /* SM_OPEN_EXLOCK */ 440 if (LogLevel > 0 && (i % 32) == 0) 441 sm_syslog(LOG_ALERT, e->e_id, 442 "queueup: cannot lock %s: %s", 443 tf, sm_errstring(errno)); 444 if ((i % 32) == 31) 445 { 446 (void) close(tfd); 447 tfd = -1; 448 } 449 } 450 451 if ((i % 32) == 31) 452 { 453 /* save the old temp file away */ 454 (void) rename(tf, queuename(e, TEMPQF_LETTER)); 455 } 456 else 457 (void) sleep(i % 32); 458 } 459 if (tfd < 0 || (tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 460 (void *) &tfd, SM_IO_WRONLY_B, 461 NULL)) == NULL) 462 { 463 int save_errno = errno; 464 465 printopenfds(true); 466 errno = save_errno; 467 syserr("!queueup: cannot create queue temp file %s, uid=%d", 468 tf, (int) geteuid()); 469 } 470 } 471 472 if (tTd(40, 1)) 473 sm_dprintf("\n>>>>> queueing %s/%s%s >>>>>\n", 474 qid_printqueue(e->e_qgrp, e->e_qdir), 475 queuename(e, ANYQFL_LETTER), 476 newid ? " (new id)" : ""); 477 if (tTd(40, 3)) 478 { 479 sm_dprintf(" e_flags="); 480 printenvflags(e); 481 } 482 if (tTd(40, 32)) 483 { 484 sm_dprintf(" sendq="); 485 printaddr(sm_debug_file(), e->e_sendqueue, true); 486 } 487 if (tTd(40, 9)) 488 { 489 sm_dprintf(" tfp="); 490 dumpfd(sm_io_getinfo(tfp, SM_IO_WHAT_FD, NULL), true, false); 491 sm_dprintf(" lockfp="); 492 if (e->e_lockfp == NULL) 493 sm_dprintf("NULL\n"); 494 else 495 dumpfd(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL), 496 true, false); 497 } 498 499 /* 500 ** If there is no data file yet, create one. 501 */ 502 503 (void) sm_strlcpy(df, queuename(e, DATAFL_LETTER), sizeof df); 504 if (bitset(EF_HAS_DF, e->e_flags)) 505 { 506 if (e->e_dfp != NULL && 507 SuperSafe != SAFE_REALLY && 508 SuperSafe != SAFE_REALLY_POSTMILTER && 509 sm_io_setinfo(e->e_dfp, SM_BF_COMMIT, NULL) < 0 && 510 errno != EINVAL) 511 { 512 syserr("!queueup: cannot commit data file %s, uid=%d", 513 queuename(e, DATAFL_LETTER), (int) geteuid()); 514 } 515 if (e->e_dfp != NULL && 516 SuperSafe == SAFE_INTERACTIVE && msync) 517 { 518 if (tTd(40,32)) 519 sm_syslog(LOG_INFO, e->e_id, 520 "queueup: fsync(e->e_dfp)"); 521 522 if (fsync(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, 523 NULL)) < 0) 524 { 525 if (newid) 526 syserr("!552 Error writing data file %s", 527 df); 528 else 529 syserr("!452 Error writing data file %s", 530 df); 531 } 532 } 533 } 534 else 535 { 536 int dfd; 537 MODE_T oldumask = 0; 538 register SM_FILE_T *dfp = NULL; 539 struct stat stbuf; 540 541 if (e->e_dfp != NULL && 542 sm_io_getinfo(e->e_dfp, SM_IO_WHAT_ISTYPE, BF_FILE_TYPE)) 543 syserr("committing over bf file"); 544 545 if (bitset(S_IWGRP, QueueFileMode)) 546 oldumask = umask(002); 547 dfd = open(df, O_WRONLY|O_CREAT|O_TRUNC|QF_O_EXTRA, 548 QueueFileMode); 549 if (bitset(S_IWGRP, QueueFileMode)) 550 (void) umask(oldumask); 551 if (dfd < 0 || (dfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 552 (void *) &dfd, SM_IO_WRONLY_B, 553 NULL)) == NULL) 554 syserr("!queueup: cannot create data temp file %s, uid=%d", 555 df, (int) geteuid()); 556 if (fstat(dfd, &stbuf) < 0) 557 e->e_dfino = -1; 558 else 559 { 560 e->e_dfdev = stbuf.st_dev; 561 e->e_dfino = ST_INODE(stbuf); 562 } 563 e->e_flags |= EF_HAS_DF; 564 memset(&mcibuf, '\0', sizeof mcibuf); 565 mcibuf.mci_out = dfp; 566 mcibuf.mci_mailer = FileMailer; 567 (*e->e_putbody)(&mcibuf, e, NULL); 568 569 if (SuperSafe == SAFE_REALLY || 570 SuperSafe == SAFE_REALLY_POSTMILTER || 571 (SuperSafe == SAFE_INTERACTIVE && msync)) 572 { 573 if (tTd(40,32)) 574 sm_syslog(LOG_INFO, e->e_id, 575 "queueup: fsync(dfp)"); 576 577 if (fsync(sm_io_getinfo(dfp, SM_IO_WHAT_FD, NULL)) < 0) 578 { 579 if (newid) 580 syserr("!552 Error writing data file %s", 581 df); 582 else 583 syserr("!452 Error writing data file %s", 584 df); 585 } 586 } 587 588 if (sm_io_close(dfp, SM_TIME_DEFAULT) < 0) 589 syserr("!queueup: cannot save data temp file %s, uid=%d", 590 df, (int) geteuid()); 591 e->e_putbody = putbody; 592 } 593 594 /* 595 ** Output future work requests. 596 ** Priority and creation time should be first, since 597 ** they are required by gatherq. 598 */ 599 600 /* output queue version number (must be first!) */ 601 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "V%d\n", QF_VERSION); 602 603 /* output creation time */ 604 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "T%ld\n", (long) e->e_ctime); 605 606 /* output last delivery time */ 607 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "K%ld\n", (long) e->e_dtime); 608 609 /* output number of delivery attempts */ 610 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "N%d\n", e->e_ntries); 611 612 /* output message priority */ 613 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "P%ld\n", e->e_msgpriority); 614 615 /* 616 ** If data file is in a different directory than the queue file, 617 ** output a "d" record naming the directory of the data file. 618 */ 619 620 if (e->e_dfqgrp != e->e_qgrp) 621 { 622 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "d%s\n", 623 Queue[e->e_dfqgrp]->qg_qpaths[e->e_dfqdir].qp_name); 624 } 625 626 /* output inode number of data file */ 627 /* XXX should probably include device major/minor too */ 628 if (e->e_dfino != -1) 629 { 630 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "I%ld/%ld/%llu\n", 631 (long) major(e->e_dfdev), 632 (long) minor(e->e_dfdev), 633 (ULONGLONG_T) e->e_dfino); 634 } 635 636 /* output body type */ 637 if (e->e_bodytype != NULL) 638 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "B%s\n", 639 denlstring(e->e_bodytype, true, false)); 640 641 /* quarantine reason */ 642 if (e->e_quarmsg != NULL) 643 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "q%s\n", 644 denlstring(e->e_quarmsg, true, false)); 645 646 /* message from envelope, if it exists */ 647 if (e->e_message != NULL) 648 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "M%s\n", 649 denlstring(e->e_message, true, false)); 650 651 /* send various flag bits through */ 652 p = buf; 653 if (bitset(EF_WARNING, e->e_flags)) 654 *p++ = 'w'; 655 if (bitset(EF_RESPONSE, e->e_flags)) 656 *p++ = 'r'; 657 if (bitset(EF_HAS8BIT, e->e_flags)) 658 *p++ = '8'; 659 if (bitset(EF_DELETE_BCC, e->e_flags)) 660 *p++ = 'b'; 661 if (bitset(EF_RET_PARAM, e->e_flags)) 662 *p++ = 'd'; 663 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 664 *p++ = 'n'; 665 if (bitset(EF_SPLIT, e->e_flags)) 666 *p++ = 's'; 667 *p++ = '\0'; 668 if (buf[0] != '\0') 669 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "F%s\n", buf); 670 671 /* save $={persistentMacros} macro values */ 672 queueup_macros(macid("{persistentMacros}"), tfp, e); 673 674 /* output name of sender */ 675 if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) 676 p = e->e_sender; 677 else 678 p = e->e_from.q_paddr; 679 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "S%s\n", 680 denlstring(p, true, false)); 681 682 /* output ESMTP-supplied "original" information */ 683 if (e->e_envid != NULL) 684 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Z%s\n", 685 denlstring(e->e_envid, true, false)); 686 687 /* output AUTH= parameter */ 688 if (e->e_auth_param != NULL) 689 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "A%s\n", 690 denlstring(e->e_auth_param, true, false)); 691 if (e->e_dlvr_flag != 0) 692 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "!%c %ld\n", 693 (char) e->e_dlvr_flag, e->e_deliver_by); 694 695 /* output list of recipient addresses */ 696 printctladdr(NULL, NULL); 697 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 698 { 699 if (!QS_IS_UNDELIVERED(q->q_state)) 700 continue; 701 702 /* message for this recipient, if it exists */ 703 if (q->q_message != NULL) 704 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "M%s\n", 705 denlstring(q->q_message, true, 706 false)); 707 708 printctladdr(q, tfp); 709 if (q->q_orcpt != NULL) 710 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Q%s\n", 711 denlstring(q->q_orcpt, true, 712 false)); 713 if (q->q_finalrcpt != NULL) 714 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "r%s\n", 715 denlstring(q->q_finalrcpt, true, 716 false)); 717 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'R'); 718 if (bitset(QPRIMARY, q->q_flags)) 719 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'P'); 720 if (bitset(QHASNOTIFY, q->q_flags)) 721 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'N'); 722 if (bitset(QPINGONSUCCESS, q->q_flags)) 723 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'S'); 724 if (bitset(QPINGONFAILURE, q->q_flags)) 725 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'F'); 726 if (bitset(QPINGONDELAY, q->q_flags)) 727 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'D'); 728 if (q->q_alias != NULL && 729 bitset(QALIAS, q->q_alias->q_flags)) 730 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'A'); 731 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, ':'); 732 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s\n", 733 denlstring(q->q_paddr, true, false)); 734 if (announce) 735 { 736 char *tag = "queued"; 737 738 if (e->e_quarmsg != NULL) 739 tag = "quarantined"; 740 741 e->e_to = q->q_paddr; 742 message(tag); 743 if (LogLevel > 8) 744 logdelivery(q->q_mailer, NULL, q->q_status, 745 tag, NULL, (time_t) 0, e); 746 e->e_to = NULL; 747 } 748 if (tTd(40, 1)) 749 { 750 sm_dprintf("queueing "); 751 printaddr(sm_debug_file(), q, false); 752 } 753 } 754 755 /* 756 ** Output headers for this message. 757 ** Expand macros completely here. Queue run will deal with 758 ** everything as absolute headers. 759 ** All headers that must be relative to the recipient 760 ** can be cracked later. 761 ** We set up a "null mailer" -- i.e., a mailer that will have 762 ** no effect on the addresses as they are output. 763 */ 764 765 memset((char *) &nullmailer, '\0', sizeof nullmailer); 766 nullmailer.m_re_rwset = nullmailer.m_rh_rwset = 767 nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; 768 nullmailer.m_eol = "\n"; 769 memset(&mcibuf, '\0', sizeof mcibuf); 770 mcibuf.mci_mailer = &nullmailer; 771 mcibuf.mci_out = tfp; 772 773 macdefine(&e->e_macro, A_PERM, 'g', "\201f"); 774 for (h = e->e_header; h != NULL; h = h->h_link) 775 { 776 if (h->h_value == NULL) 777 continue; 778 779 /* don't output resent headers on non-resent messages */ 780 if (bitset(H_RESENT, h->h_flags) && 781 !bitset(EF_RESENT, e->e_flags)) 782 continue; 783 784 /* expand macros; if null, don't output header at all */ 785 if (bitset(H_DEFAULT, h->h_flags)) 786 { 787 (void) expand(h->h_value, buf, sizeof buf, e); 788 if (buf[0] == '\0') 789 continue; 790 } 791 792 /* output this header */ 793 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "H?"); 794 795 /* output conditional macro if present */ 796 if (h->h_macro != '\0') 797 { 798 if (bitset(0200, h->h_macro)) 799 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, 800 "${%s}", 801 macname(bitidx(h->h_macro))); 802 else 803 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, 804 "$%c", h->h_macro); 805 } 806 else if (!bitzerop(h->h_mflags) && 807 bitset(H_CHECK|H_ACHECK, h->h_flags)) 808 { 809 int j; 810 811 /* if conditional, output the set of conditions */ 812 for (j = '\0'; j <= '\177'; j++) 813 if (bitnset(j, h->h_mflags)) 814 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, 815 j); 816 } 817 (void) sm_io_putc(tfp, SM_TIME_DEFAULT, '?'); 818 819 /* output the header: expand macros, convert addresses */ 820 if (bitset(H_DEFAULT, h->h_flags) && 821 !bitset(H_BINDLATE, h->h_flags)) 822 { 823 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s: %s\n", 824 h->h_field, 825 denlstring(buf, false, true)); 826 } 827 else if (bitset(H_FROM|H_RCPT, h->h_flags) && 828 !bitset(H_BINDLATE, h->h_flags)) 829 { 830 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 831 SM_FILE_T *savetrace = TrafficLogFile; 832 833 TrafficLogFile = NULL; 834 835 if (bitset(H_FROM, h->h_flags)) 836 oldstyle = false; 837 838 commaize(h, h->h_value, oldstyle, &mcibuf, e); 839 840 TrafficLogFile = savetrace; 841 } 842 else 843 { 844 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "%s: %s\n", 845 h->h_field, 846 denlstring(h->h_value, false, 847 true)); 848 } 849 } 850 851 /* 852 ** Clean up. 853 ** 854 ** Write a terminator record -- this is to prevent 855 ** scurrilous crackers from appending any data. 856 */ 857 858 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ".\n"); 859 860 if (sm_io_flush(tfp, SM_TIME_DEFAULT) != 0 || 861 ((SuperSafe == SAFE_REALLY || 862 SuperSafe == SAFE_REALLY_POSTMILTER || 863 (SuperSafe == SAFE_INTERACTIVE && msync)) && 864 fsync(sm_io_getinfo(tfp, SM_IO_WHAT_FD, NULL)) < 0) || 865 sm_io_error(tfp)) 866 { 867 if (newid) 868 syserr("!552 Error writing control file %s", tf); 869 else 870 syserr("!452 Error writing control file %s", tf); 871 } 872 873 if (!newid) 874 { 875 char new = queue_letter(e, ANYQFL_LETTER); 876 877 /* rename (locked) tf to be (locked) [qh]f */ 878 (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), 879 sizeof qf); 880 if (rename(tf, qf) < 0) 881 syserr("cannot rename(%s, %s), uid=%d", 882 tf, qf, (int) geteuid()); 883 else 884 { 885 /* 886 ** Check if type has changed and only 887 ** remove the old item if the rename above 888 ** succeeded. 889 */ 890 891 if (e->e_qfletter != '\0' && 892 e->e_qfletter != new) 893 { 894 if (tTd(40, 5)) 895 { 896 sm_dprintf("type changed from %c to %c\n", 897 e->e_qfletter, new); 898 } 899 900 if (unlink(queuename(e, e->e_qfletter)) < 0) 901 { 902 /* XXX: something more drastic? */ 903 if (LogLevel > 0) 904 sm_syslog(LOG_ERR, e->e_id, 905 "queueup: unlink(%s) failed: %s", 906 queuename(e, e->e_qfletter), 907 sm_errstring(errno)); 908 } 909 } 910 } 911 e->e_qfletter = new; 912 913 /* 914 ** fsync() after renaming to make sure metadata is 915 ** written to disk on filesystems in which renames are 916 ** not guaranteed. 917 */ 918 919 if (SuperSafe != SAFE_NO) 920 { 921 /* for softupdates */ 922 if (tfd >= 0 && fsync(tfd) < 0) 923 { 924 syserr("!queueup: cannot fsync queue temp file %s", 925 tf); 926 } 927 SYNC_DIR(qf, true); 928 } 929 930 /* close and unlock old (locked) queue file */ 931 if (e->e_lockfp != NULL) 932 (void) sm_io_close(e->e_lockfp, SM_TIME_DEFAULT); 933 e->e_lockfp = tfp; 934 935 /* save log info */ 936 if (LogLevel > 79) 937 sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", qf); 938 } 939 else 940 { 941 /* save log info */ 942 if (LogLevel > 79) 943 sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", tf); 944 945 e->e_qfletter = queue_letter(e, ANYQFL_LETTER); 946 } 947 948 errno = 0; 949 e->e_flags |= EF_INQUEUE; 950 951 if (tTd(40, 1)) 952 sm_dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id); 953 return; 954} 955 956/* 957** PRINTCTLADDR -- print control address to file. 958** 959** Parameters: 960** a -- address. 961** tfp -- file pointer. 962** 963** Returns: 964** none. 965** 966** Side Effects: 967** The control address (if changed) is printed to the file. 968** The last control address and uid are saved. 969*/ 970 971static void 972printctladdr(a, tfp) 973 register ADDRESS *a; 974 SM_FILE_T *tfp; 975{ 976 char *user; 977 register ADDRESS *q; 978 uid_t uid; 979 gid_t gid; 980 static ADDRESS *lastctladdr = NULL; 981 static uid_t lastuid; 982 983 /* initialization */ 984 if (a == NULL || a->q_alias == NULL || tfp == NULL) 985 { 986 if (lastctladdr != NULL && tfp != NULL) 987 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C\n"); 988 lastctladdr = NULL; 989 lastuid = 0; 990 return; 991 } 992 993 /* find the active uid */ 994 q = getctladdr(a); 995 if (q == NULL) 996 { 997 user = NULL; 998 uid = 0; 999 gid = 0; 1000 } 1001 else 1002 { 1003 user = q->q_ruser != NULL ? q->q_ruser : q->q_user; 1004 uid = q->q_uid; 1005 gid = q->q_gid; 1006 } 1007 a = a->q_alias; 1008 1009 /* check to see if this is the same as last time */ 1010 if (lastctladdr != NULL && uid == lastuid && 1011 strcmp(lastctladdr->q_paddr, a->q_paddr) == 0) 1012 return; 1013 lastuid = uid; 1014 lastctladdr = a; 1015 1016 if (uid == 0 || user == NULL || user[0] == '\0') 1017 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C"); 1018 else 1019 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "C%s:%ld:%ld", 1020 denlstring(user, true, false), (long) uid, 1021 (long) gid); 1022 (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, ":%s\n", 1023 denlstring(a->q_paddr, true, false)); 1024} 1025 1026/* 1027** RUNNERS_SIGTERM -- propagate a SIGTERM to queue runner process 1028** 1029** This propagates the signal to the child processes that are queue 1030** runners. This is for a queue runner "cleanup". After all of the 1031** child queue runner processes are signaled (it should be SIGTERM 1032** being the sig) then the old signal handler (Oldsh) is called 1033** to handle any cleanup set for this process (provided it is not 1034** SIG_DFL or SIG_IGN). The signal may not be handled immediately 1035** if the BlockOldsh flag is set. If the current process doesn't 1036** have a parent then handle the signal immediately, regardless of 1037** BlockOldsh. 1038** 1039** Parameters: 1040** sig -- the signal number being sent 1041** 1042** Returns: 1043** none. 1044** 1045** Side Effects: 1046** Sets the NoMoreRunners boolean to true to stop more runners 1047** from being started in runqueue(). 1048** 1049** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1050** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1051** DOING. 1052*/ 1053 1054static bool volatile NoMoreRunners = false; 1055static sigfunc_t Oldsh_term = SIG_DFL; 1056static sigfunc_t Oldsh_hup = SIG_DFL; 1057static sigfunc_t volatile Oldsh = SIG_DFL; 1058static bool BlockOldsh = false; 1059static int volatile Oldsig = 0; 1060static SIGFUNC_DECL runners_sigterm __P((int)); 1061static SIGFUNC_DECL runners_sighup __P((int)); 1062 1063static SIGFUNC_DECL 1064runners_sigterm(sig) 1065 int sig; 1066{ 1067 int save_errno = errno; 1068 1069 FIX_SYSV_SIGNAL(sig, runners_sigterm); 1070 errno = save_errno; 1071 CHECK_CRITICAL(sig); 1072 NoMoreRunners = true; 1073 Oldsh = Oldsh_term; 1074 Oldsig = sig; 1075 proc_list_signal(PROC_QUEUE, sig); 1076 1077 if (!BlockOldsh || getppid() <= 1) 1078 { 1079 /* Check that a valid 'old signal handler' is callable */ 1080 if (Oldsh_term != SIG_DFL && Oldsh_term != SIG_IGN && 1081 Oldsh_term != runners_sigterm) 1082 (*Oldsh_term)(sig); 1083 } 1084 errno = save_errno; 1085 return SIGFUNC_RETURN; 1086} 1087/* 1088** RUNNERS_SIGHUP -- propagate a SIGHUP to queue runner process 1089** 1090** This propagates the signal to the child processes that are queue 1091** runners. This is for a queue runner "cleanup". After all of the 1092** child queue runner processes are signaled (it should be SIGHUP 1093** being the sig) then the old signal handler (Oldsh) is called to 1094** handle any cleanup set for this process (provided it is not SIG_DFL 1095** or SIG_IGN). The signal may not be handled immediately if the 1096** BlockOldsh flag is set. If the current process doesn't have 1097** a parent then handle the signal immediately, regardless of 1098** BlockOldsh. 1099** 1100** Parameters: 1101** sig -- the signal number being sent 1102** 1103** Returns: 1104** none. 1105** 1106** Side Effects: 1107** Sets the NoMoreRunners boolean to true to stop more runners 1108** from being started in runqueue(). 1109** 1110** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1111** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1112** DOING. 1113*/ 1114 1115static SIGFUNC_DECL 1116runners_sighup(sig) 1117 int sig; 1118{ 1119 int save_errno = errno; 1120 1121 FIX_SYSV_SIGNAL(sig, runners_sighup); 1122 errno = save_errno; 1123 CHECK_CRITICAL(sig); 1124 NoMoreRunners = true; 1125 Oldsh = Oldsh_hup; 1126 Oldsig = sig; 1127 proc_list_signal(PROC_QUEUE, sig); 1128 1129 if (!BlockOldsh || getppid() <= 1) 1130 { 1131 /* Check that a valid 'old signal handler' is callable */ 1132 if (Oldsh_hup != SIG_DFL && Oldsh_hup != SIG_IGN && 1133 Oldsh_hup != runners_sighup) 1134 (*Oldsh_hup)(sig); 1135 } 1136 errno = save_errno; 1137 return SIGFUNC_RETURN; 1138} 1139/* 1140** MARK_WORK_GROUP_RESTART -- mark a work group as needing a restart 1141** 1142** Sets a workgroup for restarting. 1143** 1144** Parameters: 1145** wgrp -- the work group id to restart. 1146** reason -- why (signal?), -1 to turn off restart 1147** 1148** Returns: 1149** none. 1150** 1151** Side effects: 1152** May set global RestartWorkGroup to true. 1153** 1154** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1155** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1156** DOING. 1157*/ 1158 1159void 1160mark_work_group_restart(wgrp, reason) 1161 int wgrp; 1162 int reason; 1163{ 1164 if (wgrp < 0 || wgrp > NumWorkGroups) 1165 return; 1166 1167 WorkGrp[wgrp].wg_restart = reason; 1168 if (reason >= 0) 1169 RestartWorkGroup = true; 1170} 1171/* 1172** RESTART_MARKED_WORK_GROUPS -- restart work groups marked as needing restart 1173** 1174** Restart any workgroup marked as needing a restart provided more 1175** runners are allowed. 1176** 1177** Parameters: 1178** none. 1179** 1180** Returns: 1181** none. 1182** 1183** Side effects: 1184** Sets global RestartWorkGroup to false. 1185*/ 1186 1187void 1188restart_marked_work_groups() 1189{ 1190 int i; 1191 int wasblocked; 1192 1193 if (NoMoreRunners) 1194 return; 1195 1196 /* Block SIGCHLD so reapchild() doesn't mess with us */ 1197 wasblocked = sm_blocksignal(SIGCHLD); 1198 1199 for (i = 0; i < NumWorkGroups; i++) 1200 { 1201 if (WorkGrp[i].wg_restart >= 0) 1202 { 1203 if (LogLevel > 8) 1204 sm_syslog(LOG_ERR, NOQID, 1205 "restart queue runner=%d due to signal 0x%x", 1206 i, WorkGrp[i].wg_restart); 1207 restart_work_group(i); 1208 } 1209 } 1210 RestartWorkGroup = false; 1211 1212 if (wasblocked == 0) 1213 (void) sm_releasesignal(SIGCHLD); 1214} 1215/* 1216** RESTART_WORK_GROUP -- restart a specific work group 1217** 1218** Restart a specific workgroup provided more runners are allowed. 1219** If the requested work group has been restarted too many times log 1220** this and refuse to restart. 1221** 1222** Parameters: 1223** wgrp -- the work group id to restart 1224** 1225** Returns: 1226** none. 1227** 1228** Side Effects: 1229** starts another process doing the work of wgrp 1230*/ 1231 1232#define MAX_PERSIST_RESTART 10 /* max allowed number of restarts */ 1233 1234static void 1235restart_work_group(wgrp) 1236 int wgrp; 1237{ 1238 if (NoMoreRunners || 1239 wgrp < 0 || wgrp > NumWorkGroups) 1240 return; 1241 1242 WorkGrp[wgrp].wg_restart = -1; 1243 if (WorkGrp[wgrp].wg_restartcnt < MAX_PERSIST_RESTART) 1244 { 1245 /* avoid overflow; increment here */ 1246 WorkGrp[wgrp].wg_restartcnt++; 1247 (void) run_work_group(wgrp, RWG_FORK|RWG_PERSISTENT|RWG_RUNALL); 1248 } 1249 else 1250 { 1251 sm_syslog(LOG_ERR, NOQID, 1252 "ERROR: persistent queue runner=%d restarted too many times, queue runner lost", 1253 wgrp); 1254 } 1255} 1256/* 1257** SCHEDULE_QUEUE_RUNS -- schedule the next queue run for a work group. 1258** 1259** Parameters: 1260** runall -- schedule even if individual bit is not set. 1261** wgrp -- the work group id to schedule. 1262** didit -- the queue run was performed for this work group. 1263** 1264** Returns: 1265** nothing 1266*/ 1267 1268#define INCR_MOD(v, m) if (++v >= m) \ 1269 v = 0; \ 1270 else 1271 1272static void 1273schedule_queue_runs(runall, wgrp, didit) 1274 bool runall; 1275 int wgrp; 1276 bool didit; 1277{ 1278 int qgrp, cgrp, endgrp; 1279#if _FFR_QUEUE_SCHED_DBG 1280 time_t lastsched; 1281 bool sched; 1282#endif /* _FFR_QUEUE_SCHED_DBG */ 1283 time_t now; 1284 time_t minqintvl; 1285 1286 /* 1287 ** This is a bit ugly since we have to duplicate the 1288 ** code that "walks" through a work queue group. 1289 */ 1290 1291 now = curtime(); 1292 minqintvl = 0; 1293 cgrp = endgrp = WorkGrp[wgrp].wg_curqgrp; 1294 do 1295 { 1296 time_t qintvl; 1297 1298#if _FFR_QUEUE_SCHED_DBG 1299 lastsched = 0; 1300 sched = false; 1301#endif /* _FFR_QUEUE_SCHED_DBG */ 1302 qgrp = WorkGrp[wgrp].wg_qgs[cgrp]->qg_index; 1303 if (Queue[qgrp]->qg_queueintvl > 0) 1304 qintvl = Queue[qgrp]->qg_queueintvl; 1305 else if (QueueIntvl > 0) 1306 qintvl = QueueIntvl; 1307 else 1308 qintvl = (time_t) 0; 1309#if _FFR_QUEUE_SCHED_DBG 1310 lastsched = Queue[qgrp]->qg_nextrun; 1311#endif /* _FFR_QUEUE_SCHED_DBG */ 1312 if ((runall || Queue[qgrp]->qg_nextrun <= now) && qintvl > 0) 1313 { 1314#if _FFR_QUEUE_SCHED_DBG 1315 sched = true; 1316#endif /* _FFR_QUEUE_SCHED_DBG */ 1317 if (minqintvl == 0 || qintvl < minqintvl) 1318 minqintvl = qintvl; 1319 1320 /* 1321 ** Only set a new time if a queue run was performed 1322 ** for this queue group. If the queue was not run, 1323 ** we could starve it by setting a new time on each 1324 ** call. 1325 */ 1326 1327 if (didit) 1328 Queue[qgrp]->qg_nextrun += qintvl; 1329 } 1330#if _FFR_QUEUE_SCHED_DBG 1331 if (tTd(69, 10)) 1332 sm_syslog(LOG_INFO, NOQID, 1333 "sqr: wgrp=%d, cgrp=%d, qgrp=%d, intvl=%ld, QI=%ld, runall=%d, lastrun=%ld, nextrun=%ld, sched=%d", 1334 wgrp, cgrp, qgrp, Queue[qgrp]->qg_queueintvl, 1335 QueueIntvl, runall, lastsched, 1336 Queue[qgrp]->qg_nextrun, sched); 1337#endif /* _FFR_QUEUE_SCHED_DBG */ 1338 INCR_MOD(cgrp, WorkGrp[wgrp].wg_numqgrp); 1339 } while (endgrp != cgrp); 1340 if (minqintvl > 0) 1341 (void) sm_setevent(minqintvl, runqueueevent, 0); 1342} 1343 1344#if _FFR_QUEUE_RUN_PARANOIA 1345/* 1346** CHECKQUEUERUNNER -- check whether a queue group hasn't been run. 1347** 1348** Use this if events may get lost and hence queue runners may not 1349** be started and mail will pile up in a queue. 1350** 1351** Parameters: 1352** none. 1353** 1354** Returns: 1355** true if a queue run is necessary. 1356** 1357** Side Effects: 1358** may schedule a queue run. 1359*/ 1360 1361bool 1362checkqueuerunner() 1363{ 1364 int qgrp; 1365 time_t now, minqintvl; 1366 1367 now = curtime(); 1368 minqintvl = 0; 1369 for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++) 1370 { 1371 time_t qintvl; 1372 1373 if (Queue[qgrp]->qg_queueintvl > 0) 1374 qintvl = Queue[qgrp]->qg_queueintvl; 1375 else if (QueueIntvl > 0) 1376 qintvl = QueueIntvl; 1377 else 1378 qintvl = (time_t) 0; 1379 if (Queue[qgrp]->qg_nextrun <= now - qintvl) 1380 { 1381 if (minqintvl == 0 || qintvl < minqintvl) 1382 minqintvl = qintvl; 1383 if (LogLevel > 1) 1384 sm_syslog(LOG_WARNING, NOQID, 1385 "checkqueuerunner: queue %d should have been run at %s, queue interval %ld", 1386 qgrp, 1387 arpadate(ctime(&Queue[qgrp]->qg_nextrun)), 1388 qintvl); 1389 } 1390 } 1391 if (minqintvl > 0) 1392 { 1393 (void) sm_setevent(minqintvl, runqueueevent, 0); 1394 return true; 1395 } 1396 return false; 1397} 1398#endif /* _FFR_QUEUE_RUN_PARANOIA */ 1399 1400/* 1401** RUNQUEUE -- run the jobs in the queue. 1402** 1403** Gets the stuff out of the queue in some presumably logical 1404** order and processes them. 1405** 1406** Parameters: 1407** forkflag -- true if the queue scanning should be done in 1408** a child process. We double-fork so it is not our 1409** child and we don't have to clean up after it. 1410** false can be ignored if we have multiple queues. 1411** verbose -- if true, print out status information. 1412** persistent -- persistent queue runner? 1413** runall -- run all groups or only a subset (DoQueueRun)? 1414** 1415** Returns: 1416** true if the queue run successfully began. 1417** 1418** Side Effects: 1419** runs things in the mail queue using run_work_group(). 1420** maybe schedules next queue run. 1421*/ 1422 1423static ENVELOPE QueueEnvelope; /* the queue run envelope */ 1424static time_t LastQueueTime = 0; /* last time a queue ID assigned */ 1425static pid_t LastQueuePid = -1; /* last PID which had a queue ID */ 1426 1427/* values for qp_supdirs */ 1428#define QP_NOSUB 0x0000 /* No subdirectories */ 1429#define QP_SUBDF 0x0001 /* "df" subdirectory */ 1430#define QP_SUBQF 0x0002 /* "qf" subdirectory */ 1431#define QP_SUBXF 0x0004 /* "xf" subdirectory */ 1432 1433bool 1434runqueue(forkflag, verbose, persistent, runall) 1435 bool forkflag; 1436 bool verbose; 1437 bool persistent; 1438 bool runall; 1439{ 1440 int i; 1441 bool ret = true; 1442 static int curnum = 0; 1443 sigfunc_t cursh; 1444#if SM_HEAP_CHECK 1445 SM_NONVOLATILE int oldgroup = 0; 1446 1447 if (sm_debug_active(&DebugLeakQ, 1)) 1448 { 1449 oldgroup = sm_heap_group(); 1450 sm_heap_newgroup(); 1451 sm_dprintf("runqueue() heap group #%d\n", sm_heap_group()); 1452 } 1453#endif /* SM_HEAP_CHECK */ 1454 1455 /* queue run has been started, don't do any more this time */ 1456 DoQueueRun = false; 1457 1458 /* more than one queue or more than one directory per queue */ 1459 if (!forkflag && !verbose && 1460 (WorkGrp[0].wg_qgs[0]->qg_numqueues > 1 || NumWorkGroups > 1 || 1461 WorkGrp[0].wg_numqgrp > 1)) 1462 forkflag = true; 1463 1464 /* 1465 ** For controlling queue runners via signals sent to this process. 1466 ** Oldsh* will get called too by runners_sig* (if it is not SIG_IGN 1467 ** or SIG_DFL) to preserve cleanup behavior. Now that this process 1468 ** will have children (and perhaps grandchildren) this handler will 1469 ** be left in place. This is because this process, once it has 1470 ** finished spinning off queue runners, may go back to doing something 1471 ** else (like being a daemon). And we still want on a SIG{TERM,HUP} to 1472 ** clean up the child queue runners. Only install 'runners_sig*' once 1473 ** else we'll get stuck looping forever. 1474 */ 1475 1476 cursh = sm_signal(SIGTERM, runners_sigterm); 1477 if (cursh != runners_sigterm) 1478 Oldsh_term = cursh; 1479 cursh = sm_signal(SIGHUP, runners_sighup); 1480 if (cursh != runners_sighup) 1481 Oldsh_hup = cursh; 1482 1483 for (i = 0; i < NumWorkGroups && !NoMoreRunners; i++) 1484 { 1485 int rwgflags = RWG_NONE; 1486 1487 /* 1488 ** If MaxQueueChildren active then test whether the start 1489 ** of the next queue group's additional queue runners (maximum) 1490 ** will result in MaxQueueChildren being exceeded. 1491 ** 1492 ** Note: do not use continue; even though another workgroup 1493 ** may have fewer queue runners, this would be "unfair", 1494 ** i.e., this work group might "starve" then. 1495 */ 1496 1497#if _FFR_QUEUE_SCHED_DBG 1498 if (tTd(69, 10)) 1499 sm_syslog(LOG_INFO, NOQID, 1500 "rq: curnum=%d, MaxQueueChildren=%d, CurRunners=%d, WorkGrp[curnum].wg_maxact=%d", 1501 curnum, MaxQueueChildren, CurRunners, 1502 WorkGrp[curnum].wg_maxact); 1503#endif /* _FFR_QUEUE_SCHED_DBG */ 1504 if (MaxQueueChildren > 0 && 1505 CurRunners + WorkGrp[curnum].wg_maxact > MaxQueueChildren) 1506 break; 1507 1508 /* 1509 ** Pick up where we left off (curnum), in case we 1510 ** used up all the children last time without finishing. 1511 ** This give a round-robin fairness to queue runs. 1512 ** 1513 ** Increment CurRunners before calling run_work_group() 1514 ** to avoid a "race condition" with proc_list_drop() which 1515 ** decrements CurRunners if the queue runners terminate. 1516 ** Notice: CurRunners is an upper limit, in some cases 1517 ** (too few jobs in the queue) this value is larger than 1518 ** the actual number of queue runners. The discrepancy can 1519 ** increase if some queue runners "hang" for a long time. 1520 */ 1521 1522 CurRunners += WorkGrp[curnum].wg_maxact; 1523 if (forkflag) 1524 rwgflags |= RWG_FORK; 1525 if (verbose) 1526 rwgflags |= RWG_VERBOSE; 1527 if (persistent) 1528 rwgflags |= RWG_PERSISTENT; 1529 if (runall) 1530 rwgflags |= RWG_RUNALL; 1531 ret = run_work_group(curnum, rwgflags); 1532 1533 /* 1534 ** Failure means a message was printed for ETRN 1535 ** and subsequent queues are likely to fail as well. 1536 ** Decrement CurRunners in that case because 1537 ** none have been started. 1538 */ 1539 1540 if (!ret) 1541 { 1542 CurRunners -= WorkGrp[curnum].wg_maxact; 1543 break; 1544 } 1545 1546 if (!persistent) 1547 schedule_queue_runs(runall, curnum, true); 1548 INCR_MOD(curnum, NumWorkGroups); 1549 } 1550 1551 /* schedule left over queue runs */ 1552 if (i < NumWorkGroups && !NoMoreRunners && !persistent) 1553 { 1554 int h; 1555 1556 for (h = curnum; i < NumWorkGroups; i++) 1557 { 1558 schedule_queue_runs(runall, h, false); 1559 INCR_MOD(h, NumWorkGroups); 1560 } 1561 } 1562 1563 1564#if SM_HEAP_CHECK 1565 if (sm_debug_active(&DebugLeakQ, 1)) 1566 sm_heap_setgroup(oldgroup); 1567#endif /* SM_HEAP_CHECK */ 1568 return ret; 1569} 1570 1571#if _FFR_SKIP_DOMAINS 1572/* 1573** SKIP_DOMAINS -- Skip 'skip' number of domains in the WorkQ. 1574** 1575** Added by Stephen Frost <sfrost@snowman.net> to support 1576** having each runner process every N'th domain instead of 1577** every N'th message. 1578** 1579** Parameters: 1580** skip -- number of domains in WorkQ to skip. 1581** 1582** Returns: 1583** total number of messages skipped. 1584** 1585** Side Effects: 1586** may change WorkQ 1587*/ 1588 1589static int 1590skip_domains(skip) 1591 int skip; 1592{ 1593 int n, seqjump; 1594 1595 for (n = 0, seqjump = 0; n < skip && WorkQ != NULL; seqjump++) 1596 { 1597 if (WorkQ->w_next != NULL) 1598 { 1599 if (WorkQ->w_host != NULL && 1600 WorkQ->w_next->w_host != NULL) 1601 { 1602 if (sm_strcasecmp(WorkQ->w_host, 1603 WorkQ->w_next->w_host) != 0) 1604 n++; 1605 } 1606 else 1607 { 1608 if ((WorkQ->w_host != NULL && 1609 WorkQ->w_next->w_host == NULL) || 1610 (WorkQ->w_host == NULL && 1611 WorkQ->w_next->w_host != NULL)) 1612 n++; 1613 } 1614 } 1615 WorkQ = WorkQ->w_next; 1616 } 1617 return seqjump; 1618} 1619#endif /* _FFR_SKIP_DOMAINS */ 1620 1621/* 1622** RUNNER_WORK -- have a queue runner do its work 1623** 1624** Have a queue runner do its work a list of entries. 1625** When work isn't directly being done then this process can take a signal 1626** and terminate immediately (in a clean fashion of course). 1627** When work is directly being done, it's not to be interrupted 1628** immediately: the work should be allowed to finish at a clean point 1629** before termination (in a clean fashion of course). 1630** 1631** Parameters: 1632** e -- envelope. 1633** sequenceno -- 'th process to run WorkQ. 1634** didfork -- did the calling process fork()? 1635** skip -- process only each skip'th item. 1636** njobs -- number of jobs in WorkQ. 1637** 1638** Returns: 1639** none. 1640** 1641** Side Effects: 1642** runs things in the mail queue. 1643*/ 1644 1645static void 1646runner_work(e, sequenceno, didfork, skip, njobs) 1647 register ENVELOPE *e; 1648 int sequenceno; 1649 bool didfork; 1650 int skip; 1651 int njobs; 1652{ 1653 int n, seqjump; 1654 WORK *w; 1655 time_t now; 1656 1657 SM_GET_LA(now); 1658 1659 /* 1660 ** Here we temporarily block the second calling of the handlers. 1661 ** This allows us to handle the signal without terminating in the 1662 ** middle of direct work. If a signal does come, the test for 1663 ** NoMoreRunners will find it. 1664 */ 1665 1666 BlockOldsh = true; 1667 seqjump = skip; 1668 1669 /* process them once at a time */ 1670 while (WorkQ != NULL) 1671 { 1672#if SM_HEAP_CHECK 1673 SM_NONVOLATILE int oldgroup = 0; 1674 1675 if (sm_debug_active(&DebugLeakQ, 1)) 1676 { 1677 oldgroup = sm_heap_group(); 1678 sm_heap_newgroup(); 1679 sm_dprintf("run_queue_group() heap group #%d\n", 1680 sm_heap_group()); 1681 } 1682#endif /* SM_HEAP_CHECK */ 1683 1684 /* do no more work */ 1685 if (NoMoreRunners) 1686 { 1687 /* Check that a valid signal handler is callable */ 1688 if (Oldsh != SIG_DFL && Oldsh != SIG_IGN && 1689 Oldsh != runners_sighup && 1690 Oldsh != runners_sigterm) 1691 (*Oldsh)(Oldsig); 1692 break; 1693 } 1694 1695 w = WorkQ; /* assign current work item */ 1696 1697 /* 1698 ** Set the head of the WorkQ to the next work item. 1699 ** It is set 'skip' ahead (the number of parallel queue 1700 ** runners working on WorkQ together) since each runner 1701 ** works on every 'skip'th (N-th) item. 1702#if _FFR_SKIP_DOMAINS 1703 ** In the case of the BYHOST Queue Sort Order, the 'item' 1704 ** is a domain, so we work on every 'skip'th (N-th) domain. 1705#endif * _FFR_SKIP_DOMAINS * 1706 */ 1707 1708#if _FFR_SKIP_DOMAINS 1709 if (QueueSortOrder == QSO_BYHOST) 1710 { 1711 seqjump = 1; 1712 if (WorkQ->w_next != NULL) 1713 { 1714 if (WorkQ->w_host != NULL && 1715 WorkQ->w_next->w_host != NULL) 1716 { 1717 if (sm_strcasecmp(WorkQ->w_host, 1718 WorkQ->w_next->w_host) 1719 != 0) 1720 seqjump = skip_domains(skip); 1721 else 1722 WorkQ = WorkQ->w_next; 1723 } 1724 else 1725 { 1726 if ((WorkQ->w_host != NULL && 1727 WorkQ->w_next->w_host == NULL) || 1728 (WorkQ->w_host == NULL && 1729 WorkQ->w_next->w_host != NULL)) 1730 seqjump = skip_domains(skip); 1731 else 1732 WorkQ = WorkQ->w_next; 1733 } 1734 } 1735 else 1736 WorkQ = WorkQ->w_next; 1737 } 1738 else 1739#endif /* _FFR_SKIP_DOMAINS */ 1740 { 1741 for (n = 0; n < skip && WorkQ != NULL; n++) 1742 WorkQ = WorkQ->w_next; 1743 } 1744 1745 e->e_to = NULL; 1746 1747 /* 1748 ** Ignore jobs that are too expensive for the moment. 1749 ** 1750 ** Get new load average every GET_NEW_LA_TIME seconds. 1751 */ 1752 1753 SM_GET_LA(now); 1754 if (shouldqueue(WkRecipFact, Current_LA_time)) 1755 { 1756 char *msg = "Aborting queue run: load average too high"; 1757 1758 if (Verbose) 1759 message("%s", msg); 1760 if (LogLevel > 8) 1761 sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg); 1762 break; 1763 } 1764 if (shouldqueue(w->w_pri, w->w_ctime)) 1765 { 1766 if (Verbose) 1767 message(EmptyString); 1768 if (QueueSortOrder == QSO_BYPRIORITY) 1769 { 1770 if (Verbose) 1771 message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue", 1772 qid_printqueue(w->w_qgrp, 1773 w->w_qdir), 1774 w->w_name + 2, sequenceno, 1775 njobs); 1776 if (LogLevel > 8) 1777 sm_syslog(LOG_INFO, NOQID, 1778 "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)", 1779 qid_printqueue(w->w_qgrp, 1780 w->w_qdir), 1781 w->w_name + 2, w->w_pri, 1782 CurrentLA, sequenceno, 1783 njobs); 1784 break; 1785 } 1786 else if (Verbose) 1787 message("Skipping %s/%s (sequence %d of %d)", 1788 qid_printqueue(w->w_qgrp, w->w_qdir), 1789 w->w_name + 2, sequenceno, njobs); 1790 } 1791 else 1792 { 1793 if (Verbose) 1794 { 1795 message(EmptyString); 1796 message("Running %s/%s (sequence %d of %d)", 1797 qid_printqueue(w->w_qgrp, w->w_qdir), 1798 w->w_name + 2, sequenceno, njobs); 1799 } 1800 if (didfork && MaxQueueChildren > 0) 1801 { 1802 sm_blocksignal(SIGCHLD); 1803 (void) sm_signal(SIGCHLD, reapchild); 1804 } 1805 if (tTd(63, 100)) 1806 sm_syslog(LOG_DEBUG, NOQID, 1807 "runqueue %s dowork(%s)", 1808 qid_printqueue(w->w_qgrp, w->w_qdir), 1809 w->w_name + 2); 1810 1811 (void) dowork(w->w_qgrp, w->w_qdir, w->w_name + 2, 1812 ForkQueueRuns, false, e); 1813 errno = 0; 1814 } 1815 sm_free(w->w_name); /* XXX */ 1816 if (w->w_host != NULL) 1817 sm_free(w->w_host); /* XXX */ 1818 sm_free((char *) w); /* XXX */ 1819 sequenceno += seqjump; /* next sequence number */ 1820#if SM_HEAP_CHECK 1821 if (sm_debug_active(&DebugLeakQ, 1)) 1822 sm_heap_setgroup(oldgroup); 1823#endif /* SM_HEAP_CHECK */ 1824 } 1825 1826 BlockOldsh = false; 1827 1828 /* check the signals didn't happen during the revert */ 1829 if (NoMoreRunners) 1830 { 1831 /* Check that a valid signal handler is callable */ 1832 if (Oldsh != SIG_DFL && Oldsh != SIG_IGN && 1833 Oldsh != runners_sighup && Oldsh != runners_sigterm) 1834 (*Oldsh)(Oldsig); 1835 } 1836 1837 Oldsh = SIG_DFL; /* after the NoMoreRunners check */ 1838} 1839/* 1840** RUN_WORK_GROUP -- run the jobs in a queue group from a work group. 1841** 1842** Gets the stuff out of the queue in some presumably logical 1843** order and processes them. 1844** 1845** Parameters: 1846** wgrp -- work group to process. 1847** flags -- RWG_* flags 1848** 1849** Returns: 1850** true if the queue run successfully began. 1851** 1852** Side Effects: 1853** runs things in the mail queue. 1854*/ 1855 1856/* Minimum sleep time for persistent queue runners */ 1857#define MIN_SLEEP_TIME 5 1858 1859bool 1860run_work_group(wgrp, flags) 1861 int wgrp; 1862 int flags; 1863{ 1864 register ENVELOPE *e; 1865 int njobs, qdir; 1866 int sequenceno = 1; 1867 int qgrp, endgrp, h, i; 1868 time_t now; 1869 bool full, more; 1870 SM_RPOOL_T *rpool; 1871 extern void rmexpstab __P((void)); 1872 extern ENVELOPE BlankEnvelope; 1873 extern SIGFUNC_DECL reapchild __P((int)); 1874 1875 if (wgrp < 0) 1876 return false; 1877 1878 /* 1879 ** If no work will ever be selected, don't even bother reading 1880 ** the queue. 1881 */ 1882 1883 SM_GET_LA(now); 1884 1885 if (!bitset(RWG_PERSISTENT, flags) && 1886 shouldqueue(WkRecipFact, Current_LA_time)) 1887 { 1888 char *msg = "Skipping queue run -- load average too high"; 1889 1890 if (bitset(RWG_VERBOSE, flags)) 1891 message("458 %s\n", msg); 1892 if (LogLevel > 8) 1893 sm_syslog(LOG_INFO, NOQID, "runqueue: %s", msg); 1894 return false; 1895 } 1896 1897 /* 1898 ** See if we already have too many children. 1899 */ 1900 1901 if (bitset(RWG_FORK, flags) && 1902 WorkGrp[wgrp].wg_lowqintvl > 0 && 1903 !bitset(RWG_PERSISTENT, flags) && 1904 MaxChildren > 0 && CurChildren >= MaxChildren) 1905 { 1906 char *msg = "Skipping queue run -- too many children"; 1907 1908 if (bitset(RWG_VERBOSE, flags)) 1909 message("458 %s (%d)\n", msg, CurChildren); 1910 if (LogLevel > 8) 1911 sm_syslog(LOG_INFO, NOQID, "runqueue: %s (%d)", 1912 msg, CurChildren); 1913 return false; 1914 } 1915 1916 /* 1917 ** See if we want to go off and do other useful work. 1918 */ 1919 1920 if (bitset(RWG_FORK, flags)) 1921 { 1922 pid_t pid; 1923 1924 (void) sm_blocksignal(SIGCHLD); 1925 (void) sm_signal(SIGCHLD, reapchild); 1926 1927 pid = dofork(); 1928 if (pid == -1) 1929 { 1930 const char *msg = "Skipping queue run -- fork() failed"; 1931 const char *err = sm_errstring(errno); 1932 1933 if (bitset(RWG_VERBOSE, flags)) 1934 message("458 %s: %s\n", msg, err); 1935 if (LogLevel > 8) 1936 sm_syslog(LOG_INFO, NOQID, "runqueue: %s: %s", 1937 msg, err); 1938 (void) sm_releasesignal(SIGCHLD); 1939 return false; 1940 } 1941 if (pid != 0) 1942 { 1943 /* parent -- pick up intermediate zombie */ 1944 (void) sm_blocksignal(SIGALRM); 1945 1946 /* wgrp only used when queue runners are persistent */ 1947 proc_list_add(pid, "Queue runner", PROC_QUEUE, 1948 WorkGrp[wgrp].wg_maxact, 1949 bitset(RWG_PERSISTENT, flags) ? wgrp : -1, 1950 NULL); 1951 (void) sm_releasesignal(SIGALRM); 1952 (void) sm_releasesignal(SIGCHLD); 1953 return true; 1954 } 1955 1956 /* child -- clean up signals */ 1957 1958 /* Reset global flags */ 1959 RestartRequest = NULL; 1960 RestartWorkGroup = false; 1961 ShutdownRequest = NULL; 1962 PendingSignal = 0; 1963 CurrentPid = getpid(); 1964 close_sendmail_pid(); 1965 1966 /* 1967 ** Initialize exception stack and default exception 1968 ** handler for child process. 1969 */ 1970 1971 sm_exc_newthread(fatal_error); 1972 clrcontrol(); 1973 proc_list_clear(); 1974 1975 /* Add parent process as first child item */ 1976 proc_list_add(CurrentPid, "Queue runner child process", 1977 PROC_QUEUE_CHILD, 0, -1, NULL); 1978 (void) sm_releasesignal(SIGCHLD); 1979 (void) sm_signal(SIGCHLD, SIG_DFL); 1980 (void) sm_signal(SIGHUP, SIG_DFL); 1981 (void) sm_signal(SIGTERM, intsig); 1982 } 1983 1984 /* 1985 ** Release any resources used by the daemon code. 1986 */ 1987 1988 clrdaemon(); 1989 1990 /* force it to run expensive jobs */ 1991 NoConnect = false; 1992 1993 /* drop privileges */ 1994 if (geteuid() == (uid_t) 0) 1995 (void) drop_privileges(false); 1996 1997 /* 1998 ** Create ourselves an envelope 1999 */ 2000 2001 CurEnv = &QueueEnvelope; 2002 rpool = sm_rpool_new_x(NULL); 2003 e = newenvelope(&QueueEnvelope, CurEnv, rpool); 2004 e->e_flags = BlankEnvelope.e_flags; 2005 e->e_parent = NULL; 2006 2007 /* make sure we have disconnected from parent */ 2008 if (bitset(RWG_FORK, flags)) 2009 { 2010 disconnect(1, e); 2011 QuickAbort = false; 2012 } 2013 2014 /* 2015 ** If we are running part of the queue, always ignore stored 2016 ** host status. 2017 */ 2018 2019 if (QueueLimitId != NULL || QueueLimitSender != NULL || 2020 QueueLimitQuarantine != NULL || 2021 QueueLimitRecipient != NULL) 2022 { 2023 IgnoreHostStatus = true; 2024 MinQueueAge = 0; 2025 } 2026 2027 /* 2028 ** Here is where we choose the queue group from the work group. 2029 ** The caller of the "domorework" label must setup a new envelope. 2030 */ 2031 2032 endgrp = WorkGrp[wgrp].wg_curqgrp; /* to not spin endlessly */ 2033 2034 domorework: 2035 2036 /* 2037 ** Run a queue group if: 2038 ** RWG_RUNALL bit is set or the bit for this group is set. 2039 */ 2040 2041 now = curtime(); 2042 for (;;) 2043 { 2044 /* 2045 ** Find the next queue group within the work group that 2046 ** has been marked as needing a run. 2047 */ 2048 2049 qgrp = WorkGrp[wgrp].wg_qgs[WorkGrp[wgrp].wg_curqgrp]->qg_index; 2050 WorkGrp[wgrp].wg_curqgrp++; /* advance */ 2051 WorkGrp[wgrp].wg_curqgrp %= WorkGrp[wgrp].wg_numqgrp; /* wrap */ 2052 if (bitset(RWG_RUNALL, flags) || 2053 (Queue[qgrp]->qg_nextrun <= now && 2054 Queue[qgrp]->qg_nextrun != (time_t) -1)) 2055 break; 2056 if (endgrp == WorkGrp[wgrp].wg_curqgrp) 2057 { 2058 e->e_id = NULL; 2059 if (bitset(RWG_FORK, flags)) 2060 finis(true, true, ExitStat); 2061 return true; /* we're done */ 2062 } 2063 } 2064 2065 qdir = Queue[qgrp]->qg_curnum; /* round-robin init of queue position */ 2066#if _FFR_QUEUE_SCHED_DBG 2067 if (tTd(69, 12)) 2068 sm_syslog(LOG_INFO, NOQID, 2069 "rwg: wgrp=%d, qgrp=%d, qdir=%d, name=%s, curqgrp=%d, numgrps=%d", 2070 wgrp, qgrp, qdir, qid_printqueue(qgrp, qdir), 2071 WorkGrp[wgrp].wg_curqgrp, WorkGrp[wgrp].wg_numqgrp); 2072#endif /* _FFR_QUEUE_SCHED_DBG */ 2073 2074#if HASNICE 2075 /* tweak niceness of queue runs */ 2076 if (Queue[qgrp]->qg_nice > 0) 2077 (void) nice(Queue[qgrp]->qg_nice); 2078#endif /* HASNICE */ 2079 2080 /* XXX running queue group... */ 2081 sm_setproctitle(true, CurEnv, "running queue: %s", 2082 qid_printqueue(qgrp, qdir)); 2083 2084 if (LogLevel > 69 || tTd(63, 99)) 2085 sm_syslog(LOG_DEBUG, NOQID, 2086 "runqueue %s, pid=%d, forkflag=%d", 2087 qid_printqueue(qgrp, qdir), (int) CurrentPid, 2088 bitset(RWG_FORK, flags)); 2089 2090 /* 2091 ** Start making passes through the queue. 2092 ** First, read and sort the entire queue. 2093 ** Then, process the work in that order. 2094 ** But if you take too long, start over. 2095 */ 2096 2097 for (i = 0; i < Queue[qgrp]->qg_numqueues; i++) 2098 { 2099 h = gatherq(qgrp, qdir, false, &full, &more); 2100#if SM_CONF_SHM 2101 if (ShmId != SM_SHM_NO_ID) 2102 QSHM_ENTRIES(Queue[qgrp]->qg_qpaths[qdir].qp_idx) = h; 2103#endif /* SM_CONF_SHM */ 2104 /* If there are no more items in this queue advance */ 2105 if (!more) 2106 { 2107 /* A round-robin advance */ 2108 qdir++; 2109 qdir %= Queue[qgrp]->qg_numqueues; 2110 } 2111 2112 /* Has the WorkList reached the limit? */ 2113 if (full) 2114 break; /* don't try to gather more */ 2115 } 2116 2117 /* order the existing work requests */ 2118 njobs = sortq(Queue[qgrp]->qg_maxlist); 2119 Queue[qgrp]->qg_curnum = qdir; /* update */ 2120 2121 2122 if (!Verbose && bitnset(QD_FORK, Queue[qgrp]->qg_flags)) 2123 { 2124 int loop, maxrunners; 2125 pid_t pid; 2126 2127 /* 2128 ** For this WorkQ we want to fork off N children (maxrunners) 2129 ** at this point. Each child has a copy of WorkQ. Each child 2130 ** will process every N-th item. The parent will wait for all 2131 ** of the children to finish before moving on to the next 2132 ** queue group within the work group. This saves us forking 2133 ** a new runner-child for each work item. 2134 ** It's valid for qg_maxqrun == 0 since this may be an 2135 ** explicit "don't run this queue" setting. 2136 */ 2137 2138 maxrunners = Queue[qgrp]->qg_maxqrun; 2139 2140 /* No need to have more runners then there are jobs */ 2141 if (maxrunners > njobs) 2142 maxrunners = njobs; 2143 for (loop = 0; loop < maxrunners; loop++) 2144 { 2145 /* 2146 ** Since the delivery may happen in a child and the 2147 ** parent does not wait, the parent may close the 2148 ** maps thereby removing any shared memory used by 2149 ** the map. Therefore, close the maps now so the 2150 ** child will dynamically open them if necessary. 2151 */ 2152 2153 closemaps(false); 2154 2155 pid = fork(); 2156 if (pid < 0) 2157 { 2158 syserr("run_work_group: cannot fork"); 2159 return false; 2160 } 2161 else if (pid > 0) 2162 { 2163 /* parent -- clean out connection cache */ 2164 mci_flush(false, NULL); 2165#if _FFR_SKIP_DOMAINS 2166 if (QueueSortOrder == QSO_BYHOST) 2167 { 2168 sequenceno += skip_domains(1); 2169 } 2170 else 2171#endif /* _FFR_SKIP_DOMAINS */ 2172 { 2173 /* for the skip */ 2174 WorkQ = WorkQ->w_next; 2175 sequenceno++; 2176 } 2177 proc_list_add(pid, "Queue child runner process", 2178 PROC_QUEUE_CHILD, 0, -1, NULL); 2179 2180 /* No additional work, no additional runners */ 2181 if (WorkQ == NULL) 2182 break; 2183 } 2184 else 2185 { 2186 /* child -- Reset global flags */ 2187 RestartRequest = NULL; 2188 RestartWorkGroup = false; 2189 ShutdownRequest = NULL; 2190 PendingSignal = 0; 2191 CurrentPid = getpid(); 2192 close_sendmail_pid(); 2193 2194 /* 2195 ** Initialize exception stack and default 2196 ** exception handler for child process. 2197 ** When fork()'d the child now has a private 2198 ** copy of WorkQ at its current position. 2199 */ 2200 2201 sm_exc_newthread(fatal_error); 2202 2203 /* 2204 ** SMTP processes (whether -bd or -bs) set 2205 ** SIGCHLD to reapchild to collect 2206 ** children status. However, at delivery 2207 ** time, that status must be collected 2208 ** by sm_wait() to be dealt with properly 2209 ** (check success of delivery based 2210 ** on status code, etc). Therefore, if we 2211 ** are an SMTP process, reset SIGCHLD 2212 ** back to the default so reapchild 2213 ** doesn't collect status before 2214 ** sm_wait(). 2215 */ 2216 2217 if (OpMode == MD_SMTP || 2218 OpMode == MD_DAEMON || 2219 MaxQueueChildren > 0) 2220 { 2221 proc_list_clear(); 2222 sm_releasesignal(SIGCHLD); 2223 (void) sm_signal(SIGCHLD, SIG_DFL); 2224 } 2225 2226 /* child -- error messages to the transcript */ 2227 QuickAbort = OnlyOneError = false; 2228 runner_work(e, sequenceno, true, 2229 maxrunners, njobs); 2230 2231 /* This child is done */ 2232 finis(true, true, ExitStat); 2233 /* NOTREACHED */ 2234 } 2235 } 2236 2237 sm_releasesignal(SIGCHLD); 2238 2239 /* 2240 ** Wait until all of the runners have completed before 2241 ** seeing if there is another queue group in the 2242 ** work group to process. 2243 ** XXX Future enhancement: don't wait() for all children 2244 ** here, just go ahead and make sure that overall the number 2245 ** of children is not exceeded. 2246 */ 2247 2248 while (CurChildren > 0) 2249 { 2250 int status; 2251 pid_t ret; 2252 2253 while ((ret = sm_wait(&status)) <= 0) 2254 continue; 2255 proc_list_drop(ret, status, NULL); 2256 } 2257 } 2258 else if (Queue[qgrp]->qg_maxqrun > 0 || bitset(RWG_FORCE, flags)) 2259 { 2260 /* 2261 ** When current process will not fork children to do the work, 2262 ** it will do the work itself. The 'skip' will be 1 since 2263 ** there are no child runners to divide the work across. 2264 */ 2265 2266 runner_work(e, sequenceno, false, 1, njobs); 2267 } 2268 2269 /* free memory allocated by newenvelope() above */ 2270 sm_rpool_free(rpool); 2271 QueueEnvelope.e_rpool = NULL; 2272 2273 /* Are there still more queues in the work group to process? */ 2274 if (endgrp != WorkGrp[wgrp].wg_curqgrp) 2275 { 2276 rpool = sm_rpool_new_x(NULL); 2277 e = newenvelope(&QueueEnvelope, CurEnv, rpool); 2278 e->e_flags = BlankEnvelope.e_flags; 2279 goto domorework; 2280 } 2281 2282 /* No more queues in work group to process. Now check persistent. */ 2283 if (bitset(RWG_PERSISTENT, flags)) 2284 { 2285 sequenceno = 1; 2286 sm_setproctitle(true, CurEnv, "running queue: %s", 2287 qid_printqueue(qgrp, qdir)); 2288 2289 /* 2290 ** close bogus maps, i.e., maps which caused a tempfail, 2291 ** so we get fresh map connections on the next lookup. 2292 ** closemaps() is also called when children are started. 2293 */ 2294 2295 closemaps(true); 2296 2297 /* Close any cached connections. */ 2298 mci_flush(true, NULL); 2299 2300 /* Clean out expired related entries. */ 2301 rmexpstab(); 2302 2303#if NAMED_BIND 2304 /* Update MX records for FallbackMX. */ 2305 if (FallbackMX != NULL) 2306 (void) getfallbackmxrr(FallbackMX); 2307#endif /* NAMED_BIND */ 2308 2309#if USERDB 2310 /* close UserDatabase */ 2311 _udbx_close(); 2312#endif /* USERDB */ 2313 2314#if SM_HEAP_CHECK 2315 if (sm_debug_active(&SmHeapCheck, 2) 2316 && access("memdump", F_OK) == 0 2317 ) 2318 { 2319 SM_FILE_T *out; 2320 2321 remove("memdump"); 2322 out = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, 2323 "memdump.out", SM_IO_APPEND, NULL); 2324 if (out != NULL) 2325 { 2326 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n"); 2327 sm_heap_report(out, 2328 sm_debug_level(&SmHeapCheck) - 1); 2329 (void) sm_io_close(out, SM_TIME_DEFAULT); 2330 } 2331 } 2332#endif /* SM_HEAP_CHECK */ 2333 2334 /* let me rest for a second to catch my breath */ 2335 if (njobs == 0 && WorkGrp[wgrp].wg_lowqintvl < MIN_SLEEP_TIME) 2336 sleep(MIN_SLEEP_TIME); 2337 else if (WorkGrp[wgrp].wg_lowqintvl <= 0) 2338 sleep(QueueIntvl > 0 ? QueueIntvl : MIN_SLEEP_TIME); 2339 else 2340 sleep(WorkGrp[wgrp].wg_lowqintvl); 2341 2342 /* 2343 ** Get the LA outside the WorkQ loop if necessary. 2344 ** In a persistent queue runner the code is repeated over 2345 ** and over but gatherq() may ignore entries due to 2346 ** shouldqueue() (do we really have to do this twice?). 2347 ** Hence the queue runners would just idle around when once 2348 ** CurrentLA caused all entries in a queue to be ignored. 2349 */ 2350 2351 if (njobs == 0) 2352 SM_GET_LA(now); 2353 rpool = sm_rpool_new_x(NULL); 2354 e = newenvelope(&QueueEnvelope, CurEnv, rpool); 2355 e->e_flags = BlankEnvelope.e_flags; 2356 goto domorework; 2357 } 2358 2359 /* exit without the usual cleanup */ 2360 e->e_id = NULL; 2361 if (bitset(RWG_FORK, flags)) 2362 finis(true, true, ExitStat); 2363 /* NOTREACHED */ 2364 return true; 2365} 2366 2367/* 2368** DOQUEUERUN -- do a queue run? 2369*/ 2370 2371bool 2372doqueuerun() 2373{ 2374 return DoQueueRun; 2375} 2376 2377/* 2378** RUNQUEUEEVENT -- Sets a flag to indicate that a queue run should be done. 2379** 2380** Parameters: 2381** none. 2382** 2383** Returns: 2384** none. 2385** 2386** Side Effects: 2387** The invocation of this function via an alarm may interrupt 2388** a set of actions. Thus errno may be set in that context. 2389** We need to restore errno at the end of this function to ensure 2390** that any work done here that sets errno doesn't return a 2391** misleading/false errno value. Errno may be EINTR upon entry to 2392** this function because of non-restartable/continuable system 2393** API was active. Iff this is true we will override errno as 2394** a timeout (as a more accurate error message). 2395** 2396** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2397** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2398** DOING. 2399*/ 2400 2401void 2402runqueueevent(ignore) 2403 int ignore; 2404{ 2405 int save_errno = errno; 2406 2407 /* 2408 ** Set the general bit that we want a queue run, 2409 ** tested in doqueuerun() 2410 */ 2411 2412 DoQueueRun = true; 2413#if _FFR_QUEUE_SCHED_DBG 2414 if (tTd(69, 10)) 2415 sm_syslog(LOG_INFO, NOQID, "rqe: done"); 2416#endif /* _FFR_QUEUE_SCHED_DBG */ 2417 2418 errno = save_errno; 2419 if (errno == EINTR) 2420 errno = ETIMEDOUT; 2421} 2422/* 2423** GATHERQ -- gather messages from the message queue(s) the work queue. 2424** 2425** Parameters: 2426** qgrp -- the index of the queue group. 2427** qdir -- the index of the queue directory. 2428** doall -- if set, include everything in the queue (even 2429** the jobs that cannot be run because the load 2430** average is too high, or MaxQueueRun is reached). 2431** Otherwise, exclude those jobs. 2432** full -- (optional) to be set 'true' if WorkList is full 2433** more -- (optional) to be set 'true' if there are still more 2434** messages in this queue not added to WorkList 2435** 2436** Returns: 2437** The number of request in the queue (not necessarily 2438** the number of requests in WorkList however). 2439** 2440** Side Effects: 2441** prepares available work into WorkList 2442*/ 2443 2444#define NEED_P 0001 /* 'P': priority */ 2445#define NEED_T 0002 /* 'T': time */ 2446#define NEED_R 0004 /* 'R': recipient */ 2447#define NEED_S 0010 /* 'S': sender */ 2448#define NEED_H 0020 /* host */ 2449#define HAS_QUARANTINE 0040 /* has an unexpected 'q' line */ 2450#define NEED_QUARANTINE 0100 /* 'q': reason */ 2451 2452static WORK *WorkList = NULL; /* list of unsort work */ 2453static int WorkListSize = 0; /* current max size of WorkList */ 2454static int WorkListCount = 0; /* # of work items in WorkList */ 2455 2456static int 2457gatherq(qgrp, qdir, doall, full, more) 2458 int qgrp; 2459 int qdir; 2460 bool doall; 2461 bool *full; 2462 bool *more; 2463{ 2464 register struct dirent *d; 2465 register WORK *w; 2466 register char *p; 2467 DIR *f; 2468 int i, num_ent; 2469 int wn; 2470 QUEUE_CHAR *check; 2471 char qd[MAXPATHLEN]; 2472 char qf[MAXPATHLEN]; 2473 2474 wn = WorkListCount - 1; 2475 num_ent = 0; 2476 if (qdir == NOQDIR) 2477 (void) sm_strlcpy(qd, ".", sizeof qd); 2478 else 2479 (void) sm_strlcpyn(qd, sizeof qd, 2, 2480 Queue[qgrp]->qg_qpaths[qdir].qp_name, 2481 (bitset(QP_SUBQF, 2482 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 2483 ? "/qf" : "")); 2484 2485 if (tTd(41, 1)) 2486 { 2487 sm_dprintf("gatherq:\n"); 2488 2489 check = QueueLimitId; 2490 while (check != NULL) 2491 { 2492 sm_dprintf("\tQueueLimitId = %s%s\n", 2493 check->queue_negate ? "!" : "", 2494 check->queue_match); 2495 check = check->queue_next; 2496 } 2497 2498 check = QueueLimitSender; 2499 while (check != NULL) 2500 { 2501 sm_dprintf("\tQueueLimitSender = %s%s\n", 2502 check->queue_negate ? "!" : "", 2503 check->queue_match); 2504 check = check->queue_next; 2505 } 2506 2507 check = QueueLimitRecipient; 2508 while (check != NULL) 2509 { 2510 sm_dprintf("\tQueueLimitRecipient = %s%s\n", 2511 check->queue_negate ? "!" : "", 2512 check->queue_match); 2513 check = check->queue_next; 2514 } 2515 2516 if (QueueMode == QM_QUARANTINE) 2517 { 2518 check = QueueLimitQuarantine; 2519 while (check != NULL) 2520 { 2521 sm_dprintf("\tQueueLimitQuarantine = %s%s\n", 2522 check->queue_negate ? "!" : "", 2523 check->queue_match); 2524 check = check->queue_next; 2525 } 2526 } 2527 } 2528 2529 /* open the queue directory */ 2530 f = opendir(qd); 2531 if (f == NULL) 2532 { 2533 syserr("gatherq: cannot open \"%s\"", 2534 qid_printqueue(qgrp, qdir)); 2535 if (full != NULL) 2536 *full = WorkListCount >= MaxQueueRun && MaxQueueRun > 0; 2537 if (more != NULL) 2538 *more = false; 2539 return 0; 2540 } 2541 2542 /* 2543 ** Read the work directory. 2544 */ 2545 2546 while ((d = readdir(f)) != NULL) 2547 { 2548 SM_FILE_T *cf; 2549 int qfver = 0; 2550 char lbuf[MAXNAME + 1]; 2551 struct stat sbuf; 2552 2553 if (tTd(41, 50)) 2554 sm_dprintf("gatherq: checking %s..", d->d_name); 2555 2556 /* is this an interesting entry? */ 2557 if (!(((QueueMode == QM_NORMAL && 2558 d->d_name[0] == NORMQF_LETTER) || 2559 (QueueMode == QM_QUARANTINE && 2560 d->d_name[0] == QUARQF_LETTER) || 2561 (QueueMode == QM_LOST && 2562 d->d_name[0] == LOSEQF_LETTER)) && 2563 d->d_name[1] == 'f')) 2564 { 2565 if (tTd(41, 50)) 2566 sm_dprintf(" skipping\n"); 2567 continue; 2568 } 2569 if (tTd(41, 50)) 2570 sm_dprintf("\n"); 2571 2572 if (strlen(d->d_name) >= MAXQFNAME) 2573 { 2574 if (Verbose) 2575 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 2576 "gatherq: %s too long, %d max characters\n", 2577 d->d_name, MAXQFNAME); 2578 if (LogLevel > 0) 2579 sm_syslog(LOG_ALERT, NOQID, 2580 "gatherq: %s too long, %d max characters", 2581 d->d_name, MAXQFNAME); 2582 continue; 2583 } 2584 2585 check = QueueLimitId; 2586 while (check != NULL) 2587 { 2588 if (strcontainedin(false, check->queue_match, 2589 d->d_name) != check->queue_negate) 2590 break; 2591 else 2592 check = check->queue_next; 2593 } 2594 if (QueueLimitId != NULL && check == NULL) 2595 continue; 2596 2597 /* grow work list if necessary */ 2598 if (++wn >= MaxQueueRun && MaxQueueRun > 0) 2599 { 2600 if (wn == MaxQueueRun && LogLevel > 0) 2601 sm_syslog(LOG_WARNING, NOQID, 2602 "WorkList for %s maxed out at %d", 2603 qid_printqueue(qgrp, qdir), 2604 MaxQueueRun); 2605 if (doall) 2606 continue; /* just count entries */ 2607 break; 2608 } 2609 if (wn >= WorkListSize) 2610 { 2611 grow_wlist(qgrp, qdir); 2612 if (wn >= WorkListSize) 2613 continue; 2614 } 2615 SM_ASSERT(wn >= 0); 2616 w = &WorkList[wn]; 2617 2618 (void) sm_strlcpyn(qf, sizeof qf, 3, qd, "/", d->d_name); 2619 if (stat(qf, &sbuf) < 0) 2620 { 2621 if (errno != ENOENT) 2622 sm_syslog(LOG_INFO, NOQID, 2623 "gatherq: can't stat %s/%s", 2624 qid_printqueue(qgrp, qdir), 2625 d->d_name); 2626 wn--; 2627 continue; 2628 } 2629 if (!bitset(S_IFREG, sbuf.st_mode)) 2630 { 2631 /* Yikes! Skip it or we will hang on open! */ 2632 if (!((d->d_name[0] == DATAFL_LETTER || 2633 d->d_name[0] == NORMQF_LETTER || 2634 d->d_name[0] == QUARQF_LETTER || 2635 d->d_name[0] == LOSEQF_LETTER || 2636 d->d_name[0] == XSCRPT_LETTER) && 2637 d->d_name[1] == 'f' && d->d_name[2] == '\0')) 2638 syserr("gatherq: %s/%s is not a regular file", 2639 qid_printqueue(qgrp, qdir), d->d_name); 2640 wn--; 2641 continue; 2642 } 2643 2644 /* avoid work if possible */ 2645 if ((QueueSortOrder == QSO_BYFILENAME || 2646 QueueSortOrder == QSO_BYMODTIME || 2647 QueueSortOrder == QSO_RANDOM) && 2648 QueueLimitQuarantine == NULL && 2649 QueueLimitSender == NULL && 2650 QueueLimitRecipient == NULL) 2651 { 2652 w->w_qgrp = qgrp; 2653 w->w_qdir = qdir; 2654 w->w_name = newstr(d->d_name); 2655 w->w_host = NULL; 2656 w->w_lock = w->w_tooyoung = false; 2657 w->w_pri = 0; 2658 w->w_ctime = 0; 2659 w->w_mtime = sbuf.st_mtime; 2660 ++num_ent; 2661 continue; 2662 } 2663 2664 /* open control file */ 2665 cf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B, 2666 NULL); 2667 if (cf == NULL && OpMode != MD_PRINT) 2668 { 2669 /* this may be some random person sending hir msgs */ 2670 if (tTd(41, 2)) 2671 sm_dprintf("gatherq: cannot open %s: %s\n", 2672 d->d_name, sm_errstring(errno)); 2673 errno = 0; 2674 wn--; 2675 continue; 2676 } 2677 w->w_qgrp = qgrp; 2678 w->w_qdir = qdir; 2679 w->w_name = newstr(d->d_name); 2680 w->w_host = NULL; 2681 if (cf != NULL) 2682 { 2683 w->w_lock = !lockfile(sm_io_getinfo(cf, SM_IO_WHAT_FD, 2684 NULL), 2685 w->w_name, NULL, 2686 LOCK_SH|LOCK_NB); 2687 } 2688 w->w_tooyoung = false; 2689 2690 /* make sure jobs in creation don't clog queue */ 2691 w->w_pri = 0x7fffffff; 2692 w->w_ctime = 0; 2693 w->w_mtime = sbuf.st_mtime; 2694 2695 /* extract useful information */ 2696 i = NEED_P|NEED_T; 2697 if (QueueSortOrder == QSO_BYHOST 2698#if _FFR_RHS 2699 || QueueSortOrder == QSO_BYSHUFFLE 2700#endif /* _FFR_RHS */ 2701 ) 2702 { 2703 /* need w_host set for host sort order */ 2704 i |= NEED_H; 2705 } 2706 if (QueueLimitSender != NULL) 2707 i |= NEED_S; 2708 if (QueueLimitRecipient != NULL) 2709 i |= NEED_R; 2710 if (QueueLimitQuarantine != NULL) 2711 i |= NEED_QUARANTINE; 2712 while (cf != NULL && i != 0 && 2713 sm_io_fgets(cf, SM_TIME_DEFAULT, lbuf, 2714 sizeof lbuf) != NULL) 2715 { 2716 int c; 2717 time_t age; 2718 2719 p = strchr(lbuf, '\n'); 2720 if (p != NULL) 2721 *p = '\0'; 2722 else 2723 { 2724 /* flush rest of overly long line */ 2725 while ((c = sm_io_getc(cf, SM_TIME_DEFAULT)) 2726 != SM_IO_EOF && c != '\n') 2727 continue; 2728 } 2729 2730 switch (lbuf[0]) 2731 { 2732 case 'V': 2733 qfver = atoi(&lbuf[1]); 2734 break; 2735 2736 case 'P': 2737 w->w_pri = atol(&lbuf[1]); 2738 i &= ~NEED_P; 2739 break; 2740 2741 case 'T': 2742 w->w_ctime = atol(&lbuf[1]); 2743 i &= ~NEED_T; 2744 break; 2745 2746 case 'q': 2747 if (QueueMode != QM_QUARANTINE && 2748 QueueMode != QM_LOST) 2749 { 2750 if (tTd(41, 49)) 2751 sm_dprintf("%s not marked as quarantined but has a 'q' line\n", 2752 w->w_name); 2753 i |= HAS_QUARANTINE; 2754 } 2755 else if (QueueMode == QM_QUARANTINE) 2756 { 2757 if (QueueLimitQuarantine == NULL) 2758 { 2759 i &= ~NEED_QUARANTINE; 2760 break; 2761 } 2762 p = &lbuf[1]; 2763 check = QueueLimitQuarantine; 2764 while (check != NULL) 2765 { 2766 if (strcontainedin(false, 2767 check->queue_match, 2768 p) != 2769 check->queue_negate) 2770 break; 2771 else 2772 check = check->queue_next; 2773 } 2774 if (check != NULL) 2775 i &= ~NEED_QUARANTINE; 2776 } 2777 break; 2778 2779 case 'R': 2780 if (w->w_host == NULL && 2781 (p = strrchr(&lbuf[1], '@')) != NULL) 2782 { 2783#if _FFR_RHS 2784 if (QueueSortOrder == QSO_BYSHUFFLE) 2785 w->w_host = newstr(&p[1]); 2786 else 2787#endif /* _FFR_RHS */ 2788 w->w_host = strrev(&p[1]); 2789 makelower(w->w_host); 2790 i &= ~NEED_H; 2791 } 2792 if (QueueLimitRecipient == NULL) 2793 { 2794 i &= ~NEED_R; 2795 break; 2796 } 2797 if (qfver > 0) 2798 { 2799 p = strchr(&lbuf[1], ':'); 2800 if (p == NULL) 2801 p = &lbuf[1]; 2802 else 2803 ++p; /* skip over ':' */ 2804 } 2805 else 2806 p = &lbuf[1]; 2807 check = QueueLimitRecipient; 2808 while (check != NULL) 2809 { 2810 if (strcontainedin(true, 2811 check->queue_match, 2812 p) != 2813 check->queue_negate) 2814 break; 2815 else 2816 check = check->queue_next; 2817 } 2818 if (check != NULL) 2819 i &= ~NEED_R; 2820 break; 2821 2822 case 'S': 2823 check = QueueLimitSender; 2824 while (check != NULL) 2825 { 2826 if (strcontainedin(true, 2827 check->queue_match, 2828 &lbuf[1]) != 2829 check->queue_negate) 2830 break; 2831 else 2832 check = check->queue_next; 2833 } 2834 if (check != NULL) 2835 i &= ~NEED_S; 2836 break; 2837 2838 case 'K': 2839 age = curtime() - (time_t) atol(&lbuf[1]); 2840 if (age >= 0 && MinQueueAge > 0 && 2841 age < MinQueueAge) 2842 w->w_tooyoung = true; 2843 break; 2844 2845 case 'N': 2846 if (atol(&lbuf[1]) == 0) 2847 w->w_tooyoung = false; 2848 break; 2849 } 2850 } 2851 if (cf != NULL) 2852 (void) sm_io_close(cf, SM_TIME_DEFAULT); 2853 2854 if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) || 2855 bitset(HAS_QUARANTINE, i) || 2856 bitset(NEED_QUARANTINE, i) || 2857 bitset(NEED_R|NEED_S, i)) 2858 { 2859 /* don't even bother sorting this job in */ 2860 if (tTd(41, 49)) 2861 sm_dprintf("skipping %s (%x)\n", w->w_name, i); 2862 sm_free(w->w_name); /* XXX */ 2863 if (w->w_host != NULL) 2864 sm_free(w->w_host); /* XXX */ 2865 wn--; 2866 } 2867 else 2868 ++num_ent; 2869 } 2870 (void) closedir(f); 2871 wn++; 2872 2873 i = wn - WorkListCount; 2874 WorkListCount += SM_MIN(num_ent, WorkListSize); 2875 2876 if (more != NULL) 2877 *more = WorkListCount < wn; 2878 2879 if (full != NULL) 2880 *full = (wn >= MaxQueueRun && MaxQueueRun > 0) || 2881 (WorkList == NULL && wn > 0); 2882 2883 return i; 2884} 2885/* 2886** SORTQ -- sort the work list 2887** 2888** First the old WorkQ is cleared away. Then the WorkList is sorted 2889** for all items so that important (higher sorting value) items are not 2890** trunctated off. Then the most important items are moved from 2891** WorkList to WorkQ. The lower count of 'max' or MaxListCount items 2892** are moved. 2893** 2894** Parameters: 2895** max -- maximum number of items to be placed in WorkQ 2896** 2897** Returns: 2898** the number of items in WorkQ 2899** 2900** Side Effects: 2901** WorkQ gets released and filled with new work. WorkList 2902** gets released. Work items get sorted in order. 2903*/ 2904 2905static int 2906sortq(max) 2907 int max; 2908{ 2909 register int i; /* local counter */ 2910 register WORK *w; /* tmp item pointer */ 2911 int wc = WorkListCount; /* trim size for WorkQ */ 2912 2913 if (WorkQ != NULL) 2914 { 2915 WORK *nw; 2916 2917 /* Clear out old WorkQ. */ 2918 for (w = WorkQ; w != NULL; w = nw) 2919 { 2920 nw = w->w_next; 2921 sm_free(w->w_name); /* XXX */ 2922 if (w->w_host != NULL) 2923 sm_free(w->w_host); /* XXX */ 2924 sm_free((char *) w); /* XXX */ 2925 } 2926 WorkQ = NULL; 2927 } 2928 2929 if (WorkList == NULL || wc <= 0) 2930 return 0; 2931 2932 /* Check if the per queue group item limit will be exceeded */ 2933 if (wc > max && max > 0) 2934 wc = max; 2935 2936 /* 2937 ** The sort now takes place using all of the items in WorkList. 2938 ** The list gets trimmed to the most important items after the sort. 2939 ** If the trim were to happen before the sort then one or more 2940 ** important items might get truncated off -- not what we want. 2941 */ 2942 2943 if (QueueSortOrder == QSO_BYHOST) 2944 { 2945 /* 2946 ** Sort the work directory for the first time, 2947 ** based on host name, lock status, and priority. 2948 */ 2949 2950 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1); 2951 2952 /* 2953 ** If one message to host is locked, "lock" all messages 2954 ** to that host. 2955 */ 2956 2957 i = 0; 2958 while (i < wc) 2959 { 2960 if (!WorkList[i].w_lock) 2961 { 2962 i++; 2963 continue; 2964 } 2965 w = &WorkList[i]; 2966 while (++i < wc) 2967 { 2968 if (WorkList[i].w_host == NULL && 2969 w->w_host == NULL) 2970 WorkList[i].w_lock = true; 2971 else if (WorkList[i].w_host != NULL && 2972 w->w_host != NULL && 2973 sm_strcasecmp(WorkList[i].w_host, 2974 w->w_host) == 0) 2975 WorkList[i].w_lock = true; 2976 else 2977 break; 2978 } 2979 } 2980 2981 /* 2982 ** Sort the work directory for the second time, 2983 ** based on lock status, host name, and priority. 2984 */ 2985 2986 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2); 2987 } 2988 else if (QueueSortOrder == QSO_BYTIME) 2989 { 2990 /* 2991 ** Simple sort based on submission time only. 2992 */ 2993 2994 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); 2995 } 2996 else if (QueueSortOrder == QSO_BYFILENAME) 2997 { 2998 /* 2999 ** Sort based on queue filename. 3000 */ 3001 3002 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4); 3003 } 3004 else if (QueueSortOrder == QSO_RANDOM) 3005 { 3006 /* 3007 ** Sort randomly. To avoid problems with an instable sort, 3008 ** use a random index into the queue file name to start 3009 ** comparison. 3010 */ 3011 3012 randi = get_rand_mod(MAXQFNAME); 3013 if (randi < 2) 3014 randi = 3; 3015 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf5); 3016 } 3017 else if (QueueSortOrder == QSO_BYMODTIME) 3018 { 3019 /* 3020 ** Simple sort based on modification time of queue file. 3021 ** This puts the oldest items first. 3022 */ 3023 3024 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf6); 3025 } 3026#if _FFR_RHS 3027 else if (QueueSortOrder == QSO_BYSHUFFLE) 3028 { 3029 /* 3030 ** Simple sort based on shuffled host name. 3031 */ 3032 3033 init_shuffle_alphabet(); 3034 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf7); 3035 } 3036#endif /* _FFR_RHS */ 3037 else if (QueueSortOrder == QSO_BYPRIORITY) 3038 { 3039 /* 3040 ** Simple sort based on queue priority only. 3041 */ 3042 3043 qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0); 3044 } 3045 /* else don't sort at all */ 3046 3047 /* 3048 ** Convert the work list into canonical form. 3049 ** Should be turning it into a list of envelopes here perhaps. 3050 ** Only take the most important items up to the per queue group 3051 ** maximum. 3052 */ 3053 3054 for (i = wc; --i >= 0; ) 3055 { 3056 w = (WORK *) xalloc(sizeof *w); 3057 w->w_qgrp = WorkList[i].w_qgrp; 3058 w->w_qdir = WorkList[i].w_qdir; 3059 w->w_name = WorkList[i].w_name; 3060 w->w_host = WorkList[i].w_host; 3061 w->w_lock = WorkList[i].w_lock; 3062 w->w_tooyoung = WorkList[i].w_tooyoung; 3063 w->w_pri = WorkList[i].w_pri; 3064 w->w_ctime = WorkList[i].w_ctime; 3065 w->w_mtime = WorkList[i].w_mtime; 3066 w->w_next = WorkQ; 3067 WorkQ = w; 3068 } 3069 3070 /* free the rest of the list */ 3071 for (i = WorkListCount; --i >= wc; ) 3072 { 3073 sm_free(WorkList[i].w_name); 3074 if (WorkList[i].w_host != NULL) 3075 sm_free(WorkList[i].w_host); 3076 } 3077 3078 if (WorkList != NULL) 3079 sm_free(WorkList); /* XXX */ 3080 WorkList = NULL; 3081 WorkListSize = 0; 3082 WorkListCount = 0; 3083 3084 if (tTd(40, 1)) 3085 { 3086 for (w = WorkQ; w != NULL; w = w->w_next) 3087 { 3088 if (w->w_host != NULL) 3089 sm_dprintf("%22s: pri=%ld %s\n", 3090 w->w_name, w->w_pri, w->w_host); 3091 else 3092 sm_dprintf("%32s: pri=%ld\n", 3093 w->w_name, w->w_pri); 3094 } 3095 } 3096 3097 return wc; /* return number of WorkQ items */ 3098} 3099/* 3100** GROW_WLIST -- make the work list larger 3101** 3102** Parameters: 3103** qgrp -- the index for the queue group. 3104** qdir -- the index for the queue directory. 3105** 3106** Returns: 3107** none. 3108** 3109** Side Effects: 3110** Adds another QUEUESEGSIZE entries to WorkList if possible. 3111** It can fail if there isn't enough memory, so WorkListSize 3112** should be checked again upon return. 3113*/ 3114 3115static void 3116grow_wlist(qgrp, qdir) 3117 int qgrp; 3118 int qdir; 3119{ 3120 if (tTd(41, 1)) 3121 sm_dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize); 3122 if (WorkList == NULL) 3123 { 3124 WorkList = (WORK *) xalloc((sizeof *WorkList) * 3125 (QUEUESEGSIZE + 1)); 3126 WorkListSize = QUEUESEGSIZE; 3127 } 3128 else 3129 { 3130 int newsize = WorkListSize + QUEUESEGSIZE; 3131 WORK *newlist = (WORK *) sm_realloc((char *) WorkList, 3132 (unsigned) sizeof(WORK) * (newsize + 1)); 3133 3134 if (newlist != NULL) 3135 { 3136 WorkListSize = newsize; 3137 WorkList = newlist; 3138 if (LogLevel > 1) 3139 { 3140 sm_syslog(LOG_INFO, NOQID, 3141 "grew WorkList for %s to %d", 3142 qid_printqueue(qgrp, qdir), 3143 WorkListSize); 3144 } 3145 } 3146 else if (LogLevel > 0) 3147 { 3148 sm_syslog(LOG_ALERT, NOQID, 3149 "FAILED to grow WorkList for %s to %d", 3150 qid_printqueue(qgrp, qdir), newsize); 3151 } 3152 } 3153 if (tTd(41, 1)) 3154 sm_dprintf("grow_wlist: WorkListSize now %d\n", WorkListSize); 3155} 3156/* 3157** WORKCMPF0 -- simple priority-only compare function. 3158** 3159** Parameters: 3160** a -- the first argument. 3161** b -- the second argument. 3162** 3163** Returns: 3164** -1 if a < b 3165** 0 if a == b 3166** +1 if a > b 3167** 3168*/ 3169 3170static int 3171workcmpf0(a, b) 3172 register WORK *a; 3173 register WORK *b; 3174{ 3175 long pa = a->w_pri; 3176 long pb = b->w_pri; 3177 3178 if (pa == pb) 3179 return 0; 3180 else if (pa > pb) 3181 return 1; 3182 else 3183 return -1; 3184} 3185/* 3186** WORKCMPF1 -- first compare function for ordering work based on host name. 3187** 3188** Sorts on host name, lock status, and priority in that order. 3189** 3190** Parameters: 3191** a -- the first argument. 3192** b -- the second argument. 3193** 3194** Returns: 3195** <0 if a < b 3196** 0 if a == b 3197** >0 if a > b 3198** 3199*/ 3200 3201static int 3202workcmpf1(a, b) 3203 register WORK *a; 3204 register WORK *b; 3205{ 3206 int i; 3207 3208 /* host name */ 3209 if (a->w_host != NULL && b->w_host == NULL) 3210 return 1; 3211 else if (a->w_host == NULL && b->w_host != NULL) 3212 return -1; 3213 if (a->w_host != NULL && b->w_host != NULL && 3214 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 3215 return i; 3216 3217 /* lock status */ 3218 if (a->w_lock != b->w_lock) 3219 return b->w_lock - a->w_lock; 3220 3221 /* job priority */ 3222 return workcmpf0(a, b); 3223} 3224/* 3225** WORKCMPF2 -- second compare function for ordering work based on host name. 3226** 3227** Sorts on lock status, host name, and priority in that order. 3228** 3229** Parameters: 3230** a -- the first argument. 3231** b -- the second argument. 3232** 3233** Returns: 3234** <0 if a < b 3235** 0 if a == b 3236** >0 if a > b 3237** 3238*/ 3239 3240static int 3241workcmpf2(a, b) 3242 register WORK *a; 3243 register WORK *b; 3244{ 3245 int i; 3246 3247 /* lock status */ 3248 if (a->w_lock != b->w_lock) 3249 return a->w_lock - b->w_lock; 3250 3251 /* host name */ 3252 if (a->w_host != NULL && b->w_host == NULL) 3253 return 1; 3254 else if (a->w_host == NULL && b->w_host != NULL) 3255 return -1; 3256 if (a->w_host != NULL && b->w_host != NULL && 3257 (i = sm_strcasecmp(a->w_host, b->w_host)) != 0) 3258 return i; 3259 3260 /* job priority */ 3261 return workcmpf0(a, b); 3262} 3263/* 3264** WORKCMPF3 -- simple submission-time-only compare function. 3265** 3266** Parameters: 3267** a -- the first argument. 3268** b -- the second argument. 3269** 3270** Returns: 3271** -1 if a < b 3272** 0 if a == b 3273** +1 if a > b 3274** 3275*/ 3276 3277static int 3278workcmpf3(a, b) 3279 register WORK *a; 3280 register WORK *b; 3281{ 3282 if (a->w_ctime > b->w_ctime) 3283 return 1; 3284 else if (a->w_ctime < b->w_ctime) 3285 return -1; 3286 else 3287 return 0; 3288} 3289/* 3290** WORKCMPF4 -- compare based on file name 3291** 3292** Parameters: 3293** a -- the first argument. 3294** b -- the second argument. 3295** 3296** Returns: 3297** -1 if a < b 3298** 0 if a == b 3299** +1 if a > b 3300** 3301*/ 3302 3303static int 3304workcmpf4(a, b) 3305 register WORK *a; 3306 register WORK *b; 3307{ 3308 return strcmp(a->w_name, b->w_name); 3309} 3310/* 3311** WORKCMPF5 -- compare based on assigned random number 3312** 3313** Parameters: 3314** a -- the first argument (ignored). 3315** b -- the second argument (ignored). 3316** 3317** Returns: 3318** randomly 1/-1 3319*/ 3320 3321/* ARGSUSED0 */ 3322static int 3323workcmpf5(a, b) 3324 register WORK *a; 3325 register WORK *b; 3326{ 3327 if (strlen(a->w_name) < randi || strlen(b->w_name) < randi) 3328 return -1; 3329 return a->w_name[randi] - b->w_name[randi]; 3330} 3331/* 3332** WORKCMPF6 -- simple modification-time-only compare function. 3333** 3334** Parameters: 3335** a -- the first argument. 3336** b -- the second argument. 3337** 3338** Returns: 3339** -1 if a < b 3340** 0 if a == b 3341** +1 if a > b 3342** 3343*/ 3344 3345static int 3346workcmpf6(a, b) 3347 register WORK *a; 3348 register WORK *b; 3349{ 3350 if (a->w_mtime > b->w_mtime) 3351 return 1; 3352 else if (a->w_mtime < b->w_mtime) 3353 return -1; 3354 else 3355 return 0; 3356} 3357#if _FFR_RHS 3358/* 3359** WORKCMPF7 -- compare function for ordering work based on shuffled host name. 3360** 3361** Sorts on lock status, host name, and priority in that order. 3362** 3363** Parameters: 3364** a -- the first argument. 3365** b -- the second argument. 3366** 3367** Returns: 3368** <0 if a < b 3369** 0 if a == b 3370** >0 if a > b 3371** 3372*/ 3373 3374static int 3375workcmpf7(a, b) 3376 register WORK *a; 3377 register WORK *b; 3378{ 3379 int i; 3380 3381 /* lock status */ 3382 if (a->w_lock != b->w_lock) 3383 return a->w_lock - b->w_lock; 3384 3385 /* host name */ 3386 if (a->w_host != NULL && b->w_host == NULL) 3387 return 1; 3388 else if (a->w_host == NULL && b->w_host != NULL) 3389 return -1; 3390 if (a->w_host != NULL && b->w_host != NULL && 3391 (i = sm_strshufflecmp(a->w_host, b->w_host)) != 0) 3392 return i; 3393 3394 /* job priority */ 3395 return workcmpf0(a, b); 3396} 3397#endif /* _FFR_RHS */ 3398/* 3399** STRREV -- reverse string 3400** 3401** Returns a pointer to a new string that is the reverse of 3402** the string pointed to by fwd. The space for the new 3403** string is obtained using xalloc(). 3404** 3405** Parameters: 3406** fwd -- the string to reverse. 3407** 3408** Returns: 3409** the reversed string. 3410*/ 3411 3412static char * 3413strrev(fwd) 3414 char *fwd; 3415{ 3416 char *rev = NULL; 3417 int len, cnt; 3418 3419 len = strlen(fwd); 3420 rev = xalloc(len + 1); 3421 for (cnt = 0; cnt < len; ++cnt) 3422 rev[cnt] = fwd[len - cnt - 1]; 3423 rev[len] = '\0'; 3424 return rev; 3425} 3426 3427#if _FFR_RHS 3428 3429# define NASCII 128 3430# define NCHAR 256 3431 3432static unsigned char ShuffledAlphabet[NCHAR]; 3433 3434void 3435init_shuffle_alphabet() 3436{ 3437 static bool init = false; 3438 int i; 3439 3440 if (init) 3441 return; 3442 3443 /* fill the ShuffledAlphabet */ 3444 for (i = 0; i < NCHAR; i++) 3445 ShuffledAlphabet[i] = i; 3446 3447 /* mix it */ 3448 for (i = 1; i < NCHAR; i++) 3449 { 3450 register int j = get_random() % NCHAR; 3451 register int tmp; 3452 3453 tmp = ShuffledAlphabet[j]; 3454 ShuffledAlphabet[j] = ShuffledAlphabet[i]; 3455 ShuffledAlphabet[i] = tmp; 3456 } 3457 3458 /* make it case insensitive */ 3459 for (i = 'A'; i <= 'Z'; i++) 3460 ShuffledAlphabet[i] = ShuffledAlphabet[i + 'a' - 'A']; 3461 3462 /* fill the upper part */ 3463 for (i = 0; i < NCHAR; i++) 3464 ShuffledAlphabet[i + NCHAR] = ShuffledAlphabet[i]; 3465 init = true; 3466} 3467 3468static int 3469sm_strshufflecmp(a, b) 3470 char *a; 3471 char *b; 3472{ 3473 const unsigned char *us1 = (const unsigned char *) a; 3474 const unsigned char *us2 = (const unsigned char *) b; 3475 3476 while (ShuffledAlphabet[*us1] == ShuffledAlphabet[*us2++]) 3477 { 3478 if (*us1++ == '\0') 3479 return 0; 3480 } 3481 return (ShuffledAlphabet[*us1] - ShuffledAlphabet[*--us2]); 3482} 3483#endif /* _FFR_RHS */ 3484 3485/* 3486** DOWORK -- do a work request. 3487** 3488** Parameters: 3489** qgrp -- the index of the queue group for the job. 3490** qdir -- the index of the queue directory for the job. 3491** id -- the ID of the job to run. 3492** forkflag -- if set, run this in background. 3493** requeueflag -- if set, reinstantiate the queue quickly. 3494** This is used when expanding aliases in the queue. 3495** If forkflag is also set, it doesn't wait for the 3496** child. 3497** e - the envelope in which to run it. 3498** 3499** Returns: 3500** process id of process that is running the queue job. 3501** 3502** Side Effects: 3503** The work request is satisfied if possible. 3504*/ 3505 3506pid_t 3507dowork(qgrp, qdir, id, forkflag, requeueflag, e) 3508 int qgrp; 3509 int qdir; 3510 char *id; 3511 bool forkflag; 3512 bool requeueflag; 3513 register ENVELOPE *e; 3514{ 3515 register pid_t pid; 3516 SM_RPOOL_T *rpool; 3517 3518 if (tTd(40, 1)) 3519 sm_dprintf("dowork(%s/%s)\n", qid_printqueue(qgrp, qdir), id); 3520 3521 /* 3522 ** Fork for work. 3523 */ 3524 3525 if (forkflag) 3526 { 3527 /* 3528 ** Since the delivery may happen in a child and the 3529 ** parent does not wait, the parent may close the 3530 ** maps thereby removing any shared memory used by 3531 ** the map. Therefore, close the maps now so the 3532 ** child will dynamically open them if necessary. 3533 */ 3534 3535 closemaps(false); 3536 3537 pid = fork(); 3538 if (pid < 0) 3539 { 3540 syserr("dowork: cannot fork"); 3541 return 0; 3542 } 3543 else if (pid > 0) 3544 { 3545 /* parent -- clean out connection cache */ 3546 mci_flush(false, NULL); 3547 } 3548 else 3549 { 3550 /* 3551 ** Initialize exception stack and default exception 3552 ** handler for child process. 3553 */ 3554 3555 /* Reset global flags */ 3556 RestartRequest = NULL; 3557 RestartWorkGroup = false; 3558 ShutdownRequest = NULL; 3559 PendingSignal = 0; 3560 CurrentPid = getpid(); 3561 sm_exc_newthread(fatal_error); 3562 3563 /* 3564 ** See note above about SMTP processes and SIGCHLD. 3565 */ 3566 3567 if (OpMode == MD_SMTP || 3568 OpMode == MD_DAEMON || 3569 MaxQueueChildren > 0) 3570 { 3571 proc_list_clear(); 3572 sm_releasesignal(SIGCHLD); 3573 (void) sm_signal(SIGCHLD, SIG_DFL); 3574 } 3575 3576 /* child -- error messages to the transcript */ 3577 QuickAbort = OnlyOneError = false; 3578 } 3579 } 3580 else 3581 { 3582 pid = 0; 3583 } 3584 3585 if (pid == 0) 3586 { 3587 /* 3588 ** CHILD 3589 ** Lock the control file to avoid duplicate deliveries. 3590 ** Then run the file as though we had just read it. 3591 ** We save an idea of the temporary name so we 3592 ** can recover on interrupt. 3593 */ 3594 3595 if (forkflag) 3596 { 3597 /* Reset global flags */ 3598 RestartRequest = NULL; 3599 RestartWorkGroup = false; 3600 ShutdownRequest = NULL; 3601 PendingSignal = 0; 3602 } 3603 3604 /* set basic modes, etc. */ 3605 sm_clear_events(); 3606 clearstats(); 3607 rpool = sm_rpool_new_x(NULL); 3608 clearenvelope(e, false, rpool); 3609 e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 3610 set_delivery_mode(SM_DELIVER, e); 3611 e->e_errormode = EM_MAIL; 3612 e->e_id = id; 3613 e->e_qgrp = qgrp; 3614 e->e_qdir = qdir; 3615 GrabTo = UseErrorsTo = false; 3616 ExitStat = EX_OK; 3617 if (forkflag) 3618 { 3619 disconnect(1, e); 3620 set_op_mode(MD_QUEUERUN); 3621 } 3622 sm_setproctitle(true, e, "%s from queue", qid_printname(e)); 3623 if (LogLevel > 76) 3624 sm_syslog(LOG_DEBUG, e->e_id, "dowork, pid=%d", 3625 (int) CurrentPid); 3626 3627 /* don't use the headers from sendmail.cf... */ 3628 e->e_header = NULL; 3629 3630 /* read the queue control file -- return if locked */ 3631 if (!readqf(e, false)) 3632 { 3633 if (tTd(40, 4) && e->e_id != NULL) 3634 sm_dprintf("readqf(%s) failed\n", 3635 qid_printname(e)); 3636 e->e_id = NULL; 3637 if (forkflag) 3638 finis(false, true, EX_OK); 3639 else 3640 { 3641 /* adding this frees 8 bytes */ 3642 clearenvelope(e, false, rpool); 3643 3644 /* adding this frees 12 bytes */ 3645 sm_rpool_free(rpool); 3646 e->e_rpool = NULL; 3647 return 0; 3648 } 3649 } 3650 3651 e->e_flags |= EF_INQUEUE; 3652 eatheader(e, requeueflag, true); 3653 3654 if (requeueflag) 3655 queueup(e, false, false); 3656 3657 /* do the delivery */ 3658 sendall(e, SM_DELIVER); 3659 3660 /* finish up and exit */ 3661 if (forkflag) 3662 finis(true, true, ExitStat); 3663 else 3664 { 3665 dropenvelope(e, true, false); 3666 sm_rpool_free(rpool); 3667 e->e_rpool = NULL; 3668 } 3669 } 3670 e->e_id = NULL; 3671 return pid; 3672} 3673 3674/* 3675** DOWORKLIST -- process a list of envelopes as work requests 3676** 3677** Similar to dowork(), except that after forking, it processes an 3678** envelope and its siblings, treating each envelope as a work request. 3679** 3680** Parameters: 3681** el -- envelope to be processed including its siblings. 3682** forkflag -- if set, run this in background. 3683** requeueflag -- if set, reinstantiate the queue quickly. 3684** This is used when expanding aliases in the queue. 3685** If forkflag is also set, it doesn't wait for the 3686** child. 3687** 3688** Returns: 3689** process id of process that is running the queue job. 3690** 3691** Side Effects: 3692** The work request is satisfied if possible. 3693*/ 3694 3695pid_t 3696doworklist(el, forkflag, requeueflag) 3697 ENVELOPE *el; 3698 bool forkflag; 3699 bool requeueflag; 3700{ 3701 register pid_t pid; 3702 ENVELOPE *ei; 3703 3704 if (tTd(40, 1)) 3705 sm_dprintf("doworklist()\n"); 3706 3707 /* 3708 ** Fork for work. 3709 */ 3710 3711 if (forkflag) 3712 { 3713 /* 3714 ** Since the delivery may happen in a child and the 3715 ** parent does not wait, the parent may close the 3716 ** maps thereby removing any shared memory used by 3717 ** the map. Therefore, close the maps now so the 3718 ** child will dynamically open them if necessary. 3719 */ 3720 3721 closemaps(false); 3722 3723 pid = fork(); 3724 if (pid < 0) 3725 { 3726 syserr("doworklist: cannot fork"); 3727 return 0; 3728 } 3729 else if (pid > 0) 3730 { 3731 /* parent -- clean out connection cache */ 3732 mci_flush(false, NULL); 3733 } 3734 else 3735 { 3736 /* 3737 ** Initialize exception stack and default exception 3738 ** handler for child process. 3739 */ 3740 3741 /* Reset global flags */ 3742 RestartRequest = NULL; 3743 RestartWorkGroup = false; 3744 ShutdownRequest = NULL; 3745 PendingSignal = 0; 3746 CurrentPid = getpid(); 3747 sm_exc_newthread(fatal_error); 3748 3749 /* 3750 ** See note above about SMTP processes and SIGCHLD. 3751 */ 3752 3753 if (OpMode == MD_SMTP || 3754 OpMode == MD_DAEMON || 3755 MaxQueueChildren > 0) 3756 { 3757 proc_list_clear(); 3758 sm_releasesignal(SIGCHLD); 3759 (void) sm_signal(SIGCHLD, SIG_DFL); 3760 } 3761 3762 /* child -- error messages to the transcript */ 3763 QuickAbort = OnlyOneError = false; 3764 } 3765 } 3766 else 3767 { 3768 pid = 0; 3769 } 3770 3771 if (pid != 0) 3772 return pid; 3773 3774 /* 3775 ** IN CHILD 3776 ** Lock the control file to avoid duplicate deliveries. 3777 ** Then run the file as though we had just read it. 3778 ** We save an idea of the temporary name so we 3779 ** can recover on interrupt. 3780 */ 3781 3782 if (forkflag) 3783 { 3784 /* Reset global flags */ 3785 RestartRequest = NULL; 3786 RestartWorkGroup = false; 3787 ShutdownRequest = NULL; 3788 PendingSignal = 0; 3789 } 3790 3791 /* set basic modes, etc. */ 3792 sm_clear_events(); 3793 clearstats(); 3794 GrabTo = UseErrorsTo = false; 3795 ExitStat = EX_OK; 3796 if (forkflag) 3797 { 3798 disconnect(1, el); 3799 set_op_mode(MD_QUEUERUN); 3800 } 3801 if (LogLevel > 76) 3802 sm_syslog(LOG_DEBUG, el->e_id, "doworklist, pid=%d", 3803 (int) CurrentPid); 3804 3805 for (ei = el; ei != NULL; ei = ei->e_sibling) 3806 { 3807 ENVELOPE e; 3808 SM_RPOOL_T *rpool; 3809 3810 if (WILL_BE_QUEUED(ei->e_sendmode)) 3811 continue; 3812 else if (QueueMode != QM_QUARANTINE && 3813 ei->e_quarmsg != NULL) 3814 continue; 3815 3816 rpool = sm_rpool_new_x(NULL); 3817 clearenvelope(&e, true, rpool); 3818 e.e_flags |= EF_QUEUERUN|EF_GLOBALERRS; 3819 set_delivery_mode(SM_DELIVER, &e); 3820 e.e_errormode = EM_MAIL; 3821 e.e_id = ei->e_id; 3822 e.e_qgrp = ei->e_qgrp; 3823 e.e_qdir = ei->e_qdir; 3824 openxscript(&e); 3825 sm_setproctitle(true, &e, "%s from queue", qid_printname(&e)); 3826 3827 /* don't use the headers from sendmail.cf... */ 3828 e.e_header = NULL; 3829 CurEnv = &e; 3830 3831 /* read the queue control file -- return if locked */ 3832 if (readqf(&e, false)) 3833 { 3834 e.e_flags |= EF_INQUEUE; 3835 eatheader(&e, requeueflag, true); 3836 3837 if (requeueflag) 3838 queueup(&e, false, false); 3839 3840 /* do the delivery */ 3841 sendall(&e, SM_DELIVER); 3842 dropenvelope(&e, true, false); 3843 } 3844 else 3845 { 3846 if (tTd(40, 4) && e.e_id != NULL) 3847 sm_dprintf("readqf(%s) failed\n", 3848 qid_printname(&e)); 3849 } 3850 sm_rpool_free(rpool); 3851 ei->e_id = NULL; 3852 } 3853 3854 /* restore CurEnv */ 3855 CurEnv = el; 3856 3857 /* finish up and exit */ 3858 if (forkflag) 3859 finis(true, true, ExitStat); 3860 return 0; 3861} 3862/* 3863** READQF -- read queue file and set up environment. 3864** 3865** Parameters: 3866** e -- the envelope of the job to run. 3867** openonly -- only open the qf (returned as e_lockfp) 3868** 3869** Returns: 3870** true if it successfully read the queue file. 3871** false otherwise. 3872** 3873** Side Effects: 3874** The queue file is returned locked. 3875*/ 3876 3877static bool 3878readqf(e, openonly) 3879 register ENVELOPE *e; 3880 bool openonly; 3881{ 3882 register SM_FILE_T *qfp; 3883 ADDRESS *ctladdr; 3884 struct stat st, stf; 3885 char *bp; 3886 int qfver = 0; 3887 long hdrsize = 0; 3888 register char *p; 3889 char *frcpt = NULL; 3890 char *orcpt = NULL; 3891 bool nomore = false; 3892 bool bogus = false; 3893 MODE_T qsafe; 3894 char *err; 3895 char qf[MAXPATHLEN]; 3896 char buf[MAXLINE]; 3897 3898 /* 3899 ** Read and process the file. 3900 */ 3901 3902 (void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER), sizeof qf); 3903 qfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDWR_B, NULL); 3904 if (qfp == NULL) 3905 { 3906 int save_errno = errno; 3907 3908 if (tTd(40, 8)) 3909 sm_dprintf("readqf(%s): sm_io_open failure (%s)\n", 3910 qf, sm_errstring(errno)); 3911 errno = save_errno; 3912 if (errno != ENOENT 3913 ) 3914 syserr("readqf: no control file %s", qf); 3915 RELEASE_QUEUE; 3916 return false; 3917 } 3918 3919 if (!lockfile(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), qf, NULL, 3920 LOCK_EX|LOCK_NB)) 3921 { 3922 /* being processed by another queuer */ 3923 if (Verbose) 3924 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3925 "%s: locked\n", e->e_id); 3926 if (tTd(40, 8)) 3927 sm_dprintf("%s: locked\n", e->e_id); 3928 if (LogLevel > 19) 3929 sm_syslog(LOG_DEBUG, e->e_id, "locked"); 3930 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3931 RELEASE_QUEUE; 3932 return false; 3933 } 3934 3935 RELEASE_QUEUE; 3936 3937 /* 3938 ** Prevent locking race condition. 3939 ** 3940 ** Process A: readqf(): qfp = fopen(qffile) 3941 ** Process B: queueup(): rename(tf, qf) 3942 ** Process B: unlocks(tf) 3943 ** Process A: lockfile(qf); 3944 ** 3945 ** Process A (us) has the old qf file (before the rename deleted 3946 ** the directory entry) and will be delivering based on old data. 3947 ** This can lead to multiple deliveries of the same recipients. 3948 ** 3949 ** Catch this by checking if the underlying qf file has changed 3950 ** *after* acquiring our lock and if so, act as though the file 3951 ** was still locked (i.e., just return like the lockfile() case 3952 ** above. 3953 */ 3954 3955 if (stat(qf, &stf) < 0 || 3956 fstat(sm_io_getinfo(qfp, SM_IO_WHAT_FD, NULL), &st) < 0) 3957 { 3958 /* must have been being processed by someone else */ 3959 if (tTd(40, 8)) 3960 sm_dprintf("readqf(%s): [f]stat failure (%s)\n", 3961 qf, sm_errstring(errno)); 3962 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3963 return false; 3964 } 3965 3966 if (st.st_nlink != stf.st_nlink || 3967 st.st_dev != stf.st_dev || 3968 ST_INODE(st) != ST_INODE(stf) || 3969#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ 3970 st.st_gen != stf.st_gen || 3971#endif /* HAS_ST_GEN && 0 */ 3972 st.st_uid != stf.st_uid || 3973 st.st_gid != stf.st_gid || 3974 st.st_size != stf.st_size) 3975 { 3976 /* changed after opened */ 3977 if (Verbose) 3978 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3979 "%s: changed\n", e->e_id); 3980 if (tTd(40, 8)) 3981 sm_dprintf("%s: changed\n", e->e_id); 3982 if (LogLevel > 19) 3983 sm_syslog(LOG_DEBUG, e->e_id, "changed"); 3984 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 3985 return false; 3986 } 3987 3988 /* 3989 ** Check the queue file for plausibility to avoid attacks. 3990 */ 3991 3992 qsafe = S_IWOTH|S_IWGRP; 3993 if (bitset(S_IWGRP, QueueFileMode)) 3994 qsafe &= ~S_IWGRP; 3995 3996 bogus = st.st_uid != geteuid() && 3997 st.st_uid != TrustedUid && 3998 geteuid() != RealUid; 3999 4000 /* 4001 ** If this qf file results from a set-group-ID binary, then 4002 ** we check whether the directory is group-writable, 4003 ** the queue file mode contains the group-writable bit, and 4004 ** the groups are the same. 4005 ** Notice: this requires that the set-group-ID binary is used to 4006 ** run the queue! 4007 */ 4008 4009 if (bogus && st.st_gid == getegid() && UseMSP) 4010 { 4011 char delim; 4012 struct stat dst; 4013 4014 bp = SM_LAST_DIR_DELIM(qf); 4015 if (bp == NULL) 4016 delim = '\0'; 4017 else 4018 { 4019 delim = *bp; 4020 *bp = '\0'; 4021 } 4022 if (stat(delim == '\0' ? "." : qf, &dst) < 0) 4023 syserr("readqf: cannot stat directory %s", 4024 delim == '\0' ? "." : qf); 4025 else 4026 { 4027 bogus = !(bitset(S_IWGRP, QueueFileMode) && 4028 bitset(S_IWGRP, dst.st_mode) && 4029 dst.st_gid == st.st_gid); 4030 } 4031 if (delim != '\0') 4032 *bp = delim; 4033 } 4034 if (!bogus) 4035 bogus = bitset(qsafe, st.st_mode); 4036 if (bogus) 4037 { 4038 if (LogLevel > 0) 4039 { 4040 sm_syslog(LOG_ALERT, e->e_id, 4041 "bogus queue file, uid=%d, gid=%d, mode=%o", 4042 st.st_uid, st.st_gid, st.st_mode); 4043 } 4044 if (tTd(40, 8)) 4045 sm_dprintf("readqf(%s): bogus file\n", qf); 4046 e->e_flags |= EF_INQUEUE; 4047 if (!openonly) 4048 loseqfile(e, "bogus file uid/gid in mqueue"); 4049 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4050 return false; 4051 } 4052 4053 if (st.st_size == 0) 4054 { 4055 /* must be a bogus file -- if also old, just remove it */ 4056 if (!openonly && st.st_ctime + 10 * 60 < curtime()) 4057 { 4058 (void) xunlink(queuename(e, DATAFL_LETTER)); 4059 (void) xunlink(queuename(e, ANYQFL_LETTER)); 4060 } 4061 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4062 return false; 4063 } 4064 4065 if (st.st_nlink == 0) 4066 { 4067 /* 4068 ** Race condition -- we got a file just as it was being 4069 ** unlinked. Just assume it is zero length. 4070 */ 4071 4072 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4073 return false; 4074 } 4075 4076#if _FFR_TRUSTED_QF 4077 /* 4078 ** If we don't own the file mark it as unsafe. 4079 ** However, allow TrustedUser to own it as well 4080 ** in case TrustedUser manipulates the queue. 4081 */ 4082 4083 if (st.st_uid != geteuid() && st.st_uid != TrustedUid) 4084 e->e_flags |= EF_UNSAFE; 4085#else /* _FFR_TRUSTED_QF */ 4086 /* If we don't own the file mark it as unsafe */ 4087 if (st.st_uid != geteuid()) 4088 e->e_flags |= EF_UNSAFE; 4089#endif /* _FFR_TRUSTED_QF */ 4090 4091 /* good file -- save this lock */ 4092 e->e_lockfp = qfp; 4093 4094 /* Just wanted the open file */ 4095 if (openonly) 4096 return true; 4097 4098 /* do basic system initialization */ 4099 initsys(e); 4100 macdefine(&e->e_macro, A_PERM, 'i', e->e_id); 4101 4102 LineNumber = 0; 4103 e->e_flags |= EF_GLOBALERRS; 4104 set_op_mode(MD_QUEUERUN); 4105 ctladdr = NULL; 4106 e->e_qfletter = queue_letter(e, ANYQFL_LETTER); 4107 e->e_dfqgrp = e->e_qgrp; 4108 e->e_dfqdir = e->e_qdir; 4109#if _FFR_QUEUE_MACRO 4110 macdefine(&e->e_macro, A_TEMP, macid("{queue}"), 4111 qid_printqueue(e->e_qgrp, e->e_qdir)); 4112#endif /* _FFR_QUEUE_MACRO */ 4113 e->e_dfino = -1; 4114 e->e_msgsize = -1; 4115 while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) 4116 { 4117 unsigned long qflags; 4118 ADDRESS *q; 4119 int r; 4120 time_t now; 4121 auto char *ep; 4122 4123 if (tTd(40, 4)) 4124 sm_dprintf("+++++ %s\n", bp); 4125 if (nomore) 4126 { 4127 /* hack attack */ 4128 hackattack: 4129 syserr("SECURITY ALERT: extra or bogus data in queue file: %s", 4130 bp); 4131 err = "bogus queue line"; 4132 goto fail; 4133 } 4134 switch (bp[0]) 4135 { 4136 case 'A': /* AUTH= parameter */ 4137 if (!xtextok(&bp[1])) 4138 goto hackattack; 4139 e->e_auth_param = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4140 break; 4141 4142 case 'B': /* body type */ 4143 r = check_bodytype(&bp[1]); 4144 if (!BODYTYPE_VALID(r)) 4145 goto hackattack; 4146 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4147 break; 4148 4149 case 'C': /* specify controlling user */ 4150 ctladdr = setctluser(&bp[1], qfver, e); 4151 break; 4152 4153 case 'D': /* data file name */ 4154 /* obsolete -- ignore */ 4155 break; 4156 4157 case 'd': /* data file directory name */ 4158 { 4159 int qgrp, qdir; 4160 4161#if _FFR_MSP_PARANOIA 4162 /* forbid queue groups in MSP? */ 4163 if (UseMSP) 4164 goto hackattack; 4165#endif /* _FFR_MSP_PARANOIA */ 4166 for (qgrp = 0; 4167 qgrp < NumQueue && Queue[qgrp] != NULL; 4168 ++qgrp) 4169 { 4170 for (qdir = 0; 4171 qdir < Queue[qgrp]->qg_numqueues; 4172 ++qdir) 4173 { 4174 if (strcmp(&bp[1], 4175 Queue[qgrp]->qg_qpaths[qdir].qp_name) 4176 == 0) 4177 { 4178 e->e_dfqgrp = qgrp; 4179 e->e_dfqdir = qdir; 4180 goto done; 4181 } 4182 } 4183 } 4184 err = "bogus queue file directory"; 4185 goto fail; 4186 done: 4187 break; 4188 } 4189 4190 case 'E': /* specify error recipient */ 4191 /* no longer used */ 4192 break; 4193 4194 case 'F': /* flag bits */ 4195 if (strncmp(bp, "From ", 5) == 0) 4196 { 4197 /* we are being spoofed! */ 4198 syserr("SECURITY ALERT: bogus qf line %s", bp); 4199 err = "bogus queue line"; 4200 goto fail; 4201 } 4202 for (p = &bp[1]; *p != '\0'; p++) 4203 { 4204 switch (*p) 4205 { 4206 case '8': /* has 8 bit data */ 4207 e->e_flags |= EF_HAS8BIT; 4208 break; 4209 4210 case 'b': /* delete Bcc: header */ 4211 e->e_flags |= EF_DELETE_BCC; 4212 break; 4213 4214 case 'd': /* envelope has DSN RET= */ 4215 e->e_flags |= EF_RET_PARAM; 4216 break; 4217 4218 case 'n': /* don't return body */ 4219 e->e_flags |= EF_NO_BODY_RETN; 4220 break; 4221 4222 case 'r': /* response */ 4223 e->e_flags |= EF_RESPONSE; 4224 break; 4225 4226 case 's': /* split */ 4227 e->e_flags |= EF_SPLIT; 4228 break; 4229 4230 case 'w': /* warning sent */ 4231 e->e_flags |= EF_WARNING; 4232 break; 4233 } 4234 } 4235 break; 4236 4237 case 'q': /* quarantine reason */ 4238 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4239 macdefine(&e->e_macro, A_PERM, 4240 macid("{quarantine}"), e->e_quarmsg); 4241 break; 4242 4243 case 'H': /* header */ 4244 4245 /* 4246 ** count size before chompheader() destroys the line. 4247 ** this isn't accurate due to macro expansion, but 4248 ** better than before. "-3" to skip H?? at least. 4249 */ 4250 4251 hdrsize += strlen(bp) - 3; 4252 (void) chompheader(&bp[1], CHHDR_QUEUE, NULL, e); 4253 break; 4254 4255 case 'I': /* data file's inode number */ 4256 /* regenerated below */ 4257 break; 4258 4259 case 'K': /* time of last delivery attempt */ 4260 e->e_dtime = atol(&buf[1]); 4261 break; 4262 4263 case 'L': /* Solaris Content-Length: */ 4264 case 'M': /* message */ 4265 /* ignore this; we want a new message next time */ 4266 break; 4267 4268 case 'N': /* number of delivery attempts */ 4269 e->e_ntries = atoi(&buf[1]); 4270 4271 /* if this has been tried recently, let it be */ 4272 now = curtime(); 4273 if (e->e_ntries > 0 && e->e_dtime <= now && 4274 now < e->e_dtime + MinQueueAge) 4275 { 4276 char *howlong; 4277 4278 howlong = pintvl(now - e->e_dtime, true); 4279 if (Verbose) 4280 (void) sm_io_fprintf(smioout, 4281 SM_TIME_DEFAULT, 4282 "%s: too young (%s)\n", 4283 e->e_id, howlong); 4284 if (tTd(40, 8)) 4285 sm_dprintf("%s: too young (%s)\n", 4286 e->e_id, howlong); 4287 if (LogLevel > 19) 4288 sm_syslog(LOG_DEBUG, e->e_id, 4289 "too young (%s)", 4290 howlong); 4291 e->e_id = NULL; 4292 unlockqueue(e); 4293 return false; 4294 } 4295 macdefine(&e->e_macro, A_TEMP, 4296 macid("{ntries}"), &buf[1]); 4297 4298#if NAMED_BIND 4299 /* adjust BIND parameters immediately */ 4300 if (e->e_ntries == 0) 4301 { 4302 _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 4303 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 4304 } 4305 else 4306 { 4307 _res.retry = TimeOuts.res_retry[RES_TO_NORMAL]; 4308 _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL]; 4309 } 4310#endif /* NAMED_BIND */ 4311 break; 4312 4313 case 'P': /* message priority */ 4314 e->e_msgpriority = atol(&bp[1]) + WkTimeFact; 4315 break; 4316 4317 case 'Q': /* original recipient */ 4318 orcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4319 break; 4320 4321 case 'r': /* final recipient */ 4322 frcpt = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4323 break; 4324 4325 case 'R': /* specify recipient */ 4326 p = bp; 4327 qflags = 0; 4328 if (qfver >= 1) 4329 { 4330 /* get flag bits */ 4331 while (*++p != '\0' && *p != ':') 4332 { 4333 switch (*p) 4334 { 4335 case 'N': 4336 qflags |= QHASNOTIFY; 4337 break; 4338 4339 case 'S': 4340 qflags |= QPINGONSUCCESS; 4341 break; 4342 4343 case 'F': 4344 qflags |= QPINGONFAILURE; 4345 break; 4346 4347 case 'D': 4348 qflags |= QPINGONDELAY; 4349 break; 4350 4351 case 'P': 4352 qflags |= QPRIMARY; 4353 break; 4354 4355 case 'A': 4356 if (ctladdr != NULL) 4357 ctladdr->q_flags |= QALIAS; 4358 break; 4359 4360 default: /* ignore or complain? */ 4361 break; 4362 } 4363 } 4364 } 4365 else 4366 qflags |= QPRIMARY; 4367 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), 4368 "e r"); 4369 if (*p != '\0') 4370 q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', 4371 NULL, e, true); 4372 else 4373 q = NULL; 4374 if (q != NULL) 4375 { 4376 /* make sure we keep the current qgrp */ 4377 if (ISVALIDQGRP(e->e_qgrp)) 4378 q->q_qgrp = e->e_qgrp; 4379 q->q_alias = ctladdr; 4380 if (qfver >= 1) 4381 q->q_flags &= ~Q_PINGFLAGS; 4382 q->q_flags |= qflags; 4383 q->q_finalrcpt = frcpt; 4384 q->q_orcpt = orcpt; 4385 (void) recipient(q, &e->e_sendqueue, 0, e); 4386 } 4387 frcpt = NULL; 4388 orcpt = NULL; 4389 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), 4390 NULL); 4391 break; 4392 4393 case 'S': /* sender */ 4394 setsender(sm_rpool_strdup_x(e->e_rpool, &bp[1]), 4395 e, NULL, '\0', true); 4396 break; 4397 4398 case 'T': /* init time */ 4399 e->e_ctime = atol(&bp[1]); 4400 break; 4401 4402 case 'V': /* queue file version number */ 4403 qfver = atoi(&bp[1]); 4404 if (qfver <= QF_VERSION) 4405 break; 4406 syserr("Version number in queue file (%d) greater than max (%d)", 4407 qfver, QF_VERSION); 4408 err = "unsupported queue file version"; 4409 goto fail; 4410 /* NOTREACHED */ 4411 break; 4412 4413 case 'Z': /* original envelope id from ESMTP */ 4414 e->e_envid = sm_rpool_strdup_x(e->e_rpool, &bp[1]); 4415 macdefine(&e->e_macro, A_PERM, 4416 macid("{dsn_envid}"), e->e_envid); 4417 break; 4418 4419 case '!': /* deliver by */ 4420 4421 /* format: flag (1 char) space long-integer */ 4422 e->e_dlvr_flag = buf[1]; 4423 e->e_deliver_by = strtol(&buf[3], NULL, 10); 4424 4425 case '$': /* define macro */ 4426 { 4427 char *p; 4428 4429 /* XXX elimate p? */ 4430 r = macid_parse(&bp[1], &ep); 4431 if (r == 0) 4432 break; 4433 p = sm_rpool_strdup_x(e->e_rpool, ep); 4434 macdefine(&e->e_macro, A_PERM, r, p); 4435 } 4436 break; 4437 4438 case '.': /* terminate file */ 4439 nomore = true; 4440 break; 4441 4442#if _FFR_QUEUEDELAY 4443 case 'G': 4444 case 'Y': 4445 4446 /* 4447 ** Maintain backward compatibility for 4448 ** users who defined _FFR_QUEUEDELAY in 4449 ** previous releases. Remove this 4450 ** code in 8.14 or 8.15. 4451 */ 4452 4453 if (qfver == 5 || qfver == 7) 4454 break; 4455 4456 /* If not qfver 5 or 7, then 'G' or 'Y' is invalid */ 4457 /* FALLTHROUGH */ 4458#endif /* _FFR_QUEUEDELAY */ 4459 4460 default: 4461 syserr("readqf: %s: line %d: bad line \"%s\"", 4462 qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); 4463 err = "unrecognized line"; 4464 goto fail; 4465 } 4466 4467 if (bp != buf) 4468 sm_free(bp); /* XXX */ 4469 } 4470 4471 /* 4472 ** If we haven't read any lines, this queue file is empty. 4473 ** Arrange to remove it without referencing any null pointers. 4474 */ 4475 4476 if (LineNumber == 0) 4477 { 4478 errno = 0; 4479 e->e_flags |= EF_CLRQUEUE|EF_FATALERRS|EF_RESPONSE; 4480 return true; 4481 } 4482 4483 /* Check to make sure we have a complete queue file read */ 4484 if (!nomore) 4485 { 4486 syserr("readqf: %s: incomplete queue file read", qf); 4487 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4488 return false; 4489 } 4490 4491 /* possibly set ${dsn_ret} macro */ 4492 if (bitset(EF_RET_PARAM, e->e_flags)) 4493 { 4494 if (bitset(EF_NO_BODY_RETN, e->e_flags)) 4495 macdefine(&e->e_macro, A_PERM, 4496 macid("{dsn_ret}"), "hdrs"); 4497 else 4498 macdefine(&e->e_macro, A_PERM, 4499 macid("{dsn_ret}"), "full"); 4500 } 4501 4502 /* 4503 ** Arrange to read the data file. 4504 */ 4505 4506 p = queuename(e, DATAFL_LETTER); 4507 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, p, SM_IO_RDONLY_B, 4508 NULL); 4509 if (e->e_dfp == NULL) 4510 { 4511 syserr("readqf: cannot open %s", p); 4512 } 4513 else 4514 { 4515 e->e_flags |= EF_HAS_DF; 4516 if (fstat(sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL), &st) 4517 >= 0) 4518 { 4519 e->e_msgsize = st.st_size + hdrsize; 4520 e->e_dfdev = st.st_dev; 4521 e->e_dfino = ST_INODE(st); 4522 (void) sm_snprintf(buf, sizeof buf, "%ld", 4523 e->e_msgsize); 4524 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), 4525 buf); 4526 } 4527 } 4528 4529 return true; 4530 4531 fail: 4532 /* 4533 ** There was some error reading the qf file (reason is in err var.) 4534 ** Cleanup: 4535 ** close file; clear e_lockfp since it is the same as qfp, 4536 ** hence it is invalid (as file) after qfp is closed; 4537 ** the qf file is on disk, so set the flag to avoid calling 4538 ** queueup() with bogus data. 4539 */ 4540 4541 if (qfp != NULL) 4542 (void) sm_io_close(qfp, SM_TIME_DEFAULT); 4543 e->e_lockfp = NULL; 4544 e->e_flags |= EF_INQUEUE; 4545 loseqfile(e, err); 4546 return false; 4547} 4548/* 4549** PRTSTR -- print a string, "unprintable" characters are shown as \oct 4550** 4551** Parameters: 4552** s -- string to print 4553** ml -- maximum length of output 4554** 4555** Returns: 4556** number of entries 4557** 4558** Side Effects: 4559** Prints a string on stdout. 4560*/ 4561 4562static void 4563prtstr(s, ml) 4564 char *s; 4565 int ml; 4566{ 4567 int c; 4568 4569 if (s == NULL) 4570 return; 4571 while (ml-- > 0 && ((c = *s++) != '\0')) 4572 { 4573 if (c == '\\') 4574 { 4575 if (ml-- > 0) 4576 { 4577 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4578 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4579 } 4580 } 4581 else if (isascii(c) && isprint(c)) 4582 (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 4583 else 4584 { 4585 if ((ml -= 3) > 0) 4586 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4587 "\\%03o", c & 0xFF); 4588 } 4589 } 4590} 4591/* 4592** PRINTNQE -- print out number of entries in the mail queue 4593** 4594** Parameters: 4595** out -- output file pointer. 4596** prefix -- string to output in front of each line. 4597** 4598** Returns: 4599** none. 4600*/ 4601 4602void 4603printnqe(out, prefix) 4604 SM_FILE_T *out; 4605 char *prefix; 4606{ 4607#if SM_CONF_SHM 4608 int i, k = 0, nrequests = 0; 4609 bool unknown = false; 4610 4611 if (ShmId == SM_SHM_NO_ID) 4612 { 4613 if (prefix == NULL) 4614 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4615 "Data unavailable: shared memory not updated\n"); 4616 else 4617 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4618 "%sNOTCONFIGURED:-1\r\n", prefix); 4619 return; 4620 } 4621 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 4622 { 4623 int j; 4624 4625 k++; 4626 for (j = 0; j < Queue[i]->qg_numqueues; j++) 4627 { 4628 int n; 4629 4630 if (StopRequest) 4631 stop_sendmail(); 4632 4633 n = QSHM_ENTRIES(Queue[i]->qg_qpaths[j].qp_idx); 4634 if (prefix != NULL) 4635 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4636 "%s%s:%d\r\n", 4637 prefix, qid_printqueue(i, j), n); 4638 else if (n < 0) 4639 { 4640 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4641 "%s: unknown number of entries\n", 4642 qid_printqueue(i, j)); 4643 unknown = true; 4644 } 4645 else if (n == 0) 4646 { 4647 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4648 "%s is empty\n", 4649 qid_printqueue(i, j)); 4650 } 4651 else if (n > 0) 4652 { 4653 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4654 "%s: entries=%d\n", 4655 qid_printqueue(i, j), n); 4656 nrequests += n; 4657 k++; 4658 } 4659 } 4660 } 4661 if (prefix == NULL && k > 1) 4662 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4663 "\t\tTotal requests: %d%s\n", 4664 nrequests, unknown ? " (about)" : ""); 4665#else /* SM_CONF_SHM */ 4666 if (prefix == NULL) 4667 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4668 "Data unavailable without shared memory support\n"); 4669 else 4670 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 4671 "%sNOTAVAILABLE:-1\r\n", prefix); 4672#endif /* SM_CONF_SHM */ 4673} 4674/* 4675** PRINTQUEUE -- print out a representation of the mail queue 4676** 4677** Parameters: 4678** none. 4679** 4680** Returns: 4681** none. 4682** 4683** Side Effects: 4684** Prints a listing of the mail queue on the standard output. 4685*/ 4686 4687void 4688printqueue() 4689{ 4690 int i, k = 0, nrequests = 0; 4691 4692 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 4693 { 4694 int j; 4695 4696 k++; 4697 for (j = 0; j < Queue[i]->qg_numqueues; j++) 4698 { 4699 if (StopRequest) 4700 stop_sendmail(); 4701 nrequests += print_single_queue(i, j); 4702 k++; 4703 } 4704 } 4705 if (k > 1) 4706 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4707 "\t\tTotal requests: %d\n", 4708 nrequests); 4709} 4710/* 4711** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue 4712** 4713** Parameters: 4714** qgrp -- the index of the queue group. 4715** qdir -- the queue directory. 4716** 4717** Returns: 4718** number of requests in mail queue. 4719** 4720** Side Effects: 4721** Prints a listing of the mail queue on the standard output. 4722*/ 4723 4724int 4725print_single_queue(qgrp, qdir) 4726 int qgrp; 4727 int qdir; 4728{ 4729 register WORK *w; 4730 SM_FILE_T *f; 4731 int nrequests; 4732 char qd[MAXPATHLEN]; 4733 char qddf[MAXPATHLEN]; 4734 char buf[MAXLINE]; 4735 4736 if (qdir == NOQDIR) 4737 { 4738 (void) sm_strlcpy(qd, ".", sizeof qd); 4739 (void) sm_strlcpy(qddf, ".", sizeof qddf); 4740 } 4741 else 4742 { 4743 (void) sm_strlcpyn(qd, sizeof qd, 2, 4744 Queue[qgrp]->qg_qpaths[qdir].qp_name, 4745 (bitset(QP_SUBQF, 4746 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 4747 ? "/qf" : "")); 4748 (void) sm_strlcpyn(qddf, sizeof qddf, 2, 4749 Queue[qgrp]->qg_qpaths[qdir].qp_name, 4750 (bitset(QP_SUBDF, 4751 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 4752 ? "/df" : "")); 4753 } 4754 4755 /* 4756 ** Check for permission to print the queue 4757 */ 4758 4759 if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) 4760 { 4761 struct stat st; 4762#ifdef NGROUPS_MAX 4763 int n; 4764 extern GIDSET_T InitialGidSet[NGROUPS_MAX]; 4765#endif /* NGROUPS_MAX */ 4766 4767 if (stat(qd, &st) < 0) 4768 { 4769 syserr("Cannot stat %s", 4770 qid_printqueue(qgrp, qdir)); 4771 return 0; 4772 } 4773#ifdef NGROUPS_MAX 4774 n = NGROUPS_MAX; 4775 while (--n >= 0) 4776 { 4777 if (InitialGidSet[n] == st.st_gid) 4778 break; 4779 } 4780 if (n < 0 && RealGid != st.st_gid) 4781#else /* NGROUPS_MAX */ 4782 if (RealGid != st.st_gid) 4783#endif /* NGROUPS_MAX */ 4784 { 4785 usrerr("510 You are not permitted to see the queue"); 4786 setstat(EX_NOPERM); 4787 return 0; 4788 } 4789 } 4790 4791 /* 4792 ** Read and order the queue. 4793 */ 4794 4795 nrequests = gatherq(qgrp, qdir, true, NULL, NULL); 4796 (void) sortq(Queue[qgrp]->qg_maxlist); 4797 4798 /* 4799 ** Print the work list that we have read. 4800 */ 4801 4802 /* first see if there is anything */ 4803 if (nrequests <= 0) 4804 { 4805 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s is empty\n", 4806 qid_printqueue(qgrp, qdir)); 4807 return 0; 4808 } 4809 4810 sm_getla(); /* get load average */ 4811 4812 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\t\t%s (%d request%s", 4813 qid_printqueue(qgrp, qdir), 4814 nrequests, nrequests == 1 ? "" : "s"); 4815 if (MaxQueueRun > 0 && nrequests > MaxQueueRun) 4816 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4817 ", only %d printed", MaxQueueRun); 4818 if (Verbose) 4819 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4820 ")\n-----Q-ID----- --Size-- -Priority- ---Q-Time--- --------Sender/Recipient--------\n"); 4821 else 4822 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4823 ")\n-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------\n"); 4824 for (w = WorkQ; w != NULL; w = w->w_next) 4825 { 4826 struct stat st; 4827 auto time_t submittime = 0; 4828 long dfsize; 4829 int flags = 0; 4830 int qfver; 4831 char quarmsg[MAXLINE]; 4832 char statmsg[MAXLINE]; 4833 char bodytype[MAXNAME + 1]; 4834 char qf[MAXPATHLEN]; 4835 4836 if (StopRequest) 4837 stop_sendmail(); 4838 4839 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%13s", 4840 w->w_name + 2); 4841 (void) sm_strlcpyn(qf, sizeof qf, 3, qd, "/", w->w_name); 4842 f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, qf, SM_IO_RDONLY_B, 4843 NULL); 4844 if (f == NULL) 4845 { 4846 if (errno == EPERM) 4847 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4848 " (permission denied)\n"); 4849 else if (errno == ENOENT) 4850 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4851 " (job completed)\n"); 4852 else 4853 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4854 " (%s)\n", 4855 sm_errstring(errno)); 4856 errno = 0; 4857 continue; 4858 } 4859 w->w_name[0] = DATAFL_LETTER; 4860 (void) sm_strlcpyn(qf, sizeof qf, 3, qddf, "/", w->w_name); 4861 if (stat(qf, &st) >= 0) 4862 dfsize = st.st_size; 4863 else 4864 { 4865 ENVELOPE e; 4866 4867 /* 4868 ** Maybe the df file can't be statted because 4869 ** it is in a different directory than the qf file. 4870 ** In order to find out, we must read the qf file. 4871 */ 4872 4873 newenvelope(&e, &BlankEnvelope, sm_rpool_new_x(NULL)); 4874 e.e_id = w->w_name + 2; 4875 e.e_qgrp = qgrp; 4876 e.e_qdir = qdir; 4877 dfsize = -1; 4878 if (readqf(&e, false)) 4879 { 4880 char *df = queuename(&e, DATAFL_LETTER); 4881 if (stat(df, &st) >= 0) 4882 dfsize = st.st_size; 4883 } 4884 if (e.e_lockfp != NULL) 4885 { 4886 (void) sm_io_close(e.e_lockfp, SM_TIME_DEFAULT); 4887 e.e_lockfp = NULL; 4888 } 4889 clearenvelope(&e, false, e.e_rpool); 4890 sm_rpool_free(e.e_rpool); 4891 } 4892 if (w->w_lock) 4893 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "*"); 4894 else if (QueueMode == QM_LOST) 4895 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "?"); 4896 else if (w->w_tooyoung) 4897 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "-"); 4898 else if (shouldqueue(w->w_pri, w->w_ctime)) 4899 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "X"); 4900 else 4901 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " "); 4902 4903 errno = 0; 4904 4905 quarmsg[0] = '\0'; 4906 statmsg[0] = bodytype[0] = '\0'; 4907 qfver = 0; 4908 while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL) 4909 { 4910 register int i; 4911 register char *p; 4912 4913 if (StopRequest) 4914 stop_sendmail(); 4915 4916 fixcrlf(buf, true); 4917 switch (buf[0]) 4918 { 4919 case 'V': /* queue file version */ 4920 qfver = atoi(&buf[1]); 4921 break; 4922 4923 case 'M': /* error message */ 4924 if ((i = strlen(&buf[1])) >= sizeof statmsg) 4925 i = sizeof statmsg - 1; 4926 memmove(statmsg, &buf[1], i); 4927 statmsg[i] = '\0'; 4928 break; 4929 4930 case 'q': /* quarantine reason */ 4931 if ((i = strlen(&buf[1])) >= sizeof quarmsg) 4932 i = sizeof quarmsg - 1; 4933 memmove(quarmsg, &buf[1], i); 4934 quarmsg[i] = '\0'; 4935 break; 4936 4937 case 'B': /* body type */ 4938 if ((i = strlen(&buf[1])) >= sizeof bodytype) 4939 i = sizeof bodytype - 1; 4940 memmove(bodytype, &buf[1], i); 4941 bodytype[i] = '\0'; 4942 break; 4943 4944 case 'S': /* sender name */ 4945 if (Verbose) 4946 { 4947 (void) sm_io_fprintf(smioout, 4948 SM_TIME_DEFAULT, 4949 "%8ld %10ld%c%.12s ", 4950 dfsize, 4951 w->w_pri, 4952 bitset(EF_WARNING, flags) 4953 ? '+' : ' ', 4954 ctime(&submittime) + 4); 4955 prtstr(&buf[1], 78); 4956 } 4957 else 4958 { 4959 (void) sm_io_fprintf(smioout, 4960 SM_TIME_DEFAULT, 4961 "%8ld %.16s ", 4962 dfsize, 4963 ctime(&submittime)); 4964 prtstr(&buf[1], 39); 4965 } 4966 4967 if (quarmsg[0] != '\0') 4968 { 4969 (void) sm_io_fprintf(smioout, 4970 SM_TIME_DEFAULT, 4971 "\n QUARANTINE: %.*s", 4972 Verbose ? 100 : 60, 4973 quarmsg); 4974 quarmsg[0] = '\0'; 4975 } 4976 4977 if (statmsg[0] != '\0' || bodytype[0] != '\0') 4978 { 4979 (void) sm_io_fprintf(smioout, 4980 SM_TIME_DEFAULT, 4981 "\n %10.10s", 4982 bodytype); 4983 if (statmsg[0] != '\0') 4984 (void) sm_io_fprintf(smioout, 4985 SM_TIME_DEFAULT, 4986 " (%.*s)", 4987 Verbose ? 100 : 60, 4988 statmsg); 4989 statmsg[0] = '\0'; 4990 } 4991 break; 4992 4993 case 'C': /* controlling user */ 4994 if (Verbose) 4995 (void) sm_io_fprintf(smioout, 4996 SM_TIME_DEFAULT, 4997 "\n\t\t\t\t\t\t(---%.64s---)", 4998 &buf[1]); 4999 break; 5000 5001 case 'R': /* recipient name */ 5002 p = &buf[1]; 5003 if (qfver >= 1) 5004 { 5005 p = strchr(p, ':'); 5006 if (p == NULL) 5007 break; 5008 p++; 5009 } 5010 if (Verbose) 5011 { 5012 (void) sm_io_fprintf(smioout, 5013 SM_TIME_DEFAULT, 5014 "\n\t\t\t\t\t\t"); 5015 prtstr(p, 71); 5016 } 5017 else 5018 { 5019 (void) sm_io_fprintf(smioout, 5020 SM_TIME_DEFAULT, 5021 "\n\t\t\t\t\t "); 5022 prtstr(p, 38); 5023 } 5024 if (Verbose && statmsg[0] != '\0') 5025 { 5026 (void) sm_io_fprintf(smioout, 5027 SM_TIME_DEFAULT, 5028 "\n\t\t (%.100s)", 5029 statmsg); 5030 statmsg[0] = '\0'; 5031 } 5032 break; 5033 5034 case 'T': /* creation time */ 5035 submittime = atol(&buf[1]); 5036 break; 5037 5038 case 'F': /* flag bits */ 5039 for (p = &buf[1]; *p != '\0'; p++) 5040 { 5041 switch (*p) 5042 { 5043 case 'w': 5044 flags |= EF_WARNING; 5045 break; 5046 } 5047 } 5048 } 5049 } 5050 if (submittime == (time_t) 0) 5051 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 5052 " (no control file)"); 5053 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n"); 5054 (void) sm_io_close(f, SM_TIME_DEFAULT); 5055 } 5056 return nrequests; 5057} 5058 5059/* 5060** QUEUE_LETTER -- get the proper queue letter for the current QueueMode. 5061** 5062** Parameters: 5063** e -- envelope to build it in/from. 5064** type -- the file type, used as the first character 5065** of the file name. 5066** 5067** Returns: 5068** the letter to use 5069*/ 5070 5071static char 5072queue_letter(e, type) 5073 ENVELOPE *e; 5074 int type; 5075{ 5076 /* Change type according to QueueMode */ 5077 if (type == ANYQFL_LETTER) 5078 { 5079 if (e->e_quarmsg != NULL) 5080 type = QUARQF_LETTER; 5081 else 5082 { 5083 switch (QueueMode) 5084 { 5085 case QM_NORMAL: 5086 type = NORMQF_LETTER; 5087 break; 5088 5089 case QM_QUARANTINE: 5090 type = QUARQF_LETTER; 5091 break; 5092 5093 case QM_LOST: 5094 type = LOSEQF_LETTER; 5095 break; 5096 5097 default: 5098 /* should never happen */ 5099 abort(); 5100 /* NOTREACHED */ 5101 } 5102 } 5103 } 5104 return type; 5105} 5106 5107/* 5108** QUEUENAME -- build a file name in the queue directory for this envelope. 5109** 5110** Parameters: 5111** e -- envelope to build it in/from. 5112** type -- the file type, used as the first character 5113** of the file name. 5114** 5115** Returns: 5116** a pointer to the queue name (in a static buffer). 5117** 5118** Side Effects: 5119** If no id code is already assigned, queuename() will 5120** assign an id code with assign_queueid(). If no queue 5121** directory is assigned, one will be set with setnewqueue(). 5122*/ 5123 5124char * 5125queuename(e, type) 5126 register ENVELOPE *e; 5127 int type; 5128{ 5129 int qd, qg; 5130 char *sub = "/"; 5131 char pref[3]; 5132 static char buf[MAXPATHLEN]; 5133 5134 /* Assign an ID if needed */ 5135 if (e->e_id == NULL) 5136 assign_queueid(e); 5137 type = queue_letter(e, type); 5138 5139 /* begin of filename */ 5140 pref[0] = (char) type; 5141 pref[1] = 'f'; 5142 pref[2] = '\0'; 5143 5144 /* Assign a queue group/directory if needed */ 5145 if (type == XSCRPT_LETTER) 5146 { 5147 /* 5148 ** We don't want to call setnewqueue() if we are fetching 5149 ** the pathname of the transcript file, because setnewqueue 5150 ** chooses a queue, and sometimes we need to write to the 5151 ** transcript file before we have gathered enough information 5152 ** to choose a queue. 5153 */ 5154 5155 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR) 5156 { 5157 if (e->e_qgrp != NOQGRP && e->e_qdir != NOQDIR) 5158 { 5159 e->e_xfqgrp = e->e_qgrp; 5160 e->e_xfqdir = e->e_qdir; 5161 } 5162 else 5163 { 5164 e->e_xfqgrp = 0; 5165 if (Queue[e->e_xfqgrp]->qg_numqueues <= 1) 5166 e->e_xfqdir = 0; 5167 else 5168 { 5169 e->e_xfqdir = get_rand_mod( 5170 Queue[e->e_xfqgrp]->qg_numqueues); 5171 } 5172 } 5173 } 5174 qd = e->e_xfqdir; 5175 qg = e->e_xfqgrp; 5176 } 5177 else 5178 { 5179 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR) 5180 setnewqueue(e); 5181 if (type == DATAFL_LETTER) 5182 { 5183 qd = e->e_dfqdir; 5184 qg = e->e_dfqgrp; 5185 } 5186 else 5187 { 5188 qd = e->e_qdir; 5189 qg = e->e_qgrp; 5190 } 5191 } 5192 5193 /* xf files always have a valid qd and qg picked above */ 5194 if (e->e_qdir == NOQDIR && type != XSCRPT_LETTER) 5195 (void) sm_strlcpyn(buf, sizeof buf, 2, pref, e->e_id); 5196 else 5197 { 5198 switch (type) 5199 { 5200 case DATAFL_LETTER: 5201 if (bitset(QP_SUBDF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5202 sub = "/df/"; 5203 break; 5204 5205 case QUARQF_LETTER: 5206 case TEMPQF_LETTER: 5207 case NEWQFL_LETTER: 5208 case LOSEQF_LETTER: 5209 case NORMQF_LETTER: 5210 if (bitset(QP_SUBQF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5211 sub = "/qf/"; 5212 break; 5213 5214 case XSCRPT_LETTER: 5215 if (bitset(QP_SUBXF, Queue[qg]->qg_qpaths[qd].qp_subdirs)) 5216 sub = "/xf/"; 5217 break; 5218 5219 default: 5220 sm_abort("queuename: bad queue file type %d", type); 5221 } 5222 5223 (void) sm_strlcpyn(buf, sizeof buf, 4, 5224 Queue[qg]->qg_qpaths[qd].qp_name, 5225 sub, pref, e->e_id); 5226 } 5227 5228 if (tTd(7, 2)) 5229 sm_dprintf("queuename: %s\n", buf); 5230 return buf; 5231} 5232 5233/* 5234** INIT_QID_ALG -- Initialize the (static) parameters that are used to 5235** generate a queue ID. 5236** 5237** This function is called by the daemon to reset 5238** LastQueueTime and LastQueuePid which are used by assign_queueid(). 5239** Otherwise the algorithm may cause problems because 5240** LastQueueTime and LastQueuePid are set indirectly by main() 5241** before the daemon process is started, hence LastQueuePid is not 5242** the pid of the daemon and therefore a child of the daemon can 5243** actually have the same pid as LastQueuePid which means the section 5244** in assign_queueid(): 5245** * see if we need to get a new base time/pid * 5246** is NOT triggered which will cause the same queue id to be generated. 5247** 5248** Parameters: 5249** none 5250** 5251** Returns: 5252** none. 5253*/ 5254 5255void 5256init_qid_alg() 5257{ 5258 LastQueueTime = 0; 5259 LastQueuePid = -1; 5260} 5261 5262/* 5263** ASSIGN_QUEUEID -- assign a queue ID for this envelope. 5264** 5265** Assigns an id code if one does not already exist. 5266** This code assumes that nothing will remain in the queue for 5267** longer than 60 years. It is critical that files with the given 5268** name do not already exist in the queue. 5269** [No longer initializes e_qdir to NOQDIR.] 5270** 5271** Parameters: 5272** e -- envelope to set it in. 5273** 5274** Returns: 5275** none. 5276*/ 5277 5278static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 5279# define QIC_LEN 60 5280# define QIC_LEN_R 62 5281 5282/* 5283** Note: the length is "officially" 60 because minutes and seconds are 5284** usually only 0-59. However (Linux): 5285** tm_sec The number of seconds after the minute, normally in 5286** the range 0 to 59, but can be up to 61 to allow for 5287** leap seconds. 5288** Hence the real length of the string is 62 to take this into account. 5289** Alternatively % QIC_LEN can (should) be used for access everywhere. 5290*/ 5291 5292# define queuenextid() CurrentPid 5293 5294 5295void 5296assign_queueid(e) 5297 register ENVELOPE *e; 5298{ 5299 pid_t pid = queuenextid(); 5300 static int cX = 0; 5301 static long random_offset; 5302 struct tm *tm; 5303 char idbuf[MAXQFNAME - 2]; 5304 int seq; 5305 5306 if (e->e_id != NULL) 5307 return; 5308 5309 /* see if we need to get a new base time/pid */ 5310 if (cX >= QIC_LEN * QIC_LEN || LastQueueTime == 0 || 5311 LastQueuePid != pid) 5312 { 5313 time_t then = LastQueueTime; 5314 5315 /* if the first time through, pick a random offset */ 5316 if (LastQueueTime == 0) 5317 random_offset = get_random(); 5318 5319 while ((LastQueueTime = curtime()) == then && 5320 LastQueuePid == pid) 5321 { 5322 (void) sleep(1); 5323 } 5324 LastQueuePid = queuenextid(); 5325 cX = 0; 5326 } 5327 5328 /* 5329 ** Generate a new sequence number between 0 and QIC_LEN*QIC_LEN-1. 5330 ** This lets us generate up to QIC_LEN*QIC_LEN unique queue ids 5331 ** per second, per process. With envelope splitting, 5332 ** a single message can consume many queue ids. 5333 */ 5334 5335 seq = (int)((cX + random_offset) % (QIC_LEN * QIC_LEN)); 5336 ++cX; 5337 if (tTd(7, 50)) 5338 sm_dprintf("assign_queueid: random_offset = %ld (%d)\n", 5339 random_offset, seq); 5340 5341 tm = gmtime(&LastQueueTime); 5342 idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN]; 5343 idbuf[1] = QueueIdChars[tm->tm_mon]; 5344 idbuf[2] = QueueIdChars[tm->tm_mday]; 5345 idbuf[3] = QueueIdChars[tm->tm_hour]; 5346 idbuf[4] = QueueIdChars[tm->tm_min % QIC_LEN_R]; 5347 idbuf[5] = QueueIdChars[tm->tm_sec % QIC_LEN_R]; 5348 idbuf[6] = QueueIdChars[seq / QIC_LEN]; 5349 idbuf[7] = QueueIdChars[seq % QIC_LEN]; 5350 (void) sm_snprintf(&idbuf[8], sizeof idbuf - 8, "%06d", 5351 (int) LastQueuePid); 5352 e->e_id = sm_rpool_strdup_x(e->e_rpool, idbuf); 5353 macdefine(&e->e_macro, A_PERM, 'i', e->e_id); 5354#if 0 5355 /* XXX: inherited from MainEnvelope */ 5356 e->e_qgrp = NOQGRP; /* too early to do anything else */ 5357 e->e_qdir = NOQDIR; 5358 e->e_xfqgrp = NOQGRP; 5359#endif /* 0 */ 5360 5361 /* New ID means it's not on disk yet */ 5362 e->e_qfletter = '\0'; 5363 5364 if (tTd(7, 1)) 5365 sm_dprintf("assign_queueid: assigned id %s, e=%p\n", 5366 e->e_id, e); 5367 if (LogLevel > 93) 5368 sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); 5369} 5370/* 5371** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second 5372** 5373** Make sure one PID can't be used by two processes in any one second. 5374** 5375** If the system rotates PIDs fast enough, may get the 5376** same pid in the same second for two distinct processes. 5377** This will interfere with the queue file naming system. 5378** 5379** Parameters: 5380** none 5381** 5382** Returns: 5383** none 5384*/ 5385 5386void 5387sync_queue_time() 5388{ 5389#if FAST_PID_RECYCLE 5390 if (OpMode != MD_TEST && 5391 OpMode != MD_VERIFY && 5392 LastQueueTime > 0 && 5393 LastQueuePid == CurrentPid && 5394 curtime() == LastQueueTime) 5395 (void) sleep(1); 5396#endif /* FAST_PID_RECYCLE */ 5397} 5398/* 5399** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 5400** 5401** Parameters: 5402** e -- the envelope to unlock. 5403** 5404** Returns: 5405** none 5406** 5407** Side Effects: 5408** unlocks the queue for `e'. 5409*/ 5410 5411void 5412unlockqueue(e) 5413 ENVELOPE *e; 5414{ 5415 if (tTd(51, 4)) 5416 sm_dprintf("unlockqueue(%s)\n", 5417 e->e_id == NULL ? "NOQUEUE" : e->e_id); 5418 5419 5420 /* if there is a lock file in the envelope, close it */ 5421 if (e->e_lockfp != NULL) 5422 (void) sm_io_close(e->e_lockfp, SM_TIME_DEFAULT); 5423 e->e_lockfp = NULL; 5424 5425 /* don't create a queue id if we don't already have one */ 5426 if (e->e_id == NULL) 5427 return; 5428 5429 /* remove the transcript */ 5430 if (LogLevel > 87) 5431 sm_syslog(LOG_DEBUG, e->e_id, "unlock"); 5432 if (!tTd(51, 104)) 5433 (void) xunlink(queuename(e, XSCRPT_LETTER)); 5434} 5435/* 5436** SETCTLUSER -- create a controlling address 5437** 5438** Create a fake "address" given only a local login name; this is 5439** used as a "controlling user" for future recipient addresses. 5440** 5441** Parameters: 5442** user -- the user name of the controlling user. 5443** qfver -- the version stamp of this queue file. 5444** e -- envelope 5445** 5446** Returns: 5447** An address descriptor for the controlling user, 5448** using storage allocated from e->e_rpool. 5449** 5450*/ 5451 5452static ADDRESS * 5453setctluser(user, qfver, e) 5454 char *user; 5455 int qfver; 5456 ENVELOPE *e; 5457{ 5458 register ADDRESS *a; 5459 struct passwd *pw; 5460 char *p; 5461 5462 /* 5463 ** See if this clears our concept of controlling user. 5464 */ 5465 5466 if (user == NULL || *user == '\0') 5467 return NULL; 5468 5469 /* 5470 ** Set up addr fields for controlling user. 5471 */ 5472 5473 a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a); 5474 memset((char *) a, '\0', sizeof *a); 5475 5476 if (*user == ':') 5477 { 5478 p = &user[1]; 5479 a->q_user = sm_rpool_strdup_x(e->e_rpool, p); 5480 } 5481 else 5482 { 5483 p = strtok(user, ":"); 5484 a->q_user = sm_rpool_strdup_x(e->e_rpool, user); 5485 if (qfver >= 2) 5486 { 5487 if ((p = strtok(NULL, ":")) != NULL) 5488 a->q_uid = atoi(p); 5489 if ((p = strtok(NULL, ":")) != NULL) 5490 a->q_gid = atoi(p); 5491 if ((p = strtok(NULL, ":")) != NULL) 5492 { 5493 char *o; 5494 5495 a->q_flags |= QGOODUID; 5496 5497 /* if there is another ':': restore it */ 5498 if ((o = strtok(NULL, ":")) != NULL && o > p) 5499 o[-1] = ':'; 5500 } 5501 } 5502 else if ((pw = sm_getpwnam(user)) != NULL) 5503 { 5504 if (*pw->pw_dir == '\0') 5505 a->q_home = NULL; 5506 else if (strcmp(pw->pw_dir, "/") == 0) 5507 a->q_home = ""; 5508 else 5509 a->q_home = sm_rpool_strdup_x(e->e_rpool, pw->pw_dir); 5510 a->q_uid = pw->pw_uid; 5511 a->q_gid = pw->pw_gid; 5512 a->q_flags |= QGOODUID; 5513 } 5514 } 5515 5516 a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ 5517 a->q_mailer = LocalMailer; 5518 if (p == NULL) 5519 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user); 5520 else 5521 a->q_paddr = sm_rpool_strdup_x(e->e_rpool, p); 5522 return a; 5523} 5524/* 5525** LOSEQFILE -- rename queue file with LOSEQF_LETTER & try to let someone know 5526** 5527** Parameters: 5528** e -- the envelope (e->e_id will be used). 5529** why -- reported to whomever can hear. 5530** 5531** Returns: 5532** none. 5533*/ 5534 5535void 5536loseqfile(e, why) 5537 register ENVELOPE *e; 5538 char *why; 5539{ 5540 bool loseit = true; 5541 char *p; 5542 char buf[MAXPATHLEN]; 5543 5544 if (e == NULL || e->e_id == NULL) 5545 return; 5546 p = queuename(e, ANYQFL_LETTER); 5547 if (sm_strlcpy(buf, p, sizeof buf) >= sizeof buf) 5548 return; 5549 if (!bitset(EF_INQUEUE, e->e_flags)) 5550 queueup(e, false, true); 5551 else if (QueueMode == QM_LOST) 5552 loseit = false; 5553 5554 /* if already lost, no need to re-lose */ 5555 if (loseit) 5556 { 5557 p = queuename(e, LOSEQF_LETTER); 5558 if (rename(buf, p) < 0) 5559 syserr("cannot rename(%s, %s), uid=%d", 5560 buf, p, (int) geteuid()); 5561 else if (LogLevel > 0) 5562 sm_syslog(LOG_ALERT, e->e_id, 5563 "Losing %s: %s", buf, why); 5564 } 5565 if (e->e_dfp != NULL) 5566 { 5567 (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); 5568 e->e_dfp = NULL; 5569 } 5570 e->e_flags &= ~EF_HAS_DF; 5571} 5572/* 5573** NAME2QID -- translate a queue group name to a queue group id 5574** 5575** Parameters: 5576** queuename -- name of queue group. 5577** 5578** Returns: 5579** queue group id if found. 5580** NOQGRP otherwise. 5581*/ 5582 5583int 5584name2qid(queuename) 5585 char *queuename; 5586{ 5587 register STAB *s; 5588 5589 s = stab(queuename, ST_QUEUE, ST_FIND); 5590 if (s == NULL) 5591 return NOQGRP; 5592 return s->s_quegrp->qg_index; 5593} 5594/* 5595** QID_PRINTNAME -- create externally printable version of queue id 5596** 5597** Parameters: 5598** e -- the envelope. 5599** 5600** Returns: 5601** a printable version 5602*/ 5603 5604char * 5605qid_printname(e) 5606 ENVELOPE *e; 5607{ 5608 char *id; 5609 static char idbuf[MAXQFNAME + 34]; 5610 5611 if (e == NULL) 5612 return ""; 5613 5614 if (e->e_id == NULL) 5615 id = ""; 5616 else 5617 id = e->e_id; 5618 5619 if (e->e_qdir == NOQDIR) 5620 return id; 5621 5622 (void) sm_snprintf(idbuf, sizeof idbuf, "%.32s/%s", 5623 Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_name, 5624 id); 5625 return idbuf; 5626} 5627/* 5628** QID_PRINTQUEUE -- create full version of queue directory for data files 5629** 5630** Parameters: 5631** qgrp -- index in queue group. 5632** qdir -- the short version of the queue directory 5633** 5634** Returns: 5635** the full pathname to the queue (might point to a static var) 5636*/ 5637 5638char * 5639qid_printqueue(qgrp, qdir) 5640 int qgrp; 5641 int qdir; 5642{ 5643 char *subdir; 5644 static char dir[MAXPATHLEN]; 5645 5646 if (qdir == NOQDIR) 5647 return Queue[qgrp]->qg_qdir; 5648 5649 if (strcmp(Queue[qgrp]->qg_qpaths[qdir].qp_name, ".") == 0) 5650 subdir = NULL; 5651 else 5652 subdir = Queue[qgrp]->qg_qpaths[qdir].qp_name; 5653 5654 (void) sm_strlcpyn(dir, sizeof dir, 4, 5655 Queue[qgrp]->qg_qdir, 5656 subdir == NULL ? "" : "/", 5657 subdir == NULL ? "" : subdir, 5658 (bitset(QP_SUBDF, 5659 Queue[qgrp]->qg_qpaths[qdir].qp_subdirs) 5660 ? "/df" : "")); 5661 return dir; 5662} 5663 5664/* 5665** PICKQDIR -- Pick a queue directory from a queue group 5666** 5667** Parameters: 5668** qg -- queue group 5669** fsize -- file size in bytes 5670** e -- envelope, or NULL 5671** 5672** Result: 5673** NOQDIR if no queue directory in qg has enough free space to 5674** hold a file of size 'fsize', otherwise the index of 5675** a randomly selected queue directory which resides on a 5676** file system with enough disk space. 5677** XXX This could be extended to select a queuedir with 5678** a few (the fewest?) number of entries. That data 5679** is available if shared memory is used. 5680** 5681** Side Effects: 5682** If the request fails and e != NULL then sm_syslog is called. 5683*/ 5684 5685int 5686pickqdir(qg, fsize, e) 5687 QUEUEGRP *qg; 5688 long fsize; 5689 ENVELOPE *e; 5690{ 5691 int qdir; 5692 int i; 5693 long avail = 0; 5694 5695 /* Pick a random directory, as a starting point. */ 5696 if (qg->qg_numqueues <= 1) 5697 qdir = 0; 5698 else 5699 qdir = get_rand_mod(qg->qg_numqueues); 5700 5701 if (MinBlocksFree <= 0 && fsize <= 0) 5702 return qdir; 5703 5704 /* 5705 ** Now iterate over the queue directories, 5706 ** looking for a directory with enough space for this message. 5707 */ 5708 5709 i = qdir; 5710 do 5711 { 5712 QPATHS *qp = &qg->qg_qpaths[i]; 5713 long needed = 0; 5714 long fsavail = 0; 5715 5716 if (fsize > 0) 5717 needed += fsize / FILE_SYS_BLKSIZE(qp->qp_fsysidx) 5718 + ((fsize % FILE_SYS_BLKSIZE(qp->qp_fsysidx) 5719 > 0) ? 1 : 0); 5720 if (MinBlocksFree > 0) 5721 needed += MinBlocksFree; 5722 fsavail = FILE_SYS_AVAIL(qp->qp_fsysidx); 5723#if SM_CONF_SHM 5724 if (fsavail <= 0) 5725 { 5726 long blksize; 5727 5728 /* 5729 ** might be not correctly updated, 5730 ** let's try to get the info directly. 5731 */ 5732 5733 fsavail = freediskspace(FILE_SYS_NAME(qp->qp_fsysidx), 5734 &blksize); 5735 if (fsavail < 0) 5736 fsavail = 0; 5737 } 5738#endif /* SM_CONF_SHM */ 5739 if (needed <= fsavail) 5740 return i; 5741 if (avail < fsavail) 5742 avail = fsavail; 5743 5744 if (qg->qg_numqueues > 0) 5745 i = (i + 1) % qg->qg_numqueues; 5746 } while (i != qdir); 5747 5748 if (e != NULL && LogLevel > 0) 5749 sm_syslog(LOG_ALERT, e->e_id, 5750 "low on space (%s needs %ld bytes + %ld blocks in %s), max avail: %ld", 5751 CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, 5752 fsize, MinBlocksFree, 5753 qg->qg_qdir, avail); 5754 return NOQDIR; 5755} 5756/* 5757** SETNEWQUEUE -- Sets a new queue group and directory 5758** 5759** Assign a queue group and directory to an envelope and store the 5760** directory in e->e_qdir. 5761** 5762** Parameters: 5763** e -- envelope to assign a queue for. 5764** 5765** Returns: 5766** true if successful 5767** false otherwise 5768** 5769** Side Effects: 5770** On success, e->e_qgrp and e->e_qdir are non-negative. 5771** On failure (not enough disk space), 5772** e->qgrp = NOQGRP, e->e_qdir = NOQDIR 5773** and usrerr() is invoked (which could raise an exception). 5774*/ 5775 5776bool 5777setnewqueue(e) 5778 ENVELOPE *e; 5779{ 5780 if (tTd(41, 20)) 5781 sm_dprintf("setnewqueue: called\n"); 5782 5783 /* not set somewhere else */ 5784 if (e->e_qgrp == NOQGRP) 5785 { 5786 ADDRESS *q; 5787 5788 /* 5789 ** Use the queue group of the "first" recipient, as set by 5790 ** the "queuegroup" rule set. If that is not defined, then 5791 ** use the queue group of the mailer of the first recipient. 5792 ** If that is not defined either, then use the default 5793 ** queue group. 5794 ** Notice: "first" depends on the sorting of sendqueue 5795 ** in recipient(). 5796 ** To avoid problems with "bad" recipients look 5797 ** for a valid address first. 5798 */ 5799 5800 q = e->e_sendqueue; 5801 while (q != NULL && 5802 (QS_IS_BADADDR(q->q_state) || QS_IS_DEAD(q->q_state))) 5803 { 5804 q = q->q_next; 5805 } 5806 if (q == NULL) 5807 e->e_qgrp = 0; 5808 else if (q->q_qgrp >= 0) 5809 e->e_qgrp = q->q_qgrp; 5810 else if (q->q_mailer != NULL && 5811 ISVALIDQGRP(q->q_mailer->m_qgrp)) 5812 e->e_qgrp = q->q_mailer->m_qgrp; 5813 else 5814 e->e_qgrp = 0; 5815 e->e_dfqgrp = e->e_qgrp; 5816 } 5817 5818 if (ISVALIDQDIR(e->e_qdir) && ISVALIDQDIR(e->e_dfqdir)) 5819 { 5820 if (tTd(41, 20)) 5821 sm_dprintf("setnewqueue: e_qdir already assigned (%s)\n", 5822 qid_printqueue(e->e_qgrp, e->e_qdir)); 5823 return true; 5824 } 5825 5826 filesys_update(); 5827 e->e_qdir = pickqdir(Queue[e->e_qgrp], e->e_msgsize, e); 5828 if (e->e_qdir == NOQDIR) 5829 { 5830 e->e_qgrp = NOQGRP; 5831 if (!bitset(EF_FATALERRS, e->e_flags)) 5832 usrerr("452 4.4.5 Insufficient disk space; try again later"); 5833 e->e_flags |= EF_FATALERRS; 5834 return false; 5835 } 5836 5837 if (tTd(41, 3)) 5838 sm_dprintf("setnewqueue: Assigned queue directory %s\n", 5839 qid_printqueue(e->e_qgrp, e->e_qdir)); 5840 5841 if (e->e_xfqgrp == NOQGRP || e->e_xfqdir == NOQDIR) 5842 { 5843 e->e_xfqgrp = e->e_qgrp; 5844 e->e_xfqdir = e->e_qdir; 5845 } 5846 e->e_dfqdir = e->e_qdir; 5847 return true; 5848} 5849/* 5850** CHKQDIR -- check a queue directory 5851** 5852** Parameters: 5853** name -- name of queue directory 5854** sff -- flags for safefile() 5855** 5856** Returns: 5857** is it a queue directory? 5858*/ 5859 5860static bool 5861chkqdir(name, sff) 5862 char *name; 5863 long sff; 5864{ 5865 struct stat statb; 5866 int i; 5867 5868 /* skip over . and .. directories */ 5869 if (name[0] == '.' && 5870 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) 5871 return false; 5872#if HASLSTAT 5873 if (lstat(name, &statb) < 0) 5874#else /* HASLSTAT */ 5875 if (stat(name, &statb) < 0) 5876#endif /* HASLSTAT */ 5877 { 5878 if (tTd(41, 2)) 5879 sm_dprintf("chkqdir: stat(\"%s\"): %s\n", 5880 name, sm_errstring(errno)); 5881 return false; 5882 } 5883#if HASLSTAT 5884 if (S_ISLNK(statb.st_mode)) 5885 { 5886 /* 5887 ** For a symlink we need to make sure the 5888 ** target is a directory 5889 */ 5890 5891 if (stat(name, &statb) < 0) 5892 { 5893 if (tTd(41, 2)) 5894 sm_dprintf("chkqdir: stat(\"%s\"): %s\n", 5895 name, sm_errstring(errno)); 5896 return false; 5897 } 5898 } 5899#endif /* HASLSTAT */ 5900 5901 if (!S_ISDIR(statb.st_mode)) 5902 { 5903 if (tTd(41, 2)) 5904 sm_dprintf("chkqdir: \"%s\": Not a directory\n", 5905 name); 5906 return false; 5907 } 5908 5909 /* Print a warning if unsafe (but still use it) */ 5910 /* XXX do this only if we want the warning? */ 5911 i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0); 5912 if (i != 0) 5913 { 5914 if (tTd(41, 2)) 5915 sm_dprintf("chkqdir: \"%s\": Not safe: %s\n", 5916 name, sm_errstring(i)); 5917#if _FFR_CHK_QUEUE 5918 if (LogLevel > 8) 5919 sm_syslog(LOG_WARNING, NOQID, 5920 "queue directory \"%s\": Not safe: %s", 5921 name, sm_errstring(i)); 5922#endif /* _FFR_CHK_QUEUE */ 5923 } 5924 return true; 5925} 5926/* 5927** MULTIQUEUE_CACHE -- cache a list of paths to queues. 5928** 5929** Each potential queue is checked as the cache is built. 5930** Thereafter, each is blindly trusted. 5931** Note that we can be called again after a timeout to rebuild 5932** (although code for that is not ready yet). 5933** 5934** Parameters: 5935** basedir -- base of all queue directories. 5936** blen -- strlen(basedir). 5937** qg -- queue group. 5938** qn -- number of queue directories already cached. 5939** phash -- pointer to hash value over queue dirs. 5940#if SM_CONF_SHM 5941** only used if shared memory is active. 5942#endif * SM_CONF_SHM * 5943** 5944** Returns: 5945** new number of queue directories. 5946*/ 5947 5948#define INITIAL_SLOTS 20 5949#define ADD_SLOTS 10 5950 5951static int 5952multiqueue_cache(basedir, blen, qg, qn, phash) 5953 char *basedir; 5954 int blen; 5955 QUEUEGRP *qg; 5956 int qn; 5957 unsigned int *phash; 5958{ 5959 char *cp; 5960 int i, len; 5961 int slotsleft = 0; 5962 long sff = SFF_ANYFILE; 5963 char qpath[MAXPATHLEN]; 5964 char subdir[MAXPATHLEN]; 5965 char prefix[MAXPATHLEN]; /* dir relative to basedir */ 5966 5967 if (tTd(41, 20)) 5968 sm_dprintf("multiqueue_cache: called\n"); 5969 5970 /* Initialize to current directory */ 5971 prefix[0] = '.'; 5972 prefix[1] = '\0'; 5973 if (qg->qg_numqueues != 0 && qg->qg_qpaths != NULL) 5974 { 5975 for (i = 0; i < qg->qg_numqueues; i++) 5976 { 5977 if (qg->qg_qpaths[i].qp_name != NULL) 5978 (void) sm_free(qg->qg_qpaths[i].qp_name); /* XXX */ 5979 } 5980 (void) sm_free((char *) qg->qg_qpaths); /* XXX */ 5981 qg->qg_qpaths = NULL; 5982 qg->qg_numqueues = 0; 5983 } 5984 5985 /* If running as root, allow safedirpath() checks to use privs */ 5986 if (RunAsUid == 0) 5987 sff |= SFF_ROOTOK; 5988#if _FFR_CHK_QUEUE 5989 sff |= SFF_SAFEDIRPATH|SFF_NOWWFILES; 5990 if (!UseMSP) 5991 sff |= SFF_NOGWFILES; 5992#endif /* _FFR_CHK_QUEUE */ 5993 5994 if (!SM_IS_DIR_START(qg->qg_qdir)) 5995 { 5996 /* 5997 ** XXX we could add basedir, but then we have to realloc() 5998 ** the string... Maybe another time. 5999 */ 6000 6001 syserr("QueuePath %s not absolute", qg->qg_qdir); 6002 ExitStat = EX_CONFIG; 6003 return qn; 6004 } 6005 6006 /* qpath: directory of current workgroup */ 6007 len = sm_strlcpy(qpath, qg->qg_qdir, sizeof qpath); 6008 if (len >= sizeof qpath) 6009 { 6010 syserr("QueuePath %.256s too long (%d max)", 6011 qg->qg_qdir, (int) sizeof qpath); 6012 ExitStat = EX_CONFIG; 6013 return qn; 6014 } 6015 6016 /* begin of qpath must be same as basedir */ 6017 if (strncmp(basedir, qpath, blen) != 0 && 6018 (strncmp(basedir, qpath, blen - 1) != 0 || len != blen - 1)) 6019 { 6020 syserr("QueuePath %s not subpath of QueueDirectory %s", 6021 qpath, basedir); 6022 ExitStat = EX_CONFIG; 6023 return qn; 6024 } 6025 6026 /* Do we have a nested subdirectory? */ 6027 if (blen < len && SM_FIRST_DIR_DELIM(qg->qg_qdir + blen) != NULL) 6028 { 6029 6030 /* Copy subdirectory into prefix for later use */ 6031 if (sm_strlcpy(prefix, qg->qg_qdir + blen, sizeof prefix) >= 6032 sizeof prefix) 6033 { 6034 syserr("QueuePath %.256s too long (%d max)", 6035 qg->qg_qdir, (int) sizeof qpath); 6036 ExitStat = EX_CONFIG; 6037 return qn; 6038 } 6039 cp = SM_LAST_DIR_DELIM(prefix); 6040 SM_ASSERT(cp != NULL); 6041 *cp = '\0'; /* cut off trailing / */ 6042 } 6043 6044 /* This is guaranteed by the basedir check above */ 6045 SM_ASSERT(len >= blen - 1); 6046 cp = &qpath[len - 1]; 6047 if (*cp == '*') 6048 { 6049 register DIR *dp; 6050 register struct dirent *d; 6051 int off; 6052 char *delim; 6053 char relpath[MAXPATHLEN]; 6054 6055 *cp = '\0'; /* Overwrite wildcard */ 6056 if ((cp = SM_LAST_DIR_DELIM(qpath)) == NULL) 6057 { 6058 syserr("QueueDirectory: can not wildcard relative path"); 6059 if (tTd(41, 2)) 6060 sm_dprintf("multiqueue_cache: \"%s*\": Can not wildcard relative path.\n", 6061 qpath); 6062 ExitStat = EX_CONFIG; 6063 return qn; 6064 } 6065 if (cp == qpath) 6066 { 6067 /* 6068 ** Special case of top level wildcard, like /foo* 6069 ** Change to //foo* 6070 */ 6071 6072 (void) sm_strlcpy(qpath + 1, qpath, sizeof qpath - 1); 6073 ++cp; 6074 } 6075 delim = cp; 6076 *(cp++) = '\0'; /* Replace / with \0 */ 6077 len = strlen(cp); /* Last component of queue directory */ 6078 6079 /* 6080 ** Path relative to basedir, with trailing / 6081 ** It will be modified below to specify the subdirectories 6082 ** so they can be opened without chdir(). 6083 */ 6084 6085 off = sm_strlcpyn(relpath, sizeof relpath, 2, prefix, "/"); 6086 SM_ASSERT(off < sizeof relpath); 6087 6088 if (tTd(41, 2)) 6089 sm_dprintf("multiqueue_cache: prefix=\"%s%s\"\n", 6090 relpath, cp); 6091 6092 /* It is always basedir: we don't need to store it per group */ 6093 /* XXX: optimize this! -> one more global? */ 6094 qg->qg_qdir = newstr(basedir); 6095 qg->qg_qdir[blen - 1] = '\0'; /* cut off trailing / */ 6096 6097 /* 6098 ** XXX Should probably wrap this whole loop in a timeout 6099 ** in case some wag decides to NFS mount the queues. 6100 */ 6101 6102 /* Test path to get warning messages. */ 6103 if (qn == 0) 6104 { 6105 /* XXX qg_runasuid and qg_runasgid for specials? */ 6106 i = safedirpath(basedir, RunAsUid, RunAsGid, NULL, 6107 sff, 0, 0); 6108 if (i != 0 && tTd(41, 2)) 6109 sm_dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", 6110 basedir, sm_errstring(i)); 6111 } 6112 6113 if ((dp = opendir(prefix)) == NULL) 6114 { 6115 syserr("can not opendir(%s/%s)", qg->qg_qdir, prefix); 6116 if (tTd(41, 2)) 6117 sm_dprintf("multiqueue_cache: opendir(\"%s/%s\"): %s\n", 6118 qg->qg_qdir, prefix, 6119 sm_errstring(errno)); 6120 ExitStat = EX_CONFIG; 6121 return qn; 6122 } 6123 while ((d = readdir(dp)) != NULL) 6124 { 6125 i = strlen(d->d_name); 6126 if (i < len || strncmp(d->d_name, cp, len) != 0) 6127 { 6128 if (tTd(41, 5)) 6129 sm_dprintf("multiqueue_cache: \"%s\", skipped\n", 6130 d->d_name); 6131 continue; 6132 } 6133 6134 /* Create relative pathname: prefix + local directory */ 6135 i = sizeof(relpath) - off; 6136 if (sm_strlcpy(relpath + off, d->d_name, i) >= i) 6137 continue; /* way too long */ 6138 6139 if (!chkqdir(relpath, sff)) 6140 continue; 6141 6142 if (qg->qg_qpaths == NULL) 6143 { 6144 slotsleft = INITIAL_SLOTS; 6145 qg->qg_qpaths = (QPATHS *)xalloc((sizeof *qg->qg_qpaths) * 6146 slotsleft); 6147 qg->qg_numqueues = 0; 6148 } 6149 else if (slotsleft < 1) 6150 { 6151 qg->qg_qpaths = (QPATHS *)sm_realloc((char *)qg->qg_qpaths, 6152 (sizeof *qg->qg_qpaths) * 6153 (qg->qg_numqueues + 6154 ADD_SLOTS)); 6155 if (qg->qg_qpaths == NULL) 6156 { 6157 (void) closedir(dp); 6158 return qn; 6159 } 6160 slotsleft += ADD_SLOTS; 6161 } 6162 6163 /* check subdirs */ 6164 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs = QP_NOSUB; 6165 6166#define CHKRSUBDIR(name, flag) \ 6167 (void) sm_strlcpyn(subdir, sizeof subdir, 3, relpath, "/", name); \ 6168 if (chkqdir(subdir, sff)) \ 6169 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs |= flag; \ 6170 else 6171 6172 6173 CHKRSUBDIR("qf", QP_SUBQF); 6174 CHKRSUBDIR("df", QP_SUBDF); 6175 CHKRSUBDIR("xf", QP_SUBXF); 6176 6177 /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */ 6178 /* maybe even - 17 (subdirs) */ 6179 6180 if (prefix[0] != '.') 6181 qg->qg_qpaths[qg->qg_numqueues].qp_name = 6182 newstr(relpath); 6183 else 6184 qg->qg_qpaths[qg->qg_numqueues].qp_name = 6185 newstr(d->d_name); 6186 6187 if (tTd(41, 2)) 6188 sm_dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n", 6189 qg->qg_numqueues, relpath, 6190 qg->qg_qpaths[qg->qg_numqueues].qp_subdirs); 6191#if SM_CONF_SHM 6192 qg->qg_qpaths[qg->qg_numqueues].qp_idx = qn; 6193 *phash = hash_q(relpath, *phash); 6194#endif /* SM_CONF_SHM */ 6195 qg->qg_numqueues++; 6196 ++qn; 6197 slotsleft--; 6198 } 6199 (void) closedir(dp); 6200 6201 /* undo damage */ 6202 *delim = '/'; 6203 } 6204 if (qg->qg_numqueues == 0) 6205 { 6206 qg->qg_qpaths = (QPATHS *) xalloc(sizeof *qg->qg_qpaths); 6207 6208 /* test path to get warning messages */ 6209 i = safedirpath(qpath, RunAsUid, RunAsGid, NULL, sff, 0, 0); 6210 if (i == ENOENT) 6211 { 6212 syserr("can not opendir(%s)", qpath); 6213 if (tTd(41, 2)) 6214 sm_dprintf("multiqueue_cache: opendir(\"%s\"): %s\n", 6215 qpath, sm_errstring(i)); 6216 ExitStat = EX_CONFIG; 6217 return qn; 6218 } 6219 6220 qg->qg_qpaths[0].qp_subdirs = QP_NOSUB; 6221 qg->qg_numqueues = 1; 6222 6223 /* check subdirs */ 6224#define CHKSUBDIR(name, flag) \ 6225 (void) sm_strlcpyn(subdir, sizeof subdir, 3, qg->qg_qdir, "/", name); \ 6226 if (chkqdir(subdir, sff)) \ 6227 qg->qg_qpaths[0].qp_subdirs |= flag; \ 6228 else 6229 6230 CHKSUBDIR("qf", QP_SUBQF); 6231 CHKSUBDIR("df", QP_SUBDF); 6232 CHKSUBDIR("xf", QP_SUBXF); 6233 6234 if (qg->qg_qdir[blen - 1] != '\0' && 6235 qg->qg_qdir[blen] != '\0') 6236 { 6237 /* 6238 ** Copy the last component into qpaths and 6239 ** cut off qdir 6240 */ 6241 6242 qg->qg_qpaths[0].qp_name = newstr(qg->qg_qdir + blen); 6243 qg->qg_qdir[blen - 1] = '\0'; 6244 } 6245 else 6246 qg->qg_qpaths[0].qp_name = newstr("."); 6247 6248#if SM_CONF_SHM 6249 qg->qg_qpaths[0].qp_idx = qn; 6250 *phash = hash_q(qg->qg_qpaths[0].qp_name, *phash); 6251#endif /* SM_CONF_SHM */ 6252 ++qn; 6253 } 6254 return qn; 6255} 6256 6257/* 6258** FILESYS_FIND -- find entry in FileSys table, or add new one 6259** 6260** Given the pathname of a directory, determine the file system 6261** in which that directory resides, and return a pointer to the 6262** entry in the FileSys table that describes the file system. 6263** A new entry is added if necessary (and requested). 6264** If the directory does not exist, -1 is returned. 6265** 6266** Parameters: 6267** path -- pathname of directory 6268** add -- add to structure if not found. 6269** 6270** Returns: 6271** >=0: found: index in file system table 6272** <0: some error, i.e., 6273** FSF_TOO_MANY: too many filesystems (-> syserr()) 6274** FSF_STAT_FAIL: can't stat() filesystem (-> syserr()) 6275** FSF_NOT_FOUND: not in list 6276*/ 6277 6278static short filesys_find __P((char *, bool)); 6279 6280#define FSF_NOT_FOUND (-1) 6281#define FSF_STAT_FAIL (-2) 6282#define FSF_TOO_MANY (-3) 6283 6284static short 6285filesys_find(path, add) 6286 char *path; 6287 bool add; 6288{ 6289 struct stat st; 6290 short i; 6291 6292 if (stat(path, &st) < 0) 6293 { 6294 syserr("cannot stat queue directory %s", path); 6295 return FSF_STAT_FAIL; 6296 } 6297 for (i = 0; i < NumFileSys; ++i) 6298 { 6299 if (FILE_SYS_DEV(i) == st.st_dev) 6300 return i; 6301 } 6302 if (i >= MAXFILESYS) 6303 { 6304 syserr("too many queue file systems (%d max)", MAXFILESYS); 6305 return FSF_TOO_MANY; 6306 } 6307 if (!add) 6308 return FSF_NOT_FOUND; 6309 6310 ++NumFileSys; 6311 FILE_SYS_NAME(i) = path; 6312 FILE_SYS_DEV(i) = st.st_dev; 6313 FILE_SYS_AVAIL(i) = 0; 6314 FILE_SYS_BLKSIZE(i) = 1024; /* avoid divide by zero */ 6315 return i; 6316} 6317 6318/* 6319** FILESYS_SETUP -- set up mapping from queue directories to file systems 6320** 6321** This data structure is used to efficiently check the amount of 6322** free space available in a set of queue directories. 6323** 6324** Parameters: 6325** add -- initialize structure if necessary. 6326** 6327** Returns: 6328** 0: success 6329** <0: some error, i.e., 6330** FSF_NOT_FOUND: not in list 6331** FSF_STAT_FAIL: can't stat() filesystem (-> syserr()) 6332** FSF_TOO_MANY: too many filesystems (-> syserr()) 6333*/ 6334 6335static int filesys_setup __P((bool)); 6336 6337static int 6338filesys_setup(add) 6339 bool add; 6340{ 6341 int i, j; 6342 short fs; 6343 int ret; 6344 6345 ret = 0; 6346 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 6347 { 6348 for (j = 0; j < Queue[i]->qg_numqueues; ++j) 6349 { 6350 QPATHS *qp = &Queue[i]->qg_qpaths[j]; 6351 6352 fs = filesys_find(qp->qp_name, add); 6353 if (fs >= 0) 6354 qp->qp_fsysidx = fs; 6355 else 6356 qp->qp_fsysidx = 0; 6357 if (fs < ret) 6358 ret = fs; 6359 } 6360 } 6361 return ret; 6362} 6363 6364/* 6365** FILESYS_UPDATE -- update amount of free space on all file systems 6366** 6367** The FileSys table is used to cache the amount of free space 6368** available on all queue directory file systems. 6369** This function updates the cached information if it has expired. 6370** 6371** Parameters: 6372** none. 6373** 6374** Returns: 6375** none. 6376** 6377** Side Effects: 6378** Updates FileSys table. 6379*/ 6380 6381void 6382filesys_update() 6383{ 6384 int i; 6385 long avail, blksize; 6386 time_t now; 6387 static time_t nextupdate = 0; 6388 6389#if SM_CONF_SHM 6390 /* only the daemon updates this structure */ 6391 if (ShmId != SM_SHM_NO_ID && DaemonPid != CurrentPid) 6392 return; 6393#endif /* SM_CONF_SHM */ 6394 now = curtime(); 6395 if (now < nextupdate) 6396 return; 6397 nextupdate = now + FILESYS_UPDATE_INTERVAL; 6398 for (i = 0; i < NumFileSys; ++i) 6399 { 6400 FILESYS *fs = &FILE_SYS(i); 6401 6402 avail = freediskspace(FILE_SYS_NAME(i), &blksize); 6403 if (avail < 0 || blksize <= 0) 6404 { 6405 if (LogLevel > 5) 6406 sm_syslog(LOG_ERR, NOQID, 6407 "filesys_update failed: %s, fs=%s, avail=%ld, blocksize=%ld", 6408 sm_errstring(errno), 6409 FILE_SYS_NAME(i), avail, blksize); 6410 fs->fs_avail = 0; 6411 fs->fs_blksize = 1024; /* avoid divide by zero */ 6412 nextupdate = now + 2; /* let's do this soon again */ 6413 } 6414 else 6415 { 6416 fs->fs_avail = avail; 6417 fs->fs_blksize = blksize; 6418 } 6419 } 6420} 6421 6422#if _FFR_ANY_FREE_FS 6423/* 6424** FILESYS_FREE -- check whether there is at least one fs with enough space. 6425** 6426** Parameters: 6427** fsize -- file size in bytes 6428** 6429** Returns: 6430** true iff there is one fs with more than fsize bytes free. 6431*/ 6432 6433bool 6434filesys_free(fsize) 6435 long fsize; 6436{ 6437 int i; 6438 6439 if (fsize <= 0) 6440 return true; 6441 for (i = 0; i < NumFileSys; ++i) 6442 { 6443 long needed = 0; 6444 6445 if (FILE_SYS_AVAIL(i) < 0 || FILE_SYS_BLKSIZE(i) <= 0) 6446 continue; 6447 needed += fsize / FILE_SYS_BLKSIZE(i) 6448 + ((fsize % FILE_SYS_BLKSIZE(i) 6449 > 0) ? 1 : 0) 6450 + MinBlocksFree; 6451 if (needed <= FILE_SYS_AVAIL(i)) 6452 return true; 6453 } 6454 return false; 6455} 6456#endif /* _FFR_ANY_FREE_FS */ 6457 6458#if _FFR_CONTROL_MSTAT 6459/* 6460** DISK_STATUS -- show amount of free space in queue directories 6461** 6462** Parameters: 6463** out -- output file pointer. 6464** prefix -- string to output in front of each line. 6465** 6466** Returns: 6467** none. 6468*/ 6469 6470void 6471disk_status(out, prefix) 6472 SM_FILE_T *out; 6473 char *prefix; 6474{ 6475 int i; 6476 long avail, blksize; 6477 long free; 6478 6479 for (i = 0; i < NumFileSys; ++i) 6480 { 6481 avail = freediskspace(FILE_SYS_NAME(i), &blksize); 6482 if (avail >= 0 && blksize > 0) 6483 { 6484 free = (long)((double) avail * 6485 ((double) blksize / 1024)); 6486 } 6487 else 6488 free = -1; 6489 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, 6490 "%s%d/%s/%ld\r\n", 6491 prefix, i, 6492 FILE_SYS_NAME(i), 6493 free); 6494 } 6495} 6496#endif /* _FFR_CONTROL_MSTAT */ 6497 6498#if SM_CONF_SHM 6499/* 6500** UPD_QS -- update information about queue when adding/deleting an entry 6501** 6502** Parameters: 6503** e -- envelope. 6504** delete -- delete/add entry. 6505** avail -- update the space available as well. 6506** 6507** Returns: 6508** none. 6509** 6510** Side Effects: 6511** Modifies available space in filesystem. 6512** Changes number of entries in queue directory. 6513*/ 6514 6515void 6516upd_qs(e, delete, avail) 6517 ENVELOPE *e; 6518 bool delete; 6519 bool avail; 6520{ 6521 short fidx; 6522 int idx; 6523 long s; 6524 6525 if (ShmId == SM_SHM_NO_ID || e == NULL) 6526 return; 6527 if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR) 6528 return; 6529 idx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_idx; 6530 6531 /* XXX in theory this needs to be protected with a mutex */ 6532 if (QSHM_ENTRIES(idx) >= 0) 6533 { 6534 if (delete) 6535 --QSHM_ENTRIES(idx); 6536 else 6537 ++QSHM_ENTRIES(idx); 6538 } 6539 6540 fidx = Queue[e->e_qgrp]->qg_qpaths[e->e_qdir].qp_fsysidx; 6541 if (fidx < 0) 6542 return; 6543 6544 /* update available space also? (might be loseqfile) */ 6545 if (!avail) 6546 return; 6547 6548 /* convert size to blocks; this causes rounding errors */ 6549 s = e->e_msgsize / FILE_SYS_BLKSIZE(fidx); 6550 if (s == 0) 6551 return; 6552 6553 /* XXX in theory this needs to be protected with a mutex */ 6554 if (delete) 6555 FILE_SYS_AVAIL(fidx) += s; 6556 else 6557 FILE_SYS_AVAIL(fidx) -= s; 6558 6559} 6560 6561#if _FFR_SELECT_SHM 6562 6563static bool write_key_file __P((char *, long)); 6564static long read_key_file __P((char *, long)); 6565 6566/* 6567** WRITE_KEY_FILE -- record some key into a file. 6568** 6569** Parameters: 6570** keypath -- file name. 6571** key -- key to write. 6572** 6573** Returns: 6574** true iff file could be written. 6575** 6576** Side Effects: 6577** writes file. 6578*/ 6579 6580static bool 6581write_key_file(keypath, key) 6582 char *keypath; 6583 long key; 6584{ 6585 bool ok; 6586 long sff; 6587 SM_FILE_T *keyf; 6588 6589 ok = false; 6590 if (keypath == NULL || *keypath == '\0') 6591 return ok; 6592 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 6593 if (TrustedUid != 0 && RealUid == TrustedUid) 6594 sff |= SFF_OPENASROOT; 6595 keyf = safefopen(keypath, O_WRONLY|O_TRUNC, FileMode, sff); 6596 if (keyf == NULL) 6597 { 6598 sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", 6599 keypath, sm_errstring(errno)); 6600 } 6601 else 6602 { 6603 ok = sm_io_fprintf(keyf, SM_TIME_DEFAULT, "%ld\n", key) != 6604 SM_IO_EOF; 6605 ok = (sm_io_close(keyf, SM_TIME_DEFAULT) != SM_IO_EOF) && ok; 6606 } 6607 return ok; 6608} 6609 6610/* 6611** READ_KEY_FILE -- read a key from a file. 6612** 6613** Parameters: 6614** keypath -- file name. 6615** key -- default key. 6616** 6617** Returns: 6618** key. 6619*/ 6620 6621static long 6622read_key_file(keypath, key) 6623 char *keypath; 6624 long key; 6625{ 6626 int r; 6627 long sff, n; 6628 SM_FILE_T *keyf; 6629 6630 if (keypath == NULL || *keypath == '\0') 6631 return key; 6632 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY; 6633 if (RealUid == 0 || (TrustedUid != 0 && RealUid == TrustedUid)) 6634 sff |= SFF_OPENASROOT; 6635 keyf = safefopen(keypath, O_RDONLY, FileMode, sff); 6636 if (keyf == NULL) 6637 { 6638 sm_syslog(LOG_ERR, NOQID, "unable to read %s: %s", 6639 keypath, sm_errstring(errno)); 6640 } 6641 else 6642 { 6643 r = sm_io_fscanf(keyf, SM_TIME_DEFAULT, "%ld", &n); 6644 if (r == 1) 6645 key = n; 6646 (void) sm_io_close(keyf, SM_TIME_DEFAULT); 6647 } 6648 return key; 6649} 6650#endif /* _FFR_SELECT_SHM */ 6651 6652/* 6653** INIT_SHM -- initialize shared memory structure 6654** 6655** Initialize or attach to shared memory segment. 6656** Currently it is not a fatal error if this doesn't work. 6657** However, it causes us to have a "fallback" storage location 6658** for everything that is supposed to be in the shared memory, 6659** which makes the code slightly ugly. 6660** 6661** Parameters: 6662** qn -- number of queue directories. 6663** owner -- owner of shared memory. 6664** hash -- identifies data that is stored in shared memory. 6665** 6666** Returns: 6667** none. 6668*/ 6669 6670static void init_shm __P((int, bool, unsigned int)); 6671 6672static void 6673init_shm(qn, owner, hash) 6674 int qn; 6675 bool owner; 6676 unsigned int hash; 6677{ 6678 int i; 6679#if _FFR_SELECT_SHM 6680 bool keyselect; 6681#endif /* _FFR_SELECT_SHM */ 6682 6683 PtrFileSys = &FileSys[0]; 6684 PNumFileSys = &Numfilesys; 6685#if _FFR_SELECT_SHM 6686/* if this "key" is specified: select one yourself */ 6687# define SEL_SHM_KEY ((key_t) -1) 6688# define FIRST_SHM_KEY 25 6689#endif /* _FFR_SELECT_SHM */ 6690 6691 /* This allows us to disable shared memory at runtime. */ 6692 if (ShmKey != 0) 6693 { 6694 int count; 6695 int save_errno; 6696 6697 count = 0; 6698 shms = SM_T_SIZE + qn * sizeof(QUEUE_SHM_T); 6699#if _FFR_SELECT_SHM 6700 keyselect = ShmKey == SEL_SHM_KEY; 6701 if (keyselect) 6702 { 6703 if (owner) 6704 ShmKey = FIRST_SHM_KEY; 6705 else 6706 { 6707 ShmKey = read_key_file(ShmKeyFile, ShmKey); 6708 keyselect = false; 6709 if (ShmKey == SEL_SHM_KEY) 6710 goto error; 6711 } 6712 } 6713#endif /* _FFR_SELECT_SHM */ 6714 for (;;) 6715 { 6716 /* XXX: maybe allow read access for group? */ 6717 Pshm = sm_shmstart(ShmKey, shms, SHM_R|SHM_W, &ShmId, 6718 owner); 6719 save_errno = errno; 6720 if (Pshm != NULL || !sm_file_exists(save_errno)) 6721 break; 6722 if (++count >= 3) 6723 { 6724#if _FFR_SELECT_SHM 6725 if (keyselect) 6726 { 6727 ++ShmKey; 6728 6729 /* back where we started? */ 6730 if (ShmKey == SEL_SHM_KEY) 6731 break; 6732 continue; 6733 } 6734#endif /* _FFR_SELECT_SHM */ 6735 break; 6736 } 6737#if _FFR_SELECT_SHM 6738 /* only sleep if we are at the first key */ 6739 if (!keyselect || ShmKey == SEL_SHM_KEY) 6740#endif /* _FFR_SELECT_SHM */ 6741 sleep(count); 6742 } 6743 if (Pshm != NULL) 6744 { 6745 int *p; 6746 6747#if _FFR_SELECT_SHM 6748 if (keyselect) 6749 (void) write_key_file(ShmKeyFile, (long) ShmKey); 6750#endif /* _FFR_SELECT_SHM */ 6751 p = (int *) Pshm; 6752 if (owner) 6753 { 6754 *p = (int) shms; 6755 *((pid_t *) SHM_OFF_PID(Pshm)) = CurrentPid; 6756 p = (int *) SHM_OFF_TAG(Pshm); 6757 *p = hash; 6758 } 6759 else 6760 { 6761 if (*p != (int) shms) 6762 { 6763 save_errno = EINVAL; 6764 cleanup_shm(false); 6765 goto error; 6766 } 6767 p = (int *) SHM_OFF_TAG(Pshm); 6768 if (*p != (int) hash) 6769 { 6770 save_errno = EINVAL; 6771 cleanup_shm(false); 6772 goto error; 6773 } 6774 6775 /* 6776 ** XXX how to check the pid? 6777 ** Read it from the pid-file? That does 6778 ** not need to exist. 6779 ** We could disable shm if we can't confirm 6780 ** that it is the right one. 6781 */ 6782 } 6783 6784 PtrFileSys = (FILESYS *) OFF_FILE_SYS(Pshm); 6785 PNumFileSys = (int *) OFF_NUM_FILE_SYS(Pshm); 6786 QShm = (QUEUE_SHM_T *) OFF_QUEUE_SHM(Pshm); 6787 PRSATmpCnt = (int *) OFF_RSA_TMP_CNT(Pshm); 6788 *PRSATmpCnt = 0; 6789 if (owner) 6790 { 6791 /* initialize values in shared memory */ 6792 NumFileSys = 0; 6793 for (i = 0; i < qn; i++) 6794 QShm[i].qs_entries = -1; 6795 } 6796 return; 6797 } 6798 error: 6799 if (LogLevel > (owner ? 8 : 11)) 6800 { 6801 sm_syslog(owner ? LOG_ERR : LOG_NOTICE, NOQID, 6802 "can't %s shared memory, key=%ld: %s", 6803 owner ? "initialize" : "attach to", 6804 (long) ShmKey, sm_errstring(save_errno)); 6805 } 6806 } 6807} 6808#endif /* SM_CONF_SHM */ 6809 6810 6811/* 6812** SETUP_QUEUES -- setup all queue groups 6813** 6814** Parameters: 6815** owner -- owner of shared memory. 6816** 6817** Returns: 6818** none. 6819** 6820#if SM_CONF_SHM 6821** Side Effects: 6822** attaches shared memory. 6823#endif * SM_CONF_SHM * 6824*/ 6825 6826void 6827setup_queues(owner) 6828 bool owner; 6829{ 6830 int i, qn, len; 6831 unsigned int hashval; 6832 time_t now; 6833 char basedir[MAXPATHLEN]; 6834 struct stat st; 6835 6836 /* 6837 ** Determine basedir for all queue directories. 6838 ** All queue directories must be (first level) subdirectories 6839 ** of the basedir. The basedir is the QueueDir 6840 ** without wildcards, but with trailing / 6841 */ 6842 6843 hashval = 0; 6844 errno = 0; 6845 len = sm_strlcpy(basedir, QueueDir, sizeof basedir); 6846 6847 /* Provide space for trailing '/' */ 6848 if (len >= sizeof basedir - 1) 6849 { 6850 syserr("QueueDirectory: path too long: %d, max %d", 6851 len, (int) sizeof basedir - 1); 6852 ExitStat = EX_CONFIG; 6853 return; 6854 } 6855 SM_ASSERT(len > 0); 6856 if (basedir[len - 1] == '*') 6857 { 6858 char *cp; 6859 6860 cp = SM_LAST_DIR_DELIM(basedir); 6861 if (cp == NULL) 6862 { 6863 syserr("QueueDirectory: can not wildcard relative path \"%s\"", 6864 QueueDir); 6865 if (tTd(41, 2)) 6866 sm_dprintf("setup_queues: \"%s\": Can not wildcard relative path.\n", 6867 QueueDir); 6868 ExitStat = EX_CONFIG; 6869 return; 6870 } 6871 6872 /* cut off wildcard pattern */ 6873 *++cp = '\0'; 6874 len = cp - basedir; 6875 } 6876 else if (!SM_IS_DIR_DELIM(basedir[len - 1])) 6877 { 6878 /* append trailing slash since it is a directory */ 6879 basedir[len] = '/'; 6880 basedir[++len] = '\0'; 6881 } 6882 6883 /* len counts up to the last directory delimiter */ 6884 SM_ASSERT(basedir[len - 1] == '/'); 6885 6886 if (chdir(basedir) < 0) 6887 { 6888 int save_errno = errno; 6889 6890 syserr("can not chdir(%s)", basedir); 6891 if (save_errno == EACCES) 6892 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 6893 "Program mode requires special privileges, e.g., root or TrustedUser.\n"); 6894 if (tTd(41, 2)) 6895 sm_dprintf("setup_queues: \"%s\": %s\n", 6896 basedir, sm_errstring(errno)); 6897 ExitStat = EX_CONFIG; 6898 return; 6899 } 6900#if SM_CONF_SHM 6901 hashval = hash_q(basedir, hashval); 6902#endif /* SM_CONF_SHM */ 6903 6904 /* initialize for queue runs */ 6905 DoQueueRun = false; 6906 now = curtime(); 6907 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 6908 Queue[i]->qg_nextrun = now; 6909 6910 6911 if (UseMSP && OpMode != MD_TEST) 6912 { 6913 long sff = SFF_CREAT; 6914 6915 if (stat(".", &st) < 0) 6916 { 6917 syserr("can not stat(%s)", basedir); 6918 if (tTd(41, 2)) 6919 sm_dprintf("setup_queues: \"%s\": %s\n", 6920 basedir, sm_errstring(errno)); 6921 ExitStat = EX_CONFIG; 6922 return; 6923 } 6924 if (RunAsUid == 0) 6925 sff |= SFF_ROOTOK; 6926 6927 /* 6928 ** Check queue directory permissions. 6929 ** Can we write to a group writable queue directory? 6930 */ 6931 6932 if (bitset(S_IWGRP, QueueFileMode) && 6933 bitset(S_IWGRP, st.st_mode) && 6934 safefile(" ", RunAsUid, RunAsGid, RunAsUserName, sff, 6935 QueueFileMode, NULL) != 0) 6936 { 6937 syserr("can not write to queue directory %s (RunAsGid=%d, required=%d)", 6938 basedir, (int) RunAsGid, (int) st.st_gid); 6939 } 6940 if (bitset(S_IWOTH|S_IXOTH, st.st_mode)) 6941 { 6942#if _FFR_MSP_PARANOIA 6943 syserr("dangerous permissions=%o on queue directory %s", 6944 (int) st.st_mode, basedir); 6945#else /* _FFR_MSP_PARANOIA */ 6946 if (LogLevel > 0) 6947 sm_syslog(LOG_ERR, NOQID, 6948 "dangerous permissions=%o on queue directory %s", 6949 (int) st.st_mode, basedir); 6950#endif /* _FFR_MSP_PARANOIA */ 6951 } 6952#if _FFR_MSP_PARANOIA 6953 if (NumQueue > 1) 6954 syserr("can not use multiple queues for MSP"); 6955#endif /* _FFR_MSP_PARANOIA */ 6956 } 6957 6958 /* initial number of queue directories */ 6959 qn = 0; 6960 for (i = 0; i < NumQueue && Queue[i] != NULL; i++) 6961 qn = multiqueue_cache(basedir, len, Queue[i], qn, &hashval); 6962 6963#if SM_CONF_SHM 6964 init_shm(qn, owner, hashval); 6965 i = filesys_setup(owner || ShmId == SM_SHM_NO_ID); 6966 if (i == FSF_NOT_FOUND) 6967 { 6968 /* 6969 ** We didn't get the right filesystem data 6970 ** This may happen if we don't have the right shared memory. 6971 ** So let's do this without shared memory. 6972 */ 6973 6974 SM_ASSERT(!owner); 6975 cleanup_shm(false); /* release shared memory */ 6976 i = filesys_setup(false); 6977 if (i < 0) 6978 syserr("filesys_setup failed twice, result=%d", i); 6979 else if (LogLevel > 8) 6980 sm_syslog(LOG_WARNING, NOQID, 6981 "shared memory does not contain expected data, ignored"); 6982 } 6983#else /* SM_CONF_SHM */ 6984 i = filesys_setup(true); 6985#endif /* SM_CONF_SHM */ 6986 if (i < 0) 6987 ExitStat = EX_CONFIG; 6988} 6989 6990#if SM_CONF_SHM 6991/* 6992** CLEANUP_SHM -- do some cleanup work for shared memory etc 6993** 6994** Parameters: 6995** owner -- owner of shared memory? 6996** 6997** Returns: 6998** none. 6999** 7000** Side Effects: 7001** detaches shared memory. 7002*/ 7003 7004void 7005cleanup_shm(owner) 7006 bool owner; 7007{ 7008 if (ShmId != SM_SHM_NO_ID) 7009 { 7010 if (sm_shmstop(Pshm, ShmId, owner) < 0 && LogLevel > 8) 7011 sm_syslog(LOG_INFO, NOQID, "sm_shmstop failed=%s", 7012 sm_errstring(errno)); 7013 Pshm = NULL; 7014 ShmId = SM_SHM_NO_ID; 7015 } 7016} 7017#endif /* SM_CONF_SHM */ 7018 7019/* 7020** CLEANUP_QUEUES -- do some cleanup work for queues 7021** 7022** Parameters: 7023** none. 7024** 7025** Returns: 7026** none. 7027** 7028*/ 7029 7030void 7031cleanup_queues() 7032{ 7033 sync_queue_time(); 7034} 7035/* 7036** SET_DEF_QUEUEVAL -- set default values for a queue group. 7037** 7038** Parameters: 7039** qg -- queue group 7040** all -- set all values (true for default group)? 7041** 7042** Returns: 7043** none. 7044** 7045** Side Effects: 7046** sets default values for the queue group. 7047*/ 7048 7049void 7050set_def_queueval(qg, all) 7051 QUEUEGRP *qg; 7052 bool all; 7053{ 7054 if (bitnset(QD_DEFINED, qg->qg_flags)) 7055 return; 7056 if (all) 7057 qg->qg_qdir = QueueDir; 7058#if _FFR_QUEUE_GROUP_SORTORDER 7059 qg->qg_sortorder = QueueSortOrder; 7060#endif /* _FFR_QUEUE_GROUP_SORTORDER */ 7061 qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1; 7062 qg->qg_nice = NiceQueueRun; 7063} 7064/* 7065** MAKEQUEUE -- define a new queue. 7066** 7067** Parameters: 7068** line -- description of queue. This is in labeled fields. 7069** The fields are: 7070** F -- the flags associated with the queue 7071** I -- the interval between running the queue 7072** J -- the maximum # of jobs in work list 7073** [M -- the maximum # of jobs in a queue run] 7074** N -- the niceness at which to run 7075** P -- the path to the queue 7076** S -- the queue sorting order 7077** R -- number of parallel queue runners 7078** r -- max recipients per envelope 7079** The first word is the canonical name of the queue. 7080** qdef -- this is a 'Q' definition from .cf 7081** 7082** Returns: 7083** none. 7084** 7085** Side Effects: 7086** enters the queue into the queue table. 7087*/ 7088 7089void 7090makequeue(line, qdef) 7091 char *line; 7092 bool qdef; 7093{ 7094 register char *p; 7095 register QUEUEGRP *qg; 7096 register STAB *s; 7097 int i; 7098 char fcode; 7099 7100 /* allocate a queue and set up defaults */ 7101 qg = (QUEUEGRP *) xalloc(sizeof *qg); 7102 memset((char *) qg, '\0', sizeof *qg); 7103 7104 if (line[0] == '\0') 7105 { 7106 syserr("name required for queue"); 7107 return; 7108 } 7109 7110 /* collect the queue name */ 7111 for (p = line; 7112 *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); 7113 p++) 7114 continue; 7115 if (*p != '\0') 7116 *p++ = '\0'; 7117 qg->qg_name = newstr(line); 7118 7119 /* set default values, can be overridden below */ 7120 set_def_queueval(qg, false); 7121 7122 /* now scan through and assign info from the fields */ 7123 while (*p != '\0') 7124 { 7125 auto char *delimptr; 7126 7127 while (*p != '\0' && 7128 (*p == ',' || (isascii(*p) && isspace(*p)))) 7129 p++; 7130 7131 /* p now points to field code */ 7132 fcode = *p; 7133 while (*p != '\0' && *p != '=' && *p != ',') 7134 p++; 7135 if (*p++ != '=') 7136 { 7137 syserr("queue %s: `=' expected", qg->qg_name); 7138 return; 7139 } 7140 while (isascii(*p) && isspace(*p)) 7141 p++; 7142 7143 /* p now points to the field body */ 7144 p = munchstring(p, &delimptr, ','); 7145 7146 /* install the field into the queue struct */ 7147 switch (fcode) 7148 { 7149 case 'P': /* pathname */ 7150 if (*p == '\0') 7151 syserr("queue %s: empty path name", 7152 qg->qg_name); 7153 else 7154 qg->qg_qdir = newstr(p); 7155 break; 7156 7157 case 'F': /* flags */ 7158 for (; *p != '\0'; p++) 7159 if (!(isascii(*p) && isspace(*p))) 7160 setbitn(*p, qg->qg_flags); 7161 break; 7162 7163 /* 7164 ** Do we need two intervals here: 7165 ** One for persistent queue runners, 7166 ** one for "normal" queue runs? 7167 */ 7168 7169 case 'I': /* interval between running the queue */ 7170 qg->qg_queueintvl = convtime(p, 'm'); 7171 break; 7172 7173 case 'N': /* run niceness */ 7174 qg->qg_nice = atoi(p); 7175 break; 7176 7177 case 'R': /* maximum # of runners for the group */ 7178 i = atoi(p); 7179 7180 /* can't have more runners than allowed total */ 7181 if (MaxQueueChildren > 0 && i > MaxQueueChildren) 7182 { 7183 qg->qg_maxqrun = MaxQueueChildren; 7184 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7185 "Q=%s: R=%d exceeds MaxQueueChildren=%d, set to MaxQueueChildren\n", 7186 qg->qg_name, i, 7187 MaxQueueChildren); 7188 } 7189 else 7190 qg->qg_maxqrun = i; 7191 break; 7192 7193 case 'J': /* maximum # of jobs in work list */ 7194 qg->qg_maxlist = atoi(p); 7195 break; 7196 7197 case 'r': /* max recipients per envelope */ 7198 qg->qg_maxrcpt = atoi(p); 7199 break; 7200 7201#if _FFR_QUEUE_GROUP_SORTORDER 7202 case 'S': /* queue sorting order */ 7203 switch (*p) 7204 { 7205 case 'h': /* Host first */ 7206 case 'H': 7207 qg->qg_sortorder = QSO_BYHOST; 7208 break; 7209 7210 case 'p': /* Priority order */ 7211 case 'P': 7212 qg->qg_sortorder = QSO_BYPRIORITY; 7213 break; 7214 7215 case 't': /* Submission time */ 7216 case 'T': 7217 qg->qg_sortorder = QSO_BYTIME; 7218 break; 7219 7220 case 'f': /* File name */ 7221 case 'F': 7222 qg->qg_sortorder = QSO_BYFILENAME; 7223 break; 7224 7225 case 'm': /* Modification time */ 7226 case 'M': 7227 qg->qg_sortorder = QSO_BYMODTIME; 7228 break; 7229 7230 case 'r': /* Random */ 7231 case 'R': 7232 qg->qg_sortorder = QSO_RANDOM; 7233 break; 7234 7235# if _FFR_RHS 7236 case 's': /* Shuffled host name */ 7237 case 'S': 7238 qg->qg_sortorder = QSO_BYSHUFFLE; 7239 break; 7240# endif /* _FFR_RHS */ 7241 7242 case 'n': /* none */ 7243 case 'N': 7244 qg->qg_sortorder = QSO_NONE; 7245 break; 7246 7247 default: 7248 syserr("Invalid queue sort order \"%s\"", p); 7249 } 7250 break; 7251#endif /* _FFR_QUEUE_GROUP_SORTORDER */ 7252 7253 default: 7254 syserr("Q%s: unknown queue equate %c=", 7255 qg->qg_name, fcode); 7256 break; 7257 } 7258 7259 p = delimptr; 7260 } 7261 7262#if !HASNICE 7263 if (qg->qg_nice != NiceQueueRun) 7264 { 7265 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7266 "Q%s: Warning: N= set on system that doesn't support nice()\n", 7267 qg->qg_name); 7268 } 7269#endif /* !HASNICE */ 7270 7271 /* do some rationality checking */ 7272 if (NumQueue >= MAXQUEUEGROUPS) 7273 { 7274 syserr("too many queue groups defined (%d max)", 7275 MAXQUEUEGROUPS); 7276 return; 7277 } 7278 7279 if (qg->qg_qdir == NULL) 7280 { 7281 if (QueueDir == NULL || *QueueDir == '\0') 7282 { 7283 syserr("QueueDir must be defined before queue groups"); 7284 return; 7285 } 7286 qg->qg_qdir = newstr(QueueDir); 7287 } 7288 7289 if (qg->qg_maxqrun > 1 && !bitnset(QD_FORK, qg->qg_flags)) 7290 { 7291 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 7292 "Warning: Q=%s: R=%d: multiple queue runners specified\n\tbut flag '%c' is not set\n", 7293 qg->qg_name, qg->qg_maxqrun, QD_FORK); 7294 } 7295 7296 /* enter the queue into the symbol table */ 7297 if (tTd(37, 8)) 7298 sm_syslog(LOG_INFO, NOQID, 7299 "Adding %s to stab, path: %s", qg->qg_name, 7300 qg->qg_qdir); 7301 s = stab(qg->qg_name, ST_QUEUE, ST_ENTER); 7302 if (s->s_quegrp != NULL) 7303 { 7304 i = s->s_quegrp->qg_index; 7305 7306 /* XXX what about the pointers inside this struct? */ 7307 sm_free(s->s_quegrp); /* XXX */ 7308 } 7309 else 7310 i = NumQueue++; 7311 Queue[i] = s->s_quegrp = qg; 7312 qg->qg_index = i; 7313 7314 /* set default value for max queue runners */ 7315 if (qg->qg_maxqrun < 0) 7316 { 7317 if (MaxRunnersPerQueue > 0) 7318 qg->qg_maxqrun = MaxRunnersPerQueue; 7319 else 7320 qg->qg_maxqrun = 1; 7321 } 7322 if (qdef) 7323 setbitn(QD_DEFINED, qg->qg_flags); 7324} 7325#if 0 7326/* 7327** HASHFQN -- calculate a hash value for a fully qualified host name 7328** 7329** Arguments: 7330** fqn -- an all lower-case host.domain string 7331** buckets -- the number of buckets (queue directories) 7332** 7333** Returns: 7334** a bucket number (signed integer) 7335** -1 on error 7336** 7337** Contributed by Exactis.com, Inc. 7338*/ 7339 7340int 7341hashfqn(fqn, buckets) 7342 register char *fqn; 7343 int buckets; 7344{ 7345 register char *p; 7346 register int h = 0, hash, cnt; 7347 7348 if (fqn == NULL) 7349 return -1; 7350 7351 /* 7352 ** A variation on the gdb hash 7353 ** This is the best as of Feb 19, 1996 --bcx 7354 */ 7355 7356 p = fqn; 7357 h = 0x238F13AF * strlen(p); 7358 for (cnt = 0; *p != 0; ++p, cnt++) 7359 { 7360 h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF; 7361 } 7362 h = (1103515243 * h + 12345) & 0x7FFFFFFF; 7363 if (buckets < 2) 7364 hash = 0; 7365 else 7366 hash = (h % buckets); 7367 7368 return hash; 7369} 7370#endif /* 0 */ 7371 7372/* 7373** A structure for sorting Queue according to maxqrun without 7374** screwing up Queue itself. 7375*/ 7376 7377struct sortqgrp 7378{ 7379 int sg_idx; /* original index */ 7380 int sg_maxqrun; /* max queue runners */ 7381}; 7382typedef struct sortqgrp SORTQGRP_T; 7383static int cmpidx __P((const void *, const void *)); 7384 7385static int 7386cmpidx(a, b) 7387 const void *a; 7388 const void *b; 7389{ 7390 /* The sort is highest to lowest, so the comparison is reversed */ 7391 if (((SORTQGRP_T *)a)->sg_maxqrun < ((SORTQGRP_T *)b)->sg_maxqrun) 7392 return 1; 7393 else if (((SORTQGRP_T *)a)->sg_maxqrun > ((SORTQGRP_T *)b)->sg_maxqrun) 7394 return -1; 7395 else 7396 return 0; 7397} 7398 7399/* 7400** MAKEWORKGROUP -- balance queue groups into work groups per MaxQueueChildren 7401** 7402** Take the now defined queue groups and assign them to work groups. 7403** This is done to balance out the number of concurrently active 7404** queue runners such that MaxQueueChildren is not exceeded. This may 7405** result in more than one queue group per work group. In such a case 7406** the number of running queue groups in that work group will have no 7407** more than the work group maximum number of runners (a "fair" portion 7408** of MaxQueueRunners). All queue groups within a work group will get a 7409** chance at running. 7410** 7411** Parameters: 7412** none. 7413** 7414** Returns: 7415** nothing. 7416** 7417** Side Effects: 7418** Sets up WorkGrp structure. 7419*/ 7420 7421void 7422makeworkgroups() 7423{ 7424 int i, j, total_runners, dir, h; 7425 SORTQGRP_T si[MAXQUEUEGROUPS + 1]; 7426 7427 total_runners = 0; 7428 if (NumQueue == 1 && strcmp(Queue[0]->qg_name, "mqueue") == 0) 7429 { 7430 /* 7431 ** There is only the "mqueue" queue group (a default) 7432 ** containing all of the queues. We want to provide to 7433 ** this queue group the maximum allowable queue runners. 7434 ** To match older behavior (8.10/8.11) we'll try for 7435 ** 1 runner per queue capping it at MaxQueueChildren. 7436 ** So if there are N queues, then there will be N runners 7437 ** for the "mqueue" queue group (where N is kept less than 7438 ** MaxQueueChildren). 7439 */ 7440 7441 NumWorkGroups = 1; 7442 WorkGrp[0].wg_numqgrp = 1; 7443 WorkGrp[0].wg_qgs = (QUEUEGRP **) xalloc(sizeof(QUEUEGRP *)); 7444 WorkGrp[0].wg_qgs[0] = Queue[0]; 7445 if (MaxQueueChildren > 0 && 7446 Queue[0]->qg_numqueues > MaxQueueChildren) 7447 WorkGrp[0].wg_runners = MaxQueueChildren; 7448 else 7449 WorkGrp[0].wg_runners = Queue[0]->qg_numqueues; 7450 7451 Queue[0]->qg_wgrp = 0; 7452 7453 /* can't have more runners than allowed total */ 7454 if (MaxQueueChildren > 0 && 7455 Queue[0]->qg_maxqrun > MaxQueueChildren) 7456 Queue[0]->qg_maxqrun = MaxQueueChildren; 7457 WorkGrp[0].wg_maxact = Queue[0]->qg_maxqrun; 7458 WorkGrp[0].wg_lowqintvl = Queue[0]->qg_queueintvl; 7459 return; 7460 } 7461 7462 for (i = 0; i < NumQueue; i++) 7463 { 7464 si[i].sg_maxqrun = Queue[i]->qg_maxqrun; 7465 si[i].sg_idx = i; 7466 } 7467 qsort(si, NumQueue, sizeof(si[0]), cmpidx); 7468 7469 NumWorkGroups = 0; 7470 for (i = 0; i < NumQueue; i++) 7471 { 7472 total_runners += si[i].sg_maxqrun; 7473 if (MaxQueueChildren <= 0 || total_runners <= MaxQueueChildren) 7474 NumWorkGroups++; 7475 else 7476 break; 7477 } 7478 7479 if (NumWorkGroups < 1) 7480 NumWorkGroups = 1; /* gotta have one at least */ 7481 else if (NumWorkGroups > MAXWORKGROUPS) 7482 NumWorkGroups = MAXWORKGROUPS; /* the limit */ 7483 7484 /* 7485 ** We now know the number of work groups to pack the queue groups 7486 ** into. The queue groups in 'Queue' are sorted from highest 7487 ** to lowest for the number of runners per queue group. 7488 ** We put the queue groups with the largest number of runners 7489 ** into work groups first. Then the smaller ones are fitted in 7490 ** where it looks best. 7491 */ 7492 7493 j = 0; 7494 dir = 1; 7495 for (i = 0; i < NumQueue; i++) 7496 { 7497 /* a to-and-fro packing scheme, continue from last position */ 7498 if (j >= NumWorkGroups) 7499 { 7500 dir = -1; 7501 j = NumWorkGroups - 1; 7502 } 7503 else if (j < 0) 7504 { 7505 j = 0; 7506 dir = 1; 7507 } 7508 7509 if (WorkGrp[j].wg_qgs == NULL) 7510 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_malloc(sizeof(QUEUEGRP *) * 7511 (WorkGrp[j].wg_numqgrp + 1)); 7512 else 7513 WorkGrp[j].wg_qgs = (QUEUEGRP **)sm_realloc(WorkGrp[j].wg_qgs, 7514 sizeof(QUEUEGRP *) * 7515 (WorkGrp[j].wg_numqgrp + 1)); 7516 if (WorkGrp[j].wg_qgs == NULL) 7517 { 7518 syserr("!cannot allocate memory for work queues, need %d bytes", 7519 (int) (sizeof(QUEUEGRP *) * 7520 (WorkGrp[j].wg_numqgrp + 1))); 7521 } 7522 7523 h = si[i].sg_idx; 7524 WorkGrp[j].wg_qgs[WorkGrp[j].wg_numqgrp] = Queue[h]; 7525 WorkGrp[j].wg_numqgrp++; 7526 WorkGrp[j].wg_runners += Queue[h]->qg_maxqrun; 7527 Queue[h]->qg_wgrp = j; 7528 7529 if (WorkGrp[j].wg_maxact == 0) 7530 { 7531 /* can't have more runners than allowed total */ 7532 if (MaxQueueChildren > 0 && 7533 Queue[h]->qg_maxqrun > MaxQueueChildren) 7534 Queue[h]->qg_maxqrun = MaxQueueChildren; 7535 WorkGrp[j].wg_maxact = Queue[h]->qg_maxqrun; 7536 } 7537 7538 /* 7539 ** XXX: must wg_lowqintvl be the GCD? 7540 ** qg1: 2m, qg2: 3m, minimum: 2m, when do queue runs for 7541 ** qg2 occur? 7542 */ 7543 7544 /* keep track of the lowest interval for a persistent runner */ 7545 if (Queue[h]->qg_queueintvl > 0 && 7546 WorkGrp[j].wg_lowqintvl < Queue[h]->qg_queueintvl) 7547 WorkGrp[j].wg_lowqintvl = Queue[h]->qg_queueintvl; 7548 j += dir; 7549 } 7550 if (tTd(41, 9)) 7551 { 7552 for (i = 0; i < NumWorkGroups; i++) 7553 { 7554 sm_dprintf("Workgroup[%d]=", i); 7555 for (j = 0; j < WorkGrp[i].wg_numqgrp; j++) 7556 { 7557 sm_dprintf("%s, ", 7558 WorkGrp[i].wg_qgs[j]->qg_name); 7559 } 7560 sm_dprintf("\n"); 7561 } 7562 } 7563} 7564 7565/* 7566** DUP_DF -- duplicate envelope data file 7567** 7568** Copy the data file from the 'old' envelope to the 'new' envelope 7569** in the most efficient way possible. 7570** 7571** Create a hard link from the 'old' data file to the 'new' data file. 7572** If the old and new queue directories are on different file systems, 7573** then the new data file link is created in the old queue directory, 7574** and the new queue file will contain a 'd' record pointing to the 7575** directory containing the new data file. 7576** 7577** Parameters: 7578** old -- old envelope. 7579** new -- new envelope. 7580** 7581** Results: 7582** Returns true on success, false on failure. 7583** 7584** Side Effects: 7585** On success, the new data file is created. 7586** On fatal failure, EF_FATALERRS is set in old->e_flags. 7587*/ 7588 7589static bool dup_df __P((ENVELOPE *, ENVELOPE *)); 7590 7591static bool 7592dup_df(old, new) 7593 ENVELOPE *old; 7594 ENVELOPE *new; 7595{ 7596 int ofs, nfs, r; 7597 char opath[MAXPATHLEN]; 7598 char npath[MAXPATHLEN]; 7599 7600 if (!bitset(EF_HAS_DF, old->e_flags)) 7601 { 7602 /* 7603 ** this can happen if: SuperSafe != True 7604 ** and a bounce mail is sent that is split. 7605 */ 7606 7607 queueup(old, false, true); 7608 } 7609 SM_REQUIRE(ISVALIDQGRP(old->e_qgrp) && ISVALIDQDIR(old->e_qdir)); 7610 SM_REQUIRE(ISVALIDQGRP(new->e_qgrp) && ISVALIDQDIR(new->e_qdir)); 7611 7612 (void) sm_strlcpy(opath, queuename(old, DATAFL_LETTER), sizeof opath); 7613 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath); 7614 7615 if (old->e_dfp != NULL) 7616 { 7617 r = sm_io_setinfo(old->e_dfp, SM_BF_COMMIT, NULL); 7618 if (r < 0 && errno != EINVAL) 7619 { 7620 syserr("@can't commit %s", opath); 7621 old->e_flags |= EF_FATALERRS; 7622 return false; 7623 } 7624 } 7625 7626 /* 7627 ** Attempt to create a hard link, if we think both old and new 7628 ** are on the same file system, otherwise copy the file. 7629 ** 7630 ** Don't waste time attempting a hard link unless old and new 7631 ** are on the same file system. 7632 */ 7633 7634 ofs = Queue[old->e_qgrp]->qg_qpaths[old->e_qdir].qp_fsysidx; 7635 nfs = Queue[new->e_qgrp]->qg_qpaths[new->e_qdir].qp_fsysidx; 7636 if (FILE_SYS_DEV(ofs) == FILE_SYS_DEV(nfs)) 7637 { 7638 if (link(opath, npath) == 0) 7639 { 7640 new->e_flags |= EF_HAS_DF; 7641 SYNC_DIR(npath, true); 7642 return true; 7643 } 7644 goto error; 7645 } 7646 7647 /* 7648 ** Can't link across queue directories, so try to create a hard 7649 ** link in the same queue directory as the old df file. 7650 ** The qf file will refer to the new df file using a 'd' record. 7651 */ 7652 7653 new->e_dfqgrp = old->e_dfqgrp; 7654 new->e_dfqdir = old->e_dfqdir; 7655 (void) sm_strlcpy(npath, queuename(new, DATAFL_LETTER), sizeof npath); 7656 if (link(opath, npath) == 0) 7657 { 7658 new->e_flags |= EF_HAS_DF; 7659 SYNC_DIR(npath, true); 7660 return true; 7661 } 7662 7663 error: 7664 if (LogLevel > 0) 7665 sm_syslog(LOG_ERR, old->e_id, 7666 "dup_df: can't link %s to %s, error=%s, envelope splitting failed", 7667 opath, npath, sm_errstring(errno)); 7668 return false; 7669} 7670 7671/* 7672** SPLIT_ENV -- Allocate a new envelope based on a given envelope. 7673** 7674** Parameters: 7675** e -- envelope. 7676** sendqueue -- sendqueue for new envelope. 7677** qgrp -- index of queue group. 7678** qdir -- queue directory. 7679** 7680** Results: 7681** new envelope. 7682** 7683*/ 7684 7685static ENVELOPE *split_env __P((ENVELOPE *, ADDRESS *, int, int)); 7686 7687static ENVELOPE * 7688split_env(e, sendqueue, qgrp, qdir) 7689 ENVELOPE *e; 7690 ADDRESS *sendqueue; 7691 int qgrp; 7692 int qdir; 7693{ 7694 ENVELOPE *ee; 7695 7696 ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, sizeof *ee); 7697 STRUCTCOPY(*e, *ee); 7698 ee->e_message = NULL; /* XXX use original message? */ 7699 ee->e_id = NULL; 7700 assign_queueid(ee); 7701 ee->e_sendqueue = sendqueue; 7702 ee->e_flags &= ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS 7703 |EF_SENDRECEIPT|EF_RET_PARAM|EF_HAS_DF); 7704 ee->e_flags |= EF_NORECEIPT; /* XXX really? */ 7705 ee->e_from.q_state = QS_SENDER; 7706 ee->e_dfp = NULL; 7707 ee->e_lockfp = NULL; 7708 if (e->e_xfp != NULL) 7709 ee->e_xfp = sm_io_dup(e->e_xfp); 7710 7711 /* failed to dup e->e_xfp, start a new transcript */ 7712 if (ee->e_xfp == NULL) 7713 openxscript(ee); 7714 7715 ee->e_qgrp = ee->e_dfqgrp = qgrp; 7716 ee->e_qdir = ee->e_dfqdir = qdir; 7717 ee->e_errormode = EM_MAIL; 7718 ee->e_statmsg = NULL; 7719 if (e->e_quarmsg != NULL) 7720 ee->e_quarmsg = sm_rpool_strdup_x(ee->e_rpool, 7721 e->e_quarmsg); 7722 7723 /* 7724 ** XXX Not sure if this copying is necessary. 7725 ** sendall() does this copying, but I (dm) don't know if that is 7726 ** because of the storage management discipline we were using 7727 ** before rpools were introduced, or if it is because these lists 7728 ** can be modified later. 7729 */ 7730 7731 ee->e_header = copyheader(e->e_header, ee->e_rpool); 7732 ee->e_errorqueue = copyqueue(e->e_errorqueue, ee->e_rpool); 7733 7734 return ee; 7735} 7736 7737/* return values from split functions, check also below! */ 7738#define SM_SPLIT_FAIL (0) 7739#define SM_SPLIT_NONE (1) 7740#define SM_SPLIT_NEW(n) (1 + (n)) 7741 7742/* 7743** SPLIT_ACROSS_QUEUE_GROUPS 7744** 7745** This function splits an envelope across multiple queue groups 7746** based on the queue group of each recipient. 7747** 7748** Parameters: 7749** e -- envelope. 7750** 7751** Results: 7752** SM_SPLIT_FAIL on failure 7753** SM_SPLIT_NONE if no splitting occurred, 7754** or 1 + the number of additional envelopes created. 7755** 7756** Side Effects: 7757** On success, e->e_sibling points to a list of zero or more 7758** additional envelopes, and the associated data files exist 7759** on disk. But the queue files are not created. 7760** 7761** On failure, e->e_sibling is not changed. 7762** The order of recipients in e->e_sendqueue is permuted. 7763** Abandoned data files for additional envelopes that failed 7764** to be created may exist on disk. 7765*/ 7766 7767static int q_qgrp_compare __P((const void *, const void *)); 7768static int e_filesys_compare __P((const void *, const void *)); 7769 7770static int 7771q_qgrp_compare(p1, p2) 7772 const void *p1; 7773 const void *p2; 7774{ 7775 ADDRESS **pq1 = (ADDRESS **) p1; 7776 ADDRESS **pq2 = (ADDRESS **) p2; 7777 7778 return (*pq1)->q_qgrp - (*pq2)->q_qgrp; 7779} 7780 7781static int 7782e_filesys_compare(p1, p2) 7783 const void *p1; 7784 const void *p2; 7785{ 7786 ENVELOPE **pe1 = (ENVELOPE **) p1; 7787 ENVELOPE **pe2 = (ENVELOPE **) p2; 7788 int fs1, fs2; 7789 7790 fs1 = Queue[(*pe1)->e_qgrp]->qg_qpaths[(*pe1)->e_qdir].qp_fsysidx; 7791 fs2 = Queue[(*pe2)->e_qgrp]->qg_qpaths[(*pe2)->e_qdir].qp_fsysidx; 7792 if (FILE_SYS_DEV(fs1) < FILE_SYS_DEV(fs2)) 7793 return -1; 7794 if (FILE_SYS_DEV(fs1) > FILE_SYS_DEV(fs2)) 7795 return 1; 7796 return 0; 7797} 7798 7799static int 7800split_across_queue_groups(e) 7801 ENVELOPE *e; 7802{ 7803 int naddrs, nsplits, i; 7804 bool changed; 7805 char **pvp; 7806 ADDRESS *q, **addrs; 7807 ENVELOPE *ee, *es; 7808 ENVELOPE *splits[MAXQUEUEGROUPS]; 7809 char pvpbuf[PSBUFSIZE]; 7810 7811 SM_REQUIRE(ISVALIDQGRP(e->e_qgrp)); 7812 7813 /* Count addresses and assign queue groups. */ 7814 naddrs = 0; 7815 changed = false; 7816 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 7817 { 7818 if (QS_IS_DEAD(q->q_state)) 7819 continue; 7820 ++naddrs; 7821 7822 /* bad addresses and those already sent stay put */ 7823 if (QS_IS_BADADDR(q->q_state) || 7824 QS_IS_SENT(q->q_state)) 7825 q->q_qgrp = e->e_qgrp; 7826 else if (!ISVALIDQGRP(q->q_qgrp)) 7827 { 7828 /* call ruleset which should return a queue group */ 7829 i = rscap(RS_QUEUEGROUP, q->q_user, NULL, e, &pvp, 7830 pvpbuf, sizeof(pvpbuf)); 7831 if (i == EX_OK && 7832 pvp != NULL && pvp[0] != NULL && 7833 (pvp[0][0] & 0377) == CANONNET && 7834 pvp[1] != NULL && pvp[1][0] != '\0') 7835 { 7836 i = name2qid(pvp[1]); 7837 if (ISVALIDQGRP(i)) 7838 { 7839 q->q_qgrp = i; 7840 changed = true; 7841 if (tTd(20, 4)) 7842 sm_syslog(LOG_INFO, NOQID, 7843 "queue group name %s -> %d", 7844 pvp[1], i); 7845 continue; 7846 } 7847 else if (LogLevel > 10) 7848 sm_syslog(LOG_INFO, NOQID, 7849 "can't find queue group name %s, selection ignored", 7850 pvp[1]); 7851 } 7852 if (q->q_mailer != NULL && 7853 ISVALIDQGRP(q->q_mailer->m_qgrp)) 7854 { 7855 changed = true; 7856 q->q_qgrp = q->q_mailer->m_qgrp; 7857 } 7858 else if (ISVALIDQGRP(e->e_qgrp)) 7859 q->q_qgrp = e->e_qgrp; 7860 else 7861 q->q_qgrp = 0; 7862 } 7863 } 7864 7865 /* only one address? nothing to split. */ 7866 if (naddrs <= 1 && !changed) 7867 return SM_SPLIT_NONE; 7868 7869 /* sort the addresses by queue group */ 7870 addrs = sm_rpool_malloc_x(e->e_rpool, naddrs * sizeof(ADDRESS *)); 7871 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next) 7872 { 7873 if (QS_IS_DEAD(q->q_state)) 7874 continue; 7875 addrs[i++] = q; 7876 } 7877 qsort(addrs, naddrs, sizeof(ADDRESS *), q_qgrp_compare); 7878 7879 /* split into multiple envelopes, by queue group */ 7880 nsplits = 0; 7881 es = NULL; 7882 e->e_sendqueue = NULL; 7883 for (i = 0; i < naddrs; ++i) 7884 { 7885 if (i == naddrs - 1 || addrs[i]->q_qgrp != addrs[i + 1]->q_qgrp) 7886 addrs[i]->q_next = NULL; 7887 else 7888 addrs[i]->q_next = addrs[i + 1]; 7889 7890 /* same queue group as original envelope? */ 7891 if (addrs[i]->q_qgrp == e->e_qgrp) 7892 { 7893 if (e->e_sendqueue == NULL) 7894 e->e_sendqueue = addrs[i]; 7895 continue; 7896 } 7897 7898 /* different queue group than original envelope */ 7899 if (es == NULL || addrs[i]->q_qgrp != es->e_qgrp) 7900 { 7901 ee = split_env(e, addrs[i], addrs[i]->q_qgrp, NOQDIR); 7902 es = ee; 7903 splits[nsplits++] = ee; 7904 } 7905 } 7906 7907 /* no splits? return right now. */ 7908 if (nsplits <= 0) 7909 return SM_SPLIT_NONE; 7910 7911 /* assign a queue directory to each additional envelope */ 7912 for (i = 0; i < nsplits; ++i) 7913 { 7914 es = splits[i]; 7915#if 0 7916 es->e_qdir = pickqdir(Queue[es->e_qgrp], es->e_msgsize, es); 7917#endif /* 0 */ 7918 if (!setnewqueue(es)) 7919 goto failure; 7920 } 7921 7922 /* sort the additional envelopes by queue file system */ 7923 qsort(splits, nsplits, sizeof(ENVELOPE *), e_filesys_compare); 7924 7925 /* create data files for each additional envelope */ 7926 if (!dup_df(e, splits[0])) 7927 { 7928 i = 0; 7929 goto failure; 7930 } 7931 for (i = 1; i < nsplits; ++i) 7932 { 7933 /* copy or link to the previous data file */ 7934 if (!dup_df(splits[i - 1], splits[i])) 7935 goto failure; 7936 } 7937 7938 /* success: prepend the new envelopes to the e->e_sibling list */ 7939 for (i = 0; i < nsplits; ++i) 7940 { 7941 es = splits[i]; 7942 es->e_sibling = e->e_sibling; 7943 e->e_sibling = es; 7944 } 7945 return SM_SPLIT_NEW(nsplits); 7946 7947 /* failure: clean up */ 7948 failure: 7949 if (i > 0) 7950 { 7951 int j; 7952 7953 for (j = 0; j < i; j++) 7954 (void) unlink(queuename(splits[j], DATAFL_LETTER)); 7955 } 7956 e->e_sendqueue = addrs[0]; 7957 for (i = 0; i < naddrs - 1; ++i) 7958 addrs[i]->q_next = addrs[i + 1]; 7959 addrs[naddrs - 1]->q_next = NULL; 7960 return SM_SPLIT_FAIL; 7961} 7962 7963/* 7964** SPLIT_WITHIN_QUEUE 7965** 7966** Split an envelope with multiple recipients into several 7967** envelopes within the same queue directory, if the number of 7968** recipients exceeds the limit for the queue group. 7969** 7970** Parameters: 7971** e -- envelope. 7972** 7973** Results: 7974** SM_SPLIT_FAIL on failure 7975** SM_SPLIT_NONE if no splitting occurred, 7976** or 1 + the number of additional envelopes created. 7977*/ 7978 7979#define SPLIT_LOG_LEVEL 8 7980 7981static int split_within_queue __P((ENVELOPE *)); 7982 7983static int 7984split_within_queue(e) 7985 ENVELOPE *e; 7986{ 7987 int maxrcpt, nrcpt, ndead, nsplit, i; 7988 int j, l; 7989 char *lsplits; 7990 ADDRESS *q, **addrs; 7991 ENVELOPE *ee, *firstsibling; 7992 7993 if (!ISVALIDQGRP(e->e_qgrp) || bitset(EF_SPLIT, e->e_flags)) 7994 return SM_SPLIT_NONE; 7995 7996 /* don't bother if there is no recipient limit */ 7997 maxrcpt = Queue[e->e_qgrp]->qg_maxrcpt; 7998 if (maxrcpt <= 0) 7999 return SM_SPLIT_NONE; 8000 8001 /* count recipients */ 8002 nrcpt = 0; 8003 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 8004 { 8005 if (QS_IS_DEAD(q->q_state)) 8006 continue; 8007 ++nrcpt; 8008 } 8009 if (nrcpt <= maxrcpt) 8010 return SM_SPLIT_NONE; 8011 8012 /* 8013 ** Preserve the recipient list 8014 ** so that we can restore it in case of error. 8015 ** (But we discard dead addresses.) 8016 */ 8017 8018 addrs = sm_rpool_malloc_x(e->e_rpool, nrcpt * sizeof(ADDRESS *)); 8019 for (i = 0, q = e->e_sendqueue; q != NULL; q = q->q_next) 8020 { 8021 if (QS_IS_DEAD(q->q_state)) 8022 continue; 8023 addrs[i++] = q; 8024 } 8025 8026 /* 8027 ** Partition the recipient list so that bad and sent addresses 8028 ** come first. These will go with the original envelope, and 8029 ** do not count towards the maxrcpt limit. 8030 ** addrs[] does not contain QS_IS_DEAD() addresses. 8031 */ 8032 8033 ndead = 0; 8034 for (i = 0; i < nrcpt; ++i) 8035 { 8036 if (QS_IS_BADADDR(addrs[i]->q_state) || 8037 QS_IS_SENT(addrs[i]->q_state) || 8038 QS_IS_DEAD(addrs[i]->q_state)) /* for paranoia's sake */ 8039 { 8040 if (i > ndead) 8041 { 8042 ADDRESS *tmp = addrs[i]; 8043 8044 addrs[i] = addrs[ndead]; 8045 addrs[ndead] = tmp; 8046 } 8047 ++ndead; 8048 } 8049 } 8050 8051 /* Check if no splitting required. */ 8052 if (nrcpt - ndead <= maxrcpt) 8053 return SM_SPLIT_NONE; 8054 8055 /* fix links */ 8056 for (i = 0; i < nrcpt - 1; ++i) 8057 addrs[i]->q_next = addrs[i + 1]; 8058 addrs[nrcpt - 1]->q_next = NULL; 8059 e->e_sendqueue = addrs[0]; 8060 8061 /* prepare buffer for logging */ 8062 if (LogLevel > SPLIT_LOG_LEVEL) 8063 { 8064 l = MAXLINE; 8065 lsplits = sm_malloc(l); 8066 if (lsplits != NULL) 8067 *lsplits = '\0'; 8068 j = 0; 8069 } 8070 else 8071 { 8072 /* get rid of stupid compiler warnings */ 8073 lsplits = NULL; 8074 j = l = 0; 8075 } 8076 8077 /* split the envelope */ 8078 firstsibling = e->e_sibling; 8079 i = maxrcpt + ndead; 8080 nsplit = 0; 8081 for (;;) 8082 { 8083 addrs[i - 1]->q_next = NULL; 8084 ee = split_env(e, addrs[i], e->e_qgrp, e->e_qdir); 8085 if (!dup_df(e, ee)) 8086 { 8087 8088 ee = firstsibling; 8089 while (ee != NULL) 8090 { 8091 (void) unlink(queuename(ee, DATAFL_LETTER)); 8092 ee = ee->e_sibling; 8093 } 8094 8095 /* Error. Restore e's sibling & recipient lists. */ 8096 e->e_sibling = firstsibling; 8097 for (i = 0; i < nrcpt - 1; ++i) 8098 addrs[i]->q_next = addrs[i + 1]; 8099 if (lsplits != NULL) 8100 sm_free(lsplits); 8101 return SM_SPLIT_FAIL; 8102 } 8103 8104 /* prepend the new envelope to e->e_sibling */ 8105 ee->e_sibling = e->e_sibling; 8106 e->e_sibling = ee; 8107 ++nsplit; 8108 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8109 { 8110 if (j >= l - strlen(ee->e_id) - 3) 8111 { 8112 char *p; 8113 8114 l += MAXLINE; 8115 p = sm_realloc(lsplits, l); 8116 if (p == NULL) 8117 { 8118 /* let's try to get this done */ 8119 sm_free(lsplits); 8120 lsplits = NULL; 8121 } 8122 else 8123 lsplits = p; 8124 } 8125 if (lsplits != NULL) 8126 { 8127 if (j == 0) 8128 j += sm_strlcat(lsplits + j, 8129 ee->e_id, 8130 l - j); 8131 else 8132 j += sm_strlcat2(lsplits + j, 8133 "; ", 8134 ee->e_id, 8135 l - j); 8136 SM_ASSERT(j < l); 8137 } 8138 } 8139 if (nrcpt - i <= maxrcpt) 8140 break; 8141 i += maxrcpt; 8142 } 8143 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8144 { 8145 if (nsplit > 0) 8146 { 8147 sm_syslog(LOG_NOTICE, e->e_id, 8148 "split: maxrcpts=%d, rcpts=%d, count=%d, id%s=%s", 8149 maxrcpt, nrcpt - ndead, nsplit, 8150 nsplit > 1 ? "s" : "", lsplits); 8151 } 8152 sm_free(lsplits); 8153 } 8154 return SM_SPLIT_NEW(nsplit); 8155} 8156/* 8157** SPLIT_BY_RECIPIENT 8158** 8159** Split an envelope with multiple recipients into multiple 8160** envelopes as required by the sendmail configuration. 8161** 8162** Parameters: 8163** e -- envelope. 8164** 8165** Results: 8166** Returns true on success, false on failure. 8167** 8168** Side Effects: 8169** see split_across_queue_groups(), split_within_queue(e) 8170*/ 8171 8172bool 8173split_by_recipient(e) 8174 ENVELOPE *e; 8175{ 8176 int split, n, i, j, l; 8177 char *lsplits; 8178 ENVELOPE *ee, *next, *firstsibling; 8179 8180 if (OpMode == SM_VERIFY || !ISVALIDQGRP(e->e_qgrp) || 8181 bitset(EF_SPLIT, e->e_flags)) 8182 return true; 8183 n = split_across_queue_groups(e); 8184 if (n == SM_SPLIT_FAIL) 8185 return false; 8186 firstsibling = ee = e->e_sibling; 8187 if (n > 1 && LogLevel > SPLIT_LOG_LEVEL) 8188 { 8189 l = MAXLINE; 8190 lsplits = sm_malloc(l); 8191 if (lsplits != NULL) 8192 *lsplits = '\0'; 8193 j = 0; 8194 } 8195 else 8196 { 8197 /* get rid of stupid compiler warnings */ 8198 lsplits = NULL; 8199 j = l = 0; 8200 } 8201 for (i = 1; i < n; ++i) 8202 { 8203 next = ee->e_sibling; 8204 if (split_within_queue(ee) == SM_SPLIT_FAIL) 8205 { 8206 e->e_sibling = firstsibling; 8207 return false; 8208 } 8209 ee->e_flags |= EF_SPLIT; 8210 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL) 8211 { 8212 if (j >= l - strlen(ee->e_id) - 3) 8213 { 8214 char *p; 8215 8216 l += MAXLINE; 8217 p = sm_realloc(lsplits, l); 8218 if (p == NULL) 8219 { 8220 /* let's try to get this done */ 8221 sm_free(lsplits); 8222 lsplits = NULL; 8223 } 8224 else 8225 lsplits = p; 8226 } 8227 if (lsplits != NULL) 8228 { 8229 if (j == 0) 8230 j += sm_strlcat(lsplits + j, 8231 ee->e_id, l - j); 8232 else 8233 j += sm_strlcat2(lsplits + j, "; ", 8234 ee->e_id, l - j); 8235 SM_ASSERT(j < l); 8236 } 8237 } 8238 ee = next; 8239 } 8240 if (LogLevel > SPLIT_LOG_LEVEL && lsplits != NULL && n > 1) 8241 { 8242 sm_syslog(LOG_NOTICE, e->e_id, "split: count=%d, id%s=%s", 8243 n - 1, n > 2 ? "s" : "", lsplits); 8244 sm_free(lsplits); 8245 } 8246 split = split_within_queue(e) != SM_SPLIT_FAIL; 8247 if (split) 8248 e->e_flags |= EF_SPLIT; 8249 return split; 8250} 8251 8252/* 8253** QUARANTINE_QUEUE_ITEM -- {un,}quarantine a single envelope 8254** 8255** Add/remove quarantine reason and requeue appropriately. 8256** 8257** Parameters: 8258** qgrp -- queue group for the item 8259** qdir -- queue directory in the given queue group 8260** e -- envelope information for the item 8261** reason -- quarantine reason, NULL means unquarantine. 8262** 8263** Results: 8264** true if item changed, false otherwise 8265** 8266** Side Effects: 8267** Changes quarantine tag in queue file and renames it. 8268*/ 8269 8270static bool 8271quarantine_queue_item(qgrp, qdir, e, reason) 8272 int qgrp; 8273 int qdir; 8274 ENVELOPE *e; 8275 char *reason; 8276{ 8277 bool dirty = false; 8278 bool failing = false; 8279 bool foundq = false; 8280 bool finished = false; 8281 int fd; 8282 int flags; 8283 int oldtype; 8284 int newtype; 8285 int save_errno; 8286 MODE_T oldumask = 0; 8287 SM_FILE_T *oldqfp, *tempqfp; 8288 char *bp; 8289 char oldqf[MAXPATHLEN]; 8290 char tempqf[MAXPATHLEN]; 8291 char newqf[MAXPATHLEN]; 8292 char buf[MAXLINE]; 8293 8294 oldtype = queue_letter(e, ANYQFL_LETTER); 8295 (void) sm_strlcpy(oldqf, queuename(e, ANYQFL_LETTER), sizeof oldqf); 8296 (void) sm_strlcpy(tempqf, queuename(e, NEWQFL_LETTER), sizeof tempqf); 8297 8298 /* 8299 ** Instead of duplicating all the open 8300 ** and lock code here, tell readqf() to 8301 ** do that work and return the open 8302 ** file pointer in e_lockfp. Note that 8303 ** we must release the locks properly when 8304 ** we are done. 8305 */ 8306 8307 if (!readqf(e, true)) 8308 { 8309 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8310 "Skipping %s\n", qid_printname(e)); 8311 return false; 8312 } 8313 oldqfp = e->e_lockfp; 8314 8315 /* open the new queue file */ 8316 flags = O_CREAT|O_WRONLY|O_EXCL; 8317 if (bitset(S_IWGRP, QueueFileMode)) 8318 oldumask = umask(002); 8319 fd = open(tempqf, flags, QueueFileMode); 8320 if (bitset(S_IWGRP, QueueFileMode)) 8321 (void) umask(oldumask); 8322 RELEASE_QUEUE; 8323 8324 if (fd < 0) 8325 { 8326 save_errno = errno; 8327 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8328 "Skipping %s: Could not open %s: %s\n", 8329 qid_printname(e), tempqf, 8330 sm_errstring(save_errno)); 8331 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8332 return false; 8333 } 8334 if (!lockfile(fd, tempqf, NULL, LOCK_EX|LOCK_NB)) 8335 { 8336 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8337 "Skipping %s: Could not lock %s\n", 8338 qid_printname(e), tempqf); 8339 (void) close(fd); 8340 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8341 return false; 8342 } 8343 8344 tempqfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, (void *) &fd, 8345 SM_IO_WRONLY_B, NULL); 8346 if (tempqfp == NULL) 8347 { 8348 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8349 "Skipping %s: Could not lock %s\n", 8350 qid_printname(e), tempqf); 8351 (void) close(fd); 8352 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8353 return false; 8354 } 8355 8356 /* Copy the data over, changing the quarantine reason */ 8357 while ((bp = fgetfolded(buf, sizeof buf, oldqfp)) != NULL) 8358 { 8359 if (tTd(40, 4)) 8360 sm_dprintf("+++++ %s\n", bp); 8361 switch (bp[0]) 8362 { 8363 case 'q': /* quarantine reason */ 8364 foundq = true; 8365 if (reason == NULL) 8366 { 8367 if (Verbose) 8368 { 8369 (void) sm_io_fprintf(smioout, 8370 SM_TIME_DEFAULT, 8371 "%s: Removed quarantine of \"%s\"\n", 8372 e->e_id, &bp[1]); 8373 } 8374 sm_syslog(LOG_INFO, e->e_id, "unquarantine"); 8375 dirty = true; 8376 continue; 8377 } 8378 else if (strcmp(reason, &bp[1]) == 0) 8379 { 8380 if (Verbose) 8381 { 8382 (void) sm_io_fprintf(smioout, 8383 SM_TIME_DEFAULT, 8384 "%s: Already quarantined with \"%s\"\n", 8385 e->e_id, reason); 8386 } 8387 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8388 "q%s\n", reason); 8389 } 8390 else 8391 { 8392 if (Verbose) 8393 { 8394 (void) sm_io_fprintf(smioout, 8395 SM_TIME_DEFAULT, 8396 "%s: Quarantine changed from \"%s\" to \"%s\"\n", 8397 e->e_id, &bp[1], 8398 reason); 8399 } 8400 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8401 "q%s\n", reason); 8402 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s", 8403 reason); 8404 dirty = true; 8405 } 8406 break; 8407 8408 case 'S': 8409 /* 8410 ** If we are quarantining an unquarantined item, 8411 ** need to put in a new 'q' line before it's 8412 ** too late. 8413 */ 8414 8415 if (!foundq && reason != NULL) 8416 { 8417 if (Verbose) 8418 { 8419 (void) sm_io_fprintf(smioout, 8420 SM_TIME_DEFAULT, 8421 "%s: Quarantined with \"%s\"\n", 8422 e->e_id, reason); 8423 } 8424 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8425 "q%s\n", reason); 8426 sm_syslog(LOG_INFO, e->e_id, "quarantine=%s", 8427 reason); 8428 foundq = true; 8429 dirty = true; 8430 } 8431 8432 /* Copy the line to the new file */ 8433 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8434 "%s\n", bp); 8435 break; 8436 8437 case '.': 8438 finished = true; 8439 /* FALLTHROUGH */ 8440 8441 default: 8442 /* Copy the line to the new file */ 8443 (void) sm_io_fprintf(tempqfp, SM_TIME_DEFAULT, 8444 "%s\n", bp); 8445 break; 8446 } 8447 } 8448 8449 /* Make sure we read the whole old file */ 8450 errno = sm_io_error(tempqfp); 8451 if (errno != 0 && errno != SM_IO_EOF) 8452 { 8453 save_errno = errno; 8454 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8455 "Skipping %s: Error reading %s: %s\n", 8456 qid_printname(e), oldqf, 8457 sm_errstring(save_errno)); 8458 failing = true; 8459 } 8460 8461 if (!failing && !finished) 8462 { 8463 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8464 "Skipping %s: Incomplete file: %s\n", 8465 qid_printname(e), oldqf); 8466 failing = true; 8467 } 8468 8469 /* Check if we actually changed anything or we can just bail now */ 8470 if (!dirty) 8471 { 8472 /* pretend we failed, even though we technically didn't */ 8473 failing = true; 8474 } 8475 8476 /* Make sure we wrote things out safely */ 8477 if (!failing && 8478 (sm_io_flush(tempqfp, SM_TIME_DEFAULT) != 0 || 8479 ((SuperSafe == SAFE_REALLY || 8480 SuperSafe == SAFE_REALLY_POSTMILTER || 8481 SuperSafe == SAFE_INTERACTIVE) && 8482 fsync(sm_io_getinfo(tempqfp, SM_IO_WHAT_FD, NULL)) < 0) || 8483 ((errno = sm_io_error(tempqfp)) != 0))) 8484 { 8485 save_errno = errno; 8486 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8487 "Skipping %s: Error writing %s: %s\n", 8488 qid_printname(e), tempqf, 8489 sm_errstring(save_errno)); 8490 failing = true; 8491 } 8492 8493 8494 /* Figure out the new filename */ 8495 newtype = (reason == NULL ? NORMQF_LETTER : QUARQF_LETTER); 8496 if (oldtype == newtype) 8497 { 8498 /* going to rename tempqf to oldqf */ 8499 (void) sm_strlcpy(newqf, oldqf, sizeof newqf); 8500 } 8501 else 8502 { 8503 /* going to rename tempqf to new name based on newtype */ 8504 (void) sm_strlcpy(newqf, queuename(e, newtype), sizeof newqf); 8505 } 8506 8507 save_errno = 0; 8508 8509 /* rename tempqf to newqf */ 8510 if (!failing && 8511 rename(tempqf, newqf) < 0) 8512 save_errno = (errno == 0) ? EINVAL : errno; 8513 8514 /* Check rename() success */ 8515 if (!failing && save_errno != 0) 8516 { 8517 sm_syslog(LOG_DEBUG, e->e_id, 8518 "quarantine_queue_item: rename(%s, %s): %s", 8519 tempqf, newqf, sm_errstring(save_errno)); 8520 8521 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8522 "Error renaming %s to %s: %s\n", 8523 tempqf, newqf, 8524 sm_errstring(save_errno)); 8525 if (oldtype == newtype) 8526 { 8527 /* 8528 ** Bail here since we don't know the state of 8529 ** the filesystem and may need to keep tempqf 8530 ** for the user to rescue us. 8531 */ 8532 8533 RELEASE_QUEUE; 8534 errno = save_errno; 8535 syserr("!452 Error renaming control file %s", tempqf); 8536 /* NOTREACHED */ 8537 } 8538 else 8539 { 8540 /* remove new file (if rename() half completed) */ 8541 if (xunlink(newqf) < 0) 8542 { 8543 save_errno = errno; 8544 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8545 "Error removing %s: %s\n", 8546 newqf, 8547 sm_errstring(save_errno)); 8548 } 8549 8550 /* tempqf removed below */ 8551 failing = true; 8552 } 8553 8554 } 8555 8556 /* If changing file types, need to remove old type */ 8557 if (!failing && oldtype != newtype) 8558 { 8559 if (xunlink(oldqf) < 0) 8560 { 8561 save_errno = errno; 8562 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8563 "Error removing %s: %s\n", 8564 oldqf, sm_errstring(save_errno)); 8565 } 8566 } 8567 8568 /* see if anything above failed */ 8569 if (failing) 8570 { 8571 /* Something failed: remove new file, old file still there */ 8572 (void) xunlink(tempqf); 8573 } 8574 8575 /* 8576 ** fsync() after file operations to make sure metadata is 8577 ** written to disk on filesystems in which renames are 8578 ** not guaranteed. It's ok if they fail, mail won't be lost. 8579 */ 8580 8581 if (SuperSafe != SAFE_NO) 8582 { 8583 /* for soft-updates */ 8584 (void) fsync(sm_io_getinfo(tempqfp, 8585 SM_IO_WHAT_FD, NULL)); 8586 8587 if (!failing) 8588 { 8589 /* for soft-updates */ 8590 (void) fsync(sm_io_getinfo(oldqfp, 8591 SM_IO_WHAT_FD, NULL)); 8592 } 8593 8594 /* for other odd filesystems */ 8595 SYNC_DIR(tempqf, false); 8596 } 8597 8598 /* Close up shop */ 8599 RELEASE_QUEUE; 8600 if (tempqfp != NULL) 8601 (void) sm_io_close(tempqfp, SM_TIME_DEFAULT); 8602 if (oldqfp != NULL) 8603 (void) sm_io_close(oldqfp, SM_TIME_DEFAULT); 8604 8605 /* All went well */ 8606 return !failing; 8607} 8608 8609/* 8610** QUARANTINE_QUEUE -- {un,}quarantine matching items in the queue 8611** 8612** Read all matching queue items, add/remove quarantine 8613** reason, and requeue appropriately. 8614** 8615** Parameters: 8616** reason -- quarantine reason, "." means unquarantine. 8617** qgrplimit -- limit to single queue group unless NOQGRP 8618** 8619** Results: 8620** none. 8621** 8622** Side Effects: 8623** Lots of changes to the queue. 8624*/ 8625 8626void 8627quarantine_queue(reason, qgrplimit) 8628 char *reason; 8629 int qgrplimit; 8630{ 8631 int changed = 0; 8632 int qgrp; 8633 8634 /* Convert internal representation of unquarantine */ 8635 if (reason != NULL && reason[0] == '.' && reason[1] == '\0') 8636 reason = NULL; 8637 8638 if (reason != NULL) 8639 { 8640 /* clean it */ 8641 reason = newstr(denlstring(reason, true, true)); 8642 } 8643 8644 for (qgrp = 0; qgrp < NumQueue && Queue[qgrp] != NULL; qgrp++) 8645 { 8646 int qdir; 8647 8648 if (qgrplimit != NOQGRP && qgrplimit != qgrp) 8649 continue; 8650 8651 for (qdir = 0; qdir < Queue[qgrp]->qg_numqueues; qdir++) 8652 { 8653 int i; 8654 int nrequests; 8655 8656 if (StopRequest) 8657 stop_sendmail(); 8658 8659 nrequests = gatherq(qgrp, qdir, true, NULL, NULL); 8660 8661 /* first see if there is anything */ 8662 if (nrequests <= 0) 8663 { 8664 if (Verbose) 8665 { 8666 (void) sm_io_fprintf(smioout, 8667 SM_TIME_DEFAULT, "%s: no matches\n", 8668 qid_printqueue(qgrp, qdir)); 8669 } 8670 continue; 8671 } 8672 8673 if (Verbose) 8674 { 8675 (void) sm_io_fprintf(smioout, 8676 SM_TIME_DEFAULT, "Processing %s:\n", 8677 qid_printqueue(qgrp, qdir)); 8678 } 8679 8680 for (i = 0; i < WorkListCount; i++) 8681 { 8682 ENVELOPE e; 8683 8684 if (StopRequest) 8685 stop_sendmail(); 8686 8687 /* setup envelope */ 8688 clearenvelope(&e, true, sm_rpool_new_x(NULL)); 8689 e.e_id = WorkList[i].w_name + 2; 8690 e.e_qgrp = qgrp; 8691 e.e_qdir = qdir; 8692 8693 if (tTd(70, 101)) 8694 { 8695 sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8696 "Would do %s\n", e.e_id); 8697 changed++; 8698 } 8699 else if (quarantine_queue_item(qgrp, qdir, 8700 &e, reason)) 8701 changed++; 8702 8703 /* clean up */ 8704 sm_rpool_free(e.e_rpool); 8705 e.e_rpool = NULL; 8706 } 8707 if (WorkList != NULL) 8708 sm_free(WorkList); /* XXX */ 8709 WorkList = NULL; 8710 WorkListSize = 0; 8711 WorkListCount = 0; 8712 } 8713 } 8714 if (Verbose) 8715 { 8716 if (changed == 0) 8717 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8718 "No changes\n"); 8719 else 8720 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 8721 "%d change%s\n", 8722 changed, 8723 changed == 1 ? "" : "s"); 8724 } 8725} 8726