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