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