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