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