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