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