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