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